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

@@ -0,0 +1,83 @@
import { normalizeNullableStringId, normalizeStringId } from './shared';
type ProductStatusCode = Api.Product.ProductStatusCode;
type ProductStatusActionCode = Api.Product.ProductStatusActionCode;
interface ProductSettingsResponse {
baseInfo: {
id: string | number;
code: string;
directionCode: string;
name: string;
managerUserId?: string | number | null;
managerUserNickname?: string | null;
description?: string | null;
statusCode: ProductStatusCode;
lastStatusReason?: string | null;
};
lifecycle: {
statusCode: ProductStatusCode;
lastStatusReason?: string | null;
availableActions?: Array<{
actionCode: ProductStatusActionCode;
actionName: string;
needReason: boolean;
}> | null;
};
}
interface ProductMemberResponse {
id: string | number;
userId: string | number;
userNickname: string;
roleId: string | number;
roleName: string;
roleCode: string;
managerFlag: boolean;
status: 0 | 1;
joinedTime: string;
leftTime?: string | null;
remark?: string | null;
}
export function normalizeProductSettings(response: ProductSettingsResponse): Api.Product.ProductSettings {
return {
baseInfo: {
id: normalizeStringId(response.baseInfo.id),
code: response.baseInfo.code || '',
directionCode: response.baseInfo.directionCode || '',
name: response.baseInfo.name || '',
managerUserId: normalizeNullableStringId(response.baseInfo.managerUserId) ?? '',
managerUserNickname: response.baseInfo.managerUserNickname || '',
description: response.baseInfo.description ?? null,
statusCode: response.baseInfo.statusCode,
lastStatusReason: response.baseInfo.lastStatusReason ?? null
},
lifecycle: {
statusCode: response.lifecycle.statusCode,
lastStatusReason: response.lifecycle.lastStatusReason ?? null,
availableActions:
response.lifecycle.availableActions?.map(item => ({
actionCode: item.actionCode,
actionName: item.actionName,
needReason: item.needReason
})) ?? []
}
};
}
export function normalizeProductMember(response: ProductMemberResponse): Api.Product.ProductMember {
return {
id: normalizeStringId(response.id),
userId: normalizeStringId(response.userId),
userNickname: response.userNickname || '',
roleId: normalizeStringId(response.roleId),
roleName: response.roleName || '',
roleCode: response.roleCode || '',
managerFlag: Boolean(response.managerFlag),
status: response.status,
joinedTime: response.joinedTime,
leftTime: response.leftTime ?? null,
remark: response.remark ?? null
};
}