feat: 系统配置 + 用户签名

- 新增 sys_config 表,存储应用版本号、标语、描述
- 关于小菜弹窗版本号改为从数据库动态获取
- 用户表新增 slogan 字段(个性签名)
- 编辑资料页面支持修改签名
- 管理后台新增系统配置管理页面
- 更新 CLAUDE.md 文档
This commit is contained in:
2026-06-08 10:37:04 +08:00
parent 29614fdb70
commit 2705335002
15 changed files with 469 additions and 21 deletions

View File

@@ -0,0 +1,53 @@
import { Router } from 'express'
import { pool } from '../db/connection'
import { authMiddleware } from '../middleware/auth'
const router = Router()
/** 获取公开配置(无需管理员权限) */
router.get('/', async (_req, res) => {
try {
const [rows] = await pool.execute('SELECT config_key, config_value FROM sys_config')
const config: Record<string, string> = {}
for (const row of rows as any[]) {
config[row.config_key] = row.config_value
}
res.json(config)
} catch (error) {
console.error('Get config error:', error)
res.status(500).json({ error: '获取配置失败' })
}
})
/** 更新配置(管理员权限) */
router.put('/', authMiddleware, async (req, res) => {
try {
const userId = (req as any).userId
const [users] = await pool.execute('SELECT role FROM users WHERE id = ?', [userId])
const user = (users as any[])[0]
if (!user || user.role !== 'admin') {
return res.status(403).json({ error: '无权限' })
}
const data = req.body
if (!data || typeof data !== 'object') {
return res.status(400).json({ error: '无效的配置数据' })
}
// 批量更新配置
for (const [key, value] of Object.entries(data)) {
await pool.execute(
'INSERT INTO sys_config (config_key, config_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE config_value = ?',
[key, value, value]
)
}
res.json({ success: true })
} catch (error) {
console.error('Update config error:', error)
res.status(500).json({ error: '更新配置失败' })
}
})
export default router