mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-08 02:17:46 +08:00
fix(frontend): complete i18n coverage and responsive layouts
This commit is contained in:
@@ -1019,6 +1019,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getI18nLocale } from '@/i18n'
|
||||
import { computed, defineComponent, h, onMounted, onUnmounted, ref, watch, type Component } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import type { ChartData, ChartOptions } from 'chart.js'
|
||||
@@ -1300,7 +1301,7 @@ function formatShortDate(value?: string | null): string {
|
||||
if (!value) return '-'
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) return '-'
|
||||
return date.toLocaleString('zh-CN', {
|
||||
return date.toLocaleString(getI18nLocale(), {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
|
||||
@@ -802,6 +802,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getI18nLocale } from '@/i18n'
|
||||
import { ref, computed, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { useConfirm } from '@/composables/useConfirm'
|
||||
@@ -1349,7 +1350,7 @@ function isExpiringSoon(apiKey: AdminApiKey): boolean {
|
||||
}
|
||||
|
||||
function formatDate(dateString: string): string {
|
||||
return new Date(dateString).toLocaleString('zh-CN', {
|
||||
return new Date(dateString).toLocaleString(getI18nLocale(), {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
|
||||
@@ -862,7 +862,7 @@ import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { asyncTasksApi, type AsyncTaskItem, type AsyncTaskDetail, type AsyncTaskStatsResponse, type AsyncTaskStatus } from '@/api/async-tasks'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { useClipboard } from '@/composables/useClipboard'
|
||||
import { useI18n } from '@/i18n'
|
||||
import { getI18nLocale, useI18n } from '@/i18n'
|
||||
import Card from '@/components/ui/card.vue'
|
||||
import Button from '@/components/ui/button.vue'
|
||||
import Input from '@/components/ui/input.vue'
|
||||
@@ -1176,7 +1176,7 @@ function canCancel(status: string): boolean {
|
||||
function formatDate(dateStr: string | null): string {
|
||||
if (!dateStr) return '-'
|
||||
const date = new Date(dateStr)
|
||||
return date.toLocaleString('zh-CN', {
|
||||
return date.toLocaleString(getI18nLocale(), {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
@@ -1188,7 +1188,7 @@ function formatDate(dateStr: string | null): string {
|
||||
function formatDateFull(dateStr: string | null): string {
|
||||
if (!dateStr) return '-'
|
||||
const date = new Date(dateStr)
|
||||
return date.toLocaleString('zh-CN', {
|
||||
return date.toLocaleString(getI18nLocale(), {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
|
||||
@@ -409,6 +409,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getI18nLocale } from '@/i18n'
|
||||
import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
|
||||
import {
|
||||
Card,
|
||||
@@ -728,7 +729,7 @@ function getStatusCodeVariant(statusCode: number): 'default' | 'success' | 'dest
|
||||
|
||||
function formatDateTime(dateStr: string): string {
|
||||
const date = new Date(dateStr)
|
||||
return date.toLocaleString('zh-CN', {
|
||||
return date.toLocaleString(getI18nLocale(), {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
|
||||
@@ -415,7 +415,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { useI18n } from '@/i18n'
|
||||
import { getI18nLocale, useI18n } from '@/i18n'
|
||||
import Card from '@/components/ui/card.vue'
|
||||
import Badge from '@/components/ui/badge.vue'
|
||||
import Button from '@/components/ui/button.vue'
|
||||
@@ -658,7 +658,7 @@ function handleFileSelect(e: Event) {
|
||||
function formatDate(dateStr: string) {
|
||||
if (!dateStr) return '-'
|
||||
const date = new Date(dateStr)
|
||||
return date.toLocaleString('zh-CN', {
|
||||
return date.toLocaleString(getI18nLocale(), {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0 pt-1">
|
||||
<h4 class="font-semibold text-base truncate">
|
||||
<h4 class="break-words font-semibold text-base">
|
||||
{{ tool.name }}
|
||||
</h4>
|
||||
</div>
|
||||
@@ -150,7 +150,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0 pt-1 pr-8">
|
||||
<h4 class="font-semibold text-base truncate">
|
||||
<h4 class="break-words font-semibold text-base">
|
||||
{{ module.display_name }}
|
||||
</h4>
|
||||
</div>
|
||||
@@ -177,7 +177,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 操作区域 -->
|
||||
<div class="mt-5 pt-4 border-t border-border/50 flex items-center justify-between">
|
||||
<div class="mt-5 pt-4 border-t border-border/50 flex flex-wrap items-center justify-between gap-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<Switch
|
||||
:model-value="module.enabled"
|
||||
@@ -204,11 +204,11 @@
|
||||
v-if="module.admin_route"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="gap-1.5"
|
||||
class="shrink-0 gap-1.5"
|
||||
@click="router.push(module.admin_route)"
|
||||
>
|
||||
<Settings class="w-3.5 h-3.5" />
|
||||
配置
|
||||
{{ t('common.configure') }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -240,6 +240,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from '@/i18n'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import {
|
||||
@@ -266,6 +267,7 @@ import { modulesApi, type ModuleStatus } from '@/api/modules'
|
||||
|
||||
const router = useRouter()
|
||||
const { success, error } = useToast()
|
||||
const { t } = useI18n()
|
||||
const moduleStore = useModuleStore()
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
@@ -419,6 +419,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getI18nLocale } from '@/i18n'
|
||||
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
|
||||
import { CircleHelp, PlugZap, Plus, Save, Trash2 } from 'lucide-vue-next'
|
||||
import { epayGatewayApi, type EpayChannelConfig, type PaymentGatewayProvider } from '@/api/billing'
|
||||
@@ -544,7 +545,7 @@ const visibleFields = computed(() => activeProviderMeta.value.fields)
|
||||
|
||||
const updatedAtText = computed(() => {
|
||||
if (!updatedAt.value) return ''
|
||||
return new Date(updatedAt.value * 1000).toLocaleString('zh-CN')
|
||||
return new Date(updatedAt.value * 1000).toLocaleString(getI18nLocale())
|
||||
})
|
||||
|
||||
const defaultCallbackBaseUrl = computed(() => {
|
||||
|
||||
@@ -826,6 +826,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from '@/i18n'
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import {
|
||||
Activity,
|
||||
@@ -890,6 +891,7 @@ type ProviderPerformanceParams = NonNullable<Parameters<typeof adminApi.getProvi
|
||||
|
||||
const timeRange = ref<DateRangeParams>(getDateRangeFromPeriod('last7days'))
|
||||
const { error: showError } = useToast()
|
||||
const { legacyT } = useI18n()
|
||||
|
||||
const percentiles = ref<PercentileItem[]>([])
|
||||
const percentileLoading = ref(false)
|
||||
@@ -1228,7 +1230,7 @@ const errorTrendChartData = computed(() => ({
|
||||
labels: errorTrend.value.map(item => item.date),
|
||||
datasets: [
|
||||
{
|
||||
label: '错误数',
|
||||
label: legacyT('错误数'),
|
||||
data: errorTrend.value.map(item => item.total),
|
||||
borderColor: 'rgb(239, 68, 68)',
|
||||
tension: 0.25,
|
||||
|
||||
@@ -261,6 +261,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getI18nLocale } from '@/i18n'
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { RefreshCw } from 'lucide-vue-next'
|
||||
import {
|
||||
@@ -326,7 +327,7 @@ function formatUsd(value: number): string {
|
||||
|
||||
function formatUnix(value?: number | null): string {
|
||||
if (!value) return '-'
|
||||
return new Date(value * 1000).toLocaleString('zh-CN')
|
||||
return new Date(value * 1000).toLocaleString(getI18nLocale())
|
||||
}
|
||||
|
||||
function getRewardTypeLabel(value: string): string {
|
||||
|
||||
@@ -808,6 +808,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getI18nLocale } from '@/i18n'
|
||||
import { computed, onMounted, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import {
|
||||
@@ -1734,7 +1735,7 @@ async function confirmDeleteDraft(): Promise<void> {
|
||||
|
||||
function formatUnixSeconds(value?: number | null): string {
|
||||
if (!value) return '-'
|
||||
return new Date(value * 1000).toLocaleString('zh-CN')
|
||||
return new Date(value * 1000).toLocaleString(getI18nLocale())
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -1383,7 +1383,7 @@ import {
|
||||
import type { PaymentOrder } from '@/api/wallet'
|
||||
import { parseApiError } from '@/utils/errorParser'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
import { useI18n } from '@/i18n'
|
||||
import { getI18nLocale, useI18n } from '@/i18n'
|
||||
import { log } from '@/utils/logger'
|
||||
import {
|
||||
callbackStatusBadge,
|
||||
@@ -2222,7 +2222,7 @@ function ownerDisplayName(name: string | null | undefined, ownerType: 'user' | '
|
||||
|
||||
function formatDateTime(value: string | null | undefined) {
|
||||
if (!value) return '-'
|
||||
return new Date(value).toLocaleString('zh-CN', {
|
||||
return new Date(value).toLocaleString(getI18nLocale(), {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
|
||||
@@ -52,9 +52,7 @@
|
||||
class="mt-1"
|
||||
/>
|
||||
<p class="mt-1 text-xs text-muted-foreground">
|
||||
Bark App 中推送地址
|
||||
<span class="font-mono">https://api.day.app/xxxx</span>
|
||||
的 <span class="font-mono">xxxx</span> 部分
|
||||
{{ $t('modules.bark.deviceKeyHint') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -308,8 +308,8 @@
|
||||
</div>
|
||||
|
||||
<div class="mt-4 border border-border rounded-lg overflow-hidden">
|
||||
<div class="flex items-center justify-between px-4 py-3 border-b border-border">
|
||||
<div>
|
||||
<div class="flex flex-wrap items-start justify-between gap-3 px-4 py-3 border-b border-border">
|
||||
<div class="min-w-0 flex-1 basis-48">
|
||||
<h4 class="text-sm font-medium">
|
||||
最近清理记录
|
||||
</h4>
|
||||
@@ -320,6 +320,7 @@
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="shrink-0"
|
||||
:disabled="cleanupRunsLoading"
|
||||
@click="loadCleanupRuns"
|
||||
>
|
||||
|
||||
@@ -33,21 +33,23 @@
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="w-full"
|
||||
:title="item.exportLabel"
|
||||
:disabled="item.exportLoading"
|
||||
@click="$emit('export', item.key)"
|
||||
>
|
||||
<Download class="w-3.5 h-3.5 mr-1.5" />
|
||||
{{ item.exportLoading ? '导出中...' : item.exportLabel }}
|
||||
{{ item.exportLoading ? '导出中...' : '导出' }}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
class="w-full"
|
||||
:title="item.importLabel"
|
||||
:disabled="item.importLoading"
|
||||
@click="triggerDataFileSelect(item.key)"
|
||||
>
|
||||
<Upload class="w-3.5 h-3.5 mr-1.5" />
|
||||
{{ item.importLoading ? '导入中...' : item.importLabel }}
|
||||
{{ item.importLoading ? '导入中...' : '导入' }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user