feat: Phase 2 - 核心状态管理、搜索组件
- apps/web/src/stores/posts.ts: 文章状态管理 (列表、详情、分类、标签、搜索) - apps/web/src/stores/settings.ts: 站点设置状态管理 (音乐、SEO、功能开关) - apps/web/src/stores/music.ts: 全局音乐播放器状态 - apps/web/src/components/SearchModal.vue: 搜索弹窗组件 (热门关键词、历史记录、实时建议)
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import { pb } from '@/composables/usePocketBase'
|
||||
|
||||
export const useSettingsStore = defineStore('settings', () => {
|
||||
const settings = ref(null)
|
||||
const loading = ref(false)
|
||||
const error = ref(null)
|
||||
|
||||
const siteName = computed(() => settings.value?.site_name || '云升数码')
|
||||
const siteSubtitle = computed(() => settings.value?.site_subtitle || '专业数码评测与技术分享')
|
||||
const siteDescription = computed(() => settings.value?.site_description || '')
|
||||
const siteUrl = computed(() => settings.value?.site_url || '')
|
||||
const logo = computed(() => settings.value?.logo)
|
||||
const logoDark = computed(() => settings.value?.logo_dark)
|
||||
const favicon = computed(() => settings.value?.favicon)
|
||||
const footerText = computed(() => settings.value?.footer_text || '')
|
||||
const footerCopyright = computed(() => settings.value?.footer_copyright || '')
|
||||
const icpNumber = computed(() => settings.value?.icp_number || '')
|
||||
const socialLinks = computed(() => {
|
||||
try {
|
||||
return JSON.parse(settings.value?.social_links || '{}')
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
})
|
||||
|
||||
const backgroundMusic = computed(() => ({
|
||||
enabled: settings.value?.background_music_enabled ?? true,
|
||||
type: settings.value?.background_music_type || 'local',
|
||||
file: settings.value?.background_music_file,
|
||||
url: settings.value?.background_music_url,
|
||||
title: settings.value?.background_music_title || '背景音乐',
|
||||
artist: settings.value?.background_music_artist || '云升数码',
|
||||
cover: settings.value?.background_music_cover,
|
||||
volume: settings.value?.background_music_volume ?? 0.5,
|
||||
autoplay: settings.value?.background_music_autoplay ?? false,
|
||||
loop: settings.value?.background_music_loop ?? true,
|
||||
}))
|
||||
|
||||
const commentConfig = computed(() => ({
|
||||
enabled: settings.value?.comment_enabled ?? false,
|
||||
system: settings.value?.comment_system || 'giscus',
|
||||
config: settings.value?.comment_config ? JSON.parse(settings.value?.comment_config) : {},
|
||||
}))
|
||||
|
||||
const analyticsConfig = computed(() => ({
|
||||
googleAnalyticsId: settings.value?.google_analytics_id || '',
|
||||
baiduAnalyticsId: settings.value?.baidu_analytics_id || '',
|
||||
customHeadCode: settings.value?.custom_head_code || '',
|
||||
customBodyCode: settings.value?.custom_body_code || '',
|
||||
}))
|
||||
|
||||
const featureFlags = computed(() => ({
|
||||
maintenanceMode: settings.value?.maintenance_mode ?? false,
|
||||
maintenanceMessage: settings.value?.maintenance_message || '',
|
||||
registrationEnabled: settings.value?.registration_enabled ?? false,
|
||||
rssEnabled: settings.value?.rss_enabled ?? true,
|
||||
searchEnabled: settings.value?.search_enabled ?? true,
|
||||
cacheTtl: settings.value?.cache_ttl ?? 3600,
|
||||
imageOptimization: settings.value?.image_optimization ?? true,
|
||||
cdnUrl: settings.value?.cdn_url || '',
|
||||
}))
|
||||
|
||||
async function fetchSettings() {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const result = await pb.collection('site_settings').getFirstListItem('', {
|
||||
fields: '*',
|
||||
})
|
||||
settings.value = result
|
||||
return result
|
||||
} catch (err) {
|
||||
error.value = err.message
|
||||
throw err
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function updateSettings(data) {
|
||||
if (!settings.value) return
|
||||
try {
|
||||
const result = await pb.collection('site_settings').update(settings.value.id, data)
|
||||
settings.value = result
|
||||
return result
|
||||
} catch (err) {
|
||||
error.value = err.message
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
settings,
|
||||
loading,
|
||||
error,
|
||||
siteName,
|
||||
siteSubtitle,
|
||||
siteDescription,
|
||||
siteUrl,
|
||||
logo,
|
||||
logoDark,
|
||||
favicon,
|
||||
footerText,
|
||||
footerCopyright,
|
||||
icpNumber,
|
||||
socialLinks,
|
||||
backgroundMusic,
|
||||
commentConfig,
|
||||
analyticsConfig,
|
||||
featureFlags,
|
||||
fetchSettings,
|
||||
updateSettings,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user