mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-05-05 05:30:44 +08:00
Security (HIGH): - Normalize all Redis cache keys to lowercase (verifyCode, passwordReset) - Fix verify code TTL renewal on failed attempts: use remaining TTL via ExpiresAt field instead of resetting to full 15-minute window - Add 3 missing fields to diffSettings audit log (promo_code, invitation_code, custom_endpoints) Code quality (MEDIUM): - Extract filterVerifiedEmails shared helper (balance_notify_service.go) - Add Pricing array non-empty validation for channel pricing rules - Add platform token semantics comment in gateway_service.go - Complete validatePlanPatch test coverage (+10 test cases) - Replace string types with QuotaThresholdType/QuotaResetMode across frontend - Remove duplicate getPlatformTextColor/getRateBadgeClass in ChannelsView - Return EMAIL_NOT_FOUND error on RemoveNotifyEmail miss UI improvements: - Reorder cost tooltip: user billing above separator, account billing below - Add NaN guard to accountBilled function - Move timezone selector inline into reset-mode row (no longer standalone)
55 lines
2.0 KiB
Vue
55 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import { QUOTA_THRESHOLD_TYPE_FIXED, QUOTA_THRESHOLD_TYPE_PERCENTAGE, type QuotaThresholdType } from '@/constants/account'
|
|
|
|
defineProps<{
|
|
enabled: boolean | null
|
|
threshold: number | null
|
|
thresholdType: QuotaThresholdType | null
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
'update:enabled': [value: boolean | null]
|
|
'update:threshold': [value: number | null]
|
|
'update:thresholdType': [value: QuotaThresholdType | null]
|
|
}>()
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex items-center gap-1.5">
|
|
<button
|
|
type="button"
|
|
@click="emit('update:enabled', !enabled)"
|
|
:class="[
|
|
'relative inline-flex h-5 w-9 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none',
|
|
enabled ? 'bg-primary-600' : 'bg-gray-200 dark:bg-dark-600'
|
|
]"
|
|
>
|
|
<span
|
|
:class="[
|
|
'pointer-events-none inline-block h-4 w-4 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
|
|
enabled ? 'translate-x-4' : 'translate-x-0'
|
|
]"
|
|
/>
|
|
</button>
|
|
<template v-if="enabled">
|
|
<input
|
|
:value="threshold"
|
|
@input="emit('update:threshold', parseFloat(($event.target as HTMLInputElement).value) || null)"
|
|
type="number"
|
|
min="0"
|
|
:max="thresholdType === QUOTA_THRESHOLD_TYPE_PERCENTAGE ? 100 : undefined"
|
|
:step="thresholdType === QUOTA_THRESHOLD_TYPE_PERCENTAGE ? 1 : 0.01"
|
|
class="input py-1 text-sm flex-1 min-w-0"
|
|
/>
|
|
<select
|
|
:value="thresholdType || QUOTA_THRESHOLD_TYPE_FIXED"
|
|
@change="emit('update:thresholdType', ($event.target as HTMLSelectElement).value as QuotaThresholdType)"
|
|
class="input py-1 text-xs w-[4.5rem] flex-shrink-0 text-center"
|
|
>
|
|
<option :value="QUOTA_THRESHOLD_TYPE_FIXED">$</option>
|
|
<option :value="QUOTA_THRESHOLD_TYPE_PERCENTAGE">%</option>
|
|
</select>
|
|
</template>
|
|
</div>
|
|
</template>
|