task-283(后台迁移收尾/发布): admin-vue 后台工程入库 + Flask 后台整体退役
- 新后台 admin-frontend-vue 整工程入库(base=/admin-vue/、History 路由、Nginx 静态托管方案与 verify-dist 校验) - Java AdminConsoleController 改为入口重定向: /admin|/admin.html、/login|/login.html -> /admin-vue/; 删除 classpath:static 旧 admin.html/login.html 单页与 admin.js 副本 - Flask 后台整体退役: 删除 admin_api/auth/main 蓝图、web_source 页面、static 脚本与 admin 相关测试; app.py 收敛为仅注册 version_bp(/api/version、/api/version/latest, 供桌面端更新检查) - AdminApiGuardFilterTest 豁免样例路径 /admin.html -> /admin-vue/
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
|
||||
import AdminLayout from '@/layout/AdminLayout.vue'
|
||||
import LoginPage from '@/pages/login/LoginPage.vue'
|
||||
import NotFoundPage from '@/pages/error/NotFoundPage.vue'
|
||||
import { useAdminSessionStore } from '@/stores/admin-session'
|
||||
import { APP_BASE_PATH } from '@/config/app'
|
||||
@@ -10,6 +11,11 @@ import { isRouteAllowed } from './helpers'
|
||||
const router = createRouter({
|
||||
history: createWebHistory(APP_BASE_PATH),
|
||||
routes: [
|
||||
{
|
||||
path: '/login',
|
||||
component: LoginPage,
|
||||
meta: { title: '登录' },
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: AdminLayout,
|
||||
@@ -26,10 +32,15 @@ const router = createRouter({
|
||||
|
||||
router.beforeEach(async (to) => {
|
||||
const session = useAdminSessionStore()
|
||||
// 登录页是公开页;已登录访问则回根路由。
|
||||
if (to.path === '/login') {
|
||||
return session.initialized && session.user ? '/' : true
|
||||
}
|
||||
if (!session.initialized) {
|
||||
try {
|
||||
await session.initialize()
|
||||
} catch {
|
||||
// 未登录:401 由 http 拦截器整页跳转 SPA 登录页;此处放行当前导航由守卫收口。
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/** 菜单树 route 归一:column_key → 前端注册的规范页面路径。
|
||||
* 共享库 columns.route_path 仍是旧式 slug(切机迁移未应用),这里按注册表 key 映射为新 Vue 路由,
|
||||
* 保证侧边栏/面包屑/首页跳转都能命中已注册页面,无需改写共享库。纯逻辑。 */
|
||||
import { adminPages } from './routes'
|
||||
import type { AdminMenuNode } from '@/types/admin'
|
||||
|
||||
const CANONICAL_BY_KEY = new Map<string, string>()
|
||||
for (const page of adminPages) {
|
||||
if (page.menuKey) {
|
||||
CANONICAL_BY_KEY.set(page.menuKey, `/${page.path.replace(/^\/+/, '')}`)
|
||||
}
|
||||
}
|
||||
|
||||
/** column_key → 规范路由(带前导 /,无 base 前缀);未登记返回 undefined。 */
|
||||
export function canonicalRouteOf(key: string | undefined | null): string | undefined {
|
||||
return typeof key === 'string' ? CANONICAL_BY_KEY.get(key) : undefined
|
||||
}
|
||||
|
||||
/** 递归把菜单树节点的 route 替换为规范路由;分组/未登记节点保持原值。 */
|
||||
export function canonicalizeMenuTree(nodes: AdminMenuNode[] | null | undefined): AdminMenuNode[] {
|
||||
return (nodes || []).map((node) => {
|
||||
const canonical = canonicalRouteOf(node.key)
|
||||
const children = canonicalizeMenuTree(node.children)
|
||||
const route = canonical && node.route != null ? canonical : node.route
|
||||
return { ...node, route, children }
|
||||
})
|
||||
}
|
||||
@@ -17,6 +17,19 @@ export const adminPages: AdminPageDef[] = [
|
||||
{ path: 'account/users', menuKey: 'admin_users', title: '用户管理', load: () => import('@/pages/account/UsersPage.vue') },
|
||||
{ path: 'account/menus', menuKey: 'admin_columns', title: '菜单管理', load: () => import('@/pages/account/MenusPage.vue') },
|
||||
{ path: 'account/groups', menuKey: 'admin_group_manage', title: '数据权限分组', load: () => import('@/pages/account/GroupsPage.vue') },
|
||||
{ path: 'shop-center/duplicate-check', menuKey: 'admin_shop_data_duplicate_check', title: '店铺撞款监控', load: () => import('@/pages/tasks/DuplicateCheckPage.vue') },
|
||||
{ path: 'shop-center/keys', menuKey: 'admin_shop_keys', title: '店铺密钥管理', load: () => import('@/pages/shop/ShopKeysPage.vue') },
|
||||
{ path: 'shop-center/shops', menuKey: 'admin_shop_manage', title: '店铺管理', load: () => import('@/pages/shop/ShopManagePage.vue') },
|
||||
{ path: 'records/history', menuKey: 'admin_history', title: '生成记录', load: () => import('@/pages/records/RecordsHistoryPage.vue') },
|
||||
{ path: 'records/software-version', menuKey: 'admin_version', title: '软件版本管理', load: () => import('@/pages/records/RecordsSoftwareVersionPage.vue') },
|
||||
{ path: 'records/digital-human-version', menuKey: 'digital_human_version', title: '数字人版本管理', load: () => import('@/pages/records/RecordsDigitalHumanVersionPage.vue') },
|
||||
{ path: 'records/image-video-tasks', menuKey: 'admin_image_video_tasks', title: '视频任务记录', load: () => import('@/pages/tasks/ImageVideoTasksPage.vue') },
|
||||
{ path: 'shop-center/data-tasks', menuKey: 'admin_shop_data_crawl_tasks', title: '店铺数据任务/记录', load: () => import('@/pages/tasks/ShopDataTasksPage.vue') },
|
||||
{ path: 'asin-center/registry', menuKey: 'admin_dedupe_total_data', title: '数据去重总数据', load: () => import('@/pages/asin/DedupeRegistryPage.vue') },
|
||||
{ path: 'asin-center/invalid', menuKey: 'admin_invalid_asin_data', title: '不符合ASIN数据', load: () => import('@/pages/asin/AsinInvalidPage.vue') },
|
||||
{ path: 'asin-center/query', menuKey: 'admin_query_asin', title: '查询ASIN', load: () => import('@/pages/asin/QueryAsinPage.vue') },
|
||||
{ path: 'asin-center/categories', menuKey: 'admin_product_categories', title: '商品类目', load: () => import('@/pages/asin/ProductCategoryPage.vue') },
|
||||
{ path: 'asin-center/skip-price', menuKey: 'admin_skip_price_asin', title: '最低价ASIN', load: () => import('@/pages/asin/SkipPricePage.vue') },
|
||||
]
|
||||
|
||||
export function routeOf(page: AdminPageDef): RouteRecordRaw {
|
||||
|
||||
Reference in New Issue
Block a user