842 lines
23 KiB
HTML
842 lines
23 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>mobile-h5 · 控件样式 Demo(输入 / 下拉 / Tag / Tab)</title>
|
||
<style>
|
||
:root {
|
||
--ink: #1f2937;
|
||
--muted: #6b7280;
|
||
--line: #e5e7eb;
|
||
--page: #f3f4f6;
|
||
--brand: #22c55e;
|
||
--brand-ink: #166534;
|
||
}
|
||
* { box-sizing: border-box; }
|
||
html, body { margin: 0; min-height: 100%; }
|
||
body {
|
||
font-family: "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", -apple-system, system-ui, sans-serif;
|
||
color: var(--ink);
|
||
background: linear-gradient(180deg, #f8fafc 0%, #eef2f7 100%);
|
||
line-height: 1.45;
|
||
}
|
||
.wrap {
|
||
max-width: 1240px;
|
||
margin: 0 auto;
|
||
padding: 28px 16px 80px;
|
||
}
|
||
h1 { margin: 0 0 8px; font-size: 24px; letter-spacing: -0.02em; }
|
||
.sub { margin: 0; color: var(--muted); font-size: 14px; max-width: 760px; }
|
||
.note {
|
||
margin: 14px 0 22px;
|
||
padding: 10px 12px;
|
||
border-radius: 10px;
|
||
background: #fff;
|
||
border: 1px solid var(--line);
|
||
font-size: 13px;
|
||
color: var(--muted);
|
||
}
|
||
.note strong { color: var(--brand-ink); }
|
||
|
||
.scheme-tabs {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
margin-bottom: 18px;
|
||
}
|
||
.scheme-tab {
|
||
appearance: none;
|
||
border: 1px solid var(--line);
|
||
background: #fff;
|
||
border-radius: 999px;
|
||
padding: 9px 14px;
|
||
font-size: 13px;
|
||
font-weight: 650;
|
||
color: #475569;
|
||
cursor: pointer;
|
||
}
|
||
.scheme-tab.is-on {
|
||
border-color: #94a3b8;
|
||
background: #0f172a;
|
||
color: #fff;
|
||
}
|
||
.scheme-tab .rec {
|
||
margin-left: 6px;
|
||
font-size: 10px;
|
||
padding: 1px 6px;
|
||
border-radius: 999px;
|
||
background: #ecfdf5;
|
||
color: #166534;
|
||
}
|
||
.scheme-tab.is-on .rec {
|
||
background: rgba(255,255,255,.18);
|
||
color: #fff;
|
||
}
|
||
|
||
.grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 390px;
|
||
gap: 18px;
|
||
align-items: start;
|
||
}
|
||
@media (max-width: 960px) {
|
||
.grid { grid-template-columns: 1fr; }
|
||
}
|
||
|
||
.panel {
|
||
background: #fff;
|
||
border: 1px solid var(--line);
|
||
border-radius: 16px;
|
||
padding: 16px;
|
||
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04);
|
||
}
|
||
.panel h2 {
|
||
margin: 0 0 4px;
|
||
font-size: 15px;
|
||
}
|
||
.panel .desc {
|
||
margin: 0 0 14px;
|
||
font-size: 12px;
|
||
color: var(--muted);
|
||
}
|
||
|
||
.block { margin-bottom: 22px; }
|
||
.block:last-child { margin-bottom: 0; }
|
||
.block-label {
|
||
margin: 0 0 10px;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
color: #94a3b8;
|
||
}
|
||
|
||
/* ========== 手机预览壳 ========== */
|
||
.phone {
|
||
width: 100%;
|
||
max-width: 390px;
|
||
margin: 0 auto;
|
||
background: #111827;
|
||
border-radius: 36px;
|
||
padding: 10px;
|
||
box-shadow: 0 24px 50px rgba(15, 23, 42, 0.18);
|
||
}
|
||
.phone-screen {
|
||
border-radius: 28px;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
min-height: 720px;
|
||
}
|
||
.phone-nav {
|
||
height: 48px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 15px;
|
||
font-weight: 650;
|
||
border-bottom: 1px solid #f1f5f9;
|
||
background: #fff;
|
||
}
|
||
|
||
/* ========== 方案公共预览区 ========== */
|
||
.preview-pad { padding: 12px 14px 20px; background: #fff; }
|
||
.preview-stack { display: grid; gap: 16px; }
|
||
|
||
/* —— 控件原子(由 scheme class 覆盖) —— */
|
||
.ui-search {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
height: 40px;
|
||
padding: 0 12px;
|
||
width: 100%;
|
||
}
|
||
.ui-search input {
|
||
flex: 1;
|
||
border: 0;
|
||
outline: none;
|
||
background: transparent;
|
||
font-size: 14px;
|
||
color: var(--ink);
|
||
min-width: 0;
|
||
font-family: inherit;
|
||
}
|
||
.ui-search input::placeholder { color: #b0b7c3; }
|
||
.ui-ico { color: #9ca3af; font-size: 14px; flex-shrink: 0; }
|
||
|
||
.ui-select {
|
||
position: relative;
|
||
width: 100%;
|
||
}
|
||
.ui-select-trigger {
|
||
width: 100%;
|
||
height: 40px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
padding: 0 12px;
|
||
font-size: 14px;
|
||
cursor: pointer;
|
||
background: #fff;
|
||
font-family: inherit;
|
||
color: var(--ink);
|
||
}
|
||
.ui-select-trigger .ph { color: #b0b7c3; }
|
||
.ui-select-trigger .chev {
|
||
color: #9ca3af;
|
||
font-size: 12px;
|
||
transition: transform .15s;
|
||
}
|
||
.ui-select.open .ui-select-trigger .chev { transform: rotate(180deg); }
|
||
|
||
.ui-dropdown {
|
||
display: none;
|
||
position: absolute;
|
||
left: 0; right: 0;
|
||
top: calc(100% + 6px);
|
||
z-index: 20;
|
||
background: #fff;
|
||
overflow: hidden;
|
||
max-height: 260px;
|
||
}
|
||
.ui-select.open .ui-dropdown { display: block; }
|
||
.ui-dropdown .dd-search {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin: 10px;
|
||
height: 34px;
|
||
padding: 0 10px;
|
||
}
|
||
.ui-dropdown .dd-search input {
|
||
flex: 1;
|
||
border: 0;
|
||
outline: none;
|
||
background: transparent;
|
||
font-size: 13px;
|
||
font-family: inherit;
|
||
}
|
||
.ui-dropdown .dd-list {
|
||
max-height: 180px;
|
||
overflow: auto;
|
||
padding: 4px 0 8px;
|
||
}
|
||
.ui-dropdown .dd-item {
|
||
padding: 10px 14px;
|
||
font-size: 13px;
|
||
cursor: pointer;
|
||
color: var(--ink);
|
||
}
|
||
.ui-dropdown .dd-item:hover { background: #f8fafc; }
|
||
.ui-dropdown .dd-item.is-on { font-weight: 650; }
|
||
|
||
.ui-tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
}
|
||
.ui-tag {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
height: 28px;
|
||
padding: 0 12px;
|
||
font-size: 12px;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
border: 0;
|
||
font-family: inherit;
|
||
}
|
||
.ui-tag.is-on { font-weight: 650; }
|
||
|
||
.ui-tabs {
|
||
display: flex;
|
||
align-items: stretch;
|
||
gap: 0;
|
||
overflow-x: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
.ui-tab {
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
height: 40px;
|
||
padding: 0 14px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
color: #6b7280;
|
||
cursor: pointer;
|
||
background: transparent;
|
||
border: 0;
|
||
font-family: inherit;
|
||
}
|
||
.ui-tab.is-on {
|
||
color: var(--ink);
|
||
font-weight: 650;
|
||
}
|
||
|
||
/* ========== A 极简线框 ========== */
|
||
.scheme-a .ui-search {
|
||
border: 1px solid #e5e7eb;
|
||
border-radius: 10px;
|
||
background: #fff;
|
||
}
|
||
.scheme-a .ui-select-trigger {
|
||
border: 1px solid #e5e7eb;
|
||
border-radius: 10px;
|
||
}
|
||
.scheme-a .ui-dropdown {
|
||
border: 1px solid #e5e7eb;
|
||
border-radius: 12px;
|
||
box-shadow: 0 10px 28px rgba(15,23,42,.08);
|
||
}
|
||
.scheme-a .ui-dropdown .dd-search {
|
||
border: 1px solid #e5e7eb;
|
||
border-radius: 8px;
|
||
background: #fff;
|
||
}
|
||
.scheme-a .ui-dropdown .dd-item.is-on { color: #111827; background: #f3f4f6; }
|
||
.scheme-a .ui-tag {
|
||
border: 1px solid #e5e7eb;
|
||
border-radius: 8px;
|
||
background: #fff;
|
||
color: #4b5563;
|
||
}
|
||
.scheme-a .ui-tag.is-on {
|
||
border-color: #111827;
|
||
color: #111827;
|
||
background: #fff;
|
||
}
|
||
.scheme-a .ui-tabs {
|
||
border-bottom: 1px solid #eee;
|
||
}
|
||
.scheme-a .ui-tab.is-on::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: 14px; right: 14px; bottom: 0;
|
||
height: 2px;
|
||
background: #111827;
|
||
border-radius: 2px 2px 0 0;
|
||
}
|
||
|
||
/* ========== B 浅灰填充 ========== */
|
||
.scheme-b .ui-search {
|
||
border: 0;
|
||
border-radius: 12px;
|
||
background: #f3f4f6;
|
||
}
|
||
.scheme-b .ui-select-trigger {
|
||
border: 0;
|
||
border-radius: 12px;
|
||
background: #f3f4f6;
|
||
}
|
||
.scheme-b .ui-dropdown {
|
||
border: 0;
|
||
border-radius: 14px;
|
||
box-shadow: 0 12px 32px rgba(15,23,42,.12);
|
||
}
|
||
.scheme-b .ui-dropdown .dd-search {
|
||
border: 0;
|
||
border-radius: 10px;
|
||
background: #f3f4f6;
|
||
}
|
||
.scheme-b .ui-dropdown .dd-item.is-on { background: #eef2ff; color: #3730a3; }
|
||
.scheme-b .ui-tag {
|
||
border-radius: 999px;
|
||
background: #f3f4f6;
|
||
color: #6b7280;
|
||
}
|
||
.scheme-b .ui-tag.is-on {
|
||
background: #e5e7eb;
|
||
color: #111827;
|
||
}
|
||
.scheme-b .ui-tabs {
|
||
gap: 8px;
|
||
padding: 2px 0;
|
||
}
|
||
.scheme-b .ui-tab {
|
||
height: 32px;
|
||
border-radius: 999px;
|
||
background: #f3f4f6;
|
||
padding: 0 14px;
|
||
font-size: 13px;
|
||
}
|
||
.scheme-b .ui-tab.is-on {
|
||
background: #e5e7eb;
|
||
color: #111827;
|
||
}
|
||
|
||
/* ========== C 分段控件 ========== */
|
||
.scheme-c .ui-search {
|
||
border: 0;
|
||
border-radius: 999px;
|
||
background: #f5f5f7;
|
||
padding: 0 14px;
|
||
}
|
||
.scheme-c .ui-select-trigger {
|
||
border: 0;
|
||
border-radius: 12px;
|
||
background: #f5f5f7;
|
||
}
|
||
.scheme-c .ui-dropdown {
|
||
border-radius: 16px;
|
||
box-shadow: 0 16px 40px rgba(15,23,42,.14);
|
||
border: 1px solid rgba(15,23,42,.06);
|
||
}
|
||
.scheme-c .ui-dropdown .dd-search {
|
||
border: 0;
|
||
border-radius: 999px;
|
||
background: #f5f5f7;
|
||
}
|
||
.scheme-c .ui-dropdown .dd-item.is-on { color: #007aff; background: #f0f7ff; }
|
||
.scheme-c .ui-tag {
|
||
border-radius: 8px;
|
||
background: #f5f5f7;
|
||
color: #6b7280;
|
||
}
|
||
.scheme-c .ui-tag.is-on {
|
||
background: #111827;
|
||
color: #fff;
|
||
}
|
||
.scheme-c .ui-tabs {
|
||
background: #f5f5f7;
|
||
border-radius: 10px;
|
||
padding: 3px;
|
||
gap: 2px;
|
||
}
|
||
.scheme-c .ui-tab {
|
||
flex: 1;
|
||
height: 34px;
|
||
border-radius: 8px;
|
||
font-size: 13px;
|
||
justify-content: center;
|
||
}
|
||
.scheme-c .ui-tab.is-on {
|
||
background: #fff;
|
||
color: #111827;
|
||
box-shadow: 0 1px 3px rgba(15,23,42,.08);
|
||
}
|
||
|
||
/* ========== D 清爽描边 + 轻主色(推荐) ========== */
|
||
.scheme-d .ui-search {
|
||
border: 1px solid #e8eaed;
|
||
border-radius: 10px;
|
||
background: #fafafa;
|
||
}
|
||
.scheme-d .ui-search:focus-within {
|
||
border-color: #cbd5e1;
|
||
background: #fff;
|
||
box-shadow: 0 0 0 3px rgba(148, 163, 184, 0.18);
|
||
}
|
||
.scheme-d .ui-select-trigger {
|
||
border: 1px solid #e8eaed;
|
||
border-radius: 10px;
|
||
background: #fafafa;
|
||
}
|
||
.scheme-d .ui-select.open .ui-select-trigger {
|
||
border-color: #cbd5e1;
|
||
background: #fff;
|
||
}
|
||
.scheme-d .ui-dropdown {
|
||
border: 1px solid #e8eaed;
|
||
border-radius: 12px;
|
||
box-shadow: 0 12px 28px rgba(15,23,42,.1);
|
||
}
|
||
.scheme-d .ui-dropdown .dd-search {
|
||
border: 1px solid #e8eaed;
|
||
border-radius: 8px;
|
||
background: #fafafa;
|
||
}
|
||
.scheme-d .ui-dropdown .dd-item.is-on {
|
||
color: var(--brand-ink);
|
||
background: #f0fdf4;
|
||
}
|
||
.scheme-d .ui-tag {
|
||
border: 1px solid #e8eaed;
|
||
border-radius: 999px;
|
||
background: #fff;
|
||
color: #64748b;
|
||
}
|
||
.scheme-d .ui-tag.is-on {
|
||
border-color: #bbf7d0;
|
||
background: #f0fdf4;
|
||
color: var(--brand-ink);
|
||
}
|
||
.scheme-d .ui-tabs {
|
||
border-bottom: 1px solid #f1f5f9;
|
||
}
|
||
.scheme-d .ui-tab.is-on {
|
||
color: var(--brand-ink);
|
||
}
|
||
.scheme-d .ui-tab.is-on::after {
|
||
content: "";
|
||
position: absolute;
|
||
left: 14px; right: 14px; bottom: 0;
|
||
height: 2px;
|
||
background: var(--brand);
|
||
border-radius: 2px 2px 0 0;
|
||
}
|
||
|
||
.phone-list {
|
||
padding: 12px 14px 20px;
|
||
}
|
||
.phone-card {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 12px;
|
||
border: 1px solid #e8eaed;
|
||
border-radius: 12px;
|
||
margin-bottom: 10px;
|
||
background: #fff;
|
||
}
|
||
.phone-card .ico {
|
||
width: 36px; height: 36px;
|
||
border-radius: 8px;
|
||
background: #f1f5f9;
|
||
display: grid; place-items: center;
|
||
font-size: 12px; font-weight: 700; color: #64748b;
|
||
}
|
||
.phone-card .name { font-size: 14px; font-weight: 650; }
|
||
.phone-card .meta { font-size: 12px; color: #94a3b8; margin-top: 2px; }
|
||
.phone-card .go {
|
||
margin-left: auto;
|
||
font-size: 12px;
|
||
font-weight: 650;
|
||
color: #fff;
|
||
background: var(--brand);
|
||
border-radius: 8px;
|
||
padding: 6px 10px;
|
||
}
|
||
|
||
.token-list {
|
||
display: grid;
|
||
gap: 6px;
|
||
margin-top: 10px;
|
||
font-size: 12px;
|
||
color: #64748b;
|
||
}
|
||
.token-list code {
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||
background: #f8fafc;
|
||
border: 1px solid #eef2f7;
|
||
border-radius: 6px;
|
||
padding: 1px 5px;
|
||
color: #0f766e;
|
||
}
|
||
|
||
.compare {
|
||
margin-top: 22px;
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 12px;
|
||
}
|
||
@media (max-width: 1100px) {
|
||
.compare { grid-template-columns: repeat(2, 1fr); }
|
||
}
|
||
@media (max-width: 640px) {
|
||
.compare { grid-template-columns: 1fr; }
|
||
}
|
||
.compare .mini {
|
||
background: #fff;
|
||
border: 1px solid var(--line);
|
||
border-radius: 14px;
|
||
padding: 12px;
|
||
cursor: pointer;
|
||
transition: border-color .15s, box-shadow .15s;
|
||
}
|
||
.compare .mini:hover,
|
||
.compare .mini.is-on {
|
||
border-color: #94a3b8;
|
||
box-shadow: 0 0 0 3px rgba(148,163,184,.2);
|
||
}
|
||
.compare .mini h3 {
|
||
margin: 0 0 8px;
|
||
font-size: 13px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="wrap">
|
||
<h1>控件样式 Demo · 输入 / 下拉 / Tag / Tab</h1>
|
||
<p class="sub">
|
||
针对「发起审批」顶部检索与分类,以及表单里常见的下拉选择。以下 4 套均为中性清爽风格,主色只作轻量点缀(或完全不用)。
|
||
点选方案后,右侧手机预览会同步切换。
|
||
</p>
|
||
<div class="note">
|
||
文件路径:<strong>mobile-ui/zkxw-mobile-control-style-demos.html</strong>
|
||
· 本地直接打开即可。选定后告诉我方案代号(A/B/C/D),再落到工程。
|
||
</div>
|
||
|
||
<div class="scheme-tabs" id="schemeTabs"></div>
|
||
|
||
<div class="grid">
|
||
<aside class="panel" id="specPanel">
|
||
<h2 id="schemeTitle">—</h2>
|
||
<p class="desc" id="schemeDesc">—</p>
|
||
|
||
<div class="block">
|
||
<div class="block-label">1. 搜索输入框</div>
|
||
<div id="demoSearch"></div>
|
||
</div>
|
||
|
||
<div class="block">
|
||
<div class="block-label">2. 下拉框</div>
|
||
<div id="demoSelect"></div>
|
||
</div>
|
||
|
||
<div class="block">
|
||
<div class="block-label">3. 下拉框(内嵌检索)</div>
|
||
<div id="demoSelectSearch"></div>
|
||
</div>
|
||
|
||
<div class="block">
|
||
<div class="block-label">4. Tag 标签</div>
|
||
<div id="demoTags"></div>
|
||
</div>
|
||
|
||
<div class="block">
|
||
<div class="block-label">5. Tab 栏</div>
|
||
<div id="demoTabs"></div>
|
||
</div>
|
||
|
||
<div class="token-list" id="tokenList"></div>
|
||
</aside>
|
||
|
||
<section>
|
||
<div class="phone">
|
||
<div class="phone-screen" id="phoneRoot">
|
||
<div class="phone-nav">发起审批</div>
|
||
<div class="preview-pad" id="phoneToolbar"></div>
|
||
<div class="phone-list">
|
||
<div class="phone-card">
|
||
<div class="ico">假</div>
|
||
<div>
|
||
<div class="name">请假申请</div>
|
||
<div class="meta">人事 · 通用</div>
|
||
</div>
|
||
<div class="go">发起</div>
|
||
</div>
|
||
<div class="phone-card">
|
||
<div class="ico">差</div>
|
||
<div>
|
||
<div class="name">出差申请</div>
|
||
<div class="meta">行政</div>
|
||
</div>
|
||
<div class="go">发起</div>
|
||
</div>
|
||
<div class="phone-card">
|
||
<div class="ico">报</div>
|
||
<div>
|
||
<div class="name">费用报销</div>
|
||
<div class="meta">财务</div>
|
||
</div>
|
||
<div class="go">发起</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<div class="compare" id="compare"></div>
|
||
</div>
|
||
|
||
<script>
|
||
const SCHEMES = {
|
||
a: {
|
||
id: 'a',
|
||
name: 'A · 极简线框',
|
||
desc: '白底细线框,Tab 用下划线。最克制,适合信息密度高的列表页。完全不用主题绿。',
|
||
tokens: [
|
||
'搜索:白底 + #e5e7eb 描边,圆角 10',
|
||
'下拉:同搜索线框;展开层白底阴影',
|
||
'Tag:线框方圆角;选中加深描边',
|
||
'Tab:文字 + 黑色下划线'
|
||
]
|
||
},
|
||
b: {
|
||
id: 'b',
|
||
name: 'B · 浅灰填充',
|
||
desc: '控件用浅灰底、无描边。Tag / Tab 都是胶囊。柔和,但选中对比偏弱。',
|
||
tokens: [
|
||
'搜索 / 下拉:#f3f4f6 填充,圆角 12',
|
||
'内嵌检索:同浅灰底',
|
||
'Tag / Tab:灰色胶囊,选中更深灰'
|
||
]
|
||
},
|
||
c: {
|
||
id: 'c',
|
||
name: 'C · 分段控件',
|
||
desc: '搜索做成胶囊;分类用 iOS 分段控件。适合分类少(≤5)的场景。',
|
||
tokens: [
|
||
'搜索:圆角胶囊 #f5f5f7',
|
||
'Tag:选中黑底白字',
|
||
'Tab:整条灰底,选中白块浮起'
|
||
]
|
||
},
|
||
d: {
|
||
id: 'd',
|
||
name: 'D · 清爽描边',
|
||
badge: '推荐',
|
||
desc: '浅灰底 + 细描边,聚焦时微阴影。Tag/Tab 选中才用极浅绿点缀,主色不抢戏。最适合当前「明亮但不花」目标。',
|
||
tokens: [
|
||
'搜索:#fafafa + #e8eaed 边,聚焦提亮',
|
||
'下拉检索:同风格;选中项浅绿底',
|
||
'Tag:白底描边胶囊;选中浅绿',
|
||
'Tab:下划线用主色,文字深绿'
|
||
]
|
||
}
|
||
}
|
||
|
||
const GROUPS = ['全部', '人事', '行政', '财务', '其他']
|
||
const OPTIONS = ['请假申请', '出差申请', '加班申请', '费用报销', '用章申请', '采购申请']
|
||
|
||
let active = 'd'
|
||
let tabOn = 0
|
||
let tagOn = 0
|
||
let selectVal = ''
|
||
let selectSearchVal = ''
|
||
let openSelect = '' // 'plain' | 'search' | ''
|
||
|
||
function el(html) {
|
||
const t = document.createElement('template')
|
||
t.innerHTML = html.trim()
|
||
return t.content.firstElementChild
|
||
}
|
||
|
||
function renderSchemeTabs() {
|
||
const root = document.getElementById('schemeTabs')
|
||
root.innerHTML = ''
|
||
Object.values(SCHEMES).forEach((s) => {
|
||
const b = el(`<button class="scheme-tab ${s.id === active ? 'is-on' : ''}" type="button">
|
||
${s.name}${s.badge ? `<span class="rec">${s.badge}</span>` : ''}
|
||
</button>`)
|
||
b.onclick = () => { active = s.id; openSelect = ''; renderAll() }
|
||
root.appendChild(b)
|
||
})
|
||
}
|
||
|
||
function renderCompare() {
|
||
const root = document.getElementById('compare')
|
||
root.innerHTML = ''
|
||
Object.values(SCHEMES).forEach((s) => {
|
||
const card = el(`<div class="mini ${s.id === active ? 'is-on' : ''} scheme-${s.id}" data-choice="${s.id}">
|
||
<h3>${s.name}</h3>
|
||
<div class="ui-search" style="margin-bottom:8px"><span class="ui-ico">⌕</span><input placeholder="搜索审批单" readonly /></div>
|
||
<div class="ui-tags" style="margin-bottom:8px">
|
||
<button class="ui-tag is-on" type="button">全部</button>
|
||
<button class="ui-tag" type="button">人事</button>
|
||
</div>
|
||
<div class="ui-tabs">
|
||
<button class="ui-tab is-on" type="button">全部</button>
|
||
<button class="ui-tab" type="button">人事</button>
|
||
<button class="ui-tab" type="button">行政</button>
|
||
</div>
|
||
</div>`)
|
||
card.onclick = () => { active = s.id; openSelect = ''; renderAll() }
|
||
root.appendChild(card)
|
||
})
|
||
}
|
||
|
||
function searchHtml() {
|
||
return `<div class="ui-search"><span class="ui-ico">⌕</span><input placeholder="搜索审批单" /><span class="ui-ico">×</span></div>`
|
||
}
|
||
|
||
function selectHtml(kind) {
|
||
const isOpen = openSelect === kind
|
||
const val = kind === 'plain' ? selectVal : selectSearchVal
|
||
const label = val || '<span class="ph">请选择审批类型</span>'
|
||
const items = OPTIONS.map((o) =>
|
||
`<div class="dd-item ${o === val ? 'is-on' : ''}" data-v="${o}">${o}</div>`
|
||
).join('')
|
||
const searchBar = kind === 'search'
|
||
? `<div class="dd-search"><span class="ui-ico">⌕</span><input placeholder="输入关键词筛选" /></div>`
|
||
: ''
|
||
return `<div class="ui-select ${isOpen ? 'open' : ''}" data-kind="${kind}">
|
||
<button type="button" class="ui-select-trigger"><span>${label}</span><span class="chev">▾</span></button>
|
||
<div class="ui-dropdown">${searchBar}<div class="dd-list">${items}</div></div>
|
||
</div>`
|
||
}
|
||
|
||
function tagsHtml() {
|
||
return `<div class="ui-tags">${GROUPS.map((g, i) =>
|
||
`<button type="button" class="ui-tag ${i === tagOn ? 'is-on' : ''}" data-i="${i}">${g}</button>`
|
||
).join('')}</div>`
|
||
}
|
||
|
||
function tabsHtml() {
|
||
return `<div class="ui-tabs">${GROUPS.map((g, i) =>
|
||
`<button type="button" class="ui-tab ${i === tabOn ? 'is-on' : ''}" data-i="${i}">${g}</button>`
|
||
).join('')}</div>`
|
||
}
|
||
|
||
function bindSelect(root) {
|
||
root.querySelectorAll('.ui-select').forEach((box) => {
|
||
const kind = box.dataset.kind
|
||
box.querySelector('.ui-select-trigger').onclick = (e) => {
|
||
e.stopPropagation()
|
||
openSelect = openSelect === kind ? '' : kind
|
||
renderAll()
|
||
}
|
||
box.querySelectorAll('.dd-item').forEach((item) => {
|
||
item.onclick = (e) => {
|
||
e.stopPropagation()
|
||
if (kind === 'plain') selectVal = item.dataset.v
|
||
else selectSearchVal = item.dataset.v
|
||
openSelect = ''
|
||
renderAll()
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
function bindTagsTabs(root) {
|
||
root.querySelectorAll('.ui-tag').forEach((t) => {
|
||
t.onclick = () => { tagOn = Number(t.dataset.i); renderAll() }
|
||
})
|
||
root.querySelectorAll('.ui-tab').forEach((t) => {
|
||
t.onclick = () => { tabOn = Number(t.dataset.i); renderAll() }
|
||
})
|
||
}
|
||
|
||
function renderAll() {
|
||
const s = SCHEMES[active]
|
||
document.getElementById('schemeTitle').textContent = s.name
|
||
document.getElementById('schemeDesc').textContent = s.desc
|
||
document.getElementById('tokenList').innerHTML = s.tokens.map((t) => `<div>· ${t}</div>`).join('')
|
||
|
||
const panel = document.getElementById('specPanel')
|
||
panel.className = `panel scheme-${active}`
|
||
|
||
document.getElementById('demoSearch').innerHTML = searchHtml()
|
||
document.getElementById('demoSelect').innerHTML = selectHtml('plain')
|
||
document.getElementById('demoSelectSearch').innerHTML = selectHtml('search')
|
||
document.getElementById('demoTags').innerHTML = tagsHtml()
|
||
document.getElementById('demoTabs').innerHTML = tabsHtml()
|
||
bindSelect(panel)
|
||
bindTagsTabs(panel)
|
||
|
||
const phone = document.getElementById('phoneRoot')
|
||
phone.className = `phone-screen scheme-${active}`
|
||
document.getElementById('phoneToolbar').innerHTML =
|
||
`<div class="preview-stack">${searchHtml()}${tabsHtml()}</div>`
|
||
bindTagsTabs(document.getElementById('phoneToolbar'))
|
||
|
||
renderSchemeTabs()
|
||
renderCompare()
|
||
}
|
||
|
||
document.addEventListener('click', () => {
|
||
if (!openSelect) return
|
||
openSelect = ''
|
||
renderAll()
|
||
})
|
||
|
||
renderAll()
|
||
</script>
|
||
</body>
|
||
</html>
|