feat(license): 支持在租户平台修改 License 过期时间
描述详情框中的过期时间行增加内联日期选择器,与最大设备数保持 相同的行内编辑交互,支持设置具体日期或留空(永久有效)。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
c4373c8cc1
当前提交
f3c58866df
@ -104,7 +104,7 @@ export const licenseApi = {
|
||||
)
|
||||
},
|
||||
|
||||
updateAppLicense(appKey: string, data: { maxDevices?: number; isActive?: boolean; remark?: string }) {
|
||||
updateAppLicense(appKey: string, data: { maxDevices?: number; isActive?: boolean; remark?: string; expiresAt?: string }) {
|
||||
return licenseClient.patch<{ data: AppLicense }>(
|
||||
`/api/license/admin/apps/${encodeURIComponent(appKey)}`,
|
||||
data,
|
||||
|
||||
@ -64,7 +64,22 @@
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="已注册设备">{{ license?.registeredDevices ?? devices.length }}</el-descriptions-item>
|
||||
<el-descriptions-item label="过期时间">
|
||||
{{ license?.expiresAt ? formatDate(license.expiresAt) : '永久' }}
|
||||
<div v-if="!editingExpiresAt" class="max-devices-display">
|
||||
<span>{{ license?.expiresAt ? formatDate(license.expiresAt) : '永久' }}</span>
|
||||
<el-button link type="primary" size="small" style="margin-left:8px" @click="startEditExpiresAt">修改</el-button>
|
||||
</div>
|
||||
<div v-else class="max-devices-edit">
|
||||
<el-date-picker
|
||||
v-model="editExpiresAtValue"
|
||||
type="datetime"
|
||||
placeholder="留空表示永久"
|
||||
clearable
|
||||
style="width:200px"
|
||||
size="small"
|
||||
/>
|
||||
<el-button type="primary" size="small" :loading="savingExpiresAt" style="margin-left:8px" @click="saveExpiresAt">保存</el-button>
|
||||
<el-button size="small" style="margin-left:4px" @click="editingExpiresAt = false">取消</el-button>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
@ -163,6 +178,9 @@ const loading = ref(false)
|
||||
const editingMaxDevices = ref(false)
|
||||
const editMaxDevicesValue = ref(1)
|
||||
const savingMaxDevices = ref(false)
|
||||
const editingExpiresAt = ref(false)
|
||||
const editExpiresAtValue = ref<Date | null>(null)
|
||||
const savingExpiresAt = ref(false)
|
||||
|
||||
const appName = computed(() => currentApp.value?.name || license.value?.name || appKey.value || '-')
|
||||
const activeDevices = computed(() => devices.value.filter(d => d.isActive).length)
|
||||
@ -213,6 +231,28 @@ async function saveMaxDevices() {
|
||||
}
|
||||
}
|
||||
|
||||
function startEditExpiresAt() {
|
||||
editExpiresAtValue.value = license.value?.expiresAt ? new Date(license.value.expiresAt) : null
|
||||
editingExpiresAt.value = true
|
||||
}
|
||||
|
||||
async function saveExpiresAt() {
|
||||
const key = appKey.value
|
||||
if (!key) return
|
||||
savingExpiresAt.value = true
|
||||
try {
|
||||
const expiresAt = editExpiresAtValue.value ? editExpiresAtValue.value.toISOString() : ''
|
||||
const res = await licenseApi.updateAppLicense(key, { expiresAt })
|
||||
license.value = res.data.data
|
||||
editingExpiresAt.value = false
|
||||
ElMessage.success('过期时间已更新')
|
||||
} catch {
|
||||
ElMessage.error('更新失败')
|
||||
} finally {
|
||||
savingExpiresAt.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function revokeDevice(row: LicenseDevice) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认吊销该设备?', '吊销确认', { type: 'warning' })
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户