Files
iqudo-top1/docs/technical-implementation.md
2026-08-06 21:48:42 +08:00

15 KiB
Raw Blame History

销冠平台技术实现方案

1. 文档范围

本文档用于指导“场景化销售话术与 SOP 平台”的第一阶段实现。

第一阶段的核心闭环是:

创建场景 -> 配置自定义字段 -> 编排 SOP -> 审核发布 -> 一线人员执行 -> 记录反馈

场景不写死在代码中。宠物医生问诊问药只是一个配置示例,后续可以创建保险咨询、房地产销售、教育课程顾问等其他场景。

本阶段暂不实现文件存储、AI 自动生成、CRM 集成和微服务拆分。

2. 技术选型

2.1 后端

  • Go业务服务和流程执行引擎
  • GinHTTP 路由、中间件和请求处理
  • Zap结构化日志
  • cleanenvYAML 配置解析和环境变量覆盖
  • GORMMySQL 数据访问
  • golang-migrate数据库迁移
  • go-playground/validator:请求参数校验
  • JWT + Refresh Token登录认证

第一阶段采用模块化单体。所有业务模块运行在一个 Go 服务中,通过清晰的内部边界保持可维护性,后续再根据实际负载拆分服务。

配置加载使用 github.com/ilyakaznacheev/cleanenv。它的行为简单明确:先读取 YAML 文件,再读取环境变量,环境变量值覆盖文件中的同名配置。

2.2 前端

  • Vue 3
  • Vite
  • TypeScript
  • Ant Design Vue
  • Vue Router
  • Pinia
  • Axios

SOP 编辑器第一版使用步骤卡片和条件配置,不立即引入复杂的画布编辑器。需要图形化节点编排时,使用 Vue 生态的流程图组件,不使用 React Flow。

2.3 数据库和运行环境

  • MySQL 8.0+
  • Docker Compose本地开发
  • Nginx生产环境反向代理
  • Linux 容器部署

本阶段不引入 Redis。登录会话、场景配置和执行状态先使用 MySQL只有出现异步任务、缓存或高并发需求时再增加 Redis。

3. 配置管理

配置结构统一放在 internal/config/,业务代码不能直接读取环境变量。

配置优先级如下:

结构体默认值 < config.yml < 当前环境配置文件 < 环境变量

配置文件约定如下:

configs/config.example.yml       # 配置模板,可提交,不包含敏感信息
configs/config.yml               # 基础配置
configs/config.test.yml          # 测试环境覆盖配置
configs/config.prod.yml          # 生产环境覆盖配置

运行环境通过 APP_ENV 或启动参数 --env 选择,优先级为启动参数高于环境变量:

未指定环境       -> config.yml
APP_ENV=test     -> config.yml + config.test.yml
APP_ENV=prod     -> config.yml + config.prod.yml

config.yml 作为基础文件必须存在。testprod 环境对应的覆盖文件也必须存在;缺失时服务直接退出。环境配置文件只填写与基础配置不同的字段,未填写的字段沿用 config.yml

配置文件路径通过 --config-dir 指定,默认使用当前工作目录下的 configs/。部署时可以挂载外部配置目录,不需要把真实生产配置提交到代码仓库。

环境变量名称通过结构体标签显式声明,例如:

APP_SERVER_HOST
APP_SERVER_PORT
APP_DATABASE_HOST
APP_DATABASE_PORT
APP_DATABASE_USER
APP_DATABASE_PASSWORD
APP_DATABASE_NAME

配置字段约定:

  • yamlYAML 文件中的字段名。
  • env:环境变量名称,必须显式声明。
  • env-default:没有文件值和环境变量时使用的默认值。
  • env-required:"true":必须由环境变量提供的敏感或关键配置。
  • env-prefix:为嵌套配置统一增加环境变量前缀。
  • env-layout:日期、时间等特殊类型的解析格式。

生产环境中数据库密码、JWT 密钥等敏感字段必须使用 env-required:"true",不写入 YAML 文件。配置加载失败或必填项缺失时,服务直接退出,不使用不完整配置继续启动。

加载过程必须保持以下顺序:先加载基础配置,再加载当前环境配置,最后执行环境变量覆盖。环境变量不能被后续 YAML 文件覆盖。

4. 目录规划

代码统一放在 codes/ 目录下。按照 golang-standards/project-layout 的组织方式,同时遵循“根目录放置 main.go”和“前端放在 web 目录”的项目约束。

codes/
├── main.go                 # Go 服务入口,位于代码根目录
├── go.mod
├── go.sum
├── internal/
│   ├── config/              # 配置加载
│   ├── logger/              # Zap 初始化和日志字段规范
│   ├── middleware/          # 认证、租户、请求日志、异常恢复
│   ├── router/              # 路由注册
│   ├── handler/             # HTTP 接口层
│   ├── service/             # 业务服务层
│   ├── repository/          # 数据访问层
│   ├── model/               # 数据库模型和请求响应模型
│   ├── engine/              # SOP 流程执行引擎
│   └── webassets/            # 前端嵌入和静态资源处理
├── pkg/
│   └── response/            # 可被外部复用的通用响应结构
├── configs/
│   ├── config.yml
│   ├── config.test.yml
│   ├── config.prod.yml
│   └── config.example.yml
├── migrations/              # MySQL 数据库迁移文件
├── scripts/                 # 构建、检查和发布脚本
└── web/
    ├── package.json
    ├── vite.config.ts
    ├── index.html
    ├── src/
    │   ├── api/
    │   ├── components/
    │   ├── layouts/
    │   ├── router/
    │   ├── stores/
    │   ├── types/
    │   └── views/
    └── dist/                # 前端构建产物,由 Go 使用 go:embed 嵌入

说明:cmd/ 目录不使用Go 入口固定为 codes/main.gocodes/web/dist/ 是构建产物目录,前端构建完成后由 Go 服务作为静态资源提供。

浏览器
  ├── 管理端场景、字段、SOP、知识卡、审核
  └── 执行端:按 SOP 执行和记录客户回答
          |
          v
      Go HTTP 服务
  ├── 身份认证与租户权限
  ├── 场景配置服务
  ├── SOP 版本服务
  ├── 流程执行引擎
  ├── 知识卡服务
  └── 执行记录与统计
          |
          v
        MySQL

5. 系统架构

Go 服务同时承担 API 服务和前端静态资源服务。前端构建后通过 go:embed 打入 Go 二进制,生产环境只需要部署一个服务包和配置文件。

6. go:embed 方案

前端构建输出到 codes/web/dist/Go 服务通过 go:embed 嵌入该目录。

构建流程为:

进入 codes/web -> 安装依赖 -> 执行前端构建 -> 生成 web/dist
        -> 回到 codes -> 执行 Go 构建 -> 生成包含前端资源的二进制

服务端静态资源处理规则:

  • /api/ 路径只进入 Go API 路由。
  • 静态文件路径优先读取 web/dist 中对应文件。
  • 非 API 且找不到文件的路径回退到 index.html,支持 Vue Router 的 history 模式。
  • 前端资源由 Nginx 或应用服务设置长期缓存,index.html 不使用长期缓存。

前端 dist 不存在时Go 项目不能完成编译,因此代码仓库需要保留一个可构建的前端产物占位文件,或者在 CI 中强制先执行前端构建。

7. 场景模型

场景是平台的一级可配置对象,不能在代码中写死行业字段。

一个场景至少包含:

  • 场景名称
  • 所属行业
  • 适用角色
  • 使用目标
  • 触发条件
  • 可见范围
  • 自定义字段
  • 一个或多个 SOP
  • 关联知识卡
  • 发布状态

例如宠物医生问诊问药场景可以配置:

pet_type              宠物种类
pet_age               年龄
pet_weight            体重
symptom               症状
symptom_duration      症状持续时间
has_emergency_sign    是否存在急症

保险咨询场景则可以配置客户年龄、职业、预算和保险类型。新增场景只需要增加配置数据,不需要修改业务代码。

8. SOP 模型

SOP 由版本、节点和连线组成。

第一阶段支持以下节点类型:

  • start:流程开始
  • message:展示标准话术
  • question:提问并写入一个场景字段
  • form:一次收集多个字段
  • choice:让执行人员选择客户回答
  • condition:根据已收集字段进行分支
  • knowledge:展示已审核知识卡
  • escalate:转人工、转医生或线下处理
  • finish:结束流程

条件必须保存为结构化规则,不能让用户输入或执行任意 JavaScript。条件规则支持等于、不等于、包含、大于、小于、全部满足、任一满足等操作。

发布前需要校验:

  • 只有一个开始节点
  • 所有节点都可从开始节点访问
  • 所有分支都有出口
  • 不存在无法结束的路径
  • 必填字段存在对应采集节点
  • 关联知识卡已经审核
  • 急症或高风险分支有明确的转人工或转诊动作

9. MySQL 数据表

核心表如下:

users                   用户
tenants                 企业或组织
tenant_members          企业成员和角色
roles                   角色权限

scenarios               场景
scenario_fields         场景自定义字段

sops                    SOP 基础信息
sop_versions            SOP 版本
sop_nodes               SOP 节点
sop_edges               SOP 连线和条件

knowledge_cards         话术或知识卡
knowledge_card_versions 知识卡版本

sop_runs                SOP 执行实例
sop_run_events          SOP 节点执行事件
sop_feedback            执行反馈
audit_logs              操作审计

关键设计:

  • 所有租户相关数据必须能追溯到 tenant_id
  • 场景字段使用行记录保存,避免把场景字段写死在表结构中。
  • 节点配置和条件规则使用 MySQL JSON 字段保存。
  • 已发布版本不可直接修改,修改时复制为新的草稿版本。
  • 版本状态流转为 draft -> reviewing -> published -> offline;管理员也可以从草稿直接发布。
  • 执行过程保存事件记录,便于复盘和统计。
  • 需要参与筛选和统计的字段不能只存 JSON应在事件表或统计表中建立结构化字段。

10. 后端接口规划

场景接口

POST   /api/v1/scenarios
GET    /api/v1/scenarios
GET    /api/v1/scenarios/:id
PUT    /api/v1/scenarios/:id
DELETE /api/v1/scenarios/:id

自定义字段接口

POST   /api/v1/scenarios/:id/fields
PUT    /api/v1/scenario-fields/:id
DELETE /api/v1/scenario-fields/:id

SOP 接口

POST   /api/v1/scenarios/:id/sops
GET    /api/v1/scenarios/:id/sops
PUT    /api/v1/sops/:id/draft
POST   /api/v1/sops/:id/validate
POST   /api/v1/sops/:id/submit-review
POST   /api/v1/sops/:id/publish
POST   /api/v1/sops/:id/offline

SOP 执行接口

POST   /api/v1/runs
GET    /api/v1/runs/:id
POST   /api/v1/runs/:id/answer
POST   /api/v1/runs/:id/finish
POST   /api/v1/runs/:id/feedback

11. 流程执行引擎

执行流程如下:

  1. 创建执行实例,绑定一个已发布的 SOP 版本。
  2. 加载开始节点并返回给前端。
  3. 前端展示话术、表单或选项。
  4. 后端校验客户回答和字段类型。
  5. 在事务中保存回答和节点事件。
  6. 根据结构化条件计算下一节点。
  7. 返回下一节点或结束动作。

流程引擎只处理通用节点和规则,不理解“宠物”“保险”等具体业务。行业知识放在场景字段、话术内容和知识卡中。

12. Zap 日志规范

使用 Zap 输出结构化 JSON 日志到 stdout由 Docker、Kubernetes 或云平台采集,不由应用自己维护日志文件。

日志至少包含:

  • service
  • env
  • request_id
  • tenant_id
  • user_id
  • action
  • resource
  • resource_id
  • duration_ms
  • err

日志等级约定:

  • DEBUG:本地开发细节
  • INFO:正常请求、发布、执行等业务事件
  • WARN:参数异常、权限拒绝、客户端错误
  • ERROR:服务异常、数据库失败、流程执行失败

禁止记录密码、Token、完整客户聊天内容和未脱敏的个人信息。

Gin 请求日志中需要记录请求方法、路径、状态码、耗时和 Request ID。业务日志使用结构化字段不使用字符串拼接。

13. 前端页面规划

管理端

  • 场景列表
  • 创建/编辑场景
  • 自定义字段配置
  • SOP 列表
  • SOP 步骤编辑器
  • 节点条件配置
  • 知识卡管理
  • 审核发布中心
  • 执行数据看板

执行端

  • 场景选择
  • SOP 当前节点
  • 客户信息录入
  • 标准话术展示
  • 分支选择
  • 转人工或转诊提醒
  • 执行结果和反馈

Ant Design Vue 主要使用 FormTableDrawerModalStepsTreeTabsDescriptions。动态字段表单由场景字段配置生成,字段校验规则也由配置生成。

14. 安全与权限

  • 用户登录后从 Token 中获取 tenant_id,不能信任前端传入的租户 ID。
  • 所有查询必须自动附加租户条件。
  • 场景、SOP、知识卡、执行记录都需要做资源级权限判断。
  • 发布、下线、审核和修改权限分离。
  • 已发布 SOP 版本只读,修改时复制为新的草稿版本。
  • 记录关键操作到 audit_logs
  • 条件规则禁止执行任意代码。

15. 第一阶段开发顺序

第 1 阶段:基础服务

  • Go 服务初始化
  • Zap 日志
  • 配置加载
  • MySQL 连接
  • 登录和租户权限
  • 前端构建和 go:embed

第 2 阶段:场景配置

  • 场景 CRUD
  • 自定义字段 CRUD
  • 场景权限
  • 场景状态管理

第 3 阶段SOP 编排

  • 节点管理
  • 连线和条件配置
  • 草稿保存
  • 流程校验
  • 版本复制

第 4 阶段SOP 执行

  • 创建执行实例
  • 节点展示
  • 回答提交
  • 条件跳转
  • 执行事件记录

第 5 阶段:审核和反馈

  • 提交审核
  • 审核发布
  • 下线和回滚
  • 执行反馈
  • 基础数据统计

16. 构建和部署约定

首次初始化本地 MySQL 数据库时执行:

cd codes
mysql -uroot -p < scripts/create-databases.sql

服务启动时会自动执行 migrations/ 中的迁移,创建业务表并记录 schema_migrations 版本。

本地开发时前后端可以分别启动:

前端开发服务codes/web
Go API 服务codes

生产构建时先构建前端,再构建 Go 服务。最终产物只需要:

  • Go 二进制
  • 配置文件
  • MySQL 数据库

前端静态资源已经通过 go:embed 编译进入 Go 二进制,不需要单独部署前端静态目录。

17. 暂不实现的内容

  • 文件上传和对象存储
  • AI 自动提炼话术
  • AI 客户模拟陪练
  • CRM、企业微信和客服系统集成
  • 多服务拆分
  • Redis 缓存
  • 消息队列
  • 复杂 BI 分析

这些内容等核心闭环验证成功后再加入,避免第一版架构过度复杂。