feat: 更新许可证表单和授权信息展示,增加功能配置和自定义参数支持,优化国际化文本
This commit is contained in:
1 parent
22898510eb
commit
ce789093bd
8 files changed
+342
-98
No files matched your search
@@ -339,8 +339,9 @@
|
||||
"forActivation": "(For Client Activation)",
|
||||
"code": "Authorization Code",
|
||||
"tipText": "Provide this authorization code to the customer, who can automatically obtain the software license after configuring it in the software product",
|
||||
"customParameters": "Feature Settings",
|
||||
"featureConfig": "Feature Configuration",
|
||||
"usageLimits": "Usage Limits",
|
||||
"customParameters": "Custom Parameters",
|
||||
"typeColumn": "Type",
|
||||
"keyColumn": "Key",
|
||||
"valueColumn": "Value",
|
||||
@@ -449,8 +450,9 @@
|
||||
"sections": {
|
||||
"basicInfo": "Basic Information",
|
||||
"licenseConfig": "License Configuration",
|
||||
"customParameters": "Feature Settings",
|
||||
"usageLimits": "Usage Limits"
|
||||
"featureConfig": "Feature Configuration",
|
||||
"usageLimits": "Usage Limits",
|
||||
"customParameters": "Custom Parameters"
|
||||
},
|
||||
"fields": {
|
||||
"customerName": "Associated Customer Name",
|
||||
@@ -550,8 +552,9 @@
|
||||
"booleanFalse": "false",
|
||||
"validationFailed": "Fix the errors in feature or limit settings before submitting",
|
||||
"importJson": "Import JSON",
|
||||
"importTitleFeature": "Import Feature Settings JSON",
|
||||
"importTitleFeature": "Import Feature Configuration JSON",
|
||||
"importTitleLimit": "Import Usage Limits JSON",
|
||||
"importTitleCustom": "Import Custom Parameters JSON",
|
||||
"importDescription": "Paste a JSON object whose values can be string, number, or boolean. Confirming will overwrite current entries.",
|
||||
"importPlaceholder": "{ \"feature_dashboard\": \"enabled\" }",
|
||||
"importCancel": "Cancel",
|
||||
|
||||
@@ -339,8 +339,9 @@
|
||||
"forActivation": "(クライアントアクティベーション用)",
|
||||
"code": "認証コード",
|
||||
"tipText": "この認証コードを顧客に提供してください。顧客がソフトウェア製品で設定すると、ソフトウェアライセンスを自動的に取得できます",
|
||||
"customParameters": "機能設定",
|
||||
"usageLimits": "制限設定",
|
||||
"featureConfig": "機能構成",
|
||||
"usageLimits": "利用制限",
|
||||
"customParameters": "カスタムパラメータ",
|
||||
"typeColumn": "タイプ",
|
||||
"keyColumn": "キー",
|
||||
"valueColumn": "値",
|
||||
@@ -449,8 +450,9 @@
|
||||
"sections": {
|
||||
"basicInfo": "基本情報",
|
||||
"licenseConfig": "ライセンス設定",
|
||||
"customParameters": "機能設定",
|
||||
"usageLimits": "制限設定"
|
||||
"featureConfig": "機能構成",
|
||||
"usageLimits": "利用制限",
|
||||
"customParameters": "カスタムパラメータ"
|
||||
},
|
||||
"fields": {
|
||||
"customerName": "関連顧客名",
|
||||
@@ -550,8 +552,9 @@
|
||||
"booleanFalse": "false",
|
||||
"validationFailed": "送信前に機能設定または制限設定のエラーを修正してください",
|
||||
"importJson": "JSONをインポート",
|
||||
"importTitleFeature": "機能設定 JSON をインポート",
|
||||
"importTitleLimit": "制限設定 JSON をインポート",
|
||||
"importTitleFeature": "機能構成 JSON をインポート",
|
||||
"importTitleLimit": "利用制限 JSON をインポート",
|
||||
"importTitleCustom": "カスタムパラメータ JSON をインポート",
|
||||
"importDescription": "キーを設定名とするオブジェクト形式の JSON を貼り付けてください。値は文字列・数値・ブールをサポートします。確定すると現在のリストを上書きします。",
|
||||
"importPlaceholder": "{ \"feature_dashboard\": \"enabled\" }",
|
||||
"importCancel": "キャンセル",
|
||||
|
||||
@@ -339,8 +339,9 @@
|
||||
"forActivation": "(用于客户端激活)",
|
||||
"code": "授权码",
|
||||
"tipText": "将此授权码提供给客户,客户在软件产品中配置后可自动获取软件许可证",
|
||||
"customParameters": "功能设置",
|
||||
"usageLimits": "限制设置",
|
||||
"featureConfig": "功能配置",
|
||||
"usageLimits": "使用限制",
|
||||
"customParameters": "自定义参数",
|
||||
"typeColumn": "类型",
|
||||
"keyColumn": "键",
|
||||
"valueColumn": "值",
|
||||
@@ -449,8 +450,9 @@
|
||||
"sections": {
|
||||
"basicInfo": "基本信息",
|
||||
"licenseConfig": "授权配置",
|
||||
"customParameters": "功能设置",
|
||||
"usageLimits": "限制设置"
|
||||
"featureConfig": "功能配置",
|
||||
"usageLimits": "使用限制",
|
||||
"customParameters": "自定义参数"
|
||||
},
|
||||
"fields": {
|
||||
"customerName": "关联客户名称",
|
||||
@@ -550,8 +552,9 @@
|
||||
"booleanFalse": "false",
|
||||
"validationFailed": "请先修复功能或限制设置中的错误再提交",
|
||||
"importJson": "导入JSON",
|
||||
"importTitleFeature": "导入功能设置 JSON",
|
||||
"importTitleLimit": "导入限制设置 JSON",
|
||||
"importTitleFeature": "导入功能配置 JSON",
|
||||
"importTitleLimit": "导入使用限制 JSON",
|
||||
"importTitleCustom": "导入自定义参数 JSON",
|
||||
"importDescription": "粘贴一个对象格式的 JSON,键为配置项,值支持字符串、数字或布尔类型。提交后将覆盖当前列表。",
|
||||
"importPlaceholder": "{ \"feature_dashboard\": \"enabled\" }",
|
||||
"importCancel": "取消",
|
||||
|
||||
@@ -211,22 +211,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 功能设置 -->
|
||||
<!-- 功能配置 -->
|
||||
<div class="license-form">
|
||||
<div class="key-value-section-header">
|
||||
<h3 class="section-title">{{ t('pages.licenses.form.sections.customParameters') }}</h3>
|
||||
<h3 class="section-title">{{ t('pages.licenses.form.sections.featureConfig') }}</h3>
|
||||
<div class="key-value-section-actions">
|
||||
<el-button size="small" @click="addFeatureEntry">
|
||||
<el-button size="small" @click="addFeatureConfigEntry">
|
||||
{{ t('pages.licenses.form.keyValue.addItem') }}
|
||||
</el-button>
|
||||
<el-button size="small" text :disabled="!featureEntries.length" @click="clearFeatureEntries">
|
||||
<el-button
|
||||
size="small"
|
||||
text
|
||||
:disabled="!featureConfigEntries.length"
|
||||
@click="clearFeatureConfigEntries"
|
||||
>
|
||||
{{ t('pages.licenses.form.keyValue.clearAll') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
text
|
||||
:disabled="!featureJsonPreview"
|
||||
@click="copyJson(featureJsonPreview)"
|
||||
:disabled="!featureConfigPreview"
|
||||
@click="copyJson(featureConfigPreview)"
|
||||
>
|
||||
{{ t('pages.licenses.form.keyValue.copyJson') }}
|
||||
</el-button>
|
||||
@@ -237,7 +242,7 @@
|
||||
</div>
|
||||
|
||||
<div class="key-value-list">
|
||||
<div v-for="(item, index) in featureEntries" :key="item.id" class="key-value-row">
|
||||
<div v-for="(item, index) in featureConfigEntries" :key="item.id" class="key-value-row">
|
||||
<div class="key-value-field">
|
||||
<label>{{ t('pages.licenses.form.keyValue.keyLabel') }}</label>
|
||||
<el-input
|
||||
@@ -279,12 +284,12 @@
|
||||
/>
|
||||
<p v-if="item.valueError" class="key-value-error">{{ item.valueError }}</p>
|
||||
</div>
|
||||
<el-button link type="danger" @click="removeFeatureEntry(index)">
|
||||
<el-button link type="danger" @click="removeFeatureConfigEntry(index)">
|
||||
{{ t('pages.licenses.form.keyValue.remove') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-if="!featureEntries.length" class="key-value-empty">
|
||||
<div v-if="!featureConfigEntries.length" class="key-value-empty">
|
||||
{{ t('pages.licenses.form.keyValue.emptyState') }}
|
||||
</div>
|
||||
</div>
|
||||
@@ -293,7 +298,7 @@
|
||||
<div class="key-value-preview-label">
|
||||
{{ t('pages.licenses.form.keyValue.preview') }}
|
||||
</div>
|
||||
<el-input type="textarea" :rows="3" :model-value="featureJsonPreview" readonly />
|
||||
<el-input type="textarea" :rows="3" :model-value="featureConfigPreview" readonly />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -382,17 +387,99 @@
|
||||
<el-input type="textarea" :rows="3" :model-value="usageJsonPreview" readonly />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 自定义参数 -->
|
||||
<div class="license-form">
|
||||
<div class="key-value-section-header">
|
||||
<h3 class="section-title">{{ t('pages.licenses.form.sections.customParameters') }}</h3>
|
||||
<div class="key-value-section-actions">
|
||||
<el-button size="small" @click="addCustomEntry">
|
||||
{{ t('pages.licenses.form.keyValue.addItem') }}
|
||||
</el-button>
|
||||
<el-button size="small" text :disabled="!customEntries.length" @click="clearCustomEntries">
|
||||
{{ t('pages.licenses.form.keyValue.clearAll') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
text
|
||||
:disabled="!customJsonPreview"
|
||||
@click="copyJson(customJsonPreview)"
|
||||
>
|
||||
{{ t('pages.licenses.form.keyValue.copyJson') }}
|
||||
</el-button>
|
||||
<el-button size="small" text @click="openImportDialog('custom')">
|
||||
{{ t('pages.licenses.form.keyValue.importJson') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="key-value-list">
|
||||
<div v-for="(item, index) in customEntries" :key="item.id" class="key-value-row">
|
||||
<div class="key-value-field">
|
||||
<label>{{ t('pages.licenses.form.keyValue.keyLabel') }}</label>
|
||||
<el-input
|
||||
v-model="item.key"
|
||||
:placeholder="t('pages.licenses.form.keyValue.keyPlaceholder')"
|
||||
@input="item.keyError = ''"
|
||||
/>
|
||||
<p v-if="item.keyError" class="key-value-error">{{ item.keyError }}</p>
|
||||
</div>
|
||||
<div class="key-value-field type-field">
|
||||
<label>{{ t('pages.licenses.form.keyValue.typeLabel') }}</label>
|
||||
<el-select v-model="item.type" @change="handleEntryTypeChange(item)">
|
||||
<el-option
|
||||
v-for="type in typeOptions"
|
||||
:key="type"
|
||||
:label="t(`pages.licenses.form.keyValue.typeOptions.${type}`)"
|
||||
:value="type"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<div class="key-value-field">
|
||||
<label>{{ t('pages.licenses.form.keyValue.valueLabel') }}</label>
|
||||
<template v-if="item.type === 'bool'">
|
||||
<el-select v-model="item.value" @change="item.valueError = ''">
|
||||
<el-option
|
||||
v-for="option in boolOptions"
|
||||
:key="option.value"
|
||||
:label="option.label"
|
||||
:value="option.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<el-input
|
||||
v-else
|
||||
v-model="item.value"
|
||||
:placeholder="t('pages.licenses.form.keyValue.valuePlaceholder')"
|
||||
@input="item.valueError = ''"
|
||||
:inputmode="item.type === 'number' ? 'decimal' : 'text'"
|
||||
/>
|
||||
<p v-if="item.valueError" class="key-value-error">{{ item.valueError }}</p>
|
||||
</div>
|
||||
<el-button link type="danger" @click="removeCustomEntry(index)">
|
||||
{{ t('pages.licenses.form.keyValue.remove') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-if="!customEntries.length" class="key-value-empty">
|
||||
{{ t('pages.licenses.form.keyValue.emptyState') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="key-value-preview">
|
||||
<div class="key-value-preview-label">
|
||||
{{ t('pages.licenses.form.keyValue.preview') }}
|
||||
</div>
|
||||
<el-input type="textarea" :rows="3" :model-value="customJsonPreview" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="importDialogVisible"
|
||||
:title="
|
||||
importDialogTarget === 'feature'
|
||||
? t('pages.licenses.form.keyValue.importTitleFeature')
|
||||
: t('pages.licenses.form.keyValue.importTitleLimit')
|
||||
"
|
||||
:title="importDialogTitle"
|
||||
width="520px"
|
||||
destroy-on-close
|
||||
>
|
||||
@@ -462,10 +549,20 @@ const submitting = ref(false)
|
||||
const customerLoading = ref(false)
|
||||
const customerOptions = ref<Customer[]>([])
|
||||
|
||||
const featureEntries = ref<KeyValueItem[]>([])
|
||||
const featureConfigEntries = ref<KeyValueItem[]>([])
|
||||
const limitEntries = ref<KeyValueItem[]>([])
|
||||
const customEntries = ref<KeyValueItem[]>([])
|
||||
const importDialogVisible = ref(false)
|
||||
const importDialogTarget = ref<'feature' | 'limit'>('feature')
|
||||
const importDialogTarget = ref<'feature' | 'limit' | 'custom'>('feature')
|
||||
const importDialogTitle = computed(() => {
|
||||
if (importDialogTarget.value === 'limit') {
|
||||
return t('pages.licenses.form.keyValue.importTitleLimit')
|
||||
}
|
||||
if (importDialogTarget.value === 'custom') {
|
||||
return t('pages.licenses.form.keyValue.importTitleCustom')
|
||||
}
|
||||
return t('pages.licenses.form.keyValue.importTitleFeature')
|
||||
})
|
||||
const importDialogContent = ref('')
|
||||
const importDialogError = ref('')
|
||||
|
||||
@@ -497,8 +594,9 @@ const formData = reactive<
|
||||
// 独立的响应式变量
|
||||
const dateRange = ref<[string, string] | null>(null)
|
||||
|
||||
const featureJsonPreview = computed(() => buildJsonString(featureEntries.value))
|
||||
const featureConfigPreview = computed(() => buildJsonString(featureConfigEntries.value))
|
||||
const usageJsonPreview = computed(() => buildJsonString(limitEntries.value))
|
||||
const customJsonPreview = computed(() => buildJsonString(customEntries.value))
|
||||
|
||||
// 计算属性
|
||||
const isEdit = computed(() => {
|
||||
@@ -671,9 +769,9 @@ const convertValueByType = (value: string, type: KeyValueType) => {
|
||||
return value
|
||||
}
|
||||
|
||||
const buildJsonString = (entries: KeyValueItem[]) => {
|
||||
const buildJsonRecord = (entries: KeyValueItem[]) => {
|
||||
if (!entries.length) {
|
||||
return ''
|
||||
return null
|
||||
}
|
||||
const result: Record<string, string | number | boolean> = {}
|
||||
entries.forEach(item => {
|
||||
@@ -686,33 +784,50 @@ const buildJsonString = (entries: KeyValueItem[]) => {
|
||||
}
|
||||
}
|
||||
})
|
||||
return Object.keys(result).length ? JSON.stringify(result) : ''
|
||||
return Object.keys(result).length ? result : null
|
||||
}
|
||||
|
||||
const addFeatureEntry = () => {
|
||||
featureEntries.value.push(createEmptyEntry())
|
||||
const buildJsonString = (entries: KeyValueItem[]) => {
|
||||
const record = buildJsonRecord(entries)
|
||||
return record ? JSON.stringify(record) : ''
|
||||
}
|
||||
|
||||
const addFeatureConfigEntry = () => {
|
||||
featureConfigEntries.value.push(createEmptyEntry())
|
||||
}
|
||||
|
||||
const addLimitEntry = () => {
|
||||
limitEntries.value.push(createEmptyEntry())
|
||||
}
|
||||
|
||||
const removeFeatureEntry = (index: number) => {
|
||||
featureEntries.value.splice(index, 1)
|
||||
const addCustomEntry = () => {
|
||||
customEntries.value.push(createEmptyEntry())
|
||||
}
|
||||
|
||||
const removeFeatureConfigEntry = (index: number) => {
|
||||
featureConfigEntries.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const removeLimitEntry = (index: number) => {
|
||||
limitEntries.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const clearFeatureEntries = () => {
|
||||
featureEntries.value = []
|
||||
const removeCustomEntry = (index: number) => {
|
||||
customEntries.value.splice(index, 1)
|
||||
}
|
||||
|
||||
const clearFeatureConfigEntries = () => {
|
||||
featureConfigEntries.value = []
|
||||
}
|
||||
|
||||
const clearLimitEntries = () => {
|
||||
limitEntries.value = []
|
||||
}
|
||||
|
||||
const clearCustomEntries = () => {
|
||||
customEntries.value = []
|
||||
}
|
||||
|
||||
const handleEntryTypeChange = (entry: KeyValueItem) => {
|
||||
if (entry.type === 'bool') {
|
||||
entry.value = entry.value === 'false' ? 'false' : 'true'
|
||||
@@ -799,10 +914,14 @@ const validateKeyValueEntries = (entries: KeyValueItem[]) => {
|
||||
return isValid
|
||||
}
|
||||
|
||||
const openImportDialog = (target: 'feature' | 'limit') => {
|
||||
const openImportDialog = (target: 'feature' | 'limit' | 'custom') => {
|
||||
importDialogTarget.value = target
|
||||
importDialogContent.value =
|
||||
target === 'feature' ? featureJsonPreview.value : usageJsonPreview.value
|
||||
target === 'feature'
|
||||
? featureConfigPreview.value
|
||||
: target === 'limit'
|
||||
? usageJsonPreview.value
|
||||
: customJsonPreview.value
|
||||
importDialogError.value = ''
|
||||
importDialogVisible.value = true
|
||||
}
|
||||
@@ -813,9 +932,11 @@ const handleImportConfirm = () => {
|
||||
const content = importDialogContent.value.trim()
|
||||
if (!content) {
|
||||
if (importDialogTarget.value === 'feature') {
|
||||
featureEntries.value = []
|
||||
} else {
|
||||
featureConfigEntries.value = []
|
||||
} else if (importDialogTarget.value === 'limit') {
|
||||
limitEntries.value = []
|
||||
} else {
|
||||
customEntries.value = []
|
||||
}
|
||||
} else {
|
||||
const entries = parseJsonToEntries(content, { strict: true })
|
||||
@@ -823,9 +944,11 @@ const handleImportConfirm = () => {
|
||||
throw new Error(t('pages.licenses.form.keyValue.importEmpty'))
|
||||
}
|
||||
if (importDialogTarget.value === 'feature') {
|
||||
featureEntries.value = entries
|
||||
} else {
|
||||
featureConfigEntries.value = entries
|
||||
} else if (importDialogTarget.value === 'limit') {
|
||||
limitEntries.value = entries
|
||||
} else {
|
||||
customEntries.value = entries
|
||||
}
|
||||
}
|
||||
importDialogVisible.value = false
|
||||
@@ -1078,8 +1201,9 @@ const loadLicenseDetail = async () => {
|
||||
]
|
||||
}
|
||||
|
||||
hydrateEntriesFromField(data.custom_parameters, featureEntries)
|
||||
hydrateEntriesFromField(data.feature_config, featureConfigEntries)
|
||||
hydrateEntriesFromField(data.usage_limits, limitEntries)
|
||||
hydrateEntriesFromField(data.custom_parameters, customEntries)
|
||||
} else {
|
||||
throw new Error(response.message || t('pages.licenses.form.messages.loadDetailError'))
|
||||
}
|
||||
@@ -1102,15 +1226,17 @@ const handleSubmit = async () => {
|
||||
// 执行表单验证
|
||||
await formRef.value.validate()
|
||||
|
||||
const customValid = validateKeyValueEntries(featureEntries.value)
|
||||
const featureConfigValid = validateKeyValueEntries(featureConfigEntries.value)
|
||||
const limitValid = validateKeyValueEntries(limitEntries.value)
|
||||
if (!customValid || !limitValid) {
|
||||
const customValid = validateKeyValueEntries(customEntries.value)
|
||||
if (!featureConfigValid || !limitValid || !customValid) {
|
||||
ElMessage.error(t('pages.licenses.form.keyValue.validationFailed'))
|
||||
return
|
||||
}
|
||||
|
||||
formData.custom_parameters = featureJsonPreview.value
|
||||
formData.feature_config = buildJsonRecord(featureConfigEntries.value) || {}
|
||||
formData.usage_limits = usageJsonPreview.value
|
||||
formData.custom_parameters = customJsonPreview.value
|
||||
|
||||
submitting.value = true
|
||||
|
||||
@@ -1200,17 +1326,25 @@ watch(
|
||||
)
|
||||
|
||||
watch(
|
||||
featureEntries,
|
||||
limitEntries,
|
||||
() => {
|
||||
formData.custom_parameters = featureJsonPreview.value
|
||||
formData.usage_limits = usageJsonPreview.value
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
limitEntries,
|
||||
featureConfigEntries,
|
||||
() => {
|
||||
formData.usage_limits = usageJsonPreview.value
|
||||
formData.feature_config = buildJsonRecord(featureConfigEntries.value) || {}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
customEntries,
|
||||
() => {
|
||||
formData.custom_parameters = customJsonPreview.value
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
@@ -66,16 +66,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 功能设置 -->
|
||||
<!-- 功能配置 -->
|
||||
<div class="info-card">
|
||||
<div class="card-title">{{ t('pages.licenses.detail.authorizationInfo.customParameters') }}</div>
|
||||
<div v-if="customParameters.length" class="key-value-table">
|
||||
<div class="card-title">{{ t('pages.licenses.detail.authorizationInfo.featureConfig') }}</div>
|
||||
<div v-if="featureConfig.length" class="key-value-table">
|
||||
<div class="key-value-header">
|
||||
<span>{{ t('pages.licenses.detail.authorizationInfo.keyColumn') }}</span>
|
||||
<span>{{ t('pages.licenses.detail.authorizationInfo.typeColumn') }}</span>
|
||||
<span>{{ t('pages.licenses.detail.authorizationInfo.valueColumn') }}</span>
|
||||
</div>
|
||||
<div v-for="item in customParameters" :key="`feature-${item.key}`" class="key-value-row">
|
||||
<div v-for="item in featureConfig" :key="`feature-${item.key}`" class="key-value-row">
|
||||
<span class="key-cell">{{ item.key }}</span>
|
||||
<span class="type-cell">{{ t(`pages.licenses.detail.authorizationInfo.typeOptions.${item.type}`) }}</span>
|
||||
<span class="value-cell">{{ item.value || '-' }}</span>
|
||||
@@ -86,7 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 限制设置 -->
|
||||
<!-- 使用限制 -->
|
||||
<div class="info-card">
|
||||
<div class="card-title">{{ t('pages.licenses.detail.authorizationInfo.usageLimits') }}</div>
|
||||
<div v-if="usageLimits.length" class="key-value-table">
|
||||
@@ -105,6 +105,26 @@
|
||||
{{ t('pages.licenses.detail.authorizationInfo.keyValueEmpty') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 自定义参数 -->
|
||||
<div class="info-card">
|
||||
<div class="card-title">{{ t('pages.licenses.detail.authorizationInfo.customParameters') }}</div>
|
||||
<div v-if="customParameters.length" class="key-value-table">
|
||||
<div class="key-value-header">
|
||||
<span>{{ t('pages.licenses.detail.authorizationInfo.keyColumn') }}</span>
|
||||
<span>{{ t('pages.licenses.detail.authorizationInfo.typeColumn') }}</span>
|
||||
<span>{{ t('pages.licenses.detail.authorizationInfo.valueColumn') }}</span>
|
||||
</div>
|
||||
<div v-for="item in customParameters" :key="`custom-${item.key}`" class="key-value-row">
|
||||
<span class="key-cell">{{ item.key }}</span>
|
||||
<span class="type-cell">{{ t(`pages.licenses.detail.authorizationInfo.typeOptions.${item.type}`) }}</span>
|
||||
<span class="value-cell">{{ item.value || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="key-value-empty">
|
||||
{{ t('pages.licenses.detail.authorizationInfo.keyValueEmpty') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -168,8 +188,9 @@ const parseKeyValueData = (source: unknown): KeyValueItem[] => {
|
||||
})
|
||||
}
|
||||
|
||||
const customParameters = computed(() => parseKeyValueData(props.licenseData?.custom_parameters))
|
||||
const featureConfig = computed(() => parseKeyValueData(props.licenseData?.feature_config))
|
||||
const usageLimits = computed(() => parseKeyValueData(props.licenseData?.usage_limits))
|
||||
const customParameters = computed(() => parseKeyValueData(props.licenseData?.custom_parameters))
|
||||
|
||||
// 获取授权期限类型
|
||||
const getLicensePeriodType = () => {
|
||||
|
||||
Reference in new issue
Block a user