perf: 阿里云部分插件优化 @nicheng-he

1.新增RemoteAutoComplete插件
2.阿里云OSS部署插件支持自动获取BucketList
3.阿里云ESA支持选择上传到阿里云CAS产物
4.解决阿里云OSS默认接入点配置错误问题
v2-dev
ahe 2025-07-23 15:45:40 +08:00 committed by xiaojunnuo
parent f7b7d3d65e
commit e3738f6422
4 changed files with 195 additions and 2 deletions

View File

@ -0,0 +1,162 @@
<template>
<div class="remote-auto-complete">
<div class="flex flex-row">
<a-auto-complete class="remote-auto-complete-input" :filter-option="filterOption" :options="optionsRef" :value="value" v-bind="attrs" @click="onClick" @update:value="emit('update:value', $event)">
</a-auto-complete>
<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: "RemoteAutoComplete",
});
const props = defineProps<
{
watches: string[];
} & 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 optionsRef = ref([]);
const message = ref("");
const hasError = ref(false);
const loading = ref(false);
const getOptions = async () => {
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;
try {
const res = await doRequest(
{
type: pluginType,
typeName: form.type,
action: props.action,
input,
data: {},
},
{
onError(err: any) {
hasError.value = true;
message.value = `获取选项出错:${err.message}`;
},
showErrorNotify: false,
}
);
const list = res?.list || res || [];
if (list.length > 0) {
message.value = "获取数据成功,请从下拉框中选择";
}
optionsRef.value = list;
return res;
} finally {
loading.value = false;
}
};
const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 || String(option.value).toLowerCase().indexOf(input.toLowerCase());
};
async function onClick() {
if (optionsRef.value?.length === 0) {
await refreshOptions();
}
}
async function refreshOptions() {
await getOptions();
}
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,
}
);
</script>
<style lang="less"></style>

View File

@ -1,4 +1,5 @@
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 CertDomainsGetter from "./common/cert-domains-getter.vue";
@ -21,6 +22,7 @@ export default {
app.component("ApiTest", ApiTest);
app.component("SynologyDeviceIdGetter", SynologyIdDeviceGetter);
app.component("RemoteAutoComplete", RemoteAutoComplete);
app.component("RemoteSelect", RemoteSelect);
app.component("RemoteInput", RemoteInput);
app.component("CertDomainsGetter", CertDomainsGetter);

View File

@ -26,7 +26,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin {
helper: "请选择证书申请任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames]
from: [...CertApplyPluginNames, 'uploadCertToAliyun']
},
required: true
})

View File

@ -59,6 +59,15 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin {
@TaskInput({
title: 'Bucket',
helper: '存储桶名称',
component: {
name: 'remote-auto-complete',
vModel: 'value',
type: 'plugin',
action: 'onGetBucketList',
search: false,
pager: false,
watches: ['accessId', 'region']
},
required: true,
})
bucket!: string;
@ -91,7 +100,7 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin {
@TaskInput({
title: '证书服务接入点',
helper: '不会选就按默认',
value: 'cas.aliyuncs.com',
value: 'cn-hangzhou',
component: {
name: 'a-select',
options: [
@ -101,6 +110,7 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin {
],
},
required: true,
order: -99,
})
casRegion!: string;
@ -112,6 +122,7 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin {
type: 'aliyun',
},
required: true,
order: -98,
})
accessId!: string;
@ -170,6 +181,24 @@ export class DeployCertToAliyunOSS extends AbstractTaskPlugin {
});
}
async onGetBucketList(data: any) {
console.log('data', data)
const access = (await this.getAccess(this.accessId)) as AliyunAccess;
const client = await this.getClient(access);
let res;
const buckets = []
do{
const requestData = {'marker': res?.nextMarker || null, 'max-keys': 1000};
res = await client.listBuckets(requestData)
buckets.push(...(res?.buckets || []))
} while (!!res?.nextMarker)
return buckets
.filter(bucket => bucket?.region === this.region)
.map(bucket => ({label: `${bucket.name}<${bucket.region}>`, value: bucket.name}));
}
async doRequest(client: any, params: any) {
params = client._bucketRequestParams('POST', this.bucket, {
cname: '',