mirror of https://github.com/certd/certd
				
				
				
			Merge branch 'v2' into v2-dev
						commit
						aa0c282205
					
				| 
						 | 
				
			
			@ -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>
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ export class AliyunDeployCertToESA extends AbstractTaskPlugin {
 | 
			
		|||
    helper: "请选择证书申请任务输出的域名证书",
 | 
			
		||||
    component: {
 | 
			
		||||
      name: "output-selector",
 | 
			
		||||
      from: [...CertApplyPluginNames]
 | 
			
		||||
      from: [...CertApplyPluginNames, 'uploadCertToAliyun']
 | 
			
		||||
    },
 | 
			
		||||
    required: true
 | 
			
		||||
  })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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: '',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue