feat(client): A3 客户与行业目录(两级行业、客户组、字段审批)
背景:A3 需把行业 / 客户 / 客户组 / 客户级字段立为资产根节点;用户确认两级行业树与混搭 UI(行业 B / 客户列表 A / 详情 A / 新建 B / 客户组 B / 字段 A)。 改动: - 新增 ADR-002,行业改为两级树,客户挂末级行业;同步 PRD / 技术架构 / 开发计划。 - 新增 client 模块:industries / customers / customer-groups / customer-fields 接口、真实 PrismaCustomerDirectory、客户状态机与客户转交、客户组数据范围解析、跨客户 404。 - 新增迁移与幂等种子(电商/金融两级行业、2 客户、1 客户组、4 条字段)。 - 前端新增行业/客户/客户组/字段审批页面与路由、导航更名(客户管理 / 行业管理 / 客户组),复用现有 token。 - 补充 shared 契约单测、client 集成用例、A3 浏览器 e2e。 影响面:client 模块与 client 表、shared 契约、web 路由/导航、ScopeContext 数据范围、OpenAPI 与种子;A1 客户转交占位由 client 实现替换。 回滚:回滚本提交;数据库保留新增表或按报告执行 down SQL;CUSTOMER_DIRECTORY 可切回空集实现。 验证:format:check / lint / typecheck / test 全绿(shared 131 / api 90 / web 125,共 346);test:int 5 文件 39 条;A3 e2e 1/1;build 8/8;真实浏览器六页验证通过。
This commit is contained in:
1 parent
8626996bb1
commit
140dc386c1
54 files changed
+9018
-147
No files matched your search
@@ -44,6 +44,36 @@ const RoleNewPage = lazy(async () => {
|
||||
return { default: module.RoleNewPage };
|
||||
});
|
||||
|
||||
const IndustriesPage = lazy(async () => {
|
||||
const module = await import('@/pages/system/industries/IndustriesPage');
|
||||
return { default: module.IndustriesPage };
|
||||
});
|
||||
|
||||
const CustomersPage = lazy(async () => {
|
||||
const module = await import('@/pages/system/customers/CustomersPage');
|
||||
return { default: module.CustomersPage };
|
||||
});
|
||||
|
||||
const CustomerNewPage = lazy(async () => {
|
||||
const module = await import('@/pages/system/customers/CustomerNewPage');
|
||||
return { default: module.CustomerNewPage };
|
||||
});
|
||||
|
||||
const CustomerDetailPage = lazy(async () => {
|
||||
const module = await import('@/pages/system/customers/CustomerDetailPage');
|
||||
return { default: module.CustomerDetailPage };
|
||||
});
|
||||
|
||||
const CustomerGroupsPage = lazy(async () => {
|
||||
const module = await import('@/pages/system/customer-groups/CustomerGroupsPage');
|
||||
return { default: module.CustomerGroupsPage };
|
||||
});
|
||||
|
||||
const CustomerFieldsPage = lazy(async () => {
|
||||
const module = await import('@/pages/system/customer-fields/CustomerFieldsPage');
|
||||
return { default: module.CustomerFieldsPage };
|
||||
});
|
||||
|
||||
function withSkeleton(node: ReactNode): ReactNode {
|
||||
return <Suspense fallback={<PageSkeleton rows={8} />}>{node}</Suspense>;
|
||||
}
|
||||
@@ -134,6 +164,54 @@ export const router = createBrowserRouter([
|
||||
</RequirePermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'system/industries',
|
||||
element: (
|
||||
<RequirePermission permission={Permission.CUSTOMER_READ}>
|
||||
{withSkeleton(<IndustriesPage />)}
|
||||
</RequirePermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'system/customers',
|
||||
element: (
|
||||
<RequirePermission permission={Permission.CUSTOMER_READ}>
|
||||
{withSkeleton(<CustomersPage />)}
|
||||
</RequirePermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'system/customers/new',
|
||||
element: (
|
||||
<RequirePermission permission={Permission.CUSTOMER_MANAGE}>
|
||||
{withSkeleton(<CustomerNewPage />)}
|
||||
</RequirePermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'system/customers/:id',
|
||||
element: (
|
||||
<RequirePermission permission={Permission.CUSTOMER_READ}>
|
||||
{withSkeleton(<CustomerDetailPage />)}
|
||||
</RequirePermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'system/customer-groups',
|
||||
element: (
|
||||
<RequirePermission permission={Permission.CUSTOMER_GROUP_MANAGE}>
|
||||
{withSkeleton(<CustomerGroupsPage />)}
|
||||
</RequirePermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'system/customer-fields/approvals',
|
||||
element: (
|
||||
<RequirePermission permission={Permission.CUSTOMER_FIELD_APPROVE}>
|
||||
{withSkeleton(<CustomerFieldsPage />)}
|
||||
</RequirePermission>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: ':moduleKey/:itemKey?',
|
||||
lazy: async () => ({
|
||||
|
||||
Reference in new issue
Block a user