- docs/: 设计规格、讨论记录、销售数据、健康管理文档 - scripts/: 辅助脚本 - package.json + pnpm-lock.yaml: monorepo 根配置
318 lines
16 KiB
HTML
318 lines
16 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" crossorigin></script>
|
||
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
|
||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body { font-family: -apple-system, 'PingFang SC', 'Helvetica Neue', sans-serif; background: #F5F0EB; color: #2D2A26; line-height: 1.6; }
|
||
:root {
|
||
--bg: #F5F0EB;
|
||
--surface: #FFFFFF;
|
||
--surface-alt: #EDE8E2;
|
||
--text-primary: #2D2A26;
|
||
--text-secondary: #7A756E;
|
||
--text-tertiary: #A8A29E;
|
||
--accent: #C4623A;
|
||
--accent-light: #F0DDD4;
|
||
--accent-dark: #8B3E1F;
|
||
--success: #5B7A5E;
|
||
--success-light: #E8F0E8;
|
||
--warning: #C4873A;
|
||
--warning-light: #FFF3E0;
|
||
--danger: #B54A4A;
|
||
--danger-light: #FDEAEA;
|
||
--border: #E8E2DC;
|
||
--border-light: #F0EBE5;
|
||
--shadow: 0 1px 4px rgba(45,42,38,0.06);
|
||
--shadow-md: 0 4px 16px rgba(45,42,38,0.08);
|
||
--radius: 12px;
|
||
--radius-sm: 8px;
|
||
--radius-lg: 16px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="root"></div>
|
||
<script type="text/babel">
|
||
const dsStyles = {
|
||
page: { maxWidth: 1200, margin: '0 auto', padding: '60px 40px' },
|
||
title: { fontFamily: '"Noto Serif SC", serif', fontSize: 36, fontWeight: 700, color: '#2D2A26', marginBottom: 8 },
|
||
subtitle: { fontSize: 16, color: '#7A756E', marginBottom: 48, letterSpacing: '0.02em' },
|
||
section: { marginBottom: 56 },
|
||
sectionTitle: { fontFamily: '"Noto Serif SC", serif', fontSize: 22, fontWeight: 600, color: '#2D2A26', marginBottom: 24, paddingBottom: 12, borderBottom: '1px solid #E8E2DC' },
|
||
row: { display: 'flex', gap: 16, flexWrap: 'wrap', marginBottom: 16 },
|
||
card: { background: '#fff', borderRadius: 12, padding: 24, boxShadow: '0 1px 4px rgba(45,42,38,0.06)' },
|
||
};
|
||
|
||
/* ─── 色彩系统 ─── */
|
||
const ColorSwatch = ({ name, hex, desc, light }) => (
|
||
<div style={{ flex: '0 0 160px' }}>
|
||
<div style={{
|
||
height: 80, borderRadius: 12, background: hex,
|
||
border: light ? '1px solid #E8E2DC' : 'none',
|
||
marginBottom: 8, boxShadow: hex === '#FFFFFF' ? '0 1px 4px rgba(0,0,0,0.08)' : 'none',
|
||
}} />
|
||
<div style={{ fontSize: 13, fontWeight: 600, color: '#2D2A26' }}>{name}</div>
|
||
<div style={{ fontSize: 12, color: '#7A756E', fontFamily: 'monospace' }}>{hex}</div>
|
||
{desc && <div style={{ fontSize: 11, color: '#A8A29E', marginTop: 2 }}>{desc}</div>}
|
||
</div>
|
||
);
|
||
|
||
const ColorSection = () => {
|
||
const colors = [
|
||
{ name: '背景', hex: '#F5F0EB', desc: 'warm cream', light: true },
|
||
{ name: '卡片', hex: '#FFFFFF', desc: 'surface', light: true },
|
||
{ name: '辅助底', hex: '#EDE8E2', desc: 'surface-alt', light: true },
|
||
{ name: '主文字', hex: '#2D2A26', desc: 'warm black' },
|
||
{ name: '次文字', hex: '#7A756E', desc: 'warm gray' },
|
||
{ name: '淡文字', hex: '#A8A29E', desc: 'tertiary' },
|
||
{ name: '边框', hex: '#E8E2DC', desc: 'border', light: true },
|
||
];
|
||
const accent = [
|
||
{ name: '强调色', hex: '#C4623A', desc: 'terracotta' },
|
||
{ name: '强调浅', hex: '#F0DDD4', desc: 'accent-light', light: true },
|
||
{ name: '强调深', hex: '#8B3E1F', desc: 'accent-dark' },
|
||
];
|
||
const status = [
|
||
{ name: '成功', hex: '#5B7A5E', desc: 'sage green' },
|
||
{ name: '警告', hex: '#C4873A', desc: 'warm amber' },
|
||
{ name: '危险', hex: '#B54A4A', desc: 'muted red' },
|
||
{ name: '成功浅', hex: '#E8F0E8', desc: 'success-light', light: true },
|
||
{ name: '警告浅', hex: '#FFF3E0', desc: 'warning-light', light: true },
|
||
{ name: '危险浅', hex: '#FDEAEA', desc: 'danger-light', light: true },
|
||
];
|
||
return (
|
||
<div style={dsStyles.section}>
|
||
<div style={dsStyles.sectionTitle}>色彩</div>
|
||
<div style={{ fontSize: 13, color: '#7A756E', marginBottom: 16 }}>
|
||
温润米底 + 赤土橙贯穿全场。单一 accent 不多色。色值从 oklch 定义保证和谐。
|
||
</div>
|
||
<div style={dsStyles.row}>
|
||
{colors.map(c => <ColorSwatch key={c.hex} {...c} />)}
|
||
</div>
|
||
<div style={{ fontSize: 14, fontWeight: 600, color: '#2D2A26', margin: '20px 0 12px' }}>强调色</div>
|
||
<div style={dsStyles.row}>
|
||
{accent.map(c => <ColorSwatch key={c.hex} {...c} />)}
|
||
</div>
|
||
<div style={{ fontSize: 14, fontWeight: 600, color: '#2D2A26', margin: '20px 0 12px' }}>状态色</div>
|
||
<div style={dsStyles.row}>
|
||
{status.map(c => <ColorSwatch key={c.hex} {...c} />)}
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
/* ─── 字体系统 ─── */
|
||
const TypographySection = () => {
|
||
const sizes = [
|
||
{ name: '大标题', style: { fontFamily: '"Noto Serif SC", serif', fontSize: 28, fontWeight: 700 } },
|
||
{ name: '标题', style: { fontFamily: '"Noto Serif SC", serif', fontSize: 22, fontWeight: 600 } },
|
||
{ name: '小标题', style: { fontFamily: '"Noto Serif SC", serif', fontSize: 17, fontWeight: 600 } },
|
||
{ name: '正文', style: { fontFamily: '-apple-system, "PingFang SC", sans-serif', fontSize: 15, fontWeight: 400 } },
|
||
{ name: '辅助文字', style: { fontFamily: '-apple-system, "PingFang SC", sans-serif', fontSize: 13, fontWeight: 400, color: '#7A756E' } },
|
||
{ name: '数据大号', style: { fontFamily: '"Noto Serif SC", serif', fontSize: 36, fontWeight: 700, color: '#C4623A' } },
|
||
{ name: '数据中号', style: { fontFamily: '"Noto Serif SC", serif', fontSize: 24, fontWeight: 600 } },
|
||
{ name: '数据单位', style: { fontFamily: '-apple-system, "PingFang SC", sans-serif', fontSize: 13, fontWeight: 400, color: '#A8A29E' } },
|
||
];
|
||
return (
|
||
<div style={dsStyles.section}>
|
||
<div style={dsStyles.sectionTitle}>字体</div>
|
||
<div style={{ fontSize: 13, color: '#7A756E', marginBottom: 20 }}>
|
||
衬线 display (Noto Serif SC) 用于标题和数据数字,系统无衬线用于正文。字重对比鲜明。
|
||
</div>
|
||
<div style={{ background: '#fff', borderRadius: 12, padding: 28, boxShadow: '0 1px 4px rgba(45,42,38,0.06)' }}>
|
||
{sizes.map(s => (
|
||
<div key={s.name} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', padding: '12px 0', borderBottom: '1px solid #F0EBE5' }}>
|
||
<div style={s.style}>{s.name}</div>
|
||
<div style={{ fontSize: 12, color: '#A8A29E', fontFamily: 'monospace' }}>
|
||
{s.style.fontSize}px / {s.style.fontWeight} {s.style.fontFamily?.includes('Serif') ? '· serif' : '· sans'}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
/* ─── 间距与圆角 ─── */
|
||
const SpacingSection = () => {
|
||
const spacings = [4, 8, 12, 16, 20, 24, 32, 40, 48];
|
||
const radii = [
|
||
{ name: 'sm', value: 8 },
|
||
{ name: 'md', value: 12 },
|
||
{ name: 'lg', value: 16 },
|
||
{ name: 'xl', value: 20 },
|
||
{ name: 'pill', value: 999 },
|
||
];
|
||
return (
|
||
<div style={dsStyles.section}>
|
||
<div style={dsStyles.sectionTitle}>间距与圆角</div>
|
||
<div style={{ display: 'flex', gap: 32, flexWrap: 'wrap' }}>
|
||
<div style={{ flex: 1 }}>
|
||
<div style={{ fontSize: 13, color: '#7A756E', marginBottom: 12 }}>间距基准 4px</div>
|
||
<div style={{ display: 'flex', alignItems: 'flex-end', gap: 8 }}>
|
||
{spacings.map(s => (
|
||
<div key={s} style={{ textAlign: 'center' }}>
|
||
<div style={{ width: s, height: s, background: '#C4623A', borderRadius: 2, opacity: 0.6 }} />
|
||
<div style={{ fontSize: 10, color: '#A8A29E', marginTop: 4 }}>{s}</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
<div style={{ flex: 1 }}>
|
||
<div style={{ fontSize: 13, color: '#7A756E', marginBottom: 12 }}>圆角</div>
|
||
<div style={{ display: 'flex', gap: 12, alignItems: 'center' }}>
|
||
{radii.map(r => (
|
||
<div key={r.name} style={{ textAlign: 'center' }}>
|
||
<div style={{ width: 48, height: 48, border: '2px solid #C4623A', borderRadius: r.value === 999 ? 24 : r.value }} />
|
||
<div style={{ fontSize: 10, color: '#A8A29E', marginTop: 4 }}>{r.name} ({r.value})</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
/* ─── 组件库 ─── */
|
||
const ComponentSection = () => {
|
||
const buttonStyles = {
|
||
row: { display: 'flex', gap: 12, alignItems: 'center', marginBottom: 16, flexWrap: 'wrap' },
|
||
primary: { padding: '10px 28px', background: '#C4623A', color: '#fff', border: 'none', borderRadius: 12, fontSize: 15, fontWeight: 600, cursor: 'pointer' },
|
||
secondary: { padding: '10px 28px', background: 'transparent', color: '#C4623A', border: '1.5px solid #C4623A', borderRadius: 12, fontSize: 15, fontWeight: 600, cursor: 'pointer' },
|
||
ghost: { padding: '10px 28px', background: 'transparent', color: '#7A756E', border: '1.5px solid #E8E2DC', borderRadius: 12, fontSize: 15, fontWeight: 500, cursor: 'pointer' },
|
||
disabled: { padding: '10px 28px', background: '#EDE8E2', color: '#A8A29E', border: 'none', borderRadius: 12, fontSize: 15, fontWeight: 500 },
|
||
small: { padding: '6px 16px', background: '#C4623A', color: '#fff', border: 'none', borderRadius: 8, fontSize: 13, fontWeight: 600 },
|
||
};
|
||
|
||
const tagStyles = {
|
||
success: { display: 'inline-block', padding: '3px 10px', borderRadius: 6, fontSize: 12, fontWeight: 500, background: '#E8F0E8', color: '#5B7A5E' },
|
||
warning: { display: 'inline-block', padding: '3px 10px', borderRadius: 6, fontSize: 12, fontWeight: 500, background: '#FFF3E0', color: '#C4873A' },
|
||
danger: { display: 'inline-block', padding: '3px 10px', borderRadius: 6, fontSize: 12, fontWeight: 500, background: '#FDEAEA', color: '#B54A4A' },
|
||
default: { display: 'inline-block', padding: '3px 10px', borderRadius: 6, fontSize: 12, fontWeight: 500, background: '#F0EBE5', color: '#7A756E' },
|
||
};
|
||
|
||
return (
|
||
<div style={dsStyles.section}>
|
||
<div style={dsStyles.sectionTitle}>组件</div>
|
||
<div style={{ display: 'flex', gap: 24, flexDirection: 'column' }}>
|
||
|
||
{/* 按钮 */}
|
||
<div style={dsStyles.card}>
|
||
<div style={{ fontSize: 13, fontWeight: 600, color: '#2D2A26', marginBottom: 12 }}>按钮</div>
|
||
<div style={buttonStyles.row}>
|
||
<button style={buttonStyles.primary}>主要操作</button>
|
||
<button style={buttonStyles.secondary}>次要操作</button>
|
||
<button style={buttonStyles.ghost}>取消</button>
|
||
<button style={buttonStyles.disabled}>禁用</button>
|
||
<button style={buttonStyles.small}>小按钮</button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 标签 */}
|
||
<div style={dsStyles.card}>
|
||
<div style={{ fontSize: 13, fontWeight: 600, color: '#2D2A26', marginBottom: 12 }}>状态标签</div>
|
||
<div style={{ display: 'flex', gap: 8 }}>
|
||
<span style={tagStyles.success}>正常</span>
|
||
<span style={tagStyles.warning}>偏高</span>
|
||
<span style={tagStyles.danger}>异常</span>
|
||
<span style={tagStyles.default}>待处理</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 数据卡片 */}
|
||
<div style={dsStyles.card}>
|
||
<div style={{ fontSize: 13, fontWeight: 600, color: '#2D2A26', marginBottom: 12 }}>健康数据卡片</div>
|
||
<div style={{ display: 'flex', gap: 12 }}>
|
||
{[
|
||
{ label: '血压', value: '120/80', unit: 'mmHg', status: '正常', statusType: 'success' },
|
||
{ label: '心率', value: '72', unit: 'bpm', status: '正常', statusType: 'success' },
|
||
{ label: '血糖', value: '6.8', unit: 'mmol/L', status: '偏高', statusType: 'warning' },
|
||
].map(item => (
|
||
<div key={item.label} style={{ flex: 1, background: '#F5F0EB', borderRadius: 12, padding: 16, textAlign: 'center' }}>
|
||
<div style={{ fontSize: 13, color: '#7A756E', marginBottom: 8 }}>{item.label}</div>
|
||
<div style={{ fontFamily: '"Noto Serif SC", serif', fontSize: 28, fontWeight: 700, color: '#2D2A26' }}>{item.value}</div>
|
||
<div style={{ fontSize: 12, color: '#A8A29E', margin: '4px 0 8px' }}>{item.unit}</div>
|
||
<span style={tagStyles[item.statusType]}>{item.status}</span>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 列表项 */}
|
||
<div style={dsStyles.card}>
|
||
<div style={{ fontSize: 13, fontWeight: 600, color: '#2D2A26', marginBottom: 12 }}>列表项</div>
|
||
<div style={{ borderRadius: 12, border: '1px solid #E8E2DC', overflow: 'hidden' }}>
|
||
{[
|
||
{ title: '预约:2026-04-28 上午', sub: '王医生 · 心内科 · 待确认' },
|
||
{ title: '随访:血压监测', sub: '每日记录血压数据 · 截止 05-01' },
|
||
{ title: '报告:血常规检验', sub: '2026-04-25 · 已出结果' },
|
||
].map((item, i) => (
|
||
<div key={i} style={{
|
||
display: 'flex', alignItems: 'center', padding: '16px 20px',
|
||
borderBottom: i < 2 ? '1px solid #F0EBE5' : 'none',
|
||
}}>
|
||
<div style={{ flex: 1 }}>
|
||
<div style={{ fontSize: 15, fontWeight: 500, color: '#2D2A26', marginBottom: 2 }}>{item.title}</div>
|
||
<div style={{ fontSize: 13, color: '#7A756E' }}>{item.sub}</div>
|
||
</div>
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" style={{ color: '#A8A29E', flexShrink: 0 }}>
|
||
<path d="M6 4l4 4-4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
|
||
</svg>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
{/* 图标风格 */}
|
||
<div style={dsStyles.card}>
|
||
<div style={{ fontSize: 13, fontWeight: 600, color: '#2D2A26', marginBottom: 12 }}>图标风格 · 线性 1.5px</div>
|
||
<div style={{ display: 'flex', gap: 24 }}>
|
||
{[
|
||
{ label: '首页', path: 'M8 2l6 5v7a1 1 0 01-1 1H3a1 1 0 01-1-1V7l6-5z' },
|
||
{ label: '心率', path: 'M2 8h3l2-4 3 8 2-4h2' },
|
||
{ label: '预约', path: 'M3 4h10v9a1 1 0 01-1 1H4a1 1 0 01-1-1V4zM3 4V2M13 4V2M6 7h4M6 10h2' },
|
||
{ label: '消息', path: 'M2 4a1 1 0 011-1h10a1 1 0 011 1v6a1 1 0 01-1 1H5l-3 3V4z' },
|
||
{ label: '我的', path: 'M8 8a3 3 0 100-6 3 3 0 000 6zM3 14a5 5 0 0110 0' },
|
||
].map(ico => (
|
||
<div key={ico.label} style={{ textAlign: 'center' }}>
|
||
<svg width="24" height="24" viewBox="0 0 16 16" fill="none" stroke="#7A756E" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
|
||
<path d={ico.path} />
|
||
</svg>
|
||
<div style={{ fontSize: 11, color: '#A8A29E', marginTop: 4 }}>{ico.label}</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
/* ─── 渲染 ─── */
|
||
const App = () => (
|
||
<div style={dsStyles.page}>
|
||
<div style={dsStyles.title}>HMS 健康管理 · 设计系统</div>
|
||
<div style={dsStyles.subtitle}>温润东方风 — Kenya Hara 式克制留白 · 赤土橙 #C4623A 贯穿全场</div>
|
||
<ColorSection />
|
||
<TypographySection />
|
||
<SpacingSection />
|
||
<ComponentSection />
|
||
</div>
|
||
);
|
||
|
||
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
|
||
</script>
|
||
</body>
|
||
</html>
|