Files
hms/docs/design/mp-12-doctor-clinical.html
iven aa27c5174c docs(mp): 新增小程序全页面 HTML 原型 + UI 优化指南
- 新增 12 个核心页面原型(登录/首页/咨询/预约/商城/健康等)
- 新增医生端分包原型(核心 + 临床两个分包)
- 新增 AI 客服对话页原型
- 新增 MP UI 优化指南文档
- 更新 wiki 基础设施和小程序文档
2026-05-17 00:51:07 +08:00

646 lines
30 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HMS 小程序 — 医生端临床</title>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #1a1a1a; font-family: -apple-system, 'PingFang SC', sans-serif; display: flex; flex-direction: column; align-items: center; padding: 40px 20px; gap: 24px; }
.page-title { color: #999; font-size: 13px; letter-spacing: 0.15em; text-transform: uppercase; }
.note { color: #666; font-size: 12px; max-width: 1200px; text-align: center; line-height: 1.8; }
.screens { display: flex; gap: 36px; flex-wrap: wrap; justify-content: center; align-items: flex-start; }
.screen-wrap { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.screen-label { color: #888; font-size: 12px; font-style: italic; }
/* Scrollbar hide */
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 医生端临床</div>
<div class="note">医生端深靛蓝设计系统 — 临床管理模块。6 个屏幕:告警列表、告警详情、透析列表、透析创建、处方列表、处方详情。</div>
<div id="root"></div>
<script type="text/babel">
// ─── iOS 设备框 ───
const iosFrameStyles = {
wrapper: { display: 'inline-block', padding: 12, background: '#000', borderRadius: 60, boxShadow: '0 0 0 2px #1f2937, 0 20px 60px rgba(0,0,0,0.3)', position: 'relative' },
screen: { position: 'relative', borderRadius: 48, overflow: 'hidden', background: '#fff' },
statusBar: { position: 'absolute', top: 0, left: 0, right: 0, height: 54, display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 32px', fontSize: 16, fontWeight: 600, fontFamily: '-apple-system, "SF Pro Text", sans-serif', zIndex: 20, pointerEvents: 'none' },
dynamicIsland: { position: 'absolute', top: 12, left: '50%', transform: 'translateX(-50%)', width: 124, height: 36, background: '#000', borderRadius: 999, zIndex: 30 },
content: { position: 'absolute', top: 54, left: 0, right: 0, bottom: 34, overflow: 'auto' },
homeIndicator: { position: 'absolute', bottom: 10, left: '50%', transform: 'translateX(-50%)', width: 140, height: 5, background: 'rgba(0,0,0,0.3)', borderRadius: 999, zIndex: 10 },
};
function IosFrame({ children, width = 340, height = 740, time = '9:41', battery = 85, darkStatus = false, label }) {
const statusColor = darkStatus ? '#fff' : '#000';
return (
<div class="screen-wrap">
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: statusColor }}>
<span>{time}</span>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<svg width="16" height="12" viewBox="0 0 16 12" fill="none"><path d="M8 11.5a1 1 0 100-2 1 1 0 000 2z" fill={statusColor}/><path d="M3 7.5a7 7 0 0110 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke={statusColor} strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: `1.5px solid ${statusColor}`, borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: statusColor, borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div className="no-scrollbar" style={{ ...iosFrameStyles.content }}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
{label && <div class="screen-label">{label}</div>}
</div>
);
}
// ─── 设计 Token — 医生端靛蓝变体 ───
const T = {
pri: '#3A6B8C', priL: '#D4E5F0', priD: '#2A4F6A',
bg: '#F5F0EB', card: '#FFFFFF', surface: '#EDE8E2',
tx: '#2D2A26', tx2: '#5A554F', tx3: '#78716C',
bd: '#E8E2DC', bdL: '#F0EBE5',
acc: '#5B7A5E', accL: '#E8F0E8',
wrn: '#C4873A', wrnL: '#FFF3E0',
dan: '#B54A4A', danL: '#FDEAEA',
serif: "Georgia, 'Times New Roman', serif",
sans: "-apple-system, 'PingFang SC', sans-serif",
r: 16, rSm: 12, rXs: 8,
};
// ─── 通用组件 ───
function NavBar({ title }) {
return (
<div style={{ height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', background: T.bg, borderBottom: `1px solid ${T.bdL}`, flexShrink: 0 }}>
<svg style={{ position: 'absolute', left: 16 }} width="24" height="24" viewBox="0 0 24 24" fill="none" stroke={T.tx} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M15 18l-6-6 6-6"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
function Tag({ label, color = T.acc, bg = T.accL }) {
return (
<span style={{ display: 'inline-block', fontSize: 11, color, background: bg, padding: '2px 8px', borderRadius: 6, fontWeight: 500 }}>{label}</span>
);
}
function FilterTabs({ tabs, active = 0 }) {
return (
<div style={{ display: 'flex', gap: 8, marginBottom: 16 }}>
{tabs.map((t, i) => (
<div key={i} style={{
padding: '6px 14px', borderRadius: 20, fontSize: 13, fontWeight: i === active ? 600 : 400,
color: i === active ? '#fff' : T.tx2, background: i === active ? T.pri : T.card,
border: `1px solid ${i === active ? T.pri : T.bd}`, cursor: 'pointer', transition: 'all 0.2s',
}}>{t}</div>
))}
</div>
);
}
function InfoRow({ label, value }) {
return (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 0', borderBottom: `1px solid ${T.bdL}` }}>
<span style={{ fontSize: 13, color: T.tx3 }}>{label}</span>
<span style={{ fontSize: 14, color: T.tx, fontWeight: 500 }}>{value}</span>
</div>
);
}
function FormField({ label, value, placeholder, multiline }) {
return (
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>{label}</div>
<div style={{
height: multiline ? 80 : 52, background: T.card, border: `1.5px solid ${T.bd}`,
borderRadius: T.r, display: 'flex', alignItems: multiline ? 'flex-start' : 'center',
padding: multiline ? '14px 16px' : '0 16px', fontSize: 14, color: value ? T.tx : T.tx3,
fontFamily: T.sans, lineHeight: multiline ? 1.5 : 1,
}}>{value || placeholder}</div>
</div>
);
}
function ActionButton({ label, primary, danger, style: extraStyle }) {
const isDanger = danger;
const isPrimary = primary;
return (
<div style={{
height: 48, borderRadius: T.r, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 15, fontWeight: 600, cursor: 'pointer',
background: isDanger ? 'transparent' : (isPrimary ? T.pri : 'transparent'),
color: isDanger ? T.dan : (isPrimary ? '#fff' : T.pri),
border: isDanger ? `1.5px solid ${T.dan}` : (isPrimary ? 'none' : `1.5px solid ${T.pri}`),
...extraStyle,
}}>{label}</div>
);
}
// ─── 屏幕1告警列表 ───
function AlertList() {
const alerts = [
{ patient: '张三', type: '血压异常', urgency: '紧急', urgencyColor: T.dan, urgencyBg: T.danL,
value: '158', unit: 'mmHg', ref: '参考 <140', time: '10分钟前', status: '待处理', statusColor: T.dan, statusBg: T.danL },
{ patient: '赵六', type: '血糖异常', urgency: '紧急', urgencyColor: T.dan, urgencyBg: T.danL,
value: '15.2', unit: 'mmol/L', ref: '参考 <7.0', time: '2小时前', status: '待处理', statusColor: T.dan, statusBg: T.danL },
{ patient: '李四', type: '体重异常', urgency: '普通', urgencyColor: T.wrn, urgencyBg: T.wrnL,
value: '+2.3', unit: 'kg', ref: '周变化', time: '昨天', status: '已处理', statusColor: T.acc, statusBg: T.accL },
{ patient: '陈七', type: '血压异常', urgency: '紧急', urgencyColor: T.dan, urgencyBg: T.danL,
value: '162', unit: 'mmHg', ref: '参考 <140', time: '昨天', status: '待处理', statusColor: T.dan, statusBg: T.danL },
{ patient: '周八', type: '心率异常', urgency: '普通', urgencyColor: T.wrn, urgencyBg: T.wrnL,
value: '108', unit: 'bpm', ref: '参考 60-100', time: '2天前', status: '已处理', statusColor: T.acc, statusBg: T.accL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="异常告警" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 筛选标签 */}
<FilterTabs tabs={['全部', '高优', '中优', '低优']} active={0} />
{/* 统计栏 */}
<div style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
{[
{ label: '今日', value: '8', color: T.pri },
{ label: '待处理', value: '5', color: T.dan },
{ label: '已处理', value: '3', color: T.acc },
].map((s, i) => (
<div key={i} style={{ flex: 1, background: T.card, borderRadius: T.rSm, padding: '12px 14px', textAlign: 'center', boxShadow: '0 1px 8px rgba(0,0,0,0.04)' }}>
<div style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: s.color }}>{s.value}</div>
<div style={{ fontSize: 11, color: T.tx3, marginTop: 2 }}>{s.label}</div>
</div>
))}
</div>
{/* 告警列表 */}
{alerts.map((a, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '16px 18px', marginBottom: 12,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', borderLeft: `4px solid ${a.urgencyColor}`,
}}>
{/* 头部:患者 + 类型 + 紧急度 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx }}>{a.patient}</span>
<Tag label={a.type} color={T.pri} bg={T.priL} />
</div>
<Tag label={a.urgency} color={a.urgencyColor} bg={a.urgencyBg} />
</div>
{/* 异常值 */}
<div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginBottom: 10 }}>
<span style={{ fontFamily: T.serif, fontSize: 28, fontWeight: 700, color: a.urgencyColor }}>{a.value}</span>
<span style={{ fontSize: 13, color: T.tx2 }}>{a.unit}</span>
<span style={{ fontSize: 12, color: T.tx3, marginLeft: 4 }}>{a.ref}</span>
</div>
{/* 底部:时间 + 状态 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontSize: 12, color: T.tx3 }}>{a.time}</span>
<Tag label={a.status} color={a.statusColor} bg={a.statusBg} />
</div>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕2告警详情 ───
function AlertDetail() {
const history = [
{ date: '5/8', value: '158/95', note: '偏高', color: T.dan },
{ date: '5/7', value: '145/90', note: '偏高', color: T.wrn },
{ date: '5/6', value: '132/85', note: '正常', color: T.acc },
{ date: '5/5', value: '138/88', note: '偏高', color: T.wrn },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="告警详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 患者信息 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 14,
}}>
<div style={{
width: 44, height: 44, borderRadius: 22, background: T.priL,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.pri,
}}></div>
<div style={{ flex: 1 }}>
<div style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx, marginBottom: 3 }}>张三</div>
<div style={{ fontSize: 13, color: T.tx3 }}>58 · · 高血压 · 慢性肾病III期</div>
</div>
</div>
{/* 告警信息卡片 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', borderLeft: `4px solid ${T.dan}`,
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }}>
<span style={{ fontSize: 14, fontWeight: 600, color: T.tx }}>告警信息</span>
<Tag label="紧急" color={T.dan} bg={T.danL} />
</div>
<InfoRow label="类型" value="血压异常" />
<InfoRow label="触发时间" value="今天 08:30" />
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '12px 0' }}>
<span style={{ fontSize: 13, color: T.tx3 }}>异常值</span>
<div style={{ display: 'flex', alignItems: 'baseline', gap: 4 }}>
<span style={{ fontFamily: T.serif, fontSize: 22, fontWeight: 700, color: T.dan }}>158</span>
<span style={{ fontSize: 13, color: T.tx2 }}>mmHg</span>
<span style={{ fontSize: 12, color: T.tx3, marginLeft: 4 }}>参考 &lt;140</span>
</div>
</div>
</div>
{/* 近期数据 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx, marginBottom: 12 }}>近期数据</div>
{history.map((h, i) => (
<div key={i} style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
padding: '10px 0', borderBottom: i < history.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<span style={{ fontSize: 13, color: T.tx2, width: 40 }}>{h.date}</span>
<span style={{ fontFamily: T.serif, fontSize: 15, fontWeight: 600, color: T.tx, flex: 1 }}>{h.value}</span>
<Tag label={h.note} color={h.color} bg={h.color === T.dan ? T.danL : (h.color === T.wrn ? T.wrnL : T.accL)} />
</div>
))}
</div>
{/* 处理意见 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx, marginBottom: 10 }}>处理意见</div>
<div style={{
height: 72, background: T.bg, borderRadius: T.rSm, border: `1px solid ${T.bd}`,
padding: '12px 14px', fontSize: 13, color: T.tx3, lineHeight: 1.5,
}}>请输入处理意见...</div>
</div>
{/* 操作按钮 */}
<div style={{ display: 'flex', gap: 12 }}>
<ActionButton label="标记已处理" primary style={{ flex: 1 }} />
<ActionButton label="联系患者" style={{ flex: 1 }} />
</div>
</div>
</div>
);
}
// ─── 屏幕3透析列表 ───
function DialysisList() {
const records = [
{ patient: '张三', bed: '3床', mode: 'HD', time: '08:00-12:00', status: '进行中', statusColor: T.wrn, statusBg: T.wrnL,
detail: '超滤 1.8L/2.3L' },
{ patient: '李四', bed: '5床', mode: 'HDF', time: '08:30-12:30', status: '进行中', statusColor: T.wrn, statusBg: T.wrnL,
detail: '超滤 1.2L/2.0L' },
{ patient: '王五', bed: '1床', mode: 'HD', time: '13:00-17:00', status: '待开始', statusColor: T.tx3, statusBg: T.surface,
detail: null },
{ patient: '赵六', bed: '2床', mode: 'HD', time: '08:00-12:00', status: '已完成', statusColor: T.acc, statusBg: T.accL,
detail: '超滤 2.1L' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="透析管理" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 今日统计 */}
<div style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
{[
{ label: '已透析', value: '5', color: T.acc },
{ label: '进行中', value: '2', color: T.wrn },
{ label: '待开始', value: '3', color: T.tx3 },
].map((s, i) => (
<div key={i} style={{
flex: 1, background: T.card, borderRadius: T.rSm, padding: '14px 14px', textAlign: 'center',
boxShadow: '0 1px 8px rgba(0,0,0,0.04)',
}}>
<div style={{ fontFamily: T.serif, fontSize: 24, fontWeight: 700, color: s.color }}>{s.value}</div>
<div style={{ fontSize: 11, color: T.tx3, marginTop: 2 }}>{s.label}</div>
</div>
))}
</div>
{/* 透析记录 */}
{records.map((r, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '16px 18px', marginBottom: 12,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
{/* 头部 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx }}>{r.patient}</span>
<Tag label={r.bed} color={T.priD} bg={T.priL} />
</div>
<Tag label={r.status} color={r.statusColor} bg={r.statusBg} />
</div>
{/* 信息行 */}
<div style={{ display: 'flex', gap: 16, marginBottom: r.detail ? 10 : 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
<span style={{ fontSize: 12, color: T.tx3 }}>模式</span>
<span style={{ fontSize: 13, fontWeight: 600, color: T.pri }}>{r.mode}</span>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
<span style={{ fontSize: 12, color: T.tx3 }}>时段</span>
<span style={{ fontSize: 13, color: T.tx }}>{r.time}</span>
</div>
</div>
{/* 关键指标 */}
{r.detail && (
<div style={{
background: T.bg, borderRadius: T.rXs, padding: '8px 12px',
fontSize: 13, color: T.tx2,
}}>
{r.detail}
</div>
)}
</div>
))}
{/* FAB */}
<div style={{
position: 'sticky', bottom: 10, display: 'flex', justifyContent: 'flex-end', pointerEvents: 'none',
}}>
<div style={{
width: 52, height: 52, borderRadius: 26, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
boxShadow: '0 4px 20px rgba(58,107,140,0.4)', pointerEvents: 'auto', cursor: 'pointer',
}}>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2.5" strokeLinecap="round">
<path d="M12 5v14M5 12h14"/>
</svg>
</div>
</div>
</div>
</div>
);
}
// ─── 屏幕4透析创建 ───
function DialysisCreate() {
const modes = ['HD', 'HDF', 'HF'];
const activeMode = 0;
const dialysate = ['碳酸氢盐', '醋酸盐'];
const anticoagulant = ['低分子肝素', '普通肝素', '无'];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="新增透析记录" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
<FormField label="患者选择" value="张三" placeholder="请选择患者" />
{/* 透析模式 — 按钮横排 */}
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>透析模式</div>
<div style={{ display: 'flex', gap: 10 }}>
{modes.map((m, i) => (
<div key={i} style={{
flex: 1, height: 44, borderRadius: T.rSm, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 14, fontWeight: i === activeMode ? 600 : 400,
color: i === activeMode ? '#fff' : T.tx2,
background: i === activeMode ? T.pri : T.card,
border: `1.5px solid ${i === activeMode ? T.pri : T.bd}`,
cursor: 'pointer',
}}>{m}</div>
))}
</div>
</div>
<FormField label="床位号" value="3床" placeholder="请输入床位号" />
<FormField label="开始时间" value="08:00" placeholder="请选择时间" />
<FormField label="计划时长" value="4小时" placeholder="请输入时长" />
<FormField label="血流量" value="250 ml/min" placeholder="请输入血流量" />
{/* 透析液选择 */}
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>透析液</div>
<div style={{ display: 'flex', gap: 10 }}>
{dialysate.map((d, i) => (
<div key={i} style={{
flex: 1, height: 44, borderRadius: T.rSm, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 13, fontWeight: i === 0 ? 600 : 400,
color: i === 0 ? '#fff' : T.tx2,
background: i === 0 ? T.pri : T.card,
border: `1.5px solid ${i === 0 ? T.pri : T.bd}`,
cursor: 'pointer',
}}>{d}</div>
))}
</div>
</div>
{/* 抗凝剂选择 */}
<div style={{ marginBottom: 14 }}>
<div style={{ fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>抗凝剂</div>
<div style={{ display: 'flex', gap: 8 }}>
{anticoagulant.map((a, i) => (
<div key={i} style={{
flex: 1, height: 44, borderRadius: T.rSm, display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: 12, fontWeight: i === 0 ? 600 : 400,
color: i === 0 ? '#fff' : T.tx2,
background: i === 0 ? T.pri : T.card,
border: `1.5px solid ${i === 0 ? T.pri : T.bd}`,
cursor: 'pointer',
}}>{a}</div>
))}
</div>
</div>
<FormField label="目标超滤量" value="2.3 L" placeholder="请输入目标超滤量" />
{/* 底部按钮 */}
<div style={{ marginTop: 8 }}>
<ActionButton label="开始透析" primary />
</div>
</div>
</div>
);
}
// ─── 屏幕5处方列表 ───
function PrescriptionList() {
const prescriptions = [
{ patient: '张三', id: 'PX-20250401', mode: 'HD', freq: '每周3次', date: '4月1日', status: '生效中', statusColor: T.acc, statusBg: T.accL },
{ patient: '李四', id: 'PX-20250315', mode: 'HDF', freq: '每周2次', date: '3月15日', status: '生效中', statusColor: T.acc, statusBg: T.accL },
{ patient: '王五', id: 'PX-20250201', mode: 'HD', freq: '每周3次', date: '2月1日', status: '已停用', statusColor: T.tx3, statusBg: T.surface },
{ patient: '赵六', id: 'PX-20250110', mode: 'HDF', freq: '每周2次', date: '1月10日', status: '生效中', statusColor: T.acc, statusBg: T.accL },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="透析处方" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 筛选 */}
<FilterTabs tabs={['生效中', '全部']} active={0} />
{/* 处方卡片 */}
{prescriptions.map((p, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: '16px 18px', marginBottom: 12,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
{/* 头部 */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<span style={{ fontFamily: T.serif, fontSize: 16, fontWeight: 700, color: T.tx }}>{p.patient}</span>
<span style={{ fontSize: 12, color: T.tx3 }}>{p.id}</span>
</div>
<Tag label={p.status} color={p.statusColor} bg={p.statusBg} />
</div>
{/* 信息行 */}
<div style={{ display: 'flex', gap: 20, marginBottom: 4 }}>
<div>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>透析模式</div>
<div style={{ fontSize: 14, fontWeight: 600, color: T.pri }}>{p.mode}</div>
</div>
<div>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>频率</div>
<div style={{ fontSize: 14, color: T.tx }}>{p.freq}</div>
</div>
<div>
<div style={{ fontSize: 11, color: T.tx3, marginBottom: 2 }}>生效日期</div>
<div style={{ fontSize: 14, color: T.tx }}>{p.date}</div>
</div>
</div>
</div>
))}
</div>
</div>
);
}
// ─── 屏幕6处方详情 ───
function PrescriptionDetail() {
const params = [
{ label: '处方编号', value: 'PX-20250401' },
{ label: '透析模式', value: '血液透析HD' },
{ label: '频率', value: '每周 3 次(周一/三/五)' },
{ label: '单次时长', value: '4 小时' },
{ label: '血流量', value: '250 ml/min' },
{ label: '透析液流速', value: '500 ml/min' },
{ label: '透析液', value: '碳酸氢盐' },
{ label: '抗凝剂', value: '低分子肝素 4000IU' },
{ label: '干体重', value: '65.0 kg' },
{ label: '目标超滤', value: '2.0-2.5 L' },
{ label: 'Kt/V 目标', value: '≥1.2' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="处方详情" />
<div style={{ flex: 1, overflow: 'auto', padding: '16px 20px 24px' }}>
{/* 患者信息 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '18px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 14,
}}>
<div style={{
width: 44, height: 44, borderRadius: 22, background: T.priL,
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.pri,
}}></div>
<div style={{ flex: 1 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 3 }}>
<span style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color: T.tx }}>张三</span>
<Tag label="生效中" color={T.acc} bg={T.accL} />
</div>
<div style={{ fontSize: 13, color: T.tx3 }}>58 · </div>
</div>
</div>
{/* 详细参数 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '4px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.tx, padding: '14px 0 4px' }}>处方参数</div>
{params.map((p, i) => (
<div key={i} style={{
display: 'flex', justifyContent: 'space-between', alignItems: 'center',
padding: '11px 0', borderBottom: i < params.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<span style={{ fontSize: 13, color: T.tx3 }}>{p.label}</span>
<span style={{ fontSize: 14, color: T.tx, fontWeight: 500, textAlign: 'right', maxWidth: '55%' }}>{p.value}</span>
</div>
))}
</div>
{/* 医生信息 */}
<div style={{
background: T.card, borderRadius: T.r, padding: '16px 20px', marginBottom: 14,
boxShadow: '0 2px 12px rgba(0,0,0,0.04)',
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 3 }}>开方医生</div>
<div style={{ fontSize: 14, color: T.tx, fontWeight: 500 }}>李医生 · 肾内科</div>
</div>
<div style={{ textAlign: 'right' }}>
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 3 }}>生效日期</div>
<div style={{ fontSize: 14, color: T.tx, fontWeight: 500 }}>2025年4月1日</div>
</div>
</div>
</div>
{/* 底部操作 */}
<div style={{ display: 'flex', gap: 12 }}>
<ActionButton label="调整处方" primary style={{ flex: 1 }} />
<ActionButton label="停用处方" danger style={{ flex: 1 }} />
</div>
</div>
</div>
);
}
// ─── 渲染 ───
function App() {
return (
<div class="screens">
<IosFrame label="告警列表" time="9:41" battery={85}>
<AlertList />
</IosFrame>
<IosFrame label="告警详情" time="9:41" battery={85}>
<AlertDetail />
</IosFrame>
<IosFrame label="透析列表" time="9:42" battery={84}>
<DialysisList />
</IosFrame>
<IosFrame label="透析创建" time="9:43" battery={84}>
<DialysisCreate />
</IosFrame>
<IosFrame label="处方列表" time="9:43" battery={83}>
<PrescriptionList />
</IosFrame>
<IosFrame label="处方详情" time="9:44" battery={83}>
<PrescriptionDetail />
</IosFrame>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>