feat: session-cookie login/logout + three-tier roles (superadmin/admin/viewer) with read-only UI + remove pink theme

- cookie-based auth (/login /logout) replacing Basic Auth for UI, enabling logout
- roles: superadmin (account management only), admin (full except accounts), viewer/audit (read-only status+cluster, export logs)
- readonly accounts hide edit buttons (added remote node, group ops, canvas layout/save/import, cluster manage, install) instead of greying them
- auditors see status+cluster only; ordinary admins lose the accounts nav; last-admin guard covers superadmin
- remove pink theme entirely (switcher, [data-theme=pink], leftover localStorage), keep white/blue
This commit is contained in:
2026-08-20 09:08:07 +08:00
parent b39bd427fa
commit f29ec81e4a
27 changed files with 1195 additions and 724 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,257 +1,257 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500" width="500" height="500" shape-rendering="crispEdges">
<defs>
<!-- 主字母像素块(黑色) -->
<rect id="p" width="12" height="12" fill="#000000" />
<!-- frpc 小像素块(蓝色) -->
<rect id="q" width="5" height="5" fill="#2563eb" />
<!-- 装饰小方块(浅灰) -->
<rect id="p" width="14" height="14" fill="#000000" />
<rect id="q" width="7" height="7" fill="#2563eb" />
<rect id="d" width="8" height="8" fill="#94a3b8" />
<!-- 小十字星装饰 -->
<rect id="s" width="6" height="6" fill="#94a3b8" />
</defs>
<!-- 圆角白色背景(模拟 App 图标外框) -->
<!-- 圆角白色背景 -->
<rect width="500" height="500" rx="40" fill="#ffffff" stroke="#e2e8f0" stroke-width="4" />
<!-- ========== 主字母整体居中(横向间距更合理) ========== -->
<g transform="translate(70, 160)">
<!-- ===== W基于原始结构高度约 150px ===== -->
<!-- ========== 主字母 WUI ========== -->
<g transform="translate(70, 100)">
<!-- W -->
<g transform="translate(0, 0)">
<!-- 左竖线占2列 -->
<use href="#p" x="0" y="0" />
<use href="#p" x="12" y="0" />
<use href="#p" x="0" y="12" />
<use href="#p" x="12" y="12" />
<use href="#p" x="0" y="24" />
<use href="#p" x="12" y="24" />
<use href="#p" x="0" y="36" />
<use href="#p" x="12" y="36" />
<use href="#p" x="0" y="48" />
<use href="#p" x="12" y="48" />
<use href="#p" x="0" y="60" />
<use href="#p" x="12" y="60" />
<use href="#p" x="0" y="72" />
<use href="#p" x="12" y="72" />
<use href="#p" x="14" y="0" />
<use href="#p" x="0" y="14" />
<use href="#p" x="14" y="14" />
<use href="#p" x="0" y="28" />
<use href="#p" x="14" y="28" />
<use href="#p" x="0" y="42" />
<use href="#p" x="14" y="42" />
<use href="#p" x="0" y="56" />
<use href="#p" x="14" y="56" />
<use href="#p" x="0" y="70" />
<use href="#p" x="14" y="70" />
<use href="#p" x="0" y="84" />
<use href="#p" x="12" y="84" />
<use href="#p" x="0" y="96" />
<use href="#p" x="12" y="96" />
<use href="#p" x="0" y="108" />
<use href="#p" x="12" y="108" />
<use href="#p" x="0" y="120" />
<use href="#p" x="12" y="120" />
<use href="#p" x="0" y="132" />
<use href="#p" x="12" y="132" />
<!-- 右竖线占2列 -->
<use href="#p" x="84" y="0" />
<use href="#p" x="96" y="0" />
<use href="#p" x="84" y="12" />
<use href="#p" x="96" y="12" />
<use href="#p" x="84" y="24" />
<use href="#p" x="96" y="24" />
<use href="#p" x="84" y="36" />
<use href="#p" x="96" y="36" />
<use href="#p" x="84" y="48" />
<use href="#p" x="96" y="48" />
<use href="#p" x="84" y="60" />
<use href="#p" x="96" y="60" />
<use href="#p" x="84" y="72" />
<use href="#p" x="96" y="72" />
<use href="#p" x="14" y="84" />
<use href="#p" x="0" y="98" />
<use href="#p" x="14" y="98" />
<use href="#p" x="0" y="112" />
<use href="#p" x="14" y="112" />
<use href="#p" x="0" y="126" />
<use href="#p" x="14" y="126" />
<use href="#p" x="0" y="140" />
<use href="#p" x="14" y="140" />
<use href="#p" x="0" y="154" />
<use href="#p" x="14" y="154" />
<use href="#p" x="0" y="168" />
<use href="#p" x="14" y="168" />
<use href="#p" x="98" y="0" />
<use href="#p" x="112" y="0" />
<use href="#p" x="98" y="14" />
<use href="#p" x="112" y="14" />
<use href="#p" x="98" y="28" />
<use href="#p" x="112" y="28" />
<use href="#p" x="98" y="42" />
<use href="#p" x="112" y="42" />
<use href="#p" x="98" y="56" />
<use href="#p" x="112" y="56" />
<use href="#p" x="98" y="70" />
<use href="#p" x="112" y="70" />
<use href="#p" x="98" y="84" />
<use href="#p" x="112" y="84" />
<use href="#p" x="98" y="98" />
<use href="#p" x="112" y="98" />
<use href="#p" x="98" y="112" />
<use href="#p" x="112" y="112" />
<use href="#p" x="98" y="126" />
<use href="#p" x="112" y="126" />
<use href="#p" x="98" y="140" />
<use href="#p" x="112" y="140" />
<use href="#p" x="98" y="154" />
<use href="#p" x="112" y="154" />
<use href="#p" x="98" y="168" />
<use href="#p" x="112" y="168" />
<use href="#p" x="28" y="70" />
<use href="#p" x="56" y="70" />
<use href="#p" x="84" y="70" />
<use href="#p" x="28" y="84" />
<use href="#p" x="56" y="84" />
<use href="#p" x="84" y="84" />
<use href="#p" x="96" y="84" />
<use href="#p" x="84" y="96" />
<use href="#p" x="96" y="96" />
<use href="#p" x="84" y="108" />
<use href="#p" x="96" y="108" />
<use href="#p" x="84" y="120" />
<use href="#p" x="96" y="120" />
<use href="#p" x="84" y="132" />
<use href="#p" x="96" y="132" />
<!-- 中间 V 形(从 y=60 开始) -->
<use href="#p" x="24" y="60" />
<use href="#p" x="48" y="60" />
<use href="#p" x="72" y="60" />
<use href="#p" x="24" y="72" />
<use href="#p" x="48" y="72" />
<use href="#p" x="72" y="72" />
<use href="#p" x="24" y="84" />
<use href="#p" x="48" y="84" />
<use href="#p" x="72" y="84" />
<use href="#p" x="24" y="96" />
<use href="#p" x="48" y="96" />
<use href="#p" x="72" y="96" />
<!-- 底部汇合 -->
<use href="#p" x="36" y="108" />
<use href="#p" x="60" y="108" />
<use href="#p" x="36" y="120" />
<use href="#p" x="60" y="120" />
<use href="#p" x="36" y="132" />
<use href="#p" x="60" y="132" />
<use href="#p" x="48" y="132" />
<use href="#p" x="28" y="98" />
<use href="#p" x="56" y="98" />
<use href="#p" x="84" y="98" />
<use href="#p" x="28" y="112" />
<use href="#p" x="56" y="112" />
<use href="#p" x="84" y="112" />
<use href="#p" x="42" y="126" />
<use href="#p" x="70" y="126" />
<use href="#p" x="42" y="140" />
<use href="#p" x="70" y="140" />
<use href="#p" x="42" y="154" />
<use href="#p" x="70" y="154" />
<use href="#p" x="56" y="154" />
<use href="#p" x="56" y="168" />
</g>
<!-- ===== U高度与 W 一致,内部空间增大) ===== -->
<g transform="translate(124, 0)">
<!-- 左竖线占2列 -->
<!-- U -->
<g transform="translate(144, 0)">
<use href="#p" x="0" y="0" />
<use href="#p" x="12" y="0" />
<use href="#p" x="0" y="12" />
<use href="#p" x="12" y="12" />
<use href="#p" x="0" y="24" />
<use href="#p" x="12" y="24" />
<use href="#p" x="0" y="36" />
<use href="#p" x="12" y="36" />
<use href="#p" x="0" y="48" />
<use href="#p" x="12" y="48" />
<use href="#p" x="0" y="60" />
<use href="#p" x="12" y="60" />
<use href="#p" x="0" y="72" />
<use href="#p" x="12" y="72" />
<use href="#p" x="14" y="0" />
<use href="#p" x="0" y="14" />
<use href="#p" x="14" y="14" />
<use href="#p" x="0" y="28" />
<use href="#p" x="14" y="28" />
<use href="#p" x="0" y="42" />
<use href="#p" x="14" y="42" />
<use href="#p" x="0" y="56" />
<use href="#p" x="14" y="56" />
<use href="#p" x="0" y="70" />
<use href="#p" x="14" y="70" />
<use href="#p" x="0" y="84" />
<use href="#p" x="12" y="84" />
<use href="#p" x="0" y="96" />
<use href="#p" x="12" y="96" />
<use href="#p" x="0" y="108" />
<use href="#p" x="12" y="108" />
<use href="#p" x="0" y="120" />
<use href="#p" x="12" y="120" />
<use href="#p" x="0" y="132" />
<use href="#p" x="12" y="132" />
<use href="#p" x="14" y="84" />
<use href="#p" x="0" y="98" />
<use href="#p" x="14" y="98" />
<use href="#p" x="0" y="112" />
<use href="#p" x="14" y="112" />
<use href="#p" x="0" y="126" />
<use href="#p" x="14" y="126" />
<use href="#p" x="0" y="140" />
<use href="#p" x="14" y="140" />
<use href="#p" x="0" y="154" />
<use href="#p" x="14" y="154" />
<use href="#p" x="0" y="168" />
<use href="#p" x="14" y="168" />
<use href="#p" x="98" y="0" />
<use href="#p" x="112" y="0" />
<use href="#p" x="98" y="14" />
<use href="#p" x="112" y="14" />
<use href="#p" x="98" y="28" />
<use href="#p" x="112" y="28" />
<use href="#p" x="98" y="42" />
<use href="#p" x="112" y="42" />
<use href="#p" x="98" y="56" />
<use href="#p" x="112" y="56" />
<use href="#p" x="98" y="70" />
<use href="#p" x="112" y="70" />
<use href="#p" x="98" y="84" />
<use href="#p" x="112" y="84" />
<use href="#p" x="98" y="98" />
<use href="#p" x="112" y="98" />
<use href="#p" x="98" y="112" />
<use href="#p" x="112" y="112" />
<use href="#p" x="98" y="126" />
<use href="#p" x="112" y="126" />
<use href="#p" x="98" y="140" />
<use href="#p" x="112" y="140" />
<use href="#p" x="98" y="154" />
<use href="#p" x="112" y="154" />
<use href="#p" x="98" y="168" />
<use href="#p" x="112" y="168" />
<use href="#p" x="0" y="168" />
<use href="#p" x="14" y="168" />
<use href="#p" x="28" y="168" />
<use href="#p" x="42" y="168" />
<use href="#p" x="56" y="168" />
<use href="#p" x="70" y="168" />
<use href="#p" x="84" y="168" />
<use href="#p" x="98" y="168" />
<use href="#p" x="112" y="168" />
<!-- 右竖线占2列 -->
<use href="#p" x="84" y="0" />
<use href="#p" x="96" y="0" />
<use href="#p" x="84" y="12" />
<use href="#p" x="96" y="12" />
<use href="#p" x="84" y="24" />
<use href="#p" x="96" y="24" />
<use href="#p" x="84" y="36" />
<use href="#p" x="96" y="36" />
<use href="#p" x="84" y="48" />
<use href="#p" x="96" y="48" />
<use href="#p" x="84" y="60" />
<use href="#p" x="96" y="60" />
<use href="#p" x="84" y="72" />
<use href="#p" x="96" y="72" />
<use href="#p" x="84" y="84" />
<use href="#p" x="96" y="84" />
<use href="#p" x="84" y="96" />
<use href="#p" x="96" y="96" />
<use href="#p" x="84" y="108" />
<use href="#p" x="96" y="108" />
<use href="#p" x="84" y="120" />
<use href="#p" x="96" y="120" />
<use href="#p" x="84" y="132" />
<use href="#p" x="96" y="132" />
<!-- ===== frpc修正版f 有完整竖线) ===== -->
<g transform="translate(49, 20)">
<!--
每个字母高度约 28px4行×7px
间距:字母之间空 14px2行×7px
f: y=0-27竖线4行
r: y=41-62
p: y=76-97
c: y=111-132
-->
<!-- 底部横线 -->
<use href="#p" x="0" y="132" />
<use href="#p" x="12" y="132" />
<use href="#p" x="24" y="132" />
<use href="#p" x="36" y="132" />
<use href="#p" x="48" y="132" />
<use href="#p" x="60" y="132" />
<use href="#p" x="72" y="132" />
<use href="#p" x="84" y="132" />
<use href="#p" x="96" y="132" />
<!-- ===== U 内部:竖向排列的 frpc蓝色5×5 像素) ===== -->
<g transform="translate(32, 18)">
<!-- f -->
<!-- ===== f竖线完整4行+ 顶横 + 中横 ===== -->
<!-- 竖线左侧从顶到底连续4行 -->
<use href="#q" x="0" y="0" />
<use href="#q" x="0" y="6" />
<use href="#q" x="0" y="12" />
<use href="#q" x="0" y="18" />
<use href="#q" x="6" y="0" />
<use href="#q" x="12" y="0" />
<use href="#q" x="18" y="0" />
<use href="#q" x="6" y="12" />
<use href="#q" x="12" y="12" />
<use href="#q" x="0" y="7" />
<use href="#q" x="0" y="14" />
<use href="#q" x="0" y="21" />
<!-- 顶横(向右延伸) -->
<use href="#q" x="7" y="0" />
<use href="#q" x="14" y="0" />
<!-- 中横(向右延伸) -->
<use href="#q" x="7" y="14" />
<use href="#q" x="14" y="14" />
<!-- r -->
<use href="#q" x="0" y="28" />
<use href="#q" x="0" y="34" />
<use href="#q" x="0" y="40" />
<use href="#q" x="0" y="46" />
<use href="#q" x="6" y="28" />
<use href="#q" x="12" y="28" />
<use href="#q" x="18" y="28" />
<use href="#q" x="6" y="40" />
<use href="#q" x="12" y="40" />
<!-- ===== r竖线 + 顶横(一竖一横) ===== -->
<!-- 竖线左侧3行 -->
<use href="#q" x="0" y="41" />
<use href="#q" x="0" y="48" />
<use href="#q" x="0" y="55" />
<!-- 顶横(向右延伸) -->
<use href="#q" x="7" y="41" />
<use href="#q" x="14" y="41" />
<!-- p -->
<use href="#q" x="0" y="56" />
<use href="#q" x="0" y="62" />
<use href="#q" x="0" y="68" />
<use href="#q" x="0" y="74" />
<use href="#q" x="0" y="80" />
<use href="#q" x="6" y="56" />
<use href="#q" x="12" y="56" />
<use href="#q" x="18" y="56" />
<use href="#q" x="18" y="62" />
<use href="#q" x="18" y="68" />
<use href="#q" x="6" y="74" />
<use href="#q" x="12" y="74" />
<use href="#q" x="18" y="74" />
<!-- ===== p竖线向下伸出+ 右侧圆圈 ===== -->
<!-- 竖线左侧向下伸出5行 -->
<use href="#q" x="0" y="76" />
<use href="#q" x="0" y="83" />
<use href="#q" x="0" y="90" />
<use href="#q" x="0" y="97" />
<!-- 圆圈右侧3×3闭合 -->
<use href="#q" x="7" y="76" />
<use href="#q" x="14" y="76" />
<use href="#q" x="14" y="83" />
<use href="#q" x="14" y="90" />
<use href="#q" x="7" y="90" />
<use href="#q" x="14" y="90" />
<!-- c -->
<use href="#q" x="6" y="90" />
<use href="#q" x="12" y="90" />
<use href="#q" x="18" y="90" />
<use href="#q" x="0" y="96" />
<use href="#q" x="0" y="102" />
<use href="#q" x="6" y="108" />
<use href="#q" x="12" y="108" />
<use href="#q" x="18" y="108" />
<!-- ===== c开口朝右的弧形左侧半圆 ===== -->
<!-- 左竖 -->
<use href="#q" x="0" y="111" />
<use href="#q" x="0" y="118" />
<use href="#q" x="0" y="125" />
<!-- 上弧 -->
<use href="#q" x="7" y="111" />
<use href="#q" x="14" y="111" />
<!-- 下弧 -->
<use href="#q" x="7" y="125" />
<use href="#q" x="14" y="125" />
</g>
</g>
<!-- ===== I中间竖线 2 列宽,高度一致) ===== -->
<g transform="translate(248, 0)">
<!-- 顶部横线占6列 -->
<!-- I -->
<g transform="translate(288, 0)">
<use href="#p" x="0" y="0" />
<use href="#p" x="12" y="0" />
<use href="#p" x="24" y="0" />
<use href="#p" x="36" y="0" />
<use href="#p" x="48" y="0" />
<use href="#p" x="60" y="0" />
<!-- 中间竖线2 列宽) -->
<use href="#p" x="24" y="12" />
<use href="#p" x="36" y="12" />
<use href="#p" x="24" y="24" />
<use href="#p" x="36" y="24" />
<use href="#p" x="24" y="36" />
<use href="#p" x="36" y="36" />
<use href="#p" x="24" y="48" />
<use href="#p" x="36" y="48" />
<use href="#p" x="24" y="60" />
<use href="#p" x="36" y="60" />
<use href="#p" x="24" y="72" />
<use href="#p" x="36" y="72" />
<use href="#p" x="24" y="84" />
<use href="#p" x="36" y="84" />
<use href="#p" x="24" y="96" />
<use href="#p" x="36" y="96" />
<use href="#p" x="24" y="108" />
<use href="#p" x="36" y="108" />
<use href="#p" x="24" y="120" />
<use href="#p" x="36" y="120" />
<!-- 底部横线占6列 -->
<use href="#p" x="0" y="132" />
<use href="#p" x="12" y="132" />
<use href="#p" x="24" y="132" />
<use href="#p" x="36" y="132" />
<use href="#p" x="48" y="132" />
<use href="#p" x="60" y="132" />
<use href="#p" x="14" y="0" />
<use href="#p" x="28" y="0" />
<use href="#p" x="42" y="0" />
<use href="#p" x="56" y="0" />
<use href="#p" x="70" y="0" />
<use href="#p" x="28" y="14" />
<use href="#p" x="42" y="14" />
<use href="#p" x="28" y="28" />
<use href="#p" x="42" y="28" />
<use href="#p" x="28" y="42" />
<use href="#p" x="42" y="42" />
<use href="#p" x="28" y="56" />
<use href="#p" x="42" y="56" />
<use href="#p" x="28" y="70" />
<use href="#p" x="42" y="70" />
<use href="#p" x="28" y="84" />
<use href="#p" x="42" y="84" />
<use href="#p" x="28" y="98" />
<use href="#p" x="42" y="98" />
<use href="#p" x="28" y="112" />
<use href="#p" x="42" y="112" />
<use href="#p" x="28" y="126" />
<use href="#p" x="42" y="126" />
<use href="#p" x="28" y="140" />
<use href="#p" x="42" y="140" />
<use href="#p" x="28" y="154" />
<use href="#p" x="42" y="154" />
<use href="#p" x="0" y="168" />
<use href="#p" x="14" y="168" />
<use href="#p" x="28" y="168" />
<use href="#p" x="42" y="168" />
<use href="#p" x="56" y="168" />
<use href="#p" x="70" y="168" />
</g>
</g>
<!-- ========== 外围装饰元素(像素风,增加层次) ========== -->
<!-- 左上角小十字星 -->
<!-- ========== 外围装饰 ========== -->
<g transform="translate(40, 40)">
<use href="#s" x="0" y="0" />
<use href="#s" x="0" y="12" />
@ -259,11 +259,8 @@
<use href="#s" x="12" y="0" />
<use href="#s" x="12" y="12" />
</g>
<!-- 右上角小方块 -->
<use href="#d" x="440" y="40" />
<!-- 左下角小方块 -->
<use href="#d" x="40" y="440" />
<!-- 右下角小十字星 -->
<g transform="translate(436, 436)">
<use href="#s" x="0" y="0" />
<use href="#s" x="0" y="12" />
@ -272,12 +269,13 @@
<use href="#s" x="12" y="12" />
</g>
<!-- 三个随机黑色装饰点更大一点12×12 -->
<rect x="90" y="380" width="12" height="12" fill="#000000" />
<rect x="420" y="140" width="12" height="12" fill="#000000" />
<rect x="240" y="60" width="12" height="12" fill="#000000" />
<!-- 黑色装饰点 -->
<rect x="90" y="380" width="14" height="14" fill="#000000" />
<rect x="420" y="140" width="14" height="14" fill="#000000" />
<rect x="230" y="50" width="14" height="14" fill="#000000" />
<!-- 额外小点缀:蓝色小点,呼应 frpc 颜色 -->
<rect x="180" y="400" width="6" height="6" fill="#2563eb" />
<rect x="370" y="80" width="6" height="6" fill="#2563eb" />
<!-- 蓝色小点缀 -->
<rect x="180" y="400" width="8" height="8" fill="#2563eb" />
<rect x="370" y="80" width="8" height="8" fill="#2563eb" />
<rect x="50" y="250" width="8" height="8" fill="#2563eb" />
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<title>webui4frpc</title>
<script type="module" crossorigin src="/assets/index-C5WLVFP2.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CL42Ur3_.css">
<script type="module" crossorigin src="/assets/index-CbqC9m-j.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-RFHYrCiX.css">
</head>
<body>
<div id="app"></div>