fix: change quota notify threshold semantics to "remaining quota"

Threshold now represents remaining quota instead of usage amount:
- Fixed ($): threshold=400, limit=1000 → alert when remaining drops to $400
  (i.e., usage reaches $600)
- Percentage (%): threshold=30%, limit=1000 → alert when remaining drops
  to 30% (i.e., usage reaches $700)

Also:
- Rename 告警阈值 → 提醒阈值 in i18n
- Widen type dropdown to w-16 for proper $ / % display
This commit is contained in:
erio
2026-04-13 17:38:33 +08:00
parent 7141dceee2
commit 216bda58da
5 changed files with 30 additions and 49 deletions

View File

@@ -1,8 +1,4 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
defineProps<{
enabled: boolean | null
threshold: number | null
@@ -14,15 +10,10 @@ const emit = defineEmits<{
'update:threshold': [value: number | null]
'update:thresholdType': [value: string | null]
}>()
function toggleType(current: string | null) {
emit('update:thresholdType', current === 'percentage' ? 'fixed' : 'percentage')
}
</script>
<template>
<div class="flex items-center gap-2">
<label class="text-sm text-gray-500 whitespace-nowrap">{{ t('admin.accounts.quotaNotify.alert') }}</label>
<div class="flex items-center gap-1.5">
<button
type="button"
@click="emit('update:enabled', !enabled)"
@@ -39,38 +30,23 @@ function toggleType(current: string | null) {
/>
</button>
<template v-if="enabled">
<button
type="button"
class="px-1.5 py-0.5 text-xs font-medium rounded border transition-colors"
:class="(!thresholdType || thresholdType === 'fixed') ? 'bg-primary-100 text-primary-700 border-primary-300 dark:bg-primary-900/30 dark:text-primary-400 dark:border-primary-700' : 'bg-gray-100 text-gray-500 border-gray-200 dark:bg-dark-600 dark:text-gray-400 dark:border-dark-500'"
@click="toggleType(thresholdType)"
<input
:value="threshold"
@input="emit('update:threshold', parseFloat(($event.target as HTMLInputElement).value) || null)"
type="number"
min="0"
:max="thresholdType === 'percentage' ? 100 : undefined"
:step="thresholdType === 'percentage' ? 1 : 0.01"
class="input py-1 text-sm flex-1 min-w-0"
/>
<select
:value="thresholdType || 'fixed'"
@change="emit('update:thresholdType', ($event.target as HTMLSelectElement).value)"
class="input py-1 text-xs w-16 flex-shrink-0 text-center"
>
$
</button>
<button
type="button"
class="px-1.5 py-0.5 text-xs font-medium rounded border transition-colors"
:class="thresholdType === 'percentage' ? 'bg-primary-100 text-primary-700 border-primary-300 dark:bg-primary-900/30 dark:text-primary-400 dark:border-primary-700' : 'bg-gray-100 text-gray-500 border-gray-200 dark:bg-dark-600 dark:text-gray-400 dark:border-dark-500'"
@click="toggleType(thresholdType)"
>
%
</button>
<div class="relative flex-1">
<input
:value="threshold"
@input="emit('update:threshold', parseFloat(($event.target as HTMLInputElement).value) || null)"
type="number"
min="0"
:max="thresholdType === 'percentage' ? 100 : undefined"
:step="thresholdType === 'percentage' ? 1 : 0.01"
class="input py-1 text-sm w-full"
:class="thresholdType === 'percentage' ? 'pr-7' : 'pr-7'"
:placeholder="thresholdType === 'percentage' ? t('admin.accounts.quotaNotify.thresholdPlaceholder') : t('admin.accounts.quotaNotify.threshold')"
/>
<span class="absolute right-2.5 top-1/2 -translate-y-1/2 text-xs text-gray-400 pointer-events-none">
{{ thresholdType === 'percentage' ? '%' : '$' }}
</span>
</div>
<option value="fixed">$</option>
<option value="percentage">%</option>
</select>
</template>
</div>
</template>

View File

@@ -2264,7 +2264,7 @@ export default {
quotaLimitAmount: 'Total Limit',
quotaLimitAmountHint: 'Cumulative spending limit. Does not auto-reset.',
quotaNotify: {
alert: 'Alert Threshold',
alert: 'Alert',
enabled: 'Enable Alert',
threshold: 'Alert Amount',
thresholdPlaceholder: 'Enter percentage',

View File

@@ -2262,7 +2262,7 @@ export default {
quotaLimitAmount: '总限额',
quotaLimitAmountHint: '累计消费上限,不会自动重置。',
quotaNotify: {
alert: '告警阈值',
alert: '提醒阈值',
enabled: '启用告警',
threshold: '告警金额',
thresholdPlaceholder: '输入百分比',