Files
shanxia2.0/docs/superpowers/specs/2026-05-30-crm-migration-design.md
T
2026-07-13 20:26:43 +08:00

1202 lines
68 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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** 在业务字段之后包含以下公共字段:
```sql
`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(产品分类,树形)
```sql
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(产品主表)
```sql
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(产品定价)
```sql
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(价格变更历史)
```sql
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(库存变动日志)
```sql
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(产品标签)
```sql
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(产品-标签关联)
```sql
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 类型转换)。
```sql
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(客户主表)
```sql
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(客户跟进记录)
```sql
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(公海池操作记录)
```sql
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(公海池规则)
```sql
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(客户标签)
```sql
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(客户-标签关联)
```sql
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(联系人)
```sql
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(线索主表)
```sql
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(商机主表)
```sql
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(报价单)
```sql
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(合同主表)
```sql
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`(统一附件表,基于 CRM `sys_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` 统一附件表(基于 CRM `sys_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 租户字段
```sql
-- 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` |