- Change "结果展示" to "投票结果" in global controls - Add program edit modal with name, team, performer, remark fields - Add move up/down buttons for program reordering - Add delete program with confirmation - Add "添加节目" button for creating new programs - Add responsive styles for mobile view Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
103 lines
3.0 KiB
TypeScript
103 lines
3.0 KiB
TypeScript
import { createRouter, createWebHistory, type RouteLocationNormalized } from 'vue-router';
|
|
|
|
// Admin auth constants
|
|
const ADMIN_TOKEN_KEY = 'gala_admin_token';
|
|
|
|
// Auth guard for admin routes
|
|
function requireAdminAuth(to: RouteLocationNormalized) {
|
|
const token = localStorage.getItem(ADMIN_TOKEN_KEY);
|
|
if (!token) {
|
|
return { path: '/admin/login', query: { redirect: to.fullPath } };
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Export for use in login component
|
|
export { ADMIN_TOKEN_KEY };
|
|
|
|
const router = createRouter({
|
|
history: createWebHistory('/screen/'),
|
|
routes: [
|
|
// ============================================
|
|
// Big Screen Display Routes (LED PC)
|
|
// ============================================
|
|
{
|
|
path: '/',
|
|
name: 'screen-main',
|
|
component: () => import('../views/MainDisplay.vue'),
|
|
meta: { title: '年会大屏 - 主页' },
|
|
},
|
|
{
|
|
path: '/screen/voting',
|
|
name: 'screen-voting',
|
|
component: () => import('../views/LiveVotingView.vue'),
|
|
meta: { title: '年会大屏 - 实时投票' },
|
|
},
|
|
{
|
|
path: '/screen/draw',
|
|
name: 'screen-draw',
|
|
component: () => import('../views/LuckyDrawView.vue'),
|
|
meta: { title: '年会大屏 - 幸运抽奖' },
|
|
},
|
|
{
|
|
path: '/screen/results',
|
|
name: 'screen-results',
|
|
component: () => import('../views/VoteResultsView.vue'),
|
|
meta: { title: '年会大屏 - 结果展示' },
|
|
},
|
|
{
|
|
path: '/screen/lottery-results',
|
|
name: 'screen-lottery-results',
|
|
component: () => import('../views/LotteryResultsView.vue'),
|
|
meta: { title: '年会大屏 - 抽奖结果' },
|
|
},
|
|
{
|
|
path: '/screen/horse-race',
|
|
name: 'screen-horse-race',
|
|
component: () => import('../views/HorseRaceView.vue'),
|
|
meta: { title: '年会大屏 - 赛马热度' },
|
|
},
|
|
|
|
// Legacy routes (redirect to new paths)
|
|
{ path: '/voting', redirect: '/screen/voting' },
|
|
{ path: '/draw', redirect: '/screen/draw' },
|
|
{ path: '/results', redirect: '/screen/results' },
|
|
|
|
// ============================================
|
|
// Admin Routes (Director Console)
|
|
// ============================================
|
|
{
|
|
path: '/admin/login',
|
|
name: 'admin-login',
|
|
component: () => import('../views/AdminLogin.vue'),
|
|
meta: { title: '管理员登录' },
|
|
},
|
|
{
|
|
path: '/admin/director-console',
|
|
name: 'admin-console',
|
|
component: () => import('../views/AdminControl.vue'),
|
|
meta: { title: '导演控制台' },
|
|
beforeEnter: requireAdminAuth,
|
|
},
|
|
|
|
// Legacy admin route (redirect)
|
|
{ path: '/admin', redirect: '/admin/director-console' },
|
|
|
|
// ============================================
|
|
// 404 Catch-all
|
|
// ============================================
|
|
{
|
|
path: '/:pathMatch(.*)*',
|
|
name: 'not-found',
|
|
redirect: '/',
|
|
},
|
|
],
|
|
});
|
|
|
|
// Update document title on navigation
|
|
router.afterEach((to) => {
|
|
document.title = (to.meta.title as string) || '年会互动系统';
|
|
});
|
|
|
|
export default router;
|