Files
AIclinicalresearch/docs/03-业务模块/ADMIN-运营管理端/00-系统设计/运营体系设计方案-MVP-V3.0.md
HaHafeng 303dd78c54 feat(aia): Protocol Agent MVP complete with one-click generation and Word export
- Add one-click research protocol generation with streaming output

- Implement Word document export via Pandoc integration

- Add dynamic dual-panel layout with resizable split pane

- Implement collapsible content for StatePanel stages

- Add conversation history management with title auto-update

- Fix scroll behavior, markdown rendering, and UI layout issues

- Simplify conversation creation logic for reliability
2026-01-25 19:16:36 +08:00

293 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **AI 临床科研平台 \- MVP 运营监控体系实施方案 V3.0**
**文档版本**V3.0 (全景洞察版)
**面向对象**:核心开发团队 (2人)
**更新重点**
1. **宏观**:确立 DAU/DAT 双核心指标,防止“假活跃”。
2. **微观**:新增 **“用户 360 全景画像”**,支持查看单用户的资产存量与行为流水。
3. **技术**:维持 Postgres-Only 极简架构,不引入新组件。
## **1\. 核心理念:关注“生存”与“真实价值”**
在 MVP 阶段,我们必须警惕“只有管理员登录”的假象。**医生用起来,才是真的活了。**
| 优先级 | 指标名称 | 定义 | 为什么关注? |
| :---- | :---- | :---- | :---- |
| **P0+** | **活跃医生数 (DAU)** | 今日有登录/使用行为的去重 user\_id 数。 | **真实价值线**。只有医生个人觉得好用,产品才有生命力。这是防止客户流失的前哨指标。 |
| **P0** | **活跃租户数 (DAT)** | 今日有登录行为的去重 tenant\_id 数。 | **商务生死线**。代表医院客户的存活情况。 |
| **P1** | **具体功能渗透率** | 例如:“选题助手”的使用次数 vs “论文润色”的使用次数。 | **产品迭代指引**。如果没人用“润色”,我们就别在这个功能上浪费时间开发了。 |
| **P2** | **价值交付次数** | 用户点击 **“导出/下载”** 的次数。 | **北极星指标**。用户只有认可了 AI 的结果才会导出。这是交付价值的终点。 |
## **2\. 技术架构Postgres-Only 极简方案**
### **2.1 数据库设计 (Schema)**
在 admin\_schema 下新增一张通用日志表。**不需要**做聚合表,**不需要**做定时统计任务,直接查表即可。
**文件路径**backend/prisma/schema.prisma
// ... inside admin\_schema ...
/// 极简运营日志表 (MVP)
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)
userId String @map("user\_id") @db.Uuid
userName String? @map("user\_name") @db.VarChar(50)
// V3.0 核心字段设计
module String @db.VarChar(20) // 大模块: 'AIA', 'ASL', 'DC', 'PKB'
feature String @db.VarChar(50) // 细分功能: 'Topic Agent', 'Tool C', 'RAG Chat'
action String @db.VarChar(20) // 动作: 'USE', 'EXPORT', 'ERROR', 'LOGIN'
info String? @db.Text // 详情: "生成了3个选题" / "导出Excel"
@@index(\[createdAt\])
@@index(\[tenantId\])
@@index(\[userId\]) // V3.0 新增:支持查询单用户轨迹
@@index(\[module, feature\]) // 支持按功能统计热度
@@map("simple\_logs")
@@schema("admin\_schema")
}
### **2.2 后端服务实现 (ActivityService)**
负责写入日志和获取大盘数据。
**文件路径**backend/src/common/services/activity.service.ts
import { PrismaClient } from '@prisma/client';
// 假设这是全局 Prisma 实例
import { prisma } from '@/common/database/prisma';
export const activityService \= {
/\*\*
\* 核心埋点方法 (Fire-and-Forget 模式)
\* @param feature 具体功能名称,如 'Topic Agent'
\*/
async log(
tenantId: string,
userId: string,
userName: string,
action: 'LOGIN' | 'USE' | 'EXPORT' | 'ERROR',
module: 'AIA' | 'ASL' | 'DC' | 'PKB' | 'SYSTEM',
feature: string, // 必填:细分功能
info: any
) {
// 异步执行,不要 await避免影响主接口性能
prisma.simpleLog.create({
data: {
tenantId, userId, userName, action, module, feature,
info: typeof info \=== 'object' ? JSON.stringify(info) : String(info),
}
}).catch(e \=\> console.error('埋点写入失败(可忽略):', e));
},
/\*\*
\* 运营看板:获取实时流水账
\*/
async getLiveFeed(limit \= 100\) {
return prisma.simpleLog.findMany({
orderBy: { createdAt: 'desc' },
take: limit
});
},
/\*\*
\* 🟢 获取今日核心大盘数据 (DAU \+ DAT)
\* 用于 Admin 首页顶部展示
\*/
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}
\`;
return {
dau: Number(stats\[0\].dau),
dat: Number(stats\[0\].dat),
exportCount: Number(stats\[0\].export\_count)
};
}
};
## **3\. 细粒度埋点实施清单 (直接复制给开发)**
为了满足运营需求,请在以下位置埋点,并务必带上 feature 参数。
### **🤖 3.1 AIA 模块 (12个智能体细分)**
**位置**aia/services/chat.service.ts \-\> complete 方法 (AI回复完成时)
**逻辑**:根据当前对话的 agentId 记录不同的 feature。
// 示例映射表
const agentNameMap \= {
'topic-scoping': '科学问题梳理',
'pico-analysis': 'PICO梳理',
'topic-eval': '选题评价',
'outcome-design': '观察指标设计',
'crf-design': 'CRF设计',
'sample-size': '样本量计算',
'protocol-writing': '方案撰写',
'methodology-review': '方法学评审',
'paper-polish': '论文润色',
'paper-translate': '论文翻译',
// ... 其他智能体
};
const feature \= agentNameMap\[agentId\] || 'Unknown Agent';
activityService.log(..., 'USE', 'AIA', feature, '生成完成');
### **🧹 3.2 DC 模块 (清洗工具细分)**
**位置**dc/controllers/extraction.controller.ts
* **Tool B (自动提取)**: log(..., 'USE', 'DC', 'Tool B', '提取任务: 50条')
* **Tool C (数据清洗)**: log(..., 'USE', 'DC', 'Tool C', '执行清洗操作')
* **导出结果**: log(..., 'EXPORT', 'DC', 'Tool C', '导出 Excel')
### **📚 3.3 ASL 模块 (文献功能细分)**
**位置**asl/controllers/research.controller.ts
* **智能检索**: log(..., 'USE', 'ASL', 'DeepSearch', '关键词: 肺癌')
* **标题摘要筛选**: log(..., 'USE', 'ASL', 'Title/Abstract Screening', '筛选进度: 100/500')
* **全文复筛**: log(..., 'USE', 'ASL', 'Fulltext Review', '复筛完成')
### **🧠 3.4 PKB 模块 (知识库行为)**
**位置**pkb/controllers/...
* **上传文档**: log(..., 'USE', 'PKB', 'Document Upload', '上传: 3篇')
* **RAG 问答**: log(..., 'USE', 'PKB', 'RAG Chat', '提问: 入排标准是什么?')
* **批处理**: log(..., 'USE', 'PKB', 'Batch Process', '批量提取: 10篇')
## **4\. 运营看板设计 (Admin Portal) \- 宏观**
### **界面参考**
在 Admin 首页展示。
#### **\[ 顶部卡片区域 \]**
| 今日活跃医生 (DAU) | 今日活跃医院 (DAT) | 今日价值交付 (导出) |
| :---- | :---- | :---- |
| **12** 👨‍⚕️ | **3** 🏥 | **5** 🟢 |
#### **\[ 实时流水账区域 \]**
| 时间 | 医院 | 医生 | 模块 | 具体功能 | 动作 | 详情 |
| :---- | :---- | :---- | :---- | :---- | :---- | :---- |
| 10:05 | 协和 | 张主任 | **AIA** | **选题评价** | 🔵 USE | 评价得分: 85分 |
| 10:03 | 协和 | 张主任 | **AIA** | **PICO梳理** | 🔵 USE | 梳理完成 |
| 09:55 | 华西 | 李医生 | **DC** | **Tool C** | 🟢 **EXPORT** | 导出 Excel |
## **5\. 用户 360 全景画像 (User 360 View) \- 微观 🆕**
**新增模块**:当运营人员点击用户列表中的“详情”时,展示该用户的全生命周期数据。
### **5.1 后端聚合服务 (UserOverviewService)**
不建立宽表,利用 Prisma 并行查询实现\*\*“资产快照 \+ 行为流水”\*\*聚合。
**文件路径**backend/src/modules/admin/services/user-overview.service.ts
import { prisma } from '@/common/database/prisma';
export const userOverviewService \= {
async getUserProfile(userId: string) {
// 并行查询,耗时取决于最慢的那个查询,通常 \< 200ms
const \[user, aiaStats, kbs, dcStats, logs\] \= await Promise.all(\[
// 1\. 基础信息
prisma.user.findUnique({ where: { id: userId } }),
// 2\. AIA 资产 (会话数)
prisma.conversation.count({ where: { userId, isDeleted: false } }),
// 3\. PKB 资产 (知识库数 \+ 文档数)
prisma.knowledgeBase.findMany({
where: { userId },
include: { \_count: { select: { documents: true } } }
}),
// 4\. DC 资产 (任务数)
prisma.extractionTask.count({ where: { userId } }),
// 5\. 最近行为 (从 SimpleLog 查最近 20 条)
prisma.simpleLog.findMany({
where: { userId },
orderBy: { createdAt: 'desc' },
take: 20
})
\]);
// 计算文档总数
const totalDocs \= kbs.reduce((sum, kb) \=\> sum \+ kb.\_count.documents, 0);
return {
profile: user,
assets: {
aia: { conversationCount: aiaStats },
pkb: { kbCount: kbs.length, docCount: totalDocs, kbs },
dc: { taskCount: dcStats }
},
activities: logs
};
}
};
### **5.2 前端布局设计 (UserDetailPage)**
使用 Ant Design 组件库实现三段式布局。
#### **区域一:资产数字 (Asset Stats)**
| 💬 AIA 对话 | 📚 PKB 知识库 | 📄 上传文献 | 🧹 DC 清洗任务 |
| :---- | :---- | :---- | :---- |
| **158** 次 | **3** 个 | **450** 篇 | **12** 次 |
*(点击数字可展开查看具体列表,如查看 3 个知识库的名称)*
#### **区域二:行为时间轴 (Timeline)**
展示用户最近的操作轨迹,快速判断用户是否遇到困难。
* **10:30** \[AIA\] 使用了 **“选题评价”** (生成结果: 85分)
* **10:15** \[PKB\] 上传了文档 lung\_cancer\_study.pdf 到 **“肺癌课题库”**
* **09:50** \[DC\] 导出了 **Tool C** 清洗结果 (Excel)
* **09:48** \[系统\] 登录系统
## **6\. 每日自动化巡检 (SAE Job)**
复用后端镜像,使用 SAE Job 功能,每天 06:00 执行。
* **检查项**数据库连接、Python 微服务心跳、公网连通性 (NAT)。
* **通知**:检查失败时发送企业微信报警。
* **目的**:确保早上醒来时系统是健康的。
## **7\. 开发执行计划**
**总耗时预计3-4 小时**
1. **\[DB\] (15min)**:
* 更新 Prisma Schema (新增 feature 字段和索引)。
* 执行 prisma db push。
2. **\[Backend\] (60min)**:
* 实现 activityService (埋点 \+ 大盘)。
* 实现 userOverviewService (360 聚合)。
* 在 AIA/DC/ASL/PKB 核心 Controller 插入 log() 代码。
3. **\[Frontend\] (90min)**:
* Admin 首页:实现大盘卡片 \+ 实时流水表格。
* User 详情页:实现资产统计卡片 \+ 行为 Timeline。