# IT智能服务台 - 项目记忆

## 锁定的设计决策
- **AI交互原则（2026-06-14）**：小段多回合交互，逐步确认
  - 第1步：确认问题（"您是问XXX吗？"）
  - 第2步：确认谁来解决（"这个问题由XXX处理可以吗？"）
  - 第3步：确认解决方案（"我们通过XXX方式可以吗？"）
  - 第4步：处理过程逐步确认（进度透明，可逆）
  - ❌ 禁止一次性大段回复
- **文档管理**：新建文档统一保存在 `docs/` 目录下，按类型分子目录
- **资源申请流程（2026-06-11）**：所有资源申请→`docs/资源申请清单.md`，不单独发企微/邮件/工单
- **原型已锁定**：坐席工作台 v5.3 + H5用户端 v1.1，调整前须与用户确认
- **代码更新规则**：影响显示效果的前端组件更新前须通过原型图确认
- **UI偏好（2026-06-13更新）**：坐席端+H5用户端统一企微浅色扁平风格；accent=#07C160(企微绿)；深色主题保留原有配色不变
- **术语统一（2026-06-13更新）**："人工"=用户呼叫坐席(传菜铃图标)；"摇人"=坐席呼叫坐席(招手👋)；❌"举手"已改为"招手"；❌"铃铛"已改为"传菜铃"
- **双企微应用方案（2026-06-13确定）**：正式应用"IT智能服务台"(全公司)+测试应用"IT智能服务台-测试"(IT部门)；正式上线前：正式=itsupport.servyou.com.cn(10.90.5.10), 测试=itdesk.amanzac.com(NAS)；正式上线后：正式→高可用架构, 测试→10.90.5.10；原因：公司子域名申请困难
- **H5主设备**：电脑(企微桌面端~70%)，手机~30%
- **H5排查步骤**：固定消息框顶部，始终可见可收起，桌面+手机统一
- **输入框**：默认3行，自动扩展
- **桌面端栏宽**：可拖拽手柄调整，右侧flex:1
- **系统名称**：IT智能服务台 — AI驱动 · 多系统对接 · 一站式处理
- **H5企微环境限制（2026-06-12）**：前端路由守卫检测UA含`wxwork`标识，非企微环境跳转WeworkOnly拦截页；后端OAuth2接口同步校验UA；localhost开发环境跳过检测
- **统一入口架构（2026-06-12设计）**：所有用户必须通过企微工作台→IT智能服务台应用进入；路由选择页`/itportal/`（卡片UI）；角色体系user/agent/admin；管理端仅限内网/VPN访问；技术设计文档：`docs/统一入口技术设计文档.md`
- **OTP双因素认证（2026-06-14）**：
  - 绑定方式：首次登录自动引导（用户点击"OTP二次验证"菜单 → 生成二维码+密钥 → 验证启用）
  - 验证场景：访问管理后台时（admin角色且已绑定OTP）
  - 后端API：/agents/otp-bind、/agents/otp-verify、/agents/otp-unbind、/admin/agents/{id}/otp-unbind
  - 坐席端：TopBar下拉菜单添加"OTP二次验证"选项
  - 管理后台：坐席表格OTP列 + 编辑对话框强制解绑

## 产品设计文档 (2026-06-14)

- 新增 `docs/IT智能服务台-产品设计文档.md`
- 包含：竞品分析、MVP架构、风险暴露、期待管理
- 定位：融合服务台+资产+终端安全的企业级ITSM

## 技术架构
- **坐席端**：Vue 3 + TS + Vite + Element Plus + Pinia
- **H5用户端**：Vue 3 + Vant 4 + TS
- **管理后台**：Vue 3 + TS + Element Plus + Tailwind + Pinia (`frontend-admin/`)
- **后端**：FastAPI + SQLAlchemy + PostgreSQL + Redis
- **本地开发**：Python 3.12 venv + SQLite + Docker Redis + Vite proxy
- **注意**：本地开发环境 `.env` 中 DATABASE_URL 指向 **SQLite**（非 PostgreSQL），凭据存储在 `backend/it_smart_desk.db`
- **⚠️ 字段映射（CRITICAL 2026-06-23修复）**：
  - 后端 `MessageResponse` 返回 `id`/`sender_type`（与坐席端对齐）
  - H5 前端 `Message` 接口期望 `message_id`/`message_type`
  - **映射层在** `frontend-h5/src/api/conversation.ts` 的 `mapMessage()` 函数
  - 坐席端直接使用 `id`/`sender_type`（无需映射）
  - 新增消息时必须通过 `mapMessage()` 转换，否则 Vue 渲染失败
- **H5发消息后WS广播（2026-06-23新增）**：
  - 后端 `h5_send_message` 现在通过 `ws_manager.broadcast()` 向坐席端推送 new_message + conversation_updated 事件
  - 之前坐席端只能通过3秒轮询发现新消息，现在WS推送更实时
- **⚠️ 字段映射（CRITICAL 2026-06-23修复）**：
  - 后端 `MessageResponse` 返回 `id`/`sender_type`（与坐席端对齐）
  - H5 前端 `Message` 接口期望 `message_id`/`message_type`
  - **映射层在** `frontend-h5/src/api/conversation.ts` 的 `mapMessage()` 函数
  - 坐席端直接使用 `id`/`sender_type`（无需映射）
  - 新增消息时必须通过 `mapMessage()` 转换，否则 Vue 渲染失败
- **H5发消息后WS广播（2026-06-23新增）**：
  - 后端 `h5_send_message` 现在通过 `ws_manager.broadcast()` 向坐席端推送 new_message + conversation_updated 事件
  - 之前坐席端只能通过3秒轮询发现新消息，现在WS推送更实时
- **API超时配置（2026-06-23）**：
  - apiClient默认：20s（原10s）
  - 消息发送API：30s（原10s，图片/文件需更多处理时间）
  - 文件上传API：60s（不变）
  - 后端坐席发消息：非text消息不创建Redis连接（无企微API调用）
- **字段映射（CRITICAL 2026-06-23修复）**：
  - 后端 MessageResponse 用 `id`/`sender_type`，H5前端 Message 接口用 `message_id`/`message_type`
  - 映射层在 `frontend-h5/src/api/conversation.ts` 的 `mapMessage()` 函数
  - sendMessage 和 pollMessages 都经过映射
  - WS handleNewMessage 直接用 sender_type → message_type（无需映射，WS推送已用正确字段名）
- **H5发消息后WS广播（2026-06-23新增）**：
  - 后端 `h5_send_message` 现在通过 `ws_manager.broadcast()` 向坐席端推送 new_message + conversation_updated 事件
  - 之前坐席端只能通过3秒轮询发现新消息，现在WS推送更实时

## 统一入口 Portal（2026-06-23 Phase 2 完成）
- **前端**：`frontend-portal/`，base path `/itportal/`，端口 5176
- **后端**：`backend/app/api/portal.py`（/portal/roles, /portal/switch-role, /portal/entry/{role}）
- **认证流程**：企微工作台 → OAuth2 → Portal（角色选择）→ 跳转目标端（?token=xxx 传递）
- **⚠️ 测试环境（CRITICAL）**：本地开发环境无法完成企微 OAuth2 认证，所有登录相关验证必须在生产服务器 `10.90.5.110` 上进行
- **前端认证方式**：所有前端都通过企微认证，不支持独立登录页面
- **Token 传递**：Portal 通过 URL 参数 `?token=xxx` 传递到目标前端，路由守卫读取并保存到各自 localStorage key
- **端口映射**：5173(坐席), 5174(H5), 5175(管理), 5176(Portal)
- **角色系统**：user(默认) / agent / admin，DB 表 roles + user_roles + role_mapping_rules
- **构建验证**：三个前端 + 后端 portal.py 全部通过 ✅
- **部署配置**：Nginx /itportal/ 路由已添加（本地版 + 生产版）
- **角色管理脚本**：`backend/scripts/init_roles.py` + `assign_role.py`（Windows GBK 兼容，无 emoji）
- **本地启动脚本**：`scripts/dev-portal.sh` / `dev-portal.ps1`（一键启动4个服务）

## 部署
- **NAS测试**：itdesk.amanzac.com (Cloudflare Tunnel)，5容器，`/volume1/docker/wecom-it-desk`
- **正式服务器**：`itsupport.servyou.com.cn`（10.90.5.110），4容器(无cloudflared)，`/opt/wecom-it-desk`
- **服务器文件上传默认路径**：`/tmp/`（堡垒机上传到此目录后 mv 到目标位置）
  - **堡垒机**：`sxn@10.212.189.210:2222`（OTP），默认目录 `/tmp/`
- **⚠️ 公司服务器文件上传方式限制**：只能通过堡垒机手动上传（SFTP/Web界面），不支持从本地直接 scp 推送到服务器；部署时需先下载部署包到本地，再通过堡垒机上传到 `/tmp/`
- **⚠️ 公司服务器文件上传方式限制**：只能通过堡垒机手动上传（SFTP/Web界面），不支持从本地直接 scp 推送到服务器；部署时需先下载部署包到本地，再通过堡垒机上传到 `/tmp/`
- **Docker镜像加速器**：内网无法拉 Docker Hub，需配置 daemon.json（腾讯云/USTC），或离线导入 tar 包
- **PyPI镜像**：服务器可访问 pypi.tuna.tsinghua.edu.cn，后端构建正常
- **HTTPS**：已配置 SSL（`*.servyou.com.cn` 通配符证书，GeoTrust/DigiCert），nginx 监听 443，HTTP 自动 301 跳转
- **WAF**：域名 itsupport.servyou.com.cn 经 WAF(10.80.0.136) 转发到 10.90.5.110，需 WAF 管理员配置
- 堡垒机：sxn@10.212.189.210:2222 (OTP)；Dockerfile用清华PyPI镜像
- 前端base路径：H5 `/itdesk/`，Agent `/itagent/`，Admin `/itadmin/`；API `/api`
- 前端开发端口：5173(坐席)，5174(H5)，5175(管理后台)
- Mock登录：`POST /api/h5/mock-login`；生产清空 `VITE_WECOM_CORP_ID`
- **Redis协议兼容**：Windows Redis 3.x 不支持 RESP3，必须用 `protocol=2` 创建客户端（通过 `settings.create_redis_client()`）
- **Redis客户端创建统一入口**：`settings.create_redis_client()` 代替直接 `aioredis.from_url()`
- **⚠️ uvicorn --reload 缓存陷阱（2026-06-13）**：WatchFiles reloader 可能缓存旧字节码，清 `__pycache__` 无效；本地开发建议 `reload=False` 或重启前杀掉所有 Python 进程

## 五阶段演进
1. 转人工改H5+坐席MVP+邀请(1A) | 管理后台(1B) | 端到端验证(1C)
2. H5全流程+WS+排队+满意度+OAuth2
3. AI Wingman+排查流程图+标注
4. 迭代闭环+数据看板+知识库
5. 自动/辅助审核、开单、结单

## 管理后台已实现（1B+1C+P2）
- 路由前缀 `/api/admin/`；权限 require_admin；P0：仪表盘/功能开关/坐席管理
- P1：分配模式/快速回复审核/集成配置/会话监控
- **P2 已实现（2026-06-13）**：会话审计/坐席绩效/系统日志
- **集成三种配置模式**：url_key(Dify/RAGFlow) / access_key(火绒) / account_password(联软)
- **集成管理**：6个系统定义（dify/ragflow可配置，huorong access_key，lianruan account_password，其余占位）
- **终端安全页**：TerminalSecurity.vue 展示火绒终端数据（含demo数据fallback）
- **角色管理页（2026-06-13完成）**：Roles.vue — 三角色卡片+用户分配表+映射规则表；路由 `/roles`；侧边栏"运营管理"分组
  - 后端 RBAC 完整：Role/UserRole/RoleMappingRule 模型 + admin_roles API(6端点) + role_mapping_service + Portal API
  - 前端：types定义 + admin.ts 6个API函数 + Roles.vue 页面 + 路由 + 侧边栏
  - 编译验证：vite build ✅
- **功能开关增强**：CONFIG_GROUP_MAP 新增 queue_/satisfaction_/invite_/notification_/security_ 5个分组

## 外部系统集成
- **北森eHR**：OAuth2.0，需找HR数字化团队对接
- **企微设备管理**：❌付费功能公司未购买(errcode 48002)
- **火绒企业版**：HMAC-SHA1 AccessKey认证，17个API端点 ✅后端+前端已完成
  - 后端HuorongClient(4级异常+数据模型) + API端点 + 前端终端安全页
  - **errno/errcode兼容**：认证失败返回 `errno`(非 `errcode`)，需 model_validator 归一化
  - **凭据配置**：通过集成管理页 access_key 模式保存到 SQLite，路径 `/api/clnts/_list`
  - **当前状态**：✅认证成功！根据官方API文档重写了HRESS签名机制，可正常获取终端数据
  - **签名算法（官方文档确认）**：
    - Authorization = "HRESS" + AccessKeyId + ":" + Expires + ":" + Signature
    - Signature = urlencode(base64(hmac-sha1(AccessKeySecret, AccessKeyId + "\n" + Expires + "\n" + POST + "\n" + Content-MD5 + "\n" + CanonicalizedResource)))
    - Content-MD5 = base64(md5_digest(body_bytes))（RFC2616）
    - CanonicalizedResource = API路径去掉前导/（如 "api/clnts/_list"）
  - **API参数**：统一POST JSON；分页用 limit/offset（非 page/per_page）
  - **响应格式**：始终使用 errno（0=成功/1=认证失败/2=参数错误/3=内部错误/4=未授权）
  - **UI标签差异**：火绒控制中心显示"Secret ID/Secret Key"=文档的"AccessKey ID/AccessKey Secret"
  - **API文档**：不公开，通过技术支持QQ(320171962)单独分发；用户已保存MHTML到`D:\资料\00-工作文件\02-系统运维\火绒安全\`
  - **_leak接口字段差异**（高危漏洞终端）：
    - `cid`(非client_id), `hostname`(非computer_name), `ip_addr`(非local_ip)
    - `stat`(1=离线/2=在线/3=异常, 非is_online布尔值)
    - `osver`(非os_version), `prodver`(非version)
    - 外层返回 `all_client`(终端总数) + `risk_client`(高危终端数)，无total
  - **_virus_events接口字段**（病毒事件统计）：
    - `count`(病毒日志数), `result{success/fail/ignored/trusted}`(处理结果统计)
    - 必须指定`type`: 0=按client_id/1=按group_id/2=全部
    - 支持`begin_time`/`end_time`时间范围过滤(Unix时间戳)
    - 返回`total`(查询总数)
- **联软LV7000**：三层认证(IP白名单+账号密码+Token)，68个API端口 ✅后端+前端已完成
  - ⭐核心价值：`strusername`字段=员工→终端精确映射（优于火绒IP匹配）
  - 后端：LianruanClient(4级异常+数据模型) + API端点(3个) + config.py
  - 前端：Integrations.vue三模式对话框(account_password) + IntegrationCard.vue + api/admin.ts
  - 编译验证：前端 vite build ✅ / 后端 py_compile ✅
  - **IT安全运维管理系统**：主机 `192.168.1.53`，备机 `192.168.1.54`
- **Dify**：✅已集成（AIService + WingmanService），调用 dify2openai 桥接
  - 生产：`http://yw-dify.dc.servyou-it.com/dify2openai/v1/chat/completions`
  - API Key格式：`base_url|app_id|app_name`
  - 两个Agent：Agent1(员工端自动回复) + Agent2(坐席端Wingman辅助)
- **RAGFlow**：生产 `http://10.80.0.85:8080/`(前端) / `http://10.80.0.85:9380/`(API)
  - 测试：`http://10.90.5.8:8082/`
  - API Key：`sk-654e************f7b91ea2b`（已获取）
  - 向量模型：bge-m3；知识运营：宋献IT组主导
  - 大模型后端：千问 Qwen3-30B-A3B-Instruct @ `http://10.80.0.49:5000`
  - ✅ 客户端已开发：`backend/app/integrations/ragflow/client.py`
  - 核心接口：`POST /api/v1/retrieval`（知识检索）
  - 管理接口：列出/创建/删除知识库、上传/列出/删除文档
  - Admin API：`/admin/integrations/ragflow/test|datasets|retrieval`
- **千问模型**：`http://10.80.0.49:5000/api/llm/servyou/v1/chat/completions`
  - 模型：Qwen3-30B-A3B-Instruct；通过Dify Workflow间接调用，无需直连
- **对接联系人**：dify2openai→JG(标准)/CF(搭建)；Dify应急→CF/WT；B端智能体→JG
- **aTrust**：HMAC-SHA256签名，104个API端点，需找信息安全团队获取API密钥
- **映射策略**：联软(主P0) > aTrust(VPN辅) > eHR(静态数据)；火绒=安全源不参与映射

## 邀请功能（1A）
- 方案三：WebSocket+应用消息双通道扩展
- 数据模型：conversations表新增participants JSON字段
- H5端+坐席端+后端均已完成（vite build ✅）
- 后端20个邀请测试全部通过 ✅（2026-06-12修复测试基础设施）
- 测试修复：路径前缀(`/api/`→`/`) + WecomService mock + ParticipantInfo schema补全(joined/joined_at/avatar) + 断言改业务错误码
- **H5专用参与者API（2026-06-13）**：统一 `/h5/` 前缀 + `_get_current_employee` 认证
  - `POST /h5/conversations/{id}/join` — 加入会话（employee_id 从 Token 获取）
  - `POST /h5/conversations/{id}/leave-participant` — 退出会话
  - `GET /h5/conversations/{id}/participants` — 获取参与者列表
  - 原 `/conversations/{id}/join` 和 `/leave-participant` 无认证，保留给坐席端使用

## H5端消息推送
- 双通道：企微`/message/send`(必达) + H5 WebSocket(即时)；断连降级→轮询
- **H5 WS端点（2026-06-12已实现）**：`/ws/h5/{employee_id}?token=xxx`
  - 认证：Redis `employee:token:{token}` → employee_id 一致性校验
  - 事件推送：participant_invited/joined/removed/left、new_message
  - 坐席端仍使用 `/ws/{agent_id}?token=xxx`
- **ConnectionManager 扩展**：坐席连接(`active_connections`) + 员工连接(`employee_connections`) 分开管理
- **session_service._broadcast_participant_change()**：广播给坐席 + 推送给相关H5员工
- **H5前端 WS composable**：`useH5WebSocket.ts`，与坐席端 `useWebSocket.ts` 对齐
- **降级策略**：WS断连→3秒轮询；WS重连→停止轮询
- P0待办：Nginx超时优化

## 痛点清单
1. 员工入口体验差 → 阶段二
2. 坐席能力不稳定 → 阶段三
3. 知识无法积累传承 → 阶段四
4. 管理缺乏数据支撑 → 阶段四

## workbuddy 任务清单索引 (2026-06-14)

- [批量任务清单](.workbuddy/memory/2026-06-14-批量任务.md) — W-1~W-5 workbuddy 任务
- [今夜收尾任务](.workbuddy/memory/2026-06-14-今夜-收尾任务.md) — T-1~T-4 Claude+workbuddy 协作
- [今夜满载任务](.workbuddy/memory/2026-06-14-今夜-满载任务.md) — 12小时满载排期
- [评审 Gitea 重建](docs/评审报告/workbuddy-2026-06-14-Gitea重建.md) — 卸载清空事件复盘
