feat(product): 新增产品管理模块与字典组件功能

- 新增产品管理相关路由和页面(dashboard、list、requirement、setting)
- 实现产品基础信息编辑弹窗组件(base-info-dialog.vue)
- 添加运行时字典功能(dict-select、dict-text、dict-tag组件)
- 集成字典管理store和API调用
- 规范ID类型定义为string避免精度丢失问题
- 完善国际化资源文件支持中英文对照
- 新增对象上下文业务域入口页导航实现说明
- 添加Vue DevTools浮动入口注释说明
- 统一权限控制支持全局和对象作用域区分
- 规范分页查询参数类型定义与使用方式
This commit is contained in:
2026-04-23 09:05:55 +08:00
parent c5911ea34b
commit 4122dfa50d
95 changed files with 9581 additions and 801 deletions

View File

@@ -3,13 +3,12 @@ import type { RouteRecordRaw } from 'vue-router';
import { defineStore } from 'pinia';
import { useBoolean } from '@sa/hooks';
import type { CustomRoute, ElegantConstRoute, LastLevelRouteKey, RouteKey, RouteMap } from '@elegant-router/types';
import { router } from '@/router';
import { fetchGetUserRoutes, fetchIsRouteExist } from '@/service/api';
import { SetupStoreId } from '@/enum';
import { createStaticRoutes, getAuthVueRoutes } from '@/router/routes';
import { ROOT_ROUTE } from '@/router/routes/builtin';
import { getRouteName, getRoutePath } from '@/router/elegant/transform';
import { getGlobalRouter } from '@/router/instance';
import { useAuthStore } from '../auth';
import { useDictStore } from '../dict';
import { useTabStore } from '../tab';
import {
filterAuthRoutesByRoles,
@@ -23,8 +22,27 @@ import {
updateLocaleOfGlobalMenus
} from './shared';
type RouteModule = typeof import('@/router/routes');
async function loadRouteModule(): Promise<RouteModule> {
return import('@/router/routes');
}
function createRootRoute(redirect: string): CustomRoute {
return {
name: 'root',
path: '/',
redirect,
meta: {
title: 'root',
constant: true
}
};
}
export const useRouteStore = defineStore(SetupStoreId.Route, () => {
const authStore = useAuthStore();
const dictStore = useDictStore();
const tabStore = useTabStore();
const { bool: isInitConstantRoute, setBool: setIsInitConstantRoute } = useBoolean();
const { bool: isInitAuthRoute, setBool: setIsInitAuthRoute } = useBoolean();
@@ -117,7 +135,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
* @param routeKey
*/
async function resetRouteCache(routeKey?: RouteKey) {
const routeName = routeKey || (router.currentRoute.value.name as RouteKey);
const routeName = routeKey || (getGlobalRouter().currentRoute.value.name as RouteKey);
excludeCacheRoutes.value.push(routeName);
@@ -127,7 +145,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
}
/** 全局面包屑 */
const breadcrumbs = computed(() => getBreadcrumbsByRoute(router.currentRoute.value, menus.value));
const breadcrumbs = computed(() => getBreadcrumbsByRoute(getGlobalRouter().currentRoute.value, menus.value));
/** 重置 store */
async function resetStore() {
@@ -151,11 +169,12 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
async function initConstantRoute() {
if (isInitConstantRoute.value) return;
const { createStaticRoutes } = await loadRouteModule();
const staticRoute = createStaticRoutes();
addConstantRoutes(staticRoute.constantRoutes);
handleConstantAndAuthRoutes();
await handleConstantAndAuthRoutes();
setIsInitConstantRoute(true);
@@ -169,8 +188,10 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
await authStore.initUserInfo();
}
await dictStore.initDictCache();
if (authRouteMode.value === 'static') {
initStaticAuthRoute();
await initStaticAuthRoute();
} else {
await initDynamicAuthRoute();
}
@@ -179,7 +200,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
}
/** 初始化静态权限路由 */
function initStaticAuthRoute() {
async function initStaticAuthRoute() {
const { createStaticRoutes } = await loadRouteModule();
const { authRoutes: staticAuthRoutes } = createStaticRoutes();
if (authStore.isStaticSuper) {
@@ -190,7 +212,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
addAuthRoutes(filteredAuthRoutes);
}
handleConstantAndAuthRoutes();
await handleConstantAndAuthRoutes();
setIsInitAuthRoute(true);
}
@@ -204,11 +226,11 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
addAuthRoutes(routes);
handleConstantAndAuthRoutes();
await handleConstantAndAuthRoutes();
setRouteHome(home);
handleUpdateRootRouteRedirect(home);
await handleUpdateRootRouteRedirect(home);
setIsInitAuthRoute(true);
} else {
@@ -218,7 +240,8 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
}
/** 统一处理常量路由和权限路由 */
function handleConstantAndAuthRoutes() {
async function handleConstantAndAuthRoutes() {
const { getAuthVueRoutes } = await loadRouteModule();
const allRoutes = [...constantRoutes.value, ...authRoutes.value];
const sortRoutes = sortRoutesByOrder(allRoutes);
@@ -241,7 +264,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
*/
function addRoutesToVueRouter(routes: RouteRecordRaw[]) {
routes.forEach(route => {
const removeFn = router.addRoute(route);
const removeFn = getGlobalRouter().addRoute(route);
addRemoveRouteFn(removeFn);
});
}
@@ -260,11 +283,13 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
*
* @param redirectKey 重定向目标路由 key
*/
function handleUpdateRootRouteRedirect(redirectKey: LastLevelRouteKey) {
async function handleUpdateRootRouteRedirect(redirectKey: LastLevelRouteKey) {
const redirect = getRoutePath(redirectKey);
if (redirect) {
const rootRoute: CustomRoute = { ...ROOT_ROUTE, redirect };
const { getAuthVueRoutes } = await loadRouteModule();
const rootRoute = createRootRoute(redirect);
const router = getGlobalRouter();
router.removeRoute(rootRoute.name);
@@ -287,6 +312,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
}
if (authRouteMode.value === 'static') {
const { createStaticRoutes } = await loadRouteModule();
const { authRoutes: staticAuthRoutes } = createStaticRoutes();
return isRouteExistByRouteName(routeName, staticAuthRoutes);
}
@@ -316,6 +342,7 @@ export const useRouteStore = defineStore(SetupStoreId.Route, () => {
return {
resetStore,
routeHome,
authRoutes,
menus,
searchMenus,
updateGlobalMenusByLocale,