需求:前台壁纸站支持切换到开源壁纸平台,并能展示后台上传的自家图库, 保留原有「浏览器实时生成」能力(扩展而非替换),PC / 移动双端一致。 设计要点(受服务器 5M 出口带宽约束): - 开源平台图片一律走官方 CDN 直链,后端只代理元数据,零带宽消耗。 - 自建图库落盘到 /data/www/wallpaper,由 nginx 的 /wallpaper/ 直出, Go 服务不参与传图;三档尺寸(480 缩略 / 1920 预览 / 原图仅供下载)。 - 内存缓存平台响应(Bing 1h、搜索类 10min),避免撞第三方配额。 内容: - 平台插件:Bing 每日一图、Picsum、Unsplash、Pexels、Wallhaven。 新增平台 = 写一个 provider_xxx.go 并在 allProviders() 加一行, 刻意不用 init() 自注册,避免隐式副作用。所有适配器支持 config.baseUrl 覆盖,用于绕开 DNS 污染(实测 wallhaven.cc 解析到境外无关 IP)。 - 自建图库:上传(MD5 秒传去重 / 尺寸前置校验 / 失败清理孤儿文件)、 元信息编辑、删除、统计;随机取图用「数总数 → 随机偏移」而非 ORDER BY RAND()。 - 接口:open 组 4 个(sources / list / random / download-track), admin 组 8 个(list / upload / save / delete / stats / source.list|save|test)。 全部 POST 且 URL 无参数,符合工作空间接口规范;上传走 multipart 例外。 - 安全:purity 默认锁死 SFW;apiKey 只回传布尔不回传明文; 保存时留空表示保留旧值;open 组错误信息对外脱敏。 - 配置:clientMaxBodySize 提到 64M(gf 默认 8M 会截断 20MB 原图); wallpaper.root / baseUrl 支持环境变量注入并在占位符未替换时兜底。 依赖:golang.org/x/image@v0.23.0(仅用于缩略图缩放,保持 go 1.23.0 不变)。
104 lines
8.1 KiB
Go
104 lines
8.1 KiB
Go
-- 018_wallpaper.sql
|
||
-- 壁纸模块:自建图库表 + 开源平台配置表 + 菜单/权限种子。
|
||
--
|
||
-- 设计要点:
|
||
-- 1) 自建图库(wallpaper)存「原图 + 缩略图 + 预览图」三份路径。
|
||
-- 原图只用于下载,列表用缩略图(480px)、全屏展示用预览图(长边 1920),
|
||
-- 这样 5M 出口带宽不会被大图打满。三份文件都由 nginx 直出、不过 Go 服务。
|
||
-- 2) 开源平台(wallpaper_source)只存配置(含 API Key),**不存图**——
|
||
-- 图片本体走各平台官方 CDN 直链,零带宽消耗。
|
||
-- 加平台只需插一行数据 + 后端注册一个 Provider,不改表结构。
|
||
-- 3) 幂等:CREATE TABLE IF NOT EXISTS;菜单 INSERT ... ON DUPLICATE KEY UPDATE;
|
||
-- 种子 INSERT ... ON DUPLICATE KEY UPDATE(不覆盖用户已改的 enabled/config)。
|
||
--
|
||
-- 依赖:service 主库;admin_menu / admin_role_menu 已存在(001_core.sql)。
|
||
|
||
-- ============ 1) 自建壁纸图库 ============
|
||
CREATE TABLE IF NOT EXISTS `wallpaper` (
|
||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`title` VARCHAR(200) NOT NULL DEFAULT '' COMMENT '标题',
|
||
`tags` VARCHAR(300) NOT NULL DEFAULT '' COMMENT '标签(英文逗号分隔)',
|
||
`category` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '分类(自由文本)',
|
||
`orientation` TINYINT NOT NULL DEFAULT 0 COMMENT '朝向 0未知 1横版 2竖版 3方形',
|
||
`width` INT NOT NULL DEFAULT 0 COMMENT '原图宽度(px)',
|
||
`height` INT NOT NULL DEFAULT 0 COMMENT '原图高度(px)',
|
||
`filesize` BIGINT NOT NULL DEFAULT 0 COMMENT '原图字节数',
|
||
`mime` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '原图MIME(image/jpeg等)',
|
||
`path` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '原图相对路径(相对存储根)',
|
||
`thumb_path` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '缩略图相对路径(480px)',
|
||
`preview_path` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '预览图相对路径(长边1920)',
|
||
`hash` CHAR(32) NOT NULL DEFAULT '' COMMENT '原图MD5(秒传去重)',
|
||
`enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用 0否 1是',
|
||
`sort` INT NOT NULL DEFAULT 0 COMMENT '排序,小的在前',
|
||
`view_count` INT NOT NULL DEFAULT 0 COMMENT '浏览次数',
|
||
`download_count` INT NOT NULL DEFAULT 0 COMMENT '下载次数',
|
||
`remark` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '备注',
|
||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
`deleted_at` DATETIME NULL DEFAULT NULL,
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_enabled_sort` (`enabled`, `sort`),
|
||
KEY `idx_orientation` (`orientation`),
|
||
KEY `idx_hash` (`hash`),
|
||
KEY `idx_created` (`created_at`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自建壁纸图库';
|
||
|
||
-- ============ 2) 开源平台配置 ============
|
||
CREATE TABLE IF NOT EXISTS `wallpaper_source` (
|
||
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||
`code` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '平台编码 bing/picsum/unsplash/pexels/wallhaven',
|
||
`name` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '平台显示名',
|
||
`enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用 0否 1是',
|
||
`sort` INT NOT NULL DEFAULT 0 COMMENT '排序,小的在前',
|
||
`config` VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '平台配置JSON(apiKey/defaultQuery等)',
|
||
`remark` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '备注',
|
||
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_code` (`code`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='壁纸开源平台配置';
|
||
|
||
-- ============ 3) 平台种子 ============
|
||
-- bing / picsum 零配置即可用;其余三个需要各自申请 API Key,故默认停用,
|
||
-- 后台填入 Key 并打开开关即可生效(无需改代码、无需重启)。
|
||
-- 注意:ON DUPLICATE KEY UPDATE 只更新展示名与排序,**不动 enabled 与 config**,
|
||
-- 避免重放本脚本时把用户已填的 Key 或已改的开关状态覆盖掉。
|
||
INSERT INTO `wallpaper_source` (`code`, `name`, `enabled`, `sort`, `config`, `remark`) VALUES
|
||
('bing', 'Bing 每日一图', 1, 1, '', '微软必应每日壁纸,无需 API Key,每日更新一张'),
|
||
('picsum', 'Lorem Picsum', 1, 2, '', 'Lorem Picsum 随机摄影图,无需 API Key'),
|
||
('unsplash', 'Unsplash', 0, 3, '', '需在 unsplash.com/developers 申请 Access Key'),
|
||
('pexels', 'Pexels', 0, 4, '', '需在 pexels.com/api 申请 API Key'),
|
||
('wallhaven', 'Wallhaven', 0, 5, '', '需在 wallhaven.cc 申请 API Key,可按分辨率与横竖版筛选')
|
||
ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `sort` = VALUES(`sort`), `remark` = VALUES(`remark`);
|
||
|
||
-- ============ 4) 菜单:壁纸中心 ============
|
||
-- id 段选择说明:一级菜单已用 1/5/9/90/97/98/99,故取 100;
|
||
-- 其下子菜单取 1001/1002 与 API 权限 10011.. / 10021..,与既有编号无冲突。
|
||
INSERT INTO admin_menu (id, parent_id, name, icon, type, path, component, permission, sort, status, hidden, created_at, updated_at) VALUES
|
||
(100, 0, '壁纸中心', 'mdi:image-multiple-outline', 1, '/wallpaper', '', 'wallpaper:center', 10, 1, 0, NOW(), NOW()),
|
||
(1001, 100, '图库管理', 'mdi:image-album', 1, 'library', 'wallpaper/library/index', 'wallpaper:library', 1, 1, 0, NOW(), NOW()),
|
||
(1002, 100, '平台配置', 'mdi:cloud-cog-outline', 1, 'source', 'wallpaper/source/index', 'wallpaper:source', 2, 1, 0, NOW(), NOW())
|
||
ON DUPLICATE KEY UPDATE parent_id=VALUES(parent_id), name=VALUES(name), icon=VALUES(icon), type=VALUES(type),
|
||
path=VALUES(path), component=VALUES(component), permission=VALUES(permission), sort=VALUES(sort),
|
||
status=VALUES(status), hidden=VALUES(hidden), deleted_at=NULL;
|
||
|
||
-- ============ 5) type=2 API 权限 ============
|
||
-- path 必须与实际路由完全一致(中间件按「方法+路径」匹配),全 POST、无 URL 参数。
|
||
INSERT INTO admin_menu (id, parent_id, name, icon, type, path, component, permission, sort, status, hidden, created_at, updated_at) VALUES
|
||
(10011, 1001, '查询', '', 2, 'POST /api/service/admin/wallpaper/list', '', 'wallpaper:library:list', 1, 1, 0, NOW(), NOW()),
|
||
(10012, 1001, '上传', '', 2, 'POST /api/service/admin/wallpaper/upload', '', 'wallpaper:library:upload', 2, 1, 0, NOW(), NOW()),
|
||
(10013, 1001, '编辑', '', 2, 'POST /api/service/admin/wallpaper/save', '', 'wallpaper:library:save', 3, 1, 0, NOW(), NOW()),
|
||
(10014, 1001, '删除', '', 2, 'POST /api/service/admin/wallpaper/delete', '', 'wallpaper:library:delete', 4, 1, 0, NOW(), NOW()),
|
||
(10015, 1001, '统计', '', 2, 'POST /api/service/admin/wallpaper/stats', '', 'wallpaper:library:stats', 5, 1, 1, NOW(), NOW()),
|
||
(10021, 1002, '查询', '', 2, 'POST /api/service/admin/wallpaper/source/list', '', 'wallpaper:source:list', 1, 1, 0, NOW(), NOW()),
|
||
(10022, 1002, '保存', '', 2, 'POST /api/service/admin/wallpaper/source/save', '', 'wallpaper:source:save', 2, 1, 0, NOW(), NOW()),
|
||
(10023, 1002, '测试', '', 2, 'POST /api/service/admin/wallpaper/source/test', '', 'wallpaper:source:test', 3, 1, 0, NOW(), NOW())
|
||
ON DUPLICATE KEY UPDATE parent_id=VALUES(parent_id), name=VALUES(name), type=VALUES(type),
|
||
path=VALUES(path), permission=VALUES(permission), sort=VALUES(sort), status=VALUES(status), hidden=VALUES(hidden), deleted_at=NULL;
|
||
|
||
-- ============ 6) 超管角色绑定 ============
|
||
-- role_id=1 为超级管理员(见 004_seed.sql / 009_admin_account_v2.sql)。
|
||
INSERT IGNORE INTO admin_role_menu (role_id, menu_id, created_at, updated_at)
|
||
SELECT 1, id, NOW(), NOW() FROM admin_menu
|
||
WHERE id IN (100, 1001, 1002, 10011, 10012, 10013, 10014, 10015, 10021, 10022, 10023);
|