feat: stores 部分接入 i18n(auth/settings/apistats/dashboard/clients:标题、错误与日期提示本地化)

This commit is contained in:
Wangnov
2025-09-10 18:04:26 +08:00
parent 5f5826ce56
commit 01eadea10b
5 changed files with 53 additions and 35 deletions

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { apiStatsClient } from '@/config/apiStats' import { apiStatsClient } from '@/config/apiStats'
import i18n from '@/i18n'
export const useApiStatsStore = defineStore('apistats', () => { export const useApiStatsStore = defineStore('apistats', () => {
// 状态 // 状态
@@ -93,7 +94,7 @@ export const useApiStatsStore = defineStore('apistats', () => {
} }
if (!apiKey.value.trim()) { if (!apiKey.value.trim()) {
error.value = '请输入 API Key' error.value = i18n.global.t('apiStats.enterApiKey')
return return
} }
@@ -125,14 +126,18 @@ export const useApiStatsStore = defineStore('apistats', () => {
// 更新 URL // 更新 URL
updateURL() updateURL()
} else { } else {
throw new Error(statsResult.message || '查询失败') throw new Error(
statsResult.message || i18n.global.t('common.errors.requestFailed', { status: 500 })
)
} }
} else { } else {
throw new Error(idResult.message || '获取 API Key ID 失败') throw new Error(
idResult.message || i18n.global.t('common.errors.requestFailed', { status: 500 })
)
} }
} catch (err) { } catch (err) {
console.error('Query stats error:', err) console.error('Query stats error:', err)
error.value = err.message || '查询统计数据失败,请检查您的 API Key 是否正确' error.value = err.message || i18n.global.t('apiStats.errors.queryStatsFailed')
statsData.value = null statsData.value = null
modelStats.value = [] modelStats.value = []
apiId.value = null apiId.value = null
@@ -209,7 +214,7 @@ export const useApiStatsStore = defineStore('apistats', () => {
if (result.success) { if (result.success) {
modelStats.value = result.data || [] modelStats.value = result.data || []
} else { } else {
throw new Error(result.message || '加载模型统计失败') throw new Error(result.message || i18n.global.t('apiStats.errors.loadModelStatsFailed'))
} }
} catch (err) { } catch (err) {
console.error('Load model stats error:', err) console.error('Load model stats error:', err)
@@ -266,11 +271,13 @@ export const useApiStatsStore = defineStore('apistats', () => {
// 清除错误信息 // 清除错误信息
error.value = '' error.value = ''
} else { } else {
throw new Error(result.message || '查询失败') throw new Error(
result.message || i18n.global.t('common.errors.requestFailed', { status: 500 })
)
} }
} catch (err) { } catch (err) {
console.error('Load stats with apiId error:', err) console.error('Load stats with apiId error:', err)
error.value = err.message || '查询统计数据失败' error.value = err.message || i18n.global.t('apiStats.errors.queryStatsFailed')
statsData.value = null statsData.value = null
modelStats.value = [] modelStats.value = []
} finally { } finally {
@@ -330,7 +337,7 @@ export const useApiStatsStore = defineStore('apistats', () => {
async function queryBatchStats() { async function queryBatchStats() {
const keys = parseApiKeys() const keys = parseApiKeys()
if (keys.length === 0) { if (keys.length === 0) {
error.value = '请输入至少一个有效的 API Key' error.value = i18n.global.t('apiStats.errors.enterAtLeastOneKey')
return return
} }
@@ -384,11 +391,11 @@ export const useApiStatsStore = defineStore('apistats', () => {
// 更新 URL // 更新 URL
updateBatchURL() updateBatchURL()
} else { } else {
throw new Error(batchResult.message || '批量查询失败') throw new Error(batchResult.message || i18n.global.t('apiStats.errors.batchQueryFailed'))
} }
} catch (err) { } catch (err) {
console.error('Batch query error:', err) console.error('Batch query error:', err)
error.value = err.message || '批量查询统计数据失败' error.value = err.message || i18n.global.t('apiStats.errors.batchQueryFailed')
aggregatedStats.value = null aggregatedStats.value = null
individualStats.value = [] individualStats.value = []
} finally { } finally {
@@ -408,7 +415,7 @@ export const useApiStatsStore = defineStore('apistats', () => {
if (result.success) { if (result.success) {
modelStats.value = result.data || [] modelStats.value = result.data || []
} else { } else {
throw new Error(result.message || '加载批量模型统计失败') throw new Error(result.message || i18n.global.t('apiStats.errors.batchModelStatsFailed'))
} }
} catch (err) { } catch (err) {
console.error('Load batch model stats error:', err) console.error('Load batch model stats error:', err)

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import router from '@/router' import router from '@/router'
import i18n from '@/i18n'
import { apiClient } from '@/config/api' import { apiClient } from '@/config/api'
export const useAuthStore = defineStore('auth', () => { export const useAuthStore = defineStore('auth', () => {
@@ -39,10 +40,10 @@ export const useAuthStore = defineStore('auth', () => {
await router.push('/dashboard') await router.push('/dashboard')
} else { } else {
loginError.value = result.message || '登录失败' loginError.value = result.message || i18n.global.t('login.loginFailed')
} }
} catch (error) { } catch (error) {
loginError.value = error.message || '登录失败,请检查用户名和密码' loginError.value = error.message || i18n.global.t('login.loginFailedCheck')
} finally { } finally {
loginLoading.value = false loginLoading.value = false
} }
@@ -102,7 +103,7 @@ export const useAuthStore = defineStore('auth', () => {
// 设置页面标题 // 设置页面标题
if (result.data.siteName) { if (result.data.siteName) {
document.title = `${result.data.siteName} - 管理后台` document.title = `${result.data.siteName} - ${i18n.global.t('header.adminPanel')}`
} }
} }
} catch (error) { } catch (error) {

View File

@@ -1,5 +1,6 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { apiClient } from '@/config/api' import { apiClient } from '@/config/api'
import i18n from '@/i18n'
export const useClientsStore = defineStore('clients', { export const useClientsStore = defineStore('clients', {
state: () => ({ state: () => ({
@@ -24,13 +25,13 @@ export const useClientsStore = defineStore('clients', {
if (response.success) { if (response.success) {
this.supportedClients = response.data || [] this.supportedClients = response.data || []
} else { } else {
this.error = response.message || '加载支持的客户端失败' this.error = response.message || i18n.global.t('common.errors.loadSupportedClientsFailed')
console.error('Failed to load supported clients:', this.error) console.error('Failed to load supported clients:', this.error)
} }
return this.supportedClients return this.supportedClients
} catch (error) { } catch (error) {
this.error = error.message || '加载支持的客户端失败' this.error = error.message || i18n.global.t('common.errors.loadSupportedClientsFailed')
console.error('Error loading supported clients:', error) console.error('Error loading supported clients:', error)
return [] return []
} finally { } finally {

View File

@@ -2,6 +2,8 @@ import { defineStore } from 'pinia'
import { ref, computed } from 'vue' import { ref, computed } from 'vue'
import { apiClient } from '@/config/api' import { apiClient } from '@/config/api'
import { showToast } from '@/utils/toast' import { showToast } from '@/utils/toast'
import i18n from '@/i18n'
import i18n from '@/i18n'
export const useDashboardStore = defineStore('dashboard', () => { export const useDashboardStore = defineStore('dashboard', () => {
// 状态 // 状态
@@ -68,9 +70,9 @@ export const useDashboardStore = defineStore('dashboard', () => {
customEnd: '', customEnd: '',
customRange: null, customRange: null,
presetOptions: [ presetOptions: [
{ value: 'today', label: '今日', days: 1 }, { value: 'today', label: i18n.global.t('dashboard.today'), days: 1 },
{ value: '7days', label: '7天', days: 7 }, { value: '7days', label: i18n.global.t('dashboard.last7Days'), days: 7 },
{ value: '30days', label: '30天', days: 30 } { value: '30days', label: i18n.global.t('dashboard.last30Days'), days: 30 }
] ]
}) })
@@ -89,11 +91,11 @@ export const useDashboardStore = defineStore('dashboard', () => {
const minutes = Math.floor((seconds % 3600) / 60) const minutes = Math.floor((seconds % 3600) / 60)
if (days > 0) { if (days > 0) {
return `${days}${hours}小时` return i18n.global.t('dashboard.uptimeFormat.daysHours', { days, hours })
} else if (hours > 0) { } else if (hours > 0) {
return `${hours}小时 ${minutes}分钟` return i18n.global.t('dashboard.uptimeFormat.hoursMinutes', { hours, minutes })
} else { } else {
return `${minutes}分钟` return i18n.global.t('dashboard.uptimeFormat.minutes', { minutes })
} }
}) })
@@ -636,14 +638,14 @@ export const useDashboardStore = defineStore('dashboard', () => {
// 小时粒度:限制 24 小时 // 小时粒度:限制 24 小时
const hoursDiff = (end - start) / (1000 * 60 * 60) const hoursDiff = (end - start) / (1000 * 60 * 60)
if (hoursDiff > 24) { if (hoursDiff > 24) {
showToast('小时粒度下日期范围不能超过24小时', 'warning') showToast(i18n.global.t('dashboard.errors.rangeTooLongHour'), 'warning')
return return
} }
} else { } else {
// 天粒度:限制 31 天 // 天粒度:限制 31 天
const daysDiff = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1 const daysDiff = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1
if (daysDiff > 31) { if (daysDiff > 31) {
showToast('日期范围不能超过 31 天', 'warning') showToast(i18n.global.t('dashboard.errors.rangeTooLongDay'), 'warning')
return return
} }
} }
@@ -662,9 +664,13 @@ export const useDashboardStore = defineStore('dashboard', () => {
// 根据粒度更新预设选项 // 根据粒度更新预设选项
if (granularity === 'hour') { if (granularity === 'hour') {
dateFilter.value.presetOptions = [ dateFilter.value.presetOptions = [
{ value: 'last24h', label: '近24小时', hours: 24 }, {
{ value: 'yesterday', label: '昨天', hours: 24 }, value: 'last24h',
{ value: 'dayBefore', label: '前天', hours: 24 } label: i18n.global.t('dashboard.usageTrend.periodOptions.last24Hours'),
hours: 24
},
{ value: 'yesterday', label: i18n.global.t('dashboard.yesterday'), hours: 24 },
{ value: 'dayBefore', label: i18n.global.t('dashboard.dayBefore'), hours: 24 }
] ]
// 检查当前自定义日期范围是否超过24小时 // 检查当前自定义日期范围是否超过24小时
@@ -677,7 +683,7 @@ export const useDashboardStore = defineStore('dashboard', () => {
const end = new Date(dateFilter.value.customRange[1]) const end = new Date(dateFilter.value.customRange[1])
const hoursDiff = (end - start) / (1000 * 60 * 60) const hoursDiff = (end - start) / (1000 * 60 * 60)
if (hoursDiff > 24) { if (hoursDiff > 24) {
showToast('小时粒度下日期范围不能超过24小时已切换到近24小时', 'warning') showToast(i18n.global.t('dashboard.errors.rangeTooLongHourSwitched'), 'warning')
setDateFilterPreset('last24h') setDateFilterPreset('last24h')
return return
} }
@@ -691,9 +697,9 @@ export const useDashboardStore = defineStore('dashboard', () => {
} else { } else {
// 天粒度 // 天粒度
dateFilter.value.presetOptions = [ dateFilter.value.presetOptions = [
{ value: 'today', label: '今日', days: 1 }, { value: 'today', label: i18n.global.t('dashboard.today'), days: 1 },
{ value: '7days', label: '7天', days: 7 }, { value: '7days', label: i18n.global.t('dashboard.last7Days'), days: 7 },
{ value: '30days', label: '30天', days: 30 } { value: '30days', label: i18n.global.t('dashboard.last30Days'), days: 30 }
] ]
// 如果当前是小时粒度的预设,切换到天粒度的默认预设 // 如果当前是小时粒度的预设,切换到天粒度的默认预设

View File

@@ -1,6 +1,7 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
import { apiClient } from '@/config/api' import { apiClient } from '@/config/api'
import i18n from '@/i18n'
export const useSettingsStore = defineStore('settings', () => { export const useSettingsStore = defineStore('settings', () => {
// 状态 // 状态
@@ -77,7 +78,7 @@ export const useSettingsStore = defineStore('settings', () => {
const applyOemSettings = () => { const applyOemSettings = () => {
// 更新页面标题 // 更新页面标题
if (oemSettings.value.siteName) { if (oemSettings.value.siteName) {
document.title = `${oemSettings.value.siteName} - 管理后台` document.title = `${oemSettings.value.siteName} - ${i18n.global.t('header.adminPanel')}`
} }
// 更新favicon // 更新favicon
@@ -94,7 +95,9 @@ export const useSettingsStore = defineStore('settings', () => {
// 格式化日期时间 // 格式化日期时间
const formatDateTime = (dateString) => { const formatDateTime = (dateString) => {
if (!dateString) return '' if (!dateString) return ''
return new Date(dateString).toLocaleString('zh-CN', { 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', year: 'numeric',
month: '2-digit', month: '2-digit',
day: '2-digit', day: '2-digit',
@@ -110,13 +113,13 @@ export const useSettingsStore = defineStore('settings', () => {
// 检查文件大小 (350KB) // 检查文件大小 (350KB)
if (file.size > 350 * 1024) { if (file.size > 350 * 1024) {
errors.push('图标文件大小不能超过 350KB') errors.push(i18n.global.t('settings.validation.iconTooLarge'))
} }
// 检查文件类型 // 检查文件类型
const allowedTypes = ['image/x-icon', 'image/png', 'image/jpeg', 'image/jpg', 'image/svg+xml'] const allowedTypes = ['image/x-icon', 'image/png', 'image/jpeg', 'image/jpg', 'image/svg+xml']
if (!allowedTypes.includes(file.type)) { if (!allowedTypes.includes(file.type)) {
errors.push('不支持的文件类型,请选择 .ico, .png, .jpg 或 .svg 文件') errors.push(i18n.global.t('settings.validation.iconTypeNotSupported'))
} }
return { return {