fix(backend): Resolve PgBoss infinite loop issue and cleanup unused files

Backend fixes:
- Fix PgBoss task infinite loop on SAE (root cause: missing queue table constraints)
- Add singletonKey to prevent duplicate job enqueueing
- Add idempotency check in reviewWorker (skip completed tasks)
- Add optimistic locking in reviewService (atomic status update)

Frontend fixes:
- Add isSubmitting state to prevent duplicate submissions in RVW Dashboard
- Fix API baseURL in knowledgeBaseApi (relative path)

Cleanup (removed):
- Old frontend/ directory (migrated to frontend-v2)
- python-microservice/ (unused, replaced by extraction_service)
- Root package.json and node_modules (accidentally created)
- redcap-docker-dev/ (external dependency)
- Various temporary files and outdated docs in root

New documentation:
- docs/07-运维文档/01-PgBoss队列监控与维护.md
- docs/07-运维文档/02-故障预防检查清单.md
- docs/07-运维文档/03-数据库迁移注意事项.md

Database fix applied to RDS:
- Added PRIMARY KEY to platform_schema.queue
- Added 3 missing foreign key constraints

Tested: Local build passed, RDS constraints verified
This commit is contained in:
2026-01-27 18:16:22 +08:00
parent 2481b786d8
commit bbf98c4d5c
214 changed files with 4318 additions and 44920 deletions

View File

@@ -307,10 +307,6 @@ Level 3: 兜底Prompt缓存也失效

View File

@@ -1 +1,560 @@
# ADMIN-运营管理端 - 模块当前状态与开发指南
> **最后更新:** 2026-01-25
> **状态:** ✅ Phase 4.2 运营监控系统MVP完成登录跳转逻辑优化完成
> **版本:** v0.6 (Alpha)
---
## 🎯 一句话总结
**运营管理端是AI临床研究平台的核心管理后台提供多租户管理、Prompt工程化调试、用户权限配置等运营能力。**
---
## 📊 当前开发状态
### ✅ 已完成2026-01-11
**Phase 0-3基础架构**
- [x] 数据库 Schema 设计platform_schema, capability_schema
- [x] JWT 认证系统(`backend/src/common/auth/`
- [x] 登录/登出功能(前后端完整实现)
- [x] 认证中间件Fastify
- [x] 前端认证对接AuthContext, LoginPage
- [x] 测试用户创建8个角色用户
**Phase 3.5.1Prompt 基础设施**
- [x] 创建 capability_schema
- [x] 添加 prompt_templates 和 prompt_versions 表
- [x] 添加 prompt:* 权限view/edit/debug/publish
- [x] 迁移 RVW Prompt 到数据库2个EDITORIAL, METHODOLOGY
**Phase 3.5.2PromptService 核心**
- [x] 灰度预览逻辑DRAFT/ACTIVE 分发)
- [x] 模块级调试控制setDebugMode
- [x] Handlebars 模板渲染
- [x] 变量提取与校验extractVariables, validateVariables
- [x] 三级容灾(数据库→缓存→兜底)
- [x] 兜底 Prompthardcoded fallbacks
**Phase 3.5.3:管理 API**
- [x] 8个 RESTful 接口(列表、详情、保存、发布、回滚、调试、测试渲染、清缓存)
- [x] 路由注册(`/api/admin/prompts`
**Phase 3.5.4:前端管理界面**
- [x] 管理端基础架构AdminLayout, OrgLayout, 路由)
- [x] 头像下拉菜单切换入口
- [x] PromptListPage筛选、搜索、调试开关
- [x] PromptEditorCodeMirror 6 简化版,中文友好)
- [x] PromptEditorPage编辑、保存、发布、测试、版本历史
**Phase 3.5.5RVW 模块集成** ✅ 已完成2026-01-12
- [x] RVW editorialService 集成 PromptService
- [x] RVW methodologyService 集成 PromptService
- [x] RVW reviewWorker 传递 userId
- [x] 修复 ReviewTask 外键约束问题(跨 schema 外键)
- [x] 全模块认证规范化RVW, PKB, ASL, DC
**Phase 4.0:租户与模块管理** ✅ 已完成2026-01-12
- [x] 新增 modules 表(动态模块管理)
- [x] ModuleService多租户模块权限合并
- [x] requireModule 中间件(模块访问控制)
- [x] 所有业务模块添加 requireModule 检查
- [x] 租户管理后端 APICRUD + 模块配置)
- [x] 租户管理前端界面(列表、详情、编辑、模块配置)
- [x] 前端模块权限动态过滤(首页 + 导航)
- [x] Prompt 界面优化(模块中文显示、版本历史增强)
**Phase 4.1:用户管理** ✅ 已完成2026-01-16🎉
- [x] 数据库:新增 user_modules 表(精细化模块权限)
- [x] 权限系统:新增 4 个用户权限view/create/edit/delete
- [x] UserServiceCRUD + 租户隔离 + 模块权限管理780 行)
- [x] UserController + UserRoutes13 个 API 端点648 行)
- [x] 批量导入Excel 批量导入用户功能
- [x] UserListPage列表+筛选+搜索+分页412 行)
- [x] UserFormPage创建/编辑+租户配置+模块权限341 行)
- [x] UserDetailPage详情+租户管理+模块权限查看393 行)
- [x] 3 个弹窗组件导入、分配租户、模块权限配置592 行)
- [x] **架构升级:** 模块权限系统改造(版本系统 → 模块代码系统)
**架构重大升级:模块权限系统** ✅ 已完成2026-01-16🏆
- [x] 后端登录API返回用户可访问模块列表`modules: ['PKB', 'RVW']`
- [x] 后端getUserModules() 方法(智能计算用户+租户模块权限)
- [x] 前端AuthContext 添加 hasModule() 方法
- [x] 前端:导航栏基于模块权限过滤显示(只显示可访问模块)
- [x] 前端RouteGuard 基于 moduleCode 检查权限
- [x] 前端:移除旧的 requiredVersion 系统
- [x] 体验优化登录跳转智能判断避免普通用户跳转到管理端403
**Phase 4.2:运营监控系统** ✅ 已完成2026-01-25🎉
- [x] 数据库:新增 SimpleLog 运营日志表admin_schema
- [x] 后端服务ActivityService 火烧即忘埋点服务(带 try-catch 保护)
- [x] 后端APIstatsRoutes 统计接口overview/live-feed/user-overview/cleanup
- [x] 模块埋点7个模块埋点全部完成
- SYSTEM登录
- AIA智能体对话
- PKB知识库管理、RAG检索
- ASL文献筛选
- DCTool B提取、Tool C代码处理
- RVW稿件审查
- IITREDCap同步
- [x] 前端看板Admin Dashboard 运营数据展示DAU/DAT/模块统计/实时活动流)
- [x] 权限控制stats:view 权限检查
**Phase 4.3:登录体验优化** ✅ 已完成2026-01-25
- [x] 修复用户模块权限显示问题userService.ts 逻辑修正)
- [x] 修复登录后默认进入AI问答页面/ai-qa而非首页
- [x] 优化:顶部导航 LOGO 更换为品牌图标
- [x] 修复SUPER_ADMIN 用户模块权限返回完整列表
- [x] 修复LoginPage 路径映射与 moduleRegistry 一致
**Phase 4.4PKB 布局修复** ✅ 已完成2026-01-25
- [x] 修复PKB 工作区问答页面布局问题CSS类名冲突
- [x] 修复Protocol Agent 模块 CSS 类名重命名(.pa-chat-container
### ⏳ 待开发(按优先级)
**P2 - 用户管理增强(可选)**
- [ ] 用户批量操作(批量禁用、批量分配租户)
- [ ] 用户操作日志audit_logs 集成)
- [ ] 用户统计分析(活跃度、模块使用率)
**P2 - Prompt 管理优化**
- [ ] Prompt 版本对比功能
- [ ] Prompt 批量操作
- [ ] Prompt 导入/导出
**P2 - 租户高级功能**
- [ ] 品牌定制配置logo、主题色
- [ ] 租户专属登录页
- [ ] 配额管理界面
---
## 🗄️ 数据库状态
### 已有表(需要整合)
```sql
-- 现有的用户表(需要统一)
public.users -- 旧的用户表
platform_schema.User -- 新的用户表Prisma
-- 现有的审计表
public.AdminLog -- 旧的审计日志
```
### ✅ 已创建的表2026-01-12
**platform_schema平台基础**
-`users` - 用户表(含 phone, password, role, is_default_password
-`tenants` - 租户表(含 PUBLIC 类型)
-`tenant_members` - 租户成员(支持用户加入多个租户)
-`tenant_modules` - 租户订阅模块(控制租户可访问的功能)
-`tenant_quotas` - 租户配额
-`tenant_quota_allocations` - 配额分配
-`departments` - 科室表
-`permissions` - 权限表(含 prompt:*/tenant:* 权限)
-`role_permissions` - 角色权限
-`verification_codes` - 验证码表
-`modules` - 系统模块表(动态管理可用模块)🆕 2026-01-12
**capability_schema通用能力** ✅ 新增
-`prompt_templates` - Prompt模板
-`prompt_versions` - Prompt版本
**admin_schema运营管理** ✅ 新增 2026-01-25
-`simple_logs` - 极简运营日志表MVP🆕
- `admin_operation_logs` - 运营操作日志(未来)
---
## 🏗️ 架构概览
```
┌─────────────────────────────────────────────────┐
│ 运营管理端ADMIN Portal
├─────────────────────────────────────────────────┤
│ 🏢 租户管理 │ 👤 用户管理 │ 🎨 Prompt管理 │
│ 📊 配额管理 │ 🔐 权限配置 │ 📋 审计日志 │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Platform Layer (平台层) │
├─────────────────────────────────────────────────┤
│ 认证中心 │ 权限中心 │ 存储服务 │ 通知服务 │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Capability Layer (能力层) │
├─────────────────────────────────────────────────┤
│ Prompt管理 │ LLM Gateway │ 文档引擎 │ RAG引擎 │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Business Modules (业务模块) │
├─────────────────────────────────────────────────┤
│ ASL │ DC │ IIT │ PKB │ AIA │ RVW │ SSA │ ST │
└─────────────────────────────────────────────────┘
```
---
## 🔐 角色与权限矩阵
| 功能模块 | SUPER_ADMIN | PROMPT_ENGINEER | HOSPITAL_ADMIN | PHARMA_ADMIN | USER |
|---------|-------------|-----------------|----------------|--------------|------|
| 租户管理 | ✅ 全部 | ❌ | ❌ | ❌ | ❌ |
| Prompt管理 | ✅ 全部 | ✅ 全部 | ❌ | ❌ | ❌ |
| 用户管理(全局) | ✅ | ❌ | ❌ | ❌ | ❌ |
| 用户管理(租户内) | ✅ | ❌ | ✅ | ✅ | ❌ |
| 配额分配 | ✅ | ❌ | ✅ | ✅ | ❌ |
| 审计日志(全局) | ✅ | ❌ | ❌ | ❌ | ❌ |
| 审计日志(租户内) | ✅ | ❌ | ✅ | ✅ | ❌ |
| 业务模块使用 | ✅ | ✅ | ✅ | ✅ | ✅ |
---
## 📁 代码结构
### ✅ 实际已完成的结构2026-01-12
**后端**
```
backend/src/
├── common/
│ ├── auth/ # ✅ 认证模块
│ │ ├── jwt.service.ts # JWT Token管理
│ │ ├── auth.service.ts # 业务逻辑
│ │ ├── auth.middleware.ts # 认证中间件 + requireModule 🆕
│ │ ├── module.service.ts # 🆕 模块权限服务(多租户合并)
│ │ ├── auth.controller.ts # API控制器 + getUserModules 🆕
│ │ ├── auth.routes.ts # 路由
│ │ └── index.ts
│ │
│ └── prompt/ # ✅ Prompt管理
│ ├── prompt.types.ts # 类型定义
│ ├── prompt.service.ts # 核心服务
│ ├── prompt.controller.ts # API控制器增强版本返回🆕
│ ├── prompt.routes.ts # 路由
│ ├── prompt.fallbacks.ts # 兜底Prompt
│ └── index.ts
├── modules/
│ ├── admin/ # 🆕 租户管理模块
│ │ ├── types/
│ │ │ └── tenant.types.ts # 租户类型定义
│ │ ├── services/
│ │ │ └── tenantService.ts # 租户业务逻辑
│ │ ├── controllers/
│ │ │ └── tenantController.ts # 租户控制器
│ │ └── routes/
│ │ └── tenantRoutes.ts # 租户路由
│ │
│ ├── rvw/ # ✅ RVW模块已集成PromptService
│ ├── pkb/ # ✅ PKB模块已添加认证
│ ├── asl/ # ✅ ASL模块已添加认证
│ └── dc/ # ✅ DC模块已添加认证
backend/scripts/
├── seed-modules.js # 🆕 模块数据初始化
├── query-users.js # 查询用户和租户信息
└── [其他脚本]
```
**前端**
```
frontend-v2/src/
├── framework/
│ ├── auth/ # ✅ 认证框架
│ │ ├── AuthContext.tsx # 认证上下文
│ │ ├── api.ts # 认证API
│ │ ├── moduleApi.ts # 🆕 用户模块权限API
│ │ └── types.ts
│ │
│ ├── modules/ # ✅ 模块注册
│ │ ├── moduleRegistry.ts # 模块注册新增moduleCode🆕
│ │ └── types.ts # 模块类型定义
│ │
│ └── layout/ # ✅ 布局组件
│ ├── MainLayout.tsx # 业务端布局
│ ├── AdminLayout.tsx # 运营管理端布局
│ ├── OrgLayout.tsx # 机构管理端布局
│ └── TopNavigation.tsx # 顶部导航(模块权限过滤)🆕
├── pages/
│ ├── HomePage.tsx # 首页(模块权限过滤)🆕
│ ├── admin/ # ✅ 运营管理端页面
│ │ ├── AdminDashboard.tsx # 概览页
│ │ ├── PromptListPage.tsx # Prompt列表模块中文显示🆕
│ │ ├── PromptEditorPage.tsx # Prompt编辑版本历史增强🆕
│ │ ├── tenants/ # 🆕 租户管理页面
│ │ │ ├── TenantListPage.tsx # 租户列表
│ │ │ ├── TenantDetailPage.tsx # 租户详情/编辑/模块配置
│ │ │ └── api/
│ │ │ └── tenantApi.ts # 租户API调用
│ │ ├── PromptListPage.tsx # ✅ Prompt列表254行
│ │ ├── PromptEditorPage.tsx # ✅ Prompt编辑器399行
│ │ ├── components/
│ │ │ └── PromptEditor.tsx # ✅ CodeMirror 6245行
│ │ └── api/
│ │ └── promptApi.ts # ✅ API调用层172行
│ │
│ ├── org/ # ✅ 机构管理端页面
│ │ └── OrgDashboard.tsx # 概览页
│ │
│ └── LoginPage.tsx # ✅ 通用登录页368行
```
### 📋 原计划结构(待开发)
### 后端
```
backend/src/
├── modules/
│ └── admin/ # 运营管理端模块
│ ├── controllers/
│ │ ├── tenant.controller.ts
│ │ ├── user.controller.ts
│ │ └── audit.controller.ts
│ ├── services/
│ │ ├── tenant.service.ts
│ │ ├── user.service.ts
│ │ └── audit.service.ts
│ └── routes/
│ └── admin.routes.ts
├── common/
│ ├── capabilities/
│ │ └── prompt/ # Prompt管理系统
│ │ ├── prompt.service.ts # 核心逻辑
│ │ ├── prompt.controller.ts
│ │ └── prompt.routes.ts
│ │
│ └── middleware/
│ ├── auth.middleware.ts # JWT认证
│ ├── permission.middleware.ts # 权限检查
│ └── tenant.middleware.ts # 租户隔离
└── platform/
├── auth/
│ ├── auth.service.ts
│ └── jwt.service.ts
└── permission/
└── permission.service.ts
```
### 前端
```
frontend-v2/src/
├── modules/
│ └── admin/ # 运营管理端模块
│ ├── pages/
│ │ ├── TenantManagement/ # 租户管理
│ │ ├── UserManagement/ # 用户管理
│ │ ├── PromptManagement/ # Prompt管理
│ │ └── AuditLog/ # 审计日志
│ │
│ ├── components/
│ │ ├── TenantForm/
│ │ ├── UserForm/
│ │ ├── PromptEditor/
│ │ └── PromptDebugSwitch/ # 全局调试开关
│ │
│ └── services/
│ ├── tenant.service.ts
│ ├── user.service.ts
│ └── prompt.service.ts
└── framework/
├── auth/
│ └── AuthContext.tsx # 认证上下文
└── permission/
└── PermissionContext.tsx # 权限上下文
```
---
## 🚀 快速开始开发
### 1. 环境准备
```bash
# 后端
cd backend
npm install jsonwebtoken bcryptjs handlebars
npm install -D @types/jsonwebtoken @types/bcryptjs
# 前端
cd frontend-v2
# 无需额外依赖,使用现有技术栈
```
### 2. 数据库准备
```bash
# 1. 备份现有数据
cd backend
npx prisma db pull --schema=./prisma/backup.prisma
# 2. 更新Schema
# 编辑 prisma/schema.prisma添加新表
# 3. 生成迁移
npx prisma migrate dev --name add_admin_and_prompt_tables
# 4. 运行种子数据
npx prisma db seed
```
### 3. 开发优先级
**🔴 必须先做Phase 0**
1. 数据库迁移统一User表
2. 创建超级管理员账号
3. JWT认证系统
**🟠 然后做Phase 1**
1. PromptService实现
2. Prompt管理API
**🟡 最后做Phase 2**
1. 租户管理界面
2. Prompt管理界面
---
## 📚 核心文档导航
### 必读文档(开发前)
1. **架构梳理**
`00-系统设计/00-权限与角色体系梳理报告_v1.0.md`
→ 了解整体架构、数据库设计、实施路线图
2. **需求文档**
`01-需求分析/02-通用能力层_07-运营与机构管理端PRD_v2.1.md`
→ 了解业务需求、用户故事、验收标准
3. **Prompt管理核心**
`02-技术设计/03-Prompt管理系统快速参考.md`
→ 了解Prompt管理的实现细节
### 开发中参考
1. **技术设计**
`02-技术设计/02-通用能力层_03-Prompt管理系统与灰度预览设计方案.md`
2. **反馈建议**
`00-系统设计/02-通用能力层_10-权限体系梳理反馈与修正建议.md`
---
## 🔧 技术要点
### 1. JWT认证
```typescript
// 生成Token
const token = jwt.sign(
{
userId: user.id,
role: user.role,
tenantId: user.tenantId // 多租户
},
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
// 验证Token
const decoded = jwt.verify(token, process.env.JWT_SECRET);
```
### 2. 多租户隔离
```typescript
// 中间件自动注入tenantId
fastify.addHook('preHandler', async (request, reply) => {
const user = request.user;
request.tenantId = user.tenantId;
});
// ORM查询自动过滤
const projects = await prisma.project.findMany({
where: { tenantId: request.tenantId }
});
```
### 3. Prompt灰度预览
```typescript
// 核心逻辑
async get(code: string, variables: any, userId: string) {
// 调试者看DRAFT版本
if (this.debugUsers.has(userId)) {
const draft = await this.getDraftVersion(code);
if (draft) return this.render(draft.content, variables);
}
// 普通用户看ACTIVE版本带缓存
const active = await this.getActiveVersion(code);
return this.render(active.content, variables);
}
```
---
## ⚠️ 常见问题
### Q1: 现有的`public.users`表怎么处理?
**A:** Phase 0会执行数据迁移
1.`public.users`数据迁移到`platform_schema.users`
2. 重命名为`public.users_backup`保留1周
3. 验证无误后删除
### Q2: Prompt管理会影响现有业务模块吗
**A:** 不会。Prompt管理是增量功能
- 现有硬编码Prompt继续工作
- 新开发模块调用`promptService.get()`
- 老模块可逐步迁移
### Q3: 调试模式安全吗?
**A:** 是的,有多层保障:
- 权限检查(`prompt:debug`
- 状态存储在内存(登出自动失效)
- 审计日志记录所有操作
### Q4: 多租户隔离如何保证?
**A:** 三层防护:
1. **API层**:中间件检查`tenantId`
2. **Service层**:自动注入`tenantId`过滤
3. **DB层**Phase 2Prisma Extension强制隔离
---
## 📞 需要帮助?
1. **查看文档**`README.md` 和各技术设计文档
2. **查看代码**参考DC/ASL等已有模块的实现
3. **提问**:在开发记录中记录问题和解决方案
---
## 📅 下一步行动
- [ ] Review架构设计文档
- [ ] 确认开发排期建议4周
- [ ] 准备开发环境
- [ ] **启动Phase 0**:数据库迁移
---
*祝开发顺利!🚀*

View File

@@ -0,0 +1,735 @@
# 运营监控系统 MVP 开发计划
> **文档版本**V3.1 (完整版)
> **创建日期**2026-01-25
> **基于文档**:运营体系设计方案-MVP-V3.0.md
> **预计工时**4-5 小时
---
## 📋 修订说明
本计划基于 V3.0 方案进行审查修订,主要解决以下 **8 个问题**
| # | 问题 | 严重程度 | 修订内容 |
|---|------|---------|---------|
| 1 | 模块覆盖不完整 | 🔴 严重 | 补充 RVW、IIT、Protocol Agent、SSA/ST 预留 |
| 2 | 缺少 tenantName 字段 | 🔴 严重 | 添加冗余字段避免 JOIN |
| 3 | RVW 埋点清单缺失 | 🔴 严重 | 新增 RVW 模块埋点清单 |
| 4 | 用户360画像缺少 RVW | 🔴 严重 | 补充 RVW 资产统计 |
| 5 | action 类型不够全面 | 🟡 中等 | 扩展 CREATE/DELETE 类型 |
| 6 | 缺少 API 路由设计 | 🟡 中等 | 新增完整 API 端点设计 |
| 7 | 数据保留策略缺失 | 🟡 中等 | 补充 180 天数据清理 |
| 8 | 权限控制未说明 | 🟡 中等 | 明确角色权限矩阵 |
---
## 1. 核心指标定义(保持 V3.0
| 优先级 | 指标名称 | 定义 | 价值 |
|--------|---------|------|-----|
| **P0+** | 活跃医生数 (DAU) | 今日有行为的去重 user_id 数 | 真实价值线 |
| **P0** | 活跃租户数 (DAT) | 今日有行为的去重 tenant_id 数 | 商务生死线 |
| **P1** | 功能渗透率 | 各模块/功能使用次数分布 | 产品迭代指引 |
| **P2** | 价值交付次数 | 导出/下载次数 | 北极星指标 |
---
## 2. 数据库设计V3.1 修订版)
### 2.1 SimpleLog 表admin_schema
```prisma
/// 运营日志表 (MVP V3.1)
model SimpleLog {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
// === 租户和用户信息 ===
tenantId String @map("tenant_id") @db.VarChar(50)
tenantName String? @map("tenant_name") @db.VarChar(100) // 🆕 冗余字段避免JOIN
userId String @map("user_id") @db.Uuid
userName String? @map("user_name") @db.VarChar(50)
// === 行为记录 ===
module String @db.VarChar(20) // 模块代码
feature String @db.VarChar(50) // 细分功能
action String @db.VarChar(20) // 动作类型
// === 详情信息 ===
info String? @db.Text // JSON或文本详情
// === 索引 ===
@@index([createdAt])
@@index([tenantId])
@@index([userId])
@@index([module, feature])
@@index([action]) // 🆕 支持按动作筛选
@@map("simple_logs")
@@schema("admin_schema")
}
```
### 2.2 字段说明
#### module模块代码- 完整列表
```typescript
type ModuleCode =
| 'AIA' // AI智能问答 (12智能体 + Protocol Agent)
| 'PKB' // 个人知识库
| 'ASL' // AI智能文献
| 'DC' // 数据清洗整理
| 'RVW' // 稿件审查系统 🆕
| 'IIT' // IIT Manager Agent 🆕
| 'SSA' // 智能统计分析 (预留) 🆕
| 'ST' // 统计分析工具 (预留) 🆕
| 'SYSTEM'; // 系统级行为 (登录/登出)
```
#### action动作类型
```typescript
type ActionType =
| 'LOGIN' // 登录系统
| 'USE' // 使用功能
| 'EXPORT' // 导出/下载
| 'CREATE' // 创建资源 🆕
| 'DELETE' // 删除资源 🆕
| 'ERROR'; // 错误记录
```
---
## 3. 完整埋点清单(按模块)
### 3.1 🤖 AIA 模块AI智能问答
#### 12 个智能体
| agentId | feature (中文) | 埋点位置 |
|---------|---------------|---------|
| topic-scoping | 科学问题梳理 | conversationService.complete() |
| pico-analysis | PICO梳理 | conversationService.complete() |
| topic-eval | 选题评价 | conversationService.complete() |
| outcome-design | 观察指标设计 | conversationService.complete() |
| crf-design | CRF设计 | conversationService.complete() |
| sample-size | 样本量计算 | conversationService.complete() |
| protocol-writing | 方案撰写 | conversationService.complete() |
| methodology-review | 方法学评审 | conversationService.complete() |
| paper-polish | 论文润色 | conversationService.complete() |
| paper-translate | 论文翻译 | conversationService.complete() |
| data-preprocess | 数据预处理 | 跳转DC记录来源 |
| stat-analysis | 统计分析 | 跳转DC记录来源 |
#### Protocol Agent🆕 2026-01-25 新功能)
| feature | action | 埋点位置 | info 示例 |
|---------|--------|---------|----------|
| Protocol要素收集 | USE | ProtocolOrchestrator.collectPhase() | "阶段1完成" |
| Protocol方案生成 | USE | ProtocolOrchestrator.generateProtocol() | "生成12章节方案" |
| Protocol Word导出 | EXPORT | ProtocolAgentController.exportWord() | "导出Word文档" |
**埋点代码位置**
- `backend/src/modules/agent/protocol/services/ProtocolOrchestrator.ts`
- `backend/src/modules/agent/protocol/controllers/ProtocolAgentController.ts`
---
### 3.2 📚 PKB 模块(个人知识库)
| feature | action | 埋点位置 | info 示例 |
|---------|--------|---------|----------|
| 知识库创建 | CREATE | knowledgeBaseController.create() | "创建: 肺癌研究库" |
| 文档上传 | USE | documentController.upload() | "上传: 5篇PDF" |
| RAG问答 | USE | ragController.chat() | "提问: 入排标准是什么?" |
| 批处理提取 | USE | batchController.process() | "批量提取: 10篇" |
| 结果导出 | EXPORT | batchController.export() | "导出CSV" |
**埋点代码位置**
- `backend/src/modules/pkb/controllers/`
---
### 3.3 📖 ASL 模块AI智能文献
| feature | action | 埋点位置 | info 示例 |
|---------|--------|---------|----------|
| DeepSearch检索 | USE | researchController.stream() | "关键词: 肺癌治疗" |
| 标题摘要筛选 | USE | screeningController.start() | "筛选: 500篇" |
| 全文复筛 | USE | fullTextController.start() | "复筛: 100篇" |
| 筛选结果导出 | EXPORT | screeningController.export() | "导出Excel" |
**埋点代码位置**
- `backend/src/modules/asl/controllers/`
---
### 3.4 🧹 DC 模块(数据清洗整理)
| feature | action | 埋点位置 | info 示例 |
|---------|--------|---------|----------|
| Tool B 健康检查 | USE | toolBController.healthCheck() | "检查: 1000行数据" |
| Tool B 自动提取 | USE | toolBController.extract() | "提取任务: 50条" |
| Tool C 数据清洗 | USE | toolCController.process() | "执行: 筛选操作" |
| Tool C Pivot | USE | toolCController.pivot() | "Pivot转换" |
| 结果导出 | EXPORT | toolCController.export() | "导出Excel" |
**埋点代码位置**
- `backend/src/modules/dc/controllers/`
---
### 3.5 📝 RVW 模块(稿件审查系统)🆕
| feature | action | 埋点位置 | info 示例 |
|---------|--------|---------|----------|
| 稿件上传 | USE | reviewController.upload() | "上传: xxx.pdf" |
| 稿约规范性审查 | USE | reviewWorker (editorial) | "审查开始" |
| 方法学审查 | USE | reviewWorker (methodology) | "方法学审查开始" |
| 审查完成 | USE | reviewWorker.complete() | "评分: 规范85/方法78" |
| 报告导出 | EXPORT | TaskDetail.exportWord() | "导出Word报告" |
**埋点代码位置**
- `backend/src/modules/rvw/services/reviewWorker.ts`
- `backend/src/modules/rvw/controllers/reviewController.ts`
---
### 3.6 🏥 IIT 模块IIT Manager Agent🆕
| feature | action | 埋点位置 | info 示例 |
|---------|--------|---------|----------|
| REDCap数据同步 | USE | redcapAdapter.sync() | "同步: 10条记录" |
| AI质控检查 | USE | qualityCheckService.check() | "检查患者ID 7" |
| 企微通知推送 | USE | wechatService.notify() | "推送预警通知" |
| 对话查询 | USE | chatService.query() | "查询患者统计" |
| 人工确权 | USE | actionController.approve() | "确权: 排除患者" |
**埋点代码位置**
- `backend/src/modules/iit-manager/services/`
- `backend/src/modules/iit-manager/controllers/`
---
### 3.7 🔐 SYSTEM系统级
| feature | action | 埋点位置 | info 示例 |
|---------|--------|---------|----------|
| 用户登录 | LOGIN | authController.login() | "密码登录" |
| 用户登出 | USE | authController.logout() | - |
**埋点代码位置**
- `backend/src/common/auth/auth.controller.ts`
---
## 4. 后端 API 设计
### 4.1 运营统计 API
| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/api/admin/stats/overview` | 今日大盘DAU/DAT/导出数) | SUPER_ADMIN |
| GET | `/api/admin/stats/live-feed` | 实时流水账最近100条 | SUPER_ADMIN |
| GET | `/api/admin/stats/module/:code` | 模块使用统计 | SUPER_ADMIN |
| GET | `/api/admin/users/:id/overview` | 用户360画像 | SUPER_ADMIN |
### 4.2 API 响应示例
#### 今日大盘 `/api/admin/stats/overview`
```json
{
"success": true,
"data": {
"dau": 12, // 今日活跃医生数
"dat": 3, // 今日活跃租户数
"exportCount": 5, // 今日导出次数
"moduleStats": {
"AIA": 45,
"PKB": 23,
"DC": 12,
"RVW": 8,
"ASL": 5,
"IIT": 3
}
}
}
```
#### 实时流水账 `/api/admin/stats/live-feed`
```json
{
"success": true,
"data": [
{
"id": "uuid",
"createdAt": "2026-01-25T10:05:00Z",
"tenantName": "协和医院",
"userName": "张主任",
"module": "AIA",
"feature": "选题评价",
"action": "USE",
"info": "评价得分: 85分"
}
]
}
```
#### 用户360画像 `/api/admin/users/:id/overview`
```json
{
"success": true,
"data": {
"profile": {
"id": "uuid",
"name": "张主任",
"phone": "138****1234",
"tenantName": "协和医院"
},
"assets": {
"aia": { "conversationCount": 158 },
"pkb": { "kbCount": 3, "docCount": 450 },
"dc": { "taskCount": 12 },
"rvw": { "reviewTaskCount": 25, "completedCount": 20 } // 🆕
},
"activities": [
{
"createdAt": "2026-01-25T10:30:00Z",
"module": "AIA",
"feature": "选题评价",
"action": "USE",
"info": "生成结果: 85分"
}
]
}
}
```
---
## 5. 后端服务实现
### 5.1 ActivityService埋点服务
**文件路径**`backend/src/common/services/activity.service.ts`
```typescript
import { prisma } from '../../config/database.js';
import { logger } from '../logging/index.js';
type ModuleCode = 'AIA' | 'PKB' | 'ASL' | 'DC' | 'RVW' | 'IIT' | 'SSA' | 'ST' | 'SYSTEM';
type ActionType = 'LOGIN' | 'USE' | 'EXPORT' | 'CREATE' | 'DELETE' | 'ERROR';
export const activityService = {
/**
* 核心埋点方法 (Fire-and-Forget 模式)
* 异步执行,不阻塞主业务
*/
log(
tenantId: string,
tenantName: string, // 🆕 新增
userId: string,
userName: string,
module: ModuleCode,
feature: string,
action: ActionType,
info?: any
) {
// 异步执行,不要 await
prisma.simpleLog.create({
data: {
tenantId,
tenantName, // 🆕
userId,
userName,
module,
feature,
action,
info: typeof info === 'object' ? JSON.stringify(info) : String(info || ''),
}
}).catch(e => {
logger.warn('埋点写入失败(可忽略)', { error: e.message });
});
},
/**
* 获取今日核心大盘数据
*/
async getTodayOverview() {
const todayStart = new Date();
todayStart.setHours(0, 0, 0, 0);
const stats = await prisma.$queryRaw`
SELECT
COUNT(DISTINCT user_id) as dau,
COUNT(DISTINCT tenant_id) as dat,
COUNT(CASE WHEN action = 'EXPORT' THEN 1 END) as export_count
FROM admin_schema.simple_logs
WHERE created_at >= ${todayStart}
` as any[];
// 模块使用统计
const moduleStats = await prisma.$queryRaw`
SELECT module, COUNT(*) as count
FROM admin_schema.simple_logs
WHERE created_at >= ${todayStart}
GROUP BY module
` as any[];
const moduleMap: Record<string, number> = {};
moduleStats.forEach((m: any) => {
moduleMap[m.module] = Number(m.count);
});
return {
dau: Number(stats[0]?.dau || 0),
dat: Number(stats[0]?.dat || 0),
exportCount: Number(stats[0]?.export_count || 0),
moduleStats: moduleMap,
};
},
/**
* 获取实时流水账
*/
async getLiveFeed(limit = 100) {
return prisma.simpleLog.findMany({
orderBy: { createdAt: 'desc' },
take: limit,
select: {
id: true,
createdAt: true,
tenantName: true,
userName: true,
module: true,
feature: true,
action: true,
info: true,
}
});
},
/**
* 获取用户360画像
*/
async getUserOverview(userId: string) {
const [user, aiaStats, kbs, dcStats, rvwStats, logs] = await Promise.all([
// 基础信息
prisma.user.findUnique({
where: { id: userId },
include: { tenants: true }
}),
// AIA 资产 (会话数)
prisma.conversation.count({
where: { userId, deletedAt: null }
}),
// PKB 资产 (知识库数 + 文档数)
prisma.knowledgeBase.findMany({
where: { userId, deletedAt: null },
include: { _count: { select: { documents: true } } }
}),
// DC 资产 (任务数)
prisma.extractionTask.count({ where: { userId } }),
// RVW 资产 (审稿任务数) 🆕
prisma.reviewTask.groupBy({
by: ['status'],
where: { userId },
_count: true,
}),
// 最近行为 (从 SimpleLog 查最近 20 条)
prisma.simpleLog.findMany({
where: { userId },
orderBy: { createdAt: 'desc' },
take: 20,
select: {
createdAt: true,
module: true,
feature: true,
action: true,
info: true,
}
})
]);
const totalDocs = kbs.reduce((sum, kb) => sum + kb._count.documents, 0);
// 计算 RVW 统计
const rvwTotal = rvwStats.reduce((sum, s) => sum + s._count, 0);
const rvwCompleted = rvwStats.find(s => s.status === 'completed')?._count || 0;
return {
profile: user ? {
id: user.id,
name: user.name,
phone: user.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'),
tenantName: user.tenants?.name,
} : null,
assets: {
aia: { conversationCount: aiaStats },
pkb: { kbCount: kbs.length, docCount: totalDocs },
dc: { taskCount: dcStats },
rvw: { reviewTaskCount: rvwTotal, completedCount: rvwCompleted }, // 🆕
},
activities: logs,
};
}
};
```
### 5.2 StatsController统计控制器
**文件路径**`backend/src/modules/admin/controllers/statsController.ts`
```typescript
import type { FastifyRequest, FastifyReply } from 'fastify';
import { activityService } from '../../../common/services/activity.service.js';
/**
* 获取今日大盘
* GET /api/admin/stats/overview
*/
export async function getOverview(request: FastifyRequest, reply: FastifyReply) {
const data = await activityService.getTodayOverview();
return reply.send({ success: true, data });
}
/**
* 获取实时流水账
* GET /api/admin/stats/live-feed
*/
export async function getLiveFeed(
request: FastifyRequest<{ Querystring: { limit?: number } }>,
reply: FastifyReply
) {
const limit = request.query.limit || 100;
const data = await activityService.getLiveFeed(limit);
return reply.send({ success: true, data });
}
/**
* 获取用户360画像
* GET /api/admin/users/:id/overview
*/
export async function getUserOverview(
request: FastifyRequest<{ Params: { id: string } }>,
reply: FastifyReply
) {
const { id } = request.params;
const data = await activityService.getUserOverview(id);
return reply.send({ success: true, data });
}
```
---
## 6. 前端页面设计
### 6.1 Admin 首页改造
**位置**`frontend-v2/src/pages/admin/AdminDashboard.tsx`
#### 顶部卡片区域
```
┌─────────────────┬─────────────────┬─────────────────┐
│ 今日活跃医生 │ 今日活跃医院 │ 今日价值交付 │
│ 12 👨‍⚕️ │ 3 🏥 │ 5 🟢 │
│ (DAU) │ (DAT) │ (导出次数) │
└─────────────────┴─────────────────┴─────────────────┘
```
#### 实时流水账区域
```
┌──────┬──────┬──────┬──────┬────────────┬──────┬────────────┐
│ 时间 │ 医院 │ 医生 │ 模块 │ 具体功能 │ 动作 │ 详情 │
├──────┼──────┼──────┼──────┼────────────┼──────┼────────────┤
│10:05 │ 协和 │张主任│ AIA │ 选题评价 │🔵USE │评分: 85分 │
│10:03 │ 协和 │张主任│ RVW │ 稿约规范 │🔵USE │审查开始 │
│09:55 │ 华西 │李医生│ DC │ Tool C │🟢EXP │导出 Excel │
└──────┴──────┴──────┴──────┴────────────┴──────┴────────────┘
```
### 6.2 用户详情页增强
**位置**`frontend-v2/src/modules/admin/pages/UserDetailPage.tsx`
#### 资产统计区域
```
┌─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
│ 💬 AIA对话 │ 📚 PKB知识库 │ 📄 上传文献 │ 🧹 DC清洗 │ 📝 RVW审稿 │
│ 158 次 │ 3 个 │ 450 篇 │ 12 次 │ 25 篇 │
└─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
```
#### 行为时间轴
```
• 10:30 [AIA] 使用了 "选题评价" (生成结果: 85分)
• 10:15 [RVW] 完成了 "稿约规范性审查" (评分: 82分) 🆕
• 09:50 [DC] 导出了 Tool C 清洗结果 (Excel)
• 09:48 [SYSTEM] 登录系统
```
---
## 7. 权限控制
### 7.1 角色权限矩阵
| 功能 | SUPER_ADMIN | PROMPT_ENGINEER | HOSPITAL_ADMIN |
|------|-------------|-----------------|----------------|
| 查看全局大盘 | ✅ | ✅(只读) | ❌ |
| 查看实时流水 | ✅ | ✅(只读) | ❌ |
| 查看用户画像 | ✅ | ❌ | 本租户用户 |
| 数据导出 | ✅ | ❌ | ❌ |
### 7.2 数据隔离规则
- **SUPER_ADMIN**:可查看全部租户数据
- **HOSPITAL_ADMIN**:只能查看本租户的用户活动
- **普通用户**:无运营数据访问权限
---
## 8. 数据保留策略
### 8.1 清理规则
- 保留期限:**180 天**
- 清理方式pg-boss 定时任务,每日 03:00 执行
- 清理脚本:
```sql
-- 清理180天前的日志
DELETE FROM admin_schema.simple_logs
WHERE created_at < NOW() - INTERVAL '180 days';
```
### 8.2 定时任务配置
**文件路径**`backend/src/common/jobs/cleanupWorker.ts`
```typescript
import { jobQueue } from './jobQueue.js';
import { prisma } from '../../config/database.js';
import { logger } from '../logging/index.js';
// 注册清理任务
export async function registerCleanupJobs() {
await jobQueue.schedule('cleanup-simple-logs', '0 3 * * *', async () => {
const result = await prisma.$executeRaw`
DELETE FROM admin_schema.simple_logs
WHERE created_at < NOW() - INTERVAL '180 days'
`;
logger.info('运营日志清理完成', { deletedCount: result });
});
}
```
---
## 9. 开发任务清单
### Phase 1: 数据库15分钟
- [ ] 更新 `prisma/schema.prisma`,添加 SimpleLog 模型
- [ ] 执行 `npx prisma db push` 同步数据库
- [ ] 验证表结构和索引
### Phase 2: 后端服务60分钟
- [ ] 创建 `common/services/activity.service.ts`
- [ ] 创建 `modules/admin/controllers/statsController.ts`
- [ ] 创建 `modules/admin/routes/statsRoutes.ts`
- [ ]`index.ts` 注册路由
### Phase 3: 埋点集成90分钟
#### 系统级
- [ ] `auth.controller.ts` - 登录埋点
#### AIA 模块
- [ ] `conversationService.ts` - 12个智能体埋点
- [ ] `ProtocolOrchestrator.ts` - Protocol Agent 埋点
#### PKB 模块
- [ ] `knowledgeBaseController.ts` - 知识库创建埋点
- [ ] `documentController.ts` - 文档上传埋点
- [ ] `ragController.ts` - RAG问答埋点
#### DC 模块
- [ ] `toolBController.ts` - Tool B 埋点
- [ ] `toolCController.ts` - Tool C 埋点
#### RVW 模块 🆕
- [ ] `reviewController.ts` - 上传埋点
- [ ] `reviewWorker.ts` - 审查完成埋点
#### IIT 模块 🆕
- [ ] `chatService.ts` - 对话查询埋点
- [ ] `redcapAdapter.ts` - 同步埋点
### Phase 4: 前端页面90分钟
- [ ] 改造 `AdminDashboard.tsx` - 添加大盘卡片和流水账
- [ ] 改造 `UserDetailPage.tsx` - 添加资产统计和时间轴
- [ ] 创建 `StatsCard.tsx` 组件
- [ ] 创建 `LiveFeed.tsx` 组件
- [ ] 创建 `ActivityTimeline.tsx` 组件
### Phase 5: 数据清理15分钟
- [ ] 创建 `cleanupWorker.ts`
- [ ] 注册定时任务
- [ ] 测试清理逻辑
---
## 10. 测试验证
### 10.1 单元测试
```bash
# 埋点服务测试
npm test -- --grep "ActivityService"
# API 测试
npm test -- --grep "Stats API"
```
### 10.2 端到端验证
1. 登录系统,检查是否记录 LOGIN
2. 使用 AIA 智能体,检查是否记录 USE
3. 导出文件,检查是否记录 EXPORT
4. 访问 Admin 首页,验证大盘数据
5. 访问用户详情,验证 360 画像
---
## 📊 总结
| 项目 | V3.0 原方案 | V3.1 修订版 |
|------|------------|------------|
| 模块覆盖 | 4 个 | **8 个** |
| 字段设计 | 缺少 tenantName | ✅ 完整 |
| API 设计 | 缺失 | ✅ 4 个端点 |
| 数据保留 | 缺失 | ✅ 180 天 |
| 权限控制 | 缺失 | ✅ 角色矩阵 |
| 预计工时 | 3-4 小时 | **4-5 小时** |
---
**下一步**:按照任务清单执行开发,优先完成 Phase 1-2基础设施再逐步完成埋点集成和前端页面。

View File

@@ -0,0 +1,333 @@
# 运营监控系统 MVP 实施记录
> **文档版本**V1.0
> **实施日期**2026-01-25
> **基于文档**03-运营监控系统MVP开发计划.md
> **实施状态**:✅ **MVP 完成!**
---
## 📋 实施概要
### 完成状态
| 任务类型 | 计划 | 完成 | 完成率 |
|---------|------|------|--------|
| 数据库设计 | 1 | 1 | ✅ 100% |
| 后端服务 | 3 | 3 | ✅ 100% |
| 埋点集成 | 7模块 | 7模块 | ✅ 100% |
| 前端看板 | 1 | 1 | ✅ 100% |
| API测试 | 4端点 | 4端点 | ✅ 100% |
**总耗时**:约 6 小时(含调试和问题修复)
---
## 1. 数据库实施 ✅
### 1.1 SimpleLog 表创建
**Prisma Schema 位置**`backend/prisma/schema.prisma`
```prisma
/// 极简运营日志表 (MVP) - V3.1 修订版
model SimpleLog {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
createdAt DateTime @default(now()) @map("created_at")
tenantId String @map("tenant_id") @db.VarChar(50)
tenantName String? @map("tenant_name") @db.VarChar(100)
userId String @map("user_id") @db.Uuid
userName String? @map("user_name") @db.VarChar(50)
module String @db.VarChar(20)
feature String @db.VarChar(50)
action String @db.VarChar(20)
info String? @db.Text
@@index([createdAt])
@@index([tenantId])
@@index([userId])
@@index([module, feature])
@@index([action])
@@map("simple_logs")
@@schema("admin_schema")
}
```
**迁移命令**
```bash
# 由于存在跨 schema 外键约束问题,使用 db push 代替 migrate
npx prisma db push
```
**数据库备份**
- 备份文件:`ai_clinical_research_backup_20260125.sql`
- 备份时间2026-01-25 实施前
- 备份命令:`pg_dump -h localhost -U postgres -F p ai_clinical_research > backup.sql`
---
## 2. 后端服务实施 ✅
### 2.1 ActivityService埋点服务
**文件位置**`backend/src/common/services/activity.service.ts`
**核心特性**
- ✅ 火烧即忘模式Fire-and-Forget
- ✅ 外层 try-catch 保护(永不抛出异常)
- ✅ 自动填充 tenantName 和 userName
- ✅ 静默失败,不影响业务逻辑
**使用示例**
```typescript
import { activityService } from '@/common/services/activity.service';
// 在业务逻辑中添加埋点(不阻塞主流程)
await activityService.log({
userId: user.id,
tenantId: user.tenantId,
module: 'AIA',
feature: '智能体对话',
action: 'MESSAGE_SENT',
info: `对话完成tokens: ${tokens}`,
});
```
### 2.2 StatsController统计控制器
**文件位置**`backend/src/modules/admin/controllers/statsController.ts`
**API 端点**
| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/admin/stats/overview` | GET | 获取 DAU/DAT/模块统计 |
| `/api/admin/stats/live-feed` | GET | 获取最近活动流 |
| `/api/admin/users/:id/overview` | GET | 获取用户360画像 |
| `/api/admin/stats/cleanup` | POST | 清理过期日志180天 |
### 2.3 StatsRoutes路由配置
**文件位置**`backend/src/modules/admin/routes/statsRoutes.ts`
**权限控制**
- 所有端点需要 `stats:view` 权限
- 使用 `authenticate` + `requirePermission` 中间件
---
## 3. 埋点集成实施 ✅
### 3.1 各模块埋点清单
| 模块 | 埋点位置 | action 类型 | 状态 |
|------|---------|------------|------|
| **SYSTEM** | auth.controller.ts | LOGIN | ✅ |
| **AIA** | conversationService.ts | MESSAGE_SENT | ✅ |
| **PKB** | knowledgeBaseService.ts | KB_CREATED, KB_DELETED | ✅ |
| **PKB** | ragService.ts | RAG_SEARCH | ✅ |
| **ASL** | screeningWorker.ts | SCREENING_COMPLETED | ✅ |
| **DC** | extractionWorker.ts (Tool B) | EXTRACTION_COMPLETED | ✅ |
| **DC** | AICodeService.ts (Tool C) | CODE_GENERATE, CODE_EXECUTE | ✅ |
| **RVW** | reviewWorker.ts | REVIEW_COMPLETED | ✅ |
| **IIT** | SyncManager.ts | POLL_STARTED, SYNC_COMPLETED | ✅ |
### 3.2 埋点代码示例
**登录埋点**auth.controller.ts
```typescript
// 登录成功后记录
await activityService.log({
userId: result.user.id,
tenantId: result.user.tenantId,
module: 'SYSTEM',
feature: '用户登录',
action: 'LOGIN',
info: `用户 ${result.user.name} (${result.user.phone}) 登录成功`,
});
```
**AIA 对话埋点**conversationService.ts
```typescript
// 在流式对话完成后记录
await activityService.log({
userId,
tenantId: user.tenantId,
module: 'AIA',
feature: `智能体对话: ${conversation.agentId}`,
action: 'MESSAGE_SENT',
info: `对话 ${conversationId} 消息发送完成tokens: ${aiMessage.tokens}`,
});
```
**PKB 知识库埋点**knowledgeBaseService.ts
```typescript
// 创建知识库
await activityService.log({
userId,
tenantId: user.tenantId,
module: 'PKB',
feature: '知识库管理',
action: 'KB_CREATED',
info: `创建知识库: ${name} (ID: ${knowledgeBase.id})`,
});
```
---
## 4. 前端看板实施 ✅
### 4.1 Admin Dashboard 更新
**文件位置**`frontend-v2/src/pages/admin/AdminDashboard.tsx`
**功能特性**
- ✅ DAU/DAT 实时统计卡片
- ✅ 模块使用分布图表
- ✅ 最近活动实时流
- ✅ 自动刷新(基于 React Query
### 4.2 API 调用层
**文件位置**`frontend-v2/src/modules/admin/api/statsApi.ts`
**API 函数**
```typescript
// 获取运营概览
export const getOverview = async (): Promise<StatsOverview> => {
const response = await apiClient.get('/api/admin/stats/overview');
return response.data.data;
};
// 获取实时活动流
export const getLiveFeed = async (limit?: number): Promise<LiveFeedItem[]> => {
const response = await apiClient.get('/api/admin/stats/live-feed', {
params: { limit },
});
return response.data.data;
};
```
---
## 5. 测试验证 ✅
### 5.1 API 测试
**测试脚本位置**`backend/src/modules/admin/__tests__/test-stats-api.ps1`
**测试结果**
| 测试项 | 结果 |
|--------|------|
| 登录获取 Token | ✅ 通过 |
| GET /overview | ✅ 返回 DAU/DAT |
| GET /live-feed | ✅ 返回活动列表 |
| 用户 360 画像 | ✅ 返回资产统计 |
### 5.2 前端测试
- ✅ 运营管理端 Dashboard 正常显示
- ✅ 实时数据刷新正常
- ✅ 权限控制正常(仅 SUPER_ADMIN 可访问)
---
## 6. 问题与解决
### 6.1 Prisma 迁移失败
**问题**`prisma migrate dev` 报错 P3006shadow database 问题)
**原因**:存在跨 schema 外键约束
**解决**:使用 `prisma db push` 直接推送 schema 变更(仅添加新表,安全)
### 6.2 TypeScript 编译错误
**问题**:添加埋点后多处 TypeScript 错误
**修复内容**
- 修正 Prisma 模型名称(如 `prisma.reviewTask` 代替 `prisma.review_tasks`
- 添加类型注解(`reduce` 函数参数)
- 添加 `.js` 扩展名到 ESM 导入
### 6.3 DC Tool C 上传 401
**问题**:文件上传返回 401 Unauthorized
**原因**:后端服务未重启,新代码未生效
**解决**:重启后端服务后正常
---
## 7. 文件变更清单
### 新增文件
| 文件 | 说明 |
|------|------|
| `backend/src/common/services/activity.service.ts` | 埋点服务 |
| `backend/src/modules/admin/controllers/statsController.ts` | 统计控制器 |
| `backend/src/modules/admin/routes/statsRoutes.ts` | 统计路由 |
| `frontend-v2/src/modules/admin/api/statsApi.ts` | 前端 API 层 |
### 修改文件
| 文件 | 修改内容 |
|------|---------|
| `backend/prisma/schema.prisma` | 添加 SimpleLog 模型 |
| `backend/src/index.ts` | 注册 statsRoutes |
| `backend/src/common/auth/auth.controller.ts` | 登录埋点 |
| `backend/src/modules/aia/services/conversationService.ts` | AIA 对话埋点 |
| `backend/src/modules/pkb/services/knowledgeBaseService.ts` | PKB 知识库埋点 |
| `backend/src/modules/pkb/services/ragService.ts` | PKB RAG 埋点 |
| `backend/src/modules/asl/services/screeningWorker.ts` | ASL 筛选埋点 |
| `backend/src/modules/dc/tool-b/workers/extractionWorker.ts` | DC Tool B 埋点 |
| `backend/src/modules/dc/tool-c/services/AICodeService.ts` | DC Tool C 埋点 |
| `backend/src/modules/rvw/workers/reviewWorker.ts` | RVW 审查埋点 |
| `backend/src/modules/iit-manager/services/SyncManager.ts` | IIT 同步埋点 |
| `frontend-v2/src/pages/admin/AdminDashboard.tsx` | 运营看板 UI |
---
## 8. 后续优化建议
### P2 优先级
- [ ] 添加更多埋点Protocol Agent 一键生成、Word 导出
- [ ] 图表可视化:使用 ECharts 展示趋势图
- [ ] 定时任务:每日 00:00 自动清理 180 天前日志
### P3 优先级
- [ ] 用户行为路径分析
- [ ] 漏斗分析功能
- [ ] 导出统计报表
---
## 9. 总结
✅ 运营监控系统 MVP 已完成核心功能:
- **数据采集**7 个模块埋点全部完成
- **数据存储**SimpleLog 表结构稳定
- **数据展示**Admin Dashboard 实时展示
- **API 接口**4 个核心端点全部可用
MVP 阶段目标达成,可支持基本的运营数据分析需求。
---
*文档完成时间2026-01-25*