docs: 移动蓝绿部署指南到 troubleshooting 目录
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# IT智能服务台 — 系统架构设计文档
|
||||
|
||||
> **文档版本**: v1.4
|
||||
> **文档版本**: v1.5
|
||||
> **创建日期**: 2025-07-11
|
||||
> **最近更新**: 2026-07-04
|
||||
> **架构师**: 高见远 (Bob)
|
||||
@@ -356,6 +356,43 @@ Wingman 是坐席工作台的 AI 辅助系统:
|
||||
| **数据映射** | 审批标题 → TodoItem.title / 审批状态 → TodoItem.status |
|
||||
| **依赖** | 需企微管理后台创建审批应用并授权 API |
|
||||
|
||||
### 9.3 WebSocket 实时通讯技术方案
|
||||
|
||||
> **新增日期**: 2026-07-05 | **状态**: 已实现
|
||||
|
||||
#### 9.3.1 技术选型
|
||||
|
||||
| 方案 | 优点 | 缺点 | 结论 |
|
||||
|------|------|------|------|
|
||||
| WebSocket | 双向实时、低延迟 | 需心跳维护 | ✅ 推荐 |
|
||||
| SSE | 简单单向 | 仅服务器→客户端 | ❌ 不适合 |
|
||||
| 轮询 | 实现简单 | 延迟高、资源浪费 | ❌ 不推荐 |
|
||||
|
||||
#### 9.3.2 消息类型
|
||||
|
||||
| 消息类型 | 方向 | 说明 |
|
||||
|----------|------|------|
|
||||
| `message_new` | Server→Client | 新消息推送 |
|
||||
| `message_recall` | Server→Client | 消息撤回 |
|
||||
| `typing` | Bidirectional | 对方正在输入 |
|
||||
| `presence` | Bidirectional | 在线状态 |
|
||||
| `ping/pong` | Bidirectional | 心跳保活 |
|
||||
|
||||
#### 9.3.3 心跳机制
|
||||
|
||||
- 客户端每 30 秒发送一次 ping
|
||||
- 服务端 60 秒内未收到 ping 断开连接
|
||||
|
||||
#### 9.3.4 断线重连
|
||||
|
||||
- 前端 WebSocket 断开后自动重连
|
||||
- 最大重连次数: 5
|
||||
- 重连间隔: 2s, 4s, 8s, 16s, 32s
|
||||
|
||||
#### 9.3.5 降级策略
|
||||
|
||||
WebSocket 连接失败或断开时,自动降级为轮询(每3-5秒)。
|
||||
|
||||
---
|
||||
|
||||
## 10. 安全设计
|
||||
@@ -381,6 +418,56 @@ Wingman 是坐席工作台的 AI 辅助系统:
|
||||
| 角色来源追溯 | user_roles 表记录 source 和 assigned_by |
|
||||
| 管理端 IP 白名单 | 仅内网/VPN 可访问 |
|
||||
|
||||
### 10.3 OTP 双因素认证技术方案
|
||||
|
||||
> **新增日期**: 2026-07-05 | **状态**: 规划中
|
||||
|
||||
#### 10.3.1 技术选型
|
||||
|
||||
| 方案 | 优点 | 缺点 | 结论 |
|
||||
|------|------|------|------|
|
||||
| TOTP (Google Authenticator) | 开源成熟无需服务器 | 需手动绑定 | ✅ 推荐 |
|
||||
| 短信OTP | 用户无需安装App | 有成本,有延迟 | ❌ 不推荐 |
|
||||
| 邮箱OTP | 无需安装App | 有延迟,不实时 | ❌ 不推荐 |
|
||||
|
||||
#### 10.3.2 认证流程
|
||||
|
||||
```
|
||||
用户输入账号密码
|
||||
↓
|
||||
验证账号密码成功
|
||||
↓
|
||||
返回要求OTP验证
|
||||
↓
|
||||
用户输入OTP验证码
|
||||
↓
|
||||
验证OTP → 返回结果
|
||||
```
|
||||
|
||||
#### 10.3.3 绑定流程
|
||||
|
||||
```
|
||||
用户首次登录 → 系统检测未绑定OTP → 显示绑定页面 → 用户扫描二维码 → 输入验证码确认 → 绑定成功
|
||||
```
|
||||
|
||||
#### 10.3.4 API 设计
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| POST | `/api/auth/otp-bind` | 绑定OTP |
|
||||
| POST | `/api/auth/otp-verify` | 验证OTP |
|
||||
| POST | `/api/auth/otp-unbind` | 解绑OTP(管理员) |
|
||||
| GET | `/api/auth/otp-status` | 查询OTP绑定状态 |
|
||||
|
||||
#### 10.3.5 数据库设计
|
||||
|
||||
```sql
|
||||
-- 扩展 agents 表新增字段
|
||||
ALTER TABLE agents ADD COLUMN otp_secret VARCHAR(32) DEFAULT NULL;
|
||||
ALTER TABLE agents ADD COLUMN otp_bound BOOLEAN DEFAULT FALSE;
|
||||
ALTER TABLE agents ADD COLUMN otp_bound_at TIMESTAMP DEFAULT NULL;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 复杂对话场景设计
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
# 尝试多个可能的接口路径
|
||||
|
||||
# IT服务台Secret
|
||||
curl -s 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=wwa8c87970b2011f41&corpsecret=EOtQslW7WD8Rna8Nm9WnwCW-ozHP3tustL4mFnet6O8' > /tmp/token.json
|
||||
TOKEN=$(grep -o '"access_token":"[^"]*' /tmp/token.json | cut -d'"' -f4)
|
||||
|
||||
echo "Token: $TOKEN"
|
||||
echo ""
|
||||
|
||||
# 尝试不同的接口路径
|
||||
echo "=== 1. oa/get_template_list ==="
|
||||
curl -s "https://qyapi.weixin.qq.com/cgi-bin/oa/get_template_list?access_token=$TOKEN"
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
echo "=== 2. oa/template/list ==="
|
||||
curl -s "https://qyapi.weixin.qq.com/cgi-bin/oa/template/list?access_token=$TOKEN"
|
||||
echo ""
|
||||
echo ""
|
||||
|
||||
echo "=== 3. oa/approval/list ==="
|
||||
curl -s "https://qyapi.weixin.qq.com/cgi-bin/oa/approval/list?access_token=$TOKEN&starttime=1767187200&endtime=1783094400"
|
||||
echo ""
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""企微审批API权限测试脚本 - 服务器版本(使用 urllib)"""
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
import urllib.error
|
||||
import json
|
||||
import sys
|
||||
|
||||
CORP_ID = "wwa8c87970b2011f41"
|
||||
CORP_SECRET = "EOtQslW7WD8Rna8Nm9WnwCW-ozHP3tustL4mFnet6O8"
|
||||
|
||||
print("=" * 60)
|
||||
print("企微审批API权限测试")
|
||||
print("=" * 60)
|
||||
|
||||
# 1. 获取 access_token
|
||||
print("\n[1/2] 获取 access_token...")
|
||||
url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={CORP_ID}&corpsecret={CORP_SECRET}"
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=10) as response:
|
||||
result = json.loads(response.read().decode('utf-8'))
|
||||
except Exception as e:
|
||||
print(f"❌ 请求失败: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f" 返回: {result}")
|
||||
|
||||
if result.get("errcode") != 0:
|
||||
print(f"❌ access_token 获取失败: {result.get('errmsg')}")
|
||||
sys.exit(1)
|
||||
|
||||
token = result.get("access_token")
|
||||
print(f"✅ access_token: {token[:20]}...")
|
||||
|
||||
# 2. 测试审批API - 企微正确的API路径
|
||||
print("\n[2/2] 测试审批API...")
|
||||
|
||||
# 企微OA审批接口正确的调用方式
|
||||
# 首先尝试 approvallist 接口
|
||||
test_endpoints = [
|
||||
("/cgi-bin/oa/approvallist", {"start_time": 0, "end_time": 9999999999, "cursor": 0, "size": 1}),
|
||||
("/cgi-bin/oa/approvalinfo", {"spno": "test"}), # 用一个测试单号
|
||||
]
|
||||
|
||||
success = False
|
||||
for endpoint, params in test_endpoints:
|
||||
full_url = f"https://qyapi.weixin.qq.com{endpoint}?access_token={token}&{urllib.parse.urlencode(params)}"
|
||||
print(f" 测试: {endpoint}...")
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(full_url, timeout=10) as response:
|
||||
result = json.loads(response.read().decode('utf-8'))
|
||||
except urllib.error.HTTPError as e:
|
||||
result = {"errcode": e.code, "errmsg": f"HTTP {e.code}"}
|
||||
except Exception as e:
|
||||
result = {"errcode": -1, "errmsg": str(e)}
|
||||
|
||||
print(f" errcode: {result.get('errcode')}, errmsg: {result.get('errmsg')}")
|
||||
|
||||
if result.get("errcode") == 0:
|
||||
success = True
|
||||
print(f" ✅ {endpoint} 接口可用!")
|
||||
break
|
||||
elif result.get("errcode") == 48001:
|
||||
print(f" ❌ 没有权限: {result.get('errmsg')}")
|
||||
elif result.get("errcode") == 301012:
|
||||
print(f" ⚠️ 接口可用但审批单不存在(正常)")
|
||||
success = True
|
||||
break
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
if success:
|
||||
print("✅ 测试结果: 企微审批API权限已开通")
|
||||
else:
|
||||
print("❌ 测试结果: 未开通审批API权限 (错误码 48001)")
|
||||
print("=" * 60)
|
||||
@@ -192,7 +192,7 @@ M1 已升级为 **WebSocket 实时推送**(2026-06-03 完成),坐席浏览
|
||||
- 需跨平台/跨主体 → 方案A 不可替代
|
||||
- **推荐混合策略**:原生1对1做日常入口,H5 保留为扩展层
|
||||
|
||||
**运维应急**(详见 `01-项目总览与部署手册.md` §7.5):
|
||||
**运维应急**(详见 `01-项目总览/01-项目总览与部署手册-20260704.md` §7.5):
|
||||
- H5 不可用时,零代码切换至方案B
|
||||
- 需外援协作时,按需启用 appchat 群聊
|
||||
|
||||
@@ -652,4 +652,4 @@ C:\Users\simon\wecom_it_smart_desk\
|
||||
|
||||
---
|
||||
|
||||
> 本文档面向运维/架构/开发三团队沟通使用。详细技术规格见 `ARCHITECTURE.md`,产品需求见 `PRD.md`。
|
||||
> 本文档面向运维/架构/开发三团队沟通使用。详细技术规格见 `03-技术架构/00-系统架构设计文档-v1.3.md`,产品需求见 `02-产品需求/02-产品需求文档PRD-v1.2-20260704.md`。
|
||||
|
||||
Reference in New Issue
Block a user