12 KiB
CRM 功能移植通用指南
源系统:山峡 CRM(Java RuoYi + Vue 3,数据库
sx) 目标系统:山峡一体化门户(Python FastAPI + Vue 3,数据库shanxia2.0) 文档版本:v3.3 | 2026-05-31(补充线索/商机迁移工程约定与 OpenSpec 索引) 适用范围:所有原 CRM 界面移植到 shanxia2.0 的工作
⚠️ 强制要求(必读)
所有原 CRM 界面移植到 shanxia2.0 都必须遵循本指南和引用的规范文档,无例外。
强制流程
编写模块迁移方案 → 方案审核通过 → 按方案逐步实施 → 验证
- 实施前必须编写模块迁移方案:移植任何 CRM 模块前,必须先产出该模块的迁移方案文档(类似
docs/客户管理及公海池迁移方案.md的角色,但按步骤拆分为多个小文档) - 方案必须拆分为小文档:每个子文档聚焦单一主题;如果内容多就继续拆分(如
04-api-spec.md拆为04a/04b),不压缩不精简,保留完整信息 - 按方案实施,按步骤加载:实施时只加载当前步骤的方案文档 + 通用规范文档,不加载无关内容
- 不做方案外的工作:实施过程不得偏离方案,如需变更须先更新方案
禁止行为
- ❌ 不写方案直接编码
- ❌ 把所有内容塞进一个文档(如客户管理方案 4291 行)
- ❌ 偏离通用规范的 UI 适配方式(如机械式查找替换)
- ❌ 修改原 CRM 的字典值(dict_type/dict_value/dict_label)
- ❌ 减少原 CRM 的功能按钮、搜索条件、操作流程
移植四步法
第一步:编写模块迁移方案 → 第二步:拷贝前端 + UI适配 → 第三步:后端实现 + DDL更新 → 第四步:验证 + 经验沉淀
核心原则
| # | 原则 | 说明 |
|---|---|---|
| 1 | 功能不缩减 | 原 CRM 的每个按钮、搜索条件、操作流程都必须完整迁移 |
| 2 | 数据语义不变 | 字典 dict_value/dict_type/dict_label 与原 CRM 完全一致,禁止改为门户习惯值 |
| 3 | UI 风格适配 | 界面适配 Fresh Mint(#10b981),功能逻辑保留原 CRM 完整行为 |
| 4 | 前端先行 | 先拷贝原 CRM 前端代码保留功能完整性,再逐段适配 |
| 5 | 细粒度分步 | 每个模块拆分为 10~20 个小步骤,每步验证后再进下一步 |
| 6 | 先理解再编码 | 业务逻辑先在原 CRM Java 代码中理解清楚,再转写 Python |
| 7 | 逐行阅读后修改 | 前端适配不是机械式查找替换,而是逐行阅读理解后按需修改 |
| 8 | 逐行对比 set 语句 | 移植后端状态变更逻辑时,逐行对比原 CRM 的 .set() 调用,确认哪些字段清空、哪些保留 |
| 9 | 组件优先复用 | 新模块的"查看详情"等功能先搜索已有组件,直接引用不重新实现 |
| 10 | 字典名匹配 API 返回值 | 同一概念可能有多个字典,必须看 API 返回的 dict_value 格式选对 dict_type |
技术栈映射
| 层级 | 原 CRM | shanxia2.0 |
|---|---|---|
| 后端 | Spring Boot + RuoYi | FastAPI + SQLAlchemy |
| 数据校验 | Bean Validation | Pydantic v2 |
| 认证 | RuoYi Token | JWT |
| 前端 | Vue 3 + Element Plus + UnoCSS | Vue 3 + Element Plus + Tailwind CSS 4 + SCSS |
| 字典 | <dict-tag> + useDict |
useDictTag + dictStore |
| 消息 | proxy.$modal |
ElMessage / ElMessageBox |
| 上传 | RuoYi 上传组件 | MinIO fetchUploadAttachment |
| 权限 | hasPermi(['crm:xxx']) |
静态路由未配 authList 时用 useXxxPerm + /web/auth/menu-codes;已配路由时可用 v-auth |
| Excel 导出字典 | Java @ExcelDictFormat + ExcelDictConvert |
export_rows_to_xlsx_response + crm_export_columns.py(见下文) |
| 只读详情 | el-drawer / 自定义抽屉 |
SystemViewDialog(OpenSpec P09) |
| 文件下载 | 浏览器直接下载 blob | request.post({ responseType: 'blob' }) + http/index.ts blob 拦截 |
迁移工程约定(已沉淀,后续模块须遵循)
线索管理、商机管理迁移过程中形成的跨模块约定,已写入 OpenSpec 与子文档。新模块移植时 SHALL 对照本节,避免重复踩坑。
后端
| 主题 | 约定 | 权威位置 |
|---|---|---|
| Excel 导出字典翻译 | 列定义带 dict_type(对齐 Java *Vo 的 @ExcelDictFormat);一次 SQL 预加载字典;统一走 export_rows_to_xlsx_response |
OpenSpec api-conventions §「CRM Excel 导出」;backend/app/utils/excel_export.py、crm_export_columns.py |
| 导出依赖 | requirements.txt 含 openpyxl>=3.1.0,venv 须已安装 |
backend/requirements.txt |
| 列表/详情 body 字段 | Pydantic 路由层用 Python 属性名(create_time_range),勿用 JSON alias(createTimeRange) |
OpenSpec EC-API-001;ref-lessons-learned.md |
| pageSize 上限 | 通用列表 API 常 le=100;导出可传 page_size=10000 于 CRUD 层 |
ref-lessons-learned.md §16 |
| Java 对照快照 | 实施某后台步骤前按需拷贝本步 Java 到 docs/crm-migration/reference/java/{module}/;禁止方案阶段全量快照 |
scripts/snapshot-java.sh、reference/java/README.md |
前端
| 主题 | 约定 | 权威位置 |
|---|---|---|
| Blob 导出下载 | responseType: 'blob' 时拦截器跳过 JSON code 校验;request() 返回 res.data 本身 |
OpenSpec coding-conventions §「Blob 文件下载」;web-admin/src/utils/http/index.ts |
| 导出 API | 建议 showErrorMessage: false,由页面 catch 统一提示 |
api/crm/clue/index.ts exportClue |
| 查看详情 | CRM 模块只读详情用 SystemViewDialog,状态/类型字段配 tagType + dictStore.getLabel |
OpenSpec ui-conventions P09;参考 clue/detailDrawer.vue、opportunity/.../OpportunityDetailDrawer.vue |
| 按钮权限 | 菜单按钮权限码在 sys_menu.perms(如 crm:clue:export);页面用 useCluePerm / useOpportunityPerm 拉取 menu-codes |
hooks/business/useCluePerm.ts;ref-lessons-learned.md §28 |
| 用户下拉 | fetchUserOptions() 返回 { label, value };模板用 item.label / item.value,勿用 nickName/userId |
ref-lessons-learned.md(商机负责人下拉) |
| 字典展示 | 列表/详情/导出列的 dict_type 须与 API 返回的 dict_value 格式一致;必要时用 utils/crm-*-labels.ts 兜底 |
ref-lessons-learned.md §14;crm-opportunity-labels.ts |
新增 CRM 导出模块 checklist
- 在原 CRM 打开对应
*Vo.java,记录带@ExcelDictFormat(dictType=...)的字段。 - 在
backend/app/utils/crm_export_columns.py增加XXX_EXPORT_COLUMNS。 - 路由中
list_xxx取数后 仅调用export_rows_to_xlsx_response(...),禁止在路由内手写 openpyxl 循环。 - 前端
exportXxx:responseType: 'blob'+showErrorMessage: false;页面用Blob触发下载。
文档体系结构
一、通用指南(本文档)
总纲文件,定义强制要求、核心原则、技术栈映射、文档索引。所有 CRM 移植工作必须遵循。
二、通用规范文档(全程按需加载)
| 规范 | 文档 | 何时参考 |
|---|---|---|
| 数据库迁移规则 | ref-database-rules.md | 编写 DDL / Model / Schema 时 |
| 前端框架差异对照 | ref-frontend-diff.md | 前端 UI 适配时 |
| UI 规范强制要求 | ref-ui-standards.md | 前端 UI 适配时 |
| 移植经验与踩坑 | ref-lessons-learned.md | 全程参考,避免重蹈覆辙 |
| 模块移植状态 | module-status.md | 查看当前进度 |
三、实施步骤文档(按流程顺序加载)
| 步骤 | 文档 | 内容 | 何时加载 |
|---|---|---|---|
| 准备 + 编写方案 | step-01-prepare.md | 模块分析 + 编写模块迁移方案 | 开始移植新模块时 |
| 拷贝前端 | step-02-frontend-copy.md | 从原 CRM 拷贝 Vue 组件到 shanxia2.0 | 方案审核通过后 |
| 前端适配 | step-03-frontend-adapt.md | 逐行阅读修改,UI 规范适配 | 拷贝完成后 |
| 后端实现 | step-04-backend.md | DDL、Model、Schema、CRUD、API路由 | 前端适配完成后 |
| 验证 | step-05-verify.md | 功能验证、UI合规检查 | 后端实现完成后 |
四、模块迁移方案模板(每个模块必须编写)
移植任何 CRM 模块前,必须按以下模板产出该模块的迁移方案。方案保存在 docs/crm-migration/plans/{module}/ 目录下。每个文档聚焦单一主题,内容多时继续拆分子文档(如 04a-api-clue.md + 04b-api-follow.md),不压缩不精简:
docs/crm-migration/plans/{module}/
├── 01-overview.md ← 模块概述(迁移范围、涉及表、迁移策略)
├── 02-database.md ← 数据库表模型(迁移后DDL、字段对照表)
├── 03-frontend-spec.md ← 前端页面功能规格(字段、按钮、交互流程)
├── 04-api-spec.md ← 后端API接口规格(URL、参数、响应、业务逻辑)
├── 05-special.md ← 特殊场景(定时任务、导入导出、状态机等)
├── 06-steps.md ← 分步实施计划(10~20步,每步有完成标准)
└── 07-verify.md ← 验证清单(功能验证、UI合规检查、测试用例)
拆分原则:当某个文档内容较多(如 API 超过 15 个端点、前端超过 8 个页面),按子模块拆分为
04a/04b/04c等。每个文档完整保留信息,不做压缩或精简。
模板文件位于 docs/crm-migration/plan-template/,编写方案时参照模板结构填充内容。
已有参考:
docs/客户管理及公海池迁移方案.md(4291 行)包含了客户管理模块的完整方案内容,可作为内容参考。但它太长不适合 AI 直接使用,新方案必须按上述结构拆分为独立小文档。
关键源文件位置
| 资源 | 路径 |
|---|---|
| CRM 数据库快照 | docs/sql/sx.sql(43 张 crm_* 表) |
| 门户数据库快照 | docs/sql/shanxia2.0.sql |
| CRM Java 后端 | shanxia/crm/backend/(绝对路径:../shanxia/crm/backend/) |
| CRM Vue 前端 | shanxia/crm/web/(绝对路径:../shanxia/crm/web/) |
| CRM Java 模块代码 | shanxia/crm/backend/ruoyi-modules/ruoyi-crm/src/main/java/org/dromara/crm/ |
| CRM 前端视图 | shanxia/crm/web/src/views/crm/ |
| CRM 前端 API | shanxia/crm/web/src/api/crm/ |
| 前端迁移替换规则(完整版) | docs/crm-frontend-migration-guide.md |
| 客户管理迁移方案(完整版) | docs/客户管理及公海池迁移方案.md |
| UI 设计权威规范 | docs/web-admin-ui-spec-fresh-mint.md |
| 方案模板目录 | docs/crm-migration/plan-template/ |
| Excel 导出工具(后端) | backend/app/utils/excel_export.py、crm_export_columns.py |
| HTTP Blob 下载(前端) | web-admin/src/utils/http/index.ts |
| OpenSpec CRM 导出规范 | openspec/changes/zkxw-engineering-standards/specs/api-conventions/spec.md |
| OpenSpec Blob 下载规范 | openspec/changes/zkxw-engineering-standards/specs/coding-conventions/spec.md |
路径说明:
shanxia/crm/是与shanxia2.0并列的独立 Git 仓库。从 shanxia2.0 工作区根目录出发,实际路径为../shanxia/crm/。完整绝对路径示例:/Users/{user}/work/00code/shanxia/crm/。
设计原则:每个文档聚焦单一主题,内容多时继续拆分。不压缩不精简,保留完整信息。实施阶段按步骤逐个加载。避免出现像
客户管理及公海池迁移方案.md(4291 行)那样将所有内容塞进单个文档的问题。