render buttons as neon tubes and rebuild the login page

The previous commit only swapped theme tokens, so buttons kept the solid
blue from arco.css: a-button fills with rgb(var(--primary-6)), which maps
to --arcoblue-6, not --color-primary. Bridge both naming families so no
Arco blue survives.

Style buttons as hollow tubes rather than filled blocks: transparent
fill, 1px cyan wall, inner glow plus two outer halos, and a glowing
label. Hover brightens the wall, active pinches the halo inward,
loading pulses, disabled cuts power entirely. Same treatment in red for
destructive actions, and hollow-line chips for inputs, tags, switches
and popups.

Rebuild LoginView to match the approved prototype: 32px masked grid,
scanline, IsometricWave, neon card edge, badge, probe status lamp, and
default-credential chips. Logic, API calls and lock/reset messaging are
unchanged.
This commit is contained in:
2026-10-19 13:47:12 +08:00
parent 282624f801
commit 336d08fc05
4 changed files with 755 additions and 69 deletions
+299 -2
View File
@@ -29,11 +29,39 @@ textarea {
// ─── Arco Design token bridge ──────────────────────────────────
// arco-theme.ts 不是运行时来源(没有 ConfigProvider),Arco 的实际外观由 arco.css
// 里的 --color-* 变量决定。这里把 CYBER 令牌翻译成 Arco 变量,让 a-select /
// a-input / a-tag / a-table / a-modal 等自有控件与项目配色对齐。
// 里的 CSS 变量决定。这里把 CYBER 令牌翻译成 Arco 变量。
//
// 关键:Arco 有两套命名。--primary-6 是 rgb 三元组,--color-primary 是颜色值。
// a-button / a-tag / a-switch 的底色走 rgb(var(--primary-6)),也就是
// --primary-6 → --arcoblue-6 这一族;只覆盖 --color-primary 不会改变按钮底色。
// 两套都必须覆盖,否则会残留 Arco 蓝(22,93,255)。
// 变量表见 node_modules/@arco-design/web-vue/dist/arco.css 的 :root 块。
html[arco-theme='dark'],
:root {
// Arco 的 rgb 三元组族 —— 实心控件(按钮底、开关滑块、进度条)的真正来源。
// 霓虹青 oklch(0.805 0.148 188) ≈ rgb(45,212,191),按亮度排 1→10。
--arcoblue-1: 12, 58, 56;
--arcoblue-2: 16, 84, 78;
--arcoblue-3: 22, 118, 108;
--arcoblue-4: 28, 148, 135;
--arcoblue-5: 34, 172, 156;
--arcoblue-6: 45, 212, 191;
--arcoblue-7: 70, 229, 209;
--arcoblue-8: 120, 239, 224;
--arcoblue-9: 172, 246, 238;
--arcoblue-10: 218, 250, 246;
--green-6: 47, 197, 138;
--green-5: 56, 184, 130;
--green-7: 38, 178, 122;
--orange-6: 226, 175, 32;
--orange-5: 214, 165, 34;
--orange-7: 236, 190, 44;
--red-6: 232, 78, 61;
--red-5: 222, 74, 58;
--red-7: 240, 96, 78;
// Arco 的颜色值族 —— 描边、文字、浅底
--color-primary-light-1: oklch(0.30 0.060 188);
--color-primary-light-2: oklch(0.39 0.075 188);
--color-primary-light-3: oklch(0.50 0.095 188);
@@ -121,6 +149,275 @@ body {
background-color: $border-color !important;
}
// ─── Neon tube buttons ─────────────────────────────────────────
// CYBER 的按钮是「霓虹灯管」而不是实心色块:底色透明 / 内部暗,只有 1px 青色管壁
// 与外发光。hover / active 时管壁增亮、光晕收紧,模拟通电。
// 这里直接覆盖 Arco 的按钮外观类,因为 a-button 的默认样式来自 arco.css,
// token 桥接改不到「实心 vs 镂空」这一层。
$neon: var(--accent-primary);
$neon-hv: var(--accent-hover);
// 镂空管壁 + 双层外发光(内紧外散)
@mixin neon-tube($glow: 0.32, $wall: 1px) {
color: $neon;
background: transparent;
border: $wall solid rgba(var(--accent-primary-rgb), 0.55);
box-shadow:
inset 0 0 12px rgba(var(--accent-primary-rgb), $glow * 0.35),
0 0 10px rgba(var(--accent-primary-rgb), $glow),
0 0 22px rgba(var(--accent-primary-rgb), $glow * 0.5);
text-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.45);
}
// 默认按钮(secondary / 默认态):不发光的幽灵按钮,只在 hover 时点亮管壁
.arco-btn-secondary,
.arco-btn-secondary.arco-btn-status-warning,
.arco-btn-outline,
.arco-btn-default {
color: $text-secondary;
background: transparent;
border: 1px solid $border-color;
box-shadow: none;
transition: color 0.16s ease, border-color 0.16s ease,
box-shadow 0.16s ease, background-color 0.16s ease;
&:not(.arco-btn-disabled):hover {
color: $neon;
border-color: rgba(var(--accent-primary-rgb), 0.55);
background: rgba(var(--accent-primary-rgb), 0.05);
box-shadow: 0 0 10px rgba(var(--accent-primary-rgb), 0.22);
text-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.35);
}
}
// 主按钮:霓虹管
.arco-btn-primary {
@include neon-tube(0.34);
font-weight: 600;
&:not(.arco-btn-disabled):hover {
@include neon-tube(0.52);
color: $neon-hv;
border-color: rgba(var(--accent-primary-rgb), 0.85);
}
&:not(.arco-btn-disabled):active {
// 按下时管壁收窄、光晕内收,像灯管被压住
box-shadow:
inset 0 0 16px rgba(var(--accent-primary-rgb), 0.22),
0 0 6px rgba(var(--accent-primary-rgb), 0.34);
transform: translateY(1px);
}
&:not(.arco-btn-disabled):focus-visible {
outline: none;
box-shadow:
inset 0 0 12px rgba(var(--accent-primary-rgb), 0.12),
0 0 0 3px rgba(var(--accent-primary-rgb), 0.16),
0 0 16px rgba(var(--accent-primary-rgb), 0.4);
}
}
// 危险操作:同构的霓虹管,颜色换成红
@mixin neon-tube-danger($glow: 0.28) {
color: $error;
background: transparent;
border: 1px solid rgba(var(--error-rgb), 0.5);
box-shadow:
inset 0 0 12px rgba(var(--error-rgb), $glow * 0.3),
0 0 10px rgba(var(--error-rgb), $glow);
text-shadow: 0 0 8px rgba(var(--error-rgb), 0.4);
}
.arco-btn-dangerous {
@include neon-tube-danger(0.26);
font-weight: 500;
&:not(.arco-btn-disabled):hover {
@include neon-tube-danger(0.44);
background: rgba(var(--error-rgb), 0.06);
}
}
.arco-btn-dangerous.arco-btn-secondary,
.arco-btn-dangerous.arco-btn-outline {
color: rgba(var(--error-rgb), 0.85);
border-color: rgba(var(--error-rgb), 0.38);
background: transparent;
box-shadow: none;
&:not(.arco-btn-disabled):hover {
@include neon-tube-danger(0.4);
}
}
// 文字 / 链接按钮:无管壁,只让文字带辉光
.arco-btn-text,
.arco-btn-link {
background: transparent;
border: 1px solid transparent;
box-shadow: none;
color: $neon;
text-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.3);
&:not(.arco-btn-disabled):hover {
color: $neon-hv;
background: rgba(var(--accent-primary-rgb), 0.07);
text-shadow: 0 0 12px rgba(var(--accent-primary-rgb), 0.55);
}
}
// 禁用态:灯管熄灭
.arco-btn-primary.arco-btn-disabled,
.arco-btn-secondary.arco-btn-disabled,
.arco-btn-outline.arco-btn-disabled,
.arco-btn-dangerous.arco-btn-disabled,
.arco-btn-text.arco-btn-disabled,
.arco-btn-link.arco-btn-disabled {
color: var(--text-faint);
background: transparent;
border-color: var(--border-light);
box-shadow: none;
text-shadow: none;
cursor: not-allowed;
}
// 加载态:保留管壁不熄灭,用脉冲表示"通电中"
@keyframes neon-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.62; }
}
.arco-btn-primary.arco-btn-loading {
@include neon-tube(0.4);
animation: neon-pulse 1.1s ease-in-out infinite;
}
// 尺寸统一:CYBER 的按钮偏小方硬
.arco-btn {
border-radius: $radius-sm;
font-family: $font-code;
letter-spacing: 0.02em;
transition: color 0.16s ease, border-color 0.16s ease,
box-shadow 0.16s ease, background-color 0.16s ease,
transform 0.08s ease;
}
// 兜底:任何未显式分类的实心底按钮(Arco 的 .arco-btn 默认无 type class 时)
// 也不能漏成白块或蓝块。
.arco-btn:not([class*='arco-btn-primary']):not([class*='arco-btn-secondary']):not([class*='arco-btn-outline']):not([class*='arco-btn-text']):not([class*='arco-btn-link']):not([class*='arco-btn-dangerous']) {
background: transparent;
color: $text-secondary;
border: 1px solid $border-color;
&:not(.arco-btn-disabled):hover {
color: $neon;
border-color: rgba(var(--accent-primary-rgb), 0.55);
}
}
// ─── Neon inputs / selects / tags ───────────────────────────────
// 输入区是「凹陷」的:底色比卡片更沉,聚焦时管壁点亮并带一圈内发光。
.arco-input-wrapper,
.arco-textarea-wrapper,
.arco-select-view,
.arco-picker,
.arco-input-tag {
background-color: $bg-input !important;
border-color: $border-color;
box-shadow: none;
transition: border-color 0.16s ease, box-shadow 0.16s ease;
&:hover {
border-color: rgba(var(--accent-primary-rgb), 0.4);
}
}
.arco-input-wrapper-focus,
.arco-textarea-wrapper-focus,
.arco-select-view-focus,
.arco-picker-focused,
.arco-input-tag-focus {
border-color: rgba(var(--accent-primary-rgb), 0.85);
box-shadow: 0 0 0 3px rgba(var(--accent-primary-rgb), 0.12),
inset 0 0 14px rgba(var(--accent-primary-rgb), 0.06);
}
.arco-input,
.arco-textarea,
.arco-select-view-single,
.arco-select-view-value {
color: $text-primary;
}
.arco-input::placeholder,
.arco-textarea::placeholder {
color: var(--text-faint);
}
// 标签:状态语义用发丝线底 + 彩色字,不用实心块
.arco-tag {
border-radius: 4px;
font-family: $font-code;
font-size: 11.5px;
background: transparent;
border: 1px solid currentColor;
}
// 开关 / 复选 / 单选的滑块用霓虹青
.arco-switch-checked {
background-color: rgba(var(--accent-primary-rgb), 0.22);
border-color: rgba(var(--accent-primary-rgb), 0.7);
box-shadow: 0 0 10px rgba(var(--accent-primary-rgb), 0.3);
}
.arco-switch-checked .arco-switch-slider {
background-color: var(--accent-primary);
box-shadow: 0 0 10px rgba(var(--accent-primary-rgb), 0.7);
}
.arco-checkbox-checked .arco-checkbox-inner {
background-color: var(--accent-primary);
border-color: var(--accent-primary);
box-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.5);
}
// 下拉 / 弹层的浮层背景
.arco-trigger-popup,
.arco-select-popup,
.arco-picker-dropdown,
.arco-dropdown,
.arco-modal,
.arco-drawer {
background-color: var(--surface-2);
border: 1px solid var(--border-color);
box-shadow: var(--shadow, 0 18px 48px oklch(0 0 0 / 0.55));
}
// 表格:去掉亮色分隔线的突兀感,表头沉下去
.arco-table-th {
background-color: var(--surface-2);
color: $text-muted;
border-color: $border-color;
font-family: $font-code;
font-weight: 600;
}
.arco-table-td {
border-color: var(--border-light);
}
.arco-table-tr:hover .arco-table-td {
background-color: rgba(var(--accent-primary-rgb), 0.04);
}
// 进度条 / 加载条
.arco-progress-line .arco-progress-line-bar,
.arco-slider-track-bar {
background-color: var(--accent-primary);
box-shadow: 0 0 8px rgba(var(--accent-primary-rgb), 0.5);
}
html, body {
position: fixed;
top: 0;