diff --git a/server/src/config/database.js b/server/src/config/database.js index 865dcdd..54f90fe 100644 --- a/server/src/config/database.js +++ b/server/src/config/database.js @@ -200,8 +200,33 @@ function parseJSON(str, defaultValue) { } } +// 刷新缓存 - 从数据库重新加载所有数据 +async function refreshCache() { + if (!pool) return false; + + try { + const [posts] = await pool.execute('SELECT * FROM posts ORDER BY date DESC'); + const [settings] = await pool.execute('SELECT * FROM settings WHERE id = 1'); + const [about] = await pool.execute('SELECT * FROM about WHERE id = 1'); + + memoryStore.posts = posts; + if (settings.length > 0) { + memoryStore.settings = formatSettings(settings[0]); + } + if (about.length > 0) { + memoryStore.about = formatAbout(about[0]); + } + + console.log('✅ 缓存已刷新'); + return true; + } catch (error) { + console.error('缓存刷新失败:', error.message); + return false; + } +} + function getPool() { return pool; } -module.exports = { initDatabase, getPool }; \ No newline at end of file +module.exports = { initDatabase, getPool, refreshCache }; \ No newline at end of file diff --git a/server/src/index.js b/server/src/index.js index b7e74db..3902d69 100644 --- a/server/src/index.js +++ b/server/src/index.js @@ -18,12 +18,14 @@ const aboutRouter = require('./routes/about'); const settingsRouter = require('./routes/settings'); const cronRouter = require('./routes/cron'); const configRouter = require('./routes/config'); +const cacheRouter = require('./routes/cache'); app.use('/api/posts', postsRouter); app.use('/api/about', aboutRouter); app.use('/api/settings', settingsRouter); app.use('/api/cron-tasks', cronRouter); app.use('/api/config', configRouter); +app.use('/api/cache', cacheRouter); // 健康检查 app.get('/api/health', (req, res) => { diff --git a/server/src/routes/cache.js b/server/src/routes/cache.js new file mode 100644 index 0000000..99c14f3 --- /dev/null +++ b/server/src/routes/cache.js @@ -0,0 +1,20 @@ +const express = require('express'); +const router = express.Router(); +const { refreshCache } = require('../config/database'); + +// 刷新所有缓存(posts, settings, about) +router.post('/refresh', async (req, res) => { + try { + const success = await refreshCache(); + if (success) { + res.json({ message: '缓存已刷新', success: true }); + } else { + res.status(500).json({ error: '缓存刷新失败', success: false }); + } + } catch (error) { + console.error('缓存刷新失败:', error); + res.status(500).json({ error: '缓存刷新失败', success: false }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/src/i18n/index.js b/src/i18n/index.js index a92ca96..3c1a6cc 100644 --- a/src/i18n/index.js +++ b/src/i18n/index.js @@ -48,7 +48,12 @@ export const messages = { uploadIcon: '上传图标', defaultIcon: '恢复默认', myIcons: '我的图标库', - myImages: '我的图片库' + myImages: '我的图片库', + dataCache: '数据缓存', + refreshCache: '刷新缓存', + refreshCacheDesc: '直接从数据库重新加载数据,清除内存缓存', + refreshSuccess: '缓存已刷新', + refreshFailed: '刷新失败' }, serverConfig: { title: '服务端配置', @@ -177,7 +182,12 @@ export const messages = { uploadIcon: 'Upload Icon', defaultIcon: 'Reset Default', myIcons: 'My Icons', - myImages: 'My Images' + myImages: 'My Images', + dataCache: 'Data Cache', + refreshCache: 'Refresh Cache', + refreshCacheDesc: 'Reload data directly from database, clear memory cache', + refreshSuccess: 'Cache refreshed', + refreshFailed: 'Refresh failed' }, serverConfig: { title: 'Server Config', diff --git a/src/views/SettingsView.vue b/src/views/SettingsView.vue index 6be756c..82e5151 100644 --- a/src/views/SettingsView.vue +++ b/src/views/SettingsView.vue @@ -23,6 +23,8 @@ const bgImagePresets = [ ] const isUploading = ref(false) +const isRefreshing = ref(false) +const refreshMessage = ref('') function onBgTypeChange(value) { settings.setBgType(value) @@ -205,6 +207,24 @@ function deleteUploadedIcon(id) { function resetFavicon() { settings.setFavicon('') } + +async function refreshCache() { + isRefreshing.value = true + refreshMessage.value = '' + try { + const res = await fetch('/api/cache/refresh', { method: 'POST' }) + const data = await res.json() + if (data.success) { + refreshMessage.value = t('settings.refreshSuccess') + } else { + refreshMessage.value = t('settings.refreshFailed') + } + setTimeout(() => { refreshMessage.value = '' }, 3000) + } catch (e) { + refreshMessage.value = t('settings.refreshFailed') + } + isRefreshing.value = false +} @@ -768,4 +806,40 @@ function resetFavicon() { .btn-reset:hover { background: #ccc; } + +.cache-desc { + font-size: 0.85rem; + color: var(--color-text-secondary); + margin-bottom: 0.75rem; +} + +.cache-actions { + display: flex; + align-items: center; + gap: 1rem; +} + +.btn-refresh { + background: var(--color-primary); + color: white; + padding: 0.5rem 1rem; + border-radius: 4px; + border: none; + cursor: pointer; + font-size: 0.9rem; +} + +.btn-refresh:hover { + opacity: 0.9; +} + +.btn-refresh:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.refresh-message { + font-size: 0.85rem; + color: var(--color-primary); +} \ No newline at end of file