Lumin Admin 图床配置系统:多云存储统一管理
📌 概述
图床配置系统是 Lumin Admin 的核心模块之一,用于管理多个远程图床平台的访问凭据。系统采用配置与使用分离的架构设计:图床凭据在「系统设置 → 图床配置」中管理,图床文件在「媒体库」中浏览和上传。
本功能支持 6 大主流图床平台,配置数据存储在
admin/imageHosting.json,GitHub 平台支持真实 API 连接测试。
一、架构设计
1.1 配置与使用分离
1系统设置 → 图床配置 媒体库
2┌─────────────────┐ ┌─────────────────┐
3│ 添加/编辑 Key │ │ 本地文件浏览 │
4│ 启用/禁用图床 │ │ 远程图床浏览 │
5│ 测试连接 │ │ 上传到图床 │
6│ 设置默认图床 │ │ 复制链接 │
7└─────────────────┘ └─────────────────┘
这种设计的好处:
- 职责单一:配置页面只管凭据,媒体库只管文件
- 安全隔离:敏感凭据不暴露在文件浏览界面
- 灵活切换:上传时可选择任意已启用的图床
1.2 数据流
1图床配置页面 ──保存──→ imageHosting.json ←──读取── 媒体库(来源列表)
2 ←──读取── 上传接口(路由决策)
二、支持的图床平台
2.1 平台配置字段
| 平台 | Key | 必填字段 |
|---|---|---|
| 七牛云 | qiniu | AccessKey, SecretKey, Bucket, Domain, Region |
| 腾讯云 COS | tencent-cos | SecretId, SecretKey, Bucket, Region |
| 阿里云 OSS | aliyun-oss | AccessKeyId, AccessKeySecret, Bucket, Region, Endpoint(可选) |
| 又拍云 | upyun | Operator, Password, Bucket, Domain |
| GitHub | github | Token, Owner, Repo, Branch, Path, Domain(可选) |
| Cloudflare R2 | cloudflare-r2 | AccountId, AccessKeyId, SecretAccessKey, Bucket, PublicUrl |
2.2 后端字段定义
使用 PROVIDER_FIELDS 常量定义每个平台的配置字段元数据:
1const PROVIDER_FIELDS = {
2 qiniu: {
3 name: '七牛云',
4 fields: [
5 { key: 'accessKey', label: 'AccessKey', type: 'text' },
6 { key: 'secretKey', label: 'SecretKey', type: 'password' },
7 { key: 'bucket', label: 'Bucket(存储空间)', type: 'text' },
8 { key: 'domain', label: '绑定域名(含 https://)', type: 'text' },
9 { key: 'region', label: 'Region(如 z0/z1/z2)', type: 'text' }
10 ]
11 },
12 // ... 其他平台
13}
type: 'password' 的字段在前端显示为密码输入框,支持显示/隐藏切换。
三、后端 API
3.1 接口列表
| 接口 | 方法 | 说明 |
|---|---|---|
/api/image-hosting/providers | GET | 获取所有图床配置及状态 |
/api/image-hosting/providers/:provider | PUT | 保存指定平台配置 |
/api/image-hosting/providers/:provider | DELETE | 删除指定平台配置 |
/api/image-hosting/default | PUT | 设置默认图床 |
/api/image-hosting/test/:provider | GET | 测试图床连接 |
3.2 获取配置
1app.get('/api/image-hosting/providers', (req, res) => {
2 const config = loadImageHostingConfig()
3 const providers = {}
4 for (const [key, meta] of Object.entries(PROVIDER_FIELDS)) {
5 const saved = config.providers[key] || {}
6 providers[key] = {
7 key,
8 name: meta.name,
9 enabled: saved.enabled || false,
10 configured: meta.fields.every(f => saved[f.key]),
11 fields: meta.fields.map(f => ({ ...f, value: saved[f.key] || '' }))
12 }
13 }
14 ok(res, { providers, default: config.default || 'local' })
15})
返回数据中 configured 字段表示所有必填字段是否已填写,enabled 表示是否启用。
3.3 连接测试
GitHub 平台支持真实 API 连接测试:
1if (provider === 'github') {
2 const resp = await fetch(
3 `https://api.github.com/repos/${pConfig.owner}/${pConfig.repo}`,
4 { headers: { Authorization: `token ${pConfig.token}`, 'User-Agent': 'Lumin-Admin' } }
5 )
6 connected = resp.ok
7 message = connected ? 'GitHub 仓库连接成功' : `连接失败: ${resp.status}`
8}
其他平台验证配置完整性:
1if (provider === 'qiniu') {
2 connected = !!(pConfig.accessKey && pConfig.secretKey && pConfig.bucket && pConfig.domain)
3 message = connected ? '七牛云配置完整,请上传测试' : '配置不完整'
4}
3.4 配置存储
1const IMAGE_HOSTING_CONFIG = join(ROOT, 'admin', 'imageHosting.json')
2
3function loadImageHostingConfig() {
4 try {
5 if (!existsSync(IMAGE_HOSTING_CONFIG)) return { providers: {}, default: 'local' }
6 return JSON.parse(readFileSync(IMAGE_HOSTING_CONFIG, 'utf-8'))
7 } catch {
8 return { providers: {}, default: 'local' }
9 }
10}
11
12function saveImageHostingConfig(config) {
13 const dir = dirname(IMAGE_HOSTING_CONFIG)
14 if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
15 writeFileSync(IMAGE_HOSTING_CONFIG, JSON.stringify(config, null, 2), 'utf-8')
16}
四、前端实现
4.1 图床配置页面
卡片式布局展示 6 个平台,每个卡片包含:
- 品牌色图标:每个平台有独特的渐变色背景
- 状态标签:已启用 / 已配置 / 未配置
- 展开/折叠:点击展开配置表单
- 密码字段:支持显示/隐藏切换
- 操作按钮:测试连接、保存配置、删除配置
1.provider-icon {
2 &.icon--qiniu { background: linear-gradient(135deg, #00b4d8, #0077b6); }
3 &.icon--tencent-cos { background: linear-gradient(135deg, #0066ff, #0044cc); }
4 &.icon--aliyun-oss { background: linear-gradient(135deg, #ff6a00, #ee0979); }
5 &.icon--upyun { background: linear-gradient(135deg, #1a9cff, #0066cc); }
6 &.icon--github { background: linear-gradient(135deg, #333, #24292e); }
7 &.icon--cloudflare-r2 { background: linear-gradient(135deg, #f6821f, #fbad41); }
8}
4.2 默认图床选择
页面顶部设置默认图床,下拉列表包含「本地存储」和所有已配置的图床:
1<el-select v-model="defaultProvider" @change="changeDefault">
2 <el-option label="本地存储" value="local" />
3 <el-option v-for="p in configuredProviders" :key="p.key" :label="p.name" :value="p.key" />
4</el-select>
4.3 媒体库集成
媒体库页面新增来源切换,动态获取已启用的远程图床:
1async function loadRemoteProviders() {
2 const res = await getImageHostingProviders()
3 const providers = Object.values(res.data.providers || {})
4 remoteProviders.value = providers.filter(p => p.configured && p.enabled)
5}
五、安全考虑
- 密码字段:前端使用
type="password"输入,后端明文存储(因为是本地管理后台) - 路径安全:配置文件存储在
admin/目录下,不暴露在 Hugo 构建输出中 - 连接测试:GitHub 测试使用 HTTPS,Token 不记录日志
六、后续规划
- 图床文件浏览:集成各平台 SDK,在媒体库中查看远程文件
- 图床文件上传:直接上传到远程图床
- 图床文件删除:从远程图床删除文件
- 增量同步:本地与远程图床的文件同步
七、文件变更清单
| 文件 | 变更 |
|---|---|
admin/backend/server.js | 新增 5 个图床配置 API |
admin/frontend/src/views/Storage/Index.vue | 新建图床配置页面 |
admin/frontend/src/views/Media/index.vue | 新增来源切换 |
admin/frontend/src/api/index.js | 新增 5 个图床 API 函数 |
admin/frontend/src/router/index.js | 新增 /storage 路由 |
admin/frontend/src/layouts/MainLayout.vue | 侧边栏新增图床配置菜单 |
admin/imageHosting.json | 图床配置数据文件 |
留言评论
期待你的想法评论加载中