678 lines
19 KiB
Markdown
678 lines
19 KiB
Markdown
|
|
# 保险智能客服系统 — 后续开发计划
|
|||
|
|
|
|||
|
|
> **文档版本**:V1.0
|
|||
|
|
> **更新日期**:2026-06-25
|
|||
|
|
> **当前状态**:后端框架完成,核心功能完成 64%,产品推荐功能待实现
|
|||
|
|
> **预计工期**:2-3 个工作日
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、当前项目状态
|
|||
|
|
|
|||
|
|
### 1.1 已完成功能(64%)
|
|||
|
|
|
|||
|
|
| 模块 | 功能 | 状态 | 备注 |
|
|||
|
|
|------|------|:----:|------|
|
|||
|
|
| **认证系统** | 企微 OAuth 登录 | ✅ | 需配置真实企微 |
|
|||
|
|
| | 账密登录 | ✅ | admin/admin123456 |
|
|||
|
|
| | Token 刷新 | ✅ | |
|
|||
|
|
| | 退出登录 | ✅ | |
|
|||
|
|
| **对话功能** | iframe 嵌入 BaoDan | ✅ | |
|
|||
|
|
| | 险种筛选 | ✅ | 7 种险种 |
|
|||
|
|
| | 会话管理 | ✅ | |
|
|||
|
|
| **用户管理** | 用户 CRUD | ✅ | |
|
|||
|
|
| | 角色权限 | ✅ | 5 种内置角色 |
|
|||
|
|
| | 权限校验中间件 | ✅ | |
|
|||
|
|
| **知识库** | 文档上传/列表/删除 | ✅ | 调用 BaoDan API |
|
|||
|
|
| | 文档状态查询 | ✅ | |
|
|||
|
|
| | 数据源 CRUD | ✅ | |
|
|||
|
|
| **统计报表** | 使用概览 | ✅ | 占位数据 |
|
|||
|
|
| | 趋势数据 | ✅ | 占位数据 |
|
|||
|
|
| | 知识库健康度 | ✅ | 占位数据 |
|
|||
|
|
| | Token 消耗 | ✅ | 占位数据 |
|
|||
|
|
| **系统管理** | 方案模板管理 | ✅ | |
|
|||
|
|
| | 通知告警配置 | ✅ | |
|
|||
|
|
| | 分组管理 | ✅ | |
|
|||
|
|
| | Prompt 管理 | ✅ | |
|
|||
|
|
| | 登录日志 | ✅ | |
|
|||
|
|
| | 对话记录 | ✅ | |
|
|||
|
|
| **导出功能** | PDF 导出 | ✅ | |
|
|||
|
|
| | Word 导出 | ✅ | |
|
|||
|
|
|
|||
|
|
### 1.2 未完成功能(36%)
|
|||
|
|
|
|||
|
|
| 模块 | 功能 | 优先级 | 工作量 |
|
|||
|
|
|------|------|:------:|:------:|
|
|||
|
|
| **产品推荐** | BaoDan Workflow 配置 | 🔴 高 | 0.5 天 |
|
|||
|
|
| | Workflow 调用封装 | 🔴 高 | 0.5 天 |
|
|||
|
|
| | 产品推荐 API 联调 | 🔴 高 | 0.5 天 |
|
|||
|
|
| **用户管理** | 批量导入用户 | 🟡 中 | 0.5 天 |
|
|||
|
|
| | 数据权限过滤 | 🟡 中 | 0.5 天 |
|
|||
|
|
| **知识库** | 文档编号自动生成 | 🟢 低 | 0.2 天 |
|
|||
|
|
| **企微集成** | XML 加解密 | 🟡 中 | 0.5 天 |
|
|||
|
|
| **测试** | 功能测试 | 🔴 高 | 1 天 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、后续开发计划
|
|||
|
|
|
|||
|
|
### Phase 2.5:BaoDan Workflow 配置(0.5 天)
|
|||
|
|
|
|||
|
|
**目标**:在 Dify 后台配置产品推荐 Workflow
|
|||
|
|
|
|||
|
|
#### 任务清单
|
|||
|
|
|
|||
|
|
| # | 任务 | 说明 | 验证标准 |
|
|||
|
|
|---|------|------|----------|
|
|||
|
|
| W.1 | 创建 Workflow 应用 | 在 Dify 后台创建新的 Workflow 应用 | 应用创建成功 |
|
|||
|
|
| W.2 | 配置节点1:参数校验 | Code Node,校验输入参数 | 传入合法参数通过 |
|
|||
|
|
| W.3 | 配置节点2:检索策略生成 | Code Node,根据险种生成检索策略 | 输出检索策略 JSON |
|
|||
|
|
| W.4 | 配置节点3:知识库检索 | Knowledge Retrieval Node | 返回相关文档 |
|
|||
|
|
| W.5 | 配置节点4:LLM 方案生成 | LLM Node,生成推荐方案 | 输出 Markdown 方案 |
|
|||
|
|
| W.6 | 配置节点5:异常处理 | Code Node,处理异常情况 | 异常时返回友好提示 |
|
|||
|
|
| W.7 | 配置节点6:格式化输出 | Code Node,格式化为 JSON | 输出结构化方案 |
|
|||
|
|
| W.8 | 配置条件分支 | 根据险种类型分支处理 | 分支逻辑正确 |
|
|||
|
|
| W.9 | 测试验证 | 端到端测试 | 输入客户信息 → 输出 3 套方案 |
|
|||
|
|
|
|||
|
|
#### Workflow 节点设计
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
开始
|
|||
|
|
↓
|
|||
|
|
[节点1] 参数校验 (Code Node)
|
|||
|
|
↓
|
|||
|
|
[节点2] 检索策略生成 (Code Node)
|
|||
|
|
↓
|
|||
|
|
[节点3] 知识库检索 (Knowledge Retrieval Node)
|
|||
|
|
↓
|
|||
|
|
[节点4] LLM 方案生成 (LLM Node)
|
|||
|
|
↓
|
|||
|
|
[节点5] 异常处理 (Code Node)
|
|||
|
|
↓
|
|||
|
|
[节点6] 格式化输出 (Code Node)
|
|||
|
|
↓
|
|||
|
|
结束
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 输入参数
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"customer_name": "张三",
|
|||
|
|
"customer_age": 30,
|
|||
|
|
"customer_gender": "male",
|
|||
|
|
"health_status": "健康",
|
|||
|
|
"occupation": "工程师",
|
|||
|
|
"annual_income": 300000,
|
|||
|
|
"monthly_budget": 5000,
|
|||
|
|
"insurance_types": ["重疾险", "医疗险"],
|
|||
|
|
"coverage_amount": 500000,
|
|||
|
|
"coverage_period": "至80岁",
|
|||
|
|
"existing_policies": []
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 输出格式
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"status": "done",
|
|||
|
|
"proposal": {
|
|||
|
|
"customer_name": "张三",
|
|||
|
|
"plans": [
|
|||
|
|
{
|
|||
|
|
"name": "基础方案",
|
|||
|
|
"total_premium": 12000,
|
|||
|
|
"items": [
|
|||
|
|
{
|
|||
|
|
"product_name": "XX重疾险",
|
|||
|
|
"coverage_amount": 300000,
|
|||
|
|
"annual_premium": 8000,
|
|||
|
|
"recommend_reason": "性价比高,保障全面"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"summary": "适合预算有限的客户"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "均衡方案",
|
|||
|
|
"total_premium": 18000,
|
|||
|
|
"items": [...],
|
|||
|
|
"summary": "保障与价格平衡"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "全面方案",
|
|||
|
|
"total_premium": 25000,
|
|||
|
|
"items": [...],
|
|||
|
|
"summary": "保障最全面"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"disclaimer": "以上方案仅供参考,具体以保险合同为准"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Phase 3.1:产品推荐后端 API(0.5 天)
|
|||
|
|
|
|||
|
|
**目标**:实现产品推荐相关的后端 API
|
|||
|
|
|
|||
|
|
#### 任务清单
|
|||
|
|
|
|||
|
|
| # | 任务 | API | 说明 |
|
|||
|
|
|---|------|-----|------|
|
|||
|
|
| 3.1.1 | 数据库扩展 | - | 添加 share_token 等字段 |
|
|||
|
|
| 3.1.2 | Workflow 调用封装 | - | 封装 Dify Workflow API |
|
|||
|
|
| 3.1.3 | 生成方案 API | POST /recommend/generate | 调用 Workflow |
|
|||
|
|
| 3.1.4 | 查询状态 API | GET /recommend/generate/{task_id} | 轮询任务状态 |
|
|||
|
|
| 3.1.5 | 导出方案 API | POST /recommend/{id}/export | PDF/Word 导出 |
|
|||
|
|
| 3.1.6 | 分享链接 API | POST /recommend/{id}/share | 生成分享链接 |
|
|||
|
|
|
|||
|
|
#### 3.1.1 数据库扩展
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 添加分享相关字段
|
|||
|
|
ALTER TABLE recommendation_records
|
|||
|
|
ADD COLUMN IF NOT EXISTS share_token VARCHAR(64),
|
|||
|
|
ADD COLUMN IF NOT EXISTS share_expire_at TIMESTAMP;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.2 Workflow 调用封装
|
|||
|
|
|
|||
|
|
**文件**:`api/insurance/recommend/workflow_helper.py`
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
"""BaoDan Workflow 调用封装。"""
|
|||
|
|
import requests
|
|||
|
|
from flask import current_app
|
|||
|
|
|
|||
|
|
|
|||
|
|
class WorkflowHelper:
|
|||
|
|
"""Workflow API 调用封装。"""
|
|||
|
|
|
|||
|
|
def run_workflow(self, inputs: dict, user_id: str) -> dict:
|
|||
|
|
"""
|
|||
|
|
执行 Workflow 获取推荐方案。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
inputs: 客户信息和保险需求
|
|||
|
|
user_id: 用户 ID
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
Workflow 执行结果
|
|||
|
|
"""
|
|||
|
|
base_url = current_app.config.get("BAODAN_API_URL", "http://localhost:5001")
|
|||
|
|
api_key = current_app.config.get("BAODAN_WORKFLOW_API_KEY", "")
|
|||
|
|
|
|||
|
|
resp = requests.post(
|
|||
|
|
f"{base_url}/v1/workflows/run",
|
|||
|
|
json={
|
|||
|
|
"inputs": inputs,
|
|||
|
|
"response_mode": "blocking",
|
|||
|
|
"user": f"recommend_{user_id}",
|
|||
|
|
},
|
|||
|
|
headers={"Authorization": f"Bearer {api_key}"},
|
|||
|
|
timeout=120,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return resp.json()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.3 生成方案 API
|
|||
|
|
|
|||
|
|
**文件**:`api/insurance/recommend/routes.py`
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@recommend_bp.route("/generate", methods=["POST"])
|
|||
|
|
@jwt_required
|
|||
|
|
def generate():
|
|||
|
|
"""生成推荐方案。"""
|
|||
|
|
data = request.get_json()
|
|||
|
|
if not data:
|
|||
|
|
return jsonify({"code": 1001, "message": "请求体不能为空", "data": None}), 400
|
|||
|
|
|
|||
|
|
user_id = request.user_id
|
|||
|
|
|
|||
|
|
# 参数校验(见需求文档 §13.3)
|
|||
|
|
errors = self._validate_params(data)
|
|||
|
|
if errors:
|
|||
|
|
return jsonify({"code": 1001, "message": "; ".join(errors), "data": None}), 400
|
|||
|
|
|
|||
|
|
# 创建推荐记录
|
|||
|
|
from insurance.recommend.service import RecommendService
|
|||
|
|
service = RecommendService()
|
|||
|
|
result = service.create_proposal(user_id, data)
|
|||
|
|
|
|||
|
|
if result["code"] != 0:
|
|||
|
|
return jsonify(result), 400
|
|||
|
|
|
|||
|
|
task_id = result["data"]["task_id"]
|
|||
|
|
|
|||
|
|
# 异步调用 Workflow
|
|||
|
|
import threading
|
|||
|
|
threading.Thread(
|
|||
|
|
target=self._run_workflow_async,
|
|||
|
|
args=(task_id, data, user_id),
|
|||
|
|
daemon=True,
|
|||
|
|
).start()
|
|||
|
|
|
|||
|
|
return jsonify({"code": 0, "data": {"task_id": task_id, "status": "processing"}})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.4 查询状态 API
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@recommend_bp.route("/generate/<task_id>", methods=["GET"])
|
|||
|
|
@jwt_required
|
|||
|
|
def get_status(task_id):
|
|||
|
|
"""查询推荐任务状态。"""
|
|||
|
|
from insurance.recommend.service import RecommendService
|
|||
|
|
service = RecommendService()
|
|||
|
|
result = service.get_proposal_status(task_id)
|
|||
|
|
return jsonify(result)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.5 导出方案 API
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@recommend_bp.route("/<proposal_id>/export", methods=["POST"])
|
|||
|
|
@jwt_required
|
|||
|
|
def export_proposal(proposal_id):
|
|||
|
|
"""导出推荐方案。"""
|
|||
|
|
data = request.get_json()
|
|||
|
|
format_type = data.get("format", "pdf") # pdf / docx
|
|||
|
|
|
|||
|
|
from insurance.recommend.service import RecommendService
|
|||
|
|
service = RecommendService()
|
|||
|
|
result = service.export_proposal(proposal_id, format_type)
|
|||
|
|
|
|||
|
|
if result["code"] != 0:
|
|||
|
|
return jsonify(result), 400
|
|||
|
|
|
|||
|
|
return jsonify(result)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.6 分享链接 API
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@recommend_bp.route("/<proposal_id>/share", methods=["POST"])
|
|||
|
|
@jwt_required
|
|||
|
|
def share_proposal(proposal_id):
|
|||
|
|
"""生成分享链接。"""
|
|||
|
|
from insurance.recommend.service import RecommendService
|
|||
|
|
service = RecommendService()
|
|||
|
|
result = service.create_share_link(proposal_id)
|
|||
|
|
return jsonify(result)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Phase 3.2:产品推荐前端联调(0.5 天)
|
|||
|
|
|
|||
|
|
**目标**:联调前端与后端 API
|
|||
|
|
|
|||
|
|
#### 已有前端文件
|
|||
|
|
|
|||
|
|
| 文件 | 说明 | 状态 |
|
|||
|
|
|------|------|:----:|
|
|||
|
|
| RecommendPage.vue | 推荐主页面 | ✅ 已存在 |
|
|||
|
|
| RecommendForm.vue | 客户信息表单 | ✅ 已存在 |
|
|||
|
|
| RecommendResult.vue | 方案展示组件 | ✅ 已存在 |
|
|||
|
|
| RecommendHistory.vue | 历史方案列表 | ✅ 已存在 |
|
|||
|
|
| RecommendDetail.vue | 方案详情页 | ✅ 已存在 |
|
|||
|
|
|
|||
|
|
#### 需要修改的文件
|
|||
|
|
|
|||
|
|
| 文件 | 修改内容 | 工作量 |
|
|||
|
|
|------|----------|:------:|
|
|||
|
|
| RecommendPage.vue | 联调 generate API | 0.2 天 |
|
|||
|
|
| RecommendResult.vue | 适配后端返回格式 | 0.2 天 |
|
|||
|
|
| RecommendHistory.vue | 联调 list API | 0.1 天 |
|
|||
|
|
| RecommendDetail.vue | 联调 export/share API | 0.1 天 |
|
|||
|
|
|
|||
|
|
#### RecommendPage.vue 联调逻辑
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
async function onSubmit(formData: RecommendRequest) {
|
|||
|
|
loading.value = true
|
|||
|
|
generating.value = true
|
|||
|
|
result.value = null
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
// 1. 提交生成请求
|
|||
|
|
const submitRes = await api.post('/recommend/generate', formData)
|
|||
|
|
const taskId = submitRes.data.task_id
|
|||
|
|
|
|||
|
|
// 2. 轮询状态
|
|||
|
|
let retries = 0
|
|||
|
|
const maxRetries = 60
|
|||
|
|
while (retries < maxRetries) {
|
|||
|
|
await new Promise(r => setTimeout(r, 2000))
|
|||
|
|
const pollRes = await api.get(`/recommend/generate/${taskId}`)
|
|||
|
|
const task = pollRes.data
|
|||
|
|
|
|||
|
|
if (task.status === 'done') {
|
|||
|
|
result.value = task
|
|||
|
|
ElMessage.success('方案生成成功')
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
if (task.status === 'failed') {
|
|||
|
|
ElMessage.error(task.error_message || '方案生成失败')
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
retries++
|
|||
|
|
}
|
|||
|
|
ElMessage.warning('生成超时,请稍后在历史方案中查看')
|
|||
|
|
} catch {
|
|||
|
|
// 错误已由 api 拦截器处理
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false
|
|||
|
|
generating.value = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Phase 5.1:批量导入用户(0.5 天)
|
|||
|
|
|
|||
|
|
**目标**:支持 Excel 批量导入用户
|
|||
|
|
|
|||
|
|
#### 任务清单
|
|||
|
|
|
|||
|
|
| # | 任务 | 说明 |
|
|||
|
|
|---|------|------|
|
|||
|
|
| 5.1.1 | 后端 API | POST /admin/users/batch-import |
|
|||
|
|
| 5.1.2 | Excel 解析 | 使用 openpyxl 解析 Excel |
|
|||
|
|
| 5.1.3 | 批量插入 | 批量插入用户记录 |
|
|||
|
|
| 5.1.4 | 前端上传 | UsersPage 添加导入按钮 |
|
|||
|
|
|
|||
|
|
#### 后端实现
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
@bp.route("/users/batch-import", methods=["POST"])
|
|||
|
|
@super_admin_required
|
|||
|
|
def batch_import_users():
|
|||
|
|
"""批量导入用户。"""
|
|||
|
|
file = request.files.get("file")
|
|||
|
|
if not file:
|
|||
|
|
return jsonify({"code": 1001, "message": "请选择文件", "data": None}), 400
|
|||
|
|
|
|||
|
|
# 解析 Excel
|
|||
|
|
import openpyxl
|
|||
|
|
wb = openpyxl.load_workbook(file)
|
|||
|
|
ws = wb.active
|
|||
|
|
|
|||
|
|
users = []
|
|||
|
|
for row in ws.iter_rows(min_row=2, values_only=True):
|
|||
|
|
username, department, role = row[0], row[1], row[2]
|
|||
|
|
if username:
|
|||
|
|
users.append({
|
|||
|
|
"username": username,
|
|||
|
|
"department": department or "",
|
|||
|
|
"role": role or "sales",
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
# 批量插入
|
|||
|
|
from insurance.admin.service import AdminService
|
|||
|
|
service = AdminService()
|
|||
|
|
result = service.batch_create_users(users)
|
|||
|
|
|
|||
|
|
return jsonify(result)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 前端实现
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<!-- UsersPage.vue -->
|
|||
|
|
<el-upload
|
|||
|
|
:action="'/insurance/admin/users/batch-import'"
|
|||
|
|
:headers="uploadHeaders"
|
|||
|
|
:on-success="onImportSuccess"
|
|||
|
|
:on-error="onImportError"
|
|||
|
|
accept=".xlsx,.xls"
|
|||
|
|
:show-file-list="false"
|
|||
|
|
>
|
|||
|
|
<el-button>批量导入</el-button>
|
|||
|
|
</el-upload>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Phase 5.2:数据权限过滤(0.5 天)
|
|||
|
|
|
|||
|
|
**目标**:实现销售只看自己的数据,主管看本组数据
|
|||
|
|
|
|||
|
|
#### 任务清单
|
|||
|
|
|
|||
|
|
| # | 任务 | 说明 |
|
|||
|
|
|---|------|------|
|
|||
|
|
| 5.2.1 | 数据权限中间件 | get_data_scope() 已实现 |
|
|||
|
|
| 5.2.2 | 推荐记录过滤 | 根据权限过滤推荐记录 |
|
|||
|
|
| 5.2.3 | 对话记录过滤 | 根据权限过滤对话记录 |
|
|||
|
|
|
|||
|
|
#### 实现逻辑
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
# 在查询接口中注入数据权限
|
|||
|
|
def get_proposals(user_id, params):
|
|||
|
|
"""获取推荐记录列表(带数据权限)。"""
|
|||
|
|
from insurance.middleware.auth_middleware import get_data_scope
|
|||
|
|
scope = get_data_scope()
|
|||
|
|
|
|||
|
|
query = db.session.query(RecommendationRecord)
|
|||
|
|
|
|||
|
|
if scope["scope"] == "self":
|
|||
|
|
# 销售:只看自己的
|
|||
|
|
query = query.filter(RecommendationRecord.user_id == user_id)
|
|||
|
|
elif scope["scope"] == "team":
|
|||
|
|
# 主管:看本部门的
|
|||
|
|
query = query.filter(
|
|||
|
|
RecommendationRecord.user_id.in_(
|
|||
|
|
db.session.query(WeComUserMapping.id).filter(
|
|||
|
|
WeComUserMapping.department == scope["department"]
|
|||
|
|
)
|
|||
|
|
)
|
|||
|
|
)
|
|||
|
|
# admin/super_admin:看全部
|
|||
|
|
|
|||
|
|
return query.all()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Phase 7.1:文档编号自动生成(0.2 天)
|
|||
|
|
|
|||
|
|
**目标**:文档上传时自动生成编号
|
|||
|
|
|
|||
|
|
#### 编号规则
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
格式:{险种代码}-{保司代码}-{序号}
|
|||
|
|
示例:CJ-XX-001(重疾险-XX人寿-第1个文档)
|
|||
|
|
|
|||
|
|
险种代码:
|
|||
|
|
- CJ = 重疾险
|
|||
|
|
- RS = 寿险
|
|||
|
|
- YL = 医疗险
|
|||
|
|
- YW = 意外险
|
|||
|
|
- CX = 车险
|
|||
|
|
- NJ = 年金险
|
|||
|
|
- CX = 储蓄险
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 实现
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
def generate_doc_number(insurance_type: str, company: str) -> str:
|
|||
|
|
"""生成文档编号。"""
|
|||
|
|
type_codes = {
|
|||
|
|
"重疾险": "CJ", "寿险": "RS", "医疗险": "YL",
|
|||
|
|
"意外险": "YW", "车险": "CX", "年金险": "NJ", "储蓄险": "CX",
|
|||
|
|
}
|
|||
|
|
type_code = type_codes.get(insurance_type, "XX")
|
|||
|
|
company_code = company[:2] if company else "XX"
|
|||
|
|
|
|||
|
|
# 查询当前序号
|
|||
|
|
count = db.session.query(DocumentMetadata).filter(
|
|||
|
|
DocumentMetadata.insurance_type == insurance_type,
|
|||
|
|
DocumentMetadata.company == company,
|
|||
|
|
).count()
|
|||
|
|
|
|||
|
|
return f"{type_code}-{company_code}-{count + 1:03d}"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Phase 8.1:功能测试(1 天)
|
|||
|
|
|
|||
|
|
**目标**:验证所有功能正常工作
|
|||
|
|
|
|||
|
|
#### 测试清单
|
|||
|
|
|
|||
|
|
| # | 测试项 | 测试用例 | 验证标准 |
|
|||
|
|
|---|--------|----------|----------|
|
|||
|
|
| X.1 | 登录 | 账密登录 | 返回 token,可访问受保护页面 |
|
|||
|
|
| X.2 | 登录 | 企微 OAuth | 重定向到企微授权页 |
|
|||
|
|
| X.3 | 对话 | 发送消息 | 返回 AI 回答 |
|
|||
|
|
| X.4 | 对话 | 险种筛选 | 切换险种后对话正常 |
|
|||
|
|
| X.5 | 推荐 | 生成方案 | 返回 3 套方案 |
|
|||
|
|
| X.6 | 推荐 | 导出 PDF | 下载 PDF 文件 |
|
|||
|
|
| X.7 | 用户 | 新增用户 | 用户列表增加 |
|
|||
|
|
| X.8 | 用户 | 角色权限 | 非管理员无法访问 /admin |
|
|||
|
|
| X.9 | 知识库 | 上传文档 | 文档出现在列表 |
|
|||
|
|
| X.10 | 统计 | 查看仪表盘 | 显示数据 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、开发时间表
|
|||
|
|
|
|||
|
|
### 第 1 天:产品推荐核心(1.5 天工作量)
|
|||
|
|
|
|||
|
|
| 时间 | 任务 | 产出 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 上午 | Phase 2.5: Workflow 配置 | Workflow 应用创建完成 |
|
|||
|
|
| 下午 | Phase 3.1: 后端 API | generate/status/export/share API |
|
|||
|
|
| 晚上 | Phase 3.2: 前端联调 | 推荐页面可正常使用 |
|
|||
|
|
|
|||
|
|
### 第 2 天:增强功能(1.5 天工作量)
|
|||
|
|
|
|||
|
|
| 时间 | 任务 | 产出 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 上午 | Phase 5.1: 批量导入 | Excel 导入功能 |
|
|||
|
|
| 下午 | Phase 5.2: 数据权限 | 销售/主管数据隔离 |
|
|||
|
|
| 晚上 | Phase 7.1: 文档编号 | 自动编号功能 |
|
|||
|
|
|
|||
|
|
### 第 3 天:测试 + 部署(1 天工作量)
|
|||
|
|
|
|||
|
|
| 时间 | 任务 | 产出 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 上午 | Phase 8.1: 功能测试 | 测试报告 |
|
|||
|
|
| 下午 | 部署 + 文档 | 生产环境部署 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、文件变更清单
|
|||
|
|
|
|||
|
|
### 后端文件
|
|||
|
|
|
|||
|
|
| 文件 | 操作 | 说明 |
|
|||
|
|
|------|:----:|------|
|
|||
|
|
| api/insurance/recommend/workflow_helper.py | 修改 | 封装 Workflow 调用 |
|
|||
|
|
| api/insurance/recommend/routes.py | 修改 | 完善 generate/status/export/share |
|
|||
|
|
| api/insurance/recommend/service.py | 修改 | 实现业务逻辑 |
|
|||
|
|
| api/insurance/admin/routes.py | 修改 | 添加 batch-import |
|
|||
|
|
| api/insurance/admin/service.py | 修改 | 实现批量导入 |
|
|||
|
|
| api/insurance/kb/service.py | 修改 | 添加编号生成 |
|
|||
|
|
|
|||
|
|
### 前端文件
|
|||
|
|
|
|||
|
|
| 文件 | 操作 | 说明 |
|
|||
|
|
|------|:----:|------|
|
|||
|
|
| frontend/src/pages/RecommendPage.vue | 修改 | 联调 generate API |
|
|||
|
|
| frontend/src/pages/RecommendResult.vue | 修改 | 适配返回格式 |
|
|||
|
|
| frontend/src/pages/RecommendHistory.vue | 修改 | 联调 list API |
|
|||
|
|
| frontend/src/pages/admin/UsersPage.vue | 修改 | 添加导入按钮 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、配置变更
|
|||
|
|
|
|||
|
|
### docker-compose.dify.yml
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# 更新 Workflow API Key(从 Dify 后台获取)
|
|||
|
|
BAODAN_WORKFLOW_API_KEY: "app-real-workflow-api-key"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 数据库变更
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 添加分享字段
|
|||
|
|
ALTER TABLE recommendation_records
|
|||
|
|
ADD COLUMN IF NOT EXISTS share_token VARCHAR(64),
|
|||
|
|
ADD COLUMN IF NOT EXISTS share_expire_at TIMESTAMP;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、验收标准
|
|||
|
|
|
|||
|
|
### 功能验收
|
|||
|
|
|
|||
|
|
| # | 功能 | 验收标准 |
|
|||
|
|
|---|------|----------|
|
|||
|
|
| 1 | 登录 | 账密/企微登录正常 |
|
|||
|
|
| 2 | 对话 | iframe 嵌入 BaoDan,可对话 |
|
|||
|
|
| 3 | 推荐 | 填写表单 → 生成 3 套方案 |
|
|||
|
|
| 4 | 导出 | 方案可导出 PDF/Word |
|
|||
|
|
| 5 | 用户管理 | CRUD + 角色权限正常 |
|
|||
|
|
| 6 | 知识库 | 文档上传/列表正常 |
|
|||
|
|
| 7 | 统计 | 仪表盘显示数据 |
|
|||
|
|
|
|||
|
|
### 性能验收
|
|||
|
|
|
|||
|
|
| # | 指标 | 标准 |
|
|||
|
|
|---|------|------|
|
|||
|
|
| 1 | 登录响应 | < 2 秒 |
|
|||
|
|
| 2 | 对话响应 | < 5 秒 |
|
|||
|
|
| 3 | 推荐生成 | < 30 秒 |
|
|||
|
|
| 4 | 页面加载 | < 3 秒 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、风险与应对
|
|||
|
|
|
|||
|
|
| 风险 | 影响 | 应对措施 |
|
|||
|
|
|------|------|----------|
|
|||
|
|
| Workflow 配置复杂 | 推荐功能无法使用 | 参考 Dify 官方文档,逐步配置 |
|
|||
|
|
| Workflow 输出格式不稳定 | 方案解析失败 | 在 workflow_helper.py 中加容错解析 |
|
|||
|
|
| 企微 XML 加解密 | 消息回调不通 | 参考企微官方 Python SDK |
|
|||
|
|
| 测试时间不足 | 部署后出现问题 | 优先测试核心功能 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 八、总结
|
|||
|
|
|
|||
|
|
### 工作量估算
|
|||
|
|
|
|||
|
|
| 任务 | 工作量 | 优先级 |
|
|||
|
|
|------|:------:|:------:|
|
|||
|
|
| Workflow 配置 | 0.5 天 | 🔴 高 |
|
|||
|
|
| 产品推荐 API | 0.5 天 | 🔴 高 |
|
|||
|
|
| 前端联调 | 0.5 天 | 🔴 高 |
|
|||
|
|
| 批量导入 | 0.5 天 | 🟡 中 |
|
|||
|
|
| 数据权限 | 0.5 天 | 🟡 中 |
|
|||
|
|
| 文档编号 | 0.2 天 | 🟢 低 |
|
|||
|
|
| 功能测试 | 1 天 | 🔴 高 |
|
|||
|
|
| **总计** | **3.2 天** | |
|
|||
|
|
|
|||
|
|
### 交付物
|
|||
|
|
|
|||
|
|
1. 完整的产品推荐功能(Workflow + API + 前端)
|
|||
|
|
2. 批量导入用户功能
|
|||
|
|
3. 数据权限过滤
|
|||
|
|
4. 文档编号自动生成
|
|||
|
|
5. 功能测试报告
|
|||
|
|
6. 部署文档
|