# 2026-06-13 工作记录 ## H5端邀请功能后续开发 ### 后端改动 1. **h5.py** — 新增3个H5专用参与者端点(带员工认证): - `POST /h5/conversations/{id}/join` — 被邀请人加入会话(`_get_current_employee` 认证) - `POST /h5/conversations/{id}/leave-participant` — 参与者退出会话(`_get_current_employee` 认证) - `GET /h5/conversations/{id}/participants` — 获取参与者列表(`_get_current_employee` 认证) - 安全校验:employee_id 从 Token 自动获取,无需前端传递,防止冒充 ### H5前端改动 2. **api/conversation.ts** — API路径统一为 `/h5/` 前缀: - `joinConversation(conversationId)` — 移除 employeeId 参数,路径改为 `/h5/conversations/{id}/join` - `leaveAsParticipant(conversationId)` — 移除 employeeId 参数,路径改为 `/h5/conversations/{id}/leave-participant` - `getParticipants(conversationId)` — 路径改为 `/h5/conversations/{id}/participants`(独立端点) - `ConversationInfo` 类型新增 `employee_name` 字段 3. **stores/conversation.ts** — `leaveAsParticipant()` 不再传递 employeeId 4. **views/ChatView.vue** — `joinConversationApi(inviteId)` 不再传递 eid 5. **components/chat/ParticipantList.vue** — 修复发起人姓名显示: - 当发起人不是当前用户时,显示 `conv.employee_name`(真实姓名)而非固定的"员工" ### 编译验证 - 后端 py_compile ✅(h5.py) - H5前端 vue-tsc --noEmit ✅ - H5前端 vite build ✅ ## 管理后台 — 角色管理界面开发 ### 说明 后端 RBAC 角色系统(模型/API/服务/Schema/迁移)已全部完成,但前端管理后台零实现。 本次补齐前端角色管理 UI 层。 ### 改动文件 1. **frontend-admin/src/types/index.ts** — 新增角色管理类型定义: - `Role`(角色信息,含 permissions JSON 数组、user_count) - `UserRole`(用户角色关联,含 source/assigned_by/expires_at) - `UserRoleSource`(来源类型:auto/tag/ehr/manual) - `RoleMappingRule`(映射规则,含 source_type/source_value/priority) - `MappingSourceSource`(映射来源:wecom_tag/ehr_position) - `RoleAssignRequest` / `RoleRevokeRequest` / `RoleMappingRuleRequest` - `ROLE_SOURCE_LABELS` / `MAPPING_SOURCE_LABELS` 常量 2. **frontend-admin/src/api/admin.ts** — 新增 6 个 API 调用函数: - `getRoles()` — 获取所有角色列表 - `assignRole()` — 手动分配角色 - `revokeRole()` — 撤销角色 - `getRoleMappingRules()` — 获取映射规则 - `createRoleMappingRule()` — 创建映射规则 - `deleteRoleMappingRule()` — 删除映射规则 3. **frontend-admin/src/views/Roles.vue** — 新建角色管理页面: - 角色卡片网格(3 个预置角色:用户/坐席/管理员,含用户数+权限数+权限标签) - 用户角色分配表格(employee_id/角色/来源/分配者/时间/操作) - 自动映射规则表格(目标角色/来源类型/匹配值/优先级/状态/操作) - 4 个对话框:分配角色、撤销确认、新建映射规则 - Demo fallback 数据(API 不可用时的降级展示) 4. **frontend-admin/src/router/index.ts** — 新增路由: - `/roles` → `Roles.vue`,meta.title = "角色管理" 5. **frontend-admin/src/components/Sidebar.vue** — 新增菜单项: - "运营管理" 分组下添加"角色管理"(Key 图标),位于"坐席管理"之后 ### 编译验证 - 前端 vite build ✅(Roles-4zcp3cuz.js 13.33 kB,gzip: 4.48 kB) - 仅 @vueuse/core Rollup 注解警告和 chunk 大小警告(非本次引入) ## 正式服务器部署 ### 迁移修复 - **007_role_system.py** — 修复 PostgreSQL 兼容性:`datetime('now')` → `NOW()` - SQLite 的 `datetime('now')` 在 PostgreSQL 中不存在,导致后端启动失败 ### 部署记录 - 部署包已生成:`deploy-server/it-smart-desk-server-deploy.zip` (1.48 MB) - 包含:3个前端 dist + 后端代码 + docker-compose.yml + .env + nginx.conf - ⚠️ **服务器文件上传限制**:10.90.5.110 无法使用 scp,只能通过堡垒机手动上传 - 部署流程:下载部署包 → 通过堡垒机上传到 /tmp/ → 解压 → docker compose build --no-cache backend → up -d --- ## 未完成任务收尾(下午) ### 任务进度确认 - 代码审查确认 #148/#155(H5端邀请功能)**已完整实现**,包括: - ParticipantList.vue 完整组件(展示+退出+确认弹窗) - conversation.ts store(inviteParticipant/leaveAsParticipant/joinConversation) - API层(joinConversation/leaveAsParticipant/getParticipants) - ChatView.vue 邀请链接加入流程 - WebSocket 实时推送(participant_invited/joined/removed/left 事件) - 标记 #148、#155 为 completed ### #151 H5登录Bug修复(4项) 1. **isAuthenticated 增加 JWT 过期检查**:新增 `isTokenExpired()` 函数,解析 JWT payload 的 exp 字段,60秒安全余量 2. **消除循环依赖**:新建 `utils/authCallback.ts` 独立回调注册中心,打破 api/index.ts ↔ stores/employee.ts 循环依赖 3. **并发401去重**:`_authExpiredPromise` 去重锁,首个401获取锁执行处理,后续复用同一Promise 4. **Portal Token URL安全加固**:使用 URLSearchParams 精确删除 token/code/state 参数,history.replaceState 立即清除 ### #156 术语替换 + UI风格更新 **术语替换**: - "举手"→"招手"(agent 6文件+h5 4文件,约25处) - "铃铛"→"传菜铃"(H5端2文件6处) - "申请"→无需替换(均为业务数据内容) **CSS变量体系更新为企微风格**: - `--accent`: #3b82f6 → #07C160(企微绿) - `--bg-primary`: #f5f7fa → #f7f7f7 - `--bg-tertiary`: #f0f2f5 → #ededed - `--text-primary`: #1e293b → #191919 - `--text-secondary`: #64748b → #666666 - `--text-tertiary`: #94a3b8 → #999999 - `--border`: #e2e8f0 → #e5e5e5 - `--radius`: 6px → 8px, `--radius-lg`: 10px → 12px - H5 `--color-shake-start/end`: 橙色渐变 → 绿色渐变 - 深色主题变量保持不变 ### #149 端到端验证 - 阻塞已解除(#148/#151已完成) - 待用户在实际环境中执行全链路验证 ### 部署方案讨论 - 确认 NAS 测试环境在企微 OAuth2 认证下价值大幅降低 - 确定双企微应用方案(正式应用+测试应用),因公司子域名申请困难 - 正式上线前:正式=10.90.5.10, 测试=NAS - 正式上线后:正式=高可用架构, 测试=10.90.5.10 --- ## 部署包打包 + 调试验证指南(11:00) ### 部署包清单 | 文件 | 大小 | 内容 | |------|------|------| | deploy-h5.tar | 0.6 MB | frontend-h5/dist/(含JWT过期检查+企微绿风格) | | deploy-agent.tar | 2.0 MB | frontend-agent/dist/(含术语替换+企微绿风格) | | deploy-admin.tar | 1.7 MB | frontend-admin/dist/ | | deploy-portal.tar | 1.53 MB | frontend-portal/dist/ | | deploy-backend.tar | 11.02 MB | backend/ | ### 调试验证指南 - 创建 `docs/调试验证指南_2026-06-13.md` - 包含端到端验证清单(11个验证项) - 包含测试企微应用创建步骤(6个步骤) - 包含环境切换方案和常见问题排查 --- ## 管理后台 P2 功能开发(晚间) ### 任务1:仪表盘真实数据 - **admin_service.py** — `get_dashboard_overview()` 新增两项真实计算: - `avg_response_time`:从 messages 表计算首条员工消息到首条坐席/AI回复的时间差,最多统计50个会话 - `ai_hit_rate`:今日有 AI 实质性回复的会话占比(ai_substantive_reply_count > 0) - 异常处理:计算失败时降级为 "—" 显示 ### 任务2:P2 页面(会话审计/坐席绩效/系统日志) **后端新增 3 组 API:** - `GET /admin/audit/conversations` — 会话审计列表(分页+状态/坐席/关键词/日期范围筛选) - `GET /admin/audit/conversations/{id}` — 会话审计详情(含消息列表,最多200条) - `GET /admin/agent-performance` — 坐席绩效统计(总会话数/已结单/结单率/今日会话) - `GET /admin/system-logs` — 系统日志(配置变更历史,含操作人姓名) **前端新增 3 个页面:** - `SessionAudit.vue` — 会话审计页(表格+筛选+详情抽屉,消息按类型着色) - `AgentPerformance.vue` — 坐席绩效页(表格+汇总统计,支持日期范围筛选) - `SystemLogs.vue` — 系统日志页(表格+分页,变更前后值着色对比) **路由+侧边栏更新:** - 路由新增 `/session-audit`、`/agent-performance`、`/system-logs` - 侧边栏"监控与数据"分组新增 3 个菜单项 ### 任务3:功能开关增强 - `CONFIG_GROUP_MAP` 新增 5 个分组前缀: - `queue_` → 排队策略 - `satisfaction_` → 满意度评价 - `invite_` → 邀请功能 - `notification_` → 通知推送 - `security_` → 安全策略 ### 编译验证 - 后端 py_compile ✅ - 前端 vite build ✅(SessionAudit-D3UWZck-.js 6.40 kB) --- ## 统一部署包打包(10:58) ### 构建结果 - 4 个前端全部重建成功(H5/Agent/Admin/Portal),耗时 18 秒 - Admin 前端包含新增的 Roles.vue 角色管理页面 ### 部署包清单 | 文件 | 大小 | 内容 | |------|------|------| | deploy-h5.tar | 0.6 MB | frontend-h5/dist/ | | deploy-agent.tar | 2.0 MB | frontend-agent/dist/ | | deploy-admin.tar | 1.7 MB | frontend-admin/dist/(含角色管理页) | | deploy-portal.tar | 1.5 MB | frontend-portal/dist/ | | deploy-backend.tar | 11.0 MB | backend/(含角色系统全部代码+迁移) | ### 服务器部署步骤 ```bash # 1. 清理失败的数据库状态 docker compose exec postgres psql -U postgres -d it_smart_desk -c " DROP TABLE IF EXISTS role_mapping_rules CASCADE; DROP TABLE IF EXISTS user_roles CASCADE; DROP TABLE IF EXISTS roles CASCADE; " # 2. 通过堡垒机上传 5 个 tar 到 /tmp/ # 3. 在服务器执行 cd /opt/wecom-it-desk cp /tmp/deploy-*.tar ./ docker compose down # 解压前端 tar -xf deploy-h5.tar -C frontend-h5/ tar -xf deploy-agent.tar -C frontend-agent/ tar -xf deploy-admin.tar -C frontend-admin/ tar -xf deploy-portal.tar -C frontend-portal/ # 解压后端(保留 .env) cp backend/.env /tmp/backend-env-backup tar -xf deploy-backend.tar cp /tmp/backend-env-backup backend/.env # 重建并启动 docker compose build --no-cache backend docker compose up -d ``` --- ## Dify/RAGFlow/千问集成调研(12:39) ### 现有服务连通性确认(从 10.90.5.110 测试) | 服务 | 地址 | 端口 | 状态 | |------|------|------|------| | RAGFlow 前端 | 10.80.0.85 | 8080 | ✅ 200 OK | | RAGFlow API | 10.80.0.85 | 9380 | ✅ 200 OK(Werkzeug) | | 千问模型 | 10.80.0.49 | 5000 | ✅ 已连接 | | Dify | yw-dify.dc.servyou-it.com (10.80.0.240) | 80 | ✅ 307 正常 | **结论:所有服务均已连通,无需开通新路由。** ### 集成现状 | 组件 | 后端代码 | 需要做什么 | |------|----------|-----------| | Dify | ✅ AIService + WingmanService | 无需改动 | | RAGFlow | ❌ 无客户端代码 | 需开发 RagflowClient | | 千问 | ℹ️ 通过Dify间接调用 | 无需直连 | ### 交接文档关键信息 - 消息链路:企微 → B端智能体 → dify2openai → Dify Workflow → 千问 - RAGFlow 知识运营:宋献IT组主导 - 模型:Qwen3-30B-A3B-Instruct + bge-m3(向量) - 对接联系人:dify2openai→JG/CF;Dify应急→CF/WT --- ## RAGFlow 客户端开发(12:49) ### 新增文件 - `backend/app/integrations/ragflow/__init__.py` — 模块导出 - `backend/app/integrations/ragflow/client.py` — RagflowClient 客户端 - `test_connection()` — 测试连接 - `retrieval()` — 知识检索(核心接口,POST /api/v1/retrieval) - `list_datasets()` — 列出知识库 - `create_dataset()` — 创建知识库 - `delete_dataset()` — 删除知识库 - `list_documents()` — 列出文档 - `upload_document()` — 上传文档 - `delete_documents()` — 删除文档 - `backend/app/integrations/ragflow/models.py` — 数据模型 - RetrievalChunk / DocAggregate / RetrievalResult / DatasetInfo / DocumentInfo - `backend/app/integrations/ragflow/exceptions.py` — 异常定义 - RagflowError / RagflowConfigError / RagflowAuthError / RagflowApiError / RagflowConnectionError - `backend/app/integrations/ragflow/config.py` — 配置加载器 - 从 system_configs 表读取 integration_ragflow_api_url + integration_ragflow_api_key - 默认 API 地址:http://10.80.0.85:9380 ### admin.py 新增端点 - `POST /admin/integrations/ragflow/test` — 测试连接 - `GET /admin/integrations/ragflow/datasets` — 列出知识库 - `POST /admin/integrations/ragflow/retrieval` — 知识检索测试 ### 编译验证 - 后端 py_compile ✅(所有 ragflow 模块 + admin.py) ### 前端更新 - `frontend-admin/src/api/admin.ts` — 新增 3 个 RAGFlow API 函数: - `testRagflowConnection()` — 测试连接 - `getRagflowDatasets()` — 列出知识库 - `ragflowRetrieval()` — 知识检索测试 - `frontend-admin/src/views/Integrations.vue` — 更新 handleTest 函数: - 支持 RAGFlow 测试连接(调用 testRagflowConnection) - 测试成功后更新本地状态为 connected - 前端 vite build ✅(Integrations-CFvIx0q8.js 14.51 kB) --- ## 修复:消息发送失败 + 截图不可用(15:00) ### 根因 后端 `POST /h5/conversations/current/messages` 抛出异常: ``` TypeError: AIHandler.__init__() missing 1 required positional argument: 'ai_service' ``` **深层原因**:uvicorn `--reload` 模式下 WatchFiles reloader 缓存了旧的 `dependencies.py` 字节码(之前 `dep_ai_handler()` 没有 `ai_service=AIService()` 参数的版本)。即使清空 `__pycache__` 重启,reloader 仍加载旧缓存。 **修复**:去掉 `--reload` 标志启动后端即可。`start_backend.py` 已改为 `reload=False`。 ### 影响 - 消息发送:后端 500 错误 → 前端超时/失败 - 截图功能:截图本身正常(html2canvas + ScreenshotEditor),但上传后发送消息同样失败 - Mock 登录:正常(不经过 AIHandler) ### 验证 - Mock login → `code: 0` ✅ - Send message → `code: 0`, 返回 user_message + ai_reply ✅ - 后端 108 个路由正常注册 ✅ ### 教训 - uvicorn `--reload` 的 WatchFiles reloader 可能缓存旧字节码,清 `__pycache__` 不一定有效 - 本地开发如果不需要热重载,用 `reload=False` 更可靠 --- ## AIHandler 初始化问题修复 + 打包部署脚本(23:07) ### 问题描述 后端 `POST /h5/conversations/current/messages` 报错: ``` TypeError: AIHandler.__init__() missing 1 required positional argument: 'ai_service' ``` ### 根因 `dependencies.py` 中 `AIHandler()` 调用缺少必需的 `ai_service` 参数。代码重构后 `AIHandler.__init__` 需要传入 `AIService` 实例。 ### 修复内容 - `backend/app/dependencies.py` 两处修复: - `get_shared_ai_handler()`: `return AIHandler(ai_service=AIService())` - `dep_ai_handler()`: `return AIHandler(ai_service=AIService())` ### 数据库修复(已在服务器执行) ```sql ALTER TABLE conversations ADD COLUMN IF NOT EXISTS impact_scope VARCHAR(50); ALTER TABLE conversations ADD COLUMN IF NOT EXISTS is_blocking BOOLEAN DEFAULT false; ALTER TABLE conversations ADD COLUMN IF NOT EXISTS emotion_state VARCHAR(50); ALTER TABLE conversations ADD COLUMN IF NOT EXISTS dify_conversation_id VARCHAR(255); ``` ### 打包部署脚本 新增两个自动化脚本: 1. `deploy-server/build-and-deploy.ps1` — PowerShell 脚本,功能: - 打包前端构建产物(frontend-h5/agent/admin/portal dist) - 复制 nginx 配置 + docker-compose.yml + .env - 构建后端 Docker 镜像(包含修复后的代码) - 导出为 `deploy-backend.tar` - 支持 `-Mode deploy` 参数自动上传并部署到服务器 2. `deploy-server/打包部署.bat` — 一键执行批处理 - 不带参数:仅本地打包 - 带 `deploy` 参数:打包 + 部署到服务器 ### 下一步 需要重新构建后端镜像并部署到服务器: 1. 执行 `打包部署.bat deploy` 或手动运行 `build-and-deploy.ps1 -Mode deploy` 2. 脚本会自动:构建镜像 → 导出tar → 上传服务器 → 部署 --- ## 剩余安全风险修复(23:03) ### 任务说明 处理 4 个可在代码层面快速修复的风险项。 ### 修复内容 #### 1. H-6:角色映射标签验证(高风险) - `role_mapping_service.py` 新增 `_validate_tag_name()` 方法 - 验证规则:长度限制 50 字符,过滤禁止的特殊字符 (`<>'"&;\\|%$#@``) - 获取企微标签时过滤不安全的标签名称 #### 2. M-9:异常信息泄露(中等风险) - `main.py` 两处异常处理器修改 - 响应改为通用消息:"服务器内部错误,请稍后重试或联系管理员" - 详细异常信息仅记录到日志 #### 3. M-10:日志脱敏(中等风险) - 新增 `_mask_sensitive_data()` 脱敏函数(保留前3位) - 已处理:`role_mapping_service.py`(3处)、`admin_roles.py`(4处) #### 4. L-7:坐席列表 API 认证(低风险) - `agents.py` 导入 `require_role` 依赖 - `/agents` 端点添加 `@require_role("agent", "admin")` 装饰器 ### 风险处理进度 | 级别 | 处理率 | |------|--------| | 严重 | 100% (4/4) | | 高风险 | 83% (5/6) | | 中风险 | 57% (4/7) | | 低风险 | 60% (3/5) | | **总计** | **73% (16/22)** |