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,80 @@
# P5.1→NS3 缺失项 #3App3 维客线索生成的触发条件和频率
## 简要结论
- 状态:✅ 已解决
- 风险等级:🟡 低
- App3 的触发机制已通过事件驱动架构完整实现:消费结算事件触发 → dispatcher 编排调用链 → App3 执行。触发条件和频率在 P5 spec 和代码中均有明确定义。
## 详细审查
### 审查范围
- `apps/backend/app/ai/dispatcher.py` — AI 事件调度与调用链编排器
- `apps/backend/app/ai/apps/app3_clue.py` — App3 实现
- `apps/backend/app/services/trigger_scheduler.py` — 触发器调度框架
- `apps/backend/app/main.py` — AI 事件处理器注册
- `docs/prd/specs/P5-miniapp-ai-integration.md` — P5 spec 触发条件定义
### 发现
1. **触发条件**P5 spec AC3 明确定义"应用 3 维客线索在客户新增消费时自动更新"。代码实现完全匹配:
- `dispatcher.py``handle_consumption_event()` 方法在消费结算事件发生时触发 App3
- 事件名称:`ai_consumption_settled`
- 触发参数:`member_id`, `site_id`, `settle_id`, `assistant_id`(可选)
2. **触发频率**:事件驱动(非定时),每次客户新增消费(结账单)时触发一次。这是 P5 spec 设计的意图——"客户新增消费时自动更新"。
3. **事件注册链路**
- `main.py` lifespan 中创建 `AIDispatcher` 并调用 `register_ai_handlers()`
- `register_ai_handlers()` 将 3 个事件处理器注册到 `trigger_scheduler`
- `ai_consumption_settled``handle_consumption_settled`
- `ai_note_created``handle_note_created`
- `ai_task_assigned``handle_task_assigned`
- 业务代码通过 `fire_event("ai_consumption_settled", payload)` 触发
4. **调用链编排**:消费事件触发后的完整链路:
```
消费事件 → App3线索分析→ App8线索整理→ App7客户分析
如有助教参与 → App4关系分析→ App5话术参考
```
5. **容错策略**`dispatcher.py` 文档字符串明确说明:
- "某步失败记录错误日志,后续应用使用已有缓存继续"
- "失败应用写入失败 conversation 记录"
- "整条链后台异步执行,不阻塞业务请求"
### 证据
`dispatcher.py` 中的消费事件处理:
```python
async def handle_consumption_event(
self,
member_id: int,
site_id: int,
settle_id: int,
assistant_id: int | None = None,
) -> None:
"""消费事件链App3 → App8 → App7+ App4 → App5 如有助教)。"""
# 步骤 1App3 线索分析
app3_result = await self._run_step("app3_clue", app3_run, context)
# 步骤 2App8 线索整理
# 步骤 3App7 客户分析
# 步骤 4可选App4 → App5
```
`main.py` 中的 AI 事件处理器注册:
```python
_dispatcher = AIDispatcher(_bailian, AICacheService(), ConversationService())
register_ai_handlers(_dispatcher)
```
`_create_ai_event_handlers()` 中的事件映射:
```python
return {
"ai_consumption_settled": handle_consumption_settled,
"ai_note_created": handle_note_created,
"ai_task_assigned": handle_task_assigned,
}
```
P5 spec 调用链定义:
> 消费事件(结账单): └→ 应用 3维客线索分析→ 应用 8线索整理→ 应用 7客户分析