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

View File

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

View File

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

View File

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

View File

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