feat: 🎸 export csv from web and support hourly TTL of key

This commit is contained in:
yaogdu
2025-09-27 13:36:50 +08:00
committed by duyaoguang
parent c8b72b4eaa
commit d1bbc71796
7 changed files with 429 additions and 28 deletions

View File

@@ -492,11 +492,11 @@
<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
<span v-if="form.expirationMode === 'fixed'">
<i class="fas fa-info-circle mr-1" />
固定时间模式Key 创建后立即生效按设定时间过期
固定时间模式Key 创建后立即生效按设定时间过期支持小时和天数
</span>
<span v-else>
<i class="fas fa-info-circle mr-1" />
激活模式Key 首次使用时激活激活后按设定天数过期适合批量销售
激活模式Key 首次使用时激活激活后按设定时间过期支持小时和天数适合批量销售
</span>
</p>
</div>
@@ -509,6 +509,10 @@
@change="updateExpireAt"
>
<option value="">永不过期</option>
<option value="1h">1 小时</option>
<option value="3h">3 小时</option>
<option value="6h">6 小时</option>
<option value="12h">12 小时</option>
<option value="1d">1 </option>
<option value="7d">7 </option>
<option value="30d">30 </option>
@@ -537,27 +541,36 @@
<input
v-model.number="form.activationDays"
class="form-input flex-1 border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
max="3650"
:max="form.activationUnit === 'hours' ? 8760 : 3650"
min="1"
placeholder="输入天数"
:placeholder="form.activationUnit === 'hours' ? '输入小时数' : '输入天数'"
type="number"
/>
<span class="text-sm text-gray-600 dark:text-gray-400"></span>
<select
v-model="form.activationUnit"
class="form-input w-20 border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200"
@change="updateActivationValue"
>
<option value="hours">小时</option>
<option value="days"></option>
</select>
</div>
<div class="mt-2 flex flex-wrap gap-2">
<button
v-for="days in [30, 90, 180, 365]"
:key="days"
v-for="value in getQuickTimeOptions()"
:key="value.value"
class="rounded-md border border-gray-300 px-3 py-1 text-xs hover:bg-gray-100 dark:border-gray-600 dark:hover:bg-gray-700"
type="button"
@click="form.activationDays = days"
@click="form.activationDays = value.value"
>
{{ days }}
{{ value.label }}
</button>
</div>
<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
<i class="fas fa-clock mr-1" />
Key 将在首次使用后激活激活后 {{ form.activationDays || 30 }} 天过期
Key 将在首次使用后激活激活后
{{ form.activationDays || (form.activationUnit === 'hours' ? 24 : 30) }}
{{ form.activationUnit === 'hours' ? '小时' : '天' }}过期
</p>
</div>
</div>
@@ -917,6 +930,7 @@ const form = reactive({
expiresAt: null,
expirationMode: 'fixed', // 过期模式fixed(固定) 或 activation(激活)
activationDays: 30, // 激活后有效天数
activationUnit: 'days', // 激活时间单位hours 或 days
permissions: 'all',
claudeAccountId: '',
geminiAccountId: '',
@@ -1185,6 +1199,40 @@ const removeTag = (index) => {
form.tags.splice(index, 1)
}
// 获取快捷时间选项
const getQuickTimeOptions = () => {
if (form.activationUnit === 'hours') {
return [
{ value: 1, label: '1小时' },
{ value: 3, label: '3小时' },
{ value: 6, label: '6小时' },
{ value: 12, label: '12小时' }
]
} else {
return [
{ value: 30, label: '30天' },
{ value: 90, label: '90天' },
{ value: 180, label: '180天' },
{ value: 365, label: '365天' }
]
}
}
// 单位变化时更新数值
const updateActivationValue = () => {
if (form.activationUnit === 'hours') {
// 从天切换到小时,设置一个合理的默认值
if (form.activationDays > 24) {
form.activationDays = 24
}
} else {
// 从小时切换到天,设置一个合理的默认值
if (form.activationDays < 1) {
form.activationDays = 1
}
}
}
// 创建 API Key
const createApiKey = async () => {
// 验证表单
@@ -1260,6 +1308,7 @@ const createApiKey = async () => {
expiresAt: form.expirationMode === 'fixed' ? form.expiresAt || undefined : undefined,
expirationMode: form.expirationMode,
activationDays: form.expirationMode === 'activation' ? form.activationDays : undefined,
activationUnit: form.expirationMode === 'activation' ? form.activationUnit : undefined,
permissions: form.permissions,
tags: form.tags.length > 0 ? form.tags : undefined,
enableModelRestriction: form.enableModelRestriction,

View File

@@ -46,7 +46,9 @@
<i class="fas fa-pause-circle mr-1 text-blue-500" />
未激活
<span class="ml-2 text-xs font-normal text-gray-600">
(激活后 {{ apiKey.activationDays || 30 }} 天过期)
(激活后
{{ apiKey.activationDays || (apiKey.activationUnit === 'hours' ? 24 : 30) }}
{{ apiKey.activationUnit === 'hours' ? '小时' : '天' }}过期)
</span>
</template>
<!-- 已设置过期时间 -->
@@ -89,11 +91,15 @@
@click="handleActivateNow"
>
<i class="fas fa-rocket mr-2" />
立即激活 (激活后 {{ apiKey.activationDays || 30 }} 天过期)
立即激活 (激活后
{{ apiKey.activationDays || (apiKey.activationUnit === 'hours' ? 24 : 30) }}
{{ apiKey.activationUnit === 'hours' ? '小时' : '天' }}过期)
</button>
<p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
<i class="fas fa-info-circle mr-1" />
点击立即激活此 API Key激活后将在 {{ apiKey.activationDays || 30 }} 天后过期
点击立即激活此 API Key激活后将在
{{ apiKey.activationDays || (apiKey.activationUnit === 'hours' ? 24 : 30) }}
{{ apiKey.activationUnit === 'hours' ? '小时' : '天' }}后过期
</p>
</div>
@@ -400,14 +406,14 @@ const handleActivateNow = async () => {
if (window.showConfirm) {
confirmed = await window.showConfirm(
'激活 API Key',
`确定要立即激活此 API Key 吗?激活后将在 ${props.apiKey.activationDays || 30} 后自动过期。`,
`确定要立即激活此 API Key 吗?激活后将在 ${props.apiKey.activationDays || (props.apiKey.activationUnit === 'hours' ? 24 : 30)} ${props.apiKey.activationUnit === 'hours' ? '小时' : '天'}后自动过期。`,
'确定激活',
'取消'
)
} else {
// 降级方案
confirmed = confirm(
`确定要立即激活此 API Key 吗?激活后将在 ${props.apiKey.activationDays || 30} 后自动过期。`
`确定要立即激活此 API Key 吗?激活后将在 ${props.apiKey.activationDays || (props.apiKey.activationUnit === 'hours' ? 24 : 30)} ${props.apiKey.activationUnit === 'hours' ? '小时' : '天'}后自动过期。`
)
}

View File

@@ -123,7 +123,9 @@
<i class="fas fa-pause-circle mr-1 text-xs md:text-sm" />
未激活
<span class="ml-1 text-xs text-gray-500 dark:text-gray-400"
>(首次使用后{{ statsData.activationDays || 30 }}天过期)</span
>(首次使用后
{{ statsData.activationDays || (statsData.activationUnit === 'hours' ? 24 : 30)
}}{{ statsData.activationUnit === 'hours' ? '小时' : '天' }}过期)</span
>
</div>
<!-- 已设置过期时间 -->