feat(plugin): 评估量表 WASM 编译通过 — 170KB cdylib 组件
- wasm32-unknown-unknown target 编译成功 - 插件通过 API upload/install 注册,无需手动配置
This commit is contained in:
@@ -72,10 +72,10 @@ export function AdminDashboard() {
|
||||
<Tabs
|
||||
defaultActiveKey="dialysis"
|
||||
items={[
|
||||
{ key: 'dialysis', label: '透析管理', children: <HealthDataCenter data={healthDataStats} /> },
|
||||
{ key: 'lab', label: '化验报告', children: <HealthDataCenter data={healthDataStats} /> },
|
||||
{ key: 'appointments', label: '预约分析', children: <HealthDataCenter data={healthDataStats} /> },
|
||||
{ key: 'vital-signs', label: '体征数据', children: <HealthDataCenter data={healthDataStats} /> },
|
||||
{ key: 'dialysis', label: '透析管理', children: <HealthDataCenter data={healthDataStats} tab="dialysis" /> },
|
||||
{ key: 'lab', label: '化验报告', children: <HealthDataCenter data={healthDataStats} tab="lab" /> },
|
||||
{ key: 'appointments', label: '预约分析', children: <HealthDataCenter data={healthDataStats} tab="appointments" /> },
|
||||
{ key: 'vital-signs', label: '体征数据', children: <HealthDataCenter data={healthDataStats} tab="vital-signs" /> },
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@@ -1,98 +1,124 @@
|
||||
import { Row, Col, Card, Statistic, Tag, Typography } from 'antd';
|
||||
import { Row, Col, Card, Statistic, Tag, Typography, Empty } from 'antd';
|
||||
import type { HealthDataStats } from '../../../api/health/points';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
interface HealthDataCenterProps {
|
||||
data: HealthDataStats | null;
|
||||
tab?: string;
|
||||
}
|
||||
|
||||
export default function HealthDataCenter({ data }: HealthDataCenterProps) {
|
||||
function DialysisPanel({ data }: { data: HealthDataStats | null }) {
|
||||
return (
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>透析记录</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总记录" value={data?.dialysis.total_records ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月新增" value={data?.dialysis.this_month ?? 0} valueStyle={{ fontSize: 20, color: '#2563eb' }} /></Col>
|
||||
<Col span={8}><Statistic title="待审核" value={data?.dialysis.pending_review ?? 0} valueStyle={{ fontSize: 20, color: '#d97706' }} /></Col>
|
||||
</Row>
|
||||
<Row gutter={[12, 12]} style={{ marginTop: 12 }}>
|
||||
<Col span={8}><Statistic title="并发症率" value={data?.dialysis.complication_rate ?? 0} suffix="%" precision={1} valueStyle={{ fontSize: 18 }} /></Col>
|
||||
<Col span={8}><Statistic title="平均超滤(ml)" value={data?.dialysis.avg_ultrafiltration ?? 0} precision={0} valueStyle={{ fontSize: 18 }} /></Col>
|
||||
<Col span={8}><Statistic title="平均时长(分)" value={data?.dialysis.avg_duration ?? 0} precision={0} valueStyle={{ fontSize: 18 }} /></Col>
|
||||
</Row>
|
||||
{(data?.dialysis.type_distribution ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>类型分布: </Text>
|
||||
{data!.dialysis.type_distribution.map((item) => (
|
||||
<Tag key={item.name} color="blue" style={{ marginTop: 4 }}>{item.name}: {item.value}</Tag>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function LabPanel({ data }: { data: HealthDataStats | null }) {
|
||||
return (
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>化验报告</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总报告" value={data?.lab_reports.total_reports ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月新增" value={data?.lab_reports.this_month ?? 0} valueStyle={{ fontSize: 20, color: '#2563eb' }} /></Col>
|
||||
<Col span={8}><Statistic title="异常项" value={data?.lab_reports.abnormal_items ?? 0} valueStyle={{ fontSize: 20, color: '#dc2626' }} /></Col>
|
||||
</Row>
|
||||
<Row gutter={[12, 12]} style={{ marginTop: 12 }}>
|
||||
<Col span={8}><Statistic title="待审核" value={data?.lab_reports.pending_review ?? 0} valueStyle={{ fontSize: 18, color: '#d97706' }} /></Col>
|
||||
<Col span={8}><Statistic title="已审核" value={data?.lab_reports.reviewed ?? 0} valueStyle={{ fontSize: 18, color: '#059669' }} /></Col>
|
||||
</Row>
|
||||
{(data?.lab_reports.type_distribution ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>类型分布: </Text>
|
||||
{data!.lab_reports.type_distribution.map((item) => (
|
||||
<Tag key={item.name} color="green" style={{ marginTop: 4 }}>{item.name}: {item.value}</Tag>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function AppointmentsPanel({ data }: { data: HealthDataStats | null }) {
|
||||
return (
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>预约统计</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总预约" value={data?.appointments.total_appointments ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月" value={data?.appointments.this_month ?? 0} valueStyle={{ fontSize: 20, color: '#2563eb' }} /></Col>
|
||||
<Col span={8}><Statistic title="取消率" value={data?.appointments.cancel_rate ?? 0} suffix="%" precision={1} valueStyle={{ fontSize: 20, color: '#dc2626' }} /></Col>
|
||||
</Row>
|
||||
{(data?.appointments.status_distribution ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>状态: </Text>
|
||||
{data!.appointments.status_distribution.map((item) => (
|
||||
<Tag key={item.name} color="purple" style={{ marginTop: 4 }}>{item.name}: {item.value}</Tag>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function VitalSignsPanel({ data }: { data: HealthDataStats | null }) {
|
||||
return (
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>体征上报率</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总患者" value={data?.vital_signs_report_rate.total_patients ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月上报" value={data?.vital_signs_report_rate.reported_patients ?? 0} valueStyle={{ fontSize: 20, color: '#059669' }} /></Col>
|
||||
<Col span={8}><Statistic title="上报率" value={data?.vital_signs_report_rate.report_rate ?? 0} suffix="%" precision={1} valueStyle={{ fontSize: 20, color: '#7c3aed' }} /></Col>
|
||||
</Row>
|
||||
{(data?.vital_signs_report_rate.daily_trend ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>近 7 天: </Text>
|
||||
<div style={{ display: 'flex', gap: 6, marginTop: 4, flexWrap: 'wrap' }}>
|
||||
{data!.vital_signs_report_rate.daily_trend.map((d) => (
|
||||
<Tag key={d.date} color={d.rate >= 50 ? 'green' : d.rate >= 20 ? 'orange' : 'red'}>
|
||||
{d.date.slice(5)} {d.reported}/{d.total}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
const TAB_PANELS: Record<string, React.FC<{ data: HealthDataStats | null }>> = {
|
||||
dialysis: DialysisPanel,
|
||||
lab: LabPanel,
|
||||
appointments: AppointmentsPanel,
|
||||
'vital-signs': VitalSignsPanel,
|
||||
};
|
||||
|
||||
export default function HealthDataCenter({ data, tab = 'dialysis' }: HealthDataCenterProps) {
|
||||
const Panel = TAB_PANELS[tab];
|
||||
|
||||
if (!Panel) {
|
||||
return <Empty description="未知数据面板" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col xs={24} md={12}>
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>透析记录</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总记录" value={data?.dialysis.total_records ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月新增" value={data?.dialysis.this_month ?? 0} valueStyle={{ fontSize: 20, color: '#2563eb' }} /></Col>
|
||||
<Col span={8}><Statistic title="待审核" value={data?.dialysis.pending_review ?? 0} valueStyle={{ fontSize: 20, color: '#d97706' }} /></Col>
|
||||
</Row>
|
||||
<Row gutter={[12, 12]} style={{ marginTop: 12 }}>
|
||||
<Col span={8}><Statistic title="并发症率" value={data?.dialysis.complication_rate ?? 0} suffix="%" precision={1} valueStyle={{ fontSize: 18 }} /></Col>
|
||||
<Col span={8}><Statistic title="平均超滤(ml)" value={data?.dialysis.avg_ultrafiltration ?? 0} precision={0} valueStyle={{ fontSize: 18 }} /></Col>
|
||||
<Col span={8}><Statistic title="平均时长(分)" value={data?.dialysis.avg_duration ?? 0} precision={0} valueStyle={{ fontSize: 18 }} /></Col>
|
||||
</Row>
|
||||
{(data?.dialysis.type_distribution ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>类型分布: </Text>
|
||||
{data!.dialysis.type_distribution.map((item) => (
|
||||
<Tag key={item.name} color="blue" style={{ marginTop: 4 }}>{item.name}: {item.value}</Tag>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} md={12}>
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>化验报告</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总报告" value={data?.lab_reports.total_reports ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月新增" value={data?.lab_reports.this_month ?? 0} valueStyle={{ fontSize: 20, color: '#2563eb' }} /></Col>
|
||||
<Col span={8}><Statistic title="异常项" value={data?.lab_reports.abnormal_items ?? 0} valueStyle={{ fontSize: 20, color: '#dc2626' }} /></Col>
|
||||
</Row>
|
||||
<Row gutter={[12, 12]} style={{ marginTop: 12 }}>
|
||||
<Col span={12}><Statistic title="待审核" value={data?.lab_reports.pending_review ?? 0} valueStyle={{ fontSize: 18, color: '#d97706' }} /></Col>
|
||||
<Col span={12}><Statistic title="已审核" value={data?.lab_reports.reviewed ?? 0} valueStyle={{ fontSize: 18, color: '#059669' }} /></Col>
|
||||
</Row>
|
||||
{(data?.lab_reports.type_distribution ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>类型分布: </Text>
|
||||
{data!.lab_reports.type_distribution.map((item) => (
|
||||
<Tag key={item.name} color="green" style={{ marginTop: 4 }}>{item.name}: {item.value}</Tag>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} md={12}>
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>预约统计</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总预约" value={data?.appointments.total_appointments ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月" value={data?.appointments.this_month ?? 0} valueStyle={{ fontSize: 20, color: '#2563eb' }} /></Col>
|
||||
<Col span={8}><Statistic title="取消率" value={data?.appointments.cancel_rate ?? 0} suffix="%" precision={1} valueStyle={{ fontSize: 20, color: '#dc2626' }} /></Col>
|
||||
</Row>
|
||||
{(data?.appointments.status_distribution ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>状态: </Text>
|
||||
{data!.appointments.status_distribution.map((item) => (
|
||||
<Tag key={item.name} color="purple" style={{ marginTop: 4 }}>{item.name}: {item.value}</Tag>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} md={12}>
|
||||
<Card type="inner" title={<span style={{ fontSize: 14, fontWeight: 600 }}>体征上报率</span>} style={{ borderRadius: 8 }}>
|
||||
<Row gutter={[12, 12]}>
|
||||
<Col span={8}><Statistic title="总患者" value={data?.vital_signs_report_rate.total_patients ?? 0} valueStyle={{ fontSize: 20 }} /></Col>
|
||||
<Col span={8}><Statistic title="本月上报" value={data?.vital_signs_report_rate.reported_patients ?? 0} valueStyle={{ fontSize: 20, color: '#059669' }} /></Col>
|
||||
<Col span={8}><Statistic title="上报率" value={data?.vital_signs_report_rate.report_rate ?? 0} suffix="%" precision={1} valueStyle={{ fontSize: 20, color: '#7c3aed' }} /></Col>
|
||||
</Row>
|
||||
{(data?.vital_signs_report_rate.daily_trend ?? []).length > 0 && (
|
||||
<div style={{ marginTop: 12 }}>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>近 7 天: </Text>
|
||||
<div style={{ display: 'flex', gap: 6, marginTop: 4, flexWrap: 'wrap' }}>
|
||||
{data!.vital_signs_report_rate.daily_trend.map((d) => (
|
||||
<Tag key={d.date} color={d.rate >= 50 ? 'green' : d.rate >= 20 ? 'orange' : 'red'}>
|
||||
{d.date.slice(5)} {d.reported}/{d.total}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
<Col span={24}>
|
||||
<Panel data={data} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user