chore(config): 同步 src/ 路径迁移 + nginx SPA 路由 + 文档图简化

**src/ 路径迁移配套**:
- docker-compose.yml: backend context ./backend → ./src/backend
- docker-compose.yml: bind mount ./app → ./src/backend/app
- docker-compose.dev.yml: 3 个 bind mount 同步调整
- Dify 双路径超时从 12s 提到 20s(2026-07-20 用户反馈高峰期超时)

**nginx SPA 路由修复**(前端路由 /itagent/x → /itagent/index.html):
- nginx/nginx.conf: 加 try_files $uri /itagent/index.html

**生产环境 nginx 反代重写**:
- deploy-server/nginx.conf: 从 33 行 localhost 模板改为 357 行完整反代
  - 新增 /itdesk /itagent /itadmin /itportal /itterminal/itportal/meetingroom
    路由规则
  - 反代到 backend:8000 (API + WS)
  - / 根路径反代到数据查询平台

**架构图简化**(精简但保留关键类/时序):
- docs/class-diagram.mermaid: 215 行 → 59 行
- docs/sequence-diagram.mermaid: 115 行 → 35 行

合计 6 文件 + 470 行 / - 293 行
This commit is contained in:
Simon
2026-08-03 18:46:10 +08:00
parent 969f524962
commit 3a44141eac
6 changed files with 468 additions and 291 deletions
+34 -79
View File
@@ -1,81 +1,36 @@
sequenceDiagram
participant U as 坐席用户
participant UI as UserInfoBar.vue
participant CA as ChatArea.vue
participant Store as ConversationStore
participant API as message.ts API
participant BE as Backend API
participant DB as Database
autonumber
actor User as 员工
participant H5 as H5 ConversationStore
participant WS as FastAPI ws.py
participant DB as PostgreSQL/messages
participant WSM as ws_manager
participant Agent as 坐席 Store/MessageBubble
participant Task as h5_ai_task.py
participant Dify as Dify Workflow
participant REST as messages.py
Note over U,DB: ========== 阶段1:打开历史模式 ==========
U->>UI: 点击"历史会话"开关按钮
UI->>CA: $emit('toggle-history')
CA->>Store: enableHistoryMode()
Store->>Store: historyMode = true, historyLoading = true
Store->>API: getHistoryMessages(employeeId, {limit:50, current_conversation_id})
API->>BE: GET /api/employees/{employee_id}/history-messages?limit=50
BE->>DB: SELECT conversations WHERE employee_id=?
DB-->>BE: 会话ID列表 [conv1, conv2, conv3...]
BE->>DB: SELECT messages WHERE conversation_id IN (...) ORDER BY created_at DESC LIMIT 51
DB-->>BE: 消息列表 (50条 + 1条判断has_more)
BE->>DB: 对每个会话查首条employee消息, 取前20字
DB-->>BE: conversation_summaries {conv1:"摘要1", conv2:"摘要2"...}
BE-->>API: {items:[...], has_more:true, conversation_summaries:{...}}
API-->>Store: HistoryMessageListData
Store->>Store: historyMessages = items.reverse() (ASC排序)
Store->>Store: historyHasMore = has_more
Store->>Store: historyCursor = historyMessages[0].id
Store->>Store: historyConversationSummaries = conversation_summaries
Store->>Store: historyLoading = false
Store-->>CA: displayMessages 响应更新 (返回historyMessages)
CA->>CA: 渲染消息列表 + 插入ConversationSeparator
CA->>CA: 隐藏 ReplyBox + ReplySuggestArea (只读模式)
CA-->>U: 显示合并历史时间线
Note over U,DB: ========== 阶段2:向上滚动加载更多 ==========
U->>CA: 向上滚动到顶部
CA->>Store: loadMoreHistory()
Store->>Store: historyLoading = true
Store->>API: getHistoryMessages(employeeId, {limit:50, before:historyCursor})
API->>BE: GET /api/employees/{employee_id}/history-messages?limit=50&before={msgId}
BE->>DB: 获取before消息的created_at
BE->>DB: SELECT messages WHERE conv IN (...) AND created_at < before_time ORDER BY DESC LIMIT 51
DB-->>BE: 更旧的消息列表
BE->>DB: 对新涉及的会话查首条employee消息摘要
DB-->>BE: 补充 conversation_summaries
BE-->>API: {items:[...], has_more:false, conversation_summaries:{...}}
API-->>Store: HistoryMessageListData
Store->>Store: historyMessages = newItems.reverse() + historyMessages (前插)
Store->>Store: historyCursor = historyMessages[0].id (更新游标)
Store->>Store: historyHasMore = has_more
Store->>Store: merge conversation_summaries
Store->>Store: historyLoading = false
Store-->>CA: displayMessages 更新
CA-->>U: 显示更多历史消息 + 新分隔条
Note over U,DB: ========== 阶段3:关闭历史模式 ==========
U->>UI: 再次点击"历史会话"开关
UI->>CA: $emit('toggle-history')
CA->>Store: disableHistoryMode()
Store->>Store: historyMode = false
Store->>Store: 清空 historyMessages, historyCursor, historyConversationSummaries
Store-->>CA: displayMessages 返回 messages (正常数据源)
CA->>CA: 恢复 ReplyBox + ReplySuggestArea
CA-->>U: 显示当前会话正常消息
Note over U,DB: ========== 阶段4:切换会话自动重置 ==========
U->>CA: 点击左栏其他会话
CA->>Store: selectConversation(newConvId)
Store->>Store: resetHistoryState() — historyMode=false, 清空历史状态
Store->>Store: currentConversationId = newConvId
Store->>API: getMessages(newConvId, {limit:50})
API->>BE: GET /api/conversations/{newConvId}/messages?limit=50
BE-->>API: 正常消息列表
API-->>Store: MessageListData
Store->>Store: messages = data.items
Store-->>CA: displayMessages 返回 messages
CA-->>U: 显示新会话消息 (历史模式已关闭)
User->>H5: 点击选项
H5->>H5: 首次生成 client_msg_id(UUID)
H5->>WS: option_select(6字段)
WS->>DB: BEGIN + pg_advisory_xact_lock(key)
WS->>DB: 查询同会话同 client_msg_id
alt 5秒内重复
DB-->>WS: 返回首次 Message
WS-->>H5: 不重复落库/广播/Dify
else 首次受理
WS->>DB: INSERT Message(msg_type=option_select)
WS->>DB: COMMIT
WS->>WSM: broadcast new_message(masked message)
WSM-->>Agent: new_message
Agent->>Agent: 追加消息并按 question_id 计算最新
WS->>Task: create_task(feedback_context)
Task->>Dify: inputs{feedback_type, question_id, option_id...}
Dify-->>Task: 下一轮结构化回复
end
Agent-xWSM: 网络断开
Agent->>REST: GET /conversations/{id}/messages
REST->>DB: SELECT conversation_id ORDER BY created_at
DB-->>REST: 含 option_select 历史
REST-->>Agent: masked items
Agent->>Agent: 用 created_at + id 恢复最新高亮