fix(data-center): clear and remount SQL datasource select on type switch

This commit is contained in:
plum 2026-04-16 11:42:35 +08:00
parent fbfaa59b14
commit 9662f41eec

View File

@ -1,12 +1,12 @@
<template> <template>
<n-modal :show="show" @mask-click="handleClose"> <n-modal :show="show" @mask-click="handleClose">
<n-card class="w-200 max-w-1200px" :title="t('home.dataCenter.Data set config')"> <n-card class="w-200 max-w-1200px" :title="t('home.Data set config')">
<n-form :model="model" :rules="rules" ref="formRef" label-placement="left" label-width="auto" :disabled="submitLoading"> <n-form :model="model" :rules="rules" ref="formRef" label-placement="left" label-width="auto" :disabled="submitLoading">
<n-grid :cols="24" :x-gap="24"> <n-grid :cols="24" :x-gap="24">
<n-form-item-gi :span="12" :label="t('home.dataCenter.Data set name')" path="name"> <n-form-item-gi :span="12" :label="t('home.Data set name')" path="name">
<n-input v-model:value="model.name" /> <n-input v-model:value="model.name" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="12" :label="t('home.dataCenter.Data set group')" path="groupId"> <n-form-item-gi :span="12" :label="t('home.Data set group')" path="groupId">
<n-cascader <n-cascader
v-model:value="model.groupId" v-model:value="model.groupId"
expand-trigger="hover" expand-trigger="hover"
@ -19,13 +19,14 @@
value-field="id" value-field="id"
/> />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="12" :label="t('home.dataCenter.Data set type')" path="type"> <n-form-item-gi :span="12" :label="t('home.Data set type')" path="type">
<n-select v-model:value="model.type" :options="setTypes" /> <n-select v-model:value="model.type" :options="setTypes" />
</n-form-item-gi> </n-form-item-gi>
<template v-if="model.type === 'API'"> <template v-if="model.type === 'API'">
<n-form-item-gi :span="12" :label="t('home.dataCenter.Method')" path="method"> <n-form-item-gi :span="12" :label="t('home.Method')" path="method">
<n-select <n-select
:key="'dataset-method-select'"
v-model:value="model.method" v-model:value="model.method"
:options="[ :options="[
{ label: 'GET', value: 'GET' }, { label: 'GET', value: 'GET' },
@ -33,23 +34,23 @@
]" ]"
/> />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="24" :label="t('home.dataCenter.API interface')" path="api"> <n-form-item-gi :span="24" :label="t('home.API interface')" path="api">
<n-input v-model:value="model.api" type="textarea" /> <n-input v-model:value="model.api" type="textarea" />
</n-form-item-gi> </n-form-item-gi>
</template> </template>
<template v-else-if="model.type === 'SQL'"> <template v-else-if="model.type === 'SQL'">
<n-form-item-gi :span="12" :label="t('home.dataCenter.Data sources')" path="dataSourceId"> <n-form-item-gi :span="12" :label="t('home.Data sources')" path="dataSourceId">
<n-select v-model:value="model.dataSourceId" :options="dataSourceOptions" /> <n-select :key="'dataset-datasource-select'" v-model:value="model.dataSourceId" :options="dataSourceOptions" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="24" :label="`SQL(${t('home.dataCenter.Query only')})`" path="sql"> <n-form-item-gi :span="24" :label="`SQL(${t('home.Query only')})`" path="sql">
<SQLEditor v-model:value="model.sql as string" /> <SQLEditor v-model:value="model.sql as string" />
</n-form-item-gi> </n-form-item-gi>
<n-form-item-gi :span="24" label=" "> <n-form-item-gi :span="24" label=" ">
<n-blockquote> <n-blockquote>
{{ t('home.dataCenter["Parameter is passed as:"]') }} {{ t('home.Parameter is passed as ') }}
'${id}' , '${id}' ,
{{ t('home.dataCenter["For example:"]') }} {{ t('home.For example:') }}
SELECT * FROM table WHERE id='${id}' SELECT * FROM table WHERE id='${id}'
</n-blockquote> </n-blockquote>
</n-form-item-gi> </n-form-item-gi>
@ -123,27 +124,27 @@
const rules = computed(() => { const rules = computed(() => {
const baseRules: Record<string, any> = { const baseRules: Record<string, any> = {
name: { required: true, message: t("home.dataCenter.Please enter a name for the dataset"), trigger: ["input", "blur"] }, name: { required: true, message: t("prompt.Please enter a name for the dataset"), trigger: ["input", "blur"] },
groupId: createRequiredRule(t("home.dataCenter.Please select a grouping for the dataset"), ["change", "blur"]), groupId: createRequiredRule("请选择数据集分组", ["change", "blur"]),
type: { required: true, message: t("home.dataCenter.Please select a dataset type"), trigger: ["change", "blur"] }, type: { required: true, message: "请选择数据集类型", trigger: ["change", "blur"] },
}; };
const type = props.model?.type; const type = props.model?.type;
if (type === "API") { if (type === "API") {
baseRules.method = { baseRules.method = {
required: true, required: true,
message: t("home.dataCenter.Please select a method"), message: "请选择请求方式",
trigger: ["change", "blur"], trigger: ["change", "blur"],
}; };
baseRules.api = { baseRules.api = {
required: true, required: true,
message: t("home.dataCenter.Please enter the interface url"), message: "请输入接口地址",
trigger: ["input", "blur"], trigger: ["input", "blur"],
}; };
} else if (type === "SQL") { } else if (type === "SQL") {
baseRules.dataSourceId = createRequiredRule(t("home.dataCenter.Please select a data source"), ["change", "blur"]); baseRules.dataSourceId = createRequiredRule("请选择数据源", ["change", "blur"]);
baseRules.sql = { required: true, message: t("home.dataCenter.Please enter a SQL string"), trigger: ["blur"] }; baseRules.sql = { required: true, message: "请输入 SQL 语句", trigger: ["blur"] };
} else if (type === "JSON") { } else if (type === "JSON") {
baseRules.json = { required: true, message: t("home.dataCenter.Please enter the JSON data"), trigger: ["blur"] }; baseRules.json = { required: true, message: "请输入 JSON 数据", trigger: ["blur"] };
} }
return baseRules; return baseRules;
}); });
@ -211,7 +212,7 @@
} }
} }
function resetFieldsForType(type: string) { function resetFieldsForType(type: string, prevType?: string) {
if (!props.model) { if (!props.model) {
return; return;
} }
@ -225,6 +226,9 @@
if (type !== "SQL") { if (type !== "SQL") {
props.model.dataSourceId = undefined; props.model.dataSourceId = undefined;
props.model.sql = ""; props.model.sql = "";
} else if (prevType && prevType !== "SQL") {
props.model.dataSourceId = undefined;
props.model.sql = "";
} }
if (type !== "JSON") { if (type !== "JSON") {
props.model.json = ""; props.model.json = "";
@ -234,11 +238,11 @@
function validateSql(sql: string) { function validateSql(sql: string) {
const trimmed = sql.trim(); const trimmed = sql.trim();
if (!/^(SELECT|WITH)\b/i.test(trimmed)) { if (!/^(SELECT|WITH)\b/i.test(trimmed)) {
window.$message?.error(t("home.dataCenter.SQL must start with SELECT or WITH")); window.$message?.error("SQL 必须以 SELECT 或 WITH 开头");
return false; return false;
} }
if (/[;]|--|\/\*/.test(trimmed)) { if (/[;]|--|\/\*/.test(trimmed)) {
window.$message?.error(t("home.dataCenter.SQL must not include unsafe tokens")); window.$message?.error("SQL 不允许包含危险语句标记");
return false; return false;
} }
return true; return true;
@ -290,7 +294,7 @@
if (!next || next === prev) { if (!next || next === prev) {
return; return;
} }
resetFieldsForType(next); resetFieldsForType(next, prev);
formRef.value?.restoreValidation(); formRef.value?.restoreValidation();
} }
); );