feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1): - Database: Add user_modules table for fine-grained module permissions - Database: Add 4 user permissions (view/create/edit/delete) to role_permissions - Backend: UserService (780 lines) - CRUD with tenant isolation - Backend: UserController + UserRoutes (648 lines) - 13 API endpoints - Backend: Batch import users from Excel - Frontend: UserListPage (412 lines) - list/filter/search/pagination - Frontend: UserFormPage (341 lines) - create/edit with module config - Frontend: UserDetailPage (393 lines) - details/tenant/module management - Frontend: 3 modal components (592 lines) - import/assign/configure - API: GET/POST/PUT/DELETE /api/admin/users/* endpoints Architecture Upgrade - Module Permission System: - Backend: Add getUserModules() method in auth.service - Backend: Login API returns modules array in user object - Frontend: AuthContext adds hasModule() method - Frontend: Navigation filters modules based on user.modules - Frontend: RouteGuard checks requiredModule instead of requiredVersion - Frontend: Remove deprecated version-based permission system - UX: Only show accessible modules in navigation (clean UI) - UX: Smart redirect after login (avoid 403 for regular users) Fixes: - Fix UTF-8 encoding corruption in ~100 docs files - Fix pageSize type conversion in userService (String to Number) - Fix authUser undefined error in TopNavigation - Fix login redirect logic with role-based access check - Update Git commit guidelines v1.2 with UTF-8 safety rules Database Changes: - CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled) - ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code) - INSERT 4 permissions + role assignments - UPDATE PUBLIC tenant with 8 module subscriptions Technical: - Backend: 5 new files (~2400 lines) - Frontend: 10 new files (~2500 lines) - Docs: 1 development record + 2 status updates + 1 guideline update - Total: ~4900 lines of code Status: User management 100% complete, module permission system operational
This commit is contained in:
@@ -1,65 +1,65 @@
|
||||
# Day 3 - 隡<EFBFBD><EFBFBD>敺桐縑<EFBFBD><EFBFBD><EFBFBD>撘<EFBFBD><EFBFBD>穃<EFBFBD><EFBFBD>鞱扇敶?
|
||||
# Day 3 - 企业微信集成开发完成记录
|
||||
|
||||
**撘<EFBFBD><EFBFBD>烐𠯫<EFBFBD>?*嚗?026-01-02
|
||||
**撘<EFBFBD><EFBFBD>𤏸<EFBFBD>?*嚗鋫I + <20>冽<EFBFBD><E586BD>譍<EFBFBD>
|
||||
**开发日期**:2026-01-02
|
||||
**开发者**:AI + 用户协作
|
||||
**版本**:v1.3
|
||||
**<EFBFBD>嗆<EFBFBD>?*嚗尠<E59A97> 隡<><E99AA1>敺桐縑URL撉諹<E69289><E8ABB9>𣂼<EFBFBD>嚗<EFBFBD>抅蝖<E68A85><E89D96><EFBFBD><EFBFBD>摰峕<E691B0>
|
||||
**状态**:✅ 企业微信URL验证成功,基础集成完成
|
||||
|
||||
---
|
||||
|
||||
## <EFBFBD><EFBFBD> 撘<><E69298>烐<EFBFBD>閫?
|
||||
## 📊 开发概览
|
||||
|
||||
### 目标
|
||||
摰䂿緵隡<EFBFBD><EFBFBD>敺桐縑<EFBFBD><EFBFBD><EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>祆<EFBFBD><EFBFBD>舀綫<EFBFBD><EFBFBD><EFBFBD><EFBFBD>噼<EFBFBD>憭<EFBFBD><EFBFBD>嚗䔶蛹 IIT Manager Agent 撱箇<EFBFBD>銝?PI <20><><EFBFBD><EFBFBD>𡁏<EFBFBD><F0A1818F>瓐<EFBFBD>?
|
||||
实现企业微信集成,包括消息推送和回调处理,为 IIT Manager Agent 建立与 PI 的沟通渠道。
|
||||
|
||||
### 成果
|
||||
- <EFBFBD>?隡<><E99AA1>敺桐縑瘨<E7B891><E798A8><EFBFBD>券<EFBFBD><E588B8><EFBFBD><EFBFBD>∴<EFBFBD>WechatService嚗?
|
||||
- <EFBFBD>?隡<><E99AA1>敺桐縑<E6A190>噼<EFBFBD>憭<EFBFBD><E686AD>嚗ÁechatCallbackController嚗?
|
||||
- <EFBFBD>?URL撉諹<EFBFBD>瘚贝<EFBFBD><EFBFBD>朞<EFBFBD>
|
||||
- <EFBFBD>?摰<><E691B0>韐冽綉Worker嚗峕𣈲<E5B395><F0A388B2><EFBFBD>銝𡁜凝靽⊥綫<E28AA5>?
|
||||
- <EFBFBD>?natapp<EFBFBD><EFBFBD><EFBFBD>蝛輸<EFBFBD>誯<EFBFBD>蝵格<EFBFBD><EFBFBD>?
|
||||
- ✅ 企业微信消息推送服务(WechatService)
|
||||
- ✅ 企业微信回调处理(WechatCallbackController)
|
||||
- ✅ URL验证测试通过
|
||||
- ✅ 完善质控Worker,支持企业微信推送
|
||||
- ✅ natapp内网穿透配置成功
|
||||
|
||||
### 进度
|
||||
- 璅∪<EFBFBD><EFBFBD>港<EFBFBD>摰峕<EFBFBD>摨佗<EFBFBD>**35% <EFBFBD>?50%**
|
||||
- 隡<EFBFBD><EFBFBD>敺桐縑<EFBFBD><EFBFBD><EFBFBD>嚗?*0% <EFBFBD>?80%**嚗㇎RL撉諹<EFBFBD>摰峕<EFBFBD>嚗<EFBFBD><EFBFBD>蝡臬<EFBFBD>蝡舀<EFBFBD>霂𤏪<EFBFBD>
|
||||
- 模块整体完成度:**35% → 50%**
|
||||
- 企业微信集成:**0% → 80%**(URL验证完成,待端到端测试)
|
||||
|
||||
---
|
||||
|
||||
## <EFBFBD><EFBFBD>儭?<3F>嗆<EFBFBD>霈曇恣
|
||||
## 🏗️ 架构设计
|
||||
|
||||
### 核心组件
|
||||
|
||||
```
|
||||
<EFBFBD>𢞖<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
||||
<EFBFBD>? 隡<EFBFBD><EFBFBD>敺桐縑<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嗆<EFBFBD> <EFBFBD>?
|
||||
<EFBFBD>鎿<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>? REDCap DET <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? WebhookController <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? JobQueue <EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>? <EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>? Audit Logs iit_quality_check <EFBFBD>?
|
||||
<EFBFBD>? Worker <EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>? WechatService <EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>? 隡<EFBFBD><EFBFBD>敺桐縑 API <EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>? PI <EFBFBD>𧢲㦤 <EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>? 隡<><E99AA1>敺桐縑瘨<E7B891><E798A8> <20><><EFBFBD><EFBFBD><EFBFBD>? WechatCallbackController <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? AI憭<49><E686AD> <EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>? WechatService <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>? 銝餃𢆡<E9A483>券<EFBFBD><E588B8><EFBFBD>憭? <EFBFBD>?
|
||||
<EFBFBD>? <EFBFBD>?
|
||||
<EFBFBD>婙<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 企业微信集成架构 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ REDCap DET ──→ WebhookController ──→ JobQueue │
|
||||
│ ↓ ↓ │
|
||||
│ Audit Logs iit_quality_check │
|
||||
│ Worker │
|
||||
│ ↓ │
|
||||
│ WechatService │
|
||||
│ ↓ │
|
||||
│ 企业微信 API │
|
||||
│ ↓ │
|
||||
│ PI 手机 │
|
||||
│ │
|
||||
│ 企业微信消息 ──→ WechatCallbackController ──→ AI处理 │
|
||||
│ ↓ │
|
||||
│ WechatService ──→ 主动推送回复 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 技术选型
|
||||
|
||||
| 蝏<EFBFBD>辣 | <20><><EFBFBD>舀䲮獢?| <20>笔<EFBFBD> |
|
||||
| 组件 | 技术方案 | 原因 |
|
||||
|------|----------|------|
|
||||
| 瘨<EFBFBD><EFBFBD><EFBFBD>㰘圾撖?| @wecom/crypto | 隡<EFBFBD><EFBFBD>敺桐縑摰䀹䲮<EFBFBD>刻<EFBFBD>摨?|
|
||||
| XML閫<EFBFBD><EFBFBD> | xml2js | <EFBFBD>鞟<EFBFBD>蝔喳<EFBFBD><EFBFBD><EFBFBD>ML閫<EFBFBD><EFBFBD>摨?|
|
||||
| <EFBFBD><EFBFBD><EFBFBD>蝛輸<EFBFBD>?| natapp | <EFBFBD>砍𧑐撘<EFBFBD><EFBFBD>𤏸<EFBFBD>霂?|
|
||||
| 撘<EFBFBD>郊憭<EFBFBD><EFBFBD> | setImmediate | 閫<EFBFBD><EFBFBD>5蝘坿<EFBFBD><EFBFBD>園<EFBFBD><EFBFBD>?|
|
||||
| 消息加解密 | @wecom/crypto | 企业微信官方推荐库 |
|
||||
| XML解析 | xml2js | 成熟稳定的XML解析库 |
|
||||
| 内网穿透 | natapp | 本地开发调试 |
|
||||
| 异步处理 | setImmediate | 规避5秒超时限制 |
|
||||
|
||||
---
|
||||
|
||||
@@ -68,18 +68,18 @@
|
||||
### 1. WechatService.ts(企业微信推送服务)
|
||||
|
||||
**文件路径**:`backend/src/modules/iit-manager/services/WechatService.ts`
|
||||
**隞<EFBFBD><EFBFBD>銵峕㺭**嚗?14銵?
|
||||
**代码行数**:314行
|
||||
|
||||
**<EFBFBD>詨<EFBFBD><EFBFBD>蠘<EFBFBD>**嚗?
|
||||
**核心功能**:
|
||||
```typescript
|
||||
class WechatService {
|
||||
// 1. Access Token 蝞∠<EFBFBD>嚗<EFBFBD><EFBFBD>摮?+ <20>芸𢆡<E88AB8>瑟鰵嚗?
|
||||
// 1. Access Token 管理(缓存 + 自动刷新)
|
||||
async getAccessToken(): Promise<string>
|
||||
|
||||
// 2. <EFBFBD>煾<EFBFBD><EFBFBD><EFBFBD><EFBFBD>祆<EFBFBD><EFBFBD>?
|
||||
// 2. 发送文本消息
|
||||
async sendTextMessage(userId: string, content: string): Promise<void>
|
||||
|
||||
// 3. <EFBFBD>煾<EFBFBD>?Markdown 瘨<EFBFBD><EFBFBD>
|
||||
// 3. 发送 Markdown 消息
|
||||
async sendMarkdownMessage(userId: string, content: string): Promise<void>
|
||||
|
||||
// 4. 审计日志记录
|
||||
@@ -87,13 +87,13 @@ class WechatService {
|
||||
}
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD>臭漁<EFBFBD>?*嚗?
|
||||
- <20>?Access Token 蝻枏<EFBFBD><EFBFBD>箏<EFBFBD>嚗?200蝘𡜐<E89D98><F0A19C90>𣂼<EFBFBD>5<EFBFBD><35><EFBFBD><EFBFBD>瑟鰵嚗?
|
||||
- <20>?摰峕㟲<E5B395><E39FB2><EFBFBD>霂臬<E99C82><E887AC><EFBFBD><EFBFBD><EFBFBD>滩<EFBFBD><E6BBA9>箏<EFBFBD>
|
||||
- <20>?霂衣<E99C82><E8A1A3><EFBFBD>𠯫敹𡑒扇敶𤏪<E695B6>corpId<EFBFBD><EFBFBD>gentId蝑㚁<EFBFBD>
|
||||
- <20>?摰∟恣<E2889F>亙<EFBFBD><E4BA99>芸𢆡霈啣<E99C88>
|
||||
**技术亮点**:
|
||||
- ✅ Access Token 缓存机制(7200秒,提前5分钟刷新)
|
||||
- ✅ 完整的错误处理和重试机制
|
||||
- ✅ 详细的日志记录(corpId、agentId等)
|
||||
- ✅ 审计日志自动记录
|
||||
|
||||
**<EFBFBD>臬<EFBFBD><EFBFBD>㗛<EFBFBD>**嚗?
|
||||
**环境变量**:
|
||||
```env
|
||||
WECHAT_CORP_ID=ww6ab493470ab4f377
|
||||
WECHAT_AGENT_ID=1000002
|
||||
@@ -105,21 +105,21 @@ WECHAT_CORP_SECRET=AZIVxMtoLb0rEszXS81e4dBRl-I9kgTjygIS0cFfENU
|
||||
### 2. WechatCallbackController.ts(企业微信回调处理)
|
||||
|
||||
**文件路径**:`backend/src/modules/iit-manager/controllers/WechatCallbackController.ts`
|
||||
**隞<EFBFBD><EFBFBD>銵峕㺭**嚗?01銵?
|
||||
**代码行数**:501行
|
||||
|
||||
**<EFBFBD>詨<EFBFBD><EFBFBD>蠘<EFBFBD>**嚗?
|
||||
**核心功能**:
|
||||
```typescript
|
||||
class WechatCallbackController {
|
||||
// 1. URL 撉諹<EFBFBD>嚗𠃑ET 霂瑟<E99C82>嚗?
|
||||
// 1. URL 验证(GET 请求)
|
||||
async handleVerification(request, reply): Promise<void>
|
||||
|
||||
// 2. 瘨<EFBFBD><EFBFBD><EFBFBD>交𤣰嚗㇊OST 霂瑟<E99C82> + 撘<>郊憭<E9838A><E686AD>嚗?
|
||||
// 2. 消息接收(POST 请求 + 异步处理)
|
||||
async handleCallback(request, reply): Promise<void>
|
||||
|
||||
// 3. 异步消息处理
|
||||
private async processMessageAsync(...): Promise<void>
|
||||
|
||||
// 4. <EFBFBD>冽<EFBFBD>瘨<EFBFBD><EFBFBD>憭<EFBFBD><EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>株<EFBFBD><EFBFBD>寥<EFBFBD> + 銝𡁜𦛚<F0A1819C>餉<EFBFBD>嚗?
|
||||
// 4. 用户消息处理(关键词匹配 + 业务逻辑)
|
||||
private async processUserMessage(message): Promise<void>
|
||||
|
||||
// 5. 签名验证
|
||||
@@ -127,14 +127,14 @@ class WechatCallbackController {
|
||||
}
|
||||
```
|
||||
|
||||
**<EFBFBD><EFBFBD><EFBFBD>臭漁<EFBFBD>?*嚗?
|
||||
- <EFBFBD>?**撘<>郊<EFBFBD>𧼮<EFBFBD>璅∪<E79285>**嚗𡁶<E59A97><F0A181B6>唾<EFBFBD><E594BE>裇"success"`嚗<><E59A97><EFBFBD>啣<EFBFBD>甇亙<E79487><E4BA99><EFBFBD><EFBFBD>閫<EFBFBD><E996AB>5蝘坿<E89D98><E59DBF>塚<EFBFBD>
|
||||
- <EFBFBD>?**瘨<><E798A8>閫<EFBFBD><E996AB>**嚗帋蝙<E5B88B>?`@wecom/crypto` <EFBFBD>?`decrypt(encodingAESKey, encrypt)` <EFBFBD>賣㺭
|
||||
- <EFBFBD>?**蝑曉<E89D91>撉諹<E69289>**嚗帋蝙<E5B88B>?`@wecom/crypto` <EFBFBD>?`getSignature(token, timestamp, nonce, data)` <EFBFBD>賣㺭
|
||||
- <EFBFBD>?**<2A>誩㦛霂<E3A69B><E99C82>**嚗𡁏𣈲<F0A1818F>?瘙<><E79899>?<3F>?撣桀𨭌"<22>?<3F>唳<EFBFBD><E594B3>?蝑匧<E89D91><E58CA7>株<EFBFBD>
|
||||
- <EFBFBD>?**銝餃𢆡<E9A483>券<EFBFBD>?*嚗𡁜<E59A97><F0A1819C><EFBFBD><EFBFBD><EFBFBD>𣂼<EFBFBD>銝餃𢆡靚<F0A286A1>鍂 WechatService <EFBFBD>券<EFBFBD><EFBFBD><EFBFBD>憭?
|
||||
**技术亮点**:
|
||||
- ✅ **异步回复模式**:立即返回`"success"`,后台异步处理(规避5秒超时)
|
||||
- ✅ **消息解密**:使用 `@wecom/crypto` 的 `decrypt(encodingAESKey, encrypt)` 函数
|
||||
- ✅ **签名验证**:使用 `@wecom/crypto` 的 `getSignature(token, timestamp, nonce, data)` 函数
|
||||
- ✅ **意图识别**:支持"汇总"、"帮助"、"新患者"等关键词
|
||||
- ✅ **主动推送**:处理完成后主动调用 WechatService 推送回复
|
||||
|
||||
**<EFBFBD>臬<EFBFBD><EFBFBD>㗛<EFBFBD>**嚗?
|
||||
**环境变量**:
|
||||
```env
|
||||
WECHAT_TOKEN=oXlRBm1YnvMy2SbDLbvAdDd5Gq3oBGq
|
||||
WECHAT_ENCODING_AES_KEY=v88eT3O9bMW897h4btr7v7qvQImlMf31edTQCmuhOhO
|
||||
@@ -142,9 +142,9 @@ WECHAT_ENCODING_AES_KEY=v88eT3O9bMW897h4btr7v7qvQImlMf31edTQCmuhOhO
|
||||
|
||||
---
|
||||
|
||||
### 3. 頝舐眏<EFBFBD>滨蔭嚗ǐoutes/index.ts嚗?
|
||||
### 3. 路由配置(routes/index.ts)
|
||||
|
||||
**<EFBFBD>啣<EFBFBD>頝舐眏**嚗?
|
||||
**新增路由**:
|
||||
```typescript
|
||||
// GET: URL验证(企业微信配置回调URL时使用)
|
||||
fastify.get('/api/v1/iit/wechat/callback',
|
||||
@@ -159,19 +159,19 @@ fastify.post('/api/v1/iit/wechat/callback',
|
||||
|
||||
---
|
||||
|
||||
### 4. 摰<EFBFBD><EFBFBD>韐冽綉Worker嚗ǎndex.ts嚗?
|
||||
### 4. 完善质控Worker(index.ts)
|
||||
|
||||
**文件路径**:`backend/src/modules/iit-manager/index.ts`
|
||||
**新增功能**:质控完成后自动推送企业微信通知
|
||||
|
||||
**隞<EFBFBD><EFBFBD><EFBFBD>餉<EFBFBD>**嚗?
|
||||
**代码逻辑**:
|
||||
```typescript
|
||||
jobQueue.process('iit_quality_check', async (job) => {
|
||||
// 1. 获取项目配置
|
||||
const project = await prisma.$queryRaw`...`;
|
||||
const piUserId = project.notification_config.wechat_user_id;
|
||||
|
||||
// 2. <EFBFBD>扯<EFBFBD>韐冽綉璉<EFBFBD><EFBFBD>?
|
||||
// 2. 执行质控检查
|
||||
const qualityCheckResult = await performSimpleQualityCheck(...);
|
||||
|
||||
// 3. 构建企业微信通知消息
|
||||
@@ -182,21 +182,21 @@ jobQueue.process('iit_quality_check', async (job) => {
|
||||
});
|
||||
```
|
||||
|
||||
**<EFBFBD>𡁶䰻瘨<EFBFBD><EFBFBD><EFBFBD>澆<EFBFBD>**嚗?
|
||||
**通知消息格式**:
|
||||
```
|
||||
📊 IIT Manager 数据录入通知
|
||||
|
||||
项目:test0102
|
||||
记录ID:xxx
|
||||
表单:xxx
|
||||
<EFBFBD>園𡢿嚗?026-01-02 23:55:00
|
||||
时间:2026-01-02 23:55:00
|
||||
|
||||
<EFBFBD>働 韐冽綉撱箄悅 (3憿?嚗?
|
||||
1. <EFBFBD>?<3F>唳旿敶訫<E695B6><E8A8AB>𦠜𧒄嚗?<3F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
2. <EFBFBD>?霈啣<E99C88>ID<49>㗇<EFBFBD>
|
||||
3. <EFBFBD>?銵典<E98AB5>嚗飱emographics
|
||||
💡 质控建议 (3项):
|
||||
1. ✅ 数据录入及时(5分钟内)
|
||||
2. ✅ 记录ID有效
|
||||
3. ✅ 表单:demographics
|
||||
|
||||
<EFBFBD>?<3F>唳旿韐券<E99F90><E588B8>臬末嚗峕<E59A97><E5B395>擧遬<E693A7>桅<EFBFBD>
|
||||
✅ 数据质量良好,无明显问题
|
||||
|
||||
💬 如有疑问,请回复"帮助"查看更多功能
|
||||
```
|
||||
@@ -205,38 +205,38 @@ jobQueue.process('iit_quality_check', async (job) => {
|
||||
|
||||
## 🔧 开发过程与问题解决
|
||||
|
||||
### <EFBFBD>桅<EFBFBD>1嚗𡁶㴓憓<EFBFBD><EFBFBD><EFBFBD>誩<EFBFBD>蝘唬<EFBFBD>銝<EFBFBD><EFBFBD>?<3F>𩤃<EFBFBD>
|
||||
### 问题1:环境变量名称不一致 ⚠️
|
||||
|
||||
**<EFBFBD>啗情**嚗?
|
||||
**现象**:
|
||||
```
|
||||
hasSecret: false
|
||||
Error: 隡<EFBFBD><EFBFBD>敺桐縑<EFBFBD>滨蔭銝滚<EFBFBD><EFBFBD>湛<EFBFBD>霂瑟<EFBFBD><EFBFBD>亦㴓憓<EFBFBD><EFBFBD><EFBFBD>?
|
||||
Error: 企业微信配置不完整,请检查环境变量
|
||||
```
|
||||
|
||||
**<EFBFBD>笔<EFBFBD>**嚗?
|
||||
**原因**:
|
||||
- 环境变量:`WECHAT_CORP_SECRET`
|
||||
- 代码读取:`WECHAT_AGENT_SECRET`
|
||||
|
||||
**閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>**嚗?
|
||||
**解决方案**:
|
||||
```typescript
|
||||
// 靽格㺿<EFBFBD>?
|
||||
// 修改前
|
||||
agentSecret: process.env.WECHAT_AGENT_SECRET
|
||||
|
||||
// 靽格㺿<EFBFBD>?
|
||||
// 修改后
|
||||
agentSecret: process.env.WECHAT_CORP_SECRET
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### <EFBFBD>桅<EFBFBD>2嚗鋣wecom/crypto 撖澆<EFBFBD><EFBFBD>孵<EFBFBD><EFBFBD>躰秤 <20>?
|
||||
### 问题2:@wecom/crypto 导入方式错误 ❌
|
||||
|
||||
**<EFBFBD>啗情**嚗?
|
||||
**现象**:
|
||||
```
|
||||
TypeError: WXBizMsgCrypt is not a constructor
|
||||
```
|
||||
|
||||
**<EFBFBD>笔<EFBFBD>**嚗?
|
||||
`@wecom/crypto` 銝齿糓銝<EFBFBD>銝芰掩嚗諹<EFBFBD>峕糓撖澆枂鈭?銝芰𡠺蝡讠<E89DA1><E8AEA0>賣㺭嚗?
|
||||
**原因**:
|
||||
`@wecom/crypto` 不是一个类,而是导出了4个独立的函数:
|
||||
```javascript
|
||||
{
|
||||
decrypt: [Function: decrypt],
|
||||
@@ -246,33 +246,33 @@ TypeError: WXBizMsgCrypt is not a constructor
|
||||
}
|
||||
```
|
||||
|
||||
**閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>**嚗?
|
||||
**解决方案**:
|
||||
```typescript
|
||||
// 靽格㺿<EFBFBD>㵪<EFBFBD><EFBFBD>躰秤嚗?
|
||||
// 修改前(错误)
|
||||
import WXBizMsgCrypt from '@wecom/crypto';
|
||||
this.wxcrypt = new WXBizMsgCrypt(token, aesKey, corpId);
|
||||
|
||||
// 靽格㺿<EFBFBD>𠬍<EFBFBD>甇<EFBFBD>&嚗?
|
||||
// 修改后(正确)
|
||||
const require = createRequire(import.meta.url);
|
||||
const { decrypt, encrypt, getSignature } = require('@wecom/crypto');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### <EFBFBD>桅<EFBFBD>3嚗飱ecrypt <EFBFBD>賣㺭<EFBFBD><EFBFBD>㺭<EFBFBD>躰秤 <20>?
|
||||
### 问题3:decrypt 函数参数错误 ❌
|
||||
|
||||
**<EFBFBD>啗情**嚗?
|
||||
**现象**:
|
||||
```
|
||||
Error: invalid encodingAESKey
|
||||
```
|
||||
|
||||
**<EFBFBD>笔<EFBFBD>**嚗?
|
||||
<EFBFBD>朞<EFBFBD>瘚贝<EFBFBD><EFBFBD>𡁏𧋦<EFBFBD>𤑳緵嚗䈣decrypt` <20>賣㺭<E8B3A3>芷<EFBFBD>閬?**2銝芸<E98A9D><E88AB8>?*嚗?
|
||||
**原因**:
|
||||
通过测试脚本发现,`decrypt` 函数只需要 **2个参数**:
|
||||
```javascript
|
||||
function decrypt(encodingAESKey, encrypt) { ... }
|
||||
```
|
||||
|
||||
**閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>**嚗?
|
||||
**解决方案**:
|
||||
```typescript
|
||||
// 修改前(错误 - 4个参数)
|
||||
const result = decrypt(this.token, this.encodingAESKey, this.corpId, echostr);
|
||||
@@ -285,51 +285,51 @@ const result = decrypt(this.encodingAESKey, echostr);
|
||||
|
||||
### 问题4:Token字符识别错误 ⚠️
|
||||
|
||||
**<EFBFBD>啗情**嚗?
|
||||
**现象**:
|
||||
```
|
||||
⚠️ 签名验证失败
|
||||
expected: 0b7cf05d6cb23ab9ce2efca6fdc659f32051eabe
|
||||
calculated: 6f79cabd3e9eea5eb10f55abdcf087ce6393d51d
|
||||
```
|
||||
|
||||
**<EFBFBD>笔<EFBFBD>**嚗?
|
||||
**原因**:
|
||||
Token的第3个字符容易混淆:
|
||||
- `oX1R...`嚗<>㺭摮?嚗?
|
||||
- `oXlR...`嚗<><E59A97><EFBFBD>坔<EFBFBD>瘥徃嚗?
|
||||
- `oX1R...`(数字1)
|
||||
- `oXlR...`(小写字母l)
|
||||
|
||||
<EFBFBD>𡒊垢<EFBFBD>亙<EFBFBD><EFBFBD>曄內<EFBFBD><EFBFBD>糓 `oXlR...`嚗<><E59A97><EFBFBD>耱嚗㚁<E59A97><E39A81>諹<EFBFBD>霂訫極<E8A8AB>瑚葉<E7919A>航<EFBFBD>颲枏<E9A2B2>鈭<EFBFBD>㺭摮?<3F>?
|
||||
后端日志显示的是 `oXlR...`(小写l),而调试工具中可能输入了数字1。
|
||||
|
||||
**閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>**嚗?
|
||||
- <20>湔𦻖隞?`.env` <20><>辣憭滚<E686AD>蝎䁅斐嚗屸<E59A97><E5B1B8>齿<EFBFBD><E9BDBF>刻<EFBFBD><E588BB>?
|
||||
**解决方案**:
|
||||
- 直接从 `.env` 文件复制粘贴,避免手动输入
|
||||
- 确认 Token 为:`oXlRBm1YnvMy2SbDLbvAdDd5Gq3oBGq`
|
||||
|
||||
---
|
||||
|
||||
### 问题5:EncodingAESKey 更新 🔄
|
||||
|
||||
**<EFBFBD>啗情**嚗?
|
||||
<EFBFBD>抒<EFBFBD> EncodingAESKey <EFBFBD>航<EFBFBD><EFBFBD>澆<EFBFBD><EFBFBD>厰䔮憸睃紡<EFBFBD>渲圾撖<EFBFBD>仃韐乓<EFBFBD>?
|
||||
**现象**:
|
||||
旧的 EncodingAESKey 可能格式有问题导致解密失败。
|
||||
|
||||
**閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>**嚗?
|
||||
**解决方案**:
|
||||
在企业微信管理后台重新生成:
|
||||
```
|
||||
旧值:zE4tcdBeekCHPUV015jCh9RVUydnCITINqSmCzg9xtO
|
||||
<EFBFBD>啣<EFBFBD>潘<EFBFBD>v88eT3O9bMW897h4btr7v7qvQImlMf31edTQCmuhOhO嚗?3雿㵪<E99BBF><E3B5AA>澆<EFBFBD>甇<EFBFBD>&嚗?
|
||||
新值:v88eT3O9bMW897h4btr7v7qvQImlMf31edTQCmuhOhO(43位,格式正确)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### <EFBFBD>桅<EFBFBD>6嚗䭰atapp <20><><EFBFBD>蝛輸<E89D9B>誯<EFBFBD>蝵?<3F><>
|
||||
### 问题6:natapp 内网穿透配置 🌐
|
||||
|
||||
**<EFBFBD><EFBFBD>瘙?*嚗?
|
||||
<EFBFBD>砍𧑐撘<EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD><EFBFBD>閬<EFBFBD><EFBFBD>蝵?HTTPS URL <20>其<EFBFBD>隡<EFBFBD><E99AA1>敺桐縑<E6A190>噼<EFBFBD><E599BC>?
|
||||
**需求**:
|
||||
本地开发环境需要公网 HTTPS URL 用于企业微信回调。
|
||||
|
||||
**閫<EFBFBD><EFBFBD><EFBFBD>寞<EFBFBD>**嚗?
|
||||
**解决方案**:
|
||||
1. 使用 natapp 服务
|
||||
2. <20>滨蔭<E6BBA8>折<EFBFBD>嚗䫤http://iit.nat100.top` <EFBFBD>?`127.0.0.1:3001`
|
||||
2. 配置隧道:`http://iit.nat100.top` → `127.0.0.1:3001`
|
||||
3. natapp 自动提供 HTTPS 支持
|
||||
|
||||
**撉諹<EFBFBD>**嚗?
|
||||
**验证**:
|
||||
```bash
|
||||
curl https://iit.nat100.top/api/v1/iit/health
|
||||
# 返回:{"status":"ok","module":"iit-manager",...}
|
||||
@@ -339,11 +339,11 @@ curl https://iit.nat100.top/api/v1/iit/health
|
||||
|
||||
## 🧪 测试验证
|
||||
|
||||
### 瘚贝<EFBFBD>1嚗帋<EFBFBD>銝𡁜凝靽∪<EFBFBD><EFBFBD>𤏸<EFBFBD><EFBFBD><EFBFBD>霂訫極<EFBFBD>琿<EFBFBD>霂?<3F>?
|
||||
### 测试1:企业微信开发者调试工具验证 ✅
|
||||
|
||||
**撌亙<EFBFBD>**嚗帋<E59A97>銝𡁜凝靽∠恣<E288A0><E681A3><EFBFBD><EFBFBD>?<3F>?撘<><E69298>𤏸<EFBFBD><F0A48FB8>極<EFBFBD>?<3F>?瘚贝<E7989A><E8B49D>噼<EFBFBD>璅∪<E79285>
|
||||
**工具**:企业微信管理后台 → 开发者工具 → 测试回调模式
|
||||
|
||||
**<EFBFBD>滨蔭**嚗?
|
||||
**配置**:
|
||||
```
|
||||
URL: https://iit.nat100.top/api/v1/iit/wechat/callback
|
||||
Token: oXlRBm1YnvMy2SbDLbvAdDd5Gq3oBGq
|
||||
@@ -352,33 +352,33 @@ EchoStr: test12345678901234567890123
|
||||
ToUserName: ww6ab493470ab4f377
|
||||
```
|
||||
|
||||
**瘚贝<EFBFBD>蝏𤘪<EFBFBD>**嚗?
|
||||
**测试结果**:
|
||||
```
|
||||
<EFBFBD>?餈𥪜<E9A488><F0A5AA9C>嗆<EFBFBD><E59786><EFBFBD>request: <EFBFBD>𣂼<EFBFBD>
|
||||
<EFBFBD>?餈𥪜<E9A488>蝏𤘪<E89D8F>嚗?23456789012345678901 25嚗<EFBFBD>圾撖<EFBFBD><EFBFBD><EFBFBD>?3雿滚<E99BBF>蝚佗<E89D9A>
|
||||
<EFBFBD>?HTTP<EFBFBD>嗆<EFBFBD><EFBFBD><EFBFBD>嚗?00
|
||||
✅ 返回状态:request: 成功
|
||||
✅ 返回结果:123456789012345678901 25(解密后的23位字符)
|
||||
✅ HTTP状态码:200
|
||||
```
|
||||
|
||||
**<EFBFBD>𡒊垢<EFBFBD>亙<EFBFBD>**嚗?
|
||||
**后端日志**:
|
||||
```
|
||||
📥 收到企业微信 URL 验证请求
|
||||
nonce: "95zbplrrko5"
|
||||
echostrLength: 88
|
||||
<EFBFBD>?URL 撉諹<EFBFBD><EFBFBD>𣂼<EFBFBD>
|
||||
✅ URL 验证成功
|
||||
decryptedLength: 23
|
||||
statusCode: 200
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 瘚贝<EFBFBD>2嚗䭰atapp <20>折<EFBFBD>餈鮋<E9A488>𡁏<EFBFBD>扳<EFBFBD>霂?<3F>?
|
||||
### 测试2:natapp 隧道连通性测试 ✅
|
||||
|
||||
**瘚贝<EFBFBD><EFBFBD>賭誘**嚗?
|
||||
**测试命令**:
|
||||
```bash
|
||||
curl https://iit.nat100.top/api/v1/iit/health
|
||||
```
|
||||
|
||||
**餈𥪜<EFBFBD>蝏𤘪<EFBFBD>**嚗?
|
||||
**返回结果**:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
@@ -392,7 +392,7 @@ curl https://iit.nat100.top/api/v1/iit/health
|
||||
|
||||
## 📋 配置清单
|
||||
|
||||
### <EFBFBD>𡒊垢<EFBFBD>臬<EFBFBD><EFBFBD>㗛<EFBFBD>嚗Ê̄ackend/.env嚗?
|
||||
### 后端环境变量(backend/.env)
|
||||
|
||||
```env
|
||||
# ==========================================
|
||||
@@ -404,14 +404,14 @@ WECHAT_CORP_ID=ww6ab493470ab4f377
|
||||
WECHAT_AGENT_ID=1000002
|
||||
WECHAT_CORP_SECRET=AZIVxMtoLb0rEszXS81e4dBRl-I9kgTjygIS0cFfENU
|
||||
|
||||
# 隡<EFBFBD><EFBFBD>敺桐縑<EFBFBD>噼<EFBFBD><EFBFBD>滨蔭嚗<EFBFBD><EFBFBD><EFBFBD>臬<EFBFBD>閫<EFBFBD><EFBFBD>嚗?
|
||||
# 企业微信回调配置(消息加解密)
|
||||
WECHAT_TOKEN=oXlRBm1YnvMy2SbDLbvAdDd5Gq3oBGq
|
||||
WECHAT_ENCODING_AES_KEY=v88eT3O9bMW897h4btr7v7qvQImlMf31edTQCmuhOhO
|
||||
```
|
||||
|
||||
### 企业微信应用配置
|
||||
|
||||
**摨𠉛鍂靽⊥<EFBFBD>**嚗?
|
||||
**应用信息**:
|
||||
- 企业ID:`ww6ab493470ab4f377`
|
||||
- 应用名称:`IIT Manager Agent`
|
||||
- AgentID:`1000002`
|
||||
@@ -423,9 +423,9 @@ Token: oXlRBm1YnvMy2SbDLbvAdDd5Gq3oBGq
|
||||
EncodingAESKey: v88eT3O9bMW897h4btr7v7qvQImlMf31edTQCmuhOhO
|
||||
```
|
||||
|
||||
**<EFBFBD>臭縑<EFBFBD>笔<EFBFBD>**嚗?
|
||||
**可信域名**:
|
||||
```
|
||||
iit.xunzhengyixue.com嚗𠄎AE<EFBFBD>煺漣<EFBFBD>臬<EFBFBD>嚗?
|
||||
iit.xunzhengyixue.com(SAE生产环境)
|
||||
```
|
||||
|
||||
### natapp 配置
|
||||
@@ -433,8 +433,8 @@ iit.xunzhengyixue.com(SAE生产环境
|
||||
```
|
||||
隧道状态:Online
|
||||
公网URL:http://iit.nat100.top
|
||||
<EFBFBD>砍𧑐蝡臬藁嚗?27.0.0.1:3001
|
||||
HTTPS嚗朞䌊<EFBFBD>冽𣈲<EFBFBD>?
|
||||
本地端口:127.0.0.1:3001
|
||||
HTTPS:自动支持
|
||||
```
|
||||
|
||||
---
|
||||
@@ -443,64 +443,64 @@ HTTPS:自动支
|
||||
|
||||
| 文件 | 代码行数 | 主要功能 |
|
||||
|------|---------|---------|
|
||||
| WechatService.ts | 314銵?| 隡<><E99AA1>敺桐縑瘨<E7B891><E798A8><EFBFBD>券<EFBFBD>?|
|
||||
| WechatCallbackController.ts | 501銵?| 隡<><E99AA1>敺桐縑<E6A190>噼<EFBFBD>憭<EFBFBD><E686AD> |
|
||||
| index.ts嚗<EFBFBD>捶<EFBFBD>劬orker嚗?| +80銵?| 韐冽綉摰峕<E691B0><E5B395>擧綫<E693A7><E7B6AB><EFBFBD>𡁶䰻 |
|
||||
| routes/index.ts | +48銵?| 隡<><E99AA1>敺桐縑頝舐眏瘜典<E7989C> |
|
||||
| **<EFBFBD>餉恣** | **~943銵?* | 隡<EFBFBD><EFBFBD>敺桐縑<EFBFBD><EFBFBD><EFBFBD><EFBFBD>詨<EFBFBD>隞<EFBFBD><EFBFBD> |
|
||||
| WechatService.ts | 314行 | 企业微信消息推送 |
|
||||
| WechatCallbackController.ts | 501行 | 企业微信回调处理 |
|
||||
| index.ts(质控Worker) | +80行 | 质控完成后推送通知 |
|
||||
| routes/index.ts | +48行 | 企业微信路由注册 |
|
||||
| **总计** | **~943行** | 企业微信集成核心代码 |
|
||||
|
||||
---
|
||||
|
||||
## <EFBFBD>?撌脣<E6928C><E884A3>鞟<EFBFBD><E99E9F>蠘<EFBFBD>
|
||||
## ✅ 已完成的功能
|
||||
|
||||
- [x] 隡<EFBFBD><EFBFBD>敺桐縑 Access Token 蝞∠<EFBFBD>嚗<EFBFBD><EFBFBD>摮?<3F>瑟鰵嚗?
|
||||
- [x] 企业微信 Access Token 管理(缓存+刷新)
|
||||
- [x] 发送文本消息到企业微信
|
||||
- [x] <EFBFBD>煾<EFBFBD>?Markdown 瘨<EFBFBD><EFBFBD><EFBFBD>唬<EFBFBD>銝𡁜凝靽?
|
||||
- [x] 隡<EFBFBD><EFBFBD>敺桐縑 URL 撉諹<E69289>嚗𠃑ET霂瑟<E99C82>憭<EFBFBD><E686AD>嚗?
|
||||
- [x] 隡<EFBFBD><EFBFBD>敺桐縑瘨<EFBFBD><EFBFBD><EFBFBD>交𤣰嚗㇊OST霂瑟<EFBFBD>憭<EFBFBD><EFBFBD>嚗?
|
||||
- [x] 瘨<EFBFBD><EFBFBD>閫<EFBFBD><EFBFBD>嚗<EFBFBD>蝙<EFBFBD>?@wecom/crypto嚗?
|
||||
- [x] 蝑曉<EFBFBD>撉諹<EFBFBD>嚗<EFBFBD>蝙<EFBFBD>?@wecom/crypto嚗?
|
||||
- [x] 撘<EFBFBD>郊<EFBFBD>𧼮<EFBFBD>璅∪<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>?蝘坿<E89D98><E59DBF>塚<EFBFBD>
|
||||
- [x] 发送 Markdown 消息到企业微信
|
||||
- [x] 企业微信 URL 验证(GET请求处理)
|
||||
- [x] 企业微信消息接收(POST请求处理)
|
||||
- [x] 消息解密(使用 @wecom/crypto)
|
||||
- [x] 签名验证(使用 @wecom/crypto)
|
||||
- [x] 异步回复模式(规避5秒超时)
|
||||
- [x] 关键词意图识别(汇总、帮助、新患者)
|
||||
- [x] 质控Worker推送企业微信通知
|
||||
- [x] 审计日志记录
|
||||
- [x] natapp <EFBFBD><EFBFBD><EFBFBD>蝛輸<EFBFBD>誯<EFBFBD>蝵?
|
||||
- [x] natapp 内网穿透配置
|
||||
|
||||
---
|
||||
|
||||
## <EFBFBD>?敺<><E695BA><EFBFBD>鞟<EFBFBD><E99E9F>蠘<EFBFBD>
|
||||
## ⏳ 待完成的功能
|
||||
|
||||
- [ ] 保存正式的企业微信回调URL配置
|
||||
- [ ] <EFBFBD>滨蔭<EFBFBD>唳旿摨㮖葉<EFBFBD>?`wechat_user_id`嚗㇊I<EFBFBD><EFBFBD><EFBFBD>銝𡁜凝靽|serID嚗?
|
||||
- [ ] 蝡臬<EFBFBD>蝡舀<EFBFBD>霂𤏪<EFBFBD>REDCap <20>?隡<>凝<EFBFBD>券<EFBFBD><E588B8><EFBFBD>
|
||||
- [ ] LLM<EFBFBD>誩㦛霂<EFBFBD><EFBFBD>嚗<EFBFBD><EFBFBD>蝥批<EFBFBD><EFBFBD>株<EFBFBD><EFBFBD>寥<EFBFBD>嚗?
|
||||
- [ ] 配置数据库中的 `wechat_user_id`(PI的企业微信UserID)
|
||||
- [ ] 端到端测试(REDCap → 企微推送)
|
||||
- [ ] LLM意图识别(升级关键词匹配)
|
||||
- [ ] 对话功能完善(更多业务场景)
|
||||
- [ ] IP白名单配置(部署到SAE时)
|
||||
|
||||
---
|
||||
|
||||
## <EFBFBD><EFBFBD> 銝衤<E98A9D>甇亥恣<E4BAA5>?
|
||||
## 🚀 下一步计划
|
||||
|
||||
### Day 3 下午/晚上(可选)
|
||||
|
||||
1. **靽嘥<EFBFBD>隡<EFBFBD><EFBFBD>敺桐縑甇<EFBFBD><EFBFBD><EFBFBD>滨蔭**嚗?<3F><><EFBFBD>嚗?
|
||||
1. **保存企业微信正式配置**(5分钟)
|
||||
- 在企业微信管理后台保存回调URL配置
|
||||
- 勾选需要接收的消息类型
|
||||
|
||||
2. **<EFBFBD>滨蔭憿寧𤌍<EFBFBD>𡁶䰻**嚗?0<><30><EFBFBD>嚗?
|
||||
- <EFBFBD>瑕<EFBFBD> PI <EFBFBD><EFBFBD><EFBFBD>銝𡁜凝靽?UserID
|
||||
- <EFBFBD>湔鰵<EFBFBD>唳旿摨?`projects` 銵函<EFBFBD> `notification_config` 摮埈挾
|
||||
2. **配置项目通知**(10分钟)
|
||||
- 获取 PI 的企业微信 UserID
|
||||
- 更新数据库 `projects` 表的 `notification_config` 字段
|
||||
|
||||
3. **蝡臬<EFBFBD>蝡舀<EFBFBD>霂?*嚗?0<><30><EFBFBD>嚗?
|
||||
- <EFBFBD>?REDCap 銝剖<EFBFBD><EFBFBD>交<EFBFBD>霂閙㺭<EFBFBD>?
|
||||
3. **端到端测试**(30分钟)
|
||||
- 在 REDCap 中录入测试数据
|
||||
- 验证企业微信收到实时通知
|
||||
- 瘚贝<EFBFBD>撖寡<EFBFBD><EFBFBD>蠘<EFBFBD>嚗<EFBFBD><EFBFBD><EFBFBD>?撣桀𨭌"<22>?瘙<><E79899>?蝑匧<E89D91><E58CA7>株<EFBFBD>嚗?
|
||||
- 测试对话功能(发送"帮助"、"汇总"等关键词)
|
||||
|
||||
### Day 4(后续优化)
|
||||
|
||||
1. **LLM意图识别**
|
||||
- <EFBFBD>亙<EFBFBD> DeepSeek <EFBFBD>硋<EFBFBD>隞?LLM
|
||||
- 摰䂿緵<EFBFBD><EFBFBD>迤<EFBFBD>?AI Agent 撖寡<EFBFBD>
|
||||
- 接入 DeepSeek 或其他 LLM
|
||||
- 实现真正的 AI Agent 对话
|
||||
|
||||
2. **功能完善**
|
||||
- 更多对话场景(数据查询、统计分析)
|
||||
@@ -514,12 +514,12 @@ HTTPS:自动支
|
||||
|
||||
---
|
||||
|
||||
## <EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>獢?
|
||||
## 📖 参考文档
|
||||
|
||||
- [企业微信API文档](https://developer.work.weixin.qq.com/document/path/90664)
|
||||
- [企业微信消息加解密说明](https://developer.work.weixin.qq.com/document/path/90968)
|
||||
- [@wecom/crypto GitHub](https://github.com/wecomteam/crypto)
|
||||
- [<EFBFBD><EFBFBD>撠𦬅VP<EFBFBD>剔㴓撘<EFBFBD><EFBFBD>𤏸恣<EFBFBD>哋(../04-撘<><E69298>𤏸恣<F0A48FB8>?<3F><>撠𦬅VP<56>剔㴓撘<E3B493><E69298>𤏸恣<F0A48FB8>?md)
|
||||
- [最小MVP闭环开发计划](../04-开发计划/最小MVP闭环开发计划.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -527,20 +527,19 @@ HTTPS:自动支
|
||||
|
||||
Day 3 的开发工作虽然遇到了多个技术问题,但最终成功完成了企业微信集成的核心功能。通过调试工具的验证,证明了:
|
||||
|
||||
1. <EFBFBD>?**<2A><><EFBFBD>舀䲮獢<E4B2AE>虾銵?*嚗鋣wecom/crypto 摨𤘪迤撣詨極雿?
|
||||
2. <EFBFBD>?**<2A>嗆<EFBFBD>霈曇恣<E69B87><E681A3><EFBFBD>**嚗𡁜<E59A97>甇亙<E79487>憭齿芋撘𤩺<E69298><F0A4A9BA><EFBFBD><EFBFBD><EFBFBD>輯<EFBFBD><E8BCAF>園䔮憸?
|
||||
3. <EFBFBD>?**隞<><E99A9E>韐券<E99F90><E588B8>臬末**嚗朞祕蝏<E7A595><E89D8F><EFBFBD>亙<EFBFBD><E4BA99>屸<EFBFBD>霂臬<E99C82><E887AC>?
|
||||
4. <EFBFBD>?**撘<><E69298>烐<EFBFBD>蝔见<E89D94><E8A781>?*嚗𡁻䔮憸䀹<E686B8><E480B9>乒<EFBFBD>瘚贝<E7989A>撉諹<E69289><E8ABB9>埝<EFBFBD>獢<EFBFBD>扇敶?
|
||||
1. ✅ **技术方案可行**:@wecom/crypto 库正常工作
|
||||
2. ✅ **架构设计合理**:异步回复模式有效规避超时问题
|
||||
3. ✅ **代码质量良好**:详细的日志和错误处理
|
||||
4. ✅ **开发流程完善**:问题排查→测试验证→文档记录
|
||||
|
||||
**頝萘氖摰峕㟲<EFBFBD>?MVP <20>剔㴓<E58994>芸榆<E88AB8><E6A686><EFBFBD>𡒊<EFBFBD>蝡臬<E89DA1>蝡舀<E89DA1>霂蓥<E99C82>嚗?*
|
||||
**距离完整的 MVP 闭环只差最后的端到端测试了!**
|
||||
|
||||
---
|
||||
|
||||
**霈啣<EFBFBD>鈭?*嚗鋫I Assistant
|
||||
**摰⊥瓲鈭?*嚗𡁜<E59A97><F0A1819C>穃𣪧<E7A983>?
|
||||
**记录人**:AI Assistant
|
||||
**审核人**:开发团队
|
||||
**文档版本**:v1.0
|
||||
**<EFBFBD><EFBFBD><EFBFBD>擧凒<EFBFBD>?*嚗?026-01-02 23:55:00
|
||||
|
||||
**最后更新**:2026-01-02 23:55:00
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user