Files
zkxw/docs/theme-demos-alt/build-demos.mjs
T
2026-06-14 17:20:52 +08:00

434 lines
15 KiB
JavaScript
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.
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const themes = [
{
id: '01',
file: '01-dark-sidebar.html',
title: '01 · 深色侧栏藏青',
desc: '侧栏 #0f172a · 点缀天蓝 · Logo 绿最跳眼',
note: '风格差异大:深色导航 + 白内容区,很多 LIS/HIS 系统采用;Logo 绿色会非常醒目。',
primary: '#38bdf8',
dark: '#0ea5e9',
bg: 'rgba(56, 189, 248, 0.14)',
border: '#e2e8f0',
swatches: ['#0f172a', '#38bdf8', '#f8fafc', '#e2e8f0'],
darkSidebar: true,
recommended: true
},
{
id: '02',
file: '02-warm-stone.html',
title: '02 · 暖石米灰',
desc: '暖灰主色 #57534e · 米白底 · 不冷不艳',
note: '偏纸质/档案感,长时间看不疲劳;适合财务、合规、大量表格录入。',
primary: '#57534e',
dark: '#44403c',
bg: '#f5f5f4',
border: '#e7e5e4',
pageBg: '#fafaf9',
tableHead: '#f5f5f4',
text: '#292524',
textMuted: '#78716c',
swatches: ['#57534e', '#44403c', '#fafaf9', '#e7e5e4'],
warm: true
},
{
id: '03',
file: '03-medical-blue.html',
title: '03 · 经典医院蓝',
desc: '主色 #0077b6 · 传统医疗信息系统气质',
note: '比 Tailwind 蓝更「医院感」;稳重、熟悉,中老年用户接受度高。',
primary: '#0077b6',
dark: '#023e8a',
bg: '#e8f4fa',
border: '#bde0fe',
swatches: ['#0077b6', '#023e8a', '#e8f4fa', '#bde0fe']
},
{
id: '04',
file: '04-zinc-minimal.html',
title: '04 · 锌灰极简',
desc: '几乎无彩色 · 主按钮 #18181b · Logo 是唯一亮点',
note: '极简 B 端:界面本身不抢戏,状态 Tag 保留语义色;适合数据密集页面。',
primary: '#52525b',
dark: '#3f3f46',
bg: '#f4f4f5',
border: '#e4e4e7',
cta: '#18181b',
ctaDark: '#27272a',
swatches: ['#52525b', '#18181b', '#fafafa', '#e4e4e7']
},
{
id: '05',
file: '05-soft-violet.html',
title: '05 · 薄雾紫',
desc: '主色 #7c6fad · 舒缓、偏医疗康养',
note: '低饱和紫,比靛蓝更柔;适合客服、客户档案类模块,主列表页需实测。',
primary: '#7c6fad',
dark: '#6b5b95',
bg: '#f3f0f8',
border: '#ddd6fe',
swatches: ['#7c6fad', '#6b5b95', '#f3f0f8', '#ddd6fe']
},
{
id: '06',
file: '06-navy-authority.html',
title: '06 · 墨蓝权威',
desc: '主色 #1e3a5f · 传统企业门户',
note: '深藏青,权威合规感强;与绿色 Logo 对比清晰,适合审批流、协议类页面。',
primary: '#1e3a5f',
dark: '#152a45',
bg: '#eef2f6',
border: '#c5d0dc',
swatches: ['#1e3a5f', '#152a45', '#eef2f6', '#c5d0dc']
}
]
function themeJump(currentId) {
return themes
.map((t) => {
const cls = t.id === currentId ? 'is-current' : ''
return `<a class="${cls}" href="${t.file}">${t.id}</a>`
})
.join('')
}
function swatchesHtml(theme) {
const labels = theme.cta
? ['导航', '按钮', '浅底', '边']
: theme.darkSidebar
? ['侧栏', '点缀', '内容', '边']
: ['主色', '深', '浅底', '边']
return theme.swatches
.map((c, i) => `<span class="swatch"><i style="background:${c}"></i>${labels[i]}</span>`)
.join('')
}
function rootVars(theme) {
const lines = [
` --primary: ${theme.primary};`,
` --primary-dark: ${theme.dark};`,
` --primary-bg: ${theme.bg};`,
` --text: ${theme.text || '#1e293b'};`,
` --text-muted: ${theme.textMuted || '#64748b'};`,
` --border: ${theme.border};`,
` --bg-page: ${theme.pageBg || '#fefefe'};`,
` --surface: #ffffff;`,
` --table-head: ${theme.tableHead || '#f8fafc'};`,
` --row-alt: ${theme.warm ? '#f5f5f4' : '#fafafa'};`,
` --row-hover: ${theme.warm ? '#ececea' : '#f1f5f9'};`,
` --shadow: 0 1px 3px rgba(0, 0, 0, 0.05);`,
` --radius: 10px;`
]
if (theme.darkSidebar) {
lines.push(` --sidebar-bg: #0f172a;`, ` --sidebar-border: #1e293b;`)
}
if (theme.cta) {
lines.push(` --cta: ${theme.cta};`, ` --cta-dark: ${theme.ctaDark};`)
}
return lines.join('\n')
}
function renderPage(theme) {
const badge = theme.recommended ? '<span class="demo-badge">推荐</span>' : ''
const bodyClass = theme.warm ? ' class="layout-warm"' : ''
const sidebarClass = theme.darkSidebar ? 'sidebar sidebar--dark' : 'sidebar'
return `<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>${theme.title} · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
${rootVars(theme)}
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body${bodyClass}>
<div class="demo-banner">
<div>
<h1>${badge}${theme.title}</h1>
<p>${theme.desc}</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row">${swatchesHtml(theme)}</div>
<div class="theme-jump">${themeJump(theme.id)}</div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="${sidebarClass}">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">${theme.note}</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>`
}
for (const theme of themes) {
fs.writeFileSync(path.join(__dirname, theme.file), renderPage(theme))
console.log('written', theme.file)
}