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:
Stev_Wang committed 2026-11-03 21:45:38 +08:00
1 parent 8626996bb1
commit 140dc386c1
54 files changed
+9018 -147

No files matched your search

+482 -21
View File
@@ -203,27 +203,6 @@
]
}
},
"/api/v1/users/{id}/transfer-customers": {
"post": {
"description": "A3 客户模块落地前返回 42201",
"operationId": "UsersController_transferCustomers",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "客户转交(占位)",
"tags": [
"identity-users"
]
}
},
"/api/v1/departments/tree": {
"get": {
"description": "memberCount 含下级成员、directMemberCount 仅本部门直属成员;默认只返回启用部门,管理页传 include_disabled=true",
@@ -461,6 +440,488 @@
]
}
},
"/api/v1/industries": {
"get": {
"operationId": "IndustriesController_list",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "两级行业树(一级 → 二级)",
"tags": [
"client-industries"
]
},
"post": {
"operationId": "IndustriesController_create",
"parameters": [],
"responses": {
"201": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "新建一级 / 二级行业",
"tags": [
"client-industries"
]
}
},
"/api/v1/industries/{id}": {
"get": {
"operationId": "IndustriesController_detail",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "行业详情与引用(子行业 / 客户 / 资产)",
"tags": [
"client-industries"
]
},
"patch": {
"operationId": "IndustriesController_update",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "更新行业名称 / 排序 / 备注(层级与上级不可变)",
"tags": [
"client-industries"
]
},
"delete": {
"operationId": "IndustriesController_remove",
"parameters": [],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "删除行业(仅无子行业 / 客户 / 资产时)",
"tags": [
"client-industries"
]
}
},
"/api/v1/industries/{id}/status": {
"patch": {
"operationId": "IndustriesController_setStatus",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "停用 / 启用行业(有启用子行业时禁止停用)",
"tags": [
"client-industries"
]
}
},
"/api/v1/customers": {
"get": {
"operationId": "CustomersController_list",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "客户列表(游标分页 + 行业 / 状态 / 负责人 / 客户组筛选)",
"tags": [
"client-customers"
]
},
"post": {
"operationId": "CustomersController_create",
"parameters": [],
"responses": {
"201": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "新建客户(简称必填;行业必须为末级行业)",
"tags": [
"client-customers"
]
}
},
"/api/v1/customers/{id}": {
"get": {
"operationId": "CustomersController_detail",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "客户详情(跨客户访问统一 404)",
"tags": [
"client-customers"
]
},
"patch": {
"operationId": "CustomersController_update",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "更新客户档案(所属行业不可改;暂停 / 结束只读)",
"tags": [
"client-customers"
]
}
},
"/api/v1/customers/{id}/status": {
"patch": {
"operationId": "CustomersController_setStatus",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "客户状态:在服务 ⇄ 暂停 → 结束(结束不可逆)",
"tags": [
"client-customers"
]
}
},
"/api/v1/customers/{id}/transfer": {
"post": {
"operationId": "CustomersController_transfer",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "变更客户负责人(写审计)",
"tags": [
"client-customers"
]
}
},
"/api/v1/customers/{id}/groups": {
"put": {
"operationId": "CustomersController_setGroups",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "设置客户所属客户组(覆盖式)",
"tags": [
"client-customers"
]
}
},
"/api/v1/customers/{id}/apply-industry-pack": {
"post": {
"operationId": "CustomersController_applyIndustryPack",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "套用行业资产包(B0 批次提供;当前返回业务提示)",
"tags": [
"client-customers"
]
}
},
"/api/v1/users/{id}/transfer-customers": {
"post": {
"operationId": "CustomerTransferController_transfer",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "把用户名下客户转交给另一负责人",
"tags": [
"client-customers"
]
}
},
"/api/v1/customer-groups": {
"get": {
"operationId": "CustomerGroupsController_list",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "客户组列表(授权与数据范围最小单位)",
"tags": [
"client-customer-groups"
]
},
"post": {
"operationId": "CustomerGroupsController_create",
"parameters": [],
"responses": {
"201": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "新建客户组",
"tags": [
"client-customer-groups"
]
}
},
"/api/v1/customer-groups/{id}": {
"get": {
"operationId": "CustomerGroupsController_detail",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "客户组详情与成员",
"tags": [
"client-customer-groups"
]
},
"patch": {
"operationId": "CustomerGroupsController_update",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "更新客户组名称 / 说明",
"tags": [
"client-customer-groups"
]
},
"delete": {
"operationId": "CustomerGroupsController_remove",
"parameters": [],
"responses": {
"204": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "删除客户组(被角色数据范围引用时拒绝)",
"tags": [
"client-customer-groups"
]
}
},
"/api/v1/customer-groups/{id}/members": {
"post": {
"operationId": "CustomerGroupsController_updateMembers",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "批量添加 / 移除成员(幂等)",
"tags": [
"client-customer-groups"
]
}
},
"/api/v1/customer-fields": {
"get": {
"operationId": "CustomerFieldsController_list",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "字段审批队列(待审批 / 已生效 / 已驳回)",
"tags": [
"client-customer-fields"
]
}
},
"/api/v1/customer-fields/{id}/approve": {
"post": {
"operationId": "CustomerFieldsController_approve",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "审批客户级字段(通过 / 驳回;驳回原因必填)",
"tags": [
"client-customer-fields"
]
}
},
"/api/v1/customers/{id}/fields": {
"get": {
"operationId": "CustomerFieldsOfCustomerController_list",
"parameters": [],
"responses": {
"200": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "客户级字段列表(基础字段在 customers.custom_fields)",
"tags": [
"client-customer-fields"
]
},
"post": {
"operationId": "CustomerFieldsOfCustomerController_apply",
"parameters": [],
"responses": {
"201": {
"description": ""
}
},
"security": [
{
"bearer": []
}
],
"summary": "申请客户级字段(进入生成字段需审批;每客户 ≤ 5)",
"tags": [
"client-customer-fields"
]
}
},
"/health": {
"get": {
"description": "真实检查 PostgreSQL 与 Redis;任一不可用返回 503 与统一错误体。",