Files
verdaccio-cache-manager/doc/需求文档.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

992 lines
65 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 缓存可视化管理面板 — 需求文档(完整版)
本文档由两部分合并而成:第一部分为功能需求,第二部分为前端界面设计。
## 第一部分 功能需求
## Verdaccio 缓存可视化管理面板 — 需求文档
### 1. 项目概述
#### 1.1 项目背景
团队使用 Verdaccio 作为私有 npm 仓库代理,长期运行后存储目录会积累大量历史版本缓存包。当某个包的版本数超过设定阈值时,会占用大量磁盘空间,且难以手动识别和清理。
当前痛点:
无法直观看到哪些包占用了大量空间
清理版本需要手动操作 Verdaccio 存储目录,风险高
没有预警机制,磁盘空间被不知不觉耗尽
某些包虽然版本多但需要保留,无法标记"忽略"
#### 1.2 项目目标
开发一个轻量级的可视化管理面板,运行在 Docker 容器中,与 Verdaccio 共享存储目录,提供以下核心能力:
可视化管理缓存包:以表格形式展示所有缓存包的版本数、占用空间、预警状态
全局模糊检索:支持按包名关键词实时筛选
阈值可配置:可设置版本数阈值,持久化存储
预警清单:超阈值的包自动列入预警清单,标红展示
忽略标记:预警包可手工标记为"忽略",标记后不再触发预警
#### 1.3 非目标
不替代 Verdaccio 本身,仅作为管理工具
不实现用户认证/权限系统(单用户内部工具)
不实现定时自动清理(仅手动触发)
不实现跨 Verdaccio 实例管理(仅管理单个实例)
### 2. 用户角色
| 角色 | 描述 |
|---|---|
| 运维/开发人员 | 唯一使用者,负责查看缓存状态、配置阈值、执行清理操作 |
### 3. 功能需求
#### 3.1 可视化管理缓存包
##### 3.1.1 包列表展示
系统应提供一个表格,展示 Verdaccio 存储目录中的所有缓存包,包含以下字段:
| 字段 | 说明 | 示例 |
|---|---|---|
| 包名 | npm 包名称 | lodash |
| 版本数 | 该包当前缓存的版本总数 | 25 |
| 占用空间 | 该包所有版本文件占用的磁盘空间 | 128.5 MB |
| 状态 | 正常 / ️ 预警 / ️ 已忽略 | 见下文状态规则 |
| 操作 | 根据状态显示不同操作按钮 | 清理 / 忽略 / 取消忽略 |
##### 3.1.2 状态规则
| 状态 | 触发条件 | 展示样式 |
|---|---|---|
| 正常 | 版本数 ≤ 阈值 | 无特殊标记 |
| ️ 预警 | 版本数 > 阈值 且 未被忽略 | 红色标签 |
| ️ 已忽略 | 用户手动标记忽略 | 灰色标签 |
##### 3.1.3 排序规则
列表默认按以下优先级排序:
预警包排在最前面
正常包排在中间
已忽略包排在最后
同状态下按版本数降序排列
#### 3.2 全局模糊检索
##### 3.2.1 检索输入框
位于列表上方,占位符提示" 输入包名关键词..."
支持实时输入,输入后立即过滤列表
支持一键清空
##### 3.2.2 检索规则
匹配方式:不区分大小写的子串匹配
匹配范围:仅匹配包名
示例:输入 react 可匹配 react、react-dom、@types/react
##### 3.2.3 检索反馈
检索结果实时更新,无需点击搜索按钮
列表上方显示"共找到 X 个包"
清空检索条件后恢复完整列表
#### 3.3 阈值可配置
##### 3.3.1 阈值设置
提供数字输入框,允许设置版本数阈值
取值范围:1 ~ 100
默认值:15
##### 3.3.2 阈值持久化
阈值修改后自动保存到 SQLite 数据库
服务重启后阈值不丢失
页面加载时自动读取已保存的阈值
##### 3.3.3 阈值生效
修改阈值后,列表状态立即重新计算
原本正常的包可能变为预警,原本预警的包可能变为正常
#### 3.4 预警清单与清理
##### 3.4.1 预警触发
当包的版本数超过阈值时:
该包在列表中显示 ️ 预警标签
该包自动排在列表最前面
"清理"按钮变为可用状态
##### 3.4.2 清理确认弹窗
点击"清理"按钮后,弹出确认对话框,包含以下内容:
| 元素 | 说明 |
|---|---|
| 包名标题 | 显示正在清理的包名 |
| 当前版本数 | 显示该包当前有多少个版本 |
| 保留版本数输入框 | 数字输入框,默认值为当前阈值,可调整 |
| 将删除版本列表 | 展示将被删除的低版本号列表(Tag 形式) |
| 将删除数量 | 显示即将删除的版本个数 |
| 取消按钮 | 关闭弹窗,不执行任何操作 |
| 确认清理按钮 | 执行清理操作,按钮带 loading 状态 |
##### 3.4.3 清理执行逻辑
确认清理后,系统执行以下原子操作:
读取该包的 package.json 元数据
按语义化版本号排序,保留最新的 N 个版本
从元数据中删除低版本的 versions 和 time 记录
检查并修正 dist-tags(如 latest 指向了被删除的版本)
将修改后的元数据写回 package.json
物理删除对应的 .tgz 文件
记录操作日志到数据库
返回清理结果:删除数量、释放空间
##### 3.4.4 清理结果反馈
成功:显示"已清理 X 个版本,释放 Y MB"
失败:显示错误信息,不修改任何文件
#### 3.5 忽略标记
##### 3.5.1 标记忽略
预警包旁边显示"忽略"按钮
点击后,该包从预警状态变为"已忽略"状态
标记立即保存到 SQLite 数据库
该包不再触发预警,即使版本数仍超过阈值
##### 3.5.2 取消忽略
已忽略包旁边显示"取消忽略"按钮
点击后,恢复该包的正常状态判断
如果版本数仍超过阈值,自动变回预警状态
标记立即从数据库中删除
##### 3.5.3 忽略持久化
忽略标记保存到 SQLite 的 ignored_packages 表
服务重启后忽略标记不丢失
页面加载时自动读取已忽略的包列表
#### 3.6 操作日志(附加功能)
##### 3.6.1 日志记录
每次清理操作后,系统自动记录以下信息:
| 字段 | 说明 |
|---|---|
| 包名 | 被清理的包名称 |
| 删除版本列表 | 被删除的版本号,逗号分隔 |
| 删除数量 | 删除的版本个数 |
| 释放空间 | 释放的磁盘空间(格式化后) |
| 操作时间 | 清理执行的 UTC 时间 |
##### 3.6.2 日志查看
提供独立的日志页面或弹窗
按时间倒序展示最近 50 条操作记录
支持查看历史清理详情
### 3.7 Verdaccio 缓存目录配置
#### 3.7.1 配置方式
系统需配置 Verdaccio 缓存目录(storage/)路径,支持以下来源,按优先级生效:
| 优先级 | 来源 | 说明 |
|---|---|---|
| 1 | 环境变量 VERDACCIO_STORAGE | Docker / 虚拟机部署时注入 |
| 2 | UI 设置 | 面板内配置,持久化到 SQLite settings 表(key = storage_dir) |
| 3 | 首次启动引导页 | 均未配置时展示引导页,要求填写缓存目录 |
#### 3.7.2 目录校验
保存 / 启动时校验目录存在、可读、包含 package.json 或 .tgz 文件
校验失败时提示重新配置,面板不启动扫描
#### 3.7.3 扫描逻辑
递归扫描目录下所有包的 package.json,解析 versions / time 字段获取版本列表
匹配对应 .tgz 文件计算占用空间
支持 scoped 包(@scope/name 嵌套目录)
#### 3.7.4 UI 入口
首次启动引导页:缓存目录输入框 + 「自动探测」按钮(读取环境变量 / 常见路径)
后续修改:顶栏头像下拉「设置」/ 移动端设置抽屉中修改,保存后重新扫描并刷新概览
#### 3.7.5 两种部署方式
| 部署方式 | 说明 |
|---|---|
| Docker 部署 | 与 Verdaccio 同主机,共享宿主机 storage 目录:面板容器只读挂载 storage(:ro),manager-data 读写挂载存 SQLite;环境变量注入 VERDACCIO_STORAGE |
| 虚拟机部署 | 本机安装 Node.js 18 + pnpm,环境变量或 .env 指向 Verdaccio 缓存目录,pm2 / systemd 守护进程 |
### 4. 非功能需求
#### 4.1 性能要求
| 指标 | 要求 |
|---|---|
| 包列表加载 | 500 个包以内,加载时间 < 2 秒 |
| 检索响应 | 输入后 < 200ms 内完成过滤 |
| 清理操作 | 单个包清理 < 5 秒 |
#### 4.2 可靠性要求
清理操作必须是原子性的:要么全部成功,要么全部回滚
元数据文件损坏时,该包在列表中标记为"异常",不影响其他包
服务崩溃后,已完成的清理操作不丢失,未完成的清理不产生脏数据
#### 4.3 安全性要求
容器以非 root 用户运行(UID 10000)
Verdaccio 存储目录以只读方式挂载
仅允许修改目标包的元数据和文件,不遍历其他目录
#### 4.4 兼容性要求
支持 Verdaccio 5.x 存储结构
支持 scoped 包(如 @antv/g2)
支持语义化版本号(semver)排序
### 5. 数据模型
#### 5.1 SQLite 表结构
-- 配置表
CREATE TABLE settings (
key TEXT PRIMARY KEY,
value TEXT
);
-- 忽略标记表
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
);
#### 5.2 默认配置
| key | value | 说明 |
|---|---|---|
| version_threshold | 15 | 版本数阈值 |
### 6. API 接口设计
#### 6.1 阈值管理
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/threshold | 获取当前阈值 |
| POST | /api/threshold | 设置新阈值 |
#### 6.2 忽略标记
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/ignored | 获取所有已忽略的包名 |
| POST | /api/ignore | 标记某个包为忽略 |
| DELETE | /api/ignore/:pkgName | 取消某个包的忽略标记 |
#### 6.3 包管理
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/packages?keyword=xxx | 扫描并获取所有包列表(支持模糊检索) |
| POST | /api/clean | 执行清理操作 |
#### 6.4 日志
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/logs | 获取最近 50 条操作日志 |
### 7. 界面原型
#### 7.1 主页面布局
┌─────────────────────────────────────────────────────────────────┐
│ Verdaccio 缓存管理器 │
├─────────────────────────────────────────────────────────────────┤
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 版本数阈值: [ 15 ] [输入包名关键词...] 共 128 个包 │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ 包名 │ 版本数 │ 空间 │ 状态 │ 操作 │ │
│ ├───────────────┼─────────┼──────────┼──────────┼────────────┤ │
│ │ lodash │ 25 │ 128 MB │ ️ 预警 │ [清理][忽略]│ │
│ │ @antv/g2 │ 22 │ 96 MB │ ️ 预警 │ [清理][忽略]│ │
│ │ react │ 8 │ 42 MB │ 正常 │ — │ │
│ │ vue │ 19 │ 88 MB │ ️ 已忽略│ [取消忽略] │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
#### 7.2 清理确认弹窗
┌──────────────────────────────────────────┐
│ 清理 lodash │
│ ────────────────────────────────────── │
│ 当前 25 个版本,将保留最近的 [ 15 ] 个 │
│ │
│ 将删除以下 10 个版本: │
│ [3.0.0] [3.1.0] [3.5.0] [3.10.0] ... │
│ │
│ [取消] [确认清理] │
└──────────────────────────────────────────┘
### 8. 技术选型
| 层级 | 选型 | 理由 |
|---|---|---|
| 运行时 | Node.js 18-slim | 轻量,JSON 操作天然友好 |
| Web 框架 | Express | 轻量,零学习成本 |
| 数据库 | better-sqlite3 | 单文件嵌入式,无需额外部署 |
| 前端框架 | Vue 3 | 响应式,组件化 |
| UI 组件库 | Element Plus | 组件丰富,开箱即用 |
| 部署方式 | Docker 单容器 | 与 Verdaccio 同主机部署 |
### 9. 部署架构
绿联 DX4600+ NAS
├── Verdaccio 容器(端口 4873)
│ └── 存储目录: /volume1/docker/verdaccio/storage
│
└── Verdaccio Manager 容器(端口 3000)
├── 只读挂载: /volume1/docker/verdaccio/storage → /verdaccio/storage
├── 读写挂载: ./manager-data → /app/data
└── 镜像: node:18-slim(最终约 180MB)
#### 9.1 Docker 部署(compose 示例)
```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"
```
#### 9.2 虚拟机部署
- 环境: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`(与面板指向同一目录)
### 10. 验收标准
| 编号 | 验收项 | 通过标准 |
|---|---|---|
| AC-1 | 包列表展示 | 能正确列出所有包,版本数、空间、状态准确 |
| AC-2 | 模糊检索 | 输入关键词后列表实时过滤,结果正确 |
| AC-3 | 阈值配置 | 修改阈值后保存,刷新页面不丢失,列表状态立即更新 |
| AC-4 | 预警触发 | 版本数超阈值的包自动标红并排在最前 |
| AC-5 | 清理操作 | 清理后 package.json 和 .tgz 文件同步删除,dist-tags 正确修正 |
| AC-6 | 忽略标记 | 标记后不再预警,取消后恢复判断,重启不丢失 |
| AC-7 | 操作日志 | 每次清理自动记录,可查询历史 |
| AC-8 | 原子性 | 清理过程中断不会产生脏数据 |
这份需求文档覆盖了核心功能、数据模型、API 设计、界面原型和验收标准。需要我基于这份文档继续输出详细设计文档(含类图/时序图)或直接开始编码实现吗?
(AI生成)
## 第二部分 前端界面设计文档
## Verdaccio 缓存管理工具 — 前端界面设计文档
### 一、项目概述
本工具为 Verdaccio 私有 npm 仓库的缓存管理前端界面,用于可视化管理 storage/ 目录下的缓存包文件。工具定位为一款精致的 C 端产品,而非冷冰冰的后台管理系统。
#### 1.1 设计风格定位
| 维度 | 后台管理系统风格(拒绝) | C端风格(采用) |
|---|---|---|
| 布局 | 左侧固定导航 + 右侧内容区 | 顶部导航栏 + 全宽内容区 |
| 色彩 | 蓝白灰,严肃冷淡 | 多巴胺配色,活力温暖 |
| 圆角 | 4px 小圆角 | 12-24px 大圆角 |
| 阴影 | 无阴影或硬边 | 柔和弥散阴影 |
| 动效 | 无动效或生硬切换 | 平滑过渡 + 微动效 |
| 文案 | “缓存管理”“操作日志” | “你的缓存”“最近动态” |
| 图标 | 线性图标 | 圆润填充图标 + emoji |
| 页面切换 | 无过渡 | 平滑淡入 + 轻微上滑 |
#### 1.2 多巴胺配色方案
| 颜色角色 | 色值 | 用途 |
|---|---|---|
| 清新绿 | #32CD32 | 正常状态标签、选中态标签 |
| 活力橙 | #FF8C00 | 清理按钮、Logo、搜索按钮 |
| 热情红 | #FF4500 | 预警标签、删除按钮、预警数量卡片 |
| 静谧蓝 | #1E90FF | 忽略按钮、忽略标签、访问排行卡片 |
| 卡片背景 | 白色 + 大圆角 | 所有卡片容器 |
| 预警卡片 | 红色边框 + 呼吸光晕动效 | 触发阈值的包卡片 |
#### 1.3 设计原则
行动导向优先:能直接引导用户操作的指标优先(如”可清理空间”比”预警数量”更有驱动力)
宏观 + 微观结合:既有整体数据(包数量、总空间),也有极端值(最大包、最老包),帮助用户快速定位问题
避免信息过载:顶部卡片控制在 4-7 个,更多细节通过点击展开或第二行展示
C端体验优先:拒绝千篇一律的后台管理系统风格,打造轻盈、有趣、有温度的产品
### 二、菜单结构
#### 2.1 导航菜单
| 序号 | 菜单名 | 图标 | 说明 |
|---|---|---|---|
| 1 | 缓存概览 | | 主页/仪表盘,展示包卡片列表、存储空间统计、预警信息 |
| 2 | 全局检索 | | 按包名/版本/大小搜索,支持筛选条件 |
| 3 | 阈值配置 | | 设置缓存预警阈值(如单包最大体积、总缓存上限等) |
| 4 | 忽略列表 | | 管理已标记忽略的包,支持取消忽略 |
| 5 | 操作日志 | | 查看清理、删除、忽略等操作的历史记录 |
#### 2.2 顶部导航栏设计
┌────────────────────────────────────────────────────────────────┐
│ 📦 Verdaccio Manager │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 概览 │ │ 搜索 │ │ 设置 │ │ 动态 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ 👤 │
└────────────────────────────────────────────────────────────────┘
设计要点: - 顶部通栏:高度 64px,白色背景 + 底部 1px 浅灰线 - Pill 导航按钮:圆角 20px,选中态用多巴胺色块背景 - Logo:左侧 emoji + 系统名,用活力橙 #FF8C00 - 用户头像:右侧圆形头像,点击弹出下拉菜单(含”忽略列表”入口) - 响应式:移动端折叠为汉堡菜单
#### 2.3 补充说明
不需要”设置”菜单:阈值配置已经覆盖了核心设置项,其他系统级配置(如 Verdaccio 连接地址)可以在首次启动时通过弹窗配置,或放在用户头像的下拉菜单中。
不需要”用户管理”菜单:本工具定位为个人/小团队内部使用,暂不涉及多用户权限管理。
### 三、缓存概览页
#### 3.1 统计指标(共 8 个)
| 序号 | 指标 | 图标 | 说明 |
|---|---|---|---|
| 1 | 包的数量 | | 缓存包总数 |
| 2 | 占用空间 | | 总占用空间 |
| 3 | 预警数量 | | 触发阈值的包数量 |
| 4 | 今日更新包数 | | 最近更新时间等于今天的包数量 |
| 5 | 可清理空间 | | 预估可释放的空间 |
| 6 | 最大包 | | 占用空间最大的包 |
| 7 | 最老包时间 | | 最久未更新的包的时间 |
| 8 | 版本数分布 | | 单包版本数分布情况 |
#### 3.2 布局设计
##### 第一行(核心指标 · 4 个)
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ 包的数量 │ 占用空间 │ 预警数量 │ 可清理空间 │
│ 1,247 │ 12.8 GB │ 23 │ 3.2 GB │
│ 清新绿 │ 活力橙 │ 热情红呼吸 │ 静谧蓝 │
│ │ │ │ [立即清理] │
└──────────────┴──────────────┴──────────────┴──────────────┘
指标说明: - 包的数量:扫描 storage/ 目录下的包文件夹数量 - 占用空间:递归计算 storage/ 下所有 .tgz 文件总大小 - 预警数量:对比阈值配置,统计触发条件的包数量 - 可清理空间:根据阈值规则,预估可释放的空间,给用户”清理动力” - 今日更新包数:最近更新时间等于今天的包数量
##### 第二行(辅助指标 · 5 个)
┌──────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ 今日更新包数 │ 缓存版本总数 │ 最大包 │ 最老包时间 │ 版本数分布 │
│ 12 │ 86.1 万 │ tensorflow │ 3 年前 │ >50版本: 12个│
│ [查看] │ 所有版本 │ 2.1 GB │ legacy-utils │ [查看详情] │
└──────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
#### 3.3 缓存占用 Top 20 排行
概览页常驻展示占用空间最大的 20 个包,采用表格形式(真实环境无访问统计时按占用大小排序):
┌────────────────────────────────────────────────────────────────┐
│ 缓存占用 Top 20 │
├──────┬──────────────────────┬──────────┤
│ 排名 │ 包名 │ 占用空间 │
├──────┼──────────────────────┼──────────┤
│ │ tensorflow │ 2.1 GB │
│ │ @antv/g2 │ 1.4 GB │
│ │ lodash │ 854 MB │
│ 4 │ react │ 621 MB │
│ ... │ ... │ ... │
└──────┴──────────────────────┴──────────┘
设计要点: - 前三名用金银铜标识,多巴胺配色高亮 - 包名支持 scoped(如 @antv/g2),超出宽度省略 + tooltip - 点击行可打开该包的详情抽屉
#### 3.4 缓存包列表(卡片形式)
以圆角卡片形式展示每个缓存包的核心信息,卡片采用多巴胺配色,按状态排序:
┌──────────────────────────────────────────────────────────────┐
│ 📦 lodash │
│ 版本: 25 | 空间: 128.5 MB │
│ 🔥 预警 (红色光晕呼吸动效) │
│ [✨ 清理] [💤 忽略] │
└──────────────────────────────────────────────────────────────┘
卡片字段: - 包名(支持 scoped 包如 @antv/g2) - 版本数 - 占用空间(格式化后,如 128.5 MB) - 状态标签(正常 / 预警 / 已忽略) - 操作按钮(清理、忽略)
排序规则: 预警包置顶 → 正常包居中 → 已忽略包垫底,同状态按版本数降序。
#### 3.5 数据来源说明
| 指标 | 数据来源 |
|---|---|
| 包的数量 | 扫描 storage/ 目录下的包文件夹数量 |
| 占用空间 | 递归计算 storage/ 下所有 .tgz 文件总大小 |
| 预警数量 | 对比阈值配置,统计触发条件的包数量 |
| 访问次数 | 解析 Verdaccio 的 logs/ 日志或 storage/ 下各包的 package.json 中的 downloads 字段 |
### 四、全局检索页
#### 4.1 顶部搜索框(百度风格)
┌────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 输入包名、版本、大小进行模糊搜索... │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ [全部] [预警包] [已忽略] [按大小排序] [按版本数排序] │
│ │
└────────────────────────────────────────────────────────────────┘
设计要点: - 大圆角搜索框:border-radius: 24px,高度 48px,居中展示 - 占位符提示:输入包名、版本、大小进行模糊搜索… - 实时搜索:输入时防抖 300ms,自动触发检索 - 快捷筛选标签:搜索框下方一排 pill 按钮,支持状态过滤和排序切换 - 多巴胺配色:搜索按钮用活力橙 #FF8C00,选中态标签用清新绿 #32CD32
#### 4.2 搜索结果列表(无边框虚拟表格)
┌────────────────────────────────────────────────────────────────┐
│ 包名 │ 版本数 │ 占用空间 │ 状态 │ 最后更新 │
├────────────────────────────────────────────────────────────────┤
│ lodash │ 25 │ 128.5 MB │ 预警 │ 2024-01-15 │
│ axios │ 18 │ 45.2 MB │ 正常 │ 2024-03-22 │
│ @antv/g2 │ 32 │ 256.8 MB │ 预警 │ 2024-02-10 │
│ react │ 15 │ 89.3 MB │ 正常 │ 2024-04-01 │
│ ... │ ... │ ... │ ... │ ... │
└────────────────────────────────────────────────────────────────┘
技术实现: - 虚拟滚动:使用 Element Plus 的 el-table-v2 或 vue-virtual-scroller,仅渲染可视区域 DOM,支持万级数据流畅滚动 - 无边框设计:border: none,行与行之间用浅灰分割线 #F0F0F0(1px) - 按需加载:初始加载 50 条,滚动到底部自动加载下一页(Infinite Scroll) - 悬停高亮:鼠标悬停行背景变为浅多巴胺色 #FFF8F0 - 点击跳转:点击任意行,打开该包的详情抽屉/弹窗
#### 4.3 包详情页(点击行后展开)
点击列表行后,从右侧滑出抽屉(Drawer),展示该包的完整信息:
┌────────────────────────────────────────────────────────────────┐
│ lodash [× 关闭] │
├────────────────────────────────────────────────────────────────┤
│ 版本数: 25 | 占用空间: 128.5 MB | 状态: 预警 │
│ 最后更新: 2024-01-15 | 首次缓存: 2020-03-10 │
├────────────────────────────────────────────────────────────────┤
│ 版本列表 │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 4.17.21 | 1.2 MB | 2024-01-15 | [🗑️ 删除] │ │
│ │ 4.17.20 | 1.2 MB | 2023-08-22 | [🗑️ 删除] │ │
│ │ 4.17.19 | 1.1 MB | 2023-03-10 | [🗑️ 删除] │ │
│ │ ... │ │
│ └──────────────────────────────────────────────────────────┘ │
├────────────────────────────────────────────────────────────────┤
│ [ 清理全部版本] [ 忽略此包] │
└────────────────────────────────────────────────────────────────┘
抽屉交互: - 宽度:600px(桌面端),移动端全屏 - 遮罩层:点击遮罩或按 ESC 关闭 - 版本列表:支持虚拟滚动,按语义化版本排序 - 批量操作:底部提供”清理全部版本”和”忽略此包”快捷按钮
#### 4.4 搜索逻辑
模糊检索:匹配包名、版本号、文件大小
const filteredPackages = packages.filter(pkg => {
return (
pkg.name.toLowerCase().includes(keyword.toLowerCase()) ||
pkg.versions.some(v => v.includes(keyword)) ||
formatSize(pkg.size).includes(keyword)
);
});
#### 4.5 技术选型
| 组件 | 用途 |
|---|---|
| el-input | 大圆角搜索框,带搜索图标 |
| el-table-v2 | 虚拟表格,支持万级数据 |
| el-drawer | 包详情抽屉,右侧滑出 |
| el-tag | 状态标签(预警/正常/已忽略) |
| vue-infinite-scroll | 滚动加载更多 |
### 五、忽略列表页
#### 5.1 界面布局
┌────────────────────────────────────────────────────────────────┐
│ 忽略列表 │
├────────────────────────────────────────────────────────────────┤
│ 共 15 个已忽略包 │
├────────────────────────────────────────────────────────────────┤
│ 包名 │ 版本数 │ 占用空间 │ 忽略时间 │ 操作 │
├────────────────────────────────────────────────────────────────┤
│ lodash │ 25 │ 128.5 MB │ 2024-01-15 │ [取消忽略] │
│ @antv/g2 │ 32 │ 256.8 MB │ 2024-02-10 │ [取消忽略] │
│ tensorflow │ 18 │ 2.1 GB │ 2024-03-05 │ [取消忽略] │
│ legacy-utils │ 8 │ 45.2 MB │ 2024-04-01 │ [取消忽略] │
│ ... │ ... │ ... │ ... │ ... │
└────────────────────────────────────────────────────────────────┘
设计要点: - 虚拟滚动:使用 el-table-v2,支持大量忽略包流畅滚动 - 无边框:行与行之间用浅灰分割线 #F0F0F0(1px) - 悬停高亮:鼠标悬停行背景变为 #FFF8F0 - 取消忽略:点击后弹出二次确认,确认后该包恢复至缓存概览列表 - 批量操作:顶部提供 [批量取消忽略] 按钮,支持勾选多个包批量恢复
#### 5.2 交互说明
点击 [取消忽略] → 弹出确认弹窗 → 确认后从忽略列表移除,恢复至缓存概览
勾选多个包 → 点击 [批量取消忽略] → 批量恢复
#### 5.3 技术选型
| 组件 | 用途 |
|---|---|
| el-table-v2 | 虚拟表格,支持大量数据流畅滚动 |
| el-popconfirm | 取消忽略二次确认 |
### 六、操作日志页
#### 6.1 界面布局
┌────────────────────────────────────────────────────────────────┐
│ 操作日志 │
├────────────────────────────────────────────────────────────────┤
│ 筛选: [全部] [清理操作] [删除操作] [忽略操作] │
├────────────────────────────────────────────────────────────────┤
│ 时间 │ 操作类型 │ 包名 │ 详情 │
├────────────────────────────────────────────────────────────────┤
│ 2024-04-15 14:30 │ 清理 │ lodash │ 删除 3 个版本 │
│ 2024-04-15 14:28 │ 忽略 │ @antv/g2 │ 标记为忽略 │
│ 2024-04-15 14:25 │ 删除 │ legacy-utils │ 删除全部版本 │
│ 2024-04-15 14:20 │ 清理 │ tensorflow │ 删除 5 个版本 │
│ ... │ ... │ ... │ ... │
├────────────────────────────────────────────────────────────────┤
│ 共 156 条记录 < 1 2 3 4 5 ... 16 > 每页 10 条 │
└────────────────────────────────────────────────────────────────┘
设计要点: - 普通分页表格:使用 el-table + el-pagination,每页 10/20/50 条可选 - 操作类型标签:清理(活力橙)、删除(热情红)、忽略(静谧蓝) - 筛选器:顶部 pill 按钮,按操作类型过滤 - 时间倒序:最新操作在最上方 - 详情展开:点击行可展开查看完整操作详情(如删除了哪些具体版本)
#### 6.2 交互说明
点击筛选标签 → 实时过滤对应类型的日志
点击分页 → 切换页码,保持筛选条件
点击行 → 展开查看详情(可选)
#### 6.3 技术选型
| 组件 | 用途 |
|---|---|
| el-table | 普通分页表格 |
| el-pagination | 分页器 |
| el-tag | 操作类型标签 |
| el-collapse | 行详情展开 |
### 七、阈值配置页
#### 7.1 功能说明
阈值配置页用于设置缓存预警规则,用户可以在这里自定义”多大算大”“多少版本算多”。
#### 7.2 配置项(建议)
| 配置项 | 说明 | 默认值 |
|---|---|---|
| 单包最大版本数 | 超过此版本数的包标记为预警 | 20 |
| 单包最大占用空间 | 超过此大小的包标记为预警 | 500 MB |
| 总缓存上限 | 超过此总量的预警提示 | 50 GB |
| 版本保留最少数量 | 清理时至少保留的版本数 | 3 |
| 自动清理规则 | 是否开启自动清理旧版本 | 关闭 |
#### 7.3 界面风格
采用 C 端风格卡片表单,每个配置项为一个圆角卡片,包含: - 配置项名称 + 说明文字 - 输入框/开关控件 - 多巴胺配色的高亮保存按钮
### 八、响应式设计
#### 8.1 断点定义
| 断点 | 尺寸范围 | 设备类型 |
|---|---|---|
| 手机端 | < 768px | 手机竖屏 |
| 平板端 | 768px ~ 1023px | 平板竖屏 / 小屏笔记本 |
| 桌面端 | ≥ 1024px | 主流显示器 / 平板横屏 |
#### 8.2 顶部导航栏 — 三端适配
桌面端(≥1024px)
┌────────────────────────────────────────────────────────────────┐
│ 📦 Verdaccio Manager │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 概览 │ │ 搜索 │ │ 设置 │ │ 动态 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ 👤 │
└────────────────────────────────────────────────────────────────┘
平板端(768px~1023px)
┌──────────────────────────────────────────────┐
│ 📦 Verdaccio Manager │
│ [概览] [搜索] [设置] [动态] 👤 │
└──────────────────────────────────────────────┘
导航按钮缩小为紧凑 pill,文字缩小至 14px
头像保持右侧
手机端(<768px)
┌────────────────────────────────────┐
│ 📦 Verdaccio Manager ☰ 👤 │
└────────────────────────────────────┘
导航按钮折叠为汉堡菜单 ☰
点击汉堡菜单,从左侧滑出侧边抽屉,显示全部导航项
侧边抽屉宽度 280px,遮罩层可点击关闭
#### 8.3 缓存概览 — 三端适配
桌面端(≥1024px)— 4 列网格
┌──────────────┬──────────────┬──────────────┬──────────────────┐
│ 📦 1,247 │ 💾 12.8 GB │ 🔥 23 │ 🧹 可省 3.2 GB │
│ 个包 │ 占用空间 │ 个预警 │ [一键清理] │
└──────────────┴──────────────┴──────────────┴──────────────────┘
平板端(768px~1023px)— 2×2 网格
┌──────────────┬──────────────┐
│ 📦 1,247 │ 💾 12.8 GB │
│ 个包 │ 占用空间 │
├──────────────┼──────────────┤
│ 🔥 23 │ 🧹 可省 3.2 GB │
│ 个预警 │ [一键清理] │
└──────────────┴──────────────┘
手机端(<768px)— 单列滚动
┌────────────────────────────────────┐
│ 📦 1,247 个包 │
├────────────────────────────────────┤
│ 💾 12.8 GB 占用空间 │
├────────────────────────────────────┤
│ 🔥 23 个预警 │
├────────────────────────────────────┤
│ 🧹 可省 3.2 GB [一键清理] │
└────────────────────────────────────┘
每个卡片高度压缩至 80px
“一键清理”按钮缩小为图标按钮,放在卡片右侧
#### 8.4 包列表 — 三端适配
桌面端 — 卡片网格(4 列)
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ 📦 lodash │ 📦 axios │ 📦 @antv/g2 │ 📦 react │
│ 25 版本 │ 18 版本 │ 32 版本 │ 15 版本 │
│ 128.5 MB │ 45.2 MB │ 256.8 MB │ 89.3 MB │
│ 🔥 预警 │ ✅ 正常 │ 🔥 预警 │ ✅ 正常 │
│ [清理] [忽略]│ [清理] [忽略]│ [清理] [忽略]│ [清理] [忽略]│
└──────────────┴──────────────┴──────────────┴──────────────┘
平板端 — 卡片网格(2 列)
┌──────────────┬──────────────┐
│ 📦 lodash │ 📦 axios │
│ 25 版本 │ 18 版本 │
│ 128.5 MB │ 45.2 MB │
│ 🔥 预警 │ ✅ 正常 │
│ [清理] [忽略]│ [清理] [忽略]│
└──────────────┴──────────────┘
手机端 — 单列卡片列表
┌────────────────────────────────────┐
│ 📦 lodash │
│ 25 版本 · 128.5 MB · 🔥 预警 │
│ [清理] [忽略] │
├────────────────────────────────────┤
│ 📦 axios │
│ 18 版本 · 45.2 MB · ✅ 正常 │
│ [清理] [忽略] │
├────────────────────────────────────┤
│ 📦 @antv/g2 │
│ 32 版本 · 256.8 MB · 🔥 预警 │
│ [清理] [忽略] │
└────────────────────────────────────┘
卡片高度压缩,操作按钮缩小为图标
虚拟滚动保持,流畅不卡顿
#### 8.5 全局搜索 — 三端适配
桌面端 — 居中宽搜索框
┌────────────────────────────────────────────────────────────────┐
│ │
│ 📦 搜索你的缓存包 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 🔍 输入包名、版本、大小... │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ 热门: lodash axios react @antv/g2 │
│ │
└────────────────────────────────────────────────────────────────┘
搜索框宽度 600px,高度 56px
平板端 — 居中搜索框(缩小)
┌──────────────────────────────────────────────┐
│ │
│ 📦 搜索你的缓存包 │
│ ┌────────────────────────────────────┐ │
│ │ 🔍 输入包名、版本... │ │
│ └────────────────────────────────────┘ │
│ │
│ 热门: lodash axios react │
│ │
└──────────────────────────────────────────────┘
搜索框宽度 100%(最大 500px),高度 48px
手机端 — 全宽搜索框
┌────────────────────────────────────┐
│ │
│ 📦 搜索缓存包 │
│ ┌──────────────────────────┐ │
│ │ 🔍 搜索... │ │
│ └──────────────────────────┘ │
│ │
│ 热门: lodash axios │
│ │
└────────────────────────────────────┘
搜索框宽度 100%,高度 44px
热门搜索标签换行显示
#### 8.6 忽略列表 — 三端适配
桌面端 — 3 列卡片网格
┌──────────────┬──────────────┬──────────────┐
│ 📦 lodash │ 📦 @antv/g2 │ 📦 tensorflow│
│ 25 版本 │ 32 版本 │ 18 版本 │
│ 128.5 MB │ 256.8 MB │ 2.1 GB │
│ [取消忽略] │ [取消忽略] │ [取消忽略] │
└──────────────┴──────────────┴──────────────┘
平板端 — 2 列卡片网格
┌──────────────┬──────────────┐
│ 📦 lodash │ 📦 @antv/g2 │
│ 25 版本 │ 32 版本 │
│ 128.5 MB │ 256.8 MB │
│ [取消忽略] │ [取消忽略] │
└──────────────┴──────────────┘
手机端 — 单列卡片列表
┌────────────────────────────────────┐
│ 📦 lodash │
│ 25 版本 · 128.5 MB │
│ [取消忽略] │
├────────────────────────────────────┤
│ 📦 @antv/g2 │
│ 32 版本 · 256.8 MB │
│ [取消忽略] │
└────────────────────────────────────┘
#### 8.7 操作日志(时间线)— 三端适配
桌面端 — 左右分栏
┌────────────────────────────────────────────────────────────────┐
│ 🕐 最近动态 │
├────────────────────────────────────────────────────────────────┤
│ 今天 │
│ ● 14:30 清理了 lodash 的 3 个旧版本 🧹 │
│ ● 14:28 忽略了 @antv/g2 💤 │
│ │
│ 昨天 │
│ ● 09:15 删除了 legacy-utils 的全部版本 🗑️ │
└────────────────────────────────────────────────────────────────┘
平板端 — 单栏(缩小间距)
时间线节点间距缩小
emoji 保持,文字缩小至 14px
手机端 — 单栏(紧凑)
┌────────────────────────────────────┐
│ 🕐 最近动态 │
├────────────────────────────────────┤
│ 今天 │
│ ● 14:30 清理 lodash 3 版本 🧹 │
│ ● 14:28 忽略 @antv/g2 💤 │
│ │
│ 昨天 │
│ ● 09:15 删除 legacy-utils 🗑️ │
│ │
│ [加载更多] │
└────────────────────────────────────┘
文案精简,去掉冗余文字
时间线节点缩小
#### 8.8 包详情抽屉 — 三端适配
桌面端 — 右侧抽屉(600px)
┌────────────────────────────────────────────────────────────────┐
│ 主内容区 │ 📦 lodash [×] │
│ │ 25 版本 · 128.5 MB │
│ │ 🔥 预警 │
│ │ │
│ │ 版本列表 │
│ │ 4.17.21 · 1.2 MB │
│ │ 4.17.20 · 1.2 MB │
│ │ │
│ │ [🧹 清理全部] [💤 忽略] │
└────────────────────────────────────────────────────────────────┘
平板端 — 右侧抽屉(50% 宽度)
抽屉宽度为屏幕的 50%
内容自适应
手机端 — 底部弹窗(全屏)
┌────────────────────────────────────┐
│ │
│ ┌──────────────────────────────┐ │
│ │ 📦 lodash [×] │ │
│ │ 25 版本 · 128.5 MB │ │
│ │ 🔥 预警 │ │
│ │ │ │
│ │ 版本列表 │ │
│ │ 4.17.21 · 1.2 MB │ │
│ │ 4.17.20 · 1.2 MB │ │
│ │ │ │
│ │ [🧹 清理] [💤 忽略] │ │
│ └──────────────────────────────┘ │
│ │
└────────────────────────────────────┘
从底部滑出,高度 85vh
顶部大圆角 24px
支持向下滑动关闭
#### 8.9 CSS 断点实现(Tailwind 风格)
/* 桌面端:≥1024px */
@media (min-width: 1024px) {
.grid-cards { grid-template-columns: repeat(4, 1fr); }
.grid-ignore { grid-template-columns: repeat(3, 1fr); }
.search-box { width: 600px; height: 56px; }
.drawer { width: 600px; }
}
/* 平板端:768px ~ 1023px */
@media (min-width: 768px) and (max-width: 1023px) {
.grid-cards { grid-template-columns: repeat(2, 1fr); }
.grid-ignore { grid-template-columns: repeat(2, 1fr); }
.search-box { width: 100%; max-width: 500px; height: 48px; }
.drawer { width: 50%; }
}
/* 手机端:<768px */
@media (max-width: 767px) {
.grid-cards { grid-template-columns: 1fr; }
.grid-ignore { grid-template-columns: 1fr; }
.search-box { width: 100%; height: 44px; }
.drawer { width: 100%; height: 85vh; border-radius: 24px 24px 0 0; }
.nav-pills { display: none; }
.hamburger { display: block; }
}
#### 8.10 响应式速查表
| 组件 | 桌面端 | 平板端 | 手机端 |
|---|---|---|---|
| 导航栏 | 顶部 pill 按钮 | 顶部紧凑 pill | 汉堡菜单 + 侧边抽屉 |
| 统计卡片 | 4 列网格 | 2×2 网格 | 单列滚动 |
| 包列表 | 4 列卡片网格 | 2 列卡片网格 | 单列卡片列表 |
| 忽略列表 | 3 列卡片网格 | 2 列卡片网格 | 单列卡片列表 |
| 搜索框 | 居中 600px | 居中 100%(max 500px) | 全宽 100% |
| 操作日志 | 左右分栏时间线 | 单栏时间线 | 单栏紧凑时间线 |
| 包详情 | 右侧抽屉 600px | 右侧抽屉 50% | 底部弹窗 85vh |
### 九、动效规范
| 场景 | 动效 |
|---|---|
| 页面切换 | 平滑淡入 + 轻微上滑 |
| 卡片悬停 | 轻微上浮 + 阴影加深 |
| 按钮点击 | 缩放 0.95 + 回弹 |
| 弹窗打开 | 从底部滑入 + 遮罩淡入 |
| 清理操作 | 卡片缩小消失 + 成功提示 toast |
### 十、文案风格对照
| 后台管理系统 | C端风格 |
|---|---|
| “缓存管理” | “你的缓存” |
| “操作日志” | “最近动态” |
| “忽略列表” | “已忽略的包” |
| “阈值配置” | “预警设置” |
| “执行清理” | “一键清理” |
| “共 156 条记录” | “156 条动态” |
### 十一、技术组件选型汇总
| 页面 | 核心组件 | 用途 |
|---|---|---|
| 缓存概览 | el-card + el-tag + el-progress | 统计卡片 + 状态标签 + 进度条 |
| 全局检索 | el-input + el-table-v2 + el-drawer | 搜索框 + 虚拟表格 + 详情抽屉 |
| 忽略列表 | el-table-v2 + el-popconfirm | 虚拟表格 + 二次确认 |
| 操作日志 | el-table + el-pagination + el-collapse | 分页表格 + 分页器 + 详情展开 |
| 阈值配置 | el-form + el-switch + el-input-number | 表单配置 |
| 全局 | el-tooltip + el-toast | 工具提示 + 操作反馈 |
### 十二、后端数据扫描逻辑
后端扫描 Verdaccio storage/ 目录时,按以下逻辑聚合数据:
storage/
├── lodash/
│ └── package.json ← 读取 versions、time、_rev
├── @antv/
│ └── g2/
│ └── package.json
└── ...
遍历 storage/ 下所有包的 package.json
解析 versions 字段获取版本列表
读取对应 .tgz 文件计算占用空间
返回聚合后的 JSON 数据给前端
### 十三、方案对比:卡片列表 vs 文件树
| 方案 | 优点 | 缺点 |
|---|---|---|
| 文件树 | 还原真实目录结构 | 层级深、信息分散、scoped 包路径嵌套混乱 |
| 卡片列表(推荐) | 信息聚合、一目了然、操作便捷 | 不展示原始文件路径(但本工具不需要) |
Verdaccio 的存储结构是以包为单位的扁平目录,每个包下只有一个 package.json 和若干 .tgz 文件。直接展示文件树会让用户看到大量无意义的目录嵌套(如 @antv/g2/package.json),而卡片列表能直接呈现用户关心的包维度信息,更符合本工具的管理目标。
### 十四、登录页面
#### 14.1 页面定位
登录页面是用户进入系统的入口,也是塑造产品第一印象的关键页面。遵循 C 端设计风格,登录页不应是冷冰冰的表单堆砌,而应传达出产品的温度与品质感。整体采用居中卡片式布局,搭配多巴胺配色渐变背景,营造轻盈、友好的视觉体验。
#### 14.2 界面布局
登录页面采用全屏渐变背景 + 居中白色卡片的设计模式,卡片承载所有登录表单元素。桌面端卡片宽度固定,平板端自适应,手机端卡片宽度 100% 并去除多余外边距。
┌────────────────────────────────────────────────────────────────┐
│ │
│ (渐变背景) │
│ │
│ ┌──────────────────────────────┐ │
│ │ │ │
│ │ 📦 Verdaccio Manager │ │
│ │ │ │
│ │ 欢迎回来,请登录你的账户 │ │
│ │ │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ 👤 用户名 │ │ │
│ │ └────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ 🔒 密码 │ │ │
│ │ └────────────────────────┘ │ │
│ │ │ │
│ │ ┌────────────────────────┐ │ │
│ │ │ 登 录 │ │ │
│ │ └────────────────────────┘ │ │
│ │ │ │
│ │ [ ] 记住我 忘记密码? │ │
│ └──────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
#### 14.3 设计要点
| 设计元素 | 规格 | 说明 |
|---|---|---|
| 背景 | 渐变背景 | 多巴胺配色渐变(如清新绿 #32CD32 → 静谧蓝 #1E90FF),营造活力氛围 |
| 卡片 | 白色圆角卡片 | border-radius: 24px,柔和弥散阴影,宽度 420px(桌面端) |
| Logo | 📦 Verdaccio Manager | 卡片顶部居中展示,字号 24px,活力橙 #FF8C00 |
| 副标题 | 欢迎回来,请登录你的账户 | 字号 14px,浅灰色 #666666,传递温度感 |
| 输入框 | 大圆角 + emoji 图标 | border-radius: 12px,左侧 emoji 图标(👤/🔒),高度 48px |
| 登录按钮 | 多巴胺色渐变按钮 | 圆角 12px,高度 48px,渐变背景(活力橙 → 热情红),悬停微上浮 |
#### 14.4 表单字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| 用户名 | 文本输入框 | 支持邮箱或用户名登录,带实时校验(格式是否正确) |
| 密码 | 密码输入框 | 支持明文/密文切换(眼睛图标),最少 6 位 |
| 记住我 | 复选框 | 勾选后 Cookie 保存登录状态,7 天免登录 |
| 忘记密码 | 链接文字 | 点击跳转至密码找回流程(邮件重置) |
#### 14.5 交互说明
• 输入框聚焦:边框变为活力橙 #FF8C00,底部出现橙色下划线动画
• 登录按钮点击:按钮缩小至 0.95 倍 + 加载旋转图标,防止重复提交
• 登录成功:按钮变为绿色 + "登录成功" 提示,1s 后跳转首页
• 登录失败:输入框边框变红 #FF4500,下方显示错误提示文字(如"用户名或密码错误")
• 记住我:勾选后本地加密存储 token,下次打开自动填充用户名
• 忘记密码:点击后平滑过渡到密码找回页面(同一卡片内切换内容)
#### 14.6 三端适配
登录页面作为全站入口,需要在所有设备上都有良好的体验。以下是三端适配方案:
桌面端(≥1024px)
┌────────────────────────────────────────────────────────────────┐
│ ┌──────────────────────────────┐ │
│ │ 📦 Verdaccio Manager │ │
│ │ 欢迎回来,请登录你的账户 │ │
│ │ [👤 用户名输入框] │ │
│ │ [🔒 密码输入框] │ │
│ │ [ 登 录 ] │ │
│ │ [ ] 记住我 忘记密码? │ │
│ └──────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘
卡片宽度 420px,居中显示,背景渐变全屏铺满。
平板端(768px~1023px)
┌──────────────────────────────────────┐
│ ┌────────────────────────────┐ │
│ │ 📦 Verdaccio Manager │ │
│ │ 欢迎回来,请登录 │ │
│ │ [👤 用户名] │ │
│ │ [🔒 密码] │ │
│ │ [ 登 录 ] │ │
│ │ [ ] 记住我 忘记密码? │ │
│ └────────────────────────────┘ │
└──────────────────────────────────────┘
卡片宽度 100%(最大 420px),外边距自动居中,背景渐变保持。
手机端(<768px)
┌────────────────────────────┐
│ ┌────────────────────────┐ │
│ │ 📦 Verdaccio Manager │ │
│ │ 欢迎回来,请登录 │ │
│ │ [👤 用户名] │ │
│ │ [🔒 密码] │ │
│ │ [ 登 录 ] │ │
│ │ [ ] 记住我 忘记密码? │ │
│ └────────────────────────┘ │
└────────────────────────────┘
卡片宽度 100%(去除左右外边距),输入框高度压缩至 44px,按钮高度 44px,整体间距缩小,适配手指触控操作。
#### 14.7 登录页响应式速查表
| 设备 | 卡片宽度 | 特殊适配 |
|---|---|---|
| 桌面端(≥1024px) | 420px 固定 | 居中显示,背景渐变全屏 |
| 平板端(768px~1023px) | 100%(max 420px) | 外边距自动居中 |
| 手机端(<768px) | 100%(无边距) | 输入框/按钮高度压缩至 44px,适配触控 |
| 横屏适配 | 420px 或 100% | 横屏时卡片改为左右分栏(左侧品牌区 + 右侧表单区) |
#### 14.8 技术选型
| 组件/技术 | 用途 |
|---|---|
| el-form + el-form-item | 表单容器与字段校验 |
| el-input(带前缀图标) | 用户名/密码输入框 |
| el-button(渐变背景) | 登录按钮 |
| el-checkbox | 记住我复选框 |
#### 14.9 安全建议
• 密码传输必须使用 HTTPS 加密
• 登录失败超过 5 次锁定账户 15 分钟
• Token 采用 JWT 格式,设置合理的过期时间(建议 24 小时)
• 敏感操作(如批量清理)需二次确认或重新输入密码
• 防止 XSS 攻击:所有用户输入进行转义处理
• 防止 CSRF 攻击:关键接口携带 CSRF Token