chore: 设计规格文档 + 销售数据 + 脚本工具 + 根目录 monorepo 配置

- docs/: 设计规格、讨论记录、销售数据、健康管理文档
- scripts/: 辅助脚本
- package.json + pnpm-lock.yaml: monorepo 根配置
This commit is contained in:
iven
2026-04-28 00:20:37 +08:00
parent 11777e3b68
commit 1265935fa3
20 changed files with 4718 additions and 0 deletions

View File

@@ -0,0 +1,317 @@
<!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>