Files
claude-relay-service/web/admin-spa/src/stores/settings.js

157 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { apiClient } from '@/config/api'
import i18n from '@/i18n'
export const useSettingsStore = defineStore('settings', () => {
// 状态
const oemSettings = ref({
siteName: 'Claude Relay Service',
siteIcon: '',
siteIconData: '',
showAdminButton: true, // 控制管理后台按钮的显示
updatedAt: null
})
const loading = ref(false)
const saving = ref(false)
// 移除自定义API请求方法使用统一的apiClient
// Actions
const loadOemSettings = async () => {
loading.value = true
try {
const result = await apiClient.get('/admin/oem-settings')
if (result && result.success) {
oemSettings.value = { ...oemSettings.value, ...result.data }
// 应用设置到页面
applyOemSettings()
}
return result
} catch (error) {
console.error('Failed to load OEM settings:', error)
throw error
} finally {
loading.value = false
}
}
const saveOemSettings = async (settings) => {
saving.value = true
try {
const result = await apiClient.put('/admin/oem-settings', settings)
if (result && result.success) {
oemSettings.value = { ...oemSettings.value, ...result.data }
// 应用设置到页面
applyOemSettings()
}
return result
} catch (error) {
console.error('Failed to save OEM settings:', error)
throw error
} finally {
saving.value = false
}
}
const resetOemSettings = async () => {
const defaultSettings = {
siteName: 'Claude Relay Service',
siteIcon: '',
siteIconData: '',
showAdminButton: true,
updatedAt: null
}
oemSettings.value = { ...defaultSettings }
return await saveOemSettings(defaultSettings)
}
// 应用OEM设置到页面
const applyOemSettings = () => {
// 更新页面标题
if (oemSettings.value.siteName) {
document.title = `${oemSettings.value.siteName} - ${i18n.global.t('header.adminPanel')}`
}
// 更新favicon
if (oemSettings.value.siteIconData || oemSettings.value.siteIcon) {
const favicon = document.querySelector('link[rel="icon"]') || document.createElement('link')
favicon.rel = 'icon'
favicon.href = oemSettings.value.siteIconData || oemSettings.value.siteIcon
if (!document.querySelector('link[rel="icon"]')) {
document.head.appendChild(favicon)
}
}
}
// 格式化日期时间
const formatDateTime = (dateString) => {
if (!dateString) return ''
const localeMap = { 'zh-cn': 'zh-CN', 'zh-tw': 'zh-TW', en: 'en-US' }
const currentLocale = localeMap[i18n.global.locale.value] || 'en-US'
return new Date(dateString).toLocaleString(currentLocale, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
})
}
// 验证文件上传
const validateIconFile = (file) => {
const errors = []
// 检查文件大小 (350KB)
if (file.size > 350 * 1024) {
errors.push(i18n.global.t('settings.validation.iconTooLarge'))
}
// 检查文件类型
const allowedTypes = ['image/x-icon', 'image/png', 'image/jpeg', 'image/jpg', 'image/svg+xml']
if (!allowedTypes.includes(file.type)) {
errors.push(i18n.global.t('settings.validation.iconTypeNotSupported'))
}
return {
isValid: errors.length === 0,
errors
}
}
// 将文件转换为Base64
const fileToBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = (e) => resolve(e.target.result)
reader.onerror = reject
reader.readAsDataURL(file)
})
}
return {
// State
oemSettings,
loading,
saving,
// Actions
loadOemSettings,
saveOemSettings,
resetOemSettings,
applyOemSettings,
formatDateTime,
validateIconFile,
fileToBase64
}
})