Merge remote-tracking branch 'origin/v2-dev' into v2-dev

This commit is contained in:
xiaojunnuo
2025-09-08 14:45:21 +08:00
54 changed files with 952 additions and 233 deletions
@@ -66,7 +66,7 @@ const getOptions = async () => {
const input = (pluginType === "plugin" ? form?.input : form) || {};
for (let key in define.input) {
const inWatches = props.watches.includes(key);
const inWatches = props.watches?.includes(key);
const inputDefine = define.input[key];
if (inWatches && inputDefine.required) {
const value = input[key];
@@ -105,7 +105,7 @@ const getOptions = async () => {
const input = (pluginType === "plugin" ? form?.input : form) || {};
for (let key in define.input) {
const inWatches = props.watches.includes(key);
const inWatches = props.watches?.includes(key);
const inputDefine = define.input[key];
if (inWatches && inputDefine.required) {
const value = input[key];
@@ -169,7 +169,7 @@ const getOptions = async () => {
};
const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 || String(option.value).toLowerCase().indexOf(input.toLowerCase());
return option.label.toLowerCase().includes(input.toLowerCase()) || String(option.value).toLowerCase().includes(input.toLowerCase());
};
async function onClick() {
@@ -0,0 +1,192 @@
<template>
<div class="remote-select">
<div class="flex flex-row">
<a-tree-select class="remote-tree-select-input" :tree-data="optionsRef" :value="value" tree-checkable allow-clear v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)"> </a-tree-select>
<div class="ml-5">
<fs-button :loading="loading" title="刷新选项" icon="ion:refresh-outline" @click="refreshOptions"></fs-button>
</div>
</div>
<div class="helper" :class="{ error: hasError }">
{{ message }}
</div>
</div>
</template>
<script setup lang="ts">
import { ComponentPropsType, doRequest } from "/@/components/plugins/lib";
import { defineComponent, inject, ref, useAttrs, watch, Ref } from "vue";
import { PluginDefine } from "@certd/pipeline";
defineOptions({
name: "RemoteTreeSelect",
});
const props = defineProps<
{
watches: string[];
search?: boolean;
pager?: boolean;
} & ComponentPropsType
>();
const emit = defineEmits<{
"update:value": any;
}>();
const attrs = useAttrs();
const getCurrentPluginDefine: any = inject("getCurrentPluginDefine", () => {
return {};
});
const getScope: any = inject("get:scope", () => {
return {};
});
const getPluginType: any = inject("get:plugin:type", () => {
return "plugin";
});
const searchKeyRef = ref("");
const optionsRef = ref([]);
const message = ref("");
const hasError = ref(false);
const loading = ref(false);
const pagerRef: Ref = ref({
current: 1,
});
const getOptions = async () => {
debugger;
if (loading.value) {
return;
}
if (!getCurrentPluginDefine) {
return;
}
const define: PluginDefine = getCurrentPluginDefine()?.value;
if (!define) {
return;
}
const pluginType = getPluginType();
const { form } = getScope();
const input = (pluginType === "plugin" ? form?.input : form) || {};
for (let key in define.input) {
const inWatches = props.watches?.includes(key);
const inputDefine = define.input[key];
if (inWatches && inputDefine.required) {
const value = input[key];
if (value == null || value === "") {
console.log("remote-select required", key);
return;
}
}
}
message.value = "";
hasError.value = false;
loading.value = true;
const pageNo = pagerRef.value.pageNo;
const pageSize = pagerRef.value.pageSize;
try {
const res = await doRequest(
{
type: pluginType,
typeName: form.type,
action: props.action,
input,
data: {
searchKey: props.search ? searchKeyRef.value : "",
pageNo,
pageSize,
},
},
{
onError(err: any) {
hasError.value = true;
message.value = `获取选项出错:${err.message}`;
},
showErrorNotify: false,
}
);
const list = res?.list || res || [];
if (list.length > 0) {
message.value = "获取数据成功,请从下拉框中选择";
} else {
message.value = "获取数据成功,没有数据";
}
optionsRef.value = list;
pagerRef.value.total = list.length;
if (props.pager) {
if (res.pageNo != null) {
pagerRef.value.pageNo = res.pageNo ?? 1;
}
if (res.pageSize != null) {
pagerRef.value.pageSize = res.pageSize ?? 100;
}
if (res.total != null) {
pagerRef.value.total = res.total ?? list.length;
}
}
return res;
} finally {
loading.value = false;
}
};
async function onClick() {
if (optionsRef.value?.length === 0) {
await refreshOptions();
}
}
async function refreshOptions() {
await getOptions();
}
async function doSearch() {
pagerRef.value.pageNo = 1;
await refreshOptions();
}
watch(
() => {
const pluginType = getPluginType();
const { form, key } = getScope();
const input = (pluginType === "plugin" ? form?.input : form) || {};
const watches = {};
for (const key of props.watches) {
//@ts-ignore
watches[key] = input[key];
}
return {
form: watches,
key,
};
},
async (value, oldValue) => {
const { form } = value;
const oldForm: any = oldValue?.form;
let changed = oldForm == null || optionsRef.value.length == 0;
for (const key of props.watches) {
//@ts-ignore
if (oldForm && form[key] != oldForm[key]) {
changed = true;
break;
}
}
if (changed) {
await getOptions();
}
},
{
immediate: true,
}
);
async function onPageChange(current: any) {
await refreshOptions();
}
</script>
<style lang="less"></style>
@@ -2,6 +2,7 @@ import SynologyIdDeviceGetter from "./synology/device-id-getter.vue";
import RemoteAutoComplete from "./common/remote-auto-complete.vue";
import RemoteSelect from "./common/remote-select.vue";
import RemoteInput from "./common/remote-input.vue";
import RemoteTreeSelect from "./common/remote-tree-select.vue";
import CertDomainsGetter from "./common/cert-domains-getter.vue";
import OutputSelector from "/@/components/plugins/common/output-selector/index.vue";
import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selector/index.vue";
@@ -24,6 +25,7 @@ export default {
app.component("SynologyDeviceIdGetter", SynologyIdDeviceGetter);
app.component("RemoteAutoComplete", RemoteAutoComplete);
app.component("RemoteSelect", RemoteSelect);
app.component("RemoteTreeSelect", RemoteTreeSelect);
app.component("RemoteInput", RemoteInput);
app.component("CertDomainsGetter", CertDomainsGetter);
app.component("InputPassword", InputPassword);
@@ -219,6 +219,7 @@ export default {
triggerCronHelper:
"Click the button above to choose a daily execution time.\nIt is recommended to trigger once per day. The task will be skipped if the certificate has not expired and will not be executed repeatedly.",
notificationTitle: "Failure Notification",
notificationWhen: "Notification Timing",
notificationHelper: "Get real-time alerts when the task fails",
groupIdTitle: "Pipeline Group",
},
@@ -224,6 +224,7 @@ export default {
triggerCronTitle: "定时触发",
triggerCronHelper: "点击上面的按钮,选择每天几点定时执行。\n建议设置为每天触发一次,证书未到期之前任务会跳过,不会重复执行",
notificationTitle: "失败通知",
notificationWhen: "通知时机",
notificationHelper: "任务执行失败实时提醒",
groupIdTitle: "流水线分组",
},
@@ -22,7 +22,7 @@ export function fillPipelineByDefaultForm(pipeline: any, form: any) {
if (form.notification != null) {
notifications.push({
type: "custom",
when: ["error", "turnToSuccess", "success"],
when: form.notificationWhen || ["error", "turnToSuccess"],
notificationId: form.notification,
title: form.notificationTarget?.name || "自定义通知",
});
@@ -223,6 +223,25 @@ export function useCertPipelineCreator() {
helper: t("certd.pipelineForm.notificationHelper"),
},
},
notificationWhen: {
title: t("certd.pipelineForm.notificationWhen"),
type: "text",
form: {
value: ["error", "turnToSuccess"],
component: {
name: "a-select",
vModel: "value",
mode: "multiple",
options: [
{ value: "start", label: t("certd.start_time") },
{ value: "success", label: t("certd.success_time") },
{ value: "turnToSuccess", label: t("certd.fail_to_success_time") },
{ value: "error", label: t("certd.fail_time") },
],
},
order: 102,
},
},
groupId: {
title: t("certd.pipelineForm.groupIdTitle"),
type: "dict-select",
@@ -268,7 +287,7 @@ export function useCertPipelineCreator() {
async function doSubmit({ form }: any) {
// const certDetail = readCertDetail(form.cert.crt);
// 添加certd pipeline
const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "certApplyPlugin", "groupId"]);
const pluginInput = omit(form, ["triggerCron", "notification", "notificationTarget", "notificationWhen", "certApplyPlugin", "groupId"]);
let pipeline: any = {
title: form.domains[0] + "证书自动化",
runnableType: "pipeline",