mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
Revert "feat: 完整国际化支持 - Web 管理界面多语言实现"
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
<div class="relative top-20 mx-auto w-96 rounded-md border bg-white p-5 shadow-lg">
|
||||
<div class="mt-3">
|
||||
<div class="mb-4 flex items-center justify-between">
|
||||
<h3 class="text-lg font-medium text-gray-900">{{ $t('user.changeRoleModal.title') }}</h3>
|
||||
<h3 class="text-lg font-medium text-gray-900">Change User Role</h3>
|
||||
<button class="text-gray-400 hover:text-gray-600" @click="$emit('close')">
|
||||
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
@@ -54,7 +54,7 @@
|
||||
: 'bg-blue-100 text-blue-800'
|
||||
]"
|
||||
>
|
||||
{{ $t('user.changeRoleModal.currentRole', { role: user.role }) }}
|
||||
Current: {{ user.role }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,9 +64,7 @@
|
||||
<!-- Role Selection -->
|
||||
<form class="space-y-4" @submit.prevent="handleSubmit">
|
||||
<div>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700">
|
||||
{{ $t('user.changeRoleModal.newRole') }}
|
||||
</label>
|
||||
<label class="mb-2 block text-sm font-medium text-gray-700"> New Role </label>
|
||||
<div class="space-y-2">
|
||||
<label class="flex items-center">
|
||||
<input
|
||||
@@ -77,12 +75,8 @@
|
||||
value="user"
|
||||
/>
|
||||
<div class="ml-3">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{{ $t('user.changeRoleModal.roles.user') }}
|
||||
</div>
|
||||
<div class="text-xs text-gray-500">
|
||||
{{ $t('user.changeRoleModal.roles.userDesc') }}
|
||||
</div>
|
||||
<div class="text-sm font-medium text-gray-900">User</div>
|
||||
<div class="text-xs text-gray-500">Regular user with basic permissions</div>
|
||||
</div>
|
||||
</label>
|
||||
<label class="flex items-center">
|
||||
@@ -94,12 +88,8 @@
|
||||
value="admin"
|
||||
/>
|
||||
<div class="ml-3">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
{{ $t('user.changeRoleModal.roles.admin') }}
|
||||
</div>
|
||||
<div class="text-xs text-gray-500">
|
||||
{{ $t('user.changeRoleModal.roles.adminDesc') }}
|
||||
</div>
|
||||
<div class="text-sm font-medium text-gray-900">Administrator</div>
|
||||
<div class="text-xs text-gray-500">Full access to manage users and system</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
@@ -121,15 +111,15 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-yellow-800">
|
||||
{{ $t('user.changeRoleModal.roleChangeWarning.title') }}
|
||||
</h3>
|
||||
<h3 class="text-sm font-medium text-yellow-800">Role Change Warning</h3>
|
||||
<div class="mt-2 text-sm text-yellow-700">
|
||||
<p v-if="selectedRole === 'admin'">
|
||||
{{ $t('user.changeRoleModal.roleChangeWarning.grantAdmin') }}
|
||||
Granting admin privileges will give this user full access to the system,
|
||||
including the ability to manage other users and their API keys.
|
||||
</p>
|
||||
<p v-else>
|
||||
{{ $t('user.changeRoleModal.roleChangeWarning.removeAdmin') }}
|
||||
Removing admin privileges will restrict this user to only managing their own
|
||||
API keys and viewing their own usage statistics.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -160,7 +150,7 @@
|
||||
type="button"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
{{ $t('user.changeRoleModal.cancel') }}
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="rounded-md border border-transparent bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
@@ -188,9 +178,9 @@
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
{{ $t('user.changeRoleModal.updating') }}
|
||||
Updating...
|
||||
</span>
|
||||
<span v-else>{{ $t('user.changeRoleModal.updateRole') }}</span>
|
||||
<span v-else>Update Role</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -204,9 +194,6 @@
|
||||
import { ref, watch } from 'vue'
|
||||
import { apiClient } from '@/config/api'
|
||||
import { showToast } from '@/utils/toast'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
@@ -239,7 +226,7 @@ const handleSubmit = async () => {
|
||||
})
|
||||
|
||||
if (response.success) {
|
||||
showToast(t('user.changeRoleModal.roleUpdated', { role: selectedRole.value }), 'success')
|
||||
showToast(`User role updated to ${selectedRole.value}`, 'success')
|
||||
emit('updated')
|
||||
} else {
|
||||
error.value = response.message || 'Failed to update user role'
|
||||
|
||||
@@ -8,11 +8,7 @@
|
||||
<div class="mb-6 flex items-center justify-between">
|
||||
<div>
|
||||
<h3 class="text-lg font-medium text-gray-900">
|
||||
{{
|
||||
$t('user.usageStatsModal.titleWithUser', {
|
||||
displayName: user?.displayName || user?.username
|
||||
})
|
||||
}}
|
||||
Usage Statistics - {{ user?.displayName || user?.username }}
|
||||
</h3>
|
||||
<p class="text-sm text-gray-500">@{{ user?.username }} • {{ user?.role }}</p>
|
||||
</div>
|
||||
@@ -35,12 +31,10 @@
|
||||
class="block w-32 rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm"
|
||||
@change="loadUsageStats"
|
||||
>
|
||||
<option value="day">{{ $t('user.usageStatsModal.periodSelection.day') }}</option>
|
||||
<option value="week">{{ $t('user.usageStatsModal.periodSelection.week') }}</option>
|
||||
<option value="month">{{ $t('user.usageStatsModal.periodSelection.month') }}</option>
|
||||
<option value="quarter">
|
||||
{{ $t('user.usageStatsModal.periodSelection.quarter') }}
|
||||
</option>
|
||||
<option value="day">Last 24 Hours</option>
|
||||
<option value="week">Last 7 Days</option>
|
||||
<option value="month">Last 30 Days</option>
|
||||
<option value="quarter">Last 90 Days</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -66,7 +60,7 @@
|
||||
fill="currentColor"
|
||||
></path>
|
||||
</svg>
|
||||
<p class="mt-2 text-sm text-gray-500">{{ $t('user.usageStatsModal.loadingStats') }}</p>
|
||||
<p class="mt-2 text-sm text-gray-500">Loading usage statistics...</p>
|
||||
</div>
|
||||
|
||||
<!-- Stats Content -->
|
||||
@@ -93,9 +87,7 @@
|
||||
</div>
|
||||
<div class="ml-5 w-0 flex-1">
|
||||
<dl>
|
||||
<dt class="truncate text-sm font-medium text-blue-600">
|
||||
{{ $t('user.usageStatsModal.summaryCards.requests') }}
|
||||
</dt>
|
||||
<dt class="truncate text-sm font-medium text-blue-600">Requests</dt>
|
||||
<dd class="text-lg font-medium text-blue-900">
|
||||
{{ formatNumber(usageStats?.totalRequests || 0) }}
|
||||
</dd>
|
||||
@@ -125,9 +117,7 @@
|
||||
</div>
|
||||
<div class="ml-5 w-0 flex-1">
|
||||
<dl>
|
||||
<dt class="truncate text-sm font-medium text-green-600">
|
||||
{{ $t('user.usageStatsModal.summaryCards.inputTokens') }}
|
||||
</dt>
|
||||
<dt class="truncate text-sm font-medium text-green-600">Input Tokens</dt>
|
||||
<dd class="text-lg font-medium text-green-900">
|
||||
{{ formatNumber(usageStats?.totalInputTokens || 0) }}
|
||||
</dd>
|
||||
@@ -157,9 +147,7 @@
|
||||
</div>
|
||||
<div class="ml-5 w-0 flex-1">
|
||||
<dl>
|
||||
<dt class="truncate text-sm font-medium text-purple-600">
|
||||
{{ $t('user.usageStatsModal.summaryCards.outputTokens') }}
|
||||
</dt>
|
||||
<dt class="truncate text-sm font-medium text-purple-600">Output Tokens</dt>
|
||||
<dd class="text-lg font-medium text-purple-900">
|
||||
{{ formatNumber(usageStats?.totalOutputTokens || 0) }}
|
||||
</dd>
|
||||
@@ -189,9 +177,7 @@
|
||||
</div>
|
||||
<div class="ml-5 w-0 flex-1">
|
||||
<dl>
|
||||
<dt class="truncate text-sm font-medium text-yellow-600">
|
||||
{{ $t('user.usageStatsModal.summaryCards.totalCost') }}
|
||||
</dt>
|
||||
<dt class="truncate text-sm font-medium text-yellow-600">Total Cost</dt>
|
||||
<dd class="text-lg font-medium text-yellow-900">
|
||||
${{ (usageStats?.totalCost || 0).toFixed(4) }}
|
||||
</dd>
|
||||
@@ -208,9 +194,7 @@
|
||||
class="rounded-lg border border-gray-200 bg-white"
|
||||
>
|
||||
<div class="border-b border-gray-200 px-4 py-5 sm:px-6">
|
||||
<h4 class="text-lg font-medium leading-6 text-gray-900">
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.title') }}
|
||||
</h4>
|
||||
<h4 class="text-lg font-medium leading-6 text-gray-900">API Keys Usage</h4>
|
||||
</div>
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-gray-200">
|
||||
@@ -220,37 +204,37 @@
|
||||
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
|
||||
scope="col"
|
||||
>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.headers.apiKey') }}
|
||||
API Key
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
|
||||
scope="col"
|
||||
>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.headers.status') }}
|
||||
Status
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
|
||||
scope="col"
|
||||
>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.headers.requests') }}
|
||||
Requests
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
|
||||
scope="col"
|
||||
>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.headers.tokens') }}
|
||||
Tokens
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
|
||||
scope="col"
|
||||
>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.headers.cost') }}
|
||||
Cost
|
||||
</th>
|
||||
<th
|
||||
class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500"
|
||||
scope="col"
|
||||
>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.headers.lastUsed') }}
|
||||
Last Used
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -269,35 +253,21 @@
|
||||
: 'bg-red-100 text-red-800'
|
||||
]"
|
||||
>
|
||||
{{
|
||||
apiKey.isActive
|
||||
? $t('user.usageStatsModal.apiKeysTable.status.active')
|
||||
: $t('user.usageStatsModal.apiKeysTable.status.disabled')
|
||||
}}
|
||||
{{ apiKey.isActive ? 'Active' : 'Disabled' }}
|
||||
</span>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-900">
|
||||
{{ formatNumber(apiKey.usage?.requests || 0) }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-900">
|
||||
<div>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.tokensFormat.input') }}:
|
||||
{{ formatNumber(apiKey.usage?.inputTokens || 0) }}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t('user.usageStatsModal.apiKeysTable.tokensFormat.output') }}:
|
||||
{{ formatNumber(apiKey.usage?.outputTokens || 0) }}
|
||||
</div>
|
||||
<div>In: {{ formatNumber(apiKey.usage?.inputTokens || 0) }}</div>
|
||||
<div>Out: {{ formatNumber(apiKey.usage?.outputTokens || 0) }}</div>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-900">
|
||||
${{ (apiKey.usage?.totalCost || 0).toFixed(4) }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500">
|
||||
{{
|
||||
apiKey.lastUsedAt
|
||||
? formatDate(apiKey.lastUsedAt)
|
||||
: $t('user.usageStatsModal.apiKeysTable.never')
|
||||
}}
|
||||
{{ apiKey.lastUsedAt ? formatDate(apiKey.lastUsedAt) : 'Never' }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -308,9 +278,7 @@
|
||||
<!-- Chart Placeholder -->
|
||||
<div class="rounded-lg border border-gray-200 bg-white">
|
||||
<div class="border-b border-gray-200 px-4 py-5 sm:px-6">
|
||||
<h4 class="text-lg font-medium leading-6 text-gray-900">
|
||||
{{ $t('user.usageStatsModal.usageTrend.title') }}
|
||||
</h4>
|
||||
<h4 class="text-lg font-medium leading-6 text-gray-900">Usage Trend</h4>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div
|
||||
@@ -330,16 +298,12 @@
|
||||
stroke-width="2"
|
||||
/>
|
||||
</svg>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">
|
||||
{{ $t('user.usageStatsModal.usageTrend.chartTitle') }}
|
||||
</h3>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">Usage Chart</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">
|
||||
{{
|
||||
$t('user.usageStatsModal.usageTrend.dailyTrends', { period: selectedPeriod })
|
||||
}}
|
||||
Daily usage trends for {{ selectedPeriod }} period
|
||||
</p>
|
||||
<p class="mt-2 text-xs text-gray-400">
|
||||
{{ $t('user.usageStatsModal.usageTrend.chartNote') }}
|
||||
(Chart integration can be added with Chart.js, D3.js, or similar library)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -361,11 +325,9 @@
|
||||
stroke-width="2"
|
||||
/>
|
||||
</svg>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">
|
||||
{{ $t('user.usageStatsModal.noData.title') }}
|
||||
</h3>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">No usage data</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">
|
||||
{{ $t('user.usageStatsModal.noData.description') }}
|
||||
This user hasn't made any API requests in the selected period.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -375,7 +337,7 @@
|
||||
class="rounded-md border border-gray-300 px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
|
||||
@click="$emit('close')"
|
||||
>
|
||||
{{ $t('user.usageStatsModal.close') }}
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -387,7 +349,6 @@
|
||||
import { ref, watch } from 'vue'
|
||||
import { apiClient } from '@/config/api'
|
||||
import { showToast } from '@/utils/toast'
|
||||
// import { useI18n } from 'vue-i18n' - using $t in template instead
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
|
||||
Reference in New Issue
Block a user