Files
hms/docs/design/mp-13-family-profile.html
iven 3aa71a94d2 docs(skills): design-handoff 设计稿 + spec + .gitignore 更新
- mp-11-doctor-core 设计交付包(截图 + tokens)
- mp-13/mp-14 新原型 HTML
- design-handoff skill 设计规格文档
- .gitignore 排除 dist-h5/test-results/uploads 等构建产物
2026-05-18 02:13:29 +08:00

259 lines
12 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: 900px; 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; }
::-webkit-scrollbar { width: 0; height: 0; }
</style>
</head>
<body>
<div class="page-title">HMS 小程序 · 就诊人管理 + 建档</div>
<div class="note">温润东方风设计系统 — 就诊人列表(切换/编辑)+ 新建就诊人表单,两屏并排。表单即建档,建档后解锁积分商城等功能。</div>
<div id="root"></div>
<script type="text/babel">
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 = 370, height = 800, time = '9:41', battery = 85 }) {
return (
<div style={iosFrameStyles.wrapper}>
<div style={{ ...iosFrameStyles.screen, width, height }}>
<div style={{ ...iosFrameStyles.statusBar, color: '#000' }}>
<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 0 000 2z" fill="#000"/><path d="M3 7.5a7 7 0 0110 0" stroke="#000" strokeWidth="1.3" fill="none" strokeLinecap="round"/><path d="M1 4.5a11 11 0 0114 0" stroke="#000" strokeWidth="1.3" fill="none" strokeLinecap="round" opacity="0.7"/></svg>
<div style={{ width: 26, height: 12, border: '1.5px solid #000', borderRadius: 3, padding: 1, position: 'relative' }}>
<div style={{ width: `${battery}%`, height: '100%', background: '#000', borderRadius: 1 }} />
</div>
</div>
</div>
<div style={iosFrameStyles.dynamicIsland} />
<div style={iosFrameStyles.content}>{children}</div>
<div style={iosFrameStyles.homeIndicator} />
</div>
</div>
);
}
const T = {
pri: '#C4623A', priL: '#F0DDD4', priD: '#8B3E1F',
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',
borderBottom: `1px solid ${T.bdL}`, position: 'relative', background: T.bg, flexShrink: 0
}}>
<svg style={{ position: 'absolute', left: 16, top: '50%', transform: 'translateY(-50%)' }} width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M15 19l-7-7 7-7" stroke={T.tx} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
<span style={{ fontFamily: T.serif, fontSize: 18, fontWeight: 700, color: T.tx }}>{title}</span>
</div>
);
}
// ─── 就诊人列表 ───
function FamilyList() {
const patients = [
{ name: '张三', relation: '本人', gender: '男', birth: '1985-03-15', active: true },
{ name: '李四', relation: '配偶', gender: '女', birth: '1988-07-22', active: false },
];
const relationColors = { '本人': T.pri, '配偶': T.acc, '父母': T.wrn, '子女': '#8B7ACC', '其他': T.tx3 };
const relationBgs = { '本人': T.priL, '配偶': T.accL, '父母': T.wrnL, '子女': '#EDE8F4', '其他': T.surface };
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="就诊人管理" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 20px 100px' }}>
{/* 提示 */}
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 16, lineHeight: 1.5 }}>
完善信息后即可使用积分商城签到等功能可添加多位家庭成员
</div>
{patients.map((p, i) => (
<div key={i} style={{
background: T.card, borderRadius: T.r, padding: 16, marginBottom: 12,
boxShadow: '0 1px 4px rgba(45,42,38,0.06)',
border: p.active ? `2px solid ${T.pri}` : '2px solid transparent',
position: 'relative',
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
{/* 头像 */}
<div style={{
width: 48, height: 48, borderRadius: 24,
background: `linear-gradient(135deg, ${relationBgs[p.relation] || T.surface} 0%, ${relationColors[p.relation] || T.tx3} 100%)`,
display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
}}>
<span style={{ fontFamily: T.serif, fontSize: 20, fontWeight: 700, color: '#fff' }}>
{p.name.charAt(0)}
</span>
</div>
{/* 信息 */}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 4 }}>
<span style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>{p.name}</span>
{p.active && (
<span style={{ fontSize: 11, padding: '2px 8px', borderRadius: 999, background: T.priL, color: T.pri, fontWeight: 600 }}>
当前
</span>
)}
</div>
<div style={{ display: 'flex', gap: 8, fontSize: 13, color: T.tx3 }}>
<span style={{ padding: '1px 6px', borderRadius: 4, background: relationBgs[p.relation] || T.surface, color: relationColors[p.relation] || T.tx3, fontWeight: 500 }}>
{p.relation}
</span>
<span>{p.gender}</span>
<span>{p.birth.slice(0, 4)}</span>
</div>
</div>
{/* 编辑 */}
<span style={{ fontSize: 14, color: T.pri, fontWeight: 500, flexShrink: 0 }}>编辑</span>
</div>
</div>
))}
{/* 添加按钮 */}
<div style={{
height: 52, borderRadius: T.r, border: `2px dashed ${T.bd}`,
display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
color: T.pri, fontSize: 16, fontWeight: 600,
}}>
<span style={{ fontSize: 20 }}>+</span>
<span>添加就诊人</span>
</div>
</div>
</div>
);
}
// ─── 新建就诊人(建档) ───
function FamilyAdd() {
const formItems = [
{ label: '姓名', placeholder: '请输入真实姓名', type: 'text' },
{ label: '关系', placeholder: '本人', type: 'select' },
{ label: '性别', placeholder: '男', type: 'select' },
{ label: '出生日期', placeholder: '请选择', type: 'date' },
{ label: '手机号', placeholder: '选填,用于接收通知', type: 'text' },
{ label: '身份证号', placeholder: '选填,用于医保对接', type: 'text' },
];
return (
<div style={{ height: '100%', background: T.bg, display: 'flex', flexDirection: 'column' }}>
<NavBar title="添加就诊人" />
<div style={{ flex: 1, overflow: 'auto', padding: '20px 16px 100px' }}>
{/* 顶部提示卡片 */}
<div style={{
background: T.priL, borderRadius: T.r, padding: '14px 16px', marginBottom: 20,
borderLeft: `4px solid ${T.pri}`,
}}>
<div style={{ fontSize: 14, fontWeight: 600, color: T.pri, marginBottom: 4 }}>完善个人信息</div>
<div style={{ fontSize: 13, color: T.tx2, lineHeight: 1.6 }}>
完善信息后即可使用积分商城签到等功能请填写真实信息
</div>
</div>
{/* 表单 */}
<div style={{
background: T.card, borderRadius: T.r, overflow: 'hidden',
boxShadow: '0 1px 4px rgba(45,42,38,0.06)',
}}>
{formItems.map((item, i) => (
<div key={i} style={{
padding: '14px 16px',
borderBottom: i < formItems.length - 1 ? `1px solid ${T.bdL}` : 'none',
}}>
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 8, fontWeight: 500 }}>
{item.label}
{i < 4 && <span style={{ color: T.dan, marginLeft: 2 }}>*</span>}
</div>
{item.type === 'select' || item.type === 'date' ? (
<div style={{
height: 44, background: T.bg, border: `1.5px solid ${T.bd}`, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 14px',
}}>
<span style={{ fontSize: 15, color: item.placeholder === '请选择' ? T.tx3 : T.tx }}>
{item.placeholder}
</span>
<span style={{ color: T.tx3, fontSize: 14 }}></span>
</div>
) : (
<div style={{
height: 44, background: T.bg, border: `1.5px solid ${T.bd}`, borderRadius: T.rSm,
display: 'flex', alignItems: 'center', padding: '0 14px',
}}>
<span style={{ fontSize: 15, color: T.tx3 }}>{item.placeholder}</span>
</div>
)}
</div>
))}
</div>
{/* 提交按钮 */}
<div style={{
height: 52, borderRadius: T.r, background: T.pri,
display: 'flex', alignItems: 'center', justifyContent: 'center',
marginTop: 24,
boxShadow: '0 4px 16px rgba(196,98,58,0.3)',
}}>
<span style={{ fontSize: 17, fontWeight: 600, color: '#fff' }}>确认建档</span>
</div>
</div>
</div>
);
}
function App() {
return (
<div className="screens">
<div className="screen-wrap">
<span className="screen-label">就诊人列表</span>
<IosFrame time="9:41" battery={85}>
<FamilyList />
</IosFrame>
</div>
<div className="screen-wrap">
<span className="screen-label">新建就诊人建档</span>
<IosFrame time="9:42" battery={84}>
<FamilyAdd />
</IosFrame>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>