Files
wecom_it_smart_desk/docs/02-技术文档/技术架构/技术方案-REQ-会话-002-会话存档-v1.0.md
T
Simon 44e77dcb0e chore(docs): docs/ 目录全面重新编号 + 重组
**重构前**(旧编号 02-11):
- docs/02-产品需求/      → 00 产品规划/PRD
- docs/03-技术架构/      → 01-05 子目录散落
- docs/04-原型设计/      → 01-02 产品设计(HTML 原型)
- docs/05-原型设计/      → screens/
- docs/06-测试素材/      → 02-E2E / 03-功能 / 04-版本测试
- docs/07-项目管理/      → 任务说明书/日报/计划
- docs/08-安全审计/      → 审计报告
- docs/09-堡垒运维/      → toolbox / deploy
- docs/10-项目管理/      → 任务说明书(重复)
- docs/11-历史归档/      → deploy-nas-archived

**重构后**(新编号 00-07,语义化):
- docs/00-产品开发流程与文档管理规范.md
- docs/00-版本迭代总览.md
- docs/01-产品文档/      (PRD/原型/认证/会话/AI 服务/坐席/集成)
- docs/02-技术文档/      (技术方案/架构图/重构记录/前端改造/实现配置)
- docs/03-测试文档/      (E2E/功能用例/版本报告/缺陷单)
- docs/04-运维文档/      (部署运维/运维指南)
- docs/05-运营文档/      (品牌推广/用户手册)
- docs/06-安全审计/      (审计报告)
- docs/07-项目管理/      (任务说明书/日报/计划/看板)

**净收益**:
- 目录编号与产品文档管理规范对齐(按文档阶段 01-07 编号)
- 消除 02-产品需求 与 10-项目管理 的编号重叠
- 子目录按文档类型分组(如 01-产品文档/00-产品规划、01-产品文档/01-认证与登录)
- 把运维/安全/项目管理从 0X 散落改为 04/06/07

合计 494 文件 + 78495 行 / - 14076 行
2026-08-03 18:46:55 +08:00

261 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 会话存档功能 - 技术方案
> **版本**: v1.0 | **日期**: 2026-07-15 | **状态**: 已完成
---
## 1. 架构设计
### 1.1 整体架构
```
┌─────────────────────────────────────────────────────────────┐
│ IT 智能服务台架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ H5 员工端 │ │ 坐席端 │ │ 管理后台 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ Nginx 入口 │ │
│ └───────┬───────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ FastAPI 后端 │ │
│ └───────┬───────┘ │
│ │ │
│ ┌────────────┼────────────┐ │
│ │ │ │ │
│ ┌──────▼──────┐ ┌──▼──┐ ┌──────▼──────┐ │
│ │ 会话管理 API │ │ Dify │ │ 企微 API │ │
│ └──────┬──────┘ └─────┘ └────────────┘ │
│ │ │
│ ┌──────▼──────────────────────────────────┐ │
│ │ PostgreSQL 数据库 │ │
│ │ ┌────────────┐ ┌──────────────────┐ │ │
│ │ │ conversations│ │ messages │ │ │
│ │ │ - is_archived│ │ │ │ │
│ │ │ - archived_at │ │ │ │ │
│ │ └────────────┘ └──────────────────┘ │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ┌──────▼──────────────────────────────────┐ │
│ │ 定时任务 (crontab) │ │
│ │ archive_sessions.py │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
---
## 2. 数据库设计
### 2.1 Conversation 表扩展
```python
# backend/app/models/conversation.py
# 是否已归档(会话结束超过90天后自动标记)
is_archived: Mapped[bool] = mapped_column(
Boolean,
nullable=False,
default=False,
comment="是否已归档",
)
# 归档时间
archived_at: Mapped[Optional[datetime]] = mapped_column(
DateTime(timezone=True),
nullable=True,
comment="归档时间",
)
```
### 2.2 索引设计
```python
__table_args__ = (
# ... 其他索引
Index("idx_conversations_is_archived", "is_archived"),
Index("idx_conversations_archived_at", "archived_at"),
)
```
### 2.3 索引说明
| 索引名 | 字段 | 用途 |
|--------|-----|------|
| idx_conversations_is_archived | is_archived | 按归档状态筛选 |
| idx_conversations_archived_at | archived_at | 按归档时间排序 |
---
## 3. API 设计
### 3.1 管理后台 API
#### 获取会话审计列表
```
GET /api/admin/audit/conversations
```
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| status | string | 否 | 状态筛选 |
| is_archived | bool | 否 | 归档状态筛选 |
| keyword | string | 否 | 关键词搜索 |
| date_from | string | 否 | 开始日期 |
| date_to | string | 否 | 结束日期 |
| page | int | 否 | 页码,默认1 |
| page_size | int | 否 | 每页条数,默认20 |
**响应示例**
```json
{
"code": 0,
"data": {
"items": [
{
"id": "conv-xxx",
"employee_name": "张三",
"status": "resolved",
"is_archived": true,
"archived_at": "2026-07-01T03:00:00Z",
"created_at": "2026-03-01T10:00:00Z",
"updated_at": "2026-03-15T15:30:00Z"
}
],
"total": 100,
"page": 1,
"page_size": 20
}
}
```
---
## 4. 定时归档脚本
### 4.1 脚本设计
**文件位置**`backend/scripts/archive_sessions.py`
**核心逻辑**
```python
# 归档阈值(天)
ARCHIVE_DAYS = 90
# 计算归档截止时间
cutoff_date = datetime.now(timezone.utc) - timedelta(days=ARCHIVE_DAYS)
# 查找需要归档的会话
stmt = select(Conversation).where(
Conversation.status == "resolved",
Conversation.is_archived == False,
Conversation.updated_at < cutoff_date
)
```
### 4.2 定时任务配置
```bash
# crontab 配置
# 每天凌晨3点执行
0 3 * * * cd /opt/wecom-it-desk/backend && python scripts/archive_sessions.py >> /var/log/itdesk-archive.log 2>&1
```
### 4.3 日志输出
```
[2026-07-15 03:00:00] 开始执行会话归档任务...
[2026-07-15 03:00:00] 归档阈值: 90 天
[2026-07-15 03:00:00] 找到 15 个需要归档的会话
[2026-07-15 03:00:01] 成功归档 15 个会话
[2026-07-15 03:00:01] 归档时间: 2026-07-15T03:00:01+00:00
```
---
## 5. 前端设计
### 5.1 坐席端 - 历史会话过滤
**文件**`frontend-agent/src/stores/conversation.ts`
```typescript
// 历史会话仅显示 90 天内的已结单会话
const HISTORY_DAYS = 90
const historyConversations = computed(() => {
const cutoffDate = new Date()
cutoffDate.setDate(cutoffDate.getDate() - HISTORY_DAYS)
const cutoffTime = cutoffDate.getTime()
return sortedConversations.value.filter(c => {
if (c.status !== 'resolved') return false
const createdTime = c.created_at ? new Date(c.created_at).getTime() : 0
return createdTime >= cutoffTime
})
})
```
### 5.2 管理后台 - 归档状态筛选
**文件**`frontend-admin/src/views/SessionAudit.vue`
```typescript
// 过滤条件
const filters = reactive({
keyword: '',
status: '',
is_archived: '', // 新增归档状态筛选
})
// 表格列
<el-table-column prop="is_archived" label="归档" width="80">
<template #default="{ row }">
<el-tag v-if="row.is_archived" type="info"></el-tag>
<span v-else></span>
</template>
</el-table-column>
```
---
## 6. 部署配置
### 6.1 数据库迁移
```bash
# 使用 Alembic 创建迁移
cd backend
alembic revision --autogenerate -m "add archive fields"
alembic upgrade head
```
### 6.2 定时任务部署
```bash
# 复制脚本到服务器
scp backend/scripts/archive_sessions.py sxn@10.212.189.210:/opt/wecom-it-desk/backend/scripts/
# 添加 crontab 任务
crontab -e
# 添加: 0 3 * * * cd /opt/wecom-it-desk/backend && python scripts/archive_sessions.py >> /var/log/itdesk-archive.log 2>&1
```
---
## 7. 版本历史
| 版本 | 日期 | 变更 |
|------|------|------|
| v1.0 | 2026-07-15 | 初始版本 |