mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-03 06:52:13 +08:00
Merge pull request #969 from wucm667/feat/quota-fixed-reset-mode
feat: 账号配额支持固定时间重置模式
This commit is contained in:
@@ -942,11 +942,23 @@ const makeQuotaBar = (
|
||||
let resetsAt: string | null = null
|
||||
if (startKey) {
|
||||
const extra = props.account.extra as Record<string, unknown> | undefined
|
||||
const startStr = extra?.[startKey] as string | undefined
|
||||
if (startStr) {
|
||||
const startDate = new Date(startStr)
|
||||
const periodMs = startKey.includes('daily') ? 24 * 60 * 60 * 1000 : 7 * 24 * 60 * 60 * 1000
|
||||
resetsAt = new Date(startDate.getTime() + periodMs).toISOString()
|
||||
const isDaily = startKey.includes('daily')
|
||||
const mode = isDaily
|
||||
? (extra?.quota_daily_reset_mode as string) || 'rolling'
|
||||
: (extra?.quota_weekly_reset_mode as string) || 'rolling'
|
||||
|
||||
if (mode === 'fixed') {
|
||||
// Use pre-computed next reset time for fixed mode
|
||||
const resetAtKey = isDaily ? 'quota_daily_reset_at' : 'quota_weekly_reset_at'
|
||||
resetsAt = (extra?.[resetAtKey] as string) || null
|
||||
} else {
|
||||
// Rolling mode: compute from start + period
|
||||
const startStr = extra?.[startKey] as string | undefined
|
||||
if (startStr) {
|
||||
const startDate = new Date(startStr)
|
||||
const periodMs = isDaily ? 24 * 60 * 60 * 1000 : 7 * 24 * 60 * 60 * 1000
|
||||
resetsAt = new Date(startDate.getTime() + periodMs).toISOString()
|
||||
}
|
||||
}
|
||||
}
|
||||
return { utilization, resetsAt }
|
||||
|
||||
@@ -1568,9 +1568,21 @@
|
||||
:totalLimit="editQuotaLimit"
|
||||
:dailyLimit="editQuotaDailyLimit"
|
||||
:weeklyLimit="editQuotaWeeklyLimit"
|
||||
:dailyResetMode="editDailyResetMode"
|
||||
:dailyResetHour="editDailyResetHour"
|
||||
:weeklyResetMode="editWeeklyResetMode"
|
||||
:weeklyResetDay="editWeeklyResetDay"
|
||||
:weeklyResetHour="editWeeklyResetHour"
|
||||
:resetTimezone="editResetTimezone"
|
||||
@update:totalLimit="editQuotaLimit = $event"
|
||||
@update:dailyLimit="editQuotaDailyLimit = $event"
|
||||
@update:weeklyLimit="editQuotaWeeklyLimit = $event"
|
||||
@update:dailyResetMode="editDailyResetMode = $event"
|
||||
@update:dailyResetHour="editDailyResetHour = $event"
|
||||
@update:weeklyResetMode="editWeeklyResetMode = $event"
|
||||
@update:weeklyResetDay="editWeeklyResetDay = $event"
|
||||
@update:weeklyResetHour="editWeeklyResetHour = $event"
|
||||
@update:resetTimezone="editResetTimezone = $event"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -2955,6 +2967,12 @@ const apiKeyValue = ref('')
|
||||
const editQuotaLimit = ref<number | null>(null)
|
||||
const editQuotaDailyLimit = ref<number | null>(null)
|
||||
const editQuotaWeeklyLimit = ref<number | null>(null)
|
||||
const editDailyResetMode = ref<'rolling' | 'fixed' | null>(null)
|
||||
const editDailyResetHour = ref<number | null>(null)
|
||||
const editWeeklyResetMode = ref<'rolling' | 'fixed' | null>(null)
|
||||
const editWeeklyResetDay = ref<number | null>(null)
|
||||
const editWeeklyResetHour = ref<number | null>(null)
|
||||
const editResetTimezone = ref<string | null>(null)
|
||||
const modelMappings = ref<ModelMapping[]>([])
|
||||
const modelRestrictionMode = ref<'whitelist' | 'mapping'>('whitelist')
|
||||
const allowedModels = ref<string[]>([])
|
||||
@@ -3651,6 +3669,12 @@ const resetForm = () => {
|
||||
editQuotaLimit.value = null
|
||||
editQuotaDailyLimit.value = null
|
||||
editQuotaWeeklyLimit.value = null
|
||||
editDailyResetMode.value = null
|
||||
editDailyResetHour.value = null
|
||||
editWeeklyResetMode.value = null
|
||||
editWeeklyResetDay.value = null
|
||||
editWeeklyResetHour.value = null
|
||||
editResetTimezone.value = null
|
||||
modelMappings.value = []
|
||||
modelRestrictionMode.value = 'whitelist'
|
||||
allowedModels.value = [...claudeModels] // Default fill related models
|
||||
@@ -4158,6 +4182,19 @@ const createAccountAndFinish = async (
|
||||
if (editQuotaWeeklyLimit.value != null && editQuotaWeeklyLimit.value > 0) {
|
||||
quotaExtra.quota_weekly_limit = editQuotaWeeklyLimit.value
|
||||
}
|
||||
// Quota reset mode config
|
||||
if (editDailyResetMode.value === 'fixed') {
|
||||
quotaExtra.quota_daily_reset_mode = 'fixed'
|
||||
quotaExtra.quota_daily_reset_hour = editDailyResetHour.value ?? 0
|
||||
}
|
||||
if (editWeeklyResetMode.value === 'fixed') {
|
||||
quotaExtra.quota_weekly_reset_mode = 'fixed'
|
||||
quotaExtra.quota_weekly_reset_day = editWeeklyResetDay.value ?? 1
|
||||
quotaExtra.quota_weekly_reset_hour = editWeeklyResetHour.value ?? 0
|
||||
}
|
||||
if (editDailyResetMode.value === 'fixed' || editWeeklyResetMode.value === 'fixed') {
|
||||
quotaExtra.quota_reset_timezone = editResetTimezone.value || 'UTC'
|
||||
}
|
||||
if (Object.keys(quotaExtra).length > 0) {
|
||||
finalExtra = quotaExtra
|
||||
}
|
||||
|
||||
@@ -1161,9 +1161,21 @@
|
||||
:totalLimit="editQuotaLimit"
|
||||
:dailyLimit="editQuotaDailyLimit"
|
||||
:weeklyLimit="editQuotaWeeklyLimit"
|
||||
:dailyResetMode="editDailyResetMode"
|
||||
:dailyResetHour="editDailyResetHour"
|
||||
:weeklyResetMode="editWeeklyResetMode"
|
||||
:weeklyResetDay="editWeeklyResetDay"
|
||||
:weeklyResetHour="editWeeklyResetHour"
|
||||
:resetTimezone="editResetTimezone"
|
||||
@update:totalLimit="editQuotaLimit = $event"
|
||||
@update:dailyLimit="editQuotaDailyLimit = $event"
|
||||
@update:weeklyLimit="editQuotaWeeklyLimit = $event"
|
||||
@update:dailyResetMode="editDailyResetMode = $event"
|
||||
@update:dailyResetHour="editDailyResetHour = $event"
|
||||
@update:weeklyResetMode="editWeeklyResetMode = $event"
|
||||
@update:weeklyResetDay="editWeeklyResetDay = $event"
|
||||
@update:weeklyResetHour="editWeeklyResetHour = $event"
|
||||
@update:resetTimezone="editResetTimezone = $event"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1814,6 +1826,12 @@ const anthropicPassthroughEnabled = ref(false)
|
||||
const editQuotaLimit = ref<number | null>(null)
|
||||
const editQuotaDailyLimit = ref<number | null>(null)
|
||||
const editQuotaWeeklyLimit = ref<number | null>(null)
|
||||
const editDailyResetMode = ref<'rolling' | 'fixed' | null>(null)
|
||||
const editDailyResetHour = ref<number | null>(null)
|
||||
const editWeeklyResetMode = ref<'rolling' | 'fixed' | null>(null)
|
||||
const editWeeklyResetDay = ref<number | null>(null)
|
||||
const editWeeklyResetHour = ref<number | null>(null)
|
||||
const editResetTimezone = ref<string | null>(null)
|
||||
const openAIWSModeOptions = computed(() => [
|
||||
{ value: OPENAI_WS_MODE_OFF, label: t('admin.accounts.openai.wsModeOff') },
|
||||
// TODO: ctx_pool 选项暂时隐藏,待测试完成后恢复
|
||||
@@ -2001,10 +2019,23 @@ watch(
|
||||
editQuotaDailyLimit.value = (dailyVal && dailyVal > 0) ? dailyVal : null
|
||||
const weeklyVal = extra?.quota_weekly_limit as number | undefined
|
||||
editQuotaWeeklyLimit.value = (weeklyVal && weeklyVal > 0) ? weeklyVal : null
|
||||
// Load quota reset mode config
|
||||
editDailyResetMode.value = (extra?.quota_daily_reset_mode as 'rolling' | 'fixed') || null
|
||||
editDailyResetHour.value = (extra?.quota_daily_reset_hour as number) ?? null
|
||||
editWeeklyResetMode.value = (extra?.quota_weekly_reset_mode as 'rolling' | 'fixed') || null
|
||||
editWeeklyResetDay.value = (extra?.quota_weekly_reset_day as number) ?? null
|
||||
editWeeklyResetHour.value = (extra?.quota_weekly_reset_hour as number) ?? null
|
||||
editResetTimezone.value = (extra?.quota_reset_timezone as string) || null
|
||||
} else {
|
||||
editQuotaLimit.value = null
|
||||
editQuotaDailyLimit.value = null
|
||||
editQuotaWeeklyLimit.value = null
|
||||
editDailyResetMode.value = null
|
||||
editDailyResetHour.value = null
|
||||
editWeeklyResetMode.value = null
|
||||
editWeeklyResetDay.value = null
|
||||
editWeeklyResetHour.value = null
|
||||
editResetTimezone.value = null
|
||||
}
|
||||
|
||||
// Load antigravity model mapping (Antigravity 只支持映射模式)
|
||||
@@ -2945,6 +2976,28 @@ const handleSubmit = async () => {
|
||||
} else {
|
||||
delete newExtra.quota_weekly_limit
|
||||
}
|
||||
// Quota reset mode config
|
||||
if (editDailyResetMode.value === 'fixed') {
|
||||
newExtra.quota_daily_reset_mode = 'fixed'
|
||||
newExtra.quota_daily_reset_hour = editDailyResetHour.value ?? 0
|
||||
} else {
|
||||
delete newExtra.quota_daily_reset_mode
|
||||
delete newExtra.quota_daily_reset_hour
|
||||
}
|
||||
if (editWeeklyResetMode.value === 'fixed') {
|
||||
newExtra.quota_weekly_reset_mode = 'fixed'
|
||||
newExtra.quota_weekly_reset_day = editWeeklyResetDay.value ?? 1
|
||||
newExtra.quota_weekly_reset_hour = editWeeklyResetHour.value ?? 0
|
||||
} else {
|
||||
delete newExtra.quota_weekly_reset_mode
|
||||
delete newExtra.quota_weekly_reset_day
|
||||
delete newExtra.quota_weekly_reset_hour
|
||||
}
|
||||
if (editDailyResetMode.value === 'fixed' || editWeeklyResetMode.value === 'fixed') {
|
||||
newExtra.quota_reset_timezone = editResetTimezone.value || 'UTC'
|
||||
} else {
|
||||
delete newExtra.quota_reset_timezone
|
||||
}
|
||||
updatePayload.extra = newExtra
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,24 @@ const props = defineProps<{
|
||||
totalLimit: number | null
|
||||
dailyLimit: number | null
|
||||
weeklyLimit: number | null
|
||||
dailyResetMode: 'rolling' | 'fixed' | null
|
||||
dailyResetHour: number | null
|
||||
weeklyResetMode: 'rolling' | 'fixed' | null
|
||||
weeklyResetDay: number | null
|
||||
weeklyResetHour: number | null
|
||||
resetTimezone: string | null
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:totalLimit': [value: number | null]
|
||||
'update:dailyLimit': [value: number | null]
|
||||
'update:weeklyLimit': [value: number | null]
|
||||
'update:dailyResetMode': [value: 'rolling' | 'fixed' | null]
|
||||
'update:dailyResetHour': [value: number | null]
|
||||
'update:weeklyResetMode': [value: 'rolling' | 'fixed' | null]
|
||||
'update:weeklyResetDay': [value: number | null]
|
||||
'update:weeklyResetHour': [value: number | null]
|
||||
'update:resetTimezone': [value: string | null]
|
||||
}>()
|
||||
|
||||
const enabled = computed(() =>
|
||||
@@ -35,9 +47,56 @@ watch(localEnabled, (val) => {
|
||||
emit('update:totalLimit', null)
|
||||
emit('update:dailyLimit', null)
|
||||
emit('update:weeklyLimit', null)
|
||||
emit('update:dailyResetMode', null)
|
||||
emit('update:dailyResetHour', null)
|
||||
emit('update:weeklyResetMode', null)
|
||||
emit('update:weeklyResetDay', null)
|
||||
emit('update:weeklyResetHour', null)
|
||||
emit('update:resetTimezone', null)
|
||||
}
|
||||
})
|
||||
|
||||
// Whether any fixed mode is active (to show timezone selector)
|
||||
const hasFixedMode = computed(() =>
|
||||
props.dailyResetMode === 'fixed' || props.weeklyResetMode === 'fixed'
|
||||
)
|
||||
|
||||
// Common timezone options
|
||||
const timezoneOptions = [
|
||||
'UTC',
|
||||
'Asia/Shanghai',
|
||||
'Asia/Tokyo',
|
||||
'Asia/Seoul',
|
||||
'Asia/Singapore',
|
||||
'Asia/Kolkata',
|
||||
'Asia/Dubai',
|
||||
'Europe/London',
|
||||
'Europe/Paris',
|
||||
'Europe/Berlin',
|
||||
'Europe/Moscow',
|
||||
'America/New_York',
|
||||
'America/Chicago',
|
||||
'America/Denver',
|
||||
'America/Los_Angeles',
|
||||
'America/Sao_Paulo',
|
||||
'Australia/Sydney',
|
||||
'Pacific/Auckland',
|
||||
]
|
||||
|
||||
// Hours for dropdown (0-23)
|
||||
const hourOptions = Array.from({ length: 24 }, (_, i) => i)
|
||||
|
||||
// Day of week options
|
||||
const dayOptions = [
|
||||
{ value: 1, key: 'monday' },
|
||||
{ value: 2, key: 'tuesday' },
|
||||
{ value: 3, key: 'wednesday' },
|
||||
{ value: 4, key: 'thursday' },
|
||||
{ value: 5, key: 'friday' },
|
||||
{ value: 6, key: 'saturday' },
|
||||
{ value: 0, key: 'sunday' },
|
||||
]
|
||||
|
||||
const onTotalInput = (e: Event) => {
|
||||
const raw = (e.target as HTMLInputElement).valueAsNumber
|
||||
emit('update:totalLimit', Number.isNaN(raw) ? null : raw)
|
||||
@@ -50,6 +109,25 @@ const onWeeklyInput = (e: Event) => {
|
||||
const raw = (e.target as HTMLInputElement).valueAsNumber
|
||||
emit('update:weeklyLimit', Number.isNaN(raw) ? null : raw)
|
||||
}
|
||||
|
||||
const onDailyModeChange = (e: Event) => {
|
||||
const val = (e.target as HTMLSelectElement).value as 'rolling' | 'fixed'
|
||||
emit('update:dailyResetMode', val)
|
||||
if (val === 'fixed') {
|
||||
if (props.dailyResetHour == null) emit('update:dailyResetHour', 0)
|
||||
if (!props.resetTimezone) emit('update:resetTimezone', 'UTC')
|
||||
}
|
||||
}
|
||||
|
||||
const onWeeklyModeChange = (e: Event) => {
|
||||
const val = (e.target as HTMLSelectElement).value as 'rolling' | 'fixed'
|
||||
emit('update:weeklyResetMode', val)
|
||||
if (val === 'fixed') {
|
||||
if (props.weeklyResetDay == null) emit('update:weeklyResetDay', 1)
|
||||
if (props.weeklyResetHour == null) emit('update:weeklyResetHour', 0)
|
||||
if (!props.resetTimezone) emit('update:resetTimezone', 'UTC')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -94,7 +172,37 @@ const onWeeklyInput = (e: Event) => {
|
||||
:placeholder="t('admin.accounts.quotaLimitPlaceholder')"
|
||||
/>
|
||||
</div>
|
||||
<p class="input-hint">{{ t('admin.accounts.quotaDailyLimitHint') }}</p>
|
||||
<!-- 日配额重置模式 -->
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<label class="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">{{ t('admin.accounts.quotaResetMode') }}</label>
|
||||
<select
|
||||
:value="dailyResetMode || 'rolling'"
|
||||
@change="onDailyModeChange"
|
||||
class="input py-1 text-xs"
|
||||
>
|
||||
<option value="rolling">{{ t('admin.accounts.quotaResetModeRolling') }}</option>
|
||||
<option value="fixed">{{ t('admin.accounts.quotaResetModeFixed') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- 固定模式:小时选择 -->
|
||||
<div v-if="dailyResetMode === 'fixed'" class="mt-2 flex items-center gap-2">
|
||||
<label class="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">{{ t('admin.accounts.quotaResetHour') }}</label>
|
||||
<select
|
||||
:value="dailyResetHour ?? 0"
|
||||
@change="emit('update:dailyResetHour', Number(($event.target as HTMLSelectElement).value))"
|
||||
class="input py-1 text-xs w-24"
|
||||
>
|
||||
<option v-for="h in hourOptions" :key="h" :value="h">{{ String(h).padStart(2, '0') }}:00</option>
|
||||
</select>
|
||||
</div>
|
||||
<p class="input-hint">
|
||||
<template v-if="dailyResetMode === 'fixed'">
|
||||
{{ t('admin.accounts.quotaDailyLimitHintFixed', { hour: String(dailyResetHour ?? 0).padStart(2, '0'), timezone: resetTimezone || 'UTC' }) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ t('admin.accounts.quotaDailyLimitHint') }}
|
||||
</template>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 周配额 -->
|
||||
@@ -112,7 +220,57 @@ const onWeeklyInput = (e: Event) => {
|
||||
:placeholder="t('admin.accounts.quotaLimitPlaceholder')"
|
||||
/>
|
||||
</div>
|
||||
<p class="input-hint">{{ t('admin.accounts.quotaWeeklyLimitHint') }}</p>
|
||||
<!-- 周配额重置模式 -->
|
||||
<div class="mt-2 flex items-center gap-2">
|
||||
<label class="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">{{ t('admin.accounts.quotaResetMode') }}</label>
|
||||
<select
|
||||
:value="weeklyResetMode || 'rolling'"
|
||||
@change="onWeeklyModeChange"
|
||||
class="input py-1 text-xs"
|
||||
>
|
||||
<option value="rolling">{{ t('admin.accounts.quotaResetModeRolling') }}</option>
|
||||
<option value="fixed">{{ t('admin.accounts.quotaResetModeFixed') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- 固定模式:星期几 + 小时 -->
|
||||
<div v-if="weeklyResetMode === 'fixed'" class="mt-2 flex items-center gap-2 flex-wrap">
|
||||
<label class="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">{{ t('admin.accounts.quotaWeeklyResetDay') }}</label>
|
||||
<select
|
||||
:value="weeklyResetDay ?? 1"
|
||||
@change="emit('update:weeklyResetDay', Number(($event.target as HTMLSelectElement).value))"
|
||||
class="input py-1 text-xs w-28"
|
||||
>
|
||||
<option v-for="d in dayOptions" :key="d.value" :value="d.value">{{ t('admin.accounts.dayOfWeek.' + d.key) }}</option>
|
||||
</select>
|
||||
<label class="text-xs text-gray-500 dark:text-gray-400 whitespace-nowrap">{{ t('admin.accounts.quotaResetHour') }}</label>
|
||||
<select
|
||||
:value="weeklyResetHour ?? 0"
|
||||
@change="emit('update:weeklyResetHour', Number(($event.target as HTMLSelectElement).value))"
|
||||
class="input py-1 text-xs w-24"
|
||||
>
|
||||
<option v-for="h in hourOptions" :key="h" :value="h">{{ String(h).padStart(2, '0') }}:00</option>
|
||||
</select>
|
||||
</div>
|
||||
<p class="input-hint">
|
||||
<template v-if="weeklyResetMode === 'fixed'">
|
||||
{{ t('admin.accounts.quotaWeeklyLimitHintFixed', { day: t('admin.accounts.dayOfWeek.' + (dayOptions.find(d => d.value === (weeklyResetDay ?? 1))?.key || 'monday')), hour: String(weeklyResetHour ?? 0).padStart(2, '0'), timezone: resetTimezone || 'UTC' }) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ t('admin.accounts.quotaWeeklyLimitHint') }}
|
||||
</template>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 时区选择(当任一维度使用固定模式时显示) -->
|
||||
<div v-if="hasFixedMode">
|
||||
<label class="input-label">{{ t('admin.accounts.quotaResetTimezone') }}</label>
|
||||
<select
|
||||
:value="resetTimezone || 'UTC'"
|
||||
@change="emit('update:resetTimezone', ($event.target as HTMLSelectElement).value)"
|
||||
class="input text-sm"
|
||||
>
|
||||
<option v-for="tz in timezoneOptions" :key="tz" :value="tz">{{ tz }}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 总配额 -->
|
||||
|
||||
@@ -1866,6 +1866,23 @@ export default {
|
||||
quotaWeeklyLimitHint: 'Automatically resets every 7 days from first usage.',
|
||||
quotaTotalLimit: 'Total Limit',
|
||||
quotaTotalLimitHint: 'Cumulative spending limit. Does not auto-reset — use "Reset Quota" to clear.',
|
||||
quotaResetMode: 'Reset Mode',
|
||||
quotaResetModeRolling: 'Rolling Window',
|
||||
quotaResetModeFixed: 'Fixed Time',
|
||||
quotaResetHour: 'Reset Hour',
|
||||
quotaWeeklyResetDay: 'Reset Day',
|
||||
quotaResetTimezone: 'Reset Timezone',
|
||||
quotaDailyLimitHintFixed: 'Resets daily at {hour}:00 ({timezone}).',
|
||||
quotaWeeklyLimitHintFixed: 'Resets every {day} at {hour}:00 ({timezone}).',
|
||||
dayOfWeek: {
|
||||
monday: 'Monday',
|
||||
tuesday: 'Tuesday',
|
||||
wednesday: 'Wednesday',
|
||||
thursday: 'Thursday',
|
||||
friday: 'Friday',
|
||||
saturday: 'Saturday',
|
||||
sunday: 'Sunday',
|
||||
},
|
||||
quotaLimitAmount: 'Total Limit',
|
||||
quotaLimitAmountHint: 'Cumulative spending limit. Does not auto-reset.',
|
||||
testConnection: 'Test Connection',
|
||||
|
||||
@@ -1872,6 +1872,23 @@ export default {
|
||||
quotaWeeklyLimitHint: '从首次使用起每 7 天自动重置。',
|
||||
quotaTotalLimit: '总限额',
|
||||
quotaTotalLimitHint: '累计消费上限,不会自动重置 — 使用「重置配额」手动清零。',
|
||||
quotaResetMode: '重置方式',
|
||||
quotaResetModeRolling: '滚动窗口',
|
||||
quotaResetModeFixed: '固定时间',
|
||||
quotaResetHour: '重置时间',
|
||||
quotaWeeklyResetDay: '重置日',
|
||||
quotaResetTimezone: '重置时区',
|
||||
quotaDailyLimitHintFixed: '每天 {hour}:00({timezone})重置。',
|
||||
quotaWeeklyLimitHintFixed: '每{day} {hour}:00({timezone})重置。',
|
||||
dayOfWeek: {
|
||||
monday: '周一',
|
||||
tuesday: '周二',
|
||||
wednesday: '周三',
|
||||
thursday: '周四',
|
||||
friday: '周五',
|
||||
saturday: '周六',
|
||||
sunday: '周日',
|
||||
},
|
||||
quotaLimitAmount: '总限额',
|
||||
quotaLimitAmountHint: '累计消费上限,不会自动重置。',
|
||||
testConnection: '测试连接',
|
||||
|
||||
@@ -727,6 +727,16 @@ export interface Account {
|
||||
quota_weekly_limit?: number | null
|
||||
quota_weekly_used?: number | null
|
||||
|
||||
// 配额固定时间重置配置
|
||||
quota_daily_reset_mode?: 'rolling' | 'fixed' | null
|
||||
quota_daily_reset_hour?: number | null
|
||||
quota_weekly_reset_mode?: 'rolling' | 'fixed' | null
|
||||
quota_weekly_reset_day?: number | null
|
||||
quota_weekly_reset_hour?: number | null
|
||||
quota_reset_timezone?: string | null
|
||||
quota_daily_reset_at?: string | null
|
||||
quota_weekly_reset_at?: string | null
|
||||
|
||||
// 运行时状态(仅当启用对应限制时返回)
|
||||
current_window_cost?: number | null // 当前窗口费用
|
||||
active_sessions?: number | null // 当前活跃会话数
|
||||
|
||||
Reference in New Issue
Block a user