1202 lines
68 KiB
Markdown
1202 lines
68 KiB
Markdown
# 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` |
|