-- 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);