mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-04-27 09:28:37 +00:00
feat: add per-API-key weekly cost reset day/hour configuration
Allow each API key to configure its own weekly reset day (1-7, Mon-Sun) and hour (0-23) so the relay service's weekly limit tracking can align with upstream Claude account reset schedules instead of using a fixed Monday 00:00 boundary for all keys.
This commit is contained in:
@@ -246,8 +246,45 @@
|
||||
type="number"
|
||||
/>
|
||||
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
||||
设置 Claude 模型的周费用限制(周一到周日),仅对 Claude 模型请求生效
|
||||
设置 Claude 模型的周费用限制,仅对 Claude 模型请求生效
|
||||
</p>
|
||||
<div
|
||||
v-if="form.weeklyOpusCostLimit && Number(form.weeklyOpusCostLimit) > 0"
|
||||
class="mt-2 flex gap-3"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400"
|
||||
>重置日</label
|
||||
>
|
||||
<select
|
||||
v-model="form.weeklyResetDay"
|
||||
class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
|
||||
>
|
||||
<option value="">不修改</option>
|
||||
<option :value="1">周一</option>
|
||||
<option :value="2">周二</option>
|
||||
<option :value="3">周三</option>
|
||||
<option :value="4">周四</option>
|
||||
<option :value="5">周五</option>
|
||||
<option :value="6">周六</option>
|
||||
<option :value="7">周日</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400"
|
||||
>重置时间 (UTC+8)</label
|
||||
>
|
||||
<select
|
||||
v-model="form.weeklyResetHour"
|
||||
class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
|
||||
>
|
||||
<option value="">不修改</option>
|
||||
<option v-for="h in 24" :key="h - 1" :value="h - 1">
|
||||
{{ String(h - 1).padStart(2, '0') }}:00
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 并发限制 -->
|
||||
@@ -511,6 +548,8 @@ const form = reactive({
|
||||
dailyCostLimit: '',
|
||||
totalCostLimit: '',
|
||||
weeklyOpusCostLimit: '', // 新增Claude周费用限制
|
||||
weeklyResetDay: '',
|
||||
weeklyResetHour: '',
|
||||
permissions: '', // 空字符串表示不修改
|
||||
claudeAccountId: '',
|
||||
geminiAccountId: '',
|
||||
@@ -737,6 +776,12 @@ const batchUpdateApiKeys = async () => {
|
||||
if (form.weeklyOpusCostLimit !== '' && form.weeklyOpusCostLimit !== null) {
|
||||
updates.weeklyOpusCostLimit = parseFloat(form.weeklyOpusCostLimit)
|
||||
}
|
||||
if (form.weeklyResetDay !== '' && form.weeklyResetDay !== null) {
|
||||
updates.weeklyResetDay = Number(form.weeklyResetDay)
|
||||
}
|
||||
if (form.weeklyResetHour !== '' && form.weeklyResetHour !== null) {
|
||||
updates.weeklyResetHour = Number(form.weeklyResetHour)
|
||||
}
|
||||
|
||||
// 权限设置
|
||||
if (form.permissions !== '') {
|
||||
|
||||
@@ -428,9 +428,43 @@
|
||||
type="number"
|
||||
/>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||
设置 Claude 模型的周费用限制(周一到周日),仅对 Claude 模型请求生效,0
|
||||
或留空表示无限制
|
||||
设置 Claude 模型的周费用限制,仅对 Claude 模型请求生效,0 或留空表示无限制
|
||||
</p>
|
||||
<div
|
||||
v-if="form.weeklyOpusCostLimit && Number(form.weeklyOpusCostLimit) > 0"
|
||||
class="mt-2 flex gap-3"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400"
|
||||
>重置日</label
|
||||
>
|
||||
<select
|
||||
v-model="form.weeklyResetDay"
|
||||
class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
|
||||
>
|
||||
<option :value="1">周一</option>
|
||||
<option :value="2">周二</option>
|
||||
<option :value="3">周三</option>
|
||||
<option :value="4">周四</option>
|
||||
<option :value="5">周五</option>
|
||||
<option :value="6">周六</option>
|
||||
<option :value="7">周日</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400"
|
||||
>重置时间 (UTC+8)</label
|
||||
>
|
||||
<select
|
||||
v-model="form.weeklyResetHour"
|
||||
class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
|
||||
>
|
||||
<option v-for="h in 24" :key="h - 1" :value="h - 1">
|
||||
{{ String(h - 1).padStart(2, '0') }}:00
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1061,6 +1095,8 @@ const form = reactive({
|
||||
dailyCostLimit: '',
|
||||
totalCostLimit: '',
|
||||
weeklyOpusCostLimit: '',
|
||||
weeklyResetDay: 1,
|
||||
weeklyResetHour: 0,
|
||||
expireDuration: '',
|
||||
customExpireDate: '',
|
||||
expiresAt: null,
|
||||
@@ -1495,6 +1531,8 @@ const createApiKey = async () => {
|
||||
form.weeklyOpusCostLimit !== '' && form.weeklyOpusCostLimit !== null
|
||||
? parseFloat(form.weeklyOpusCostLimit)
|
||||
: 0,
|
||||
weeklyResetDay: form.weeklyResetDay,
|
||||
weeklyResetHour: form.weeklyResetHour,
|
||||
expiresAt: form.expirationMode === 'fixed' ? form.expiresAt || undefined : undefined,
|
||||
expirationMode: form.expirationMode,
|
||||
activationDays: form.expirationMode === 'activation' ? form.activationDays : undefined,
|
||||
|
||||
@@ -411,9 +411,43 @@
|
||||
type="number"
|
||||
/>
|
||||
<p class="text-xs text-gray-500 dark:text-gray-400">
|
||||
设置 Claude 模型的周费用限制(周一到周日),仅对 Claude 模型请求生效,0
|
||||
或留空表示无限制
|
||||
设置 Claude 模型的周费用限制,仅对 Claude 模型请求生效,0 或留空表示无限制
|
||||
</p>
|
||||
<div
|
||||
v-if="form.weeklyOpusCostLimit && Number(form.weeklyOpusCostLimit) > 0"
|
||||
class="mt-3 flex gap-3"
|
||||
>
|
||||
<div class="flex-1">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400"
|
||||
>重置日</label
|
||||
>
|
||||
<select
|
||||
v-model="form.weeklyResetDay"
|
||||
class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
|
||||
>
|
||||
<option :value="1">周一</option>
|
||||
<option :value="2">周二</option>
|
||||
<option :value="3">周三</option>
|
||||
<option :value="4">周四</option>
|
||||
<option :value="5">周五</option>
|
||||
<option :value="6">周六</option>
|
||||
<option :value="7">周日</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400"
|
||||
>重置时间 (UTC+8)</label
|
||||
>
|
||||
<select
|
||||
v-model="form.weeklyResetHour"
|
||||
class="form-input w-full border-gray-300 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
|
||||
>
|
||||
<option v-for="h in 24" :key="h - 1" :value="h - 1">
|
||||
{{ String(h - 1).padStart(2, '0') }}:00
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -901,6 +935,8 @@ const form = reactive({
|
||||
dailyCostLimit: '',
|
||||
totalCostLimit: '',
|
||||
weeklyOpusCostLimit: '',
|
||||
weeklyResetDay: 1,
|
||||
weeklyResetHour: 0,
|
||||
permissions: [], // 数组格式,空数组表示全部服务
|
||||
claudeAccountId: '',
|
||||
geminiAccountId: '',
|
||||
@@ -1033,6 +1069,8 @@ const updateApiKey = async () => {
|
||||
form.weeklyOpusCostLimit !== '' && form.weeklyOpusCostLimit !== null
|
||||
? parseFloat(form.weeklyOpusCostLimit)
|
||||
: 0,
|
||||
weeklyResetDay: form.weeklyResetDay,
|
||||
weeklyResetHour: form.weeklyResetHour,
|
||||
permissions: form.permissions,
|
||||
tags: form.tags
|
||||
}
|
||||
@@ -1355,6 +1393,8 @@ onMounted(async () => {
|
||||
form.dailyCostLimit = props.apiKey.dailyCostLimit || ''
|
||||
form.totalCostLimit = props.apiKey.totalCostLimit || ''
|
||||
form.weeklyOpusCostLimit = props.apiKey.weeklyOpusCostLimit || ''
|
||||
form.weeklyResetDay = props.apiKey.weeklyResetDay || 1
|
||||
form.weeklyResetHour = props.apiKey.weeklyResetHour || 0
|
||||
// 处理权限数据,兼容旧格式(字符串)和新格式(数组)
|
||||
// 有效的权限值
|
||||
const VALID_PERMS = ['claude', 'gemini', 'openai', 'droid']
|
||||
|
||||
@@ -186,6 +186,17 @@
|
||||
:style="{ width: getOpusWeeklyCostProgress() + '%' }"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
v-if="statsData.limits.weeklyResetDay"
|
||||
class="mt-1 text-xs text-gray-400 dark:text-gray-500"
|
||||
>
|
||||
每{{
|
||||
['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'][
|
||||
statsData.limits.weeklyResetDay || 1
|
||||
]
|
||||
}}
|
||||
{{ String(statsData.limits.weeklyResetHour || 0).padStart(2, '0') }}:00 (UTC+8) 重置
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- 时间窗口限制 -->
|
||||
|
||||
Reference in New Issue
Block a user