Files
zkxw/docs/oa-start-footer-btn-style-demo.html
T
2026-08-12 15:48:15 +08:00

559 lines
20 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>发起审批 · 底栏按钮重设计 Demo</title>
<style>
:root {
--ink: #0f172a;
--muted: #64748b;
--line: #e2e8f0;
--brand: #22c55e;
--brand-dark: #16a34a;
--brand-deep: #15803d;
--brand-soft: #ecfdf5;
}
* { 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:
radial-gradient(900px 420px at 8% -8%, rgba(52, 211, 153, 0.16), transparent 55%),
radial-gradient(700px 380px at 92% 0%, rgba(148, 163, 184, 0.14), transparent 50%),
linear-gradient(180deg, #f8fffc 0%, #f4f7fb 50%, #f7f8fa 100%);
line-height: 1.45;
}
.wrap {
max-width: 1180px;
margin: 0 auto;
padding: 28px 18px 96px;
}
h1 {
margin: 0 0 8px;
font-size: 24px;
letter-spacing: -0.02em;
font-weight: 720;
}
.sub {
margin: 0;
max-width: 720px;
color: var(--muted);
font-size: 14px;
}
.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-deep); }
.layout {
display: grid;
grid-template-columns: 1fr minmax(300px, 360px);
gap: 22px;
align-items: start;
}
@media (max-width: 920px) {
.layout { grid-template-columns: 1fr; }
}
/* —— 方案列表 —— */
.schemes { display: grid; gap: 12px; }
.scheme {
appearance: none;
width: 100%;
text-align: left;
border: 1px solid var(--line);
background: #fff;
border-radius: 16px;
padding: 14px 16px;
cursor: pointer;
transition: border-color .15s, box-shadow .15s, background .15s;
font-family: inherit;
color: inherit;
}
.scheme:hover {
border-color: #cbd5e1;
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.05);
}
.scheme.is-on {
border-color: var(--brand);
background: linear-gradient(180deg, #f0fdf4, #fff);
box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.18);
}
.scheme-top {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 6px;
}
.letter {
width: 28px; height: 28px;
border-radius: 8px;
display: grid; place-items: center;
font-size: 13px; font-weight: 750;
background: #f1f5f9;
color: #334155;
flex-shrink: 0;
}
.scheme.is-on .letter {
background: var(--brand-soft);
color: var(--brand-deep);
}
.scheme h2 {
margin: 0;
font-size: 15px;
font-weight: 680;
}
.scheme p {
margin: 0 0 10px;
font-size: 12.5px;
color: var(--muted);
padding-left: 38px;
}
.tag {
margin-left: auto;
font-size: 10px;
font-weight: 700;
padding: 2px 8px;
border-radius: 999px;
background: #f1f5f9;
color: #64748b;
}
.tag.rec {
background: var(--brand-soft);
color: var(--brand-deep);
}
/* —— 右侧手机 —— */
.stage {
position: sticky;
top: 16px;
}
.phone {
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: #f8fafc;
min-height: 640px;
display: flex;
flex-direction: column;
}
.phone-nav {
height: 52px;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border-bottom: 1px solid #f1f5f9;
font-size: 16px;
font-weight: 650;
color: #0f172a;
position: relative;
}
.phone-nav .back {
position: absolute;
left: 14px;
color: #64748b;
font-size: 14px;
font-weight: 500;
}
.form-mock {
flex: 1;
padding: 14px 14px 20px;
display: flex;
flex-direction: column;
gap: 12px;
}
.field {
background: #fff;
border-radius: 12px;
border: 1px solid #eef2f6;
padding: 12px 14px;
}
.field .lab {
font-size: 12px;
color: #94a3b8;
margin-bottom: 6px;
}
.field .val {
font-size: 14px;
color: #334155;
}
.field .val.ph { color: #cbd5e1; }
.stage-meta {
margin-top: 14px;
padding: 12px 14px;
background: rgba(255,255,255,.92);
border: 1px solid var(--line);
border-radius: 14px;
font-size: 13px;
color: var(--muted);
}
.stage-meta strong { color: var(--brand-deep); }
.stage-meta .why {
margin-top: 6px;
font-size: 12.5px;
line-height: 1.5;
}
/* ========== 按钮原子 ========== */
.ft {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
background: #fff;
border-top: 1px solid #eef2f6;
}
.btn {
margin: 0;
appearance: none;
font-family: inherit;
font-size: 15px;
line-height: 1;
border: none;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 44px;
padding: 0 16px;
border-radius: 12px;
font-weight: 600;
transition: transform .12s, opacity .12s, background .15s, box-shadow .15s;
-webkit-tap-highlight-color: transparent;
white-space: nowrap;
}
.btn:active { transform: scale(0.98); opacity: 0.92; }
.btn svg { width: 16px; height: 16px; flex-shrink: 0; }
/* 方案样式仅作用于右侧大屏,避免污染左侧迷你条 */
.phone-screen.s1 .ft { gap: 10px; padding: 12px 14px; }
.phone-screen.s1 .btn-cancel {
flex: 0 0 auto; height: 44px; padding: 0 10px;
background: transparent; color: #94a3b8;
font-weight: 500; font-size: 14px; border-radius: 0;
}
.phone-screen.s1 .btn-draft {
flex: 1; background: #f1f5f9; color: #334155; font-weight: 600;
}
.phone-screen.s1 .btn-submit {
flex: 1.35; background: var(--brand); color: #fff; font-weight: 700;
box-shadow: 0 8px 18px rgba(34, 197, 94, 0.28);
}
.phone-screen.s2 .ft { gap: 12px; padding: 12px 16px; }
.phone-screen.s2 .btn-cancel { display: none; }
.phone-screen.s2 .btn-draft {
flex: 0 0 auto; background: transparent; color: #64748b;
font-weight: 500; font-size: 15px; padding: 0 8px; height: 44px; border-radius: 0;
}
.phone-screen.s2 .btn-submit {
flex: 1; height: 46px; border-radius: 12px;
background: var(--brand-dark); color: #fff; font-weight: 680; letter-spacing: 0.02em;
}
.phone-screen.s3 .ft { gap: 12px; padding: 14px 16px; border-top-color: #f1f5f9; }
.phone-screen.s3 .btn-cancel { display: none; }
.phone-screen.s3 .btn-draft {
flex: 1; height: 46px; border-radius: 10px; background: #fff; color: #475569;
font-weight: 550; box-shadow: inset 0 0 0 1px #d0d5dd;
}
.phone-screen.s3 .btn-submit {
flex: 1; height: 46px; border-radius: 10px; background: #0f172a; color: #fff; font-weight: 650;
}
.phone-screen.s3 .btn-submit span.dot {
width: 6px; height: 6px; border-radius: 50%; background: var(--brand); margin-right: 2px;
}
.phone-screen.s4 { background: #f1f5f9; }
.phone-screen.s4 .ft {
margin: 0 12px 12px; padding: 8px; gap: 8px; border: none; border-radius: 18px;
background: rgba(255,255,255,0.92);
box-shadow: 0 1px 0 rgba(255,255,255,0.8) inset, 0 10px 28px rgba(15, 23, 42, 0.1);
backdrop-filter: blur(12px);
}
.phone-screen.s4 .btn-cancel {
flex: 0 0 44px; width: 44px; height: 44px; padding: 0; border-radius: 14px;
background: #f1f5f9; color: #64748b; font-size: 13px; font-weight: 600;
}
.phone-screen.s4 .btn-draft {
flex: 1; height: 44px; border-radius: 14px; background: #f8fafc; color: #334155;
font-weight: 600; box-shadow: inset 0 0 0 1px #e2e8f0;
}
.phone-screen.s4 .btn-submit {
flex: 1.2; height: 44px; border-radius: 14px;
background: linear-gradient(180deg, #4ade80, #16a34a); color: #fff; font-weight: 720;
box-shadow: 0 6px 14px rgba(22, 163, 74, 0.35);
}
.phone-screen.s5 .ft { gap: 0; padding: 0; border-top: 1px solid #e5e7eb; }
.phone-screen.s5 .btn { height: 52px; border-radius: 0; font-size: 15px; }
.phone-screen.s5 .btn-cancel {
flex: 0 0 76px; background: #fff; color: #64748b; font-weight: 500;
border-right: 1px solid #f1f5f9;
}
.phone-screen.s5 .btn-draft {
flex: 1; background: #fff; color: #1e293b; font-weight: 550;
border-right: 1px solid #f1f5f9;
}
.phone-screen.s5 .btn-submit {
flex: 1.25; background: var(--brand-dark); color: #fff; font-weight: 700;
}
.phone-screen.s6 .ft { gap: 10px; padding: 12px 14px; }
.phone-screen.s6 .btn-cancel {
flex: 0 0 auto; background: transparent; color: #94a3b8; font-weight: 500;
font-size: 14px; padding: 0 8px; height: 44px; border-radius: 0;
}
.phone-screen.s6 .btn-draft {
flex: 1; height: 44px; border-radius: 999px; background: #fff; color: var(--brand-deep);
font-weight: 620; box-shadow: inset 0 0 0 1.5px #86efac;
}
.phone-screen.s6 .btn-submit {
flex: 1.35; height: 44px; border-radius: 999px; background: var(--brand-deep);
color: #fff; font-weight: 700;
}
.phone-screen.s7 .ft { gap: 10px; padding: 12px 14px; }
.phone-screen.s7 .btn-cancel { display: none; }
.phone-screen.s7 .btn-draft {
flex: 0 0 auto; min-width: 108px; height: 46px; border-radius: 12px;
background: #fff; color: #475569; font-weight: 550; font-size: 14px; gap: 6px;
box-shadow: inset 0 0 0 1px #e2e8f0;
}
.phone-screen.s7 .btn-submit {
flex: 1; height: 46px; border-radius: 12px; background: var(--brand); color: #fff;
font-weight: 720; font-size: 16px; box-shadow: 0 10px 22px rgba(34, 197, 94, 0.28);
}
.phone-screen.s8 .ft {
gap: 10px; padding: 12px 14px; background: #fafbfc; border-top-color: #eef2f6;
}
.phone-screen.s8 .btn-cancel {
flex: 0 0 52px; height: 44px; padding: 0; border-radius: 12px;
background: #fff; color: #64748b; font-weight: 500; font-size: 14px;
box-shadow: inset 0 0 0 1px #e5e7eb;
}
.phone-screen.s8 .btn-draft {
flex: 1; height: 44px; border-radius: 12px; background: #eff6ff; color: #1d4ed8; font-weight: 620;
}
.phone-screen.s8 .btn-submit {
flex: 1.3; height: 44px; border-radius: 12px; background: var(--brand-dark); color: #fff; font-weight: 700;
}
/* 左侧迷你色条:只示意配色,不套完整底栏布局 */
.mini-ft {
display: flex; gap: 6px; align-items: center;
margin-left: 38px; pointer-events: none;
}
.mini-ft .ft { display: contents; }
.mini-ft .btn {
height: 28px; font-size: 11px; padding: 0 10px; border-radius: 8px;
box-shadow: none !important; min-width: 0;
}
.mini-ft .btn-cancel { display: none; }
.scheme.s1 .mini-ft .btn-draft { background: #f1f5f9; color: #334155; }
.scheme.s1 .mini-ft .btn-submit { background: #22c55e; color: #fff; }
.scheme.s2 .mini-ft .btn-draft { background: transparent; color: #64748b; padding: 0 4px; }
.scheme.s2 .mini-ft .btn-submit { flex: 1; background: #16a34a; color: #fff; }
.scheme.s3 .mini-ft .btn-draft { background: #fff; color: #475569; box-shadow: inset 0 0 0 1px #d0d5dd !important; }
.scheme.s3 .mini-ft .btn-submit { background: #0f172a; color: #fff; }
.scheme.s3 .mini-ft .dot { display: none; }
.scheme.s4 .mini-ft .btn-draft { background: #f8fafc; color: #334155; box-shadow: inset 0 0 0 1px #e2e8f0 !important; }
.scheme.s4 .mini-ft .btn-submit { background: linear-gradient(180deg, #4ade80, #16a34a); color: #fff; }
.scheme.s5 .mini-ft .btn { border-radius: 0; height: 30px; }
.scheme.s5 .mini-ft .btn-draft { background: #fff; color: #1e293b; box-shadow: inset 0 0 0 1px #e5e7eb !important; }
.scheme.s5 .mini-ft .btn-submit { background: #16a34a; color: #fff; }
.scheme.s6 .mini-ft .btn { border-radius: 999px; }
.scheme.s6 .mini-ft .btn-draft { background: #fff; color: #15803d; box-shadow: inset 0 0 0 1.5px #86efac !important; }
.scheme.s6 .mini-ft .btn-submit { background: #15803d; color: #fff; }
.scheme.s7 .mini-ft .btn-draft { background: #fff; color: #475569; box-shadow: inset 0 0 0 1px #e2e8f0 !important; }
.scheme.s7 .mini-ft .btn-submit { flex: 1; background: #22c55e; color: #fff; }
.scheme.s8 .mini-ft .btn-draft { background: #eff6ff; color: #1d4ed8; }
.scheme.s8 .mini-ft .btn-submit { background: #16a34a; color: #fff; }
</style>
</head>
<body>
<div class="wrap">
<h1>底栏按钮 · 重新设计</h1>
<p class="sub">
上一版问题:草稿与提交都抢绿色、圆角/描边千篇一律、缩略图看不出层级。
这一版只保留 <strong>8 个差异化方向</strong>,右侧大屏实时预览;核心原则是
<strong>草稿弱、提交强</strong>,避免双绿对撞。
</p>
<div class="note">
点左侧方案切换右侧手机。选好后回复编号,例如「用 <strong>S1</strong>」。
取消是否保留也可一并说明。
</div>
<div class="layout">
<div class="schemes" id="schemes"></div>
<aside class="stage">
<div class="phone">
<div class="phone-screen" id="phoneScreen">
<div class="phone-nav">
<span class="back">‹ 返回</span>
请假申请
</div>
<div class="form-mock">
<div class="field">
<div class="lab">请假类型</div>
<div class="val">年假</div>
</div>
<div class="field">
<div class="lab">开始时间</div>
<div class="val">2026-08-12 09:00</div>
</div>
<div class="field">
<div class="lab">结束时间</div>
<div class="val">2026-08-13 18:00</div>
</div>
<div class="field">
<div class="lab">请假事由</div>
<div class="val ph">请填写事由…</div>
</div>
</div>
<div class="ft" id="liveFt"></div>
</div>
</div>
<div class="stage-meta">
当前:<strong id="liveName">—</strong>
<div class="why" id="liveWhy"></div>
</div>
</aside>
</div>
</div>
<script>
const ICO_SAVE = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>`
const schemes = [
{
id: 'S1',
title: '石板次钮 + 薄荷主钮',
rec: true,
why: '草稿用中性灰底,不再抢绿;提交纯色+轻阴影,层级一眼可读。保留取消文字链。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">暂存草稿</button>
<button class="btn btn-submit" type="button">提交</button>`
},
{
id: 'S2',
title: '飞书式 · 文字草稿 + 宽提交',
why: '草稿降为次级文字操作,主视线落在提交。信息密度低、决策成本低。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">暂存草稿</button>
<button class="btn btn-submit" type="button">提交审批</button>`
},
{
id: 'S3',
title: '等宽双钮 · 白描边 + 墨黑提交',
why: '提交用近黑而非绿,品牌绿只做小圆点点缀,克制、偏工具产品。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">暂存草稿</button>
<button class="btn btn-submit" type="button"><span class="dot"></span>提交</button>`
},
{
id: 'S4',
title: '悬浮胶囊底栏',
why: '底栏浮起成卡片;取消为方块、草稿线框、提交亮绿渐变,现代感强。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">草稿</button>
<button class="btn btn-submit" type="button">提交</button>`
},
{
id: 'S5',
title: '通栏三段 · 右主色块',
why: '无圆角贴底通栏,右段深绿实心。偏企业后台/工具效率感。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">暂存草稿</button>
<button class="btn btn-submit" type="button">提交</button>`
},
{
id: 'S6',
title: '双胶囊 · 线框绿字 + 实心深绿',
why: '同圆角语言,但草稿只留线框墨绿字,提交实心深绿,绿不打架。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">暂存草稿</button>
<button class="btn btn-submit" type="button">提交</button>`
},
{
id: 'S7',
title: '紧凑草稿 + 超宽提交',
why: '草稿缩成带图标的次钮,提交占满剩余宽度,强调「主行动只有一个」。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">${ICO_SAVE}草稿</button>
<button class="btn btn-submit" type="button">提交</button>`
},
{
id: 'S8',
title: '冷暖分层 · 蓝草稿 / 绿提交',
why: '用色相区分动作:草稿偏冷蓝、提交偏暖绿,语义分离最强(略跳脱品牌单色)。',
markup: `
<button class="btn btn-cancel" type="button">取消</button>
<button class="btn btn-draft" type="button">暂存草稿</button>
<button class="btn btn-submit" type="button">提交</button>`
}
]
const list = document.getElementById('schemes')
const phone = document.getElementById('phoneScreen')
const liveFt = document.getElementById('liveFt')
const liveName = document.getElementById('liveName')
const liveWhy = document.getElementById('liveWhy')
function apply(id) {
const s = schemes.find((x) => x.id === id)
phone.className = 'phone-screen ' + id.toLowerCase()
liveFt.innerHTML = s.markup
liveName.textContent = id + ' · ' + s.title
liveWhy.textContent = s.why
list.querySelectorAll('.scheme').forEach((el) => {
el.classList.toggle('is-on', el.dataset.id === id)
})
}
schemes.forEach((s) => {
const btn = document.createElement('button')
btn.type = 'button'
btn.className = 'scheme ' + s.id.toLowerCase()
btn.dataset.id = s.id
btn.innerHTML = `
<div class="scheme-top">
<span class="letter">${s.id.replace('S', '')}</span>
<h2>${s.title}</h2>
${s.rec ? '<span class="tag rec">推荐</span>' : '<span class="tag">' + s.id + '</span>'}
</div>
<p>${s.why}</p>
<div class="mini-ft"><div class="ft">${s.markup}</div></div>`
btn.addEventListener('click', () => apply(s.id))
list.appendChild(btn)
})
apply('S1')
</script>
</body>
</html>