fix: Phase 1.3 完善修复 — 管理端对接 + HMS清理 + 编辑器加载
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled

- feat(web): ClassList.tsx 对接 update/deactivate/reset-code API
  - 编辑班级: PUT /diary/classes/:id
  - 停用班级: PATCH /diary/classes/:id/deactivate (Popconfirm 确认)
  - 重置班级码: POST /diary/classes/:id/reset-code (Popconfirm 确认)
  - 数据源改用 listAll() 获取所有班级
- fix(web): JournalList.tsx 班级筛选改用 classApi.listAll()
- fix(app): EditorPage 加载已有日记数据 (journalId 非空时)
  - 从 Isar 恢复笔画/元素/标签/心情/标题
  - _EditorView 改为 StatefulWidget + initState 加载
- chore(web): HMS 遗留代码清理
  - 删除 api/copilot.ts, healthFixtures.ts, healthHandlers.ts
  - AuditLogViewer 资源类型替换为日记模块类型
  - auth.test.ts / renderWithProviders 权限码 health.* → diary.*
- docs: 确认 M6 NotificationService 为误报 (已在 3 处调用)
This commit is contained in:
iven
2026-06-02 22:54:09 +08:00
parent 860844a399
commit 85d6781372
11 changed files with 201 additions and 757 deletions

View File

@@ -1,66 +0,0 @@
import client from './client';
import type { PaginatedResponse } from './types';
// --- Types ---
export type InsightType = 'risk_score' | 'anomaly' | 'follow_up_hint' | 'consult_hint';
export type InsightSource = 'rule' | 'llm' | 'hybrid';
export type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
export interface MatchedRule {
rule_id: string;
name: string;
score: number;
severity: string;
suggestion?: string;
}
export interface RiskScore {
score: number;
level: RiskLevel;
matched_rules: MatchedRule[];
}
export interface CopilotInsight {
id: string;
patient_id: string;
insight_type: InsightType;
source: InsightSource;
severity: 'info' | 'warning' | 'critical';
title: string;
content: Record<string, unknown>;
rule_matches?: MatchedRule[];
llm_supplement?: string;
created_at: string;
}
// --- API Functions ---
export async function getPatientRisk(patientId: string) {
const { data } = await client.get<{ success: boolean; data: RiskScore }>(`/copilot/patients/${patientId}/risk`);
return data.data;
}
export async function listInsights(params: {
patient_id?: string;
insight_type?: string;
severity?: string;
page?: number;
page_size?: number;
}) {
const { data } = await client.get<{ success: boolean; data: PaginatedResponse<CopilotInsight> }>('/copilot/insights', { params });
return data.data;
}
export function dismissInsight(id: string) {
return client.post(`/copilot/insights/${id}/dismiss`);
}
export function listAlerts(params?: { severity?: string; page?: number; page_size?: number }) {
return listInsights({ insight_type: 'anomaly', ...params });
}
export async function listRules(params?: { page?: number; page_size?: number }) {
const { data } = await client.get<{ success: boolean; data: PaginatedResponse<Record<string, unknown>> }>('/copilot/rules', { params });
return data.data;
}

View File

@@ -1,20 +1,23 @@
import client from '../client';
import type { SchoolClass, CreateClassReq, ClassMember, PaginatedResponse } from './types';
import type { SchoolClass, CreateClassReq, UpdateClassReq, ClassMember, PaginatedResponse } from './types';
export const classApi = {
/** 班级列表 — 后端返回纯数组,前端转换为 PaginatedResponse 格式 */
/** 班级列表 — 当前用户加入的班级 (GET /diary/classes → my_classes) */
list: (params?: { page?: number; page_size?: number }) =>
client.get<{ success: boolean; data: SchoolClass[] }>('/diary/classes', { params })
.then((r) => {
const raw = r.data.data;
// 后端返回纯数组,包装为分页格式
if (Array.isArray(raw)) {
return { data: raw, total: raw.length, page: params?.page ?? 1, page_size: params?.page_size ?? 20 } as PaginatedResponse<SchoolClass>;
}
// 兼容:如果后端已升级为分页格式
return raw as unknown as PaginatedResponse<SchoolClass>;
}),
/** 所有班级 — 管理端用,需要 diary.class.manage 权限 (GET /diary/classes/all) */
listAll: () =>
client.get<{ success: boolean; data: SchoolClass[] }>('/diary/classes/all')
.then((r) => r.data.data),
myClasses: () =>
client.get<{ success: boolean; data: SchoolClass[] }>('/diary/classes/my')
.then((r) => r.data.data),
@@ -26,6 +29,18 @@ export const classApi = {
create: (data: CreateClassReq) =>
client.post('/diary/classes', data).then((r) => r.data.data),
/** 更新班级信息 (PUT /diary/classes/:id) */
update: (id: string, data: UpdateClassReq) =>
client.put(`/diary/classes/${id}`, data).then((r) => r.data.data),
/** 停用班级 (PATCH /diary/classes/:id/deactivate) */
deactivate: (id: string) =>
client.patch(`/diary/classes/${id}/deactivate`).then((r) => r.data.data),
/** 重置班级码 (POST /diary/classes/:id/reset-code) */
resetCode: (id: string) =>
client.post(`/diary/classes/${id}/reset-code`).then((r) => r.data.data),
listMembers: (classId: string) =>
client.get<{ success: boolean; data: ClassMember[] }>(`/diary/classes/${classId}/members`)
.then((r) => r.data.data),

View File

@@ -50,6 +50,17 @@ export interface CreateClassReq {
school_name?: string;
}
export interface UpdateClassReq {
name?: string;
school_name?: string;
version: number;
}
export interface ResetClassCodeResp {
class_id: string;
new_class_code: string;
}
export interface ClassMember {
user_id: string;
role: string;