feat: 完成布局/仪表板/用户相关组件国际化与语言切换优化(TabBar/MainLayout/AppHeader、UsageTrend/ModelDistribution、User*、Common 组件、i18n/locale 增强)

This commit is contained in:
Wangnov
2025-09-10 18:13:27 +08:00
parent 022724336b
commit d5b9f809b0
20 changed files with 410 additions and 300 deletions

View File

@@ -3,12 +3,16 @@
<div class="mb-6 flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
<h2 class="flex items-center text-xl font-bold text-gray-800">
<i class="fas fa-robot mr-2 text-purple-500" />
模型使用分布
{{ $t('dashboard.modelDistribution.title') }}
</h2>
<el-radio-group v-model="modelPeriod" size="small" @change="handlePeriodChange">
<el-radio-button label="daily"> 今日 </el-radio-button>
<el-radio-button label="total"> 累计 </el-radio-button>
<el-radio-button label="daily">
{{ $t('dashboard.modelDistribution.periods.daily') }}
</el-radio-button>
<el-radio-button label="total">
{{ $t('dashboard.modelDistribution.periods.total') }}
</el-radio-button>
</el-radio-group>
</div>
@@ -17,16 +21,16 @@
class="py-12 text-center text-gray-500"
>
<i class="fas fa-chart-pie mb-3 text-4xl opacity-30" />
<p>暂无模型使用数据</p>
<p>{{ $t('dashboard.modelDistribution.noData') }}</p>
</div>
<div v-else class="grid grid-cols-1 gap-6 lg:grid-cols-2">
<!-- 饼图 -->
<!-- Pie Chart -->
<div class="relative" style="height: 300px">
<canvas ref="chartCanvas" />
</div>
<!-- 数据列表 -->
<!-- Data List -->
<div class="space-y-3">
<div
v-for="(stat, index) in sortedStats"
@@ -38,8 +42,14 @@
<span class="font-medium text-gray-700">{{ stat.model }}</span>
</div>
<div class="text-right">
<p class="font-semibold text-gray-800">{{ formatNumber(stat.requests) }} 请求</p>
<p class="text-sm text-gray-500">{{ formatNumber(stat.totalTokens) }} tokens</p>
<p class="font-semibold text-gray-800">
{{ formatNumber(stat.requests) }}
{{ $t('dashboard.modelDistribution.units.requests') }}
</p>
<p class="text-sm text-gray-500">
{{ formatNumber(stat.totalTokens) }}
{{ $t('dashboard.modelDistribution.units.tokens') }}
</p>
</div>
</div>
</div>
@@ -50,10 +60,13 @@
<script setup>
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
import { Chart } from 'chart.js/auto'
import { useI18n } from 'vue-i18n'
import { useDashboardStore } from '@/stores/dashboard'
import { useChartConfig } from '@/composables/useChartConfig'
import { formatNumber } from '@/utils/format'
const { t } = useI18n()
const dashboardStore = useDashboardStore()
const chartCanvas = ref(null)
let chart = null
@@ -110,8 +123,8 @@ const createChart = () => {
).toFixed(1)
return [
`${stat.model}: ${percentage}%`,
`请求: ${formatNumber(stat.requests)}`,
`Tokens: ${formatNumber(stat.totalTokens)}`
`${t('dashboard.modelDistribution.chart.tooltip.requests')}: ${formatNumber(stat.requests)}`,
`${t('dashboard.modelDistribution.chart.tooltip.tokens')}: ${formatNumber(stat.totalTokens)}`
]
}
}

View File

@@ -3,13 +3,17 @@
<div class="mb-6 flex flex-col items-start justify-between gap-4 md:flex-row md:items-center">
<h2 class="flex items-center text-xl font-bold text-gray-800">
<i class="fas fa-chart-area mr-2 text-blue-500" />
使用趋势
{{ $t('dashboard.usageTrend.title') }}
</h2>
<div class="flex items-center gap-3">
<el-radio-group v-model="granularity" size="small" @change="handleGranularityChange">
<el-radio-button label="day"> 按天 </el-radio-button>
<el-radio-button label="hour"> 按小时 </el-radio-button>
<el-radio-button label="day">
{{ $t('dashboard.usageTrend.granularity.byDay') }}
</el-radio-button>
<el-radio-button label="hour">
{{ $t('dashboard.usageTrend.granularity.byHour') }}
</el-radio-button>
</el-radio-group>
<el-select
@@ -21,7 +25,7 @@
<el-option
v-for="period in periodOptions"
:key="period.days"
:label="`最近${period.days}天`"
:label="$t('dashboard.usageTrend.periodOptions.recentDays', { days: period.days })"
:value="period.days"
/>
</el-select>
@@ -35,23 +39,25 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
import { Chart } from 'chart.js/auto'
import { useDashboardStore } from '@/stores/dashboard'
import { useChartConfig } from '@/composables/useChartConfig'
import { useI18n } from 'vue-i18n'
const dashboardStore = useDashboardStore()
const chartCanvas = ref(null)
let chart = null
const { t } = useI18n()
const trendPeriod = ref(7)
const granularity = ref('day')
const periodOptions = [
{ days: 1, label: '24小时' },
{ days: 7, label: '7天' },
{ days: 30, label: '30天' }
]
const periodOptions = computed(() => [
{ days: 1, label: t('dashboard.usageTrend.periodOptions.last24Hours') },
{ days: 7, label: t('dashboard.usageTrend.periodOptions.last7Days') },
{ days: 30, label: t('dashboard.usageTrend.periodOptions.last30Days') }
])
const createChart = () => {
if (!chartCanvas.value || !dashboardStore.trendData.length) return
@@ -81,7 +87,7 @@ const createChart = () => {
labels,
datasets: [
{
label: '请求次数',
label: t('dashboard.usageTrend.chartLabels.requests'),
data: dashboardStore.trendData.map((item) => item.requests),
borderColor: '#667eea',
backgroundColor: getGradient(ctx, '#667eea', 0.1),
@@ -89,7 +95,7 @@ const createChart = () => {
tension: 0.4
},
{
label: 'Token使用量',
label: t('dashboard.usageTrend.chartLabels.tokens'),
data: dashboardStore.trendData.map((item) => item.tokens),
borderColor: '#f093fb',
backgroundColor: getGradient(ctx, '#f093fb', 0.1),
@@ -127,7 +133,7 @@ const createChart = () => {
position: 'left',
title: {
display: true,
text: '请求次数'
text: t('dashboard.usageTrend.chartLabels.requestsAxis')
}
},
y1: {
@@ -136,7 +142,7 @@ const createChart = () => {
position: 'right',
title: {
display: true,
text: 'Token使用量'
text: t('dashboard.usageTrend.chartLabels.tokensAxis')
},
grid: {
drawOnChartArea: false