feat: 管理端公账支付与确认、锁店遮罩及表单提交修复
新增公账账单/到账确认页与全局锁店组件;系统配置补公账参数面板; 统一弹窗 onConfirm 校验提交,并完善订单详情与门店相关交互。
This commit is contained in:
@@ -238,3 +238,76 @@ describe('generateAccessible - redirect normalization', () => {
|
||||
expect(findByName(result, 'Custom')?.redirect).toBe('/custom/keep');
|
||||
});
|
||||
});
|
||||
|
||||
describe('generateAccessible - Root path=/ flatten', () => {
|
||||
/**
|
||||
* 模拟框架 Root:path=/、name=Root,用于断言后端 Dashboard(path=/) 被扁平合并
|
||||
*/
|
||||
function createRootRouterStub() {
|
||||
const root: RouteRecordRaw = {
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: '/home',
|
||||
children: [],
|
||||
meta: { title: 'Root' },
|
||||
};
|
||||
const routes = [root];
|
||||
return {
|
||||
addRoute: (route: RouteRecordRaw) => {
|
||||
const idx = routes.findIndex((r) => r.name === route.name);
|
||||
if (idx === -1) {
|
||||
routes.push(route);
|
||||
} else {
|
||||
routes[idx] = route;
|
||||
}
|
||||
},
|
||||
getRoutes: () => routes,
|
||||
removeRoute: (name: string | symbol) => {
|
||||
const idx = routes.findIndex((r) => r.name === name);
|
||||
if (idx !== -1) {
|
||||
routes.splice(idx, 1);
|
||||
}
|
||||
},
|
||||
_root: root,
|
||||
} as any;
|
||||
}
|
||||
|
||||
it('后端 Dashboard path=/ 不嵌套进 Root,子路由扁平挂到 Root.children', async () => {
|
||||
const router = createRootRouterStub();
|
||||
const { accessibleRoutes } = await generateAccessible('frontend', {
|
||||
router,
|
||||
routes: [
|
||||
{
|
||||
name: 'Dashboard',
|
||||
path: '/',
|
||||
redirect: '/workspace',
|
||||
children: [
|
||||
{
|
||||
name: 'Workspace',
|
||||
path: '/workspace',
|
||||
meta: { title: 'workspace' },
|
||||
},
|
||||
],
|
||||
meta: { title: 'dashboard' },
|
||||
},
|
||||
{
|
||||
name: 'System',
|
||||
path: '/system',
|
||||
meta: { title: 'system' },
|
||||
},
|
||||
] as unknown as RouteRecordRaw[],
|
||||
});
|
||||
|
||||
const root = router._root as RouteRecordRaw;
|
||||
const childNames = (root.children ?? []).map((c) => c.name);
|
||||
|
||||
// 不应再挂一层同名 Dashboard
|
||||
expect(childNames).not.toContain('Dashboard');
|
||||
expect(childNames).toContain('Workspace');
|
||||
expect(childNames).toContain('System');
|
||||
expect(root.redirect).toBe('/workspace');
|
||||
|
||||
// 菜单树仍保留原始 Dashboard(侧栏结构不变)
|
||||
expect(findByName(accessibleRoutes, 'Dashboard')?.path).toBe('/');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,10 +29,33 @@ async function generateAccessible(
|
||||
// 生成路由
|
||||
const accessibleRoutes = await generateRoutes(mode, options);
|
||||
|
||||
const root = router.getRoutes().find((item) => item.path === '/');
|
||||
// 优先按 name=Root 定位布局根,避免误抓到后端 path=/ 的 Dashboard
|
||||
const root =
|
||||
router.getRoutes().find((item) => item.name === 'Root') ??
|
||||
router.getRoutes().find((item) => item.path === '/');
|
||||
|
||||
// 获取已有的路由名称列表
|
||||
const names = root?.children?.map((item) => item.name) ?? [];
|
||||
// 获取已有的路由名称列表(合并过程中同步维护,保证同批去重)
|
||||
const names: (string | symbol | undefined)[] =
|
||||
root?.children?.map((item) => item.name) ?? [];
|
||||
|
||||
/**
|
||||
* 将一条路由挂到 Root.children:同名则替换,否则追加
|
||||
* 为什么:切换用户时一级目录要更新,且 path=/ 扁平合并时也要复用同一套去重
|
||||
*/
|
||||
const upsertRootChild = (child: RouteRecordRaw) => {
|
||||
if (!root?.children) {
|
||||
return;
|
||||
}
|
||||
if (names.includes(child.name)) {
|
||||
const index = root.children.findIndex((item) => item.name === child.name);
|
||||
if (index !== -1) {
|
||||
root.children[index] = child;
|
||||
}
|
||||
return;
|
||||
}
|
||||
root.children.push(child);
|
||||
names.push(child.name);
|
||||
};
|
||||
|
||||
// 动态添加到router实例内
|
||||
accessibleRoutes.forEach((route) => {
|
||||
@@ -42,18 +65,19 @@ async function generateAccessible(
|
||||
if (route.children && route.children.length > 0) {
|
||||
delete route.component;
|
||||
}
|
||||
// 根据router name判断,如果路由已经存在,则不再添加
|
||||
if (names?.includes(route.name)) {
|
||||
// 找到已存在的路由索引并更新,不更新会造成切换用户时,一级目录未更新,homePath 在二级目录导致的404问题
|
||||
const index = root.children?.findIndex(
|
||||
(item) => item.name === route.name,
|
||||
);
|
||||
if (index !== undefined && index !== -1 && root.children) {
|
||||
root.children[index] = route;
|
||||
|
||||
// 后端「概览」等与 Root 同 path=/:扁平合并子路由,禁止再嵌套一层同名 Dashboard
|
||||
if (route.path === '/' || route.path === root.path) {
|
||||
if (route.redirect) {
|
||||
root.redirect = route.redirect;
|
||||
}
|
||||
} else {
|
||||
root.children?.push(route);
|
||||
for (const child of route.children ?? []) {
|
||||
upsertRootChild(child);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
upsertRootChild(route);
|
||||
} else {
|
||||
router.addRoute(route);
|
||||
}
|
||||
@@ -66,7 +90,7 @@ async function generateAccessible(
|
||||
router.addRoute(root);
|
||||
}
|
||||
|
||||
// 生成菜单
|
||||
// 生成菜单(仍用原始树,侧栏「概览」结构不变;仅 router 挂载做了扁平)
|
||||
const accessibleMenus = generateMenus(accessibleRoutes, options.router);
|
||||
|
||||
return { accessibleMenus, accessibleRoutes };
|
||||
|
||||
Reference in New Issue
Block a user