✨ 添加主题切换功能:支持暗色/亮色玻璃主题
功能说明: - 管理员可在系统设置中配置全局默认主题 - 普通用户可在设置页面选择:跟随全局/暗色/亮色 - 分享页面自动继承分享者的主题偏好 - 主题设置实时保存,刷新后保持 技术实现: - 后端:数据库添加theme_preference字段,新增主题API - 前端:CSS变量实现主题切换,localStorage缓存避免闪烁 - 分享页:加载时获取分享者主题设置 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1628,6 +1628,56 @@ app.get('/api/user/profile', authMiddleware, (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// 获取用户主题偏好(包含全局默认主题)
|
||||
app.get('/api/user/theme', authMiddleware, (req, res) => {
|
||||
try {
|
||||
const globalTheme = SettingsDB.get('global_theme') || 'dark';
|
||||
const userTheme = req.user.theme_preference; // null表示跟随全局
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
theme: {
|
||||
global: globalTheme,
|
||||
user: userTheme,
|
||||
effective: userTheme || globalTheme // 用户设置优先,否则使用全局
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: '获取主题失败' });
|
||||
}
|
||||
});
|
||||
|
||||
// 设置用户主题偏好
|
||||
app.post('/api/user/theme', authMiddleware, (req, res) => {
|
||||
try {
|
||||
const { theme } = req.body;
|
||||
const validThemes = ['dark', 'light', null]; // null表示跟随全局
|
||||
|
||||
if (!validThemes.includes(theme)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '无效的主题设置,可选: dark, light, null(跟随全局)'
|
||||
});
|
||||
}
|
||||
|
||||
UserDB.update(req.user.id, { theme_preference: theme });
|
||||
|
||||
const globalTheme = SettingsDB.get('global_theme') || 'dark';
|
||||
res.json({
|
||||
success: true,
|
||||
message: '主题偏好已更新',
|
||||
theme: {
|
||||
global: globalTheme,
|
||||
user: theme,
|
||||
effective: theme || globalTheme
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('更新主题失败:', error);
|
||||
res.status(500).json({ success: false, message: '更新主题失败' });
|
||||
}
|
||||
});
|
||||
|
||||
// 更新FTP配置
|
||||
app.post('/api/user/update-ftp',
|
||||
authMiddleware,
|
||||
@@ -2888,6 +2938,44 @@ app.delete('/api/share/:id', authMiddleware, (req, res) => {
|
||||
|
||||
// ===== 分享链接访问(公开) =====
|
||||
|
||||
// 获取公共主题设置(用于分享页面,无需认证)
|
||||
app.get('/api/public/theme', (req, res) => {
|
||||
try {
|
||||
const globalTheme = SettingsDB.get('global_theme') || 'dark';
|
||||
res.json({
|
||||
success: true,
|
||||
theme: globalTheme
|
||||
});
|
||||
} catch (error) {
|
||||
res.json({ success: true, theme: 'dark' }); // 出错默认暗色
|
||||
}
|
||||
});
|
||||
|
||||
// 获取分享页面主题(基于分享者偏好或全局设置)
|
||||
app.get('/api/share/:code/theme', (req, res) => {
|
||||
try {
|
||||
const { code } = req.params;
|
||||
const share = ShareDB.findByCode(code);
|
||||
const globalTheme = SettingsDB.get('global_theme') || 'dark';
|
||||
|
||||
if (!share) {
|
||||
return res.json({
|
||||
success: true,
|
||||
theme: globalTheme
|
||||
});
|
||||
}
|
||||
|
||||
// 优先使用分享者的主题偏好,否则使用全局主题
|
||||
const effectiveTheme = share.theme_preference || globalTheme;
|
||||
res.json({
|
||||
success: true,
|
||||
theme: effectiveTheme
|
||||
});
|
||||
} catch (error) {
|
||||
res.json({ success: true, theme: 'dark' });
|
||||
}
|
||||
});
|
||||
|
||||
// 访问分享链接 - 验证密码(支持本地存储和SFTP)
|
||||
app.post('/api/share/:code/verify', shareRateLimitMiddleware, async (req, res) => {
|
||||
const { code } = req.params;
|
||||
@@ -3418,11 +3506,13 @@ app.get('/api/admin/settings', authMiddleware, adminMiddleware, (req, res) => {
|
||||
const smtpUser = SettingsDB.get('smtp_user');
|
||||
const smtpFrom = SettingsDB.get('smtp_from') || smtpUser;
|
||||
const smtpHasPassword = !!SettingsDB.get('smtp_password');
|
||||
const globalTheme = SettingsDB.get('global_theme') || 'dark';
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
settings: {
|
||||
max_upload_size: maxUploadSize,
|
||||
global_theme: globalTheme,
|
||||
smtp: {
|
||||
host: smtpHost || '',
|
||||
port: smtpPort ? parseInt(smtpPort, 10) : 465,
|
||||
@@ -3445,7 +3535,7 @@ app.get('/api/admin/settings', authMiddleware, adminMiddleware, (req, res) => {
|
||||
// 更新系统设置
|
||||
app.post('/api/admin/settings', authMiddleware, adminMiddleware, (req, res) => {
|
||||
try {
|
||||
const { max_upload_size, smtp } = req.body;
|
||||
const { max_upload_size, smtp, global_theme } = req.body;
|
||||
|
||||
if (max_upload_size !== undefined) {
|
||||
const size = parseInt(max_upload_size);
|
||||
@@ -3458,6 +3548,18 @@ app.post('/api/admin/settings', authMiddleware, adminMiddleware, (req, res) => {
|
||||
SettingsDB.set('max_upload_size', size.toString());
|
||||
}
|
||||
|
||||
// 更新全局主题
|
||||
if (global_theme !== undefined) {
|
||||
const validThemes = ['dark', 'light'];
|
||||
if (!validThemes.includes(global_theme)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '无效的主题设置'
|
||||
});
|
||||
}
|
||||
SettingsDB.set('global_theme', global_theme);
|
||||
}
|
||||
|
||||
if (smtp) {
|
||||
if (!smtp.host || !smtp.port || !smtp.user) {
|
||||
return res.status(400).json({ success: false, message: 'SMTP配置不完整' });
|
||||
|
||||
Reference in New Issue
Block a user