mirror of
https://github.com/ctwj/urldb.git
synced 2025-11-25 11:29:37 +08:00
updat: config
This commit is contained in:
@@ -353,10 +353,16 @@ func SystemConfigToPublicResponse(configs []entity.SystemConfig) map[string]inte
|
|||||||
response["telegram_qr_image"] = config.Value
|
response["telegram_qr_image"] = config.Value
|
||||||
case entity.ConfigKeyQrCodeStyle:
|
case entity.ConfigKeyQrCodeStyle:
|
||||||
response["qr_code_style"] = config.Value
|
response["qr_code_style"] = config.Value
|
||||||
// 跳过不需要返回给公众的配置
|
|
||||||
case entity.ConfigKeyAutoProcessReadyResources:
|
case entity.ConfigKeyAutoProcessReadyResources:
|
||||||
case entity.ConfigKeyAutoProcessInterval:
|
if val, err := strconv.ParseBool(config.Value); err == nil {
|
||||||
|
response["auto_process_ready_resources"] = val
|
||||||
|
}
|
||||||
case entity.ConfigKeyAutoTransferEnabled:
|
case entity.ConfigKeyAutoTransferEnabled:
|
||||||
|
if val, err := strconv.ParseBool(config.Value); err == nil {
|
||||||
|
response["auto_transfer_enabled"] = val
|
||||||
|
}
|
||||||
|
// 跳过不需要返回给公众的配置
|
||||||
|
case entity.ConfigKeyAutoProcessInterval:
|
||||||
case entity.ConfigKeyAutoTransferLimitDays:
|
case entity.ConfigKeyAutoTransferLimitDays:
|
||||||
case entity.ConfigKeyAutoTransferMinSpace:
|
case entity.ConfigKeyAutoTransferMinSpace:
|
||||||
case entity.ConfigKeyAutoFetchHotDramaEnabled:
|
case entity.ConfigKeyAutoFetchHotDramaEnabled:
|
||||||
|
|||||||
204
web/components/SystemConfigCacheInfo.vue
Normal file
204
web/components/SystemConfigCacheInfo.vue
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="showCacheInfo && isClient" class="fixed bottom-4 right-4 z-50 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 p-4 max-w-sm">
|
||||||
|
<div class="flex items-center justify-between mb-3">
|
||||||
|
<h3 class="text-sm font-semibold text-gray-900 dark:text-gray-100">系统配置缓存状态</h3>
|
||||||
|
<button
|
||||||
|
@click="showCacheInfo = false"
|
||||||
|
class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
|
||||||
|
>
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-2 text-xs">
|
||||||
|
<!-- 初始化状态 -->
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">初始化状态:</span>
|
||||||
|
<span :class="status.initialized ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'">
|
||||||
|
{{ status.initialized ? '已初始化' : '未初始化' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">加载状态:</span>
|
||||||
|
<span :class="status.isLoading ? 'text-blue-600 dark:text-blue-400' : 'text-gray-600 dark:text-gray-400'">
|
||||||
|
{{ status.isLoading ? '加载中...' : '空闲' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 缓存状态 -->
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">缓存状态:</span>
|
||||||
|
<span :class="status.isCacheValid ? 'text-green-600 dark:text-green-400' : 'text-orange-600 dark:text-orange-400'">
|
||||||
|
{{ status.isCacheValid ? '有效' : '无效/过期' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 缓存剩余时间 -->
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">缓存剩余:</span>
|
||||||
|
<span class="text-gray-900 dark:text-gray-100">
|
||||||
|
{{ formatTime(status.cacheTimeRemaining) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 最后获取时间 -->
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">最后更新:</span>
|
||||||
|
<span class="text-gray-900 dark:text-gray-100">
|
||||||
|
{{ formatLastFetch(status.lastFetchTime) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 错误信息 -->
|
||||||
|
<div v-if="status.error" class="flex justify-between">
|
||||||
|
<span class="text-gray-600 dark:text-gray-400">错误:</span>
|
||||||
|
<span class="text-red-600 dark:text-red-400">
|
||||||
|
{{ status.error }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<div class="mt-4 flex gap-2">
|
||||||
|
<button
|
||||||
|
@click="refreshCache"
|
||||||
|
:disabled="status.isLoading"
|
||||||
|
class="flex-1 px-2 py-1 text-xs bg-blue-500 text-white rounded hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
<i class="fas fa-sync-alt mr-1"></i>
|
||||||
|
刷新
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click="clearCache"
|
||||||
|
class="flex-1 px-2 py-1 text-xs bg-red-500 text-white rounded hover:bg-red-600"
|
||||||
|
>
|
||||||
|
<i class="fas fa-trash mr-1"></i>
|
||||||
|
清除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 浮动按钮(仅在开发环境和客户端显示) -->
|
||||||
|
<button
|
||||||
|
v-if="isDev && isClient"
|
||||||
|
@click="showCacheInfo = !showCacheInfo"
|
||||||
|
class="fixed bottom-4 right-4 z-40 w-12 h-12 bg-purple-500 text-white rounded-full shadow-lg hover:bg-purple-600 transition-colors flex items-center justify-center"
|
||||||
|
title="系统配置缓存信息"
|
||||||
|
>
|
||||||
|
<i class="fas fa-database"></i>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||||
|
import { useSystemConfigStore } from '~/stores/systemConfig'
|
||||||
|
|
||||||
|
const systemConfigStore = useSystemConfigStore()
|
||||||
|
const showCacheInfo = ref(false)
|
||||||
|
|
||||||
|
// 检查是否为开发环境
|
||||||
|
const isDev = computed(() => {
|
||||||
|
return process.env.NODE_ENV === 'development'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 检查是否为客户端
|
||||||
|
const isClient = computed(() => {
|
||||||
|
return process.client
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取状态信息 - 直接访问store的响应式状态以确保正确更新
|
||||||
|
const status = computed(() => ({
|
||||||
|
initialized: systemConfigStore.initialized,
|
||||||
|
isLoading: systemConfigStore.isLoading,
|
||||||
|
error: systemConfigStore.error,
|
||||||
|
lastFetchTime: systemConfigStore.lastFetchTime,
|
||||||
|
cacheTimeRemaining: systemConfigStore.cacheTimeRemaining,
|
||||||
|
isCacheValid: systemConfigStore.isCacheValid
|
||||||
|
}))
|
||||||
|
|
||||||
|
// 格式化时间显示
|
||||||
|
const formatTime = (seconds: number): string => {
|
||||||
|
if (seconds <= 0) return '已过期'
|
||||||
|
|
||||||
|
const minutes = Math.floor(seconds / 60)
|
||||||
|
const remainingSeconds = seconds % 60
|
||||||
|
|
||||||
|
if (minutes > 0) {
|
||||||
|
return `${minutes}分${remainingSeconds}秒`
|
||||||
|
} else {
|
||||||
|
return `${remainingSeconds}秒`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化最后获取时间
|
||||||
|
const formatLastFetch = (timestamp: number): string => {
|
||||||
|
if (!timestamp) return '从未'
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
const diff = now - timestamp
|
||||||
|
|
||||||
|
if (diff < 60 * 1000) {
|
||||||
|
return '刚刚'
|
||||||
|
} else if (diff < 60 * 60 * 1000) {
|
||||||
|
const minutes = Math.floor(diff / (60 * 1000))
|
||||||
|
return `${minutes}分钟前`
|
||||||
|
} else if (diff < 24 * 60 * 60 * 1000) {
|
||||||
|
const hours = Math.floor(diff / (60 * 60 * 1000))
|
||||||
|
return `${hours}小时前`
|
||||||
|
} else {
|
||||||
|
const date = new Date(timestamp)
|
||||||
|
return date.toLocaleString('zh-CN', {
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新缓存
|
||||||
|
const refreshCache = async () => {
|
||||||
|
try {
|
||||||
|
await systemConfigStore.refreshConfig()
|
||||||
|
console.log('[CacheInfo] 手动刷新缓存完成')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[CacheInfo] 刷新缓存失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除缓存
|
||||||
|
const clearCache = () => {
|
||||||
|
systemConfigStore.clearCache()
|
||||||
|
console.log('[CacheInfo] 手动清除缓存完成')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 键盘快捷键支持
|
||||||
|
const handleKeydown = (e: KeyboardEvent) => {
|
||||||
|
// Ctrl+Shift+C 显示/隐藏缓存信息(仅在开发环境)
|
||||||
|
if (isDev.value && e.ctrlKey && e.shiftKey && e.key === 'C') {
|
||||||
|
e.preventDefault()
|
||||||
|
showCacheInfo.value = !showCacheInfo.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (isClient.value) {
|
||||||
|
document.addEventListener('keydown', handleKeydown)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (isClient.value) {
|
||||||
|
document.removeEventListener('keydown', handleKeydown)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 添加一些动画效果 */
|
||||||
|
.transition-colors {
|
||||||
|
transition: color 0.2s, background-color 0.2s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -301,25 +301,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 开发环境缓存信息组件 -->
|
||||||
|
<SystemConfigCacheInfo />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
// 获取运行时配置
|
// 获取运行时配置
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
|
|
||||||
import { useResourceApi, useStatsApi, usePanApi, useSystemConfigApi, usePublicSystemConfigApi, useSearchStatsApi } from '~/composables/useApi'
|
import { useResourceApi, useStatsApi, usePanApi, useSearchStatsApi } from '~/composables/useApi'
|
||||||
|
import SystemConfigCacheInfo from '~/components/SystemConfigCacheInfo.vue'
|
||||||
|
|
||||||
const resourceApi = useResourceApi()
|
const resourceApi = useResourceApi()
|
||||||
const statsApi = useStatsApi()
|
const statsApi = useStatsApi()
|
||||||
const panApi = usePanApi()
|
const panApi = usePanApi()
|
||||||
const publicSystemConfigApi = usePublicSystemConfigApi()
|
|
||||||
|
|
||||||
// 路由参数已通过自动导入提供,直接使用
|
// 路由参数已通过自动导入提供,直接使用
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// 页面元数据 - 使用系统配置的标题
|
// 使用系统配置Store(带缓存支持)
|
||||||
const { data: systemConfigData } = await useAsyncData('systemConfig', () => publicSystemConfigApi.getPublicSystemConfig())
|
const { useSystemConfigStore } = await import('~/stores/systemConfig')
|
||||||
|
const systemConfigStore = useSystemConfigStore()
|
||||||
|
|
||||||
|
// 初始化系统配置(会自动使用缓存)
|
||||||
|
await systemConfigStore.initConfig()
|
||||||
|
|
||||||
|
// 检查并自动刷新即将过期的缓存
|
||||||
|
await systemConfigStore.checkAndRefreshCache()
|
||||||
|
|
||||||
// 获取平台名称的辅助函数
|
// 获取平台名称的辅助函数
|
||||||
const getPlatformName = (platformId: string) => {
|
const getPlatformName = (platformId: string) => {
|
||||||
@@ -329,12 +339,11 @@ const getPlatformName = (platformId: string) => {
|
|||||||
return platform?.name || ''
|
return platform?.name || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动态生成页面标题和meta信息 - 修复安全访问问题
|
// 动态生成页面标题和meta信息 - 使用缓存的系统配置
|
||||||
const pageTitle = computed(() => {
|
const pageTitle = computed(() => {
|
||||||
try {
|
try {
|
||||||
const config = systemConfigData.value as any
|
const config = systemConfigStore.config
|
||||||
const siteTitle = (config?.data?.site_title) ? config.data.site_title :
|
const siteTitle = config?.site_title || '老九网盘资源数据库'
|
||||||
(config?.site_title) ? config.site_title : '老九网盘资源数据库'
|
|
||||||
const searchKeyword = (route.query?.search) ? route.query.search as string : ''
|
const searchKeyword = (route.query?.search) ? route.query.search as string : ''
|
||||||
const platformId = (route.query?.platform) ? route.query.platform as string : ''
|
const platformId = (route.query?.platform) ? route.query.platform as string : ''
|
||||||
const platformName = getPlatformName(platformId)
|
const platformName = getPlatformName(platformId)
|
||||||
@@ -360,9 +369,8 @@ const pageTitle = computed(() => {
|
|||||||
|
|
||||||
const pageDescription = computed(() => {
|
const pageDescription = computed(() => {
|
||||||
try {
|
try {
|
||||||
const config = systemConfigData.value as any
|
const config = systemConfigStore.config
|
||||||
const baseDescription = (config?.data?.site_description) ? config.data.site_description :
|
const baseDescription = config?.site_description || '老九网盘资源管理系统, 一个现代化的网盘资源数据库,支持多网盘自动化转存分享,支持百度网盘,阿里云盘,夸克网盘, 天翼云盘,迅雷云盘,123云盘,115网盘,UC网盘'
|
||||||
(config?.site_description) ? config.site_description : '老九网盘资源管理系统, 一个现代化的网盘资源数据库,支持多网盘自动化转存分享,支持百度网盘,阿里云盘,夸克网盘, 天翼云盘,迅雷云盘,123云盘,115网盘,UC网盘'
|
|
||||||
|
|
||||||
const searchKeyword = (route.query && route.query.search) ? route.query.search as string : ''
|
const searchKeyword = (route.query && route.query.search) ? route.query.search as string : ''
|
||||||
const platformId = (route.query && route.query.platform) ? route.query.platform as string : ''
|
const platformId = (route.query && route.query.platform) ? route.query.platform as string : ''
|
||||||
@@ -388,9 +396,8 @@ const pageDescription = computed(() => {
|
|||||||
|
|
||||||
const pageKeywords = computed(() => {
|
const pageKeywords = computed(() => {
|
||||||
try {
|
try {
|
||||||
const config = systemConfigData.value as any
|
const config = systemConfigStore.config
|
||||||
const baseKeywords = (config?.data?.keywords) ? config.data.keywords :
|
const baseKeywords = config?.keywords || '网盘资源,资源管理,数据库'
|
||||||
(config?.keywords) ? config.keywords : '网盘资源,资源管理,数据库'
|
|
||||||
|
|
||||||
const searchKeyword = (route.query && route.query.search) ? route.query.search as string : ''
|
const searchKeyword = (route.query && route.query.search) ? route.query.search as string : ''
|
||||||
const platformId = (route.query && route.query.platform) ? route.query.platform as string : ''
|
const platformId = (route.query && route.query.platform) ? route.query.platform as string : ''
|
||||||
@@ -474,7 +481,7 @@ onBeforeMount(async () => {
|
|||||||
|
|
||||||
// 监听路由变化和系统配置数据,当搜索条件或配置改变时更新SEO
|
// 监听路由变化和系统配置数据,当搜索条件或配置改变时更新SEO
|
||||||
watch(
|
watch(
|
||||||
() => [route.query?.search, route.query?.platform, systemConfigData.value],
|
() => [route.query?.search, route.query?.platform, systemConfigStore.config],
|
||||||
() => {
|
() => {
|
||||||
// 使用nextTick确保响应式数据已更新
|
// 使用nextTick确保响应式数据已更新
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@@ -626,7 +633,7 @@ const safeResources = computed(() => {
|
|||||||
})
|
})
|
||||||
const safeStats = computed(() => (statsData.value as any) || { total_resources: 0, total_categories: 0, total_tags: 0, total_views: 0, today_resources: 0 })
|
const safeStats = computed(() => (statsData.value as any) || { total_resources: 0, total_categories: 0, total_tags: 0, total_views: 0, today_resources: 0 })
|
||||||
const platforms = computed(() => (platformsData.value as any) || [])
|
const platforms = computed(() => (platformsData.value as any) || [])
|
||||||
const systemConfig = computed(() => (systemConfigData.value as any)?.data || { site_title: '老九网盘资源数据库' })
|
const systemConfig = computed(() => systemConfigStore.config || { site_title: '老九网盘资源数据库' })
|
||||||
const safeLoading = computed(() => pending.value)
|
const safeLoading = computed(() => pending.value)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -483,6 +483,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 开发环境缓存信息组件 -->
|
||||||
|
<SystemConfigCacheInfo />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -495,6 +498,7 @@ import { useNotification } from 'naive-ui'
|
|||||||
|
|
||||||
// 导入API
|
// 导入API
|
||||||
import { useResourceApi } from '~/composables/useApi'
|
import { useResourceApi } from '~/composables/useApi'
|
||||||
|
import SystemConfigCacheInfo from '~/components/SystemConfigCacheInfo.vue'
|
||||||
|
|
||||||
// 导入组件
|
// 导入组件
|
||||||
import SearchButton from '~/components/SearchButton.vue'
|
import SearchButton from '~/components/SearchButton.vue'
|
||||||
@@ -527,8 +531,17 @@ const hotResources = ref<any[]>([])
|
|||||||
const hotResourcesLoading = ref(true)
|
const hotResourcesLoading = ref(true)
|
||||||
|
|
||||||
// 获取系统配置
|
// 获取系统配置
|
||||||
const { data: systemConfigData } = await useAsyncData('systemConfig', () => publicSystemConfigApi.getPublicSystemConfig())
|
// 使用系统配置Store(带缓存支持)
|
||||||
const systemConfig = computed(() => (systemConfigData.value as any)?.data || { site_title: '老九网盘资源数据库' })
|
const { useSystemConfigStore } = await import('~/stores/systemConfig')
|
||||||
|
const systemConfigStore = useSystemConfigStore()
|
||||||
|
|
||||||
|
// 初始化系统配置(会自动使用缓存)
|
||||||
|
await systemConfigStore.initConfig()
|
||||||
|
|
||||||
|
// 检查并自动刷新即将过期的缓存
|
||||||
|
await systemConfigStore.checkAndRefreshCache()
|
||||||
|
|
||||||
|
const systemConfig = computed(() => systemConfigStore.config || { site_title: '老九网盘资源数据库' })
|
||||||
|
|
||||||
// 获取资源数据
|
// 获取资源数据
|
||||||
const { data: resourcesData, error: resourcesError } = await useAsyncData(
|
const { data: resourcesData, error: resourcesError } = await useAsyncData(
|
||||||
|
|||||||
@@ -2,38 +2,265 @@ import { defineStore } from 'pinia'
|
|||||||
import { useApiFetch } from '~/composables/useApiFetch'
|
import { useApiFetch } from '~/composables/useApiFetch'
|
||||||
import { parseApiResponse } from '~/composables/useApi'
|
import { parseApiResponse } from '~/composables/useApi'
|
||||||
|
|
||||||
|
// 缓存配置
|
||||||
|
const CACHE_KEY = 'system-config-cache'
|
||||||
|
const CACHE_TIMESTAMP_KEY = 'system-config-cache-timestamp'
|
||||||
|
const CACHE_DURATION = 30 * 60 * 1000 // 30分钟缓存
|
||||||
|
|
||||||
|
// 安全的客户端检查函数
|
||||||
|
const isClient = () => {
|
||||||
|
return typeof process !== 'undefined' && process.client
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CacheData {
|
||||||
|
config: any
|
||||||
|
timestamp: number
|
||||||
|
version?: string
|
||||||
|
}
|
||||||
|
|
||||||
export const useSystemConfigStore = defineStore('systemConfig', {
|
export const useSystemConfigStore = defineStore('systemConfig', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
config: null as any,
|
config: null as any,
|
||||||
initialized: false
|
initialized: false,
|
||||||
|
lastFetchTime: 0 as number,
|
||||||
|
isLoading: false as boolean,
|
||||||
|
error: null as string | null
|
||||||
}),
|
}),
|
||||||
actions: {
|
|
||||||
async initConfig(force = false, useAdminApi = false) {
|
getters: {
|
||||||
if (this.initialized && !force) return
|
// 检查缓存是否有效
|
||||||
|
isCacheValid(): boolean {
|
||||||
|
if (!isClient()) return false
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const cacheData = localStorage.getItem(CACHE_KEY)
|
||||||
|
const cacheTimestamp = localStorage.getItem(CACHE_TIMESTAMP_KEY)
|
||||||
|
|
||||||
|
if (!cacheData || !cacheTimestamp) return false
|
||||||
|
|
||||||
|
const timestamp = parseInt(cacheTimestamp)
|
||||||
|
const now = Date.now()
|
||||||
|
|
||||||
|
// 检查缓存是否过期
|
||||||
|
const isValid = (now - timestamp) < CACHE_DURATION
|
||||||
|
|
||||||
|
console.log(`[SystemConfig] 缓存检查: ${isValid ? '有效' : '已过期'}, 剩余时间: ${Math.max(0, CACHE_DURATION - (now - timestamp)) / 1000 / 60}分钟`)
|
||||||
|
|
||||||
|
return isValid
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[SystemConfig] 缓存检查失败:', error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取缓存的数据
|
||||||
|
cachedConfig(): any {
|
||||||
|
if (!isClient() || !this.isCacheValid) return null
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cacheData = localStorage.getItem(CACHE_KEY)
|
||||||
|
if (cacheData) {
|
||||||
|
const parsed = JSON.parse(cacheData) as CacheData
|
||||||
|
console.log('[SystemConfig] 使用缓存数据')
|
||||||
|
return parsed.config
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[SystemConfig] 读取缓存失败:', error)
|
||||||
|
this.clearCache()
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取缓存剩余时间(秒)
|
||||||
|
cacheTimeRemaining(): number {
|
||||||
|
if (!isClient()) return 0
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cacheTimestamp = localStorage.getItem(CACHE_TIMESTAMP_KEY)
|
||||||
|
if (!cacheTimestamp) return 0
|
||||||
|
|
||||||
|
const timestamp = parseInt(cacheTimestamp)
|
||||||
|
const now = Date.now()
|
||||||
|
const remaining = Math.max(0, CACHE_DURATION - (now - timestamp))
|
||||||
|
|
||||||
|
return Math.floor(remaining / 1000)
|
||||||
|
} catch (error) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
// 清除缓存
|
||||||
|
clearCache() {
|
||||||
|
if (!isClient()) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
localStorage.removeItem(CACHE_KEY)
|
||||||
|
localStorage.removeItem(CACHE_TIMESTAMP_KEY)
|
||||||
|
console.log('[SystemConfig] 缓存已清除')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[SystemConfig] 清除缓存失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 保存到缓存
|
||||||
|
saveToCache(config: any) {
|
||||||
|
if (!isClient()) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cacheData: CacheData = {
|
||||||
|
config,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
version: '1.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData))
|
||||||
|
localStorage.setItem(CACHE_TIMESTAMP_KEY, cacheData.timestamp.toString())
|
||||||
|
|
||||||
|
console.log('[SystemConfig] 配置已缓存,有效期30分钟')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[SystemConfig] 保存缓存失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 从缓存加载
|
||||||
|
loadFromCache(): boolean {
|
||||||
|
if (!isClient()) return false
|
||||||
|
|
||||||
|
const cachedConfig = this.cachedConfig
|
||||||
|
if (cachedConfig) {
|
||||||
|
this.config = cachedConfig
|
||||||
|
this.initialized = true
|
||||||
|
|
||||||
|
// 从缓存时间戳设置 lastFetchTime
|
||||||
|
const cacheTimestamp = localStorage.getItem(CACHE_TIMESTAMP_KEY)
|
||||||
|
if (cacheTimestamp) {
|
||||||
|
this.lastFetchTime = parseInt(cacheTimestamp)
|
||||||
|
} else {
|
||||||
|
this.lastFetchTime = Date.now()
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[SystemConfig] 从缓存加载配置成功')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
// 初始化配置(带缓存支持)
|
||||||
|
async initConfig(force = false, useAdminApi = false) {
|
||||||
|
// 如果已经初始化且不强制刷新,直接返回
|
||||||
|
if (this.initialized && !force) {
|
||||||
|
console.log('[SystemConfig] 配置已初始化,直接返回')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果不强制刷新,先尝试从缓存加载
|
||||||
|
if (!force && this.loadFromCache()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防止重复请求
|
||||||
|
if (this.isLoading) {
|
||||||
|
console.log('[SystemConfig] 正在加载中,等待完成...')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isLoading = true
|
||||||
|
this.error = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log(`[SystemConfig] 开始获取配置 (force: ${force}, useAdminApi: ${useAdminApi})`)
|
||||||
|
|
||||||
// 根据上下文选择API:管理员页面使用管理员API,其他页面使用公开API
|
// 根据上下文选择API:管理员页面使用管理员API,其他页面使用公开API
|
||||||
const apiUrl = useAdminApi ? '/system/config' : '/public/system-config'
|
const apiUrl = useAdminApi ? '/system/config' : '/public/system-config'
|
||||||
const response = await useApiFetch(apiUrl)
|
const response = await useApiFetch(apiUrl)
|
||||||
// console.log('Store API响应:', response) // 调试信息
|
|
||||||
|
|
||||||
// 使用parseApiResponse正确解析API响应
|
// 使用parseApiResponse正确解析API响应
|
||||||
const data = parseApiResponse(response)
|
const data = parseApiResponse(response)
|
||||||
// console.log('Store 处理后的数据:', data) // 调试信息
|
|
||||||
// console.log('Store 自动处理状态:', data.auto_process_ready_resources)
|
|
||||||
// console.log('Store 自动转存状态:', data.auto_transfer_enabled)
|
|
||||||
|
|
||||||
this.config = data
|
this.config = data
|
||||||
this.initialized = true
|
this.initialized = true
|
||||||
} catch (e) {
|
this.lastFetchTime = Date.now()
|
||||||
console.error('Store 获取系统配置失败:', e) // 调试信息
|
this.isLoading = false
|
||||||
// 可根据需要处理错误
|
|
||||||
|
// 保存到缓存(仅在客户端)
|
||||||
|
this.saveToCache(data)
|
||||||
|
|
||||||
|
console.log('[SystemConfig] 配置获取并缓存成功')
|
||||||
|
console.log('[SystemConfig] 自动处理状态:', data.auto_process_ready_resources)
|
||||||
|
console.log('[SystemConfig] 自动转存状态:', data.auto_transfer_enabled)
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.isLoading = false
|
||||||
|
this.error = error instanceof Error ? error.message : '获取配置失败'
|
||||||
|
console.error('[SystemConfig] 获取系统配置失败:', error)
|
||||||
|
|
||||||
|
// 如果网络请求失败,尝试使用过期的缓存作为降级方案
|
||||||
|
if (!force) {
|
||||||
|
try {
|
||||||
|
const expiredCache = localStorage.getItem(CACHE_KEY)
|
||||||
|
if (expiredCache) {
|
||||||
|
const parsed = JSON.parse(expiredCache) as CacheData
|
||||||
|
this.config = parsed.config
|
||||||
|
this.initialized = true
|
||||||
|
console.log('[SystemConfig] 网络请求失败,使用过期缓存作为降级方案')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (cacheError) {
|
||||||
|
console.error('[SystemConfig] 降级缓存方案也失败:', cacheError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.config = null
|
this.config = null
|
||||||
this.initialized = false
|
this.initialized = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 强制刷新配置
|
||||||
|
async refreshConfig(useAdminApi = false) {
|
||||||
|
console.log('[SystemConfig] 强制刷新配置')
|
||||||
|
this.clearCache()
|
||||||
|
await this.initConfig(true, useAdminApi)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查并自动刷新缓存(如果即将过期)
|
||||||
|
async checkAndRefreshCache(useAdminApi = false) {
|
||||||
|
if (!isClient()) return
|
||||||
|
|
||||||
|
const timeRemaining = this.cacheTimeRemaining
|
||||||
|
|
||||||
|
// 如果缓存剩余时间少于5分钟,自动刷新
|
||||||
|
if (timeRemaining > 0 && timeRemaining < 5 * 60) {
|
||||||
|
console.log(`[SystemConfig] 缓存即将过期(剩余${timeRemaining}秒),自动刷新`)
|
||||||
|
await this.refreshConfig(useAdminApi)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 手动设置配置(用于管理员更新配置后)
|
||||||
setConfig(newConfig: any) {
|
setConfig(newConfig: any) {
|
||||||
this.config = newConfig
|
this.config = newConfig
|
||||||
this.initialized = true
|
this.initialized = true
|
||||||
|
this.lastFetchTime = Date.now()
|
||||||
|
|
||||||
|
// 更新缓存
|
||||||
|
this.saveToCache(newConfig)
|
||||||
|
|
||||||
|
console.log('[SystemConfig] 配置已手动更新并缓存')
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取配置状态信息
|
||||||
|
getStatus() {
|
||||||
|
return {
|
||||||
|
initialized: this.initialized,
|
||||||
|
isLoading: this.isLoading,
|
||||||
|
error: this.error,
|
||||||
|
lastFetchTime: this.lastFetchTime,
|
||||||
|
cacheTimeRemaining: this.cacheTimeRemaining,
|
||||||
|
isCacheValid: this.isCacheValid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Reference in New Issue
Block a user