mirror of https://github.com/certd/certd
perf: 商业版支持自定义插件的参数配置
parent
8e3d699856
commit
17f23f3751
|
@ -564,7 +564,7 @@ export default {
|
||||||
ipv6Priority: "IPv6 Priority",
|
ipv6Priority: "IPv6 Priority",
|
||||||
dualStackNetworkHelper: "If IPv6 priority is selected, enable IPv6 in docker-compose.yaml",
|
dualStackNetworkHelper: "If IPv6 priority is selected, enable IPv6 in docker-compose.yaml",
|
||||||
enableCommonCnameService: "Enable Public CNAME Service",
|
enableCommonCnameService: "Enable Public CNAME Service",
|
||||||
commonCnameHelper: "Allow use of public CNAME service. If disabled and no <router-link to='/sys/cname/provider'>custom CNAME service</router-link> is set, CNAME proxy certificate application will not work.",
|
commonCnameHelper: "Allow use of public CNAME service. If disabled and no <a href='#/sys/cname/provider'>custom CNAME service</a> is set, CNAME proxy certificate application will not work.",
|
||||||
enableCommonSelfServicePasswordRetrieval: "Enable self-service password recovery",
|
enableCommonSelfServicePasswordRetrieval: "Enable self-service password recovery",
|
||||||
saveButton: "Save",
|
saveButton: "Save",
|
||||||
stopSuccess: "Stopped successfully",
|
stopSuccess: "Stopped successfully",
|
||||||
|
|
|
@ -570,7 +570,7 @@ export default {
|
||||||
ipv6Priority: "IPV6优先",
|
ipv6Priority: "IPV6优先",
|
||||||
dualStackNetworkHelper: "如果选择IPv6优先,需要在docker-compose.yaml中启用ipv6",
|
dualStackNetworkHelper: "如果选择IPv6优先,需要在docker-compose.yaml中启用ipv6",
|
||||||
enableCommonCnameService: "启用公共CNAME服务",
|
enableCommonCnameService: "启用公共CNAME服务",
|
||||||
commonCnameHelper: "是否可以使用公共CNAME服务,如果禁用,且没有设置<router-link to='/sys/cname/provider'>自定义CNAME服务</router-link>,则无法使用CNAME代理方式申请证书",
|
commonCnameHelper: "是否可以使用公共CNAME服务,如果禁用,且没有设置<a href='#/sys/cname/provider'>自定义CNAME服务</a>,则无法使用CNAME代理方式申请证书",
|
||||||
enableCommonSelfServicePasswordRetrieval: "启用自助找回密码",
|
enableCommonSelfServicePasswordRetrieval: "启用自助找回密码",
|
||||||
saveButton: "保存",
|
saveButton: "保存",
|
||||||
stopSuccess: "停止成功",
|
stopSuccess: "停止成功",
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import * as api from "./api.plugin";
|
import * as api from "./api.plugin";
|
||||||
import { DynamicType, FormItemProps } from "@fast-crud/fast-crud";
|
import { DynamicType, FormItemProps, useMerge } from "@fast-crud/fast-crud";
|
||||||
import { i18n } from "/src/locales/i18n";
|
import { i18n } from "/src/locales/i18n";
|
||||||
|
import { cloneDeep } from "lodash-es";
|
||||||
interface PluginState {
|
interface PluginState {
|
||||||
group?: PluginGroups;
|
group?: PluginGroups;
|
||||||
}
|
}
|
||||||
|
@ -32,14 +33,17 @@ export class PluginGroups {
|
||||||
groups!: { [key: string]: PluginGroup };
|
groups!: { [key: string]: PluginGroup };
|
||||||
map!: { [key: string]: PluginDefine };
|
map!: { [key: string]: PluginDefine };
|
||||||
t: any;
|
t: any;
|
||||||
constructor(groups: { [key: string]: PluginGroup }) {
|
mergeSetting?: boolean;
|
||||||
|
constructor(groups: { [key: string]: PluginGroup }, opts?: { mergeSetting?: boolean }) {
|
||||||
this.groups = groups;
|
this.groups = groups;
|
||||||
this.t = i18n.global.t;
|
this.t = i18n.global.t;
|
||||||
|
this.mergeSetting = opts?.mergeSetting ?? false;
|
||||||
this.initGroup(groups);
|
this.initGroup(groups);
|
||||||
this.initMap();
|
this.initMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initGroup(groups: { [p: string]: PluginGroup }) {
|
private initGroup(groups: { [p: string]: PluginGroup }) {
|
||||||
|
const { merge } = useMerge();
|
||||||
const all: PluginGroup = {
|
const all: PluginGroup = {
|
||||||
key: "all",
|
key: "all",
|
||||||
title: this.t("certd.all"),
|
title: this.t("certd.all"),
|
||||||
|
@ -48,6 +52,14 @@ export class PluginGroups {
|
||||||
icon: "material-symbols:border-all-rounded",
|
icon: "material-symbols:border-all-rounded",
|
||||||
};
|
};
|
||||||
for (const key in groups) {
|
for (const key in groups) {
|
||||||
|
if (this.mergeSetting) {
|
||||||
|
for (const plugin of groups[key].plugins) {
|
||||||
|
if (plugin.sysSetting) {
|
||||||
|
merge(plugin.input, plugin.sysSetting.metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
all.plugins.push(...groups[key].plugins);
|
all.plugins.push(...groups[key].plugins);
|
||||||
}
|
}
|
||||||
this.groups = {
|
this.groups = {
|
||||||
|
@ -132,11 +144,15 @@ export const usePluginStore = defineStore({
|
||||||
id: "app.plugin",
|
id: "app.plugin",
|
||||||
state: (): PluginState => ({
|
state: (): PluginState => ({
|
||||||
group: null,
|
group: null,
|
||||||
|
originGroup: null,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async reload() {
|
async reload() {
|
||||||
const groups = await api.GetGroups({});
|
const groups = await api.GetGroups({});
|
||||||
this.group = new PluginGroups(groups);
|
this.group = new PluginGroups(groups, { mergeSetting: true });
|
||||||
|
this.originGroup = new PluginGroups(cloneDeep(groups));
|
||||||
|
console.log("group", this.group);
|
||||||
|
console.log("originGroup", this.originGroup);
|
||||||
},
|
},
|
||||||
async init() {
|
async init() {
|
||||||
if (!this.group) {
|
if (!this.group) {
|
||||||
|
@ -159,6 +175,10 @@ export const usePluginStore = defineStore({
|
||||||
await this.init();
|
await this.init();
|
||||||
return this.group.get(name);
|
return this.group.get(name);
|
||||||
},
|
},
|
||||||
|
async getPluginDefineFromOrigin(name: string): Promise<PluginDefine> {
|
||||||
|
await this.init();
|
||||||
|
return this.originGroup.get(name);
|
||||||
|
},
|
||||||
async getPluginConfig(query: any) {
|
async getPluginConfig(query: any) {
|
||||||
return await api.GetPluginConfig(query);
|
return await api.GetPluginConfig(query);
|
||||||
},
|
},
|
||||||
|
|
|
@ -304,3 +304,11 @@ h6 {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
color: #6e6e6e;
|
color: #6e6e6e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-modal-body{
|
||||||
|
.fs-form-body{
|
||||||
|
max-height: 66vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -138,6 +138,7 @@ export function useCertPipelineCreator() {
|
||||||
form: {
|
form: {
|
||||||
doSubmit,
|
doSubmit,
|
||||||
wrapper: {
|
wrapper: {
|
||||||
|
wrapClassName: "cert_pipeline_create_form",
|
||||||
width: 1350,
|
width: 1350,
|
||||||
saveRemind: false,
|
saveRemind: false,
|
||||||
title: t("certd.pipelineForm.createTitle"),
|
title: t("certd.pipelineForm.createTitle"),
|
||||||
|
|
|
@ -115,4 +115,13 @@ function batchRerun() {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cert_pipeline_create_form {
|
||||||
|
.ant-collapse {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.ant-collapse-header {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
</a-tab-pane>
|
</a-tab-pane>
|
||||||
</a-tabs>
|
</a-tabs>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-button type="primary" size="large" html-type="submit" :loading="loading" class="login-button">
|
<a-button type="primary" size="large" html-type="button" :loading="loading" class="login-button" @click="handleFinish">
|
||||||
{{ t("authentication.loginButton") }}
|
{{ t("authentication.loginButton") }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
|
@ -217,7 +217,6 @@ export default defineComponent({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
||||||
.login-page.main {
|
.login-page.main {
|
||||||
//margin: 20px !important;
|
//margin: 20px !important;
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
|
|
|
@ -7,38 +7,49 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="p-10">
|
<div class="p-10">
|
||||||
<div ref="formRef" class="config-form w-full" :label-col="labelCol" :wrapper-col="wrapperCol">
|
<div ref="formRef" class="config-form w-full" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||||
<template v-for="(item, key) in originInputs" :key="key">
|
<table class="table-fixed w-full">
|
||||||
<div>
|
<thead>
|
||||||
<div :label="item.title">
|
<tr>
|
||||||
<label class="flex mt-5">
|
<th class="text-left p-5" width="200px">插件参数</th>
|
||||||
<span class="w-20 flex-shrink-0">默认值</span>
|
<th class="text-left p-5" width="100px">参数配置</th>
|
||||||
<rollbackable :value="configForm[key].value" @set="configForm[key].value = item.value ?? null" @clear="unset(configForm, `${key}.value`)"></rollbackable>
|
<th class="text-left flex-1 p-5">自定义</th>
|
||||||
</label>
|
</tr>
|
||||||
<label class="flex mt-5">
|
</thead>
|
||||||
<span class="w-20 flex-shrink-0">是否显示</span>
|
<tbody>
|
||||||
<rollbackable :value="configForm[key].show" @set="set(configForm, `${key}.show`, item.show ?? null)" @clear="unset(configForm, `${key}.show`)"></rollbackable>
|
<template v-for="(item, key) in originInputs" :key="key">
|
||||||
</label>
|
<template v-for="prop in editableKeys" :key="prop.key">
|
||||||
<label class="flex mt-5">
|
<tr>
|
||||||
<span class="w-20 flex-shrink-0">帮助说明</span>
|
<td v-if="prop.key === 'value'" class="border-t-2 p-5" rowspan="3" :class="{ 'border-t-2': prop.key === 'value' }">{{ item.title }}</td>
|
||||||
{{ configForm[key].helper }}
|
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">{{ prop.label }}</td>
|
||||||
<rollbackable :value="configForm[key].helper" @setter="configForm[key].helper = item.helper" @clear1="delete configForm[key].helper"></rollbackable>
|
<td class="border-t p-5" :class="{ 'border-t-2': prop.key === 'value' }">
|
||||||
</label>
|
<rollbackable :value="configForm[key][prop.key]" @set="configForm[key][prop.key] = item[prop.key] ?? null" @clear="delete configForm[key][prop.key]">
|
||||||
</div>
|
<template #default>
|
||||||
</div>
|
<fs-render :render-func="prop.defaultRender(key, item)"></fs-render>
|
||||||
</template>
|
</template>
|
||||||
|
<template #edit>
|
||||||
|
<fs-render :render-func="prop.editRender(key, item)"></fs-render>
|
||||||
|
</template>
|
||||||
|
</rollbackable>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="tsx">
|
||||||
import { computed, nextTick, onMounted, reactive, ref, Ref, unref } from "vue";
|
import { computed, nextTick, onMounted, reactive, ref, Ref, unref } from "vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
import { usePluginStore } from "/@/store/plugin";
|
import { usePluginStore } from "/@/store/plugin";
|
||||||
import { cloneDeep, get, merge, set, unset } from "lodash-es";
|
import { cloneDeep, get, merge, set, unset } from "lodash-es";
|
||||||
import Rollbackable from "./rollbackable.vue";
|
import Rollbackable from "./rollbackable.vue";
|
||||||
|
import { FsRender } from "@fast-crud/fast-crud";
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pluginStore = usePluginStore();
|
const pluginStore = usePluginStore();
|
||||||
|
@ -48,7 +59,6 @@ const props = defineProps<{
|
||||||
|
|
||||||
const pluginMetadata = ref<any>("");
|
const pluginMetadata = ref<any>("");
|
||||||
const currentPlugin = ref();
|
const currentPlugin = ref();
|
||||||
console.log("111111111111111111111");
|
|
||||||
const labelCol = ref({
|
const labelCol = ref({
|
||||||
span: null,
|
span: null,
|
||||||
style: {
|
style: {
|
||||||
|
@ -71,9 +81,49 @@ function getForm() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const editableKeys = ref([
|
const editableKeys = ref([
|
||||||
{ key: "value", label: "默认值" },
|
{
|
||||||
{ key: "show", label: "是否显示", component: { name: "a-switch", vModel: "checked" } },
|
key: "value",
|
||||||
{ key: "helper", label: "帮助说明", component: { name: "a-textarea", vModel: "value", rows: 4 } },
|
label: "默认值",
|
||||||
|
defaultRender(key: string, item: any) {
|
||||||
|
return () => {
|
||||||
|
return item["value"] ?? "";
|
||||||
|
};
|
||||||
|
},
|
||||||
|
editRender(key: string, item: any) {
|
||||||
|
return () => {
|
||||||
|
return <fs-component-render {...item.component} vModel:modelValue={configForm[key]["value"]} scope={getScope()} />;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "show",
|
||||||
|
label: "是否显示",
|
||||||
|
defaultRender(key: string, item: any) {
|
||||||
|
return () => {
|
||||||
|
const value = item["show"];
|
||||||
|
return value === false ? "不显示" : "显示";
|
||||||
|
};
|
||||||
|
},
|
||||||
|
editRender(key: string, item: any) {
|
||||||
|
return () => {
|
||||||
|
return <a-switch vModel:checked={configForm[key]["show"]} />;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "helper",
|
||||||
|
label: "帮助说明",
|
||||||
|
defaultRender(key: string, item: any) {
|
||||||
|
return () => {
|
||||||
|
return <pre class={"helper"}>{item["helper"]}</pre>;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
editRender(key: string, item: any) {
|
||||||
|
return () => {
|
||||||
|
return <a-textarea rows={5} vModel:value={configForm[key]["helper"]} />;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const originInputs = computed(() => {
|
const originInputs = computed(() => {
|
||||||
|
@ -98,7 +148,7 @@ function clearFormValue(key: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadPluginSetting() {
|
async function loadPluginSetting() {
|
||||||
currentPlugin.value = await pluginStore.getPluginDefine(props.plugin.name);
|
currentPlugin.value = await pluginStore.getPluginDefineFromOrigin(props.plugin.name);
|
||||||
for (const key in currentPlugin.value.input) {
|
for (const key in currentPlugin.value.input) {
|
||||||
configForm[key] = {};
|
configForm[key] = {};
|
||||||
}
|
}
|
||||||
|
@ -113,7 +163,9 @@ onMounted(async () => {
|
||||||
await loadPluginSetting();
|
await loadPluginSetting();
|
||||||
});
|
});
|
||||||
|
|
||||||
function doSave() {}
|
defineExpose({
|
||||||
|
getForm,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
|
@ -1,32 +1,45 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { cloneDeep, get, merge, set, unset } from "lodash-es";
|
|
||||||
import { defineProps } from "vue";
|
import { defineProps } from "vue";
|
||||||
|
|
||||||
const props = defineProps<{ value: any }>();
|
const props = defineProps<{ value: any }>();
|
||||||
|
|
||||||
const emits = defineEmits(["setter", "clear1"]);
|
const emits = defineEmits(["set", "clear"]);
|
||||||
function setValue() {
|
function setValue() {
|
||||||
console.log("33333");
|
emits("set");
|
||||||
emits("setter");
|
|
||||||
}
|
}
|
||||||
function clearValue() {
|
function clearValue() {
|
||||||
console.log("4444");
|
emits("clear");
|
||||||
emits("clear1");
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="rollbackable">
|
<div class="rollbackable">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div>
|
<div style="width: 100px">
|
||||||
|
<a-tag v-if="value === undefined" color="green" size="small" class="pointer flex-inline items-center" @click.stop="setValue">
|
||||||
|
<fs-icon icon="material-symbols:edit" class="mr-5"></fs-icon>
|
||||||
|
自定义
|
||||||
|
</a-tag>
|
||||||
|
<a-tag v-else color="red" size="small" class="pointer flex-inline items-center" @click.stop="clearValue">
|
||||||
|
<fs-icon icon="material-symbols:undo" class="mr-5"></fs-icon>
|
||||||
|
还原
|
||||||
|
</a-tag>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 overflow-hidden value-render">
|
||||||
<slot v-if="value === undefined" name="default"></slot>
|
<slot v-if="value === undefined" name="default"></slot>
|
||||||
<slot v-else name="edit"></slot>
|
<slot v-else name="edit"></slot>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<div v-if="value === undefined" type="primary" size="small" @click.stop="setValue">自定义</div>
|
|
||||||
<div v-else style="margin-left: 100px" type="primary" size="small" @click.stop="clearValue">还原</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="less"></style>
|
<style lang="less">
|
||||||
|
.rollbackable {
|
||||||
|
.value-render {
|
||||||
|
.ant-select,
|
||||||
|
.ant-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -4,54 +4,67 @@ import { useI18n } from "/@/locales";
|
||||||
import { Modal, notification } from "ant-design-vue";
|
import { Modal, notification } from "ant-design-vue";
|
||||||
import ConfigEditor from "./config-editor.vue";
|
import ConfigEditor from "./config-editor.vue";
|
||||||
import { useModal } from "/@/use/use-modal";
|
import { useModal } from "/@/use/use-modal";
|
||||||
|
import { ref } from "vue";
|
||||||
export function usePluginConfig() {
|
export function usePluginConfig() {
|
||||||
const { openCrudFormDialog } = useFormWrapper();
|
const { openCrudFormDialog } = useFormWrapper();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const modal = useModal();
|
const modal = useModal();
|
||||||
async function openConfigDialog({ row, crudExpose }) {
|
async function openConfigDialog({ row, crudExpose }) {
|
||||||
// function createCrudOptions() {
|
const configEditorRef = ref();
|
||||||
// return {
|
function createCrudOptions() {
|
||||||
// crudOptions: {
|
return {
|
||||||
// columns: {},
|
crudOptions: {
|
||||||
// form: {
|
columns: {},
|
||||||
// wrapper: {
|
form: {
|
||||||
// width: "80%",
|
wrapper: {
|
||||||
// title: "插件元数据配置",
|
width: "80%",
|
||||||
// saveRemind: false,
|
title: "插件元数据配置",
|
||||||
// slots: {
|
saveRemind: false,
|
||||||
// "form-body-top": () => {
|
slots: {
|
||||||
// return (
|
"form-body-top": () => {
|
||||||
// <div>
|
return (
|
||||||
// <ConfigEditor plugin={row}></ConfigEditor>
|
<div>
|
||||||
// </div>
|
<ConfigEditor ref={configEditorRef} plugin={row}></ConfigEditor>
|
||||||
// );
|
</div>
|
||||||
// },
|
);
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
// afterSubmit() {
|
},
|
||||||
// notification.success({ message: t("certd.operationSuccess") });
|
afterSubmit() {
|
||||||
// crudExpose.doRefresh();
|
notification.success({ message: t("certd.operationSuccess") });
|
||||||
// },
|
crudExpose.doRefresh();
|
||||||
// async doSubmit({ form }: any) {
|
},
|
||||||
// return await api.ImportPlugin({
|
async doSubmit({}: any) {
|
||||||
// ...form,
|
const form = configEditorRef.value.getForm();
|
||||||
// });
|
const newForm: any = {};
|
||||||
// },
|
for (const key in form) {
|
||||||
// },
|
const value = form[key];
|
||||||
// },
|
if (value && Object.keys(value).length > 0) {
|
||||||
// };
|
newForm[key] = value;
|
||||||
// }
|
}
|
||||||
// const { crudOptions } = createCrudOptions();
|
}
|
||||||
// await openCrudFormDialog({ crudOptions });
|
return await api.savePluginSetting({
|
||||||
|
name: row.name,
|
||||||
|
sysSetting: {
|
||||||
|
metadata: newForm,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const { crudOptions } = createCrudOptions();
|
||||||
|
await openCrudFormDialog({ crudOptions });
|
||||||
|
|
||||||
modal.confirm({
|
// modal.confirm({
|
||||||
title: "插件元数据配置",
|
// title: "插件元数据配置",
|
||||||
width: "80%",
|
// width: "80%",
|
||||||
content: () => {
|
// content: () => {
|
||||||
return <ConfigEditor plugin={row}></ConfigEditor>;
|
// return <ConfigEditor plugin={row}></ConfigEditor>;
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -2,7 +2,11 @@ import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/c
|
||||||
import { merge } from 'lodash-es';
|
import { merge } from 'lodash-es';
|
||||||
import { CrudController } from '@certd/lib-server';
|
import { CrudController } from '@certd/lib-server';
|
||||||
import { PluginImportReq, PluginService } from "../../../modules/plugin/service/plugin-service.js";
|
import { PluginImportReq, PluginService } from "../../../modules/plugin/service/plugin-service.js";
|
||||||
import { CommPluginConfig, PluginConfigService } from '../../../modules/plugin/service/plugin-config-service.js';
|
import {
|
||||||
|
CommPluginConfig,
|
||||||
|
PluginConfig,
|
||||||
|
PluginConfigService
|
||||||
|
} from '../../../modules/plugin/service/plugin-config-service.js';
|
||||||
/**
|
/**
|
||||||
* 插件
|
* 插件
|
||||||
*/
|
*/
|
||||||
|
@ -79,7 +83,11 @@ export class PluginController extends CrudController<PluginService> {
|
||||||
const res = await this.pluginConfigService.saveCommPluginConfig(body);
|
const res = await this.pluginConfigService.saveCommPluginConfig(body);
|
||||||
return this.ok(res);
|
return this.ok(res);
|
||||||
}
|
}
|
||||||
|
@Post('/saveSetting', { summary: 'sys:settings:edit' })
|
||||||
|
async saveSetting(@Body(ALL) body: PluginConfig) {
|
||||||
|
const res = await this.pluginConfigService.savePluginConfig(body);
|
||||||
|
return this.ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
@Post('/import', { summary: 'sys:settings:edit' })
|
@Post('/import', { summary: 'sys:settings:edit' })
|
||||||
async import(@Body(ALL) body: PluginImportReq) {
|
async import(@Body(ALL) body: PluginImportReq) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { PluginService } from './plugin-service.js';
|
||||||
|
|
||||||
export type PluginConfig = {
|
export type PluginConfig = {
|
||||||
name: string;
|
name: string;
|
||||||
disabled: boolean;
|
disabled?: boolean;
|
||||||
sysSetting: {
|
sysSetting: {
|
||||||
input?: Record<string, any>;
|
input?: Record<string, any>;
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, any>;
|
||||||
|
@ -38,10 +38,12 @@ export class PluginConfigService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveCommPluginConfig(config: CommPluginConfig) {
|
async saveCommPluginConfig(config: CommPluginConfig) {
|
||||||
await this.savePluginConfig('CertApply', config.CertApply);
|
config.CertApply.name = 'CertApply';
|
||||||
|
await this.savePluginConfig(config.CertApply);
|
||||||
}
|
}
|
||||||
|
|
||||||
async savePluginConfig(name: string, config: PluginConfig) {
|
async savePluginConfig( config: PluginConfig) {
|
||||||
|
const name = config.name;
|
||||||
const sysSetting = config?.sysSetting;
|
const sysSetting = config?.sysSetting;
|
||||||
if (!sysSetting) {
|
if (!sysSetting) {
|
||||||
throw new Error(`${name}.sysSetting is required`);
|
throw new Error(`${name}.sysSetting is required`);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
|
import {Inject, Provide, Scope, ScopeEnum} from "@midwayjs/core";
|
||||||
import { BaseService, PageReq } from "@certd/lib-server";
|
import {BaseService, PageReq} from "@certd/lib-server";
|
||||||
import { PluginEntity } from "../entity/plugin.js";
|
import {PluginEntity} from "../entity/plugin.js";
|
||||||
import { InjectEntityModel } from "@midwayjs/typeorm";
|
import {InjectEntityModel} from "@midwayjs/typeorm";
|
||||||
import { Repository } from "typeorm";
|
import {IsNull, Not, Repository} from "typeorm";
|
||||||
import { isComm } from "@certd/plus-core";
|
import {isComm} from "@certd/plus-core";
|
||||||
import { BuiltInPluginService } from "../../pipeline/service/builtin-plugin-service.js";
|
import {BuiltInPluginService} from "../../pipeline/service/builtin-plugin-service.js";
|
||||||
import { merge } from "lodash-es";
|
import {merge} from "lodash-es";
|
||||||
import { accessRegistry, notificationRegistry, pluginRegistry } from "@certd/pipeline";
|
import {accessRegistry, notificationRegistry, pluginRegistry} from "@certd/pipeline";
|
||||||
import { dnsProviderRegistry } from "@certd/plugin-cert";
|
import {dnsProviderRegistry} from "@certd/plugin-cert";
|
||||||
import { logger } from "@certd/basic";
|
import {logger} from "@certd/basic";
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import { getDefaultAccessPlugin, getDefaultDeployPlugin, getDefaultDnsPlugin } from "./default-plugin.js";
|
import {getDefaultAccessPlugin, getDefaultDeployPlugin, getDefaultDnsPlugin} from "./default-plugin.js";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
|
@ -57,9 +57,9 @@ export class PluginService extends BaseService<PluginEntity> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async getEnabledBuildInGroup(isSimple = false) {
|
async getEnabledBuildInGroup(opts?:{isSimple?:boolean,withSetting?:boolean}) {
|
||||||
const groups = this.builtInPluginService.getGroups();
|
const groups = this.builtInPluginService.getGroups();
|
||||||
if (isSimple) {
|
if (opts?.isSimple) {
|
||||||
for (const key in groups) {
|
for (const key in groups) {
|
||||||
const group = groups[key];
|
const group = groups[key];
|
||||||
group.plugins.forEach(item => {
|
group.plugins.forEach(item => {
|
||||||
|
@ -72,9 +72,43 @@ export class PluginService extends BaseService<PluginEntity> {
|
||||||
if (!isComm()) {
|
if (!isComm()) {
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化设置
|
||||||
|
const settingPlugins = await this.repository.find({
|
||||||
|
select:{
|
||||||
|
id:true,
|
||||||
|
name:true,
|
||||||
|
sysSetting:true
|
||||||
|
},
|
||||||
|
where: {
|
||||||
|
sysSetting : Not(IsNull())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//合并插件配置
|
||||||
|
const pluginSettingMap:any = {}
|
||||||
|
for (const item of settingPlugins) {
|
||||||
|
if (!item.sysSetting) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pluginSettingMap[item.name] = JSON.parse(item.sysSetting);
|
||||||
|
}
|
||||||
|
for (const key in groups) {
|
||||||
|
const group = groups[key];
|
||||||
|
if (!group.plugins) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const item of group.plugins) {
|
||||||
|
const pluginSetting = pluginSettingMap[item.name];
|
||||||
|
if (pluginSetting){
|
||||||
|
item.sysSetting = pluginSetting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//排除禁用的
|
||||||
const list = await this.list({
|
const list = await this.list({
|
||||||
query: {
|
query: {
|
||||||
type: "builtIn",
|
|
||||||
disabled: true
|
disabled: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue