润滑油 CRM/ERP 系统 — 阶段性全栈复盘与架构白皮书
项目代号:天津硕博霖业财一体化 ERP(SHBL-ERP)
当前阶段:Phase 2.0(多租户隔离 + AI 交互优化 / 内测上线态)
报告日期:2026 年 3 月 19 日
系统版本:v0.2.0
部署地址:http://192.168.1.100(内网单节点)
变更基线:基于 v0.1.0 (Phase 1.5) 增量更新
一、系统技术基座 (Tech Stack & Dependencies)
本系统采用现代化前后端分离架构,AI 能力通过 Dify + Ollama 私有化部署实现,全栈可控。
1. 前端架构 (Frontend)
| 技术 |
说明 |
| Vue 3 (Composition API) + TypeScript |
核心框架,14 个业务页面组件 |
| Vite |
构建工具,极速冷启动与 HMR |
| Element Plus |
企业级 UI,深度定制了报销单 @media print A4 打印样式 |
| Pinia |
全局状态管理(UserInfo、Token、RBAC 权限、当前公司 ID) |
| Axios |
封装全局 Request/Response 拦截器,自动处理 401 登出、业务异常及 X-Company-Id 头部注入 |
| SSE (EventSource) |
AI 复盘报告实时流式输出 |
2. 后端架构 (Backend)
| 技术 |
说明 |
| Python 3.10+ & FastAPI |
核心框架,17 个 API 路由模块,自带 OpenAPI/Swagger 文档 |
| Uvicorn |
ASGI 异步服务器 |
| SQLAlchemy 2.0 + Asyncpg |
全异步 ORM,24 张业务表 |
| Alembic |
数据库 Schema 版本管理(4 个迁移脚本),async 模式 |
| JWT + Passlib (Bcrypt) |
认证体系(Token + 密码哈希) |
| httpx |
异步 HTTP 客户端,用于调用 Dify API 和 Ollama |
3. AI 能力层
| 组件 |
说明 |
| Dify (192.168.1.88) |
AI 编排平台,承载 Workflow(复盘报告生成)和 Chat(AI 悬浮球对话) |
| Ollama — RTX 3090 (192.168.1.88:11434) |
运行 qwen3.5:27b,用于复盘报告、企业画像等重任务 |
| Ollama — RTX 4060 (192.168.1.88:11435) |
运行 qwen3.5:4b,用于发票 OCR 解析等轻任务 |
4. 数据持久层 (Database)
- 核心数据库:PostgreSQL(宿主机直连,asyncpg 驱动)
- 24 张业务表,覆盖 CRM、ERP、财务、AI、系统五大域 + 多租户域
- Alembic 迁移管理:4 个版本化迁移脚本(baseline → 多租户 → 新宇公司 → sales_logs 业务标签)
- 亮点特性:
JSONB 承载 AI OCR 提取数据 (ai_extracted_data)
ARRAY(UUID) 承载 sales_logs.involved_company_ids(多公司业务标签)
- 强事务并发控制(库存/发货防重)
- 行级多租户隔离(
company_id 外键 + GIN 索引)
5. 部署架构
二、多租户架构(v0.2.0 新增)
设计原则
采用行级数据隔离(Row-Level Isolation),同一数据库、同一张表,通过 company_id 列区分不同公司数据。
已注册公司
| 公司 |
UUID |
说明 |
| 天津硕博霖 |
aaaaaaaa-bbbb-cccc-dddd-eeeeeeee0001 |
默认公司 |
| 新宇润滑油 |
aaaaaaaa-bbbb-cccc-dddd-eeeeeeee0002 |
第二家公司 |
隔离矩阵
| 表 |
隔离方式 |
说明 |
erp_orders |
company_id FK |
订单按公司隔离 |
erp_shipping_records |
company_id FK |
发货单按公司隔离 |
erp_inventory_flows |
company_id FK |
库存流水按公司隔离 |
erp_sku_inventory |
company_id FK |
库存快照按公司隔离 |
fin_invoice_pool |
company_id FK |
报销发票池按公司隔离 |
fin_expense_records |
company_id FK |
报销单按公司隔离 |
finance_sales_invoices |
company_id FK |
销项发票按公司隔离 |
sales_logs |
involved_company_ids ARRAY(UUID) |
业务标签:一条日志可关联多个公司 |
crm_customers |
全局共享 |
客户资源跨公司共享 |
erp_product_categories |
全局共享 |
产品分类跨公司共享 |
erp_product_skus |
全局共享 |
产品 SKU 跨公司共享 |
技术实现链路
- IDOR 防护:
get_current_company_id 依赖会查 sys_user_companies 表验证当前用户确实关联了该公司,防止伪造 Header 越权
- 前端公司切换:登录页公司选择 + 首页顶部 Header 下拉切换
- sales_logs 特殊处理:使用
ARRAY.any(company_id) 包含查询 + GIN 索引加速
三、九大核心业务模块全景剖析
系统已点亮 9 大核心模块 + 2 个 AI 模块,实现从"线索"到"现金"的业财链路闭环,并接入大模型智能辅助。
模块 1:RBAC 权限与系统基座
- 功能:用户登录、改密、角色管理、员工管理、公司管理与切换
- 核心亮点:
data_scope 数据横向隔离 — self / dept_and_sub / all 三维度
- 多租户公司隔离 —
sys_companies + sys_user_companies 多对多关联,支持用户归属多个公司
X-Company-Id 依赖注入 — 所有私有数据查询均受公司视角拦截,双层校验(JWT + 公司归属)
- 关键表:
sys_users、sys_roles、sys_departments、sys_companies、sys_user_companies
模块 2:CRM 客户管理
- 功能:客户全生命周期管理(新增、编辑、归档、搜索筛选、导入/导出、转移负责人)
- 核心亮点:
- 创建时自动绑定
owner_id,融入 data_scope 防线
- 联系人管理 — 独立
crm_contacts 表,支持多联系人关联
- AI 企业画像 — 调用 Ollama 大模型生成企业分析卡片(Dify Workflow 回调双轨写入)
- AI 客情健康度评分 — 基于交互频率自动打分
- 批量 Excel 导入/导出 — 支持模板下载 + openpyxl 解析
- 客户转移 — 管理员可跨人员重新分配客户负责人
- 全局共享 — 客户数据跨公司共享,不受
company_id 隔离
- 关键表:
crm_customers、crm_contacts、crm_follow_up_logs
模块 3:供应链与货品库存
- 功能:左树(无限级分类)右表(SKU)经典布局
- 核心亮点:
- 无限级分类树:
erp_product_categories 自关联支持 N 级嵌套
- 安全库存变更:一切库存变动必须通过
POST /api/products/inventory/flow 提交出入库流水,后端强事务加减库存,留存 erp_inventory_flows 审计轨迹
- 库存预警:
stock_qty <= warning_threshold 自动标红提示(erp_sku_inventory 表)
- 批量 SKU 导入:Excel 模板 + SKU 编码防重
- 产品/分类全局共享 — SKU 和分类跨公司共享,库存快照 (
erp_sku_inventory) 按公司隔离
模块 4:订单交易枢纽
- 功能:主子表嵌套的沉浸式开单体验,支持多 SKU 明细行
- 核心亮点:
- B2B 智能动态定价(一客一价) — 选中 SKU 时静默调用
/api/orders/price/calculate,自动调取该客户历史专属拿货价
- 按公司隔离 — 订单数据通过
company_id 实现多租户隔离
模块 5:物流与发货执行
- 功能:发货单管理,指导仓库拣货出库
- 核心亮点:
- 五步原子事务防超发:校验
发货量 ≤ 订单总量 - 已发量,订单状态更新 + 库存扣减 + 发货单生成毫秒级级联
- 数据级联预加载:发货单透出客户名称、包装规格等
模块 6:财务报销与票据中心
- 功能:三 Tab 一站式财务管理 — 统一票据池 / 新建报销 / 报销大盘
- 核心亮点:
- 发票 AI 智能解析:拖拽上传 PDF/JPG/PNG/MD → 调用 Ollama 4060 (qwen3.5:4b) 自动提取发票号、金额、日期等字段 → 存入
fin_invoice_pool.ai_extracted_data (JSONB)
- 批量上传队列:支持多文件并行处理,逐一显示解析进度(不再自动清空,手动关闭)
- 发票状态机:发票被报销单选中瞬间
is_used 锁定,驳回自动释放
- 高级科目定制:硬编码专属原始种类(招待费、交通费)和冲顶类型(税务费用)
- A4 打印:CSS
@media print 标准黑白审批单,带四大签字占位符
模块 7:销项发票管理
- 功能:独立的销项发票(开票)管理模块
- 核心亮点:
- 客户名称/发票号搜索 + 回款状态筛选 + 开票日期范围
- AI 发票 OCR 识别 — 调用 Ollama 视觉模型提取
merchant/buyer/amount/date 等字段
- 批量 OCR → 待确认列表(v0.2.0 新增):批量上传后不直接创建,OCR 结果暂存可编辑表格,不完整字段标黄高亮,用户审核修正后"一键全部创建"批量入库
- 单文件模式:OCR 结果预填到新增表单,
buyer 字段自动匹配 CRM 客户
- 独立
finance_sales_invoices 表
模块 8:销售日志
- 功能:销售人员每日拜访/沟通记录管理
- 核心亮点:
- 独立
sales_logs 表,支持关键字搜索 + 日期筛选
- AI 智能审阅 — 调用大模型对日志内容进行质量评分和建议
- 数据同时作为 AI 复盘报告的原始素材
- 多公司业务标签(v0.2.0 新增):
involved_company_ids (ARRAY UUID) — 一篇日志可关联1~N个公司,切换公司视角时通过 ARRAY.any() 包含过滤,GIN 索引加速
模块 9:Dashboard 工作台
- 功能:首页 KPI 总览 + 快捷操作入口 + 公司切换
- 核心亮点:
- 四大 KPI 卡片:本月订单数 / 待出库发货 / 库存预警 SKU / 本月营收 — 后端
GET /api/dashboard/stats 聚合查询实时计算
- 快捷按钮一键跳转至订单、发货、库存、日志页面
- 顶部公司切换下拉 — 支持在不同公司视角间即时切换
四、AI 中枢模块
AI 模块 A:智能复盘报告(Dify Workflow + SSE)
- 架构:
前端 → 后端 SSE → Dify Workflow → Ollama 3090 (27B)
- 流程:
- 前端选择时间范围,后端查询
sales_logs 并序列化(按 involved_company_ids 过滤当前公司)
- 通过 httpx 异步调用 Dify Workflow API(streaming 模式)
- Workflow 内部:HTTP 获取日志 → LLM 分析生成 → HTTP 回调存档
- 后端 SSE 实时推送
text_chunk 到前端逐字渲染
- 生成完毕自动保存至
ai_report_drafts,支持历史加载和再编辑
- 关键配置:httpx 600s 超时 + nginx
proxy_buffering off + 600s 读超时
- 多租户感知(v0.2.0):
generate_report 端点注入 company_id 依赖,仅提取涉及当前公司的日志,防止跨公司分析幻觉
AI 模块 B:全局 AI 助手(浮球对话)
- 架构:
前端 FloatingChat → 后端 /api/chat → Dify Chat API
- 功能:全页面右下角悬浮球,随时与 AI 对话,支持上下文记忆
- 底层引擎:Dify Chat 应用,对接 Ollama
五、核心数据模型约束
所有核心表均遵守以下企业级约束:
| 约束 |
说明 |
| 主键策略 |
全局 UUID (uuid4),防爬虫遍历 |
| 软删除 |
所有表包含 is_deleted (Boolean),严禁物理 DELETE |
| 时间戳 |
created_at / updated_at,SQLAlchemy 监听器自动维护 |
| 数据隔离 |
业务查询均受 data_scope + owner_id + company_id 三重拦截 |
| 迁移管理 |
Alembic async 模式,所有 DDL 变更必须通过版本化迁移脚本 |
数据库全表清单(24 张)
| 域 |
表名 |
用途 |
隔离方式 |
| CRM |
crm_customers |
客户主表 |
全局共享 |
| CRM |
crm_contacts |
客户联系人 |
全局共享 |
| CRM |
crm_follow_up_logs |
跟进记录 |
全局共享 |
| ERP |
erp_product_categories |
产品分类树 |
全局共享 |
| ERP |
erp_product_skus |
产品 SKU |
全局共享 |
| ERP |
erp_sku_inventory |
库存快照(stock_qty + warning_threshold) |
company_id |
| ERP |
erp_inventory_flows |
库存变动流水 |
company_id |
| ERP |
erp_orders |
订单主表 |
company_id |
| ERP |
erp_order_items |
订单明细行 |
— (随主表) |
| ERP |
erp_shipping_records |
发货单主表 |
company_id |
| ERP |
erp_shipping_items |
发货明细行 |
— (随主表) |
| 财务 |
fin_invoice_pool |
报销发票池 |
company_id |
| 财务 |
fin_expense_records |
报销单主表 |
company_id |
| 财务 |
fin_expense_details |
报销明细行 |
— (随主表) |
| 财务 |
finance_sales_invoices |
销项发票 |
company_id |
| 协同 |
sales_logs |
销售日志 |
involved_company_ids (ARRAY) |
| AI |
ai_chat_sessions |
AI 对话记录 |
— |
| AI |
ai_report_drafts |
AI 复盘报告草稿 |
— |
| 系统 |
sys_users |
系统用户 |
— |
| 系统 |
sys_roles |
角色权限 |
— |
| 系统 |
sys_departments |
部门组织 |
— |
| 系统 |
sys_companies |
公司/租户主表 |
— |
| 系统 |
sys_user_companies |
用户-公司多对多 (含 is_default) |
— |
| 系统 |
alembic_version |
Alembic 迁移版本号 |
— |
Alembic 迁移清单
| 序号 |
Revision |
说明 |
| 1 |
03d8dcc2d72a |
v0.1.0 baseline(19 张表) |
| 2 |
a1b2c3d4e5f6 |
多租户隔离:新增 sys_companies / sys_user_companies,8 张表添加 company_id |
| 3 |
b2c3d4e5f6a7 |
新增新宇润滑油公司 + 全员关联 |
| 4 |
c3d4e5f6a7b8 |
sales_logs.company_id → involved_company_ids (ARRAY UUID) + GIN 索引 |
六、API 接口全景(17 个路由模块)
| 模块 |
前缀 |
核心端点示例 |
多租户 |
| auth |
/api/auth |
login, me, password, user-info (含公司列表) |
— |
| customers |
/api/customers |
CRUD + 归档 + AI 画像 + 转移 |
共享 |
| contacts |
/api/contacts |
客户联系人 CRUD |
共享 |
| companies |
/api/companies |
公司列表、用户关联公司查询 |
— |
| orders |
/api/orders |
CRUD + 动态定价 |
✅ |
| shipping |
/api/shipping |
发货 + 原子事务 |
✅ |
| products |
/api/products |
SKU + 分类树 + 库存变更 |
部分 |
| finance |
/api/finance |
票据池 + 报销 + 审批 |
✅ |
| sales_invoice |
/api/sales-invoices |
销项发票 CRUD |
✅ |
| sales_logs |
/api/sales-logs |
销售日志 CRUD + AI 审阅 (company_ids 数组) |
✅ ARRAY |
| reports |
/api/reports |
AI 复盘 SSE 生成 + 历史 (公司过滤) |
✅ |
| dashboard |
/api/dashboard |
KPI 聚合统计 |
✅ |
| chat |
/api/chat |
AI 浮球对话 |
— |
| dify_tools |
/api/dify-tools |
Dify 回调工具端点 |
— |
| import_export |
/api |
模板下载 + Excel 导入导出 |
— |
| sys_settings |
/api/settings |
用户/角色/部门管理 |
— |
| deps |
— |
鉴权依赖注入 + get_current_company_id |
— |
七、v0.1.0 → v0.2.0 变更日志
已完成增量(Phase 1.5 → 2.0)
| 项目 |
v0.1.0 状态 |
v0.2.0 状态 |
| Alembic 迁移 |
❌ 手工 DDL |
✅ 4 个版本化迁移脚本,async 模式 |
| 多租户 |
❌ 仅天津硕博霖 |
✅ 行级 company_id 隔离,IDOR 防护 |
| 公司切换 |
❌ |
✅ 登录页选择 + 首页下拉切换 |
| 新宇润滑油 |
❌ |
✅ 第二家公司,全员关联 |
| 客户转移 |
❌ |
✅ 管理员可跨人员重新分配 |
| sales_logs 多公司 |
无 company 概念 |
✅ involved_company_ids ARRAY + GIN 索引 |
| AI 复盘公司过滤 |
提取所有日志 |
✅ 仅提取涉及当前公司的日志 |
| 发票 OCR buyer 字段 |
❌ 映射缺失 |
✅ 修复 buyer/buyer_name/customer_name 链 |
| 发票批量交互 |
自动创建 + 5s 消失 |
✅ 待确认列表 + 字段标黄 + 一键创建 |
| 报销上传队列 |
3s 自动清空 |
✅ 手动关闭 |
| Dashboard 库存预警 |
erp_product_skus.warning_threshold |
✅ 修正为 erp_sku_inventory 表 |
| 数据库表数量 |
19 张 |
24 张(+5) |
| API 路由模块 |
16 个 |
17 个(+companies) |
Phase 3 规划
| 优先级 |
方向 |
说明 |
| P0 |
HTTPS |
内网 CA 自签证书,保护 JWT Token 传输安全 |
| P1 |
数据可视化 |
ECharts 接入 Dashboard — 月度趋势折线图、报销占比饼图 |
| P1 |
操作审计日志 |
记录关键操作(删除、审批、密码重置)的完整审计轨迹 |
| P1 |
文件存储优化 |
对接 MinIO / 阿里云 OSS,替代本地 uploads 目录 |
| P1 |
通知公告模块 |
实现系统内通知与公告发布功能 |
| P2 |
移动端适配 |
响应式布局或微信小程序,支持外出销售人员使用 |
| P2 |
外网访问 |
VPN / Cloudflare Tunnel 实现远程办公访问 |
| P2 |
监控告警 |
Prometheus + Grafana 仪表板 + 钉钉/微信告警推送 |
| P2 |
AI 复盘页修复 |
排查 SSE 流 / 前端组件加载问题 |
八、关键架构决策记录 (ADR)
| # |
决策 |
理由 |
| ADR-001 |
后端 Docker 使用 network_mode: host |
直连宿主机 PostgreSQL,免改 pg_hba.conf,简化内网部署 |
| ADR-002 |
前端 Docker 使用 bridge + extra_hosts |
通过 host.docker.internal 解析宿主机,隔离前端网络 |
| ADR-003 |
AI 引擎选择 Dify + Ollama 私有化 |
数据不出内网,满足工业企业信息安全合规要求 |
| ADR-004 |
复盘报告采用 SSE 而非 WebSocket |
单向推送场景 SSE 更轻量,nginx 配置更简单 |
| ADR-005 |
全表 UUID 主键 |
防止 ID 遍历攻击,适配分布式未来扩展 |
| ADR-006 |
库存变更仅允许流水模式 |
杜绝直接篡改库存,确保账实一致 + 审计可追溯 |
| ADR-007 |
行级多租户而非 Schema 隔离 |
公司数量有限(2~5 家),行级隔离实现简单,共享表无需冗余 |
| ADR-008 |
sales_logs 使用 ARRAY UUID 而非单 company_id |
CRM 日志需保持"以客户为中心"完整性,一篇日志可能涉及多个公司业务 |
| ADR-009 |
Alembic async 模式 + env.py 地址替换 |
Docker 内 .env 用 host.docker.internal,Alembic 在宿主机执行时自动替换为 127.0.0.1 |
| ADR-010 |
X-Company-Id Header + IDOR 校验 |
比 Cookie/Session 更适配 SPA 前后端分离,校验 sys_user_companies 防止伪造 |
本文档为 SHBL-ERP CRM 系统 Phase 2.0 阶段性存档,随系统迭代持续更新。