# Verdaccio 缓存可视化管理面板 — 设计规范(编码阶段参考) > 文档依据: > 1. `doc/需求文档.md`(完整版:第一部分 功能需求 + 第二部分 前端界面设计) > 2. `doc/bright/`(浅色设计稿:design-mockup-v2.html + 7 张效果图) > 3. `doc/dark/`(暗色设计稿:design-mockup-v2-dark.html + 7 张效果图) > 4. 手机版竖屏效果基准:`bright/design-v2-mobile.png`、`dark/design-v2-dark-mobile.png` > > 编码方式:**一套代码 + CSS 变量双主题**(bright=浅色默认 / dark=暗色),**三端适配(电脑 ≥1024px / 平板 768~1023px / 手机 <768px)**,手机端效果以 dark/、bright/ 目录的 mobile 效果图为基准。 --- ## 1. 设计 Token(bright / dark 双主题) ### 1.1 多巴胺色板 | Token | bright(浅色) | dark(暗色) | 用途 | | --- | --- | --- | --- | | `--green` | `#32CD32` | `#3DDB4D` | 正常状态标签、选中态标签 | | `--green-soft` | `#E9F9E9` | `rgba(61,219,77,.14)` | 绿色标签底色 | | `--orange` | `#FF8C00` | `#FFA033` | 清理按钮、Logo、搜索按钮 | | `--orange-soft` | `#FFF3E2` | `rgba(255,160,51,.14)` | 橙色标签/数字底色 | | `--red` | `#FF4500` | `#FF5630` | 预警标签、删除按钮、预警数量 | | `--red-soft` | `#FFE9E2` | `rgba(255,86,48,.15)` | 红色标签/危险按钮底色 | | `--blue` | `#1E90FF` | `#45A2FF` | 忽略类标签、信息类 | | `--blue-soft` | `#E6F2FF` | `rgba(69,162,255,.15)` | 蓝色标签底色 | ### 1.2 中性色 / 背景 | Token | bright | dark | 用途 | | --- | --- | --- | --- | | `--ink` | `#2B2B33` | `#F1E8DE` | 主文字 | | `--ink-dim` | `#8A8A94` | `#A79E91` | 次级文字 | | `--ink-faint` | `#B9B9C2` | `#6E655A` | 弱化文字/提示 | | `--line` | `#F1E7DA` | `#3A2F25` | 边框、分隔线 | | `--card` | `#FFFFFF` | `#221B14` | 卡片/面板底色 | | `--card-2` | `#FFFFFF` | `#2A211A` | 次级面板(抽屉内用户卡等) | | `--bg` | `#FFF8EF` | `#16110C` | 页面底色(暖白 / 暖黑) | | `--bg-deep` | `#FFFDF9` | `#100C08` | 深一档背景(画板容器) | ### 1.3 字体 | Token | 值 | 用途 | | --- | --- | --- | | `--num` | `'Fredoka','PingFang SC',sans-serif` | 数字/统计值/徽章/表格数字 | | `--sans` | `'PingFang SC','Hiragino Sans GB','Microsoft YaHei',sans-serif` | 正文 | | `--display` | `'ZCOOL QingKe HuangYou','PingFang SC',sans-serif` | 展示性标题 | 字号梯度:30(页面大标题)/ 16.5(品牌名)/ 14–15(卡片标题)/ 13.5(导航)/ 12–12.5(次要)/ 11–11.5(弱化)。 ### 1.4 圆角 / 阴影 / 渐变 | Token | 值 | 用途 | | --- | --- | --- | | `--r-lg` | `22px` | 大卡片 | | `--r-md` | `16px` | 中小卡片/输入框 | | pill | `99px` | 按钮、标签、搜索框、导航项 | | `--shadow` | bright:`0 10px 30px -12px rgba(180,120,60,.18), 0 2px 8px -2px rgba(180,120,60,.08)` / dark:`0 12px 32px -14px rgba(0,0,0,.6), 0 2px 8px -2px rgba(0,0,0,.4)` | 卡片常态 | | `--shadow-hover` | bright:`0 18px 44px -14px rgba(180,120,60,.30), 0 4px 14px -4px rgba(180,120,60,.12)` / dark:`0 20px 46px -16px rgba(0,0,0,.75), 0 4px 14px -4px rgba(0,0,0,.5)` | hover 上浮 | 渐变常量(两版一致):主按钮 `linear-gradient(120deg,#FFB347,#FF8C00)`;预警按钮 bright `#FF5E1A→#FF8C00`、dark `#FF5630→#FF8C00`;头像 `#7CC6FF→#1E90FF`(dark `#5FA8E8→#2B74B9`)。 --- ## 2. 双主题实现方案 ```css :root { /* bright 浅色 token(默认) */ } html[data-theme="dark"] { /* 覆盖 dark token + 氛围背景 */ } ``` - 切换入口:顶栏右侧 pill 按钮(bright 显示「🌙 切到暗色」,dark 显示「☀️ 切到亮色」);移动端并入设置抽屉「🌙 主题切换」项 - 记忆:`localStorage` 键 `vcm-theme`,加载时读取 - 注意:dark 下需同步覆盖 `.ambient` 氛围渐变、点阵背景、搜索框聚焦光圈、呼吸光晕强度等硬编码色(对照 bright/dark 两版 HTML) --- ## 3. 功能需求要点(编码约束,来自第一部分) ### 3.1 包列表与状态 - 字段:包名 / 版本数 / 占用空间 / 状态(正常·预警·已忽略)/ 操作(清理、忽略、取消忽略) - 状态规则:正常 = 版本数 ≤ 阈值;预警 = 版本数 > 阈值 且未被忽略;已忽略 = 用户手动标记 - 排序:预警置顶 → 正常居中 → 已忽略垫底;同状态按版本数降序 ### 3.2 检索 - 输入框实时过滤(防抖 300ms),一键清空;匹配:不区分大小写子串,仅匹配包名(界面文档扩展为包名/版本号/文件大小,编码以扩展版为准) - 反馈:实时更新 + 「共找到 X 个包」;清空恢复完整列表 ### 3.3 阈值配置 - **版本数阈值:取值范围 1~100,默认 15**(功能需求为准;界面设计稿示例为 50,编码以 15 为默认并可在 UI 调整) - 持久化:保存到 SQLite `settings` 表,重启不丢失,加载时读取;修改后列表状态立即重算 - 界面扩展配置项(设计稿已实现):单包大小阈值(默认 500MB)、单包例外(覆盖全局)、恢复默认、保存生效提示 ### 3.4 预警清理 - 超阈值包:预警标签、自动置顶、清理按钮可用 - 清理确认弹窗:包名、当前版本数、保留版本数输入(默认=阈值)、将删除版本列表(Tag)、将删除数量、取消、确认清理(loading) - 清理原子逻辑:读 package.json → 按 semver 排序保留最新 N 个 → 删低版本 versions/time 记录 → 修正 dist-tags(如 latest 指向已删版本)→ 写回元数据 → 物理删 .tgz → 记日志 → 返回「删除数量、释放空间」 - 反馈:成功「已清理 X 个版本,释放 Y MB」;失败展示错误、不修改任何文件 ### 3.5 忽略标记 - 标记/取消忽略立即持久化到 `ignored_packages` 表;取消后若仍超阈值自动回预警 ### 3.6 操作日志 - 每次清理自动记录:包名、删除版本列表、删除数量、释放空间、操作时间(UTC) - 按时间倒序展示最近 50 条,支持查看详情 ### 3.7 非功能要求 - 性能:500 包加载 <2s、检索 <200ms、单包清理 <5s - 可靠:清理原子性、元数据损坏标记「异常」不影响其他包、崩溃无脏数据 - 安全:非 root(UID 10000)、storage 只读挂载、仅改目标包文件 --- ## 4. 数据模型与 API(编码依据) ### 4.1 SQLite ```sql CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT); -- version_threshold 默认 '15' CREATE TABLE ignored_packages (pkg_name TEXT PRIMARY KEY, ignored_at DATETIME DEFAULT CURRENT_TIMESTAMP); CREATE TABLE logs (id INTEGER PRIMARY KEY AUTOINCREMENT, pkg_name TEXT, deleted_versions TEXT, deleted_count INTEGER, freed_space TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP); ``` ### 4.2 REST API | 方法 | 路径 | 说明 | | --- | --- | --- | | GET/POST | `/api/threshold` | 获取/设置阈值 | | GET | `/api/ignored` | 获取已忽略包名 | | POST | `/api/ignore` | 标记忽略 | | DELETE | `/api/ignore/:pkgName` | 取消忽略 | | GET | `/api/packages?keyword=` | 扫描包列表(模糊检索) | | POST | `/api/clean` | 执行清理 | | GET | `/api/logs` | 最近 50 条日志 | --- ## 5. 页面清单(画板 → 页面) | # | 页面/视图 | 关键内容 | 路由建议 | | --- | --- | --- | --- | | 1 | 缓存概览 | 4 核心统计卡 + 5 辅助指标、预警横幅卡、Top 30 访问排行、包卡片列表 | `/` | | 2 | 全局检索 | 48px 大圆角搜索框、快捷筛选 pill、无边框结果表格 | `/search` | | 3 | 阈值配置 | 全局阈值卡×2(版本数/大小,−/+ 步进器、恢复默认、保存)、单包例外表格、行内添加例外表单 | `/thresholds` | | 4 | 包详情抽屉 | 600px 右侧滑出,包信息 + 版本列表(单版本删除、清理全部、忽略) | 覆盖层 | | 5 | 忽略列表 | 已忽略包表格 + 移出忽略(二次确认) | `/ignored` | | 6 | 最近动态 | 时间倒序操作日志表格,删除数量/释放空间 chip | `/logs` | | 7 | 移动端竖版 | 底部 4 Tab(概览/检索/阈值/动态)、2×2 统计、单列包卡、设置抽屉;效果图:`bright/design-v2-mobile.png`、`dark/design-v2-dark-mobile.png` | 响应式实现 | | 8 | 登录页 | 渐变背景 + 居中卡片 420px、emoji 输入框、渐变登录按钮、记住我/忘记密码;效果图 FRAME 08:`bright/design-v2-login.png`、`dark/design-v2-dark-login.png`(按需求文档 14 节) | `/login` | --- ## 6. 组件清单(来自设计稿) | 组件 | 要点 | | --- | --- | | 顶栏 Topbar | 64px;Logo 渐变块 + 品牌名 + 副标题;中部 pill 导航(active 橙色渐变);右侧主题切换按钮 + 圆形头像 | | 统计卡 Stat1 | 4 个:图标 + Fredoka 数字 + 标签;四色 tone;预警数量卡红色呼吸光晕 | | 辅助指标 Stat2 | 5 个轻量小卡(访问排行/今日下载/最大包/最老包/版本数分布) | | 预警卡 Alert | 红色渐变边框 + 呼吸光晕 + 立即清理按钮 | | 清理卡 Clean | 橙色渐变 + 可清理空间 + 立即清理按钮 | | Top30 排行 | 表格:金银铜徽章、包名(scoped 省略+tooltip)、访问次数、热度进度条 | | 包卡片 | 图标、包名、版本数/占用/最近更新、状态标签、清理/忽略按钮;warn 卡呼吸光晕 | | 搜索框 | 48px 高、大圆角、放大镜 + 快捷键提示;focus 橙色光圈 | | Pill 筛选 | 状态过滤 + 排序切换,选中态绿色 | | 结果表格 | 无边框、hover 行高亮、状态标签、删除操作 | | 阈值卡 | 全局阈值 + −/+ 步进器 + 恢复默认 + 保存按钮 + 生效提示条 | | 例外表格 | 包名/版本数阈值/大小阈值/命中状态/删除;行内添加例外表单 | | 抽屉 Drawer | 600px 右滑 + 遮罩;包详情版本列表、单版本删除、清理全部/忽略 | | 忽略表 | 已忽略包 + 取消忽略 | | 日志表 | 时间倒序;操作类型 + 版本数/释放空间 chip | | 移动端系列 | M-Topbar(☰)、M-Stats 2×2、M-Banner 预警横幅、M-Card 单列、M-Tabbar 底部 4 Tab、M-Drawer 设置抽屉(主题/阈值入口/版本信息/退出登录) | | 登录页 | 渐变背景、居中白卡 420px、emoji 输入框、渐变登录按钮、记住我/忘记密码 | --- ## 7. 响应式断点(三端,以需求文档为准) | 断点 | 尺寸 | 导航 | 统计卡 | 包列表 | 忽略列表 | 搜索框 | 包详情抽屉 | | --- | --- | --- | --- | --- | --- | --- | --- | | 桌面端 | ≥1024px | 顶部 pill 按钮 | 4 列 | 4 列卡片网格 | 3 列网格 | 居中 600px | 右侧 600px | | 平板端 | 768~1023px | 紧凑 pill | 2×2 | 2 列 | 2 列 | 100%(max 500px) | 右侧 50% | | 手机端 | <768px | 汉堡/☰ + 抽屉 | 单列 | 单列 | 单列 | 全宽 | 底部弹窗 85vh | > 差异标注:需求文档手机端导航为「汉堡菜单 + 左侧 280px 侧边抽屉」;设计稿 FRAME 07 为「右上角 ☰ + 右侧设置抽屉(主题/阈值/版本/退出)+ 底部 4 Tab 核心导航」。**编码以设计稿为准**(设置类进抽屉、页面切换走底部 Tab),汉堡抽屉用于承载非核心设置项。 --- ## 8. 动效规范 | 场景 | 动效 | | --- | --- | | 页面切换 | 平滑淡入 + 轻微上滑(300ms) | | 卡片悬停 | 上浮 2px + 阴影增强 + 边框强调 | | 按钮点击 | 缩放 0.95 + 回弹 | | 弹窗/抽屉 | 右侧滑入(0.35s cubic-bezier(.2,.8,.25,1))+ 遮罩淡入;移动端底部滑入 | | 预警呼吸 | 红色光晕呼吸动效(2.4~2.6s ease-in-out 循环) | | 清理成功 | 卡片缩小消失 + 成功 toast | --- ## 9. 文案风格(C 端对照) | 后台风 | C 端 | | --- | --- | | 缓存管理 | 你的缓存 | | 操作日志 | 最近动态 | | 忽略列表 | 已忽略的包 | | 阈值配置 | 预警设置 | | 执行清理 | 一键清理 | | 共 156 条记录 | 156 条动态 | --- ## 10. 技术选型与编码建议 - 后端:Node.js 18-slim + Express + better-sqlite3(单文件嵌入),Docker 单容器,storage 只读挂载、`manager-data` 读写挂载,非 root(UID 10000),端口 3000 - 前端:Vue 3 + Vite(pnpm 管理)+ **Element Plus 按需引入**;组件样式按 §1/§2 双主题 token **二次重写**为设计稿风格(覆盖 el-card/el-table/el-table-v2/el-drawer/el-tag/el-input-number/el-pagination 等的圆角、阴影、边框、hover 态与预警呼吸光晕) - 目录建议:`src/components/`(§6 组件逐一落地)、`src/views/`(§5 页面)、`src/styles/tokens.css`(双主题 token) - 图标:emoji(与设计稿一致,无外部图标库) - 数据:mock 先行跑通 UI,接口按 §4.2 对接 - 验收对照:需求文档 AC-1~8(包列表/检索/阈值/预警/清理/忽略/日志/原子性) --- ## 11. 已确认决策(编码按此执行) 1. **阈值默认值:15**(功能需求 1~100 为准,UI 可调) 2. **登录页:补效果图**(FRAME 08 已输出 bright/dark 两版,见 §5 #8) 3. **UI 库:Element Plus 按需引入**,组件样式按 §1/§2 token 重写覆盖为设计稿风格 --- ## 12. Verdaccio 缓存目录配置与部署(编码依据) ### 12.1 目录配置机制 - Verdaccio 侧:缓存目录由 `config.yaml` 的 `storage` 字段指定(Docker 镜像内默认 `/verdaccio/storage`) - 面板侧:**环境变量 `VERDACCIO_STORAGE` 优先** → 其次 UI「设置」中配置并持久化到 SQLite `settings` 表(key = `storage_dir`)→ 均无时进入**首次启动引导页**要求配置 - 校验:保存/启动时校验目录存在、可读、含 `package.json` / `.tgz`;无效时提示重新配置,面板不启动扫描 - 扫描逻辑:递归 `**/package.json` 解析 `versions`/`time`,匹配 `.tgz` 计算占用;支持 scoped 包(`@scope/name` 嵌套目录) ### 12.2 部署方式一:Docker(与 Verdaccio 同主机) ```yaml services: verdaccio: image: verdaccio/verdaccio volumes: ["./storage:/verdaccio/storage"] # Verdaccio 读写 verdaccio-manager: build: ./ # node:18-slim 约 180MB environment: [VERDACCIO_STORAGE=/verdaccio/storage, PORT=3000] volumes: - "./storage:/verdaccio/storage:ro" # 只读挂载 Verdaccio 存储 - "./manager-data:/app/data" # 读写:SQLite 数据 ports: ["3000:3000"] ``` ### 12.3 部署方式二:虚拟机 / 裸机 - 环境:Node.js 18 + pnpm,构建前端后 `node server.js`,pm2/systemd 守护 - 配置(环境变量或 `.env`): ``` VERDACCIO_STORAGE=/var/lib/verdaccio/storage PORT=3000 DATA_DIR=/var/lib/verdaccio-manager/data ``` - Verdaccio 侧 `config.yaml`:`storage: /var/lib/verdaccio/storage`(与面板指向同一目录) ### 12.4 UI 配置入口 - 首次启动:无 `storage_dir` 时展示引导页,提供缓存目录输入 + 「自动探测」(读环境变量/常见路径)按钮 - 后续修改:顶栏头像下拉「设置」/ 移动端设置抽屉中修改,保存后重新扫描并刷新概览