feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本

包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Neo
2026-04-06 00:03:48 +08:00
parent 70324d8542
commit 6f8f12314f
515 changed files with 76604 additions and 7456 deletions

View File

@@ -0,0 +1,127 @@
# P5.1→NS3 缺失项 #10AI 生成内容的审计日志
## 简要结论
- 状态:✅ 已解决
- 风险等级:🟡 低
- `biz.ai_conversations` + `biz.ai_messages` 两张表已完整记录"谁在什么时候对哪个客户生成了什么",满足审计日志需求
## 详细审查
### 审查范围
- `apps/backend/app/ai/conversation_service.py` — 对话持久化服务
- `apps/backend/app/services/chat_service.py` — Chat 模块服务
- `docs/database/ddl/zqyy_app__biz.sql` — biz schema DDL 基线
- `db/zqyy_app/migrations/2026-03-20__rns14_chat_module_extend.sql` — Chat 模块扩展迁移
- `apps/backend/app/ai/apps/app5_tactics.py` — 典型 App 调用流程(审计写入示例)
### 发现
#### ✅ 审计信息完整记录
**1. `biz.ai_conversations` 表 — 对话级审计**
| 字段 | 类型 | 审计用途 |
|------|------|----------|
| `id` | bigint PK | 对话唯一标识 |
| `user_id` | varchar(50) NOT NULL | **谁**:操作用户 ID系统自动调用时为 `'system'` |
| `nickname` | varchar(100) | 用户昵称 |
| `app_id` | varchar(30) NOT NULL | **什么应用**app1_chat / app2_finance / ... / app8_consolidation |
| `site_id` | bigint NOT NULL | **哪个门店** |
| `source_page` | varchar(100) | 触发来源页面 |
| `source_context` | jsonb | 上下文信息(含 `assistant_id``member_id` 等 → **对哪个客户** |
| `context_type` | varchar(20) | 对话关联类型task/customer/coach/general |
| `context_id` | varchar(50) | 关联 IDtaskId/customerId/coachId |
| `title` | varchar(200) | 对话标题 |
| `created_at` | timestamptz | **什么时候** |
**2. `biz.ai_messages` 表 — 消息级审计**
| 字段 | 类型 | 审计用途 |
|------|------|----------|
| `id` | bigint PK | 消息唯一标识 |
| `conversation_id` | bigint FK | 关联对话 |
| `role` | varchar(10) | system / user / assistant |
| `content` | text NOT NULL | **生成了什么**:完整的 AI 输入和输出内容 |
| `tokens_used` | integer | Token 消耗量 |
| `reference_card` | jsonb | 引用卡片数据 |
| `created_at` | timestamptz | 消息时间戳 |
**3. 写入时机**
所有 8 个 AI 应用在每次调用时都通过 `ConversationService` 写入完整审计链:
```
create_conversation(user_id, nickname, app_id, site_id, source_context)
→ add_message(role="system", content=prompt)
→ add_message(role="user", content=user_input)
→ 调用百炼 API
→ add_message(role="assistant", content=ai_output, tokens_used=N)
```
**4. 索引支持审计查询**
```sql
-- 按用户+门店查询历史对话
CREATE INDEX idx_ai_conv_user_site ON biz.ai_conversations (user_id, site_id, created_at DESC);
-- 按应用+门店查询
CREATE INDEX idx_ai_conv_app_site ON biz.ai_conversations (app_id, site_id, created_at DESC);
-- 按上下文查询(客户/任务/助教维度)
CREATE INDEX idx_ai_conv_context ON biz.ai_conversations (user_id, site_id, context_type, context_id, ...);
-- 按对话查询消息
CREATE INDEX idx_ai_msg_conv ON biz.ai_messages (conversation_id, created_at);
```
### 证据
**App5 审计写入示例app5_tactics.py L240-268**
```python
# 创建对话记录
conversation_id = conv_svc.create_conversation(
user_id=user_id, nickname=nickname,
app_id=APP_ID, site_id=site_id,
source_context={"assistant_id": assistant_id, "member_id": member_id},
)
# 写入 system + user 消息
conv_svc.add_message(conversation_id=conversation_id, role="system", content=...)
conv_svc.add_message(conversation_id=conversation_id, role="user", content=...)
# 调用 AI 后写入 assistant 消息
result, tokens_used = await bailian.chat_json(messages)
conv_svc.add_message(
conversation_id=conversation_id, role="assistant",
content=json.dumps(result, ensure_ascii=False),
tokens_used=tokens_used,
)
```
**DDL 基线确认zqyy_app__biz.sql**
```sql
CREATE TABLE biz.ai_conversations (
id bigint ... NOT NULL,
user_id character varying(50) NOT NULL,
nickname character varying(100) ...,
app_id character varying(30) NOT NULL,
site_id bigint NOT NULL,
source_page character varying(100),
source_context jsonb,
context_type character varying(20),
context_id character varying(50),
...
created_at timestamp with time zone DEFAULT now() NOT NULL
);
CREATE TABLE biz.ai_messages (
id bigint ... NOT NULL,
conversation_id bigint NOT NULL,
role character varying(10) NOT NULL,
content text NOT NULL,
tokens_used integer,
reference_card jsonb,
created_at timestamp with time zone DEFAULT now() NOT NULL
);
```
### 建议
审计日志功能已完整实现,以下为可选增强方向(非必须):
1. **审计查询 API**:当前仅有面向用户的历史对话查询(`get_conversations`可增加面向管理员的审计查询接口按时间范围、app_id、site_id 筛选)
2. **数据保留策略**:当前无自动清理机制,长期运行后 `ai_messages.content` 可能占用大量存储,建议制定保留策略