chore: docs 结构整改 + compose 双目录对齐(合并重建提交)
本提交为 .git 对象库损坏后的重建提交,内容等价于原先三个本地提交 (5e2fd4c2 / 57a53c98 / 5d7e1873)的累积结果,未做任何额外改动。 一、docs 结构整改(整改 #14) 根因:重构时新结构为 untracked 文件,执行 git stash(未带 -u)未纳入, 随后 git reset 拉回 HEAD 旧 tracked 树,导致旧树复活、新旧两棵目录 树并存于 docs/,共 791 文件、双分类体系冲突。 修复动作: - b2 同名异主题文件改名迁移保全 9 个 - C 类 39 个孤立文件按主题正确归类 - A/B1 类 222 个重复文件删除(新结构已有内容副本) - 9 个旧独有空目录删除 - 270 处内部引用按 verified 映射改写 - 整改记录 #14 登记于 04-运维文档/部署运维 结果:docs 791 → 569 文件,顶层仅规范 8 类 + 治理文件,单树恢复。 残留:约 20 处指向从未存在文件的陈旧死链,归入独立文档卫生任务。 二、compose 双目录对齐(消除踩坑 A) - docker-compose.yml:nginx 前端挂载全部由根目录 frontend-*/dist 改为 src/frontend-*/dist(h5 / agent / admin / terminal) - docker-compose.dev.yml:dev 服务 build context 与卷同步改 src/ - 效果:本地 docker compose up 不再把根目录 stale dist 挂回, 与线上一致,分叉隐患消除(已 docker compose config 校验通过) 防复发铁律: - 重构须提交;仓库修复须 git stash -u 或先 commit - 新结构须 git add 并提交,避免再次 untracked 复活 - H5 改动只动 src/frontend-h5/,禁改根目录遗留 frontend-*/
This commit is contained in:
@@ -0,0 +1,446 @@
|
||||
# 技术方案 - 快速回复规则后台管理
|
||||
|
||||
> **关联PRD**: `01-产品文档/00-产品规划/PRD-REQ-通用-002-快速回复规则后台管理-v1.2.md`
|
||||
> **版本**: v1.2
|
||||
> **日期**: 2026-07-27(初版) / 2026-07-28(v1.2 调整)
|
||||
> **作者**: Simon
|
||||
|
||||
---
|
||||
|
||||
## 1. 技术架构设计
|
||||
|
||||
### 1.1 整体架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ITAgent 管理后台 │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ /quick-rules /quick-rules/greeting │ │
|
||||
│ │ /quick-rules/contacts /quick-rules/routing │ │
|
||||
│ │ /quick-rules/targets │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└────────────────────────┬────────────────────────────────────┘
|
||||
│ HTTP API
|
||||
┌────────────────────────┴────────────────────────────────────┐
|
||||
│ FastAPI 后端 │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ QuickRuleService (规则加载 + 缓存) │ │
|
||||
│ │ - get_greeting_keywords() │ │
|
||||
│ │ - get_contact_keywords() │ │
|
||||
│ │ - get_routing_keywords() │ │
|
||||
│ │ - get_routing_targets() │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ QuickRuleCRUD API │ │
|
||||
│ │ - /api/admin/quick-rules (CRUD) │ │
|
||||
│ │ - /api/admin/quick-rules/refresh (热刷新) │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└────────────────────────┬────────────────────────────────────┘
|
||||
│
|
||||
┌────────────────────────┴────────────────────────────────────┐
|
||||
│ PostgreSQL 数据库 │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ quick_rules 表 │ │
|
||||
│ │ - id / rule_type / category / keyword / ... │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 1.2 模块设计
|
||||
|
||||
| 模块 | 职责 | 文件位置 |
|
||||
|------|------|---------|
|
||||
| `QuickRule` | 数据库模型 | `app/models/quick_rule.py` |
|
||||
| `quick_rules_api` | 管理API | `app/api/admin/quick_rules.py` |
|
||||
| `QuickRuleService` | 规则加载服务 | `app/services/quick_rule_service.py` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 数据库设计
|
||||
|
||||
### 2.1 quick_rules 表
|
||||
|
||||
```sql
|
||||
CREATE TABLE quick_rules (
|
||||
id SERIAL PRIMARY KEY,
|
||||
rule_type VARCHAR(50) NOT NULL,
|
||||
-- 枚举: greeting, routing_prefilter, routing_target
|
||||
category VARCHAR(50),
|
||||
-- 业务分类: IT服务, 行政, 人力资源, 财务, 法务, 行政-物业
|
||||
keyword TEXT NOT NULL,
|
||||
-- 关键词内容 或 名称
|
||||
priority INTEGER DEFAULT 0,
|
||||
-- 优先级,匹配时按优先级排序
|
||||
response_template TEXT,
|
||||
-- 回复模板(可选)
|
||||
extra_data JSONB,
|
||||
-- 扩展字段(用于kfid等配置)
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
-- 是否启用
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT uk_rule_type_keyword UNIQUE (rule_type, keyword)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_quick_rules_type_active ON quick_rules(rule_type, is_active);
|
||||
CREATE INDEX idx_quick_rules_category ON quick_rules(category);
|
||||
```
|
||||
|
||||
### 2.2 初始数据
|
||||
|
||||
```sql
|
||||
-- 打招呼关键词(从 ai_handler.py 迁移)
|
||||
INSERT INTO quick_rules (rule_type, keyword, priority, is_active) VALUES
|
||||
('greeting', '你好', 10, true),
|
||||
('greeting', '您好', 9, true),
|
||||
('greeting', 'hi', 8, true),
|
||||
('greeting', 'hello', 7, true),
|
||||
('greeting', '在吗', 6, true),
|
||||
('greeting', '在么', 5, true);
|
||||
|
||||
-- 路由预过滤关键词(从 routing_service.py 迁移)
|
||||
INSERT INTO quick_rules (rule_type, category, keyword, priority, is_active) VALUES
|
||||
('routing_prefilter', 'IT服务', '打印机', 10, true),
|
||||
('routing_prefilter', 'IT服务', '打印', 9, true),
|
||||
('routing_prefilter', 'IT服务', '电脑', 8, true),
|
||||
('routing_prefilter', '行政', '复印机', 7, true),
|
||||
('routing_prefilter', '人力资源', '考勤', 8, true),
|
||||
('routing_prefilter', '人力资源', '入职', 7, true),
|
||||
('routing_prefilter', '财务', '报销', 10, true),
|
||||
('routing_prefilter', '财务', '发票', 9, true),
|
||||
('routing_prefilter', '法务', '合同', 10, true);
|
||||
|
||||
-- 路由目标配置
|
||||
INSERT INTO quick_rules (rule_type, category, keyword, extra_data, is_active) VALUES
|
||||
('routing_target', '行政', '机票酒店前台', '{"service_name": "机票酒店前台", "description": "受理机票、酒店、快递、访客等", "url": "https://work.weixin.qq.com/nl/innerkfid/ikfCtcYBwAAV00zNJGfmuA0aG1c2qCDnQ"}', true),
|
||||
('routing_target', '人力资源', '人力资源共享服务咨询', '{"service_name": "人力资源共享服务咨询", "description": "工牌/考勤/入离职/社保", "url": "https://work.weixin.qq.com/nl/innerkfid/ikfCtcYBwAAvSRL5i5b_Xia8vCmFc2gRw"}', true);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. API 设计
|
||||
|
||||
### 3.1 管理接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/admin/quick-rules` | GET | 列表查询(支持 rule_type、category、keyword 筛选) |
|
||||
| `/api/admin/quick-rules` | POST | 创建规则 |
|
||||
| `/api/admin/quick-rules/{id}` | PUT | 更新规则 |
|
||||
| `/api/admin/quick-rules/{id}` | DELETE | 删除规则 |
|
||||
| `/api/admin/quick-rules/batch` | POST | 批量导入 |
|
||||
| `/api/admin/quick-rules/refresh` | POST | 热刷新缓存 |
|
||||
| `/api/admin/quick-rules/stats` | GET | 统计各类型规则数量 |
|
||||
|
||||
### 3.2 请求/响应示例
|
||||
|
||||
**GET /api/admin/quick-rules?rule_type=greeting&page=1&size=20**
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 6,
|
||||
"page": 1,
|
||||
"size": 20,
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"rule_type": "greeting",
|
||||
"keyword": "你好",
|
||||
"priority": 10,
|
||||
"is_active": true,
|
||||
"created_at": "2026-07-27T10:00:00Z",
|
||||
"updated_at": "2026-07-27T10:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**POST /api/admin/quick-rules**
|
||||
|
||||
```json
|
||||
{
|
||||
"rule_type": "routing_prefilter",
|
||||
"category": "IT服务",
|
||||
"keyword": "投影仪",
|
||||
"priority": 5,
|
||||
"is_active": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 服务设计
|
||||
|
||||
### 4.1 QuickRuleService
|
||||
|
||||
```python
|
||||
class QuickRuleService:
|
||||
"""规则加载服务 - 单例模式"""
|
||||
|
||||
_cache: dict = {}
|
||||
|
||||
@classmethod
|
||||
async def load_all(cls) -> None:
|
||||
"""启动时加载所有规则到缓存"""
|
||||
rules = await db.query(QuickRule).where(QuickRule.is_active == True).all()
|
||||
cls._cache = {
|
||||
'greeting': [r.keyword for r in rules if r.rule_type == 'greeting'],
|
||||
'contact': [r.keyword for r in rules if r.rule_type == 'contact'],
|
||||
'routing_prefilter': {r.keyword: r.category for r in rules if r.rule_type == 'routing_prefilter'},
|
||||
'routing_target': {r.category: r.extra_data for r in rules if r.rule_type == 'routing_target'},
|
||||
}
|
||||
|
||||
@classmethod
|
||||
async def refresh(cls) -> None:
|
||||
"""热刷新缓存"""
|
||||
await cls.load_all()
|
||||
|
||||
@classmethod
|
||||
def get_greeting_keywords(cls) -> list[str]:
|
||||
"""获取打招呼关键词列表"""
|
||||
return cls._cache.get('greeting', [])
|
||||
|
||||
@classmethod
|
||||
def get_contact_keywords(cls) -> list[str]:
|
||||
"""获取联系人关键词列表"""
|
||||
return cls._cache.get('contact', [])
|
||||
|
||||
@classmethod
|
||||
def get_routing_keywords(cls) -> dict[str, str]:
|
||||
"""获取路由预过滤关键词 {keyword: category}"""
|
||||
return cls._cache.get('routing_prefilter', {})
|
||||
|
||||
@classmethod
|
||||
def get_routing_targets(cls) -> dict[str, dict]:
|
||||
"""获取路由目标 {category: {service_name, description, url}}"""
|
||||
return cls._cache.get('routing_target', {})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 代码改造计划
|
||||
|
||||
### 5.1 新增文件
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `app/models/quick_rule.py` | QuickRule SQLAlchemy 模型 |
|
||||
| `app/api/admin/quick_rules.py` | CRUD API |
|
||||
| `app/services/quick_rule_service.py` | 规则加载服务 |
|
||||
| `migrations/versions/xxx_quick_rules.py` | Alembic 迁移脚本 |
|
||||
|
||||
### 5.2 改造文件
|
||||
|
||||
| 文件 | 改造内容 |
|
||||
|------|---------|
|
||||
| `app/services/ai_handler.py` | 从 QuickRuleService 加载打招呼关键词 |
|
||||
| `app/api/contacts.py` | 从 QuickRuleService 加载联系人配置 |
|
||||
| `app/services/routing_service.py` | 从 QuickRuleService 加载路由配置 |
|
||||
|
||||
### 5.3 改造示例
|
||||
|
||||
**改造前 (ai_handler.py)**:
|
||||
```python
|
||||
_GREETING_KEYWORDS = ["你好", "您好", "hi", "hello", "在吗", "在么"]
|
||||
|
||||
def check_greeting(text: str) -> bool:
|
||||
return any(kw in text for kw in _GREETING_KEYWORDS)
|
||||
```
|
||||
|
||||
**改造后 (ai_handler.py)**:
|
||||
```python
|
||||
from app.services.quick_rule_service import QuickRuleService
|
||||
|
||||
def check_greeting(text: str) -> bool:
|
||||
keywords = QuickRuleService.get_greeting_keywords()
|
||||
return any(kw in text for kw in keywords)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 前端实现
|
||||
|
||||
### 6.1 路由配置
|
||||
|
||||
```typescript
|
||||
// router/index.ts
|
||||
{
|
||||
path: '/quick-rules',
|
||||
component: Layout,
|
||||
children: [
|
||||
{ path: '', component: () => import('@/views/quick-rules/index.vue') },
|
||||
{ path: 'greeting', component: () => import('@/views/quick-rules/greeting.vue') },
|
||||
{ path: 'contacts', component: () => import('@/views/quick-rules/contacts.vue') },
|
||||
{ path: 'routing', component: () => import('@/views/quick-rules/routing.vue') },
|
||||
{ path: 'targets', component: () => import('@/views/quick-rules/targets.vue') },
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 页面结构
|
||||
|
||||
| 页面 | 组件 |
|
||||
|------|------|
|
||||
| `quick-rules/index.vue` | 规则管理主页(标签导航 + count 徽标 + 筛选区 + 规则表格) |
|
||||
| `quick-rules/greeting.vue` | 打招呼关键词管理 |
|
||||
| `quick-rules/contacts.vue` | 业务联系人管理 |
|
||||
| `quick-rules/routing.vue` | 路由关键词管理 |
|
||||
| `quick-rules/targets.vue` | 路由目标配置 |
|
||||
|
||||
### 6.3 v1.2 UI 调整
|
||||
|
||||
移除 `src/frontend-admin/src/views/quick-rules/index.vue` 顶部 `.stats-row` 三张统计卡片;标签导航 `.tab-bar` 保留 `count` 徽标,作为规则数量的唯一页面展示来源。卡片原有点击行为仅调用 `switchTab`,标签导航已完整承担相同切换能力,因此删除不影响路由切换、筛选、批量删除、编辑、启停、分页和搜索。后端 `getQuickRuleStats` 接口保留;`quick-rules/audit.vue` 的 4 张审计统计卡片不在本次调整范围。
|
||||
|
||||
---
|
||||
|
||||
## 7. 部署与运维
|
||||
|
||||
### 7.1 部署顺序
|
||||
|
||||
1. 执行数据库迁移脚本(创建 quick_rules 表 + 初始数据)
|
||||
2. 部署后端代码
|
||||
3. 部署前端代码
|
||||
4. 验证功能
|
||||
|
||||
### 7.2 监控指标
|
||||
|
||||
| 指标 | 说明 |
|
||||
|------|------|
|
||||
| `quick_rules_query_duration` | 规则查询耗时 |
|
||||
| `quick_rules_cache_hit_rate` | 缓存命中率 |
|
||||
| `quick_rules_api_requests` | 管理API请求数 |
|
||||
|
||||
### 7.3 回滚方案
|
||||
|
||||
- 数据库:保留迁移脚本,可降级表
|
||||
- 代码:旧页面保留,新页面上线后观察一周再下线旧页面
|
||||
|
||||
---
|
||||
|
||||
## 8. 验收检查点
|
||||
|
||||
| 检查点 | 验证方式 |
|
||||
|--------|---------|
|
||||
| 数据库迁移成功 | 确认 quick_rules 表存在且数据正确 |
|
||||
| API 可用 | curl 测试 CRUD 接口 |
|
||||
| 规则加载正确 | 调用服务方法验证返回值 |
|
||||
| 前端页面可访问 | 浏览器访问 /quick-rules |
|
||||
| 现有功能无影响 | 发送消息验证打招呼/路由仍正常工作 |
|
||||
| 热刷新生效 | 修改规则后无需重启即可生效 |
|
||||
|
||||
---
|
||||
|
||||
## 9. v2.0 增量设计 — 智能体自动优化 + 导入导出
|
||||
|
||||
### 9.1 新增 API 端点
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/admin/quick-rules/import` | POST | 批量导入(JSON/Excel) |
|
||||
| `/api/admin/quick-rules/export` | GET | 批量导出(JSON/Excel) |
|
||||
| `/api/admin/quick-rules/batch-delete` | POST | 批量删除(按ID列表) |
|
||||
| `/api/admin/quick-rules/agent-update` | POST | 智能体专用更新(带置信度) |
|
||||
| `/api/admin/quick-rules/audit-log` | GET | 规则修改审计日志 |
|
||||
| `/api/admin/quick-rules/stats` | GET | 规则统计(命中率、误判率) |
|
||||
|
||||
### 9.2 智能体专用更新请求
|
||||
|
||||
```json
|
||||
POST /api/admin/quick-rules/agent-update
|
||||
|
||||
{
|
||||
"rule_type": "routing_prefilter",
|
||||
"category": "IT服务",
|
||||
"keyword": "投影仪",
|
||||
"priority": 5,
|
||||
"confidence": 0.92,
|
||||
"reason": "误判率分析:最近30天5条'投影仪'相关消息被误判为闲聊",
|
||||
"agent_id": "rule_optimizer_v1",
|
||||
"execution_id": "exec_2026-07-27_001"
|
||||
}
|
||||
```
|
||||
|
||||
**置信度阈值**:
|
||||
- ≥ 0.85:自动应用并记录审计
|
||||
- 0.5 ~ 0.85:进入待审核队列
|
||||
- < 0.5:拒绝(不入库)
|
||||
|
||||
### 9.3 批量导入导出
|
||||
|
||||
**导入格式(JSON)**:
|
||||
```json
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"rule_type": "greeting",
|
||||
"keyword": "你好",
|
||||
"priority": 10,
|
||||
"is_active": true
|
||||
}
|
||||
],
|
||||
"mode": "skip_duplicates" // skip_duplicates | overwrite | fail
|
||||
}
|
||||
```
|
||||
|
||||
**导出格式**:支持 JSON 和 Excel 两种格式
|
||||
|
||||
### 9.4 审计日志表
|
||||
|
||||
```sql
|
||||
CREATE TABLE quick_rule_audit_log (
|
||||
id SERIAL PRIMARY KEY,
|
||||
rule_id INTEGER,
|
||||
rule_type VARCHAR(50),
|
||||
action VARCHAR(20), -- create/update/delete/batch
|
||||
actor_type VARCHAR(20), -- human/agent
|
||||
actor_id VARCHAR(100), -- agent_id 或 坐席ID
|
||||
old_value JSONB,
|
||||
new_value JSONB,
|
||||
confidence FLOAT,
|
||||
reason TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
### 9.5 规则统计
|
||||
|
||||
```python
|
||||
GET /api/admin/quick-rules/stats
|
||||
|
||||
{
|
||||
"total_rules": 45,
|
||||
"hit_rate": 0.78,
|
||||
"false_positive_rate": 0.05,
|
||||
"active_rules": 42,
|
||||
"by_type": {
|
||||
"greeting": 6,
|
||||
"routing_prefilter": 25,
|
||||
"routing_target": 14
|
||||
},
|
||||
"top_unkonwn_keywords": ["云盘权限", "VPN", "VPN登录"]
|
||||
}
|
||||
```
|
||||
|
||||
### 9.6 实施步骤
|
||||
|
||||
| 步骤 | 内容 | 预估时间 |
|
||||
|------|------|---------|
|
||||
| 1 | 批量导入/导出 API | 1h |
|
||||
| 2 | 批量删除 API | 0.5h |
|
||||
| 3 | 智能体专用 API(带置信度) | 1.5h |
|
||||
| 4 | 审计日志表 + 记录逻辑 | 1.5h |
|
||||
| 5 | 规则统计 API | 1h |
|
||||
| 6 | 前端导入/导出按钮 | 1h |
|
||||
| 7 | 智能体调用脚本示例 | 0.5h |
|
||||
| **总计** | | **7h** |
|
||||
|
||||
---
|
||||
|
||||
## 10. 变更记录
|
||||
|
||||
| 日期 | 版本 | 变更内容 | 变更人 | 变更原因 | 影响范围 |
|
||||
|------|------|---------|-------|----------|----------|
|
||||
| 2026-07-27 | v1.0 | 初始版本 | Simon | 快速回复规则后台管理技术设计建立 | 后端、数据库及管理后台 |
|
||||
| 2026-07-27 | v1.1 | 新增第9章 v2.0 增量设计(智能体自动优化 + 导入导出) | Simon | 补充智能体扩展设计 | API、审计及导入导出 |
|
||||
| 2026-07-28 | v1.2 | 移除 `index.vue` 顶部 `.stats-row` 三张重复统计卡片,保留 `.tab-bar` 的 count 徽标;统计接口与审计页卡片保持不变 | Simon | 页面信息冗余 | 管理后台 `/quick-rules` 页面 |
|
||||
Reference in New Issue
Block a user