极简图标库,专为 NAS 设计。图标管理 Web 应用,提供在线图标链接,支持分类管理、上传、搜索、编辑、缩略图缓存与数据统计。
- 框架: Nuxt 4 + Vue 3(SSR)
- UI: Element Plus(按需导入)+ 玻璃态设计
- 图表: ECharts 6(按需导入:PieChart + TooltipComponent + LegendComponent)
- 国际化: 中文 / English(@nuxtjs/i18n)
- 后端: Nitro(Nuxt 内置服务端)
- 缩略图: sharp(WebP,200px,按需生成 + 后台批量生成)
- 密码哈希: Node.js 内置 crypto.scryptSync(零依赖)
- 容器化: Docker + docker-compose
# 安装依赖
npm install
# 开发模式(默认 http://localhost:3000)
npm run dev
# 生产构建与预览
npm run build
node .output/server/index.mjs
# 构建并启动
docker compose up -d --build
# 访问 http://localhost:3000
项目附带 dev.sh 自启动脚本:自动释放 3000 端口、清理残留 nuxi 进程、后台启动并等待 HTTP 200:
| 角色 |
操作范围 |
| 管理员 |
完整 CRUD:上传/编辑/删除图标、管理分类、站点设置(含发布)、认证配置、缩略图生成 |
| 游客 |
只读浏览:搜索图标、查看分类、复制链接;设置页可修改个人偏好(仅本地 localStorage 保存) |
设置页共 9 张卡片,瀑布流布局,列数自适应窗口宽度:
| 区块 |
功能 |
| 外观设置 |
深浅模式、背景模糊、界面配色(4 色)、文字颜色(2 色)、图标配色(2 色) |
| 壁纸设置 |
本地/网络/自定义上传、背景色 |
| 图标设置 |
图标大小、卡片圆角、间距、名称/边框显示、图标配色 |
| 搜索设置 |
显示搜索框、实时搜索、排序方式/顺序 |
| 分页设置 |
显示分页、单页隐藏、每页数量 |
| 文字内容 |
网站名称、功能介绍、描述文字 |
| 站点设置 |
界面语言、URL 前缀、自定义 CSS |
| 账号安全 |
游客模式开关、用户名、密码修改 |
| 数据管理 |
图标分类饼图、数据统计(图标/缓存/空间)、缩略图生成/删除 |
管理员修改任意配置后,右上角出现「发布」按钮 → 点击写入 setting.json,全站生效。游客的本地偏好不受影响。
- 分类文件夹命名:索引 + "_" + 文件夹名称(如
01_图标)
- 文件夹封面图:Cover.png(放在对应分类文件夹下)
- 上传图标到对应分类,点击图标即可获取 URL 链接
- 支持搜索、分类筛选、分页浏览
- 按需生成:首次访问图标时自动生成 WebP 缩略图(200px 宽,参考
server/api/thumb.get.js)
- 后台批量生成:设置页「数据管理」→ 点击「生成缓存」,后台任务边生成边返回进度
- 本地脚本:
scripts/generate-thumbs.mjs 可独立运行批量生成(node scripts/generate-thumbs.mjs)
myicon/
├── app/ # 前端
│ ├── pages/ # 路由页面
│ │ ├── index.vue # 首页(导航 + 搜索 + 子页面切换,~755 行)
│ │ ├── home.vue # 图标网格 + 分类筛选 + 分页(~591 行)
│ │ ├── setting.vue # 设置页(9 张卡片,瀑布流,~1606 行)
│ │ ├── about.vue # 关于页(8 张卡片,瀑布流,~561 行)
│ │ ├── login.vue # 登录页(打字机效果 + 记住账号,~521 行)
│ │ └── [...slug].vue # 安全兜底(catch-all 404)
│ ├── components/ # IconDialog.vue / FolderDialog.vue / IconPublish.vue
│ ├── layouts/ # blank.vue / default.vue
│ ├── assets/ # 静态资源
│ ├── plugins/ # 插件(auth-sync.client.js)
│ └── utils/ # api.js(Token 管理 + API 封装)/ color.js(颜色工具)
├── server/ # 后端
│ ├── api/ # API 路由
│ │ ├── config.js # 通用文件操作 CRUD(read/write/readDir/mkdir/rename/delete/upload)
│ │ ├── icon-files.js # 批量读取图标文件列表(公开)
│ │ ├── auth-status.get.js # 游客模式状态(公开)
│ │ ├── authConfig.js # 认证配置读取(需登录)
│ │ ├── authSave.js # 认证配置写入(需登录)
│ │ ├── login.js # 登录验证(scrypt 校验 + Token 签发)
│ │ ├── data-stats.js # 数据统计 GET + 缩略图生成/删除 POST(含进度轮询)
│ │ └── thumb.get.js # 缩略图按需生成(路径校验 + sharp 实时生成)
│ ├── middleware/ # rate-limit.js(IP 限流中间件)
│ ├── data/ # auth.json / tokens.json(认证数据,Docker volume)
│ └── utils/ # auth.js(Token 验证/清理)/ hash.js(scrypt 哈希)
├── i18n/ # 国际化
│ ├── locales/ # zh-CN.json(236 条)/ en-US.json(236 条)
│ └── i18n.config.ts # Vue I18n 配置
├── public/data/ # 运行时数据(Docker volume)
│ ├── icon/ # 图标文件(按分类文件夹)
│ ├── wallpaper/ # 壁纸图片
│ ├── img/ # UI 资源图片
│ ├── qrcode/ # 打赏二维码
│ ├── .thumb/ # 缩略图缓存(WebP,自动生成,可重建)
│ └── setting.json # 站点配置(管理员发布写入)
├── scripts/ # 工具脚本
│ └── generate-thumbs.mjs # 批量生成缩略图(独立运行)
├── Dockerfile # 多阶段构建(node:22-slim)
├── docker-compose.yml # 双 volume 持久化
├── dev.sh # 开发自启动脚本
├── nuxt.config.ts # Nuxt 配置(Element Plus 按需 + i18n + 字体预加载)
└── package.json
| 数据 |
路径 |
持久化(Docker) |
| 图标文件 |
public/data/icon/ |
volume myicon-data |
| 壁纸 |
public/data/wallpaper/ |
同上 |
| 站点配置 |
public/data/setting.json |
同上 |
| UI 图片 |
public/data/img/ |
同上 |
| 打赏二维码 |
public/data/qrcode/ |
同上 |
| 认证配置 |
server/data/auth.json |
volume myicon-auth |
| 登录 Token |
server/data/tokens.json |
同上 |
| 缩略图缓存 |
public/data/.thumb/ |
可随时重建,不入库 |
| 变量 |
默认值 |
说明 |
NITRO_PORT / PORT |
3000 |
服务端口 |
NITRO_HOST |
0.0.0.0 |
监听地址(Docker 默认 0.0.0.0) |
无自定义环境变量。反代场景下,中间件通过 x-forwarded-for 或 x-real-ip 取客户端 IP 用于限流(无需额外配置)。
| 端点 |
方法 |
说明 |
/api/auth-status |
GET |
返回 { tourist: boolean },游客模式开关 |
/api/icon-files |
GET |
所有分类及文件列表(含图标名称、扩展名、大小) |
/api/thumb?path=... |
GET |
缩略图(按需生成,路径相对 public/data/) |
/api/data-stats |
GET |
数据统计(分类/图标/缓存/空间) |
| 端点 |
方法 |
说明 |
/api/login |
POST |
登录验证,返回 { token, mode, username } |
/api/config |
POST |
文件操作(read/write/readDir/mkdir/rename/delete/upload) |
/api/authConfig |
GET |
读取认证配置({ tourist, username }) |
/api/authSave |
POST |
写入认证配置({ tourist, username, password }) |
/api/data-stats |
POST |
缩略图管理(action: generate/progress/delete) |
中间件规则按路径前缀匹配(server/middleware/rate-limit.js,内存计数,按分钟窗口重置)。
| 路径 |
限制 |
说明 |
/api/login |
5 次/分钟/IP |
登录尝试 |
/api/authSave |
20 次/分钟/IP |
认证配置保存 |
/api/config |
120 次/分钟/IP |
文件操作(读/写/目录/上传) |
- 密码哈希:
crypto.scryptSync(salt + 64 字节 hash),支持旧明文密码兼容迁移
- Token 管理: 随机 32 字节 hex,7 天过期,写入前自动清理过期条目,防止文件膨胀
- 路径穿越防护:
path.join + startsWith(ALLOWED_ROOT) 校验,拒绝越界访问
- 上传校验: 白名单扩展名(png/jpg/jpeg/gif/webp/svg)+ 10MB 上限
- 壁纸自动压缩: >512KB 的图片自动缩放到 ≤1920px 宽(保持原格式),节省存储与带宽
- IP 限流: 进程内内存计数,按分钟窗口重置,
Retry-After 响应头提示
- 错误页: 自定义 404/错误页(
app/error.vue),生产环境由 Nitro 默认脱敏错误响应
- 认证数据隔离:
server/data/ 不在 public/ 下,外部无法直接访问
- 缩略图路径校验: 仅允许
public/data/ 下的文件生成缩略图