- 新增 12 个核心页面原型(登录/首页/咨询/预约/商城/健康等) - 新增医生端分包原型(核心 + 临床两个分包) - 新增 AI 客服对话页原型 - 新增 MP UI 优化指南文档 - 更新 wiki 基础设施和小程序文档
481 lines
29 KiB
HTML
481 lines
29 KiB
HTML
<!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: 40px; 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; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class="page-title">HMS 小程序 · 个人中心其他页面</div>
|
||
<div class="note">温润东方风设计系统 — 个人中心子页面原型。6 个屏幕:家庭管理 / 添加家庭成员 / 知情同意 / 事件记录 / 长者模式 / 设置。</div>
|
||
<div id="root"></div>
|
||
|
||
<script type="text/babel">
|
||
// ─── 设计 Token ───
|
||
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,
|
||
};
|
||
|
||
// ─── 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 }) {
|
||
const statusColor = darkStatus ? '#fff' : '#000';
|
||
return (
|
||
<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 style={iosFrameStyles.content}>{children}</div>
|
||
<div style={iosFrameStyles.homeIndicator} />
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ─── 导航栏组件 ───
|
||
function NavBar({ title, dark = false }) {
|
||
const color = dark ? '#fff' : T.tx;
|
||
return (
|
||
<div style={{ height: 44, display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'relative', borderBottom: `1px solid ${T.bdL}`, background: dark ? 'transparent' : T.card }}>
|
||
<svg style={{ position: 'absolute', left: 16, top: 12 }} width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
|
||
<span style={{ fontFamily: T.serif, fontSize: 17, fontWeight: 700, color }}>{title}</span>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ─── 右箭头图标 ───
|
||
function ArrowRight({ color = T.tx3 }) {
|
||
return <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"/></svg>;
|
||
}
|
||
|
||
// ─── 开关组件 ───
|
||
function Toggle({ on = false, color = T.pri }) {
|
||
return (
|
||
<div style={{ width: 48, height: 28, borderRadius: 14, background: on ? color : '#D1D5DB', position: 'relative', transition: 'background 0.2s', flexShrink: 0 }}>
|
||
<div style={{ width: 24, height: 24, borderRadius: 12, background: '#fff', position: 'absolute', top: 2, left: on ? 22 : 2, boxShadow: '0 1px 3px rgba(0,0,0,0.15)', transition: 'left 0.2s' }} />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// 屏幕1:家庭管理
|
||
// ═══════════════════════════════════════════════════════════════
|
||
function FamilyPage() {
|
||
const patients = [
|
||
{ name: '张三', relation: '本人', phone: '138****1234', isDefault: true, color: T.pri },
|
||
{ name: '张父', relation: '父亲', phone: '139****5678', isDefault: false, color: T.acc },
|
||
{ name: '张母', relation: '母亲', phone: '136****9012', isDefault: false, color: T.wrn },
|
||
];
|
||
|
||
return (
|
||
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
|
||
<NavBar title="就诊人管理" />
|
||
<div style={{ padding: '16px' }}>
|
||
{patients.map((p, i) => (
|
||
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 12, boxShadow: '0 1px 4px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 12 }}>
|
||
{/* 头像 */}
|
||
<div style={{ width: 48, height: 48, borderRadius: 24, background: p.isDefault ? T.priL : T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
||
<span style={{ fontSize: 18, fontWeight: 700, color: p.isDefault ? T.priD : T.tx2, fontFamily: T.serif }}>{p.name[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>
|
||
<span style={{ fontSize: 12, color: T.tx3, background: T.surface, padding: '2px 8px', borderRadius: 6 }}>{p.relation}</span>
|
||
{p.isDefault && (
|
||
<span style={{ fontSize: 11, color: T.priD, background: T.priL, padding: '2px 8px', borderRadius: 6, fontWeight: 600 }}>默认</span>
|
||
)}
|
||
</div>
|
||
<span style={{ fontSize: 13, color: T.tx3 }}>{p.phone}</span>
|
||
</div>
|
||
{/* 箭头 */}
|
||
<ArrowRight />
|
||
</div>
|
||
))}
|
||
|
||
{/* 添加就诊人按钮 */}
|
||
<div style={{ border: `2px dashed ${T.bd}`, borderRadius: T.r, padding: '16px 0', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, marginTop: 4, cursor: 'pointer' }}>
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={T.pri} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
|
||
<span style={{ fontSize: 15, color: T.pri, fontWeight: 500 }}>添加就诊人</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// 屏幕2:添加家庭成员
|
||
// ═══════════════════════════════════════════════════════════════
|
||
function FamilyAddPage() {
|
||
const FieldStyle = { width: '100%', height: 56, background: T.card, border: `1.5px solid ${T.bd}`, borderRadius: T.r, padding: '0 16px', fontSize: 15, color: T.tx, outline: 'none', fontFamily: T.sans };
|
||
|
||
return (
|
||
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
|
||
<NavBar title="添加就诊人" />
|
||
<div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
|
||
{/* 姓名 */}
|
||
<div>
|
||
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>姓名</label>
|
||
<input style={FieldStyle} placeholder="请输入真实姓名" />
|
||
</div>
|
||
|
||
{/* 关系 */}
|
||
<div>
|
||
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>关系</label>
|
||
<div style={{ ...FieldStyle, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: T.tx3 }}>
|
||
<span>请选择关系</span>
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 手机号 */}
|
||
<div>
|
||
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>手机号</label>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
||
<div style={{ height: 56, background: T.surface, borderRadius: T.r, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '0 14px', fontSize: 14, color: T.tx, fontWeight: 600, flexShrink: 0, border: `1.5px solid ${T.bd}` }}>
|
||
+86
|
||
</div>
|
||
<input style={{ ...FieldStyle, flex: 1 }} placeholder="请输入手机号" type="tel" />
|
||
</div>
|
||
</div>
|
||
|
||
{/* 身份证号 */}
|
||
<div>
|
||
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>身份证号</label>
|
||
<input style={FieldStyle} placeholder="请输入身份证号" />
|
||
</div>
|
||
|
||
{/* 出生日期 */}
|
||
<div>
|
||
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>出生日期</label>
|
||
<div style={{ ...FieldStyle, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: T.tx3 }}>
|
||
<span>请选择出生日期</span>
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx3} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 性别 */}
|
||
<div>
|
||
<label style={{ display: 'block', fontSize: 13, color: T.tx2, marginBottom: 6, fontWeight: 500 }}>性别</label>
|
||
<div style={{ display: 'flex', gap: 12 }}>
|
||
{['男', '女'].map((g, i) => (
|
||
<div key={g} style={{ flex: 1, height: 56, borderRadius: T.r, border: i === 0 ? `2px solid ${T.pri}` : `1.5px solid ${T.bd}`, background: i === 0 ? T.priL : T.card, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8, cursor: 'pointer' }}>
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={i === 0 ? T.pri : T.tx3} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||
{i === 0 ? (<><circle cx="10.5" cy="10.5" r="7"/><line x1="16" y1="16" x2="21" y2="21"/></>) : (<><circle cx="12" cy="12" r="7"/><line x1="8" y1="8" x2="16" y2="16"/></>)}
|
||
</svg>
|
||
<span style={{ fontSize: 15, fontWeight: 600, color: i === 0 ? T.pri : T.tx2 }}>{g}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 保存按钮 */}
|
||
<div style={{ marginTop: 10 }}>
|
||
<div style={{ height: 56, borderRadius: T.r, background: T.pri, display: 'flex', alignItems: 'center', justifyContent: 'center', boxShadow: `0 4px 16px rgba(196,98,58,0.3)`, cursor: 'pointer' }}>
|
||
<span style={{ fontSize: 17, fontWeight: 600, color: '#fff' }}>保存</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// 屏幕3:知情同意
|
||
// ═══════════════════════════════════════════════════════════════
|
||
function ConsentsPage() {
|
||
const consents = [
|
||
{ title: '血液透析知情同意书', date: '2025-04-01', status: 'signed', icon: 'blood' },
|
||
{ title: '透析血管通路知情同意书', date: '2025-04-01', status: 'signed', icon: 'vein' },
|
||
{ title: '数据共享知情同意书', date: '', status: 'pending', icon: 'data' },
|
||
];
|
||
|
||
return (
|
||
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
|
||
<NavBar title="知情同意书" />
|
||
<div style={{ padding: 16 }}>
|
||
{consents.map((c, i) => (
|
||
<div key={i} style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 12, boxShadow: '0 1px 4px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', gap: 12 }}>
|
||
{/* 图标 */}
|
||
<div style={{ width: 44, height: 44, borderRadius: T.rSm, background: c.status === 'signed' ? T.accL : T.wrnL, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={c.status === 'signed' ? T.acc : T.wrn} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
|
||
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/>
|
||
</svg>
|
||
</div>
|
||
{/* 信息 */}
|
||
<div style={{ flex: 1, minWidth: 0 }}>
|
||
<div style={{ fontFamily: T.serif, fontSize: 14, fontWeight: 600, color: T.tx, marginBottom: 4, lineHeight: 1.4 }}>{c.title}</div>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||
{c.date && <span style={{ fontSize: 12, color: T.tx3 }}>{c.date}</span>}
|
||
<span style={{ fontSize: 11, fontWeight: 600, color: c.status === 'signed' ? T.acc : T.wrn, background: c.status === 'signed' ? T.accL : T.wrnL, padding: '2px 8px', borderRadius: 6 }}>
|
||
{c.status === 'signed' ? '已签署' : '待签署'}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<ArrowRight />
|
||
</div>
|
||
))}
|
||
|
||
{/* 底部提示 */}
|
||
<div style={{ textAlign: 'center', marginTop: 20, padding: '0 20px' }}>
|
||
<p style={{ fontSize: 12, color: T.tx3, lineHeight: 1.8 }}>签署后的同意书具有法律效力,请仔细阅读后再签署。</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// 屏幕4:事件记录
|
||
// ═══════════════════════════════════════════════════════════════
|
||
function EventsPage() {
|
||
const events = [
|
||
{ date: '5月8日', desc: '开始透析治疗', color: T.pri, bg: T.priL, type: '治疗' },
|
||
{ date: '4月15日', desc: '调整透析方案', color: T.acc, bg: T.accL, type: '方案' },
|
||
{ date: '3月20日', desc: '完成血管通路手术', color: T.wrn, bg: T.wrnL, type: '手术' },
|
||
{ date: '2月10日', desc: '首次门诊', color: T.pri, bg: T.priL, type: '门诊' },
|
||
{ date: '2024-12-01', desc: '确诊慢性肾病', color: T.dan, bg: T.danL, type: '诊断' },
|
||
];
|
||
|
||
return (
|
||
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
|
||
<NavBar title="事件记录" />
|
||
<div style={{ padding: '16px 16px 16px 24px' }}>
|
||
{/* 时间线 */}
|
||
<div style={{ position: 'relative' }}>
|
||
{/* 竖线 */}
|
||
<div style={{ position: 'absolute', left: 7, top: 12, bottom: 12, width: 2, background: T.bdL, borderRadius: 1 }} />
|
||
|
||
{events.map((e, i) => (
|
||
<div key={i} style={{ position: 'relative', paddingLeft: 28, marginBottom: i < events.length - 1 ? 20 : 0 }}>
|
||
{/* 圆点 */}
|
||
<div style={{ position: 'absolute', left: 0, top: 6, width: 16, height: 16, borderRadius: 8, background: e.color, border: `3px solid ${e.bg}`, boxShadow: `0 0 0 2px ${e.bg}`, zIndex: 1 }} />
|
||
|
||
{/* 事件卡片 */}
|
||
<div style={{ background: T.card, borderRadius: T.rSm, padding: 14, boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
|
||
<span style={{ fontSize: 13, color: T.tx3, fontWeight: 500 }}>{e.date}</span>
|
||
<span style={{ fontSize: 11, color: e.color, background: e.bg, padding: '2px 8px', borderRadius: 6, fontWeight: 600 }}>{e.type}</span>
|
||
</div>
|
||
<div style={{ fontSize: 15, fontWeight: 600, color: T.tx, lineHeight: 1.4 }}>{e.desc}</div>
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// 屏幕5:长者模式
|
||
// ═══════════════════════════════════════════════════════════════
|
||
function ElderModePage() {
|
||
return (
|
||
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
|
||
<NavBar title="关怀模式" />
|
||
<div style={{ padding: 16 }}>
|
||
{/* 说明区域 */}
|
||
<div style={{ background: T.accL, borderLeft: `4px solid ${T.acc}`, borderRadius: '0 T.rSm T.rSm 0', padding: '14px 16px', marginBottom: 20 }}>
|
||
<div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
|
||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke={T.acc} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0, marginTop: 1 }}>
|
||
<circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/>
|
||
</svg>
|
||
<span style={{ fontSize: 13, color: T.acc, lineHeight: 1.7, fontWeight: 500 }}>开启关怀模式后,字体将放大,界面更简洁,方便阅读。</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 模式开关卡片 */}
|
||
<div style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 16, boxShadow: '0 1px 4px rgba(0,0,0,0.04)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||
<div style={{ width: 40, height: 40, borderRadius: 12, background: T.priL, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke={T.pri} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>
|
||
</div>
|
||
<div>
|
||
<div style={{ fontSize: 16, fontWeight: 600, color: T.tx }}>关怀模式</div>
|
||
<div style={{ fontSize: 12, color: T.tx3, marginTop: 2 }}>放大字号,简化界面</div>
|
||
</div>
|
||
</div>
|
||
<Toggle on={true} color={T.pri} />
|
||
</div>
|
||
|
||
{/* 字号预览 */}
|
||
<div style={{ background: T.card, borderRadius: T.r, padding: 16, marginBottom: 16, boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
|
||
<div style={{ fontSize: 13, color: T.tx3, marginBottom: 12, fontWeight: 500 }}>字号预览</div>
|
||
|
||
{/* 标准字号 */}
|
||
<div style={{ marginBottom: 14 }}>
|
||
<span style={{ fontSize: 11, color: T.tx3, display: 'block', marginBottom: 4 }}>标准</span>
|
||
<div style={{ background: T.surface, borderRadius: T.rXs, padding: '10px 14px' }}>
|
||
<span style={{ fontSize: 15, color: T.tx }}>血压 130/85 mmHg</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 放大字号 */}
|
||
<div>
|
||
<span style={{ fontSize: 11, color: T.pri, display: 'block', marginBottom: 4, fontWeight: 600 }}>关怀模式</span>
|
||
<div style={{ background: T.priL, borderRadius: T.rXs, padding: '12px 14px' }}>
|
||
<span style={{ fontSize: 22, color: T.priD, fontWeight: 600 }}>血压 130/85 mmHg</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 其他设置 */}
|
||
<div style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
|
||
{/* 高对比度 */}
|
||
<div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: `1px solid ${T.bdL}` }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||
<div style={{ width: 36, height: 36, borderRadius: 10, background: T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx2} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 2a10 10 0 000 20z"/></svg>
|
||
</div>
|
||
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500 }}>高对比度模式</span>
|
||
</div>
|
||
<Toggle on={false} />
|
||
</div>
|
||
|
||
{/* 语音播报 */}
|
||
<div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||
<div style={{ width: 36, height: 36, borderRadius: 10, background: T.surface, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={T.tx2} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/><path d="M19.07 4.93a10 10 0 010 14.14M15.54 8.46a5 5 0 010 7.07"/></svg>
|
||
</div>
|
||
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500 }}>语音播报</span>
|
||
</div>
|
||
<Toggle on={false} />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// 屏幕6:设置
|
||
// ═══════════════════════════════════════════════════════════════
|
||
function SettingsPage() {
|
||
const settingsGroups = [
|
||
[
|
||
{ icon: 'shield', iconBg: T.acc, label: '账号与安全', value: '' },
|
||
{ icon: 'bell', iconBg: T.wrn, label: '消息通知', value: '' },
|
||
{ icon: 'eye', iconBg: T.pri, label: '隐私设置', value: '' },
|
||
],
|
||
[
|
||
{ icon: 'globe', iconBg: '#6B8ABF', label: '语言', value: '简体中文' },
|
||
{ icon: 'trash', iconBg: T.tx3, label: '清除缓存', value: '12.3 MB' },
|
||
{ icon: 'info', iconBg: T.tx2, label: '关于 HMS', value: '' },
|
||
],
|
||
];
|
||
|
||
const iconPaths = {
|
||
shield: <><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></>,
|
||
bell: <><path d="M18 8A6 6 0 006 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 01-3.46 0"/></>,
|
||
eye: <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></>,
|
||
globe: <><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 014 10 15.3 15.3 0 01-4 10 15.3 15.3 0 01-4-10 15.3 15.3 0 014-10z"/></>,
|
||
trash: <><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></>,
|
||
info: <><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></>,
|
||
};
|
||
|
||
return (
|
||
<div style={{ background: T.bg, minHeight: '100%', fontFamily: T.sans }}>
|
||
<NavBar title="设置" />
|
||
<div style={{ padding: 16 }}>
|
||
{settingsGroups.map((group, gi) => (
|
||
<div key={gi} style={{ background: T.card, borderRadius: T.r, overflow: 'hidden', marginBottom: 16, boxShadow: '0 1px 4px rgba(0,0,0,0.04)' }}>
|
||
{group.map((item, ii) => (
|
||
<div key={ii} style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: ii < group.length - 1 ? `1px solid ${T.bdL}` : 'none' }}>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
||
<div style={{ width: 34, height: 34, borderRadius: 10, background: item.iconBg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
|
||
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">{iconPaths[item.icon]}</svg>
|
||
</div>
|
||
<span style={{ fontSize: 15, color: T.tx, fontWeight: 500 }}>{item.label}</span>
|
||
</div>
|
||
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
|
||
{item.value && <span style={{ fontSize: 13, color: T.tx3 }}>{item.value}</span>}
|
||
<ArrowRight />
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
))}
|
||
|
||
{/* 版本号 + 退出登录 */}
|
||
<div style={{ textAlign: 'center', marginTop: 20 }}>
|
||
<div style={{ fontSize: 12, color: T.tx3, marginBottom: 16 }}>v1.0.0</div>
|
||
<div style={{ height: 48, borderRadius: T.r, border: `1.5px solid ${T.dan}`, display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer' }}>
|
||
<span style={{ fontSize: 15, fontWeight: 600, color: T.dan }}>退出登录</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════
|
||
// 主渲染
|
||
// ═══════════════════════════════════════════════════════════════
|
||
function App() {
|
||
const screens = [
|
||
{ label: '家庭管理', component: <FamilyPage /> },
|
||
{ label: '添加家庭成员', component: <FamilyAddPage /> },
|
||
{ label: '知情同意', component: <ConsentsPage /> },
|
||
{ label: '事件记录', component: <EventsPage /> },
|
||
{ label: '长者模式', component: <ElderModePage /> },
|
||
{ label: '设置', component: <SettingsPage /> },
|
||
];
|
||
|
||
return (
|
||
<div className="screens">
|
||
{screens.map((s, i) => (
|
||
<div key={i} className="screen-wrap">
|
||
<IosFrame width={340} height={740}>
|
||
{s.component}
|
||
</IosFrame>
|
||
<div className="screen-label">{s.label}</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
|
||
</script>
|
||
</body>
|
||
</html> |