From 4190848c4a22fa40b2ac1300ac87f434e10cf832 Mon Sep 17 00:00:00 2001 From: maogeigei Date: Sun, 13 Sep 2026 20:15:33 +0800 Subject: [PATCH] =?UTF-8?q?style(ui):=20=E3=80=8C=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E3=80=8D=E8=A7=86=E8=A7=89=E5=B1=82=E6=8C=89?= =?UTF-8?q?=2006-=E5=B7=A5=E4=BD=9C=E5=8F=B0UI=E8=A7=84=E8=8C=83=20?= =?UTF-8?q?=E9=87=8D=E5=81=9A=EF=BC=88=E7=94=A8=E6=88=B7=E5=8F=8D=E9=A6=88?= =?UTF-8?q?=E6=AF=9B=E5=9D=AF=E6=88=BF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 管理项 行 → 卡片网格(§4.5 .data-card:r12 / 16px 18px / 轻投影 / hover 上浮 2px + 蓝边 + 蓝影) - 弹窗 → §4.7(mask rgba(0,0,0,.35);面板 r14 / 22px 26px / 520px / 0 8px 30px / 进场动画) - 按钮 §4.1 .btn-sm 量级 + hover;计数右对齐 + tabular-nums(§5);字号阶梯 15/13/17 - 卡片补图标;prefers-reduced-motion 降级 - 色彩仍用 dsh 官方 token --dsw-*(嵌在 dsh 面板内须跟随主题,规范硬色值是给门户静态页的) - 版本 0.3.0 → 0.3.1,已铺发 --- poc/business-plugins/lib/client.js | 58 ++++++++++++++++++++---------- poc/business-plugins/package.json | 2 +- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/poc/business-plugins/lib/client.js b/poc/business-plugins/lib/client.js index 7285a7b..b2d1498 100644 --- a/poc/business-plugins/lib/client.js +++ b/poc/business-plugins/lib/client.js @@ -338,7 +338,21 @@ window.__ModuleLoader__.load({ ".bp-row:hover{border-color:var(--dsw-alias-brand-primary, #2f6fed);box-shadow:0 4px 12px rgba(47,111,237,.15)}", ".bp-btn{transition:border-color .18s cubic-bezier(.16,1,.3,1),color .18s cubic-bezier(.16,1,.3,1)}", ".bp-btn:hover:not(:disabled){border-color:var(--dsw-alias-brand-primary, #2f6fed);color:var(--dsw-alias-brand-primary, #2f6fed)}", - ".bp-row input[type=checkbox]{cursor:pointer;margin:0}" + ".bp-row input[type=checkbox]{cursor:pointer;margin:0}", + + // 2026-09-13 ·「系统管理」视觉层(对齐 06-工作台UI规范:§4.5 卡片 hover 上浮 / §4.7 弹窗 / §4.1 按钮) + ".pa-card{transition:border-color .15s cubic-bezier(.16,1,.3,1),box-shadow .15s cubic-bezier(.16,1,.3,1),transform .15s cubic-bezier(.16,1,.3,1)}", + ".pa-card:hover{border-color:var(--dsw-alias-brand-primary,#2f6fed);box-shadow:0 4px 12px rgba(47,111,237,.15);transform:translateY(-2px)}", + ".pa-card:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#2f6fed);outline-offset:2px}", + ".pa-card:hover .pa-go{color:var(--dsw-alias-brand-primary,#2f6fed);opacity:1}", + ".pa-go{opacity:.45;transition:color .15s,opacity .15s}", + ".pa-btn{transition:border-color .15s cubic-bezier(.16,1,.3,1),color .15s cubic-bezier(.16,1,.3,1),background .15s cubic-bezier(.16,1,.3,1)}", + ".pa-btn:hover:not(:disabled){border-color:var(--dsw-alias-brand-primary,#2f6fed);color:var(--dsw-alias-brand-primary,#2f6fed);background:rgba(47,111,237,.06)}", + ".pa-row{transition:background .15s}", + ".pa-row:hover{background:rgba(47,111,237,.06)}", + ".pa-modal{box-shadow:0 8px 30px rgba(0,0,0,.28);animation:paIn .18s cubic-bezier(.16,1,.3,1)}", + "@keyframes paIn{from{opacity:0;transform:translateY(6px) scale(.985)}to{opacity:1;transform:none}}", + "@media (prefers-reduced-motion: reduce){.pa-card,.pa-modal{animation:none;transition:none}.pa-card:hover{transform:none}}" ].join(""); document.head.appendChild(el); return function () { el.remove(); }; @@ -1079,25 +1093,32 @@ window.__ModuleLoader__.load({ // ── 管理项清单:每项点开都是「弹窗内管理」(用户 2026-09-13 要求) var ITEMS = [ - { id: "users", title: t("pa.usersTitle"), desc: t("pa.pending") + " " + nPending + " · " + t("pa.disabled") + " " + nDisabled, badge: userList.length }, - { id: "plugins", title: t("pa.pool"), desc: t("pa.poolCount"), badge: pool.length }, - { id: "runtime", title: t("pa.runtime"), desc: t("pa.items"), badge: rt.length }, - { id: "storage", title: t("pa.storage"), desc: t("pa.storageUsers"), badge: stUsers.length }, - { id: "instance", title: t("pa.inst"), desc: inst + (brk ? " · " + t("pa.breakerOpen") : ""), badge: s.status && s.status.instance ? s.status.instance.port : "—" }, + { id: "users", icon: "👥", title: t("pa.usersTitle"), desc: t("pa.pending") + " " + nPending + " · " + t("pa.disabled") + " " + nDisabled, badge: userList.length }, + { id: "plugins", icon: "🧩", title: t("pa.pool"), desc: t("pa.poolCount"), badge: pool.length }, + { id: "runtime", icon: "📦", title: t("pa.runtime"), desc: t("pa.items"), badge: rt.length }, + { id: "storage", icon: "💾", title: t("pa.storage"), desc: t("pa.storageUsers"), badge: stUsers.length }, + { id: "instance", icon: "🖥️", title: t("pa.inst"), desc: inst + (brk ? " · " + t("pa.breakerOpen") : ""), badge: s.status && s.status.instance ? s.status.instance.port : "—" }, ]; - function itemRow(it) { + // 卡片(06-工作台UI规范 §4.5 .data-card:r12 / 16px 18px / shadow / hover 上浮 + 蓝边 + 蓝影) + function itemCard(it) { return jsxRuntime.jsx("div", { - key: it.id, role: "button", tabIndex: 0, + key: it.id, role: "button", tabIndex: 0, className: "pa-card", onClick: function () { setNote(""); setModal(it.id); }, onKeyDown: function (e) { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setModal(it.id); } }, - style: { display: "flex", alignItems: "center", gap: "10px", padding: "10px 12px", border: "1px solid " + T.border, borderRadius: "10px", background: T.field, cursor: "pointer" }, + style: { + border: "1px solid " + T.border, borderRadius: "12px", background: T.field, + padding: "16px 18px", cursor: "pointer", display: "flex", flexDirection: "column", + gap: "6px", minHeight: "104px", boxShadow: "0 1px 3px rgba(0,0,0,.08)" + }, children: [ - jsxRuntime.jsx("div", { key: "t", style: { flex: "1 1 auto", minWidth: 0 }, children: [ - jsxRuntime.jsx("div", { key: "a", style: { fontSize: "14px", fontWeight: 500, color: T.text }, children: it.title }), - jsxRuntime.jsx("div", { key: "b", style: { fontSize: "12px", color: T.dim, marginTop: "2px" }, children: it.desc }) ] }), - jsxRuntime.jsx("div", { key: "n", style: { fontSize: "13px", color: T.sub, fontVariantNumeric: "tabular-nums" }, children: it.badge }), - jsxRuntime.jsx("div", { key: "c", style: { color: T.dim, fontSize: "14px" }, children: "›" }) + jsxRuntime.jsx("div", { key: "top", style: { display: "flex", alignItems: "center", gap: "8px" }, children: [ + jsxRuntime.jsx("span", { key: "i", style: { fontSize: "16px", lineHeight: 1 }, children: it.icon }), + jsxRuntime.jsx("span", { key: "t", style: { fontSize: "15px", fontWeight: 500, color: T.text }, children: it.title }), + jsxRuntime.jsx("span", { key: "g", className: "pa-go", style: { marginLeft: "auto", fontSize: "14px", color: T.dim }, children: "›" }) + ] }), + jsxRuntime.jsx("div", { key: "d", style: { fontSize: "13px", color: T.dim, lineHeight: 1.6 }, children: it.desc }), + jsxRuntime.jsx("div", { key: "n", style: { marginTop: "auto", fontSize: "17px", fontWeight: 500, color: T.text, textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: it.badge }) ] }); } @@ -1159,17 +1180,18 @@ window.__ModuleLoader__.load({ var rows = [ jsxRuntime.jsx("div", { key: "hd", style: { fontSize: "15px", fontWeight: 500, color: T.text }, children: t("pa.label") }), jsxRuntime.jsx("div", { key: "sub", style: { fontSize: "12px", color: T.dim }, children: t("pa.readonlyHint") }), - jsxRuntime.jsx("div", { key: "items", style: { display: "flex", flexDirection: "column", gap: "8px" }, children: ITEMS.map(itemRow) }), + jsxRuntime.jsx("div", { key: "items", style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(158px, 1fr))", gap: "12px" }, children: ITEMS.map(itemCard) }), ]; if (modal) { var it = ITEMS.filter(function (x) { return x.id === modal; })[0] || { title: modal }; rows.push(jsxRuntime.jsx("div", { key: "overlay", onClick: function () { setModal(null); }, - style: { position: "fixed", inset: 0, zIndex: 9999, background: "rgba(0,0,0,.4)", display: "flex", alignItems: "center", justifyContent: "center", padding: "24px" }, - children: jsxRuntime.jsx("div", { + style: { position: "fixed", inset: 0, zIndex: 9999, background: "rgba(0,0,0,.35)", display: "flex", alignItems: "center", justifyContent: "center", padding: "24px" }, + className: "pa-modal", + children: jsxRuntime.jsx("div", { onClick: function (e) { e.stopPropagation(); }, - style: { background: T.text === "" ? "#fff" : ("var(--dsw-alias-bg-layer-1, #ffffff)"), border: "1px solid " + T.border, borderRadius: "12px", width: "100%", maxWidth: "760px", maxHeight: "78vh", overflow: "auto", padding: "16px", boxShadow: "0 8px 32px rgba(0,0,0,.2)" }, + style: { background: T.text === "" ? "#fff" : ("var(--dsw-alias-bg-layer-1, #ffffff)"), border: "1px solid " + T.border, borderRadius: "14px", width: "520px", maxWidth: "92vw", maxHeight: "80vh", overflow: "auto", padding: "22px 26px" }, children: [ jsxRuntime.jsx("div", { key: "mh", style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "10px" }, children: [ jsxRuntime.jsx("div", { key: "t", style: { fontSize: "15px", fontWeight: 500, color: T.text }, children: it.title }), diff --git a/poc/business-plugins/package.json b/poc/business-plugins/package.json index 1f6e71a..86a8dc8 100644 --- a/poc/business-plugins/package.json +++ b/poc/business-plugins/package.json @@ -1,6 +1,6 @@ { "name": "@dsh-local/business-plugins", - "version": "0.3.0", + "version": "0.3.1", "description": "功能管理(原「功能插件」)section for dsh web profile — v0.2.8(2026-09-13):**所有弹窗改页内弹窗** —— 弃用 window.confirm,改为 fixed 遮罩 + 居中面板 + 点遮罩/✕ 关闭(视觉与交互对齐 MCN 工作台 dsh-plugin-mcn 的 modalTitle/modalText/modalBtns 三段结构);**超限时弹窗内红底警告块**(标题 + 说明 + 内存数字),确认按钮转危险色,未点确认不发请求。v0.2.7(档案 75 维度 B 落地 · 2026-09-13):卡片新增「预估内存 ≈ N MiB」徽章(按实测成本分色:≥60 红 / ≥30 黄)、卡片加高(minHeight 112 + padding 14/16)便于四层信息排布;**列表上方新增「内存预估」状态条** —— 实心段=当前已启用插件预估占用、半透明段=本次勾选增量、超单实例上限(384 MiB)整条转红并给文字警告,确认弹窗也带上内存预估。口径 = 空载基线 285 MiB + 逐插件实测加载成本(隔离 cgroup 的 rss 增量),**是预估值不是实时读数**。候选池列表 + 搜索/状态徽章 + 批量启用/禁用 + 确认弹窗 + 重启后自动刷新。v0.2.4(档案 67):对齐 06-工作台UI规范 —— **信息层次反转**(主视觉改为插件用途说明,插件名/版本退为副行小字;中文说明由候选池入库时优先取官方目录)、字号阶梯 14/13/12、徽章与按钮改规范量级、空态改「标题 + 说明」、新增列表行 hover 反馈。v0.2.2:分区名由「功能插件」改为「功能管理」。v0.2.0:配色改用官方 --dsw-* design token(跟随 dsh 主题);文案走官方 locale(zh/en)。", "type": "module", "main": "lib/index.js",