feat(admin): Implement operational monitoring MVP and login optimization
Summary: - Add SimpleLog table for activity tracking (admin_schema) - Implement ActivityService with fire-and-forget pattern - Add stats API endpoints (overview/live-feed/user-overview/cleanup) - Complete activity logging for 7 modules (SYSTEM/AIA/PKB/ASL/DC/RVW/IIT) - Update Admin Dashboard with DAU/DAT metrics and live feed - Fix user module permission display logic - Fix login redirect to /ai-qa instead of homepage - Replace top navigation LOGO with brand image - Fix PKB workspace layout CSS conflict (rename to .pa-chat-container) New files: - 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 - docs/03-.../04-operational-monitoring-mvp-plan.md - docs/03-.../04-operational-monitoring-mvp-implementation.md Tested: All features verified locally
This commit is contained in:
333
docs/03-业务模块/ADMIN-运营管理端/04-开发计划/04-运营监控系统MVP实施记录.md
Normal file
333
docs/03-业务模块/ADMIN-运营管理端/04-开发计划/04-运营监控系统MVP实施记录.md
Normal 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` 报错 P3006(shadow 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*
|
||||
|
||||
Reference in New Issue
Block a user