Files
verdaccio-cache-manager/doc/design-spec.md
T
陈银军 8a54fb2d5c feat: 包信息展示与扫描数据修正
- scanner: 版本数只统计实际存在的 .tgz(修复 playwright-core 5113 版本虚高),解析 description/homepage/repository/author/license 元数据字段
- 前端: 新增 PkgLogo 首字母徽标组件,详情抽屉展示包 logo(主页 favicon 加载失败自动回退)、介绍与主页/仓库/许可胶囊,优化抽屉头部布局
- 全量 UI 改进: 毛玻璃扫描遮罩与进度、头像菜单重新扫描、主题切换、移动端 Tabbar/StatMini/Top30Panel 响应式、列表瘦身与详情按需加载
- compose: TZ=Asia/Shanghai + 命名卷 vcm-data 解决 SQLite 权限
- 更新 amd64 镜像 tar
2026-09-19 21:07:27 +08:00

269 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 20 排行、包卡片列表 | `/` |
| 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 | 橙色渐变 + 可清理空间 + 立即清理按钮 |
| Top20 排行 | 表格:金银铜徽章、包名(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` 时展示引导页,提供缓存目录输入 + 「自动探测」(读环境变量/常见路径)按钮
- 后续修改:顶栏头像下拉「设置」/ 移动端设置抽屉中修改,保存后重新扫描并刷新概览