fix(frontend): 修复重构页面的遗漏问题

- 添加 en.ts 中缺失的 admin.redeem.types 翻译
- RedeemView 状态筛选器添加 expired 选项
- SubscriptionsView 用量进度条添加 null/undefined 兜底
- SubscriptionsView 添加 validity_days 表单校验
- GroupsView/ProxiesView 搜索图标添加 dark mode 样式
This commit is contained in:
ianshaw
2026-01-04 20:51:37 -08:00
parent 85f53ef2dd
commit ee29b9428b
6 changed files with 21 additions and 7 deletions

View File

@@ -914,6 +914,7 @@ export default {
failedToRevoke: 'Failed to revoke subscription',
pleaseSelectUser: 'Please select a user',
pleaseSelectGroup: 'Please select a group',
validityDaysRequired: 'Please enter a valid number of days (at least 1)',
revokeConfirm:
"Are you sure you want to revoke the subscription for '{user}'? This action cannot be undone."
},
@@ -1652,6 +1653,11 @@ export default {
failedToDelete: 'Failed to delete code',
failedToDeleteUnused: 'Failed to delete unused codes',
failedToCopy: 'Failed to copy codes',
types: {
balance: 'Balance',
concurrency: 'Concurrency',
subscription: 'Subscription'
},
selectGroup: 'Select Group',
selectGroupPlaceholder: 'Choose a subscription group',
validityDays: 'Validity Days',

View File

@@ -991,6 +991,7 @@ export default {
failedToRevoke: '撤销订阅失败',
pleaseSelectUser: '请选择用户',
pleaseSelectGroup: '请选择分组',
validityDaysRequired: '请输入有效的天数至少1天',
revokeConfirm: "确定要撤销 '{user}' 的订阅吗?此操作无法撤销。"
},

View File

@@ -7,7 +7,7 @@
<div class="flex flex-1 flex-wrap items-center gap-3">
<div class="relative w-full sm:w-72 lg:w-80">
<svg
class="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400"
class="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400 dark:text-gray-500"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"

View File

@@ -9,7 +9,7 @@
<!-- Search -->
<div class="relative w-full sm:flex-1 sm:min-w-[14rem] sm:max-w-md">
<svg
class="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400"
class="absolute left-3 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400 dark:text-gray-500"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"

View File

@@ -525,7 +525,8 @@ const filterTypeOptions = computed(() => [
const filterStatusOptions = computed(() => [
{ value: '', label: t('admin.redeem.allStatus') },
{ value: 'unused', label: t('admin.redeem.unused') },
{ value: 'used', label: t('admin.redeem.used') }
{ value: 'used', label: t('admin.redeem.used') },
{ value: 'expired', label: t('admin.redeem.status.expired') }
])
const codes = ref<RedeemCode[]>([])

View File

@@ -877,6 +877,10 @@ const handleAssignSubscription = async () => {
appStore.showError(t('admin.subscriptions.pleaseSelectGroup'))
return
}
if (!assignForm.validity_days || assignForm.validity_days < 1) {
appStore.showError(t('admin.subscriptions.validityDaysRequired'))
return
}
submitting.value = true
try {
@@ -960,15 +964,17 @@ const isExpiringSoon = (expiresAt: string): boolean => {
return days !== null && days <= 7
}
const getProgressWidth = (used: number, limit: number | null): string => {
const getProgressWidth = (used: number | null | undefined, limit: number | null): string => {
if (!limit || limit === 0) return '0%'
const percentage = Math.min((used / limit) * 100, 100)
const usedValue = used ?? 0
const percentage = Math.min((usedValue / limit) * 100, 100)
return `${percentage}%`
}
const getProgressClass = (used: number, limit: number | null): string => {
const getProgressClass = (used: number | null | undefined, limit: number | null): string => {
if (!limit || limit === 0) return 'bg-gray-400'
const percentage = (used / limit) * 100
const usedValue = used ?? 0
const percentage = (usedValue / limit) * 100
if (percentage >= 90) return 'bg-red-500'
if (percentage >= 70) return 'bg-orange-500'
return 'bg-green-500'