feat(zen-box): 新增云端配置同步功能,完善应用构建与配置

本次提交实现了观空禅音应用的核心云端同步功能,包括:
1.  添加用户登录验证接口与本地存储管理
2.  新增云端配置存储与拉取接口,支持跨设备同步歌单、播放进度等设置
3.  新增登录页面与设置页账号管理模块
4.  更新依赖包版本与安卓、iOS打包配置
5.  优化缓存下载逻辑,修复OSS链接编码问题
6.  新增离线模式支持,自动过滤无缓存歌单
7.  新增歌曲排序偏好本地与云端同步功能
This commit is contained in:
yangxiangyuan
2026-07-11 10:57:02 +08:00
parent 33625e3438
commit 6a043687f5
18 changed files with 880 additions and 66 deletions
+46
View File
@@ -5760,6 +5760,52 @@ app.get('/api/zen_box/playlists', (req, res) => {
}
})
// 观空禅音:登录验证(读环境变量,不走用户表)
app.post('/api/zen_box/auth/login', (req, res) => {
try {
const { username, password } = req.body || {}
const expectedUser = process.env.ZEN_BOX_USERNAME || ''
const expectedPass = process.env.ZEN_BOX_PASSWORD || ''
if (expectedUser && expectedPass && username === expectedUser && password === expectedPass) {
return res.json({ ok: true, username })
}
return res.status(401).json({ ok: false, error: '账号或密码错误' })
} catch (e) {
res.status(500).json({ ok: false, error: String(e.message || e) })
}
})
// 观空禅音:云端配置存储(简易文件存储,按 username 隔离)
const ZEN_BOX_CONFIG_DIR = path.join(process.cwd(), 'data', 'zen_box_configs')
app.get('/api/zen_box/config', (req, res) => {
try {
const username = String(req.query.username || '').trim()
if (!username) return res.status(400).json({ ok: false, error: '缺少 username 参数' })
const configFile = path.join(ZEN_BOX_CONFIG_DIR, `${username}.json`)
if (!fs.existsSync(configFile)) return res.json({ ok: true, config: null })
const raw = fs.readFileSync(configFile, 'utf-8')
const config = JSON.parse(raw)
return res.json({ ok: true, config })
} catch (e) {
res.status(500).json({ ok: false, error: String(e.message || e) })
}
})
app.post('/api/zen_box/config', (req, res) => {
try {
const { username, config } = req.body || {}
if (!username || !config) return res.status(400).json({ ok: false, error: '缺少参数' })
if (!fs.existsSync(ZEN_BOX_CONFIG_DIR)) {
fs.mkdirSync(ZEN_BOX_CONFIG_DIR, { recursive: true })
}
const configFile = path.join(ZEN_BOX_CONFIG_DIR, `${username}.json`)
fs.writeFileSync(configFile, JSON.stringify(config, null, 2), 'utf-8')
return res.json({ ok: true })
} catch (e) {
res.status(500).json({ ok: false, error: String(e.message || e) })
}
})
// Static: keep weekly tool assets always fresh
app.use(express.static(path.join(process.cwd(), 'public'), {
setHeaders: (res, filePath) => {