feat: 支持 Linux 客户端配置与发布校验
This commit is contained in:
@@ -28,6 +28,7 @@ const currentAppId = ref("");
|
||||
const createdLicenseKey = ref("");
|
||||
const generatedClientConfig = ref("");
|
||||
const generatedCrashTestInfo = ref("");
|
||||
const licenseConfigWarning = ref("");
|
||||
const runtime = reactive<any>({});
|
||||
|
||||
const appForm = reactive({ app_id: "", app_name: "" });
|
||||
@@ -193,6 +194,14 @@ function handleError(prefix: string, error: unknown) {
|
||||
ElMessage.error(`${prefix}:${friendlyError(error)}`);
|
||||
}
|
||||
|
||||
function isLicenseFull(row: any) {
|
||||
return Number(row?.used_devices || 0) >= Number(row?.max_devices || 0);
|
||||
}
|
||||
|
||||
function isLicenseUsable(row: any) {
|
||||
return row?.status === "active" && row?.license_key && !isLicenseFull(row);
|
||||
}
|
||||
|
||||
async function loadRuntime() {
|
||||
const data = await adminRequest<any>("/admin/runtime-config");
|
||||
Object.assign(runtime, data || {});
|
||||
@@ -434,10 +443,9 @@ async function loadLicenses() {
|
||||
const usable =
|
||||
licenses.value.find(
|
||||
item =>
|
||||
item.status === "active" &&
|
||||
item.license_key &&
|
||||
isLicenseUsable(item) &&
|
||||
item.channel_code === publishForm.channel
|
||||
) || licenses.value.find(item => item.status === "active" && item.license_key);
|
||||
) || licenses.value.find(item => isLicenseUsable(item));
|
||||
if (usable && !configForm.license_key) configForm.license_key = usable.license_key;
|
||||
}
|
||||
|
||||
@@ -457,8 +465,17 @@ async function createLicense() {
|
||||
}
|
||||
|
||||
function fillLicense(row: any) {
|
||||
if (isLicenseFull(row)) {
|
||||
ElMessage.warning("这张 License 的设备数已达到上限,请创建或申请新的 License。");
|
||||
return;
|
||||
}
|
||||
if (row.status !== "active") {
|
||||
ElMessage.warning("这张 License 当前不可用,请启用后再填入配置。");
|
||||
return;
|
||||
}
|
||||
configForm.license_key = row.license_key;
|
||||
createdLicenseKey.value = row.license_key;
|
||||
licenseConfigWarning.value = "";
|
||||
ElMessage.success("License 已填入客户端配置");
|
||||
}
|
||||
|
||||
@@ -530,7 +547,13 @@ async function generateClientConfig() {
|
||||
generatedCrashTestInfo.value =
|
||||
result.crash_test_text ||
|
||||
JSON.stringify(result.crash_test_config || {}, null, 2);
|
||||
ElMessage.success("客户端配置已生成");
|
||||
licenseConfigWarning.value = result.license_warning || "";
|
||||
if (licenseConfigWarning.value) {
|
||||
configForm.license_key = result.config?.license_key || "";
|
||||
ElMessage.warning(licenseConfigWarning.value);
|
||||
} else {
|
||||
ElMessage.success("客户端配置已生成");
|
||||
}
|
||||
} catch (error) {
|
||||
handleError("生成客户端配置失败", error);
|
||||
}
|
||||
@@ -910,11 +933,11 @@ onMounted(loadAll);
|
||||
<el-table-column prop="license_id" label="License ID" min-width="190" />
|
||||
<el-table-column prop="customer_name" label="客户" min-width="140" />
|
||||
<el-table-column prop="channel_code" label="渠道" width="100" />
|
||||
<el-table-column label="设备" width="110"><template #default="{ row }">{{ row.used_devices }} / {{ row.max_devices }}</template></el-table-column>
|
||||
<el-table-column label="设备" width="130"><template #default="{ row }"><span>{{ row.used_devices }} / {{ row.max_devices }}</span><el-tag v-if="isLicenseFull(row)" class="ml-xs" type="warning" size="small">已满</el-tag></template></el-table-column>
|
||||
<el-table-column prop="valid_until" label="有效期" min-width="170" />
|
||||
<el-table-column label="License" min-width="260"><template #default="{ row }"><span v-if="row.license_key" class="mono">{{ row.license_key }}</span><el-tag v-else type="info">旧授权不可查看</el-tag></template></el-table-column>
|
||||
<el-table-column label="状态" width="90"><template #default="{ row }"><el-tag :type="row.status === 'active' ? 'success' : 'danger'">{{ row.status === "active" ? "有效" : "禁用" }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="操作" width="300"><template #default="{ row }"><el-button v-if="row.license_key" link type="primary" @click="fillLicense(row)">填入配置</el-button><el-button v-if="row.license_key" link type="primary" @click="copyLicense(row)">复制</el-button><el-button link :type="row.status === 'active' ? 'danger' : 'success'" @click="toggleLicense(row)">{{ row.status === "active" ? "禁用" : "启用" }}</el-button><el-button link type="danger" @click="deleteLicense(row)">删除</el-button></template></el-table-column>
|
||||
<el-table-column label="操作" width="320"><template #default="{ row }"><el-button v-if="row.license_key" link type="primary" :disabled="isLicenseFull(row) || row.status !== 'active'" @click="fillLicense(row)">填入配置</el-button><el-button v-if="row.license_key" link type="primary" @click="copyLicense(row)">复制</el-button><el-button link :type="row.status === 'active' ? 'danger' : 'success'" @click="toggleLicense(row)">{{ row.status === "active" ? "禁用" : "启用" }}</el-button><el-button link type="danger" @click="deleteLicense(row)">删除</el-button></template></el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
@@ -925,6 +948,7 @@ onMounted(loadAll);
|
||||
<el-form-item label="主程序文件名"><el-input v-model="configForm.main_executable" placeholder="例如 SimCAE.exe" /></el-form-item>
|
||||
<el-form-item label="License"><el-input v-model="configForm.license_key" placeholder="可从上方 License 列表填入;也可留空让客户端首次启动时输入" /></el-form-item>
|
||||
</el-form>
|
||||
<el-alert v-if="licenseConfigWarning" class="mb" type="warning" :closable="false" show-icon :title="licenseConfigWarning" />
|
||||
<div class="action-row"><el-button type="primary" @click="generateClientConfig">生成配套配置</el-button><el-button :disabled="!generatedClientConfig" @click="copyGeneratedConfig">复制配置</el-button></div>
|
||||
<div class="config-section-title">客户端 app_config.json</div>
|
||||
<pre class="code-block">{{ generatedClientConfig || "尚未生成客户端配置" }}</pre>
|
||||
@@ -1149,6 +1173,10 @@ onMounted(loadAll);
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.ml-xs {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.mono {
|
||||
display: inline-block;
|
||||
max-width: 360px;
|
||||
|
||||
Reference in New Issue
Block a user