68 KiB
CRM 模块迁移设计文档
日期: 2026-05-30 状态: 待审核 决策: 方案 A+C — 统一规范重建 + 渐进式分迭代交付
1. 背景与目标
1.1 背景
山峡化工现有两套独立系统:
- 一体化门户 (
shanxia2.0): Python FastAPI + Vue 3,覆盖系统管理、细胞存储、工作流等 - CRM 系统 (
shanxia/crm): Java Spring Boot (若依框架) + Vue 3,覆盖线索/客户/商机/合同等
目标:将 CRM 核心业务模块迁移至一体化门户,统一技术栈和运行时。
1.2 迁移范围
迁移的模块(8 个业务域,~28 张表):
| 模块 | CRM 表 | 页面数 | 优先级 |
|---|---|---|---|
| 产品分类 | crm_product_category |
1 | P0 |
| 产品管理 | crm_product, crm_product_price, crm_product_price_history, crm_product_stock_log, crm_product_tag, crm_product_tag_relation(附件复用 biz_attachment) |
6 | P0 |
| 客户管理 | crm_customer, crm_customer_follow, crm_customer_pool, crm_customer_pool_rule, crm_customer_tag, crm_customer_tag_relation |
12 | P1 |
| 联系人 | crm_contact |
4 | P1 |
| 线索管理 | crm_clue, crm_clue_follow |
9 | P2 |
| 商机管理 | crm_opportunity, crm_opportunity_follow, crm_opportunity_product, crm_opportunity_stage_log |
8 | P2 |
| 报价管理 | crm_quote, crm_quote_product, crm_quote_approval, crm_quote_share_log |
7 | P3 |
| 合同管理 | crm_contract, crm_contract_product, crm_contract_product_price_tier, crm_contract_approval, crm_contract_change, crm_contract_template |
12 | P3 |
不迁移:报销子系统 (bx_)、拜访管理、发票管理、回款管理、智慧校园 (xg_)
1.3 交付节奏(4 个迭代)
迭代 1(基础层): 产品分类 + 产品管理 + 字典数据迁移 SQL
迭代 2(核心客户): 客户管理 + 联系人 + 标签 + 公海池
迭代 3(销售漏斗): 线索管理 + 商机管理
迭代 4(成交闭环): 报价管理 + 合同管理(含工作流审批对接)
2. 设计决策
| 决策点 | 结论 | 理由 |
|---|---|---|
| 主键策略 | VARCHAR(64),数据迁移 原样保留源 id |
见 docs/data-migration/05-id-preservation-policy.md |
| 租户字段 | 统一 tenant_no VARCHAR(64) |
与一体化 sys_* 表一致 |
| 用户/部门引用 | VARCHAR(64) 指向 sys_user/sys_dept |
复用一体化用户体系 |
| 附件策略 | 新建 sys_oss(基于 CRM sys_oss 结构,id→str(oss_id) + 加 tenant_no + biz_type/biz_id),全系统共用 |
与 CRM 源表同名同字段,方便迁移;报销/地磅等也复用 |
| 字典策略 | 复用一体化 sys_dict_data/sys_dict_type,CRM 字典数据迁移 SQL 插入 |
字典功能相同,避免两套字典割裂 |
| 工作流 | 复用 wf_* 引擎 |
合同审批、报价审批走统一工作流 |
| 字典数据 | 编写迁移 SQL 脚本导入 sys_dict_data |
CRM 使用的行业/来源/等级等字典需导入 |
| 前端 UI | 按 Fresh Mint 规范重写,参考现有模板页 | 与一体化 UI 一致 |
| 软删除 | del_flag SMALLINT DEFAULT 0 |
与一体化一致 |
| 排序字段 | order_num INTEGER |
与一体化一致(列表/弹窗默认不展示) |
3. 公共字段规范(shanxia2.0 标准)
每张 CRM 业务表 SHALL 在业务字段之后包含以下公共字段:
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
主键:id VARCHAR(64) NOT NULL;生产数据迁移时写入 str(源id)(见 05-id-preservation-policy)。
4. 表结构设计(按迭代)
4.1 迭代 1 — 产品分类 + 产品管理
已排除功能(用户确认):产品定价(crm_product_price)、价格历史(crm_product_price_history)、库存日志(crm_product_stock_log)、产品标签(crm_product_tag + crm_product_tag_relation)、复制产品 — 原因:用户确认无此业务需求。
crm_product_category(产品分类,树形)
CREATE TABLE `crm_product_category` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`parent_id` VARCHAR(64) NOT NULL DEFAULT '0' COMMENT '父级分类ID(0为顶级)',
`category_name` VARCHAR(128) NOT NULL COMMENT '分类名称',
`category_code` VARCHAR(64) DEFAULT NULL COMMENT '分类编码',
`level` TINYINT NOT NULL DEFAULT 1 COMMENT '层级',
`status` CHAR(1) NOT NULL DEFAULT '1' COMMENT '状态 1启用 0停用',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-产品分类';
crm_product(产品主表)
CREATE TABLE `crm_product` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`product_no` VARCHAR(50) NOT NULL COMMENT '产品编号',
`product_name` VARCHAR(200) NOT NULL COMMENT '产品名称',
`category_id` VARCHAR(64) DEFAULT NULL COMMENT '分类ID',
`category_name` VARCHAR(100) DEFAULT NULL COMMENT '分类名称(冗余)',
`model` VARCHAR(100) DEFAULT NULL COMMENT '规格型号',
`unit` VARCHAR(20) NOT NULL DEFAULT '件' COMMENT '单位',
`price` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '标准单价',
`cost_price` DECIMAL(15,2) DEFAULT 0.00 COMMENT '成本价',
`status` CHAR(1) NOT NULL DEFAULT '1' COMMENT '状态 1上架 0下架',
`description` TEXT DEFAULT NULL COMMENT '产品描述',
`package_spec` VARCHAR(200) DEFAULT NULL COMMENT '包装规格',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_no` (`product_no`, `del_flag`),
KEY `idx_category_id` (`category_id`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-产品主表';
crm_product_price(产品定价)
CREATE TABLE `crm_product_price` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`product_id` VARCHAR(64) NOT NULL COMMENT '产品ID',
`price_type` VARCHAR(20) NOT NULL DEFAULT 'standard' COMMENT '价格类型 standard-标准价 wholesale-批发价 retail-零售价',
`price` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '价格',
`min_quantity` DECIMAL(20,4) DEFAULT 1.0000 COMMENT '最低起订量',
`effective_date` DATE DEFAULT NULL COMMENT '生效日期',
`expiry_date` DATE DEFAULT NULL COMMENT '失效日期',
`status` CHAR(1) NOT NULL DEFAULT '1' COMMENT '状态 1有效 0无效',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-产品定价';
crm_product_price_history(价格变更历史)
CREATE TABLE `crm_product_price_history` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`product_id` VARCHAR(64) NOT NULL COMMENT '产品ID',
`old_price` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '变更前价格',
`new_price` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '变更后价格',
`change_reason` VARCHAR(500) DEFAULT NULL COMMENT '变更原因',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-产品价格历史';
crm_product_stock_log(库存变动日志)
CREATE TABLE `crm_product_stock_log` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`product_id` VARCHAR(64) NOT NULL COMMENT '产品ID',
`change_type` VARCHAR(20) NOT NULL COMMENT '变动类型 in-入库 out-出库 adjust-调整',
`quantity` DECIMAL(20,4) NOT NULL DEFAULT 0.0000 COMMENT '变动数量',
`before_qty` DECIMAL(20,4) NOT NULL DEFAULT 0.0000 COMMENT '变动前库存',
`after_qty` DECIMAL(20,4) NOT NULL DEFAULT 0.0000 COMMENT '变动后库存',
`biz_type` VARCHAR(32) DEFAULT NULL COMMENT '关联业务类型 contract-合同 deliver-发货',
`biz_id` VARCHAR(64) DEFAULT NULL COMMENT '关联业务ID',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_product_id` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-产品库存日志';
crm_product_tag(产品标签)
CREATE TABLE `crm_product_tag` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`tag_name` VARCHAR(64) NOT NULL COMMENT '标签名称',
`color` VARCHAR(20) DEFAULT NULL COMMENT '标签颜色',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-产品标签';
crm_product_tag_relation(产品-标签关联)
CREATE TABLE `crm_product_tag_relation` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`product_id` VARCHAR(64) NOT NULL COMMENT '产品ID',
`tag_id` VARCHAR(64) NOT NULL COMMENT '标签ID',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_tag` (`product_id`, `tag_id`),
KEY `idx_tag_id` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-产品标签关联';
注意:
crm_product_attachment不再建独立表。产品附件统一使用sys_oss,biz_type = 'crm_product',biz_id = 产品ID。
sys_oss(统一附件表,基于 CRM sys_oss 结构,全系统共用)
采用 CRM 系统
sys_oss的字段模型,仅将oss_id(bigint)改为id(str(oss_id)),新增tenant_no,新增biz_type/biz_id关联字段。 此表为 CRM、报销、地磅等所有子系统的统一附件存储,通过biz_type区分业务归属。 方便后续从 CRM 直接迁移 sys_oss 数据(字段名完全一致,仅 id 类型转换)。
CREATE TABLE `sys_oss` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID(原 CRM sys_oss.oss_id)',
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号(原 CRM sys_oss.tenant_id)',
`biz_type` VARCHAR(50) DEFAULT NULL COMMENT '业务类型(crm_product/crm_customer/crm_contract/bx_advance/bx_reimburse/dibang_weigh 等)',
`biz_id` VARCHAR(64) DEFAULT NULL COMMENT '业务主键ID',
`file_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '文件名(原 sys_oss.file_name)',
`original_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '原始文件名(原 sys_oss.original_name)',
`file_suffix` VARCHAR(10) NOT NULL DEFAULT '' COMMENT '文件后缀名(原 sys_oss.file_suffix)',
`url` VARCHAR(500) NOT NULL COMMENT '文件URL地址(原 sys_oss.url)',
`file_size` BIGINT DEFAULT NULL COMMENT '文件大小(字节)',
`file_type` VARCHAR(200) DEFAULT NULL COMMENT 'MIME类型',
`attach_type` VARCHAR(32) DEFAULT 'attachment' COMMENT '附件类型 attachment-普通附件 invoice-发票 image-图片 issue_proof-发放截图',
`sort_order` INT NOT NULL DEFAULT 0 COMMENT '排序号',
`service` VARCHAR(20) NOT NULL DEFAULT 'minio' COMMENT '存储服务商(原 sys_oss.service)',
`ext1` TEXT DEFAULT NULL COMMENT '扩展字段(原 sys_oss.ext1)',
-- 公共字段
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id(经 user_mapping)',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id(经 user_mapping)',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_biz` (`biz_type`, `biz_id`),
KEY `idx_tenant` (`tenant_no`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='统一附件表(全系统共用,基于CRM sys_oss结构)';
4.2 迭代 2 — 客户管理 + 联系人 + 标签 + 公海池
crm_customer(客户主表)
CREATE TABLE `crm_customer` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`customer_no` VARCHAR(50) NOT NULL COMMENT '客户编号',
`customer_name` VARCHAR(200) NOT NULL COMMENT '客户名称',
`short_name` VARCHAR(100) DEFAULT NULL COMMENT '客户简称',
`customer_type` VARCHAR(20) NOT NULL DEFAULT 'company' COMMENT '客户类型 company-企业 person-个人',
`mobile` VARCHAR(20) DEFAULT NULL COMMENT '手机号',
`telephone` VARCHAR(30) DEFAULT NULL COMMENT '固定电话',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
`website` VARCHAR(500) DEFAULT NULL COMMENT '客户网站',
`level` VARCHAR(20) NOT NULL DEFAULT 'normal' COMMENT '客户级别 key-重点 normal-普通 potential-潜在',
`source` VARCHAR(20) DEFAULT NULL COMMENT '客户来源',
`industry` VARCHAR(50) DEFAULT NULL COMMENT '所属行业',
`park_area` VARCHAR(100) DEFAULT NULL COMMENT '所在园区',
`payment_terms` VARCHAR(500) DEFAULT NULL COMMENT '收付款条件',
`scale` VARCHAR(20) DEFAULT NULL COMMENT '企业规模',
`province` VARCHAR(50) DEFAULT NULL COMMENT '省',
`city` VARCHAR(50) DEFAULT NULL COMMENT '市',
`district` VARCHAR(50) DEFAULT NULL COMMENT '区',
`address` VARCHAR(255) DEFAULT NULL COMMENT '详细地址',
`status` VARCHAR(20) NOT NULL DEFAULT 'normal' COMMENT '客户状态 normal-正常 pool-公海 invalid-无效',
`deal_status` VARCHAR(20) NOT NULL DEFAULT 'not_deal' COMMENT '成交状态 not_deal-未成交 dealed-已成交 lost-已流失',
`owner_user_id` VARCHAR(64) DEFAULT NULL COMMENT '负责人ID',
`owner_user_name` VARCHAR(50) DEFAULT NULL COMMENT '负责人姓名(冗余)',
`last_time` DATETIME DEFAULT NULL COMMENT '最后跟进时间',
`next_time` DATETIME DEFAULT NULL COMMENT '下次联系时间',
`follow_count` INT NOT NULL DEFAULT 0 COMMENT '跟进次数',
`deal_time` DATETIME DEFAULT NULL COMMENT '成交时间',
`deal_amount` DECIMAL(15,2) DEFAULT 0.00 COMMENT '累计成交金额',
`contact_count` INT NOT NULL DEFAULT 0 COMMENT '联系人数量',
`opportunity_count` INT NOT NULL DEFAULT 0 COMMENT '商机数量',
`contract_count` INT NOT NULL DEFAULT 0 COMMENT '合同数量',
`into_pool_time` DATETIME DEFAULT NULL COMMENT '进入公海时间',
`into_pool_by` VARCHAR(64) DEFAULT NULL COMMENT '进入公海操作人ID',
`into_pool_reason` VARCHAR(500) DEFAULT NULL COMMENT '进入公海原因',
`claim_time` DATETIME DEFAULT NULL COMMENT '领取时间',
`assign_time` DATETIME DEFAULT NULL COMMENT '分配时间',
`assign_by` VARCHAR(64) DEFAULT NULL COMMENT '分配人ID',
`protect_time` DATETIME DEFAULT NULL COMMENT '保护到期时间',
`clue_id` VARCHAR(64) DEFAULT NULL COMMENT '关联线索ID',
`business_license_images` VARCHAR(1000) DEFAULT NULL COMMENT '营业执照图片(逗号分隔附件ID)',
`business_permit_images` VARCHAR(1000) DEFAULT NULL COMMENT '经营许可证图片(逗号分隔附件ID)',
`other_cert_images` VARCHAR(1000) DEFAULT NULL COMMENT '其他证件图片(逗号分隔附件ID)',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_customer_no` (`customer_no`, `del_flag`),
KEY `idx_owner` (`owner_user_id`),
KEY `idx_status` (`status`),
KEY `idx_deal_status` (`deal_status`),
KEY `idx_level` (`level`),
KEY `idx_source` (`source`),
KEY `idx_clue` (`clue_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-客户主表';
crm_customer_follow(客户跟进记录)
CREATE TABLE `crm_customer_follow` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`customer_id` VARCHAR(64) NOT NULL COMMENT '客户ID',
`customer_name` VARCHAR(200) DEFAULT NULL COMMENT '客户名称(冗余)',
`contact_id` VARCHAR(64) DEFAULT NULL COMMENT '联系人ID',
`contact_name` VARCHAR(100) DEFAULT NULL COMMENT '联系人姓名(冗余)',
`follow_type` VARCHAR(20) NOT NULL COMMENT '跟进方式 电话/微信/邮件/拜访/其他',
`follow_content` TEXT NOT NULL COMMENT '跟进内容',
`next_time` DATETIME DEFAULT NULL COMMENT '下次联系时间',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id(跟进人)',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '跟进时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_customer_id` (`customer_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-客户跟进记录';
crm_customer_pool(公海池操作记录)
CREATE TABLE `crm_customer_pool` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`customer_id` VARCHAR(64) NOT NULL COMMENT '客户ID',
`customer_name` VARCHAR(200) DEFAULT NULL COMMENT '客户名称(冗余)',
`operation_type` VARCHAR(20) NOT NULL COMMENT '操作类型 into-进入公海 claim-领取 assign-分配 recycle-回收',
`from_user_id` VARCHAR(64) DEFAULT NULL COMMENT '原负责人ID',
`from_user_name` VARCHAR(50) DEFAULT NULL COMMENT '原负责人姓名(冗余)',
`to_user_id` VARCHAR(64) DEFAULT NULL COMMENT '新负责人ID',
`to_user_name` VARCHAR(50) DEFAULT NULL COMMENT '新负责人姓名(冗余)',
`reason` VARCHAR(500) DEFAULT NULL COMMENT '操作原因',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_customer_id` (`customer_id`),
KEY `idx_operation_type` (`operation_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-公海池操作记录';
crm_customer_pool_rule(公海池规则)
CREATE TABLE `crm_customer_pool_rule` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`pool_name` VARCHAR(100) NOT NULL COMMENT '规则名称',
`rule_type` VARCHAR(20) NOT NULL COMMENT '规则类型 no_follow-未跟进 no_deal-未成交',
`timeout_days` INT NOT NULL COMMENT '超时天数',
`protect_days` INT NOT NULL DEFAULT 0 COMMENT '保护期天数',
`status` VARCHAR(20) NOT NULL DEFAULT 'enable' COMMENT '状态 enable-启用 disable-禁用',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-公海池规则';
crm_customer_tag(客户标签)
CREATE TABLE `crm_customer_tag` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`tag_name` VARCHAR(64) NOT NULL COMMENT '标签名称',
`color` VARCHAR(20) DEFAULT NULL COMMENT '标签颜色',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-客户标签';
crm_customer_tag_relation(客户-标签关联)
CREATE TABLE `crm_customer_tag_relation` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`customer_id` VARCHAR(64) NOT NULL COMMENT '客户ID',
`tag_id` VARCHAR(64) NOT NULL COMMENT '标签ID',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_customer_tag` (`customer_id`, `tag_id`),
KEY `idx_tag_id` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-客户标签关联';
crm_contact(联系人)
CREATE TABLE `crm_contact` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`customer_id` VARCHAR(64) NOT NULL COMMENT '客户ID',
`customer_name` VARCHAR(200) DEFAULT NULL COMMENT '客户名称(冗余)',
`contact_name` VARCHAR(100) NOT NULL COMMENT '联系人姓名',
`gender` VARCHAR(10) DEFAULT NULL COMMENT '性别 male-男 female-女',
`mobile` VARCHAR(20) DEFAULT NULL COMMENT '手机号',
`telephone` VARCHAR(30) DEFAULT NULL COMMENT '固定电话',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
`wechat` VARCHAR(100) DEFAULT NULL COMMENT '微信号',
`qq` VARCHAR(20) DEFAULT NULL COMMENT 'QQ号',
`department` VARCHAR(100) DEFAULT NULL COMMENT '部门',
`position` VARCHAR(50) DEFAULT NULL COMMENT '职位',
`role` VARCHAR(20) DEFAULT NULL COMMENT '角色 decision-决策人 manager-管理者 user-使用者 other-其他',
`birthday` DATE DEFAULT NULL COMMENT '生日',
`address` VARCHAR(255) DEFAULT NULL COMMENT '住址',
`is_key` TINYINT NOT NULL DEFAULT 0 COMMENT '是否关键决策人 0否 1是',
`is_primary` TINYINT NOT NULL DEFAULT 0 COMMENT '是否主要联系人 0否 1是',
`status` VARCHAR(20) NOT NULL DEFAULT 'active' COMMENT '状态 active-在职 leave-离职',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_customer_id` (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-联系人';
4.3 迭代 3 — 线索管理 + 商机管理
crm_clue(线索主表)
CREATE TABLE `crm_clue` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`clue_name` VARCHAR(100) NOT NULL COMMENT '线索姓名',
`mobile` VARCHAR(20) NOT NULL COMMENT '手机号',
`company` VARCHAR(200) DEFAULT NULL COMMENT '公司名称',
`customer_type` VARCHAR(20) DEFAULT NULL COMMENT '客户类型 company-企业 person-个人',
`telephone` VARCHAR(30) DEFAULT NULL COMMENT '固定电话',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
`title` VARCHAR(10) DEFAULT NULL COMMENT '称呼 先生/女士/其他',
`position` VARCHAR(50) DEFAULT NULL COMMENT '职位',
`source` VARCHAR(20) NOT NULL COMMENT '线索来源',
`level` VARCHAR(10) NOT NULL DEFAULT 'unrated' COMMENT '线索等级 A/B/C/unrated',
`industry` VARCHAR(50) DEFAULT NULL COMMENT '所属行业',
`park_area` VARCHAR(100) DEFAULT NULL COMMENT '所在园区',
`province` VARCHAR(50) DEFAULT NULL COMMENT '省',
`city` VARCHAR(50) DEFAULT NULL COMMENT '市',
`district` VARCHAR(50) DEFAULT NULL COMMENT '区',
`address` VARCHAR(255) DEFAULT NULL COMMENT '详细地址',
`website` VARCHAR(500) DEFAULT NULL COMMENT '客户网站',
`intent_products` VARCHAR(500) DEFAULT NULL COMMENT '意向产品(逗号分隔)',
`expect_time` DATE DEFAULT NULL COMMENT '预计购买时间',
`budget` VARCHAR(20) DEFAULT NULL COMMENT '预算范围',
`requirement` TEXT DEFAULT NULL COMMENT '需求描述',
`status` VARCHAR(20) NOT NULL DEFAULT 'new' COMMENT '线索状态 new-新线索 follow-跟进中 invalid-无效 converted-已转化',
`owner_user_id` VARCHAR(64) DEFAULT NULL COMMENT '负责人ID',
`owner_user_name` VARCHAR(50) DEFAULT NULL COMMENT '负责人姓名(冗余)',
`last_time` DATETIME DEFAULT NULL COMMENT '最后跟进时间',
`next_time` DATETIME DEFAULT NULL COMMENT '下次联系时间',
`follow_count` INT NOT NULL DEFAULT 0 COMMENT '跟进次数',
`is_converted` TINYINT NOT NULL DEFAULT 0 COMMENT '是否已转化 0否 1是',
`converted_time` DATETIME DEFAULT NULL COMMENT '转化时间',
`customer_id` VARCHAR(64) DEFAULT NULL COMMENT '转化的客户ID',
`converted_by` VARCHAR(64) DEFAULT NULL COMMENT '转化操作人',
`assign_time` DATETIME DEFAULT NULL COMMENT '分配时间',
`assign_by` VARCHAR(64) DEFAULT NULL COMMENT '分配人',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_mobile` (`mobile`),
KEY `idx_owner` (`owner_user_id`),
KEY `idx_status` (`status`),
KEY `idx_level` (`level`),
KEY `idx_source` (`source`),
KEY `idx_customer` (`customer_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-线索主表';
crm_clue_follow(线索跟进记录)
结构与 crm_customer_follow 类似,关联 clue_id 而非 customer_id。省略重复 SQL,实现时参照 crm_customer_follow 创建。
crm_opportunity(商机主表)
CREATE TABLE `crm_opportunity` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`opportunity_name` VARCHAR(200) NOT NULL COMMENT '商机名称',
`customer_id` VARCHAR(64) NOT NULL COMMENT '客户ID',
`customer_name` VARCHAR(200) DEFAULT NULL COMMENT '客户名称(冗余)',
`contact_id` VARCHAR(64) DEFAULT NULL COMMENT '联系人ID',
`contact_name` VARCHAR(100) DEFAULT NULL COMMENT '联系人姓名(冗余)',
`amount` DECIMAL(15,2) DEFAULT 0.00 COMMENT '预计金额',
`stage` VARCHAR(20) NOT NULL DEFAULT 'initial' COMMENT '商机阶段 initial-初步接洽/qualify-需求确认/proposal-方案报价/negotiation-商务谈判/won-赢单/lost-输单',
`probability` INT NOT NULL DEFAULT 0 COMMENT '成交概率(%)',
`expected_date` DATE DEFAULT NULL COMMENT '预计成交日期',
`source` VARCHAR(20) DEFAULT NULL COMMENT '商机来源',
`status` VARCHAR(20) NOT NULL DEFAULT 'active' COMMENT '状态 active-进行中 won-已赢 lost-已输',
`owner_user_id` VARCHAR(64) DEFAULT NULL COMMENT '负责人ID',
`owner_user_name` VARCHAR(50) DEFAULT NULL COMMENT '负责人姓名(冗余)',
`last_time` DATETIME DEFAULT NULL COMMENT '最后跟进时间',
`next_time` DATETIME DEFAULT NULL COMMENT '下次联系时间',
`follow_count` INT NOT NULL DEFAULT 0 COMMENT '跟进次数',
`clue_id` VARCHAR(64) DEFAULT NULL COMMENT '关联线索ID',
`lose_reason` VARCHAR(500) DEFAULT NULL COMMENT '输单原因',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_customer_id` (`customer_id`),
KEY `idx_owner` (`owner_user_id`),
KEY `idx_stage` (`stage`),
KEY `idx_status` (`status`),
KEY `idx_clue` (`clue_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-商机主表';
crm_opportunity_follow / crm_opportunity_product / crm_opportunity_stage_log
结构与 crm_customer_follow 类似,分别关联 opportunity_id。实现时参照创建。
4.4 迭代 4 — 报价管理 + 合同管理
crm_quote(报价单)
CREATE TABLE `crm_quote` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`quote_no` VARCHAR(50) NOT NULL COMMENT '报价单号',
`quote_name` VARCHAR(200) NOT NULL COMMENT '报价名称',
`customer_id` VARCHAR(64) NOT NULL COMMENT '客户ID',
`customer_name` VARCHAR(200) DEFAULT NULL COMMENT '客户名称(冗余)',
`opportunity_id` VARCHAR(64) DEFAULT NULL COMMENT '商机ID',
`contact_id` VARCHAR(64) DEFAULT NULL COMMENT '联系人ID',
`contact_name` VARCHAR(100) DEFAULT NULL COMMENT '联系人姓名(冗余)',
`amount` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '报价金额',
`discount_amount` DECIMAL(15,2) DEFAULT 0.00 COMMENT '优惠金额',
`final_amount` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '最终金额',
`status` VARCHAR(20) NOT NULL DEFAULT 'draft' COMMENT '状态 draft-草稿 pending-待审批 approved-已通过 rejected-已驳回',
`valid_until` DATE DEFAULT NULL COMMENT '报价有效期',
`wf_instance_id` VARCHAR(64) DEFAULT NULL COMMENT '工作流实例ID',
`owner_user_id` VARCHAR(64) DEFAULT NULL COMMENT '负责人ID',
`owner_user_name` VARCHAR(50) DEFAULT NULL COMMENT '负责人姓名(冗余)',
`contract_id` VARCHAR(64) DEFAULT NULL COMMENT '转化的合同ID',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_quote_no` (`quote_no`, `del_flag`),
KEY `idx_customer_id` (`customer_id`),
KEY `idx_opportunity_id` (`opportunity_id`),
KEY `idx_status` (`status`),
KEY `idx_owner` (`owner_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-报价单';
crm_quote_product / crm_quote_approval / crm_quote_share_log
参照 CRM 原始表结构,外键类型改为 VARCHAR(64)。实现时参照创建。
crm_contract(合同主表)
CREATE TABLE `crm_contract` (
`id` VARCHAR(64) NOT NULL COMMENT '主键ID',
`contract_no` VARCHAR(50) NOT NULL COMMENT '合同编号',
`contract_name` VARCHAR(200) NOT NULL COMMENT '合同名称',
`customer_id` VARCHAR(64) NOT NULL COMMENT '客户ID',
`customer_name` VARCHAR(200) DEFAULT NULL COMMENT '客户名称(冗余)',
`opportunity_id` VARCHAR(64) DEFAULT NULL COMMENT '商机ID',
`quote_id` VARCHAR(64) DEFAULT NULL COMMENT '报价单ID',
`parent_contract_id` VARCHAR(64) DEFAULT NULL COMMENT '原合同ID(续签)',
`renewal_count` INT NOT NULL DEFAULT 0 COMMENT '续签次数',
`template_id` VARCHAR(64) DEFAULT NULL COMMENT '合同模板ID',
`contract_template` VARCHAR(50) NOT NULL DEFAULT 'shanxia' COMMENT '合同模版 shanxia-山峡 customer-客户',
`contact_id` VARCHAR(64) DEFAULT NULL COMMENT '联系人ID',
`contact_name` VARCHAR(50) DEFAULT NULL COMMENT '联系人姓名(冗余)',
`contact_mobile` VARCHAR(20) DEFAULT NULL COMMENT '联系人手机(冗余)',
`contract_type` VARCHAR(20) NOT NULL DEFAULT 'sale' COMMENT '合同类型 sale-销售 service-服务 lease-租赁 other-其他',
`contract_nature` VARCHAR(20) NOT NULL DEFAULT 'new' COMMENT '合同性质 new-新签 renewal-续签 change-变更',
`amount` DECIMAL(15,2) NOT NULL DEFAULT 0.00 COMMENT '合同金额',
`currency` VARCHAR(10) NOT NULL DEFAULT 'CNY' COMMENT '币种',
`tax_rate` DECIMAL(5,2) DEFAULT 6.00 COMMENT '税率(%)',
`amount_with_tax` DECIMAL(15,2) DEFAULT 0.00 COMMENT '含税金额',
`sign_date` DATE DEFAULT NULL COMMENT '签订日期',
`actual_sign_date` DATE DEFAULT NULL COMMENT '实际签订日期',
`start_date` DATE DEFAULT NULL COMMENT '开始日期',
`end_date` DATE DEFAULT NULL COMMENT '结束日期',
`contract_period` INT DEFAULT NULL COMMENT '合同期限(月)',
`status` VARCHAR(20) NOT NULL DEFAULT 'draft' COMMENT '合同状态 draft-草稿 approving-审批中 approved-已审批 executing-执行中 finished-已完成 invalid-已作废',
`performance_status` VARCHAR(20) NOT NULL DEFAULT 'normal' COMMENT '履约状态 normal-正常 delayed-延期 abnormal-异常 completed-已完成',
`performance_rate` DECIMAL(5,2) DEFAULT 0.00 COMMENT '履约完成度(%)',
`approval_status` VARCHAR(20) DEFAULT NULL COMMENT '审批状态 pending-待审批 approved-已通过 rejected-已驳回',
`wf_instance_id` VARCHAR(64) DEFAULT NULL COMMENT '工作流实例ID',
`contract_file` VARCHAR(500) DEFAULT NULL COMMENT '合同文件路径',
`attachment_files` VARCHAR(1000) DEFAULT NULL COMMENT '附件(逗号分隔附件ID)',
`owner_user_id` VARCHAR(64) NOT NULL COMMENT '负责人ID',
`owner_user_name` VARCHAR(50) DEFAULT NULL COMMENT '负责人姓名(冗余)',
`received_amount` DECIMAL(15,2) DEFAULT 0.00 COMMENT '已回款金额',
`unreceived_amount` DECIMAL(15,2) DEFAULT 0.00 COMMENT '未回款金额',
`invoice_amount` DECIMAL(15,2) DEFAULT 0.00 COMMENT '已开票金额',
`uninvoice_amount` DECIMAL(15,2) DEFAULT 0.00 COMMENT '未开票金额',
-- 甲方信息
`party_a` VARCHAR(200) DEFAULT NULL COMMENT '甲方(客户方)',
`party_a_address` VARCHAR(255) DEFAULT NULL COMMENT '甲方地址',
`party_a_contact` VARCHAR(50) DEFAULT NULL COMMENT '甲方联系人',
`party_a_mobile` VARCHAR(20) DEFAULT NULL COMMENT '甲方联系电话',
`party_a_legal_person` VARCHAR(50) DEFAULT NULL COMMENT '甲方法定代表人',
`party_a_bank` VARCHAR(100) DEFAULT NULL COMMENT '甲方开户银行',
`party_a_account` VARCHAR(50) DEFAULT NULL COMMENT '甲方银行账号',
-- 乙方信息
`party_b` VARCHAR(200) DEFAULT NULL COMMENT '乙方(我方)',
`party_b_address` VARCHAR(255) DEFAULT NULL COMMENT '乙方地址',
`party_b_contact` VARCHAR(50) DEFAULT NULL COMMENT '乙方联系人',
`party_b_mobile` VARCHAR(20) DEFAULT NULL COMMENT '乙方联系电话',
`party_b_legal_person` VARCHAR(100) DEFAULT NULL COMMENT '乙方法定代表人',
`party_b_bank` VARCHAR(200) DEFAULT NULL COMMENT '乙方开户银行',
`party_b_account` VARCHAR(100) DEFAULT NULL COMMENT '乙方银行账号',
-- 条款
`payment_terms` TEXT DEFAULT NULL COMMENT '付款条款',
`delivery_terms` TEXT DEFAULT NULL COMMENT '交付条款',
`contract_terms` TEXT DEFAULT NULL COMMENT '合同条款',
-- 其他
`supplier_id` VARCHAR(64) DEFAULT NULL COMMENT '供方主体ID',
`settlement_method` VARCHAR(50) DEFAULT NULL COMMENT '结算方式 arrive_payment-货到付款 advance_payment-款到发货',
`invalid_reason` VARCHAR(500) DEFAULT NULL COMMENT '作废原因',
`invalid_time` DATETIME DEFAULT NULL COMMENT '作废时间',
`template_content` LONGTEXT DEFAULT NULL COMMENT '合同模板内容(富文本HTML)',
`settlement_clause_drafts` LONGTEXT DEFAULT NULL COMMENT '结算方式草稿(JSON)',
-- 公共字段
`tenant_no` VARCHAR(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` INT DEFAULT NULL COMMENT '排序号',
`remark` VARCHAR(512) DEFAULT NULL COMMENT '备注',
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人id',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` SMALLINT NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_contract_no` (`contract_no`, `del_flag`),
KEY `idx_customer_id` (`customer_id`),
KEY `idx_opportunity_id` (`opportunity_id`),
KEY `idx_quote_id` (`quote_id`),
KEY `idx_owner` (`owner_user_id`),
KEY `idx_status` (`status`),
KEY `idx_approval_status` (`approval_status`),
KEY `idx_sign_date` (`sign_date`),
KEY `idx_end_date` (`end_date`),
KEY `idx_parent_contract_id` (`parent_contract_id`),
KEY `idx_supplier_id` (`supplier_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='CRM-合同主表';
crm_contract_product / crm_contract_product_price_tier / crm_contract_approval / crm_contract_change / crm_contract_template
参照 CRM 原始表结构,外键类型改为 VARCHAR(64),公共字段统一。实现时参照创建。
5. 后端架构设计
5.1 目录结构
backend/
├── app/
│ ├── models/
│ │ └── crm_models.py — CRM 所有 SQLAlchemy 模型(~20 个类)
│ ├── schemas/
│ │ └── crm/
│ │ ├── product.py — 产品/分类 Pydantic schemas
│ │ ├── customer.py — 客户/联系人 schemas
│ │ ├── clue.py — 线索 schemas
│ │ ├── opportunity.py — 商机 schemas
│ │ ├── quote.py — 报价 schemas
│ │ └── contract.py — 合同 schemas
│ ├── crud/
│ │ └── crm/
│ │ ├── product.py — 产品 CRUD
│ │ ├── customer.py — 客户 CRUD
│ │ ├── clue.py — 线索 CRUD
│ │ ├── opportunity.py — 商机 CRUD
│ │ ├── quote.py — 报价 CRUD
│ │ └── contract.py — 合同 CRUD
│ ├── api/
│ │ └── crm.py — CRM 所有 API 路由(注册到 main.py)
│ └── services/
│ └── crm/
│ ├── customer_pool.py — 公海池逻辑(定时回收等)
│ └── biz_no_generator.py — 业务编号生成(客户编号、合同编号等)
5.2 API 路由设计
/api/crm/ — CRM 模块统一前缀
# 产品分类
GET /api/crm/product-categories — 列表(树形)
POST /api/crm/product-categories — 新增
PUT /api/crm/product-categories/{id} — 修改
DELETE /api/crm/product-categories/{id} — 删除
# 产品管理
GET /api/crm/products — 列表(分页)
GET /api/crm/products/{id} — 详情
POST /api/crm/products — 新增
PUT /api/crm/products/{id} — 修改
DELETE /api/crm/products/{id} — 删除
GET /api/crm/products/select-options — 下拉选项
# 客户管理
GET /api/crm/customers — 列表(分页)
GET /api/crm/customers/{id} — 详情
POST /api/crm/customers — 新增
PUT /api/crm/customers/{id} — 修改
DELETE /api/crm/customers/{id} — 删除
POST /api/crm/customers/{id}/follow — 添加跟进
GET /api/crm/customers/{id}/follows — 跟进列表
# 公海池
GET /api/crm/customer-pool — 公海池列表
POST /api/crm/customer-pool/{id}/claim — 领取
POST /api/crm/customer-pool/assign — 分配
GET /api/crm/customer-pool/rules — 规则列表
PUT /api/crm/customer-pool/rules/{id} — 修改规则
# 联系人
GET /api/crm/contacts — 列表
POST /api/crm/contacts — 新增
PUT /api/crm/contacts/{id} — 修改
DELETE /api/crm/contacts/{id} — 删除
# 线索管理
GET /api/crm/clues — 列表(分页)
GET /api/crm/clues/{id} — 详情
POST /api/crm/clues — 新增
PUT /api/crm/clues/{id} — 修改
DELETE /api/crm/clues/{id} — 删除
POST /api/crm/clues/{id}/follow — 添加跟进
POST /api/crm/clues/{id}/convert — 转化为客户
POST /api/crm/clues/{id}/invalid — 标记无效
POST /api/crm/clues/{id}/assign — 分配
# 商机管理
GET /api/crm/opportunities — 列表(分页)
GET /api/crm/opportunities/{id} — 详情
POST /api/crm/opportunities — 新增
PUT /api/crm/opportunities/{id} — 修改
DELETE /api/crm/opportunities/{id} — 删除
POST /api/crm/opportunities/{id}/follow — 添加跟进
POST /api/crm/opportunities/{id}/stage — 推进阶段(赢单/输单)
# 报价管理
GET /api/crm/quotes — 列表(分页)
GET /api/crm/quotes/{id} — 详情
POST /api/crm/quotes — 新增
PUT /api/crm/quotes/{id} — 修改
DELETE /api/crm/quotes/{id} — 删除
POST /api/crm/quotes/{id}/submit — 提交审批
POST /api/crm/quotes/{id}/to-contract — 转合同
# 合同管理
GET /api/crm/contracts — 列表(分页)
GET /api/crm/contracts/{id} — 详情
POST /api/crm/contracts — 新增
PUT /api/crm/contracts/{id} — 修改
DELETE /api/crm/contracts/{id} — 删除
POST /api/crm/contracts/{id}/submit — 提交审批
POST /api/crm/contracts/{id}/invalid — 作废
POST /api/crm/contracts/{id}/change — 变更
GET /api/crm/contracts/templates — 模板列表
GET /api/crm/contracts/templates/{id} — 模板详情
5.3 编码约定
- CRUD:继承
CRUDBase,遵循驼峰/蛇形自动映射 - 模型:所有模型继承
Base,公共字段与一体化一致 - 路由注册:CRM 路由注册在
app/api/__init__.py和app/main.py - 权限守卫:使用
require_admin_or_super_admin+require_menu_code("crm:xxx:list") - 租户隔离:所有查询过滤
tenant_no == current_user.tenant_no - 数据权限:使用
apply_data_scope()叠加角色数据权限 - 附件:通过
sys_oss(统一附件表,基于 CRMsys_oss结构),biz_type命名规则crm_{entity} - 工作流:审批通过
wf_instance_id关联wf_process_instance
6. 前端架构设计
6.1 目录结构
web-admin/src/
├── api/
│ └── crm/
│ ├── product.ts — 产品/分类 API
│ ├── customer.ts — 客户 API
│ ├── contact.ts — 联系人 API
│ ├── clue.ts — 线索 API
│ ├── opportunity.ts — 商机 API
│ ├── quote.ts — 报价 API
│ └── contract.ts — 合同 API
├── views/
│ └── crm/
│ ├── product/
│ │ ├── index.vue — 产品列表(参考 product/index.vue 模板)
│ │ ├── ProductFormDialog.vue
│ │ ├── ProductViewDialog.vue
│ │ └── PriceDialog.vue
│ ├── product-category/
│ │ └── index.vue — 产品分类(树形,参考 category/index.vue)
│ ├── customer/
│ │ ├── index.vue — 客户列表
│ │ ├── CustomerFormDialog.vue
│ │ ├── CustomerViewDialog.vue
│ │ ├── FollowDialog.vue
│ │ └── PoolPanel.vue
│ ├── contact/
│ │ ├── index.vue
│ │ └── ContactFormDialog.vue
│ ├── clue/
│ │ ├── index.vue
│ │ ├── ClueFormDialog.vue
│ │ ├── ConvertDialog.vue
│ │ └── FollowDialog.vue
│ ├── opportunity/
│ │ ├── index.vue
│ │ ├── OpportunityFormDialog.vue
│ │ ├── OpportunityViewDialog.vue
│ │ └── StageDialog.vue
│ ├── quote/
│ │ ├── index.vue
│ │ ├── QuoteFormDialog.vue
│ │ └── QuoteViewDialog.vue
│ └── contract/
│ ├── index.vue
│ ├── ContractFormDialog.vue
│ ├── ContractViewDialog.vue
│ └── TemplateDialog.vue
6.2 UI 规范
- 色彩:Fresh Mint (
--primary #10b981),不使用 CRM 的色板 - 表单弹窗:
label-position="top",.dialog-form-layout+.form-grid-2 - 表格:
el-table-column用min-width(不用width),操作列fixed="right"min-width ≥ 260px - 状态/类型字段:使用
<el-tag>+ 语义色 - 按钮图标:所有
el-button带<el-icon> - 附件上传:使用
sys_oss统一附件表(基于 CRMsys_oss接口模式),卡片化布局 - 模板页参考:
- 树形:
category/index.vue - 标准列表:
unit/index.vue - 复杂列表:
order/index.vue - 产品+查看弹窗:
product/index.vue
- 树形:
6.3 菜单注册
在 sqxp.ts 和 menu.py 中新增「CRM 管理」一级菜单:
CRM 管理
├── 产品分类
├── 产品管理
├── 客户管理
│ (公海池作为客户列表的 tab 或筛选条件)
├── 联系人
├── 线索管理
├── 商机管理
├── 报价管理
└── 合同管理
7. 数据迁移注意事项
本节记录数据迁移时需要特别注意的映射关系和风险点。 数据迁移方案将在后续单独编写。
7.1 主键映射
修订(2026-07-12):生产数据同步以
docs/data-migration/05-id-preservation-policy.md为准——业务主键原样保留(bigint→ 同值VARCHAR字符串),不再统一生成 UUID。用户外键仍经user_mapping转换。
| CRM (bigint) | 一体化 (VARCHAR) | 说明 |
|---|---|---|
id (AUTO_INCREMENT) |
id (str(id)) |
恒等映射;crm_id_mapping 用于审计 |
owner_user_id (bigint) |
owner_user_id (VARCHAR) |
例外:映射到 sys_user.id(门户 UUID) |
customer_id (bigint) |
customer_id (VARCHAR) |
str(customer_id);先迁客户再迁子表 |
create_by (bigint) |
create_by (VARCHAR) |
例外:映射到 sys_user.id |
7.2 租户字段
-- CRM: tenant_id (VARCHAR(20), DEFAULT '000000')
-- 一体化: tenant_no (VARCHAR(64), DEFAULT 'zkxw')
-- 迁移时: UPDATE SET tenant_no = 'zkxw' (或对应租户编号)
7.3 附件迁移
CRM 附件: sys_oss 表
oss_id (bigint) → 主键
url → 完整文件 URL
file_name / original_name / file_suffix → 文件信息
create_by (bigint) → 上传人
service → 存储服务商(minio)
目标: sys_oss 统一附件表(与 CRM 源表同名同结构)
id (VARCHAR) ← str(oss_id),原样保留
tenant_no ← tenant_id 改名
biz_type / biz_id ← 业务关联字段(需根据 CRM 中的附件关联逻辑补充)
file_name / original_name / file_suffix / url ← 字段名完全一致,直接复制
create_by (VARCHAR) ← create_by (bigint) 经 user_mapping
create_dept_id (VARCHAR) ← create_dept (bigint) 经 dept_mapping(若有)
service ← 字段完全一致,直接复制
迁移优势:
1. 字段名完全一致(file_name/original_name/file_suffix/url/service),直接 INSERT
2. 只需 oss_id→str(oss_id)、tenant_id→tenant_no、create_by/create_dept 的用户 UUID 映射
3. 未来报销系统(bx_*)、地磅系统的附件同样写入此表,用 biz_type 区分
4. 报销迁移时 bx_attachment 的数据也可映射到此表
7.4 字典数据迁移
CRM 字典来源: sys_dict_data (sx 库)
目标: sys_dict_data (shanxia2.0 库)
需迁移的字典类型:
- crm_customer_industry (行业)
- crm_customer_source (客户来源)
- crm_customer_level (客户级别)
- crm_clue_source (线索来源)
- crm_clue_level (线索等级)
- crm_opportunity_stage (商机阶段)
- crm_contract_type (合同类型)
- crm_contract_nature (合同性质)
- crm_follow_type (跟进方式)
- crm_budget_range (预算范围)
- crm_payment_terms (付款条件)
... (实现时从 CRM 数据库中导出完整列表)
7.5 部门映射
CRM: create_dept (bigint) → CRM 的 sys_dept
一体化: create_dept_id (VARCHAR(64)) → sys_dept
需先确认:
1. CRM 中的部门是否与一体化 sys_dept 一致
2. 如不一致,需导入部门数据并建立映射
7.6 迁移顺序(依赖关系)
1. 字典数据 (sys_dict_data)
2. 部门数据 (sys_dept) — 如需导入
3. 用户数据 (sys_user) — 如需导入
4. 产品分类 (crm_product_category)
5. 产品 (crm_product)
6. 产品附件 (→ biz_attachment)
7. 客户标签 (crm_customer_tag)
8. 客户 (crm_customer)
9. 联系人 (crm_contact)
10. 客户附件 (→ biz_attachment)
11. 客户跟进 (crm_customer_follow)
12. 公海池记录 (crm_customer_pool)
13. 线索 (crm_clue)
14. 线索跟进 (crm_clue_follow)
15. 商机 (crm_opportunity)
16. 商机产品/跟进/阶段日志
17. 报价单 + 产品
18. 合同 + 产品 + 审批记录
8. 定时任务
8.1 公海池自动回收
在 app/tasks/ 中实现:
规则:
- 未跟进超过 N 天的客户 → 自动进入公海池
- 未成交超过 N 天的客户 → 自动进入公海池
- 领取后保护 M 天内不回收
实现:
- 使用 APScheduler (一体化已有依赖)
- 每日定时扫描 crm_customer + crm_customer_pool_rule
- 符合条件的客户: status → 'pool',写入 crm_customer_pool 记录
9. 附录
A. CRM 原始表 → 新表对照清单
| CRM 原始表 | 新表 | 变更说明 |
|---|---|---|
| crm_product_category | crm_product_category | 主键原样保留 str(id),公共字段统一 |
| crm_product | crm_product | 主键原样保留 str(id),category_id 改 VARCHAR |
| crm_product_price | crm_product_price | 主键原样保留 str(id),product_id 改 VARCHAR |
| crm_product_price_history | crm_product_price_history | 主键原样保留 str(id) |
| crm_product_stock_log | crm_product_stock_log | 主键原样保留 str(id) |
| crm_product_tag | crm_product_tag | 主键原样保留 str(id) |
| crm_product_tag_relation | crm_product_tag_relation | 主键原样保留 str(id),关联 ID 改 VARCHAR |
| crm_product_attachment | 删除 → 复用 sys_oss | biz_type='crm_product' |
| crm_customer | crm_customer | 主键原样保留 str(id),owner/create 用户外键经 mapping |
| crm_customer_follow | crm_customer_follow | 主键原样保留 str(id) |
| crm_customer_pool | crm_customer_pool | 主键原样保留 str(id) |
| crm_customer_pool_rule | crm_customer_pool_rule | 主键原样保留 str(id) |
| crm_customer_tag | crm_customer_tag | 主键原样保留 str(id) |
| crm_customer_tag_relation | crm_customer_tag_relation | 主键原样保留 str(id) |
| crm_contact | crm_contact | 主键原样保留 str(id) |
| crm_clue | crm_clue | 主键原样保留 str(id) |
| crm_clue_follow | crm_clue_follow | 主键原样保留 str(id) |
| crm_opportunity | crm_opportunity | 主键原样保留 str(id) |
| crm_opportunity_follow | crm_opportunity_follow | 主键原样保留 str(id) |
| crm_opportunity_product | crm_opportunity_product | 主键原样保留 str(id) |
| crm_opportunity_stage_log | crm_opportunity_stage_log | 主键原样保留 str(id) |
| crm_quote | crm_quote | 主键原样保留 str(id) |
| crm_quote_product | crm_quote_product | 主键原样保留 str(id) |
| crm_quote_approval | crm_quote_approval | 主键原样保留 str(id) |
| crm_quote_share_log | crm_quote_share_log | 主键原样保留 str(id) |
| crm_contract | crm_contract | 主键原样保留 str(id) |
| crm_contract_product | crm_contract_product | 主键原样保留 str(id) |
| crm_contract_product_price_tier | crm_contract_product_price_tier | 主键原样保留 str(id) |
| crm_contract_approval | crm_contract_approval | 主键原样保留 str(id) |
| crm_contract_change | crm_contract_change | 主键原样保留 str(id) |
| crm_contract_template | crm_contract_template | 主键原样保留 str(id) |
B. 参考文件清单
| 用途 | 路径 |
|---|---|
| CRM DDL | docs/sql/sx.sql |
| 一体化 DDL | docs/sql/shanxia2.0.sql |
| CRM 后端 (Java) | /Users/zlwu/work/00code/shanxia/crm/backend/ |
| CRM 前端 (Vue) | /Users/zlwu/work/00code/shanxia/crm/web/ |
| 一体化后端模型 | backend/app/models/models.py |
| 一体化 CRUD 基类 | backend/app/crud/base.py |
| 一体化 API 示例 | backend/app/api/admin.py |
| 前端模板页-标准列表 | web-admin/src/views/system/unit/index.vue |
| 前端模板页-复杂列表 | web-admin/src/views/system/order/index.vue |
| 前端模板页-树形 | web-admin/src/views/system/category/index.vue |
| 前端模板页-产品 | web-admin/src/views/system/product/index.vue |
| 工程规范 | openspec/changes/zkxw-engineering-standards/specs/ |
| UI 规范 | docs/web-admin-ui-spec-fresh-mint.md |