perf: 任务配置不需要的字段可以自动隐藏

pull/189/head
xiaojunnuo 2024-09-04 15:49:00 +08:00
parent d0d3c2b588
commit 192d9dc7e3
12 changed files with 216 additions and 95 deletions

View File

@ -15,6 +15,7 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
vModel: "value",
mode: "tags",
open: false,
tokenSeparators: [",", " ", "", "、", "|"],
},
required: true,
col: {
@ -25,7 +26,7 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
"1、支持通配符域名例如 *.foo.com、foo.com、*.test.handsfree.work\n" +
"2、支持多个域名、多个子域名、多个通配符域名打到一个证书上域名必须是在同一个DNS提供商解析\n" +
"3、多级子域名要分成多个域名输入*.foo.com的证书不能用于xxx.yyy.foo.com、foo.com\n" +
"4、输入一个回车之后,再输入下一个",
"4、输入一个空格之后,再输入下一个",
})
domains!: string[];
@ -77,13 +78,6 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
})
successNotify = true;
@TaskInput({
title: "配置说明",
order: 9999,
helper: "运行策略请选择总是运行,其他证书部署任务请选择成功后跳过;当证书快到期前将会自动重新申请证书,然后会清空后续任务的成功状态,部署任务将会重新运行",
})
intro!: string;
// @TaskInput({
// title: "CsrInfo",
// helper: "暂时没有用",

View File

@ -37,11 +37,31 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
{ value: "zerossl", label: "ZeroSSL" },
],
},
helper: "如果letsencrypt.org或dv.acme-v02.api.pki.goog无法访问请尝试开启代理选项\n如果使用ZeroSSL、google证书需要提供EAB授权",
helper: "Let's Encrypt最简单如果使用ZeroSSL、google证书需要提供EAB授权",
required: true,
})
sslProvider!: SSLProvider;
@TaskInput({
title: "EAB授权",
component: {
name: "pi-access-selector",
type: "eab",
},
maybeNeed: true,
required: true,
helper:
"需要提供EAB授权\nZeroSSL请前往[zerossl开发者中心](https://app.zerossl.com/developer),生成 'EAB Credentials' \n Google请查看[google获取eab帮助文档](https://github.com/certd/certd/blob/v2/doc/google/google.md)",
mergeScript: `
return {
show: ctx.compute(({form})=>{
return form.sslProvider === 'zerossl' || form.sslProvider === 'google'
})
}
`,
})
eabAccessId!: number;
@TaskInput({
title: "加密算法",
value: "rsa_2048",
@ -62,18 +82,6 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
})
privateKeyType!: PrivateKeyType;
@TaskInput({
title: "EAB授权",
component: {
name: "pi-access-selector",
type: "eab",
},
maybeNeed: true,
helper:
"如果使用ZeroSSL或者google证书需要提供EAB授权\nZeroSSL请前往 https://app.zerossl.com/developer 生成 'EAB Credentials' \n Google请前往https://github.com/certd/certd/blob/v2/doc/google/google.md",
})
eabAccessId!: number;
@TaskInput({
title: "DNS提供商",
component: {
@ -81,7 +89,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
},
required: true,
helper:
"请选择dns解析提供商您的域名是在哪里注册的或者域名的dns解析服务器属于哪个平台\n如果这里没有您的dns解析提供商您可以将域名解析服务器设置成上面的任意一个提供商",
"请选择dns解析提供商您的域名是在哪里注册的或者域名的dns解析服务器属于哪个平台\n如果这里没有您需要的dns解析提供商您需要将域名解析服务器设置成上面的任意一个提供商",
})
dnsProviderType!: string;
@ -92,13 +100,14 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
},
required: true,
helper: "请选择dns解析提供商授权",
reference: [
{
src: "form.dnsProviderType",
dest: "component.type",
type: "computed",
},
],
mergeScript: `return {
component:{
type: ctx.compute(({form})=>{
return form.dnsProviderType
})
}
}
`,
})
dnsProviderAccess!: string;

View File

@ -70,6 +70,7 @@ const onError = (error: any) => {
}
.vcron-select-input {
min-height: 22px;
background-color: #fff;
}
.vcron-select-container {
display: flex;

View File

@ -1,17 +0,0 @@
import _ from "lodash-es";
import { compute } from "@fast-crud/fast-crud";
export function useReference(form: any) {
if (!form.reference) {
return;
}
for (const reference of form.reference) {
_.set(
form,
reference.dest,
compute<any>((scope) => {
return _.get(scope, reference.src);
})
);
}
}

View File

@ -0,0 +1,40 @@
import _ from "lodash-es";
import { compute } from "@fast-crud/fast-crud";
export function useReference(formItem: any) {
if (formItem.reference) {
for (const reference of formItem.reference) {
_.set(
formItem,
reference.dest,
compute<any>((scope) => {
return _.get(scope, reference.src);
})
);
}
delete formItem.reference;
}
if (formItem.mergeScript) {
const ctx = {
compute
};
const script = formItem.mergeScript;
const func = new Function("ctx", script);
const merged = func(ctx);
_.merge(formItem, merged);
delete formItem.mergeScript;
}
//helper
if (formItem.helper && typeof formItem.helper === "string") {
//正则表达式替换 [name](url) 成 <a href="url" >
let helper = formItem.helper.replace(/\[(.*)\]\((.*)\)/g, '<a href="$2" target="_blank">$1</a>');
helper = helper.replace(/\n/g, "<br/>");
formItem.helper = {
render: () => {
return <div innerHTML={helper}></div>;
}
};
}
}

View File

@ -1,4 +1,4 @@
import { ColumnCompositionProps, dict } from "@fast-crud/fast-crud";
import { ColumnCompositionProps, dict, compute } from "@fast-crud/fast-crud";
// @ts-ignore
import * as api from "./api";
// @ts-ignore
@ -32,11 +32,25 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any) {
...value,
key
};
const column = _.merge({ title: key }, defaultPluginConfig, field);
if (column.value != null && _.get(form, key) == null) {
let column = _.merge({ title: key }, defaultPluginConfig, field);
//eval
if (column.mergeScript) {
const ctx = {
compute
};
const script = column.mergeScript;
delete column.mergeScript;
const func = new Function("ctx", script);
const merged = func(ctx);
column = _.merge(column, merged);
}
//设置默认值
if (column.value != null && _.get(form, key) == null) {
_.set(form, key, column.value);
}
//字段配置赋值
columnsRef.value[key] = column;
console.log("form", columnsRef.value);
});
@ -55,7 +69,12 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any) {
},
form: {
component: {
disabled: false
disabled: false,
showSearch: true,
filterOption: (input: string, option: any) => {
input = input?.toLowerCase();
return option.value.toLowerCase().indexOf(input) >= 0 || option.label.toLowerCase().indexOf(input) >= 0;
}
},
rules: [{ required: true, message: "请选择类型" }],
valueChange: {

View File

@ -22,12 +22,17 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
form: {
...inputDefine,
show: compute((ctx) => {
console.log(formWrapperRef);
const form = formWrapperRef.value.getFormData();
if (!form) {
return false;
}
return form?.certApplyPlugin === plugin.name;
let inputDefineShow = true;
if (inputDefine.show != null) {
const computeShow = inputDefine.show as any;
inputDefineShow = computeShow.computeFn({ form });
}
return form?.certApplyPlugin === plugin.name && inputDefineShow;
})
}
};
@ -60,8 +65,8 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
render: () => {
return (
<ul>
<li>Lego-ACMELegoDNS</li>
<li>JS-ACMEDNSCloudflare</li>
<li>JS-ACMEDNSCloudflare西</li>
<li>Lego-ACMELegoDNSLEGO使</li>
</ul>
);
}
@ -78,7 +83,7 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre
vModel: "modelValue",
placeholder: "0 0 4 * * *"
},
helper: "请输入cron表达式, 例如0 0 4 * * *每天凌晨4点触发",
helper: "点击上面的按钮,选择每天几点几分定时执行, 例如0 0 4 * * *每天凌晨4点0分0秒触发",
order: 100
}
},

View File

@ -1,5 +1,5 @@
<template>
<a-drawer v-model:open="stepDrawerVisible" placement="right" :closable="true" width="700px" @after-open-change="stepDrawerOnAfterVisibleChange">
<a-drawer v-model:open="stepDrawerVisible" placement="right" :closable="true" width="700px">
<template #title>
编辑步骤
<a-button v-if="editMode" @click="stepDelete()">
@ -59,7 +59,7 @@
:get-context-fn="blankFn"
/>
<template v-for="(item, key) in currentPlugin.input" :key="key">
<fs-form-item v-model="currentStep.input[key]" :item="item" :get-context-fn="blankFn" />
<fs-form-item v-if="item.show !== false" v-model="currentStep.input[key]" :item="item" :get-context-fn="blankFn" />
</template>
<fs-form-item v-model="currentStep.strategy.runStrategy" :item="runStrategyProps" :get-context-fn="blankFn" />
@ -83,9 +83,12 @@ import { nanoid } from "nanoid";
import { CopyOutlined } from "@ant-design/icons-vue";
import { PluginGroups } from "/@/views/certd/pipeline/pipeline/type";
import { useUserStore } from "/@/store/modules/user";
import { compute, useCompute } from "@fast-crud/fast-crud";
import { useReference } from "/@/use/use-refrence";
export default {
name: "PiStepForm",
// eslint-disable-next-line vue/no-unused-components
components: { CopyOutlined },
props: {
editMode: {
@ -106,7 +109,6 @@ export default {
const mode: Ref = ref("add");
const callback: Ref = ref();
const currentStep: Ref = ref({ title: undefined, input: {} });
const currentPlugin: Ref = ref({});
const stepFormRef: Ref = ref(null);
const stepDrawerVisible: Ref = ref(false);
const rules: Ref = ref({
@ -150,15 +152,10 @@ export default {
stepDrawerVisible.value = false;
};
const stepDrawerOnAfterVisibleChange = (val: any) => {
console.log("stepDrawerOnAfterVisibleChange", val);
};
const stepOpen = (step: any, emit: any) => {
callback.value = emit;
currentStep.value = _.merge({ input: {}, strategy: {} }, step);
console.log("currentStepOpen", currentStep.value);
if (step.type) {
changeCurrentPlugin(currentStep.value);
}
@ -189,33 +186,41 @@ export default {
stepOpen(step, emit);
};
const changeCurrentPlugin = (step: any) => {
const stepType = step.type;
const pluginDefine = pluginGroups.get(stepType);
if (pluginDefine) {
step.type = stepType;
step._isAdd = false;
currentPlugin.value = _.cloneDeep(pluginDefine);
for (let key in currentPlugin.value.input) {
const input = currentPlugin.value.input[key];
if (input?.reference) {
for (const reference of input.reference) {
_.set(
input,
reference.dest,
computed<any>(() => {
const scope = {
const currentPluginDefine = ref();
function getContext() {
return {
form: currentStep.value.input
};
return _.get(scope, reference.src);
})
);
}
const { doComputed } = useCompute();
const currentPlugin = doComputed(() => {
return currentPluginDefine.value;
}, getContext);
const changeCurrentPlugin = (step: any) => {
const stepType = step.type;
step.type = stepType;
step._isAdd = false;
let pluginDefine = pluginGroups.get(stepType);
if (pluginDefine == null) {
console.log("插件未找到", stepType);
return;
}
pluginDefine = _.cloneDeep(pluginDefine);
const columns = pluginDefine.input;
for (let key in columns) {
const column = columns[key];
useReference(column);
}
currentPluginDefine.value = pluginDefine;
for (let key in pluginDefine.input) {
const column = pluginDefine.input[key];
//
if ((input.default != null || input.value != null) && currentStep.value.input[key] == null) {
currentStep.value.input[key] = input.default ?? input.value;
}
if ((column.default != null || column.value != null) && currentStep.value.input[key] == null) {
currentStep.value.input[key] = column.default ?? column.value;
}
}
@ -269,7 +274,6 @@ export default {
stepView,
stepDrawerShow,
stepDrawerVisible,
stepDrawerOnAfterVisibleChange,
currentStep,
currentPlugin,
stepSave,

View File

@ -56,7 +56,7 @@
name: 'cron-editor',
vModel: 'modelValue'
},
helper: 'cron表达式例如 0 0 3 * * * 表示每天凌晨3点触发',
helper: '点击上面的按钮,选择每天几点几分定时执行, 例如0 0 4 * * *每天凌晨4点0分0秒触发',
rules: [{ required: true, message: '此项必填' }]
}"
/>

View File

@ -1,5 +1,5 @@
import type { Pipeline } from "@certd/pipeline";
import { FormItemProps } from "@fast-crud/fast-crud";
import { DynamicType, FormItemProps } from "@fast-crud/fast-crud";
export type PipelineDetail = {
pipeline: Pipeline;
};
@ -24,7 +24,7 @@ export type PluginDefine = {
title: string;
desc?: string;
input: {
[key: string]: FormItemProps;
[key: string]: DynamicType<FormItemProps>;
};
output: {
[key: string]: any;

View File

@ -34,6 +34,7 @@ export class DemoAccess implements IAccess {
},
//是否必填
required: true,
//改属性是否需要加密
encrypt: true,
})
//属性名称

View File

@ -10,16 +10,81 @@ import { IsAccess, AccessInput } from '@certd/pipeline';
desc: '',
})
export class WestAccess {
/**
*
*/
@AccessInput({
title: '权限范围',
component: {
name: 'a-select',
vModel: 'value',
options: [
{ value: 'account', label: '账户级别,对所有域名都有权限管理' },
{ value: 'domain', label: '域名级别,仅能管理单个域名' },
],
},
helper: '选择权限范围',
required: true,
})
scope = '';
/**
*
*/
@AccessInput({
title: '账号',
helper: '你的登录账号',
encrypt: false,
required: false,
mergeScript: `
return {
show:ctx.compute(({form})=>{
return form.access.scope === 'account'
})
}
`,
})
username = '';
/**
*
*/
@AccessInput({
title: 'ApiKey',
component: {
placeholder: 'apidomainkey',
placeholder: '账户级别的key对整个账户都有管理权限',
},
helper:'前往https://www.west.cn/manager/domain/ 进入对应域名管理页面上方点击ApiKey获取密钥',
required: true,
helper: '账户级别的key对整个账户都有管理权限\n前往https://www.west.cn/manager/API/APIconfig.asp手动设置“api连接密码”',
encrypt: true,
required: false,
mergeScript: `
return {
show:ctx.compute(({form})=>{
return form.access.scope === 'account'
})
}
`,
})
apikey = '';
/**
*
*/
@AccessInput({
title: 'apidomainkey',
component: {
placeholder: '域名级别的key仅对单个域名有权限',
},
helper: '域名级别的key仅对单个域名有权限。 \n前往[西部数据域名管理](https://www.west.cn/manager/domain/)点击域名右上方点击ApiKey获取密钥',
encrypt: true,
required: false,
mergeScript: `
return {
show:ctx.compute(({form})=>{
return form.access.scope === 'domain'
})
}
`,
})
apidomainkey = '';
}