| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1" />
- <title>主页菜单图标 · 配色挑选</title>
- <style>
- :root {
- --ink: #1f2a26;
- --muted: #6b7b74;
- --line: #e2e8e5;
- --page: #f5f8f7;
- --brand: #16a34a;
- }
- * { box-sizing: border-box; }
- body {
- margin: 0;
- font-family: "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", system-ui, sans-serif;
- color: var(--ink);
- background:
- radial-gradient(900px 480px at 0% -10%, #dcfce7 0%, transparent 50%),
- radial-gradient(800px 420px at 100% 0%, #e0e7ff 0%, transparent 45%),
- var(--page);
- line-height: 1.45;
- }
- .wrap { max-width: 1100px; margin: 0 auto; padding: 24px 18px 100px; }
- h1 { margin: 0 0 8px; font-size: 24px; letter-spacing: -0.02em; }
- .sub { margin: 0; color: var(--muted); font-size: 14px; max-width: 720px; }
- .note {
- margin: 14px 0 0;
- padding: 10px 12px;
- border-radius: 10px;
- background: #fff;
- border: 1px solid var(--line);
- font-size: 13px;
- color: var(--muted);
- }
- .note code {
- font-family: ui-monospace, Menlo, monospace;
- font-size: 12px;
- background: #f1f5f4;
- padding: 1px 6px;
- border-radius: 4px;
- color: var(--ink);
- }
- .phone {
- margin: 20px 0 8px;
- max-width: 390px;
- background: #fff;
- border: 1px solid var(--line);
- border-radius: 22px;
- overflow: hidden;
- box-shadow: 0 16px 40px rgba(20,40,30,.08);
- }
- .phone-hd {
- padding: 18px 16px 14px;
- background: linear-gradient(155deg, #14532d 0%, #16a34a 48%, #22c55e 100%);
- color: #fff;
- }
- .phone-hd .brand { font-size: 12px; opacity: .85; }
- .phone-hd .hello { font-size: 18px; font-weight: 650; margin-top: 6px; }
- .phone-body { padding: 14px; background: #f5f8f7; }
- .panel {
- background: #fff;
- border-radius: 14px;
- border: 1px solid var(--line);
- padding: 12px;
- }
- .panel-hd {
- display: flex; justify-content: space-between; align-items: baseline;
- margin-bottom: 12px;
- }
- .panel-title { font-size: 14px; font-weight: 650; }
- .hint { font-size: 12px; color: var(--muted); }
- .menu-grid {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- gap: 10px 6px;
- }
- .menu-card {
- display: flex; flex-direction: column; align-items: center; gap: 8px;
- padding: 8px 4px;
- border-radius: 12px;
- }
- .menu-icon {
- width: 48px; height: 48px; border-radius: 14px;
- display: flex; align-items: center; justify-content: center;
- box-shadow: inset 0 0 0 1px rgba(0,0,0,.04);
- }
- .menu-icon svg { width: 26px; height: 26px; display: block; }
- .menu-title {
- font-size: 12px; text-align: center; color: var(--ink);
- max-width: 72px; line-height: 1.2;
- }
- .sec {
- margin: 28px 0 10px;
- font-size: 14px; color: var(--muted);
- display: flex; align-items: center; gap: 8px;
- }
- .sec::after { content: ""; flex: 1; height: 1px; background: var(--line); }
- .grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
- gap: 12px;
- }
- .card {
- background: #fff;
- border: 1px solid var(--line);
- border-radius: 14px;
- padding: 14px 12px 12px;
- cursor: pointer;
- transition: .15s;
- text-align: center;
- }
- .card:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(0,0,0,.06); }
- .card.is-current { outline: 2px dashed #94a3b8; outline-offset: -2px; }
- .card.is-selected {
- border-color: var(--fg, #2563eb);
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--fg) 25%, transparent);
- }
- .card .icon-box {
- width: 56px; height: 56px; border-radius: 16px;
- margin: 0 auto 10px;
- display: flex; align-items: center; justify-content: center;
- box-shadow: inset 0 0 0 1px rgba(0,0,0,.05);
- }
- .card .icon-box svg { width: 30px; height: 30px; }
- .card .name { font-size: 13px; font-weight: 650; margin: 0 0 4px; }
- .card .meta {
- font-size: 11px; color: var(--muted);
- font-family: ui-monospace, Menlo, monospace;
- line-height: 1.4;
- }
- .tag {
- display: inline-block; margin-top: 8px;
- font-size: 11px; padding: 2px 8px; border-radius: 999px;
- background: #f1f5f4; color: var(--muted);
- }
- .tag.rec { background: #eff6ff; color: #1d4ed8; }
- .tag.hot { background: #fff7ed; color: #c2410c; }
- .footer {
- position: sticky; bottom: 12px; margin-top: 22px;
- background: rgba(255,255,255,.94);
- border: 1px solid var(--line);
- border-radius: 14px;
- padding: 12px 14px;
- display: flex; flex-wrap: wrap; gap: 12px;
- align-items: center; justify-content: space-between;
- backdrop-filter: blur(10px);
- box-shadow: 0 10px 30px rgba(0,0,0,.08);
- }
- .picked { display: flex; align-items: center; gap: 10px; font-size: 13px; }
- .picked .sw {
- width: 44px; height: 44px; border-radius: 12px;
- display: flex; align-items: center; justify-content: center;
- box-shadow: inset 0 0 0 1px rgba(0,0,0,.06);
- }
- .picked .sw svg { width: 24px; height: 24px; }
- .picked strong { display: block; font-size: 14px; }
- .picked span { color: var(--muted); font-size: 12px; font-family: ui-monospace, Menlo, monospace; }
- .actions { display: flex; gap: 8px; flex-wrap: wrap; }
- .actions button {
- height: 36px; padding: 0 14px; border-radius: 8px;
- border: 1px solid var(--line); background: #fff;
- font: inherit; font-size: 13px; cursor: pointer;
- }
- .actions button.primary {
- background: var(--brand); border-color: transparent; color: #fff; font-weight: 600;
- }
- .toast {
- position: fixed; left: 50%; bottom: 88px; transform: translateX(-50%) translateY(10px);
- background: #1f2a26; color: #fff; padding: 8px 14px; border-radius: 999px;
- font-size: 13px; opacity: 0; transition: .2s; pointer-events: none; z-index: 20;
- }
- .toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
- </style>
- </head>
- <body>
- <!-- 印章/发起审批图标:用 currentColor 便于换色 -->
- <svg xmlns="http://www.w3.org/2000/svg" style="display:none">
- <symbol id="icon-approve" viewBox="0 0 1024 1024">
- <path fill="currentColor" d="M645.51 854.33c15.49-57.33 86.49-42 86.49-42s-43.54-44.53-23-112.67c11.22-37.2 39.58-67.99 79.81-76.43 20.41-4.28 56.37-4.23 69.42 0.55 3.66-18.04 7.33-36.14 10.85-54.39l23.84-117.26c7.41-37.35 14.81-74.7 22.78-112.05 6.27-32.55 13.19-65.1 19.53-97.81 4.72-24.74 10.09-49.48 14.81-74.71 2.6-14.16 5.86-28.31 8.46-42.07 0.61-2.04 0.96-4.14 1.06-6.26-1.06-24.66-1.06-41.01-16.93-48.83-16.43-7.89-32.38-7.89-40.85 0-21.65 10.98-43.45 21.48-65.1 32.55-54.04 26.85-107.41 53.7-161.45 80.48L468.71 285.97c-59.16 29.46-118.4 60.46-178.21 88.78-45.57 21.56-90 45.81-135.08 67.38-19.53 9.44-40.2 15.79-59.73 25.71-15.79 7.97-31.25 20.02-31.25 39.55 0 8.87 1.63 21.48 8.95 27.83 2.68 2.03 5.94 3.58 8.46 5.69 40.28 22.14 78.44 48.42 117.58 72.67l76.17 47.2h0.57c16.44 7.98 32.31 7.98 48.74-7.81l0.49-0.57c0.49-0.57 0.98-0.57 0.98-1.05 0.65-0.49 1.71-1.06 2.2-2.04 1.14-1.14 2.11-1.63 3.25-2.68 0.98-1.06 2.61-2.04 3.66-3.17 1.63-1.55 3.17-2.61 4.23-4.15 1.62-1.73 3.39-3.31 5.29-4.72 2.11-1.63 3.66-3.66 5.77-5.29 2.2-2.11 4.31-3.66 6.35-5.7 2.11-2.19 4.8-4.23 6.91-6.43 2.68-2.03 4.8-4.72 7.49-6.83 2.61-2.61 5.21-4.72 7.81-7.32 2.77-2.61 5.86-5.29 8.46-7.89 3.25-2.61 5.86-5.21 9.03-7.89 3.25-2.61 6.35-5.86 9.52-8.38 3.25-3.26 6.43-5.86 10.09-8.95 3.17-3.17 6.91-6.35 10.09-8.95 3.67-3.17 6.84-6.34 10.58-9.44 3.76-3.08 7.3-6.43 10.58-10.01 3.66-3.17 7.32-6.92 11.15-10.09 3.66-3.1 7.33-6.76 11.07-9.93 3.66-3.66 7.97-6.83 11.64-10.5 3.74-3.66 7.98-6.84 11.72-10.58 3.66-3.66 7.81-6.83 11.64-10.41 4.07-3.74 7.89-7.32 12.13-10.58 4.23-3.67 7.97-7.33 12.21-10.58 4.15-3.58 7.89-7.32 12.21-10.98 4.15-3.66 7.89-7.32 12.12-10.98 4.15-3.74 7.98-7.4 12.13-10.58 3.74-3.58 7.65-7.08 11.72-10.41 3.66-3.74 7.89-6.83 11.64-10.58 3.66-3.67 7.89-6.84 11.64-10.5 3.66-3.74 7.32-6.83 11.64-10.58 3.66-3.09 7.32-6.75 11.15-9.93 3.66-3.25 7.32-6.83 11.07-10.01 3.67-3.01 7.25-6.19 10.58-9.44 3.74-3.17 6.83-6.35 10.58-9.52 3.25-3.1 6.83-6.27 10.09-8.95 3.25-3.17 6.34-5.7 9.52-8.87 3.17-2.68 6.35-5.78 9.52-8.46 3.25-2.6 5.86-5.21 8.95-7.89 2.68-2.6 5.86-5.21 8.54-7.89 2.6-2.6 5.21-4.72 7.89-7.32 2.64-2.11 5.14-4.39 7.49-6.83 2.03-2.12 4.72-4.23 6.83-6.35 2.11-2.11 4.23-3.66 6.34-5.69 2.12-1.63 3.66-3.26 5.86-5.29l4.72-4.72c1.62-1.14 2.6-2.68 4.23-3.74 1.05-0.98 2.19-2.11 3.66-3.09 1.13-1.14 2.19-1.63 2.68-2.69l3.17-3.09h0.57c2.68 0.98 5.29 2.53 7.89 3.58 1.63 0.65 2.69 1.63 4.23 2.2 0.57 0.49 1.14 0.49 2.12 0.98 0.56 0 2.11 0.57 2.11 1.14v0.49c-0.57 0.49-1.06 0.49-1.06 0.98l-1.62 1.63-6.84 6.83a76.647 76.647 0 0 0-8.95 10.01c-2.12 2.12-4.31 4.72-6.35 6.84a22.64 22.64 0 0 0-3.25 3.66l-1.55 1.62c-0.57 0.49-1.05 1.47-1.62 1.47-9.44 10.09-19.04 20.59-28.48 30.59l-74.7 78.94c-28.56 29.86-56.64 59.89-85.28 89.83-26.93 28.4-53.95 56.8-80.4 85.2-20.67 21.56-40.69 43.13-61.36 64.69-8.95 9.44-18.06 18.88-27.02 28.88l-0.57 0.57c-7.89 7.81-7.89 16.28-7.89 24.17v177.81c0 16.28 7.89 31.98 24.33 40.36 16.36 7.97 32.31 0 40.69-7.89l62.98-62.5c10.66-10.58 20.75-21.07 30.76-31.57 1.13-1.06 2.11-2.11 3.25-2.11 1.46-0.57 3.58 0.57 4.72 1.62 22.7 14.9 97.27 71.69 97.27 71.69s3.59-31.79 6.31-41.84z"/>
- <path fill="currentColor" d="M699.65 908.97H948.6c7.12 0 13.06-7.66 11.87-15.33l-4.75-28.07c-2.37-11.5-11.87-20.41-22.52-20.41h-76.72l-4.75-31.9c26.08-11.5 43.89-38.29 43.89-70.19 0-42.12-32.02-76.58-71.16-76.58-39.14 0-71.2 34.42-71.2 76.55 0 31.9 17.78 58.7 43.89 70.19l-3.56 31.9h-77.33c-10.68 0-21.34 8.94-22.52 20.41L689 893.61c-2.4 7.69 3.53 15.36 10.65 15.36z m248.89 19.12M944.08 960.22h-239.4c-9.34 0-16.92-7.58-16.92-16.92v-0.91c0-9.34 7.58-16.92 16.92-16.92h239.4c9.34 0 16.92 7.58 16.92 16.92v0.91c0 9.35-7.57 16.92-16.92 16.92z"/>
- </symbol>
- </svg>
- <div class="wrap">
- <h1>主页菜单图标 · 配色挑选</h1>
- <p class="sub">
- 针对「发起审批」图标底色 + 图形色。未来多个入口应各自配色,避免整屏同一种绿。
- 点选下方色卡,顶部手机预览会同步;底部可复制 <code>iconBg / iconFg</code>。
- </p>
- <p class="note">
- 当前实现:底色靠 CSS <code>.tone-approve</code>(浅绿),SVG 内写死 <code>fill="#16a34a"</code>。
- 目标:菜单项可配置 <code>iconBg</code> + <code>iconFg</code>(或复用已有 OA 色对)。
- </p>
- <div class="phone">
- <div class="phone-hd">
- <div class="brand">中科兴皖 · 移动工作台</div>
- <div class="hello">您好,示例用户</div>
- </div>
- <div class="phone-body">
- <div class="panel">
- <div class="panel-hd">
- <span class="panel-title">功能菜单</span>
- <span class="hint">配色预览</span>
- </div>
- <div class="menu-grid" id="liveGrid"></div>
- </div>
- </div>
- </div>
- <div class="sec">当前(对照)</div>
- <div class="grid" id="g-current"></div>
- <div class="sec">OA 审批色对(与发起页 ep 图标一致,推荐复用)</div>
- <div class="grid" id="g-oa"></div>
- <div class="sec">扩展色对(非绿,适合多入口区分)</div>
- <div class="grid" id="g-extra"></div>
- <div class="footer">
- <div class="picked">
- <div class="sw" id="pickedSw"></div>
- <div>
- <strong id="pickedName">未选择</strong>
- <span id="pickedHex">点击色卡挑选</span>
- </div>
- </div>
- <div class="actions">
- <button type="button" id="copyPair">复制 bg, fg</button>
- <button type="button" class="primary" id="copyJson">复制菜单字段 JSON</button>
- </div>
- </div>
- </div>
- <div class="toast" id="toast">已复制</div>
- <script>
- const ICON = `<svg viewBox="0 0 1024 1024" aria-hidden="true"><use href="#icon-approve"/></svg>`;
- /** 与 mobile-h5/utils/oa-app-icons.js 对齐 */
- const OA_PAIRS = [
- { id: 'oa-0', name: '翠绿', bg: '#d1fae5', fg: '#059669', tag: 'OA', tagClass: '' },
- { id: 'oa-1', name: '青蓝', bg: '#cffafe', fg: '#0891b2', tag: 'OA · 推荐', tagClass: 'rec' },
- { id: 'oa-2', name: '天蓝', bg: '#dbeafe', fg: '#2563eb', tag: 'OA · 推荐', tagClass: 'rec' },
- { id: 'oa-3', name: '靛蓝', bg: '#e0e7ff', fg: '#4f46e5', tag: 'OA', tagClass: '' },
- { id: 'oa-4', name: '紫罗兰', bg: '#ede9fe', fg: '#7c3aed', tag: 'OA', tagClass: '' },
- { id: 'oa-5', name: '玫粉', bg: '#fce7f3', fg: '#db2777', tag: 'OA', tagClass: '' },
- { id: 'oa-6', name: '橙', bg: '#ffedd5', fg: '#ea580c', tag: 'OA · 推荐', tagClass: 'rec' },
- { id: 'oa-7', name: '琥珀', bg: '#fef3c7', fg: '#d97706', tag: 'OA', tagClass: '' }
- ];
- const CURRENT = [
- {
- id: 'current',
- name: '当前 tone-approve',
- bg: '#c8f5de',
- fg: '#16a34a',
- tag: '当前',
- tagClass: 'hot',
- current: true
- }
- ];
- const EXTRA = [
- { id: 'ex-slate', name: '石板灰', bg: '#eef2f1', fg: '#3d524a', tag: '克制', tagClass: '' },
- { id: 'ex-sky', name: '晴空蓝', bg: '#e0f2fe', fg: '#0284c7', tag: '清爽', tagClass: 'rec' },
- { id: 'ex-royal', name: '宝蓝', bg: '#dbeafe', fg: '#1d4ed8', tag: '正式', tagClass: 'rec' },
- { id: 'ex-indigo', name: '深靛', bg: '#e0e7ff', fg: '#3730a3', tag: '稳重', tagClass: '' },
- { id: 'ex-violet', name: '葡萄紫', bg: '#f3e8ff', fg: '#7e22ce', tag: '个性', tagClass: '' },
- { id: 'ex-rose', name: '玫瑰红', bg: '#ffe4e6', fg: '#e11d48', tag: '醒目', tagClass: '' },
- { id: 'ex-coral', name: '珊瑚', bg: '#ffedd5', fg: '#c2410c', tag: '温暖', tagClass: '' },
- { id: 'ex-amber', name: '大麦黄邻', bg: '#fff7e8', fg: '#a67b20', tag: '已有 tone', tagClass: '' },
- { id: 'ex-teal', name: '孔雀石', bg: '#ccfbf1', fg: '#0f766e', tag: '青绿', tagClass: '' },
- { id: 'ex-lime', name: '青柠', bg: '#ecfccb', fg: '#4d7c0f', tag: '活力', tagClass: '' },
- { id: 'ex-brown', name: '咖啡', bg: '#f5e6d3', fg: '#92400e', tag: '沉稳', tagClass: '' },
- { id: 'ex-ink', name: '墨蓝', bg: '#e2e8f0', fg: '#334155', tag: '极简', tagClass: '' }
- ];
- /** 预览宫格:第 1 个跟随选中的「发起审批」配色,其余用固定多色演示可定制 */
- const PREVIEW_OTHERS = [
- { title: '待办', bg: '#dbeafe', fg: '#2563eb', glyph: '☰' },
- { title: '已办', bg: '#ffedd5', fg: '#ea580c', glyph: '▤' },
- { title: '抄送', bg: '#ede9fe', fg: '#7c3aed', glyph: '↗' },
- { title: '统计', bg: '#fef3c7', fg: '#d97706', glyph: '¥' },
- { title: '通讯录', bg: '#fce7f3', fg: '#db2777', glyph: '☺' },
- { title: '设置', bg: '#eef2f1', fg: '#3d524a', glyph: '⚙' },
- { title: '更多', bg: '#cffafe', fg: '#0891b2', glyph: '▦' }
- ];
- let selected = CURRENT[0];
- function toast(msg) {
- const el = document.getElementById('toast');
- el.textContent = msg;
- el.classList.add('show');
- clearTimeout(toast._t);
- toast._t = setTimeout(() => el.classList.remove('show'), 1400);
- }
- async function copyText(t) {
- try {
- await navigator.clipboard.writeText(t);
- } catch {
- const ta = document.createElement('textarea');
- ta.value = t;
- document.body.appendChild(ta);
- ta.select();
- document.execCommand('copy');
- ta.remove();
- }
- toast('已复制');
- }
- function renderCard(p, host) {
- const el = document.createElement('article');
- el.className = 'card' + (p.current ? ' is-current' : '') + (selected?.id === p.id ? ' is-selected' : '');
- el.style.setProperty('--fg', p.fg);
- el.innerHTML = `
- <div class="icon-box" style="background:${p.bg};color:${p.fg}">${ICON}</div>
- <div class="name">${p.name}</div>
- <div class="meta">${p.bg}<br/>${p.fg}</div>
- <span class="tag ${p.tagClass || ''}">${p.tag || ''}</span>
- `;
- el.addEventListener('click', () => {
- selected = p;
- sync();
- });
- host.appendChild(el);
- }
- function renderLiveGrid() {
- const grid = document.getElementById('liveGrid');
- const first = `
- <div class="menu-card">
- <div class="menu-icon" style="background:${selected.bg};color:${selected.fg}">${ICON}</div>
- <div class="menu-title">发起审批</div>
- </div>`;
- const rest = PREVIEW_OTHERS.map(
- (o) => `
- <div class="menu-card">
- <div class="menu-icon" style="background:${o.bg};color:${o.fg}">
- <span style="font-size:20px;line-height:1;color:${o.fg}">${o.glyph}</span>
- </div>
- <div class="menu-title">${o.title}</div>
- </div>`
- ).join('');
- grid.innerHTML = first + rest;
- }
- function syncFooter() {
- const sw = document.getElementById('pickedSw');
- sw.style.background = selected.bg;
- sw.style.color = selected.fg;
- sw.innerHTML = ICON;
- document.getElementById('pickedName').textContent = selected.name;
- document.getElementById('pickedHex').textContent = `${selected.bg} / ${selected.fg}`;
- }
- function sync() {
- document.getElementById('g-current').innerHTML = '';
- document.getElementById('g-oa').innerHTML = '';
- document.getElementById('g-extra').innerHTML = '';
- CURRENT.forEach((p) => renderCard(p, document.getElementById('g-current')));
- OA_PAIRS.forEach((p) => renderCard(p, document.getElementById('g-oa')));
- EXTRA.forEach((p) => renderCard(p, document.getElementById('g-extra')));
- renderLiveGrid();
- syncFooter();
- }
- document.getElementById('copyPair').addEventListener('click', () => {
- copyText(`${selected.bg}, ${selected.fg}`);
- });
- document.getElementById('copyJson').addEventListener('click', () => {
- const json = JSON.stringify(
- {
- title: '发起审批',
- icon: 'approve',
- iconBg: selected.bg,
- iconFg: selected.fg
- },
- null,
- 2
- );
- copyText(json);
- });
- // 默认推荐:天蓝(正式、非绿)
- selected = OA_PAIRS[2];
- sync();
- </script>
- </body>
- </html>
|