feat(web): 工作台页面改造 — 管理员/运营数据改用真实 API
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

- AdminDashboard 移除硬编码模块列表,改用 system-health/user-activity/modules API
- OperatorWorkbench 移除硬编码积分动态和文章统计,改用 points-recent-activity/article-stats API
- 新增 dashboard.ts API 客户端,AxiosResponse 解包到 data.data
- Home.tsx 集成 4 个角色工作台组件路由
- useDashboardRole 支持 health_manager 角色
This commit is contained in:
iven
2026-05-02 11:56:26 +08:00
parent 0006e427e2
commit dd44c1526f
8 changed files with 1589 additions and 15 deletions

View File

@@ -32,8 +32,12 @@ import { useStatsData } from './health/StatisticsDashboard/useStatsData';
import { useCountUp } from '../hooks/useCountUp';
import TodoList from './health/components/workbench/TodoList';
import AiInsightPanel from './health/components/workbench/AiInsightPanel';
import TeamOverviewPanel from './health/components/workbench/TeamOverviewPanel';
import ActionDetailDrawer from './health/components/workbench/ActionDetailDrawer';
import TaskQueue from './health/components/workbench/TaskQueue';
import TaskDetail from './health/components/workbench/TaskDetail';
import DoctorWorkbench from './health/components/workbench/DoctorWorkbench';
import OperatorWorkbench from './health/components/workbench/OperatorWorkbench';
import AdminDashboard from './health/components/workbench/AdminDashboard';
import type { ActionItem } from '../api/health/actionInbox';
// --- Shared utilities ---
@@ -92,6 +96,7 @@ interface QuickActionDef {
const ROLE_WELCOME: Record<DashboardRole, { title: string; subtitle: string }> = {
doctor: { title: '今日工作台', subtitle: '患者概览与待办事项' },
health_manager: { title: '任务工作台', subtitle: '待处理任务与患者管理' },
nurse: { title: '随访监控台', subtitle: '今日随访与体征上报' },
admin: { title: '管理中心', subtitle: '平台运营数据概览' },
operator: { title: '运营中心', subtitle: '积分、内容与活动' },
@@ -112,6 +117,12 @@ const ROLE_STATS: Record<DashboardRole, StatCardDef[]> = {
{ key: 'consultations', title: '本月咨询', getValue: (p) => p?.consultations_this_month ?? 0, getDiff: (p) => { const c = p?.consultations_this_month, y = p?.yesterday_consultations_this_month; return c != null && y != null ? c - y : undefined; }, icon: <MessageOutlined />, path: '/health/consultations' },
{ key: 'followup-rate', title: '随访完成率', getValue: (p) => p?.follow_up_rate ?? 0, icon: <HeartOutlined />, suffix: '%', path: '/health/follow-ups' },
],
health_manager: [
{ key: 'today-followups', title: '今日随访', getValue: (p) => p?.today_follow_ups ?? 0, getDiff: (p) => { const c = p?.today_follow_ups, y = p?.yesterday_today_follow_ups; return c != null && y != null ? c - y : undefined; }, icon: <HeartOutlined />, path: '/health/follow-up-tasks' },
{ key: 'vital-anomaly', title: '体征异常', getValue: (p) => p?.overdue_follow_ups ?? 0, icon: <AlertOutlined />, path: '/health/alert-dashboard' },
{ key: 'ai-pending', title: 'AI 建议待审', getValue: (p) => p?.consultations_this_month ?? 0, icon: <MedicineBoxOutlined />, path: '/health/ai-analysis' },
{ key: 'followup-rate', title: '处理率', getValue: (p) => p?.follow_up_rate ?? 0, icon: <CheckCircleOutlined />, suffix: '%', path: '/health/follow-up-tasks' },
],
nurse: [
{ key: 'today-appointments', title: '今日预约', getValue: (p) => p?.today_appointments ?? 0, getDiff: (p) => { const c = p?.today_appointments, y = p?.yesterday_today_appointments; return c != null && y != null ? c - y : undefined; }, icon: <CalendarOutlined />, path: '/health/appointments' },
{ key: 'today-followups', title: '今日随访', getValue: (p) => p?.today_follow_ups ?? 0, getDiff: (p) => { const c = p?.today_follow_ups, y = p?.yesterday_today_follow_ups; return c != null && y != null ? c - y : undefined; }, icon: <HeartOutlined />, path: '/health/follow-ups' },
@@ -141,6 +152,14 @@ const ROLE_ACTIONS: Record<DashboardRole, QuickActionDef[]> = {
{ icon: <AlertOutlined />, label: '告警中心', path: '/health/alert-dashboard' },
{ icon: <MedicineBoxOutlined />, label: '健康数据', path: '/health/statistics' },
],
health_manager: [
{ icon: <HeartOutlined />, label: '随访管理', path: '/health/follow-up-tasks' },
{ icon: <MedicineBoxOutlined />, label: '体征监测', path: '/health/alert-dashboard' },
{ icon: <MessageOutlined />, label: '患者咨询', path: '/health/consultations' },
{ icon: <TeamOutlined />, label: '患者管理', path: '/health/patients' },
{ icon: <TrophyOutlined />, label: '积分商城', path: '/health/points-products' },
{ icon: <FileTextOutlined />, label: '统计报表', path: '/health/statistics' },
],
nurse: [
{ icon: <HeartOutlined />, label: '随访管理', path: '/health/follow-ups' },
{ icon: <MedicineBoxOutlined />, label: '健康数据', path: '/health/vital-signs' },
@@ -230,6 +249,20 @@ export default function Home() {
return (
<div>
{/* 角色工作台路由 */}
{role === 'doctor' ? (
<DoctorWorkbench />
) : role === 'health_manager' ? (
<div style={{ display: 'flex', height: 'calc(100vh - 64px)', overflow: 'hidden', margin: -20 }}>
<TaskQueue />
<TaskDetail />
</div>
) : role === 'operator' ? (
<OperatorWorkbench />
) : role === 'admin' ? (
<AdminDashboard />
) : (
<>
{/* 欢迎语 */}
<div className="erp-fade-in" style={{ marginBottom: 24 }}>
<h2 style={{
@@ -288,10 +321,9 @@ export default function Home() {
})}
</div>
{/* 双栏布局 */}
{(role === 'doctor' || role === 'nurse') ? (
{/* 双栏布局 — nurse */}
{role === 'nurse' ? (
<div style={{ display: 'grid', gridTemplateColumns: '1fr 340px', gap: 20, marginBottom: 24 }}>
{/* 左:待办列表 */}
<div style={{
background: 'var(--erp-bg-card, white)',
borderRadius: 12,
@@ -309,8 +341,6 @@ export default function Home() {
</div>
<TodoList onItemClick={(item) => { setDrawerItem(item); setDrawerOpen(true); }} />
</div>
{/* 右AI 洞察 */}
<AiInsightPanel />
</div>
) : (
@@ -416,13 +446,6 @@ export default function Home() {
</Col>
</Row>
{/* 主任团队概览 — 在快捷入口上方,全宽展示 */}
{role === 'admin' && (
<div style={{ marginBottom: 24 }}>
<TeamOverviewPanel />
</div>
)}
{/* 行动详情抽屉 */}
<ActionDetailDrawer
item={drawerItem}
@@ -433,6 +456,8 @@ export default function Home() {
setDrawerItem(null);
}}
/>
</>
)}
</div>
);
}