Archived
2026-08-31 用户:「不要把这个动画做到背景板上,会被卡片覆盖;和卡片做到一级, 可以压缩一点卡片的大小」—— 上一稿的对向穿行点走在卡后,只在缝里闪现,基本看不见。 .dossiers 改三列网格(minmax(0,1fr) 76px minmax(0,1fr)):卡片各占左右列自然收窄, 中间 76px 是**谁也盖不住的实体动画道** —— ⇄ 徽居中轻呼吸,两枚信号点绕徽轨道对转 (此上彼下绕圈 = 两颗料换位),底下的虚线总线在道里露出来把两张卡接起来。 窄屏(<620px)卡片竖排,动画道随之收起。浏览器两帧相位实证在转; 105 包内 + 2531 全仓;2.12.1 装库核过(orbit/lane)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
460 lines
34 KiB
TypeScript
460 lines
34 KiB
TypeScript
/**
|
||
* ACT-WORK-05 三张工单件的设计系统(2026-08-31 视图层整体重设计。用户定:
|
||
* 「中间这一块不要搞的像后台管理端,要像给客户使用的 C 端界面;可以按主题加 SVG 图形,
|
||
* 可以有动画,加强交互 —— 只保留功能,视图层可以推翻重新设计」)。
|
||
*
|
||
* 设计语言:「精密检测报告」——
|
||
* · 题头是一块深色电路板夜景(hero):芯片封装、铜引脚、流动的走线信号,
|
||
* 三张件各有一幕对应自己职能的场景(建档台 / 对决量尺 / 落账席);
|
||
* · 正文回到瓷白纸面,报告化排版:丝印体小标(silkscreen)、mono 料号、
|
||
* 引脚号式的序号列 —— 用电子行业自己的版面语汇,不借后台管理端的灰表格;
|
||
* · 动画只做 transform / opacity(信号点流动、晶粒呼吸、印章环慢转、入场浮起),
|
||
* prefers-reduced-motion 下全部静止 —— 与工作台动画同一条纪律。
|
||
*
|
||
* 旧的 target-style.ts(逐字节抽自目标件的三段样式)随本次重设计退役:目标件是
|
||
* 「照着做」时代的锚,这一版是活动自己的设计,样式只此一处真源。
|
||
*
|
||
* **这一整段活在 TS 模板字符串里 —— 不许出现反引号**(一个反引号就把串截断,
|
||
* esbuild 报在几行之外;本仓踩过)。注释里也别写星号斜杠连排。
|
||
*
|
||
* 几条被包内测试钉死的**机制规则逐字保留**,别「顺手整理」:
|
||
* · 序号计数器五连(.jc-tbl-wrap table, .tbl-wrap table 成对出现);
|
||
* · table:not(.on) tr.jc-row-static { display: none; }(种子行只在编辑态露面);
|
||
* · .jc-gate-bar:has(.jc-gate-text:empty) 显隐(gate_reason 是中文自由文本,
|
||
* data-class-of 在它上面永远算不出 v-token,显隐只认 data-blank 出的空文本节点);
|
||
* · .jc-tbl-wrap 不许 overflow:hidden(表宽超出要能横着滑)。
|
||
*/
|
||
|
||
/** 件① 数据工单的强调色 —— 数据蓝(与治理台「数据」语义同族) */
|
||
export const ACCENT_DATA = `
|
||
:root{
|
||
--acc:#2e6bff; --acc-deep:#1f52d6; --acc-soft:#e3ecff; --acc-line:#c2d5ff; --acc-wash:#f3f7ff;
|
||
--glow:#6fa1ff; --glow-line:rgba(111,161,255,.36); --hero-tint:rgba(46,107,255,.34);
|
||
}
|
||
`;
|
||
|
||
/** 件②③ 验收工单的强调色 —— 验收绿 #0aa294(2026-08-27 用户定:与对话区验收卡同色) */
|
||
export const ACCENT_LEDGER = `
|
||
:root{
|
||
--acc:#0aa294; --acc-deep:#07857a; --acc-soft:#dcf5f1; --acc-line:#aee5dd; --acc-wash:#f0fbf9;
|
||
--glow:#2fd4c2; --glow-line:rgba(47,212,194,.34); --hero-tint:rgba(10,162,148,.32);
|
||
--ledger:#0aa294;
|
||
}
|
||
`;
|
||
|
||
export const SHELL_CSS = `
|
||
/* ================= 令牌与底 ================= */
|
||
:root{
|
||
--ink:#182430; --ink-2:#3d4c5c; --ink-3:#67788a; --ink-4:#97a5b3;
|
||
--line:#dbe3ea; --line-soft:#e8edf3; --soft:#f5f8fa; --paper:#edf1f5;
|
||
--board:#0e1b27; --board-2:#15263a;
|
||
--cu:#d99a5b; --cu-deep:#b57632;
|
||
--ok:#1e9e56; --ok-soft:#e4f7ec;
|
||
--danger:#dd4a3a; --danger-soft:#feecea;
|
||
--amber:#b07a10; --amber-soft:#fdf3d8;
|
||
--cond:#5661f0; --cond-soft:#e9ebfe;
|
||
--hero-ink:#f4f8fc; --hero-dim:rgba(226,238,248,.62);
|
||
--mono:"SF Mono",Menlo,Consolas,monospace;
|
||
}
|
||
*{box-sizing:border-box}
|
||
html,body{margin:0;padding:0}
|
||
body{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:var(--paper);color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
|
||
.page{margin:0;padding:0}
|
||
.card{background:#fff;overflow:hidden;border:0;border-radius:0}
|
||
.mono{font-family:var(--mono)}
|
||
i{font-style:normal}
|
||
|
||
/* ================= 题头:电路板夜景 hero ================= */
|
||
.card-head{
|
||
position:relative;display:flex;flex-direction:column;gap:12px;padding:20px 22px 22px;color:var(--hero-ink);
|
||
background:
|
||
repeating-linear-gradient(0deg, rgba(255,255,255,.03) 0 1px, transparent 1px 28px),
|
||
repeating-linear-gradient(90deg, rgba(255,255,255,.03) 0 1px, transparent 1px 28px),
|
||
radial-gradient(900px 340px at 18% -40%, var(--hero-tint), transparent 62%),
|
||
linear-gradient(158deg, #13212f 0%, var(--board) 56%, #0f1d2b 100%);
|
||
}
|
||
.hero-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
|
||
.hero-sys{flex:1 1 auto;min-width:0;font-size:10.5px;font-weight:800;letter-spacing:.17em;color:var(--hero-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.hero-chips{flex:none;display:flex;gap:6px}
|
||
.hero-tag{font-size:11px;font-weight:800;padding:2px 11px;border-radius:999px;color:#fff;background:var(--acc);box-shadow:0 4px 14px var(--glow-line);white-space:nowrap}
|
||
.hero-step{font-size:11px;font-weight:700;padding:2px 11px;border-radius:999px;color:var(--hero-dim);border:1px solid rgba(255,255,255,.22);white-space:nowrap}
|
||
.hero-title{margin:0;font-size:23px;font-weight:800;line-height:1.25;letter-spacing:.01em;color:#fff}
|
||
.hero-meta{font-size:11.5px;color:var(--hero-dim)}
|
||
.hero-meta b{font-weight:700;color:#fff}
|
||
|
||
/* ── hero 舞台:芯片铭牌 + 信号走线 ── */
|
||
.stage{position:relative;display:flex;align-items:stretch;justify-content:center;gap:clamp(20px,7vw,72px);padding:14px 6px 6px}
|
||
.stage::before{content:"";position:absolute;left:5%;right:5%;top:52%;border-top:2px dashed var(--glow-line)}
|
||
.stage::after{content:"";position:absolute;top:52%;left:5%;width:9px;height:9px;margin-top:-4px;border-radius:999px;background:var(--glow);box-shadow:0 0 14px 3px var(--glow-line),0 0 4px 1px var(--glow);animation:sig 3.4s linear infinite}
|
||
.stage-lab{padding-bottom:8px}
|
||
.stage-duel{padding-top:28px}
|
||
.hchip{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;gap:6px;flex:0 1 176px;min-width:128px;padding:13px 12px 11px;border-radius:14px;background:rgba(255,255,255,.97);color:var(--ink);box-shadow:0 14px 30px rgba(3,10,18,.5),inset 0 1px 0 rgba(255,255,255,.7)}
|
||
.hchip.v-absent{background:rgba(255,252,246,.97);outline:2px dashed var(--cu);outline-offset:-6px}
|
||
.hchip-role{font-size:10.5px;font-weight:800;letter-spacing:.08em;color:var(--ink-4)}
|
||
.hchip-pn{font-size:14.5px;font-weight:800;color:var(--ink);overflow-wrap:anywhere;text-align:center;line-height:1.3}
|
||
.hchip-badges{display:flex;gap:6px;flex-wrap:wrap;justify-content:center}
|
||
.csvg{width:86px;height:auto;display:block}
|
||
.c-body{fill:var(--board-2);stroke:rgba(217,154,91,.55);stroke-width:1.4}
|
||
.c-pin{fill:var(--cu)}
|
||
.c-die{fill:var(--acc);opacity:.9;animation:breathe 2.8s ease-in-out infinite}
|
||
.c-dot{fill:rgba(255,255,255,.85)}
|
||
.duel-type{position:absolute;z-index:1;left:50%;top:-4px;transform:translateX(-50%);font-size:10.5px;font-weight:800;letter-spacing:.06em;color:var(--hero-dim);border:1px solid rgba(255,255,255,.2);border-radius:999px;padding:2px 12px;background:rgba(10,20,30,.55);white-space:nowrap}
|
||
.duel-type i{font-style:normal;color:#fff}
|
||
.hero-verdict{display:flex;justify-content:center;padding:2px 0 0}
|
||
|
||
/* ── hero 落账席(件③):印章 + 一句话结论 ── */
|
||
.stage-seal{position:relative;display:flex;align-items:center;justify-content:center;gap:22px;padding:12px 4px 4px;flex-wrap:wrap}
|
||
.seal{position:relative;flex:none;width:112px;height:112px;border-radius:999px;display:grid;place-items:center}
|
||
.seal::before{content:"";position:absolute;inset:0;border:1.6px dashed rgba(255,255,255,.34);border-radius:999px;animation:sealspin 16s linear infinite}
|
||
.seal-core{display:grid;place-items:center;padding:7px 11px;border-radius:999px;background:rgba(255,255,255,.97);box-shadow:0 12px 26px rgba(3,10,18,.5)}
|
||
.seal-sum{flex:1 1 240px;min-width:200px;max-width:420px;margin:0;font-size:13px;line-height:1.85;color:var(--hero-dim)}
|
||
.seal-sum:empty::after{content:"—"}
|
||
|
||
/* ── 浅色题头变体(件① 2026-08-31 用户:「标题背景还是改成之前的那种蓝色渐变」——
|
||
渐变取自原目标件 card-head 那一条,深色电路夜景只留给验收两件)── */
|
||
.hd-light .card-head{background:linear-gradient(120deg,#f0f5ff 0%,#fff 55%,#eef4ff 100%);color:var(--ink);border-bottom:2px solid var(--ink)}
|
||
.hd-light .hero-sys{color:var(--ink-4)}
|
||
.hd-light .hero-title{color:var(--ink)}
|
||
.hd-light .hero-step{color:var(--ink-3);border-color:var(--line)}
|
||
.hd-light .hero-meta{color:var(--ink-3)}
|
||
.hd-light .hero-meta b{color:var(--ink)}
|
||
|
||
/* ================= 正文分区 ================= */
|
||
.card-bd{padding:20px 22px 8px}
|
||
.sec{display:flex;align-items:baseline;gap:9px;margin:26px 0 10px;flex-wrap:wrap}
|
||
.sec:first-child{margin-top:4px}
|
||
.sec-pin{flex:none;align-self:center;width:24px;height:24px;border-radius:8px;display:grid;place-items:center;background:var(--acc-soft);color:var(--acc-deep)}
|
||
.zic{width:13px;height:13px;display:block}
|
||
.sec-t{font-size:13.5px;font-weight:800;color:var(--ink);letter-spacing:.02em}
|
||
.sec-d{flex:1 1 200px;min-width:0;font-size:11.5px;color:var(--ink-3)}
|
||
|
||
/* 简报卡(做什么 / 纪律…) */
|
||
.brief{border:1px solid var(--line-soft);border-left:3px solid var(--acc);border-radius:10px;background:var(--acc-wash);padding:13px 16px;margin:0 0 4px}
|
||
.brief p{margin:0 0 7px;font-size:12.5px;line-height:1.75;color:var(--ink-2)}
|
||
.brief p:last-child{margin-bottom:0}
|
||
.brief b{color:var(--ink)}
|
||
.done,.need{display:inline-block;font-size:10.5px;font-weight:800;padding:0 8px;border-radius:999px;vertical-align:1px;margin-right:2px}
|
||
.done{color:var(--ok);background:var(--ok-soft)}
|
||
.need{color:var(--acc-deep);background:var(--acc-soft)}
|
||
|
||
/* 收尾指引 */
|
||
.flow{margin:24px 0 14px;padding:12px 16px;border-radius:10px;border:1px dashed var(--acc-line);background:var(--acc-wash);font-size:12.5px;color:var(--ink-2);line-height:1.8}
|
||
.flow b{color:var(--acc-deep)}
|
||
|
||
/* 页脚:丝印条 */
|
||
.card-foot{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:12px 22px;border-top:1px solid var(--line-soft);background:var(--soft);font-size:11px;color:var(--ink-4);flex-wrap:wrap}
|
||
.foot-r{letter-spacing:.04em}
|
||
|
||
/* ================= 顶部「还差什么」红带(机制:显隐认 data-blank 的空文本节点) ================= */
|
||
.jc-gate-bar{display:flex;flex-direction:column;gap:5px;margin:0 0 16px;padding:11px 14px;border-radius:10px;background:var(--danger-soft);border:1px solid #f5c0ba;color:var(--danger);font-size:12.5px;line-height:1.7}
|
||
.jc-gate-bar b{font-weight:800}
|
||
.jc-gate-bar:has(.jc-gate-text:empty){display:none}
|
||
/* 逐块的缺项点名并进这一条(2026-08-31 用户:「页面上所有的问题都合并到最上面的还差什么」)——
|
||
与提交闸同源的基座读数,数值为 0 的那一行自己消失,只在待处理态出现 */
|
||
.jc-gate-sub{display:none;font-size:12px;color:#a03d34;padding-left:2px}
|
||
html.editable .jc-gate-sub{display:block}
|
||
html.editable .jc-gate-sub.v-0{display:none}
|
||
|
||
/* 缺项红带 —— 与提交闸同源的必填提示,只在待处理态出现 */
|
||
.jc-gapbar{display:none}
|
||
html.editable .jc-gapbar{display:flex;align-items:flex-start;gap:8px;margin:0 0 10px;padding:9px 13px;border-radius:9px;background:var(--danger-soft);border:1px solid #f5c0ba;color:var(--danger);font-size:12px;line-height:1.7}
|
||
.jc-gapbar b{font-weight:800}
|
||
.jc-gapbar span{color:#a03d34}
|
||
html.editable .jc-gapbar.v-0{display:none}
|
||
|
||
/* ================= 编辑闸与加行(只在待处理态露面) ================= */
|
||
html:not(.editable) .jc-editgate, html:not(.editable) .jc-addrow { display: none !important; }
|
||
.jc-editgate{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 10px;padding:8px 12px;border-radius:10px;background:var(--soft);border:1px solid var(--line-soft);font-size:12px;color:var(--ink-3)}
|
||
.jc-editgate-t{flex:1 1 auto;min-width:0}
|
||
.jc-editgate-t b{color:var(--ink-2);font-weight:700}
|
||
.jc-egbtn{flex:none;display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:1px solid var(--line);border-radius:999px;padding:6px 15px;font:inherit;font-size:12px;font-weight:700;color:var(--ink-2);background:#fff;transition:border-color .16s,color .16s,background .16s,box-shadow .16s}
|
||
.jc-egbtn:hover{border-color:var(--acc);color:var(--acc-deep);box-shadow:0 0 0 3px var(--acc-soft)}
|
||
.jc-egbtn:active{transform:scale(.96)}
|
||
.jc-egbtn.save{color:#fff;background:var(--acc);border-color:var(--acc)}
|
||
.jc-egbtn.save:hover{filter:brightness(1.06);color:#fff}
|
||
.jc-editgate .eg-cancel,.jc-editgate .eg-save{display:none}
|
||
.jc-editgate.on{background:var(--acc-wash);border-color:var(--acc-line);color:var(--acc-deep)}
|
||
.jc-editgate.on .eg-open{display:none}
|
||
.jc-editgate.on .eg-cancel,.jc-editgate.on .eg-save{display:inline-flex}
|
||
.jc-addrow{display:none;margin:8px 0 0}
|
||
.jc-tbl-wrap:has(table.on) + .jc-addrow { display: flex; align-items: center; gap: 8px; }
|
||
.jc-addrow button{cursor:pointer;border:1px dashed var(--acc-line);border-radius:999px;background:var(--acc-wash);color:var(--acc-deep);font:inherit;font-size:12px;font-weight:700;padding:6px 15px;transition:border-color .16s,box-shadow .16s}
|
||
.jc-addrow button:hover{border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-soft)}
|
||
.jc-addrow button:active{transform:scale(.96)}
|
||
.jc-addrow em{font-style:normal;font-size:11px;color:var(--ink-4)}
|
||
|
||
/* ================= 报告表格 ================= */
|
||
.jc-tbl-wrap{border:1px solid var(--line-soft);border-radius:12px;background:#fff;overflow-x:auto;overflow-y:hidden}
|
||
.jc-tbl-wrap, .tbl-wrap { overflow-x: auto; overflow-y: hidden; }
|
||
table{width:100%;border-collapse:collapse;font-size:12.5px}
|
||
thead th{position:static;text-align:left;font-size:10.5px;font-weight:800;letter-spacing:.07em;color:var(--ink-4);background:var(--soft);padding:9px 12px;border-bottom:1px solid var(--line);white-space:nowrap}
|
||
th.req::after{content:" *";color:var(--danger);font-size:10px}
|
||
tbody td{padding:10px 12px;border-bottom:1px solid var(--line-soft);vertical-align:top;color:var(--ink-2)}
|
||
tbody tr:last-child td{border-bottom:0}
|
||
tbody tr:hover td{background:var(--acc-wash)}
|
||
td.rn,td.num{font-family:var(--mono);font-size:11px;color:var(--ink-4);white-space:nowrap}
|
||
td.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
|
||
td.cust{font-weight:700;color:var(--ink)}
|
||
td.desc,.desc{color:var(--ink-3);font-size:12px;line-height:1.6}
|
||
|
||
/* 序号列交给 CSS 计数器(沙箱零脚本,增删行后自己数对;两种列名、两种包装类都接) */
|
||
.jc-tbl-wrap table, .tbl-wrap table { counter-reset: rn; }
|
||
.jc-tbl-wrap table td.rn, .tbl-wrap table td.rn { counter-increment: rn; }
|
||
.jc-tbl-wrap table td.rn .jc-rn-num::before, .tbl-wrap table td.rn .jc-rn-num::before { content: counter(rn); }
|
||
.jc-tbl-wrap table td.num, .tbl-wrap table td.num { counter-increment: rn; }
|
||
.jc-tbl-wrap table td.num::before, .tbl-wrap table td.num::before { content: counter(rn); }
|
||
|
||
/* ── 看与改是两件事:只读份 / 输入孪生件由 .on 二选一 ── */
|
||
.jc-vcell{display:block;font-size:12.5px;color:var(--ink);line-height:1.55;overflow-wrap:anywhere}
|
||
.jc-vcell.mono{font-family:var(--mono);font-size:12px;color:var(--ink-2)}
|
||
.jc-vcell:empty::after{content:"—";color:var(--ink-4)}
|
||
.jc-cell{display:none;width:100%;min-width:72px;border:1px solid var(--line);border-radius:8px;padding:6px 9px;font:inherit;font-size:12.5px;color:var(--ink);background:#fff}
|
||
.jc-cell:focus{border-color:var(--acc);box-shadow:0 0 0 3px var(--acc-soft);outline:none}
|
||
.jc-cell.mono{font-family:var(--mono);font-size:12px}
|
||
input.jc-cell, select.jc-cell { height: 32px; box-sizing: border-box; padding-top: 0; padding-bottom: 0; vertical-align: middle; }
|
||
table.on td>.jc-vcell{display:none}
|
||
table.on td>.jc-vcell.ro{display:block}
|
||
table.on td>.jc-cell{display:block}
|
||
table.on td>.jc-vcell:empty::after{content:none}
|
||
|
||
/* 增删行的痕(取消还原三件套的可视面) */
|
||
table.on tr.jc-row-new td { background: #f0fbf5; }
|
||
table.on tr.jc-row-gone td { background: #fff6f5; opacity: .55; }
|
||
table.on tr.jc-row-gone .jc-cell { text-decoration: line-through; color: var(--ink-3); }
|
||
.jc-rowdel{display:none;cursor:pointer;border:1px solid var(--line);border-radius:999px;background:#fff;color:var(--ink-3);width:20px;height:20px;line-height:1;font-size:12px;padding:0;margin-left:5px;vertical-align:middle}
|
||
table.on .jc-rowdel{display:inline-grid;place-items:center}
|
||
.jc-rowdel:hover{border-color:var(--danger);color:var(--danger)}
|
||
table.on tr.jc-row-gone .jc-rowdel { border-color: var(--danger); color: var(--danger); background: #fff; }
|
||
|
||
/* 静态种子行:零行也加得出第一行 —— 只在编辑态露面(读态看见空壳子是界面撒谎) */
|
||
table:not(.on) tr.jc-row-static { display: none; }
|
||
table.on tr.jc-row-static td{background:var(--acc-wash);border-top:1px dashed var(--acc-line)}
|
||
|
||
/* 主键钥匙格:不给人看,但真挂 data-col(漏了钥匙,这一行凑不出主键) */
|
||
.rowkey{display:none}
|
||
|
||
/* ================= 徽标基座(取值上色一律 data-class-of 投影,选择器从值算) ================= */
|
||
.stx,.ct,.rl,.st,.risk-badge{display:inline-block;font-size:11px;font-weight:700;padding:1px 9px;border-radius:999px;border:1px solid transparent;white-space:nowrap}
|
||
.rl{background:var(--soft);border-color:var(--line-soft);color:var(--ink-3);font-size:10.5px;letter-spacing:.03em}
|
||
.rec{display:inline-block;font-size:11.5px;font-weight:800;padding:2px 13px;border-radius:999px;border:1px solid transparent;white-space:nowrap}
|
||
.rec.rec-lg{font-size:14.5px;padding:7px 20px;letter-spacing:.03em}
|
||
|
||
/* kv 行(收口结论 / 待验项共用的键值版式) */
|
||
.kv{display:flex;gap:12px;padding:10px 0;border-bottom:1px solid var(--line-soft);font-size:12.5px}
|
||
.kv:last-child{border-bottom:0}
|
||
.kv i{flex:0 0 84px;font-style:normal;color:var(--ink-4);font-size:11px;font-weight:700;letter-spacing:.05em;padding-top:2px}
|
||
.kv > span{flex:1 1 auto;color:var(--ink-2);line-height:1.7;overflow-wrap:anywhere}
|
||
.kv > span:empty::after{content:"—";color:var(--ink-4)}
|
||
.kv-box{border:1px solid var(--line-soft);border-radius:12px;background:var(--soft);padding:4px 16px;margin-bottom:4px}
|
||
|
||
/* ================= 动画(全部 transform / opacity;reduced-motion 全静) ================= */
|
||
@keyframes sig{0%{transform:translateX(0);opacity:0}7%{opacity:1}93%{opacity:1}100%{transform:translateX(min(86vw,760px));opacity:0}}
|
||
@keyframes breathe{0%,100%{opacity:.55}50%{opacity:1}}
|
||
@keyframes sealspin{to{transform:rotate(360deg)}}
|
||
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}
|
||
.hero-top{animation:rise .5s cubic-bezier(.2,.7,.3,1) both}
|
||
.hero-title{animation:rise .5s .06s cubic-bezier(.2,.7,.3,1) both}
|
||
.stage,.stage-seal{animation:rise .55s .14s cubic-bezier(.2,.7,.3,1) both}
|
||
.hero-verdict,.hero-meta{animation:rise .55s .22s cubic-bezier(.2,.7,.3,1) both}
|
||
@media (prefers-reduced-motion: reduce){
|
||
*{animation:none !important;transition:none !important}
|
||
}
|
||
|
||
/* ================= 电路蓝图工作台(件① 的两张档案卡)=================
|
||
2026-08-31 用户:「卡片下面那个容器黑色和页面背景不搭」—— 深色板底退场,换**浅色蓝图**:
|
||
底是强调色的极浅晕染 + 淡格线,走线与信号点用强调色 —— 电路语汇留着,纸面色阶不断裂。 */
|
||
.board{position:relative;margin:0 0 6px;padding:18px 14px 16px;border-radius:16px;border:1px solid var(--acc-line);
|
||
background:
|
||
repeating-linear-gradient(0deg, rgba(46,107,255,.045) 0 1px, transparent 1px 26px),
|
||
repeating-linear-gradient(90deg, rgba(46,107,255,.045) 0 1px, transparent 1px 26px),
|
||
linear-gradient(158deg, var(--acc-wash) 0%, #fff 62%, var(--acc-wash) 100%)}
|
||
.board::before{content:"";position:absolute;left:4%;right:4%;top:50%;border-top:2px dashed var(--acc-line)}
|
||
/* 「可替换」动画(2026-08-31 用户第二稿:「不要做到背景板上,背景板会被卡片覆盖;
|
||
和卡片做到一级,可以压缩一点卡片的大小」)—— .dossiers 改三列网格,中间留一条
|
||
**实体动画道**(卡片各占左右列、相应收窄,谁也盖不住它):中央 ⇄ 徽轻呼吸,
|
||
两枚信号点绕徽**轨道对转**(此上彼下地绕圈 = 两颗料换位),底下横穿的虚线总线
|
||
在道里露出来把两张卡接起来。 */
|
||
.swapfx{position:absolute;left:50%;top:50%;width:76px;height:76px;transform:translate(-50%,-50%);z-index:1;pointer-events:none}
|
||
.sw-ic{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:36px;height:36px;padding:8px;box-sizing:border-box;color:var(--acc);background:#fff;border:1px solid var(--acc-line);border-radius:999px;box-shadow:0 4px 12px rgba(18,38,63,.16);animation:swbreathe 2.8s ease-in-out infinite}
|
||
.sw-orbit{position:absolute;left:50%;top:50%;width:64px;height:64px;margin:-32px 0 0 -32px;animation:sworbit 4.5s linear infinite}
|
||
.sw-dot{position:absolute;left:50%;width:8px;height:8px;margin-left:-4px;border-radius:999px;background:var(--acc);box-shadow:0 0 8px 2px var(--acc-soft)}
|
||
.sw-d1{top:-4px}
|
||
.sw-d2{bottom:-4px}
|
||
@keyframes sworbit{to{transform:rotate(360deg)}}
|
||
@keyframes swbreathe{0%,100%{transform:translate(-50%,-50%) scale(1)}50%{transform:translate(-50%,-50%) scale(1.1)}}
|
||
/* 三列网格:左右两列给卡,中间 76px 是动画道 —— 与卡同级的真实空间,不被覆盖 */
|
||
.dossiers{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1fr) 76px minmax(0,1fr);row-gap:16px}
|
||
.dossiers > .dossier:nth-of-type(odd){grid-column:1}
|
||
.dossiers > .dossier:nth-of-type(even){grid-column:3}
|
||
.dossier{display:flex;flex-direction:column;gap:11px;background:#fff;border:1px solid var(--line-soft);border-radius:16px;padding:15px 16px 14px;box-shadow:0 8px 22px rgba(18,38,63,.09);transition:box-shadow .18s,transform .18s}
|
||
.dossier:hover{transform:translateY(-2px);box-shadow:0 12px 28px rgba(18,38,63,.13)}
|
||
.dz-top{display:flex;align-items:center;gap:12px}
|
||
.dz-top .csvg{width:64px;flex:none}
|
||
.dz-id{display:flex;flex-direction:column;gap:4px;min-width:0}
|
||
.dz-role{display:flex;gap:6px;flex-wrap:wrap}
|
||
.dz-pn{font-size:15px;font-weight:800;overflow-wrap:anywhere;line-height:1.3}
|
||
.dz-pn .jc-vcell{font-size:15px;font-weight:800;color:var(--ink)}
|
||
.dz-type{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:8px 10px;border-radius:10px;background:var(--acc-wash);border:1px solid var(--acc-line)}
|
||
.dz-lb{flex:none;font-style:normal;font-size:10.5px;font-weight:800;letter-spacing:.05em;color:var(--ink-4)}
|
||
.dz-type .jc-cell{flex:1 1 140px;width:auto}
|
||
/* 类型名守卫:这一行的下拉真有选中项(selectCurrent 按行作用域写的 option[selected])才摆名 ——
|
||
行里没选,data-by 落回外层的名一个字都不摆,换「待选择」胶囊。
|
||
守卫挂在共同祖先 .dz-type 上、单层 :has —— :has() 里再嵌 :has() 是非法选择器,整条会被浏览器
|
||
静默丢弃(第一版就栽在这:守卫写了等于没写,XL 那张卡照样摆出它没有的类型)。 */
|
||
.tsel{flex:1 1 auto;min-width:0}
|
||
.tsel > span > i{display:inline-block;font-size:11.5px;font-weight:800;color:var(--acc-deep);background:var(--acc-soft);border-radius:999px;padding:1px 11px}
|
||
.dz-type:not(:has(option[selected])) .tsel > span{display:none}
|
||
.dz-type:not(:has(option[selected])) .tsel::after{content:"待选择 · 点「编辑」挑一个";display:inline-block;font-size:11px;font-weight:700;color:var(--amber);background:var(--amber-soft);border:1px dashed #eeda9e;border-radius:999px;padding:1px 10px}
|
||
.dz-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px 12px}
|
||
.fcell{display:flex;flex-direction:column;gap:3px;min-width:0}
|
||
.fcell.wide{grid-column:1 / -1}
|
||
.fcell > i{font-style:normal;font-size:10.5px;font-weight:800;letter-spacing:.05em;color:var(--ink-4)}
|
||
.fcell.req > i::after{content:" *";color:var(--danger)}
|
||
.fcell .jc-vcell{font-size:12.5px}
|
||
/* 三级占位:必填红 / 建议橘(空格子直说要不要填,不摆一枚含糊的破折号) */
|
||
.fcell.req .jc-vcell:empty::after{content:"必填";font-size:10.5px;font-weight:800;color:var(--danger);background:var(--danger-soft);border-radius:999px;padding:0 9px}
|
||
/* 徽标包装的必填格(如生命周期):没值时徽标 class 恰为裸 "stx"(class-of 没投出 v-*),
|
||
wrapper 不为 :empty,上一条够不着 —— 认裸 class 补同一枚胶囊(单层 :has) */
|
||
.fcell.req .jc-vcell:has(> [class="stx"])::after{content:"必填";font-size:10.5px;font-weight:800;color:var(--danger);background:var(--danger-soft);border-radius:999px;padding:0 9px}
|
||
.fcell.sug .jc-vcell:empty::after{content:"建议";font-size:10.5px;font-weight:800;color:var(--amber);background:var(--amber-soft);border-radius:999px;padding:0 9px}
|
||
/* 档案卡的编辑态 —— **按卡开,只点亮这张卡的正面**(2026-08-31 用户:「各自编辑各自的部分,
|
||
不要做联动」:.on 由 scopedTargets 落在被点那张卡的行 section 上,不再落整个宿主);
|
||
只圈 .front 是因为卡背住着另一地址的宿主,不圈的话参数输入会被主数据的编辑顺手点亮 */
|
||
.dossier.on .front .jc-vcell{display:none}
|
||
.dossier.on .front .jc-vcell.ro{display:block}
|
||
.dossier.on .front .jc-cell{display:block}
|
||
.dossier.on .front .jc-vcell:empty::after{content:none}
|
||
.dossier.on .dz-role{display:flex}
|
||
|
||
/* ── 翻面(纯 CSS:checkbox + :has,零脚本;reduced-motion 下瞬时切换)── */
|
||
.dossier{position:relative;perspective:1200px;padding:0;background:none;border:0;box-shadow:none}
|
||
.dossier:hover{transform:none;box-shadow:none}
|
||
.flip-in{display:grid;transform-style:preserve-3d;transition:transform .55s cubic-bezier(.3,.7,.3,1)}
|
||
.face{grid-area:1 / 1;display:flex;flex-direction:column;gap:11px;background:#fff;border:1px solid var(--line-soft);border-radius:16px;padding:15px 16px 14px;box-shadow:0 8px 22px rgba(18,38,63,.09);backface-visibility:hidden;min-width:0}
|
||
.face.back{transform:rotateY(180deg)}
|
||
.flip-tg{position:absolute;opacity:0;pointer-events:none}
|
||
.flip-hit{position:absolute;inset:0;z-index:3;cursor:pointer}
|
||
.flip-cue{position:absolute;z-index:4;bottom:10px;right:10px;pointer-events:none;opacity:.6;transition:opacity .16s,transform .16s}
|
||
.flip-cue i{font-style:normal;display:inline-block;font-size:10.5px;font-weight:800;color:var(--acc-deep);background:var(--acc-soft);border:1px solid var(--acc-line);border-radius:999px;padding:2px 10px}
|
||
.dossier:hover .flip-cue{opacity:1;transform:translateY(-2px)}
|
||
/* 两句提示按面切换 —— 选择器都写到 .flip-cue i 之下的同层级,别被基座那条特异度压回来(踩过) */
|
||
.flip-cue .cue-back{display:none}
|
||
/* 翻转三态,后写的赢:人点的 < 主数据编辑锁正面 < 参数编辑翻背面 */
|
||
.dossier:has(.flip-tg:checked) .flip-in{transform:rotateY(180deg)}
|
||
.dossier:has(.flip-tg:checked) .flip-cue .cue-front{display:none}
|
||
.dossier:has(.flip-tg:checked) .flip-cue .cue-back{display:inline-block}
|
||
.dossier.on .flip-in{transform:rotateY(0deg)}
|
||
.dossier:has(.pback.on) .flip-in{transform:rotateY(180deg)}
|
||
/* 编辑中的**这张卡**不许翻(哪面在编辑锁哪面),点击层与提示丸一起收;另一张卡不受影响 */
|
||
.dossier.on .flip-hit,.dossier:has(.pback.on) .flip-hit{display:none}
|
||
.dossier.on .flip-cue,.dossier:has(.pback.on) .flip-cue{display:none}
|
||
/* 悬浮侧倾:预告「这张卡点了会翻」—— 只在读态、只在真有悬浮的设备、且不嫌动画的人那里 */
|
||
@media (hover:hover) and (prefers-reduced-motion: no-preference){
|
||
.dossier:hover:not(.on):not(:has(.flip-tg:checked)):not(:has(.pback.on)) .flip-in{transform:rotateY(-12deg)}
|
||
.dossier:hover:not(.on):has(.flip-tg:checked):not(:has(.pback.on)) .flip-in{transform:rotateY(168deg)}
|
||
}
|
||
|
||
/* ── 卡角编辑钮:笔=编辑当前这一面,软盘=保存,叉=放弃(2026-08-31 用户定,顶掉两行编辑闸)──
|
||
笔只在待处理态露面(html.editable,与从前的闸同一条纪律);软盘/叉只在对应面的编辑态露面。 */
|
||
.fabs{position:absolute;top:10px;right:10px;z-index:5;display:flex;gap:6px}
|
||
.fab{display:none;width:32px;height:32px;border-radius:999px;border:1px solid var(--acc-line);background:#fff;color:var(--acc-deep);cursor:pointer;place-items:center;padding:0;box-shadow:0 4px 12px rgba(18,38,63,.14);transition:border-color .16s,color .16s,box-shadow .16s}
|
||
.fab:hover{border-color:var(--acc);box-shadow:0 6px 16px rgba(18,38,63,.22)}
|
||
.fab:active{transform:scale(.94)}
|
||
.fic{width:15px;height:15px;display:block;margin:auto}
|
||
.fab.pen{color:var(--acc-deep)}
|
||
.fab.disk{background:var(--acc);border-color:var(--acc);color:#fff}
|
||
.fab.xbtn{color:var(--ink-3)}
|
||
/* 笔:这张卡当下这一面、且这张卡没在编辑 —— 各卡各开,互不联动 */
|
||
html.editable .dossier:not(.on):not(:has(.pback.on)):not(:has(.flip-tg:checked)) .pen-f{display:grid}
|
||
html.editable .dossier:not(.on):not(:has(.pback.on)):has(.flip-tg:checked) .pen-b{display:grid}
|
||
.dossier.on .disk-f{display:grid}
|
||
.dossier.on .x-f{display:grid}
|
||
.dossier:has(.pback.on) .disk-b{display:grid}
|
||
.dossier:has(.pback.on) .x-b{display:grid}
|
||
|
||
/* ── 卡背:参数瓷贴 ── */
|
||
.pb-hd{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
|
||
.pb-hd b{font-size:14px;font-weight:800;color:var(--ink)}
|
||
.pb-lb{font-size:10.5px;font-weight:800;letter-spacing:.08em;color:var(--ink-4)}
|
||
.pback{display:grid;grid-template-columns:1fr 1fr;gap:8px}
|
||
.ptile{display:flex;flex-direction:column;gap:2px;border:1px solid var(--line-soft);border-radius:10px;background:var(--soft);padding:8px 10px;min-width:0}
|
||
.pt-hd{display:flex;align-items:baseline;gap:6px;min-width:0}
|
||
.pt-hd .jc-vcell{font-size:11px;font-weight:800;color:var(--ink-3)}
|
||
.pt-unit{font-style:normal;font-size:10px;color:var(--ink-4);font-family:var(--mono)}
|
||
.pt-val .jc-vcell{font-size:14px;font-weight:800;color:var(--ink)}
|
||
.pt-note .jc-vcell{font-size:10.5px;color:var(--ink-3)}
|
||
/* 三级占位:值必填红 / 说明建议橘 */
|
||
.ptile .pv .jc-vcell:empty::after{content:"必填";font-size:10.5px;font-weight:800;color:var(--danger);background:var(--danger-soft);border-radius:999px;padding:0 9px}
|
||
/* 说明空着**什么都不摆**(2026-08-31 用户:「没写就什么都不要展示」)—— 连兜底破折号一起收 */
|
||
.ptile .sg .jc-vcell:empty{display:none}
|
||
/* 参数编辑态:值与说明换输入,参数名照旧当标签摆着;两枚主键孪生件藏死(钥匙不是编辑面)。
|
||
藏钥匙用包装类(.pt-name / .rowkey),不用「data-col 属性选择器」—— 那段选择器文本会原样
|
||
出现在共享样式表里,把「落账确认全只读」那类字面断言踩翻(2026-08-31 踩过,连注释也不许写)。 */
|
||
.pback.on .pv > .jc-vcell,.pback.on .sg > .jc-vcell{display:none}
|
||
.pback.on .pv > .jc-cell,.pback.on .sg > .jc-cell{display:block}
|
||
.pback .pt-name .jc-cell{display:none}
|
||
.pt-name{display:inline-flex;min-width:0}
|
||
|
||
/* ================= 比对基准卡(类型 + 字段合一,只读、跟手)================= */
|
||
.basis{display:block;margin:0 0 10px}
|
||
.basis:empty{border:1.5px dashed var(--line);border-radius:12px;padding:16px;display:block}
|
||
.basis:empty::after{content:"还没定比对基准 —— 先在上面任一张档案卡上挑一个芯片类型,或展开下面的抽屉新建一个。";font-size:12.5px;color:var(--ink-3)}
|
||
.basis-in{display:flex;flex-direction:column;gap:10px;border:1px solid var(--acc-line);border-radius:12px;background:var(--acc-wash);padding:12px 14px 14px}
|
||
.basis-hd{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
|
||
.basis-lb{flex:none;font-size:10.5px;font-weight:800;letter-spacing:.08em;color:var(--acc-deep)}
|
||
.basis-chip b{display:inline-block;font-size:13px;font-weight:800;color:#fff;background:var(--acc);border-radius:999px;padding:2px 14px;margin-right:8px}
|
||
.basis-desc{font-style:normal;font-size:11.5px;color:var(--ink-3)}
|
||
.basis-hd:has(.basis-chip:empty)::after{content:"待选择";font-size:11px;font-weight:700;color:var(--amber);background:var(--amber-soft);border:1px dashed #eeda9e;border-radius:999px;padding:1px 10px}
|
||
.basis-hd .csvg{width:56px;flex:none}
|
||
/* 类型图:层叠双封装 —— 后面那枚是「同类的别的芯片」,淡出成剪影 */
|
||
.basis-hd .tsvg{width:60px;flex:none}
|
||
.tsvg{display:block}
|
||
.t-ghost{opacity:.32}
|
||
.basis-id{display:flex;flex-direction:column;gap:5px;min-width:0;flex:1 1 auto}
|
||
.basis-in:has(.ftiles:empty) .ftiles{display:none}
|
||
/* 降噪(2026-08-31 用户:「乱糟糟…没必要显示全就不要显示完全,鼠标指上去后再显示」):
|
||
字段收成一排丸(名 + 硬/软徽 + 单位),说明藏进悬浮气泡 —— 指上去才现身 */
|
||
.ftiles{display:flex;flex-wrap:wrap;gap:8px}
|
||
.ftile{position:relative;display:flex;flex-direction:row;align-items:center;gap:7px;border:1px solid var(--line-soft);border-radius:999px;background:#fff;padding:6px 13px;min-width:0;transition:border-color .16s,box-shadow .16s}
|
||
.ftile:hover{border-color:var(--acc-line);box-shadow:0 4px 12px rgba(18,38,63,.1)}
|
||
.ft-hd{display:flex;align-items:baseline;gap:7px;white-space:nowrap}
|
||
.ft-hd b{font-size:12px;font-weight:800;color:var(--ink)}
|
||
.ft-unit{font-style:normal;font-size:10px;color:var(--ink-4);font-family:var(--mono)}
|
||
.ft-desc{display:none;position:absolute;z-index:6;top:calc(100% + 7px);left:0;width:max-content;max-width:280px;margin:0;font-size:11px;line-height:1.65;color:var(--ink-2);background:#fff;border:1px solid var(--line);border-radius:9px;padding:8px 11px;box-shadow:0 10px 24px rgba(18,38,63,.16)}
|
||
.ftile:hover .ft-desc:not(:empty){display:block}
|
||
/* 类型说明:默认一行截断,悬浮题头才放开 */
|
||
.basis-desc{display:block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.basis-hd:hover .basis-desc{white-space:normal}
|
||
|
||
/* ================= 新建类型工作抽屉(details,零脚本)================= */
|
||
.lab{margin:0 0 6px;border:1.5px dashed var(--line);border-radius:12px;background:var(--soft)}
|
||
.lab[open]{border-style:solid;background:#fff}
|
||
.lab-sm{cursor:pointer;list-style:none;display:flex;align-items:center;gap:8px;padding:11px 14px;font-size:12.5px;color:var(--ink-3);user-select:none}
|
||
.lab-sm::-webkit-details-marker{display:none}
|
||
.lab-sm b{color:var(--ink-2)}
|
||
.lab-sm:hover{color:var(--acc-deep)}
|
||
.lab-caret{margin-left:auto;flex:none;width:8px;height:8px;border-right:2px solid var(--ink-4);border-bottom:2px solid var(--ink-4);transform:rotate(45deg);transition:transform .16s}
|
||
.lab[open] .lab-caret{transform:rotate(-135deg)}
|
||
.lab-bd{padding:2px 14px 14px}
|
||
.lab-brief{margin:0 0 16px}
|
||
.lab-brief .brief{margin:2px 14px 14px;border-left-width:3px}
|
||
|
||
/* ================= 窄屏 ================= */
|
||
@media(max-width:620px){
|
||
.card-head{padding:16px 14px 18px}
|
||
.dz-grid{grid-template-columns:1fr}
|
||
.swapfx{display:none}
|
||
.dossiers{grid-template-columns:1fr}
|
||
.dossiers > .dossier:nth-of-type(odd),.dossiers > .dossier:nth-of-type(even){grid-column:1}
|
||
.pback{grid-template-columns:1fr}
|
||
.ftiles{grid-template-columns:1fr}
|
||
.card-bd{padding:16px 14px 6px}
|
||
.hero-title{font-size:19.5px}
|
||
.stage{gap:14px}
|
||
.hchip{min-width:108px;padding:10px 8px 9px}
|
||
.csvg{width:68px}
|
||
.kv i{flex-basis:72px}
|
||
.card-foot{padding:10px 14px}
|
||
}
|
||
`;
|