2025-08-26 18:42:54 +08:00
|
|
|
|
<template>
|
2025-08-27 09:56:36 +08:00
|
|
|
|
<div class="plugin-config">
|
|
|
|
|
|
<div class="origin-metadata w-100%">
|
2025-08-26 18:42:54 +08:00
|
|
|
|
<div class="block-title">
|
2025-08-27 09:56:36 +08:00
|
|
|
|
自定义插件参数配置
|
2025-08-28 00:58:17 +08:00
|
|
|
|
<div class="helper">可以设置插件选项的配置,设置配置默认值、修改帮助说明、设置是否显示该字段等</div>
|
2025-08-26 18:42:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="p-10">
|
2025-08-27 09:56:36 +08:00
|
|
|
|
<div ref="formRef" class="config-form w-full" :label-col="labelCol" :wrapper-col="wrapperCol">
|
2025-08-27 18:23:24 +08:00
|
|
|
|
<table class="table-fixed w-full">
|
|
|
|
|
|
<thead>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<th class="text-left p-5" width="200px">插件参数</th>
|
|
|
|
|
|
<th class="text-left p-5" width="100px">参数配置</th>
|
|
|
|
|
|
<th class="text-left flex-1 p-5">自定义</th>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
2025-08-28 00:58:17 +08:00
|
|
|
|
<template v-for="item in originInputs" :key="item.key">
|
2025-08-27 18:23:24 +08:00
|
|
|
|
<template v-for="prop in editableKeys" :key="prop.key">
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td v-if="prop.key === 'value'" class="border-t-2 p-5" rowspan="3" :class="{ 'border-t-2': prop.key === 'value' }">{{ item.title }}</td>
|
|
|
|
|
|
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">{{ prop.label }}</td>
|
|
|
|
|
|
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">
|
2025-08-28 00:58:17 +08:00
|
|
|
|
<rollbackable :value="configForm[item.key][prop.key]" @set="prop.onSet(item)" @clear="delete configForm[item.key][prop.key]">
|
2025-08-27 18:23:24 +08:00
|
|
|
|
<template #default>
|
2025-08-28 00:58:17 +08:00
|
|
|
|
<fs-render :render-func="prop.defaultRender(item)"></fs-render>
|
2025-08-27 18:23:24 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
<template #edit>
|
2025-08-28 00:58:17 +08:00
|
|
|
|
<fs-render :render-func="prop.editRender(item)"></fs-render>
|
2025-08-27 18:23:24 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
</rollbackable>
|
|
|
|
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
2025-08-27 09:56:36 +08:00
|
|
|
|
</div>
|
2025-08-26 18:42:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
2025-08-27 18:23:24 +08:00
|
|
|
|
<script setup lang="tsx">
|
2025-08-27 09:56:36 +08:00
|
|
|
|
import { computed, nextTick, onMounted, reactive, ref, Ref, unref } from "vue";
|
2025-08-26 18:42:54 +08:00
|
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
|
|
import * as api from "./api";
|
|
|
|
|
|
import { usePluginStore } from "/@/store/plugin";
|
2025-08-27 09:56:36 +08:00
|
|
|
|
import { cloneDeep, get, merge, set, unset } from "lodash-es";
|
|
|
|
|
|
import Rollbackable from "./rollbackable.vue";
|
2025-08-27 18:23:24 +08:00
|
|
|
|
import { FsRender } from "@fast-crud/fast-crud";
|
2025-08-26 18:42:54 +08:00
|
|
|
|
const route = useRoute();
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
const pluginStore = usePluginStore();
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
|
plugin: any;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
|
2025-08-27 09:56:36 +08:00
|
|
|
|
const pluginMetadata = ref<any>("");
|
2025-08-26 18:42:54 +08:00
|
|
|
|
const currentPlugin = ref();
|
2025-08-27 09:56:36 +08:00
|
|
|
|
const labelCol = ref({
|
|
|
|
|
|
span: null,
|
|
|
|
|
|
style: {
|
|
|
|
|
|
width: "145px",
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
const wrapperCol = ref({ span: 16 });
|
|
|
|
|
|
const configForm: any = reactive({});
|
|
|
|
|
|
|
|
|
|
|
|
function getScope() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
form: configForm,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-08-28 00:58:17 +08:00
|
|
|
|
|
2025-08-27 09:56:36 +08:00
|
|
|
|
function getForm() {
|
|
|
|
|
|
return configForm;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const editableKeys = ref([
|
2025-08-27 18:23:24 +08:00
|
|
|
|
{
|
|
|
|
|
|
key: "value",
|
|
|
|
|
|
label: "默认值",
|
2025-08-28 00:58:17 +08:00
|
|
|
|
onSet(item: any) {
|
|
|
|
|
|
configForm[item.key]["value"] = item.value ?? null;
|
|
|
|
|
|
},
|
|
|
|
|
|
defaultRender(item: any) {
|
2025-08-27 18:23:24 +08:00
|
|
|
|
return () => {
|
|
|
|
|
|
return item["value"] ?? "";
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
2025-08-28 00:58:17 +08:00
|
|
|
|
editRender(item: any) {
|
2025-08-27 18:23:24 +08:00
|
|
|
|
return () => {
|
2025-08-28 00:58:17 +08:00
|
|
|
|
return <fs-component-render {...item.component} vModel:modelValue={configForm[item.key]["value"]} scope={getScope()} />;
|
2025-08-27 18:23:24 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: "show",
|
|
|
|
|
|
label: "是否显示",
|
2025-08-28 00:58:17 +08:00
|
|
|
|
onSet(item: any) {
|
|
|
|
|
|
configForm[item.key]["show"] = item.show ?? true;
|
|
|
|
|
|
},
|
|
|
|
|
|
defaultRender(item: any) {
|
2025-08-27 18:23:24 +08:00
|
|
|
|
return () => {
|
|
|
|
|
|
const value = item["show"];
|
|
|
|
|
|
return value === false ? "不显示" : "显示";
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
2025-08-28 00:58:17 +08:00
|
|
|
|
editRender(item: any) {
|
2025-08-27 18:23:24 +08:00
|
|
|
|
return () => {
|
2025-08-28 00:58:17 +08:00
|
|
|
|
return <a-switch vModel:checked={configForm[item.key]["show"]} />;
|
2025-08-27 18:23:24 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: "helper",
|
|
|
|
|
|
label: "帮助说明",
|
2025-08-28 00:58:17 +08:00
|
|
|
|
onSet(item: any) {
|
|
|
|
|
|
configForm[item.key]["helper"] = item.helper ?? "";
|
|
|
|
|
|
},
|
|
|
|
|
|
defaultRender(item: any) {
|
2025-08-27 18:23:24 +08:00
|
|
|
|
return () => {
|
2026-03-15 18:26:49 +08:00
|
|
|
|
return <pre class={"helper pre"}>{item["helper"]}</pre>;
|
2025-08-27 18:23:24 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
2025-08-28 00:58:17 +08:00
|
|
|
|
editRender(item: any) {
|
2025-08-27 18:23:24 +08:00
|
|
|
|
return () => {
|
2025-08-28 00:58:17 +08:00
|
|
|
|
return <a-textarea rows={5} vModel:value={configForm[item.key]["helper"]} />;
|
2025-08-27 18:23:24 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
2025-08-27 09:56:36 +08:00
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
const originInputs = computed(() => {
|
2025-08-26 18:42:54 +08:00
|
|
|
|
if (!currentPlugin.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const input = cloneDeep(currentPlugin.value.input);
|
|
|
|
|
|
const newInputs: any = {};
|
|
|
|
|
|
|
|
|
|
|
|
for (const key in input) {
|
|
|
|
|
|
const value = input[key];
|
2025-08-27 09:56:36 +08:00
|
|
|
|
value.key = key;
|
|
|
|
|
|
const newInput: any = cloneDeep(value);
|
2025-08-26 18:42:54 +08:00
|
|
|
|
newInputs[key] = newInput;
|
|
|
|
|
|
}
|
2025-08-27 09:56:36 +08:00
|
|
|
|
return newInputs;
|
2025-08-26 18:42:54 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2025-08-27 09:56:36 +08:00
|
|
|
|
function clearFormValue(key: string) {
|
|
|
|
|
|
unset(configForm, key);
|
|
|
|
|
|
console.log(key, configForm);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-26 18:42:54 +08:00
|
|
|
|
async function loadPluginSetting() {
|
2025-08-27 18:23:24 +08:00
|
|
|
|
currentPlugin.value = await pluginStore.getPluginDefineFromOrigin(props.plugin.name);
|
2025-08-27 09:56:36 +08:00
|
|
|
|
for (const key in currentPlugin.value.input) {
|
|
|
|
|
|
configForm[key] = {};
|
|
|
|
|
|
}
|
2025-08-26 18:42:54 +08:00
|
|
|
|
const setting = props.plugin.sysSetting;
|
|
|
|
|
|
if (setting) {
|
|
|
|
|
|
const settingJson = JSON.parse(setting);
|
2025-08-28 00:58:17 +08:00
|
|
|
|
merge(configForm, settingJson.metadata?.input || {});
|
2025-08-26 18:42:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
await loadPluginSetting();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-08-27 18:23:24 +08:00
|
|
|
|
defineExpose({
|
|
|
|
|
|
getForm,
|
|
|
|
|
|
});
|
2025-08-26 18:42:54 +08:00
|
|
|
|
</script>
|
2025-08-27 09:56:36 +08:00
|
|
|
|
|
|
|
|
|
|
<style lang="less">
|
|
|
|
|
|
.plugin-config {
|
|
|
|
|
|
pre {
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|