feat(security-center): add license file parser
- SecurityCenterView: add license file upload/parse card with ElUpload and ElDescriptions - appApi: add parseLicenseFile() calling POST /api/apps/license/parse Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
这个提交包含在:
父节点
655c5bc598
当前提交
a8db0519ae
@ -203,4 +203,10 @@ export const appApi = {
|
|||||||
client.post<{ data: null }>(`/apps/${appKey}/services/request-activation`, null, {
|
client.post<{ data: null }>(`/apps/${appKey}/services/request-activation`, null, {
|
||||||
params: { platform: 'ANDROID', serviceType, applyReason: reason },
|
params: { platform: 'ANDROID', serviceType, applyReason: reason },
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
parseLicenseFile: (content: string) =>
|
||||||
|
client.post<{ data: { appKey: string; appName: string; packageName: string; iosBundleId: string; harmonyBundleName: string; baseUrl: string; serverUrl: string } }>(
|
||||||
|
'/apps/license/parse',
|
||||||
|
{ content },
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,6 +67,43 @@
|
|||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
<!-- License 文件解析 -->
|
||||||
|
<el-card style="margin-bottom: 16px">
|
||||||
|
<template #header>License 文件解析</template>
|
||||||
|
<p style="color: #606266; margin: 0 0 16px;">
|
||||||
|
上传已下载的 License 文件(.xuqmlicense),解析并验证文件内容。
|
||||||
|
</p>
|
||||||
|
<el-input
|
||||||
|
v-model="licenseFileContent"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder="将 License 文件内容粘贴到此处,或点击上传文件"
|
||||||
|
style="margin-bottom: 12px"
|
||||||
|
/>
|
||||||
|
<div style="display: flex; gap: 12px; flex-wrap: wrap; align-items: center;">
|
||||||
|
<el-upload
|
||||||
|
ref="licenseUploadRef"
|
||||||
|
action="#"
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-change="handleLicenseFileChange"
|
||||||
|
:show-file-list="false"
|
||||||
|
accept=".xuqmlicense"
|
||||||
|
>
|
||||||
|
<el-button type="primary" plain>选择 License 文件</el-button>
|
||||||
|
</el-upload>
|
||||||
|
<el-button :loading="parsingLicense" @click="parseLicense">解析</el-button>
|
||||||
|
<el-button v-if="licenseParseResult" @click="clearLicenseParse">清除</el-button>
|
||||||
|
</div>
|
||||||
|
<el-descriptions v-if="licenseParseResult" :column="isMobile ? 1 : 2" border style="margin-top: 16px">
|
||||||
|
<el-descriptions-item label="AppKey">{{ licenseParseResult.appKey }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="应用名称">{{ licenseParseResult.appName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="Android 包名">{{ licenseParseResult.packageName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="iOS BundleId">{{ licenseParseResult.iosBundleId || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="鸿蒙 BundleName">{{ licenseParseResult.harmonyBundleName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="服务地址">{{ licenseParseResult.serverUrl || licenseParseResult.baseUrl || '-' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
<el-card>
|
<el-card>
|
||||||
<template #header>应用密钥管理</template>
|
<template #header>应用密钥管理</template>
|
||||||
<el-table :data="apps" v-loading="loading" border stripe>
|
<el-table :data="apps" v-loading="loading" border stripe>
|
||||||
@ -241,6 +278,53 @@ const selectedApp = ref<App | null>(null)
|
|||||||
const dialogMode = ref<'REVEAL_SECRET' | 'RESET_SECRET'>('REVEAL_SECRET')
|
const dialogMode = ref<'REVEAL_SECRET' | 'RESET_SECRET'>('REVEAL_SECRET')
|
||||||
const secretResult = ref('')
|
const secretResult = ref('')
|
||||||
|
|
||||||
|
// License file parse
|
||||||
|
const licenseFileContent = ref('')
|
||||||
|
const parsingLicense = ref(false)
|
||||||
|
const licenseParseResult = ref<{
|
||||||
|
appKey: string
|
||||||
|
appName: string
|
||||||
|
packageName: string
|
||||||
|
iosBundleId: string
|
||||||
|
harmonyBundleName: string
|
||||||
|
baseUrl: string
|
||||||
|
serverUrl: string
|
||||||
|
} | null>(null)
|
||||||
|
const licenseUploadRef = ref<any>(null)
|
||||||
|
|
||||||
|
function handleLicenseFileChange(file: any) {
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = (e) => {
|
||||||
|
licenseFileContent.value = (e.target?.result as string) || ''
|
||||||
|
}
|
||||||
|
reader.readAsText(file.raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function parseLicense() {
|
||||||
|
if (!licenseFileContent.value.trim()) {
|
||||||
|
ElMessage.warning('请输入或上传 License 文件内容')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parsingLicense.value = true
|
||||||
|
try {
|
||||||
|
const res = await appApi.parseLicenseFile(licenseFileContent.value.trim())
|
||||||
|
licenseParseResult.value = res.data.data
|
||||||
|
ElMessage.success('解析成功')
|
||||||
|
} catch (e: any) {
|
||||||
|
ElMessage.error(e?.response?.data?.message || '解析失败,请检查文件内容')
|
||||||
|
} finally {
|
||||||
|
parsingLicense.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearLicenseParse() {
|
||||||
|
licenseFileContent.value = ''
|
||||||
|
licenseParseResult.value = null
|
||||||
|
if (licenseUploadRef.value) {
|
||||||
|
licenseUploadRef.value.clearFiles()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户