mirror of https://github.com/certd/certd
				
				
				
			chore:
							parent
							
								
									656cb89fe8
								
							
						
					
					
						commit
						d558d50102
					
				| 
						 | 
				
			
			@ -1,5 +1,4 @@
 | 
			
		|||
import { CertInfo } from "../acme";
 | 
			
		||||
 | 
			
		||||
export interface ICertApplyUploadService {
 | 
			
		||||
  getCertInfo: (opts: { certId: number; userId: number }) => Promise<any>;
 | 
			
		||||
  updateCert: (opts: { certId: number; cert: CertInfo; userId: number }) => Promise<any>;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@ import type { CertInfo } from "../acme.js";
 | 
			
		|||
import { CertReader } from "../cert-reader.js";
 | 
			
		||||
import { CertApplyBaseConvertPlugin } from "../base-convert.js";
 | 
			
		||||
export * from "./d.js";
 | 
			
		||||
 | 
			
		||||
import dayjs from "dayjs";
 | 
			
		||||
import { ICertApplyUploadService } from "./d";
 | 
			
		||||
export { CertReader };
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +21,7 @@ export type { CertInfo };
 | 
			
		|||
  shortcut: {
 | 
			
		||||
    certUpdate: {
 | 
			
		||||
      title: "更新证书",
 | 
			
		||||
      icon: "ph:upload",
 | 
			
		||||
      icon: "ion:upload",
 | 
			
		||||
      action: "onCertUpdate",
 | 
			
		||||
      form: {
 | 
			
		||||
        columns: {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,20 +64,19 @@ export type { CertInfo };
 | 
			
		|||
})
 | 
			
		||||
export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: "证书仓库ID",
 | 
			
		||||
    title: "手动上传证书",
 | 
			
		||||
    component: {
 | 
			
		||||
      name: "cert-info-selector",
 | 
			
		||||
      name: "cert-info-updater",
 | 
			
		||||
      vModel: "modelValue",
 | 
			
		||||
    },
 | 
			
		||||
    helper: "请不要随意修改",
 | 
			
		||||
    helper: "手动上传证书",
 | 
			
		||||
    order: -9999,
 | 
			
		||||
    required: true,
 | 
			
		||||
    mergeScript: `
 | 
			
		||||
    return {
 | 
			
		||||
      component:{
 | 
			
		||||
        on:{
 | 
			
		||||
          selectedChange(scope){
 | 
			
		||||
          console.log(scope)
 | 
			
		||||
          updated(scope){
 | 
			
		||||
            scope.form.input.domains = scope.$event?.domains
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +142,7 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
 | 
			
		|||
  async onCertUpdate(data: any) {
 | 
			
		||||
    const certApplyUploadService = await this.ctx.serviceGetter.get("CertApplyUploadService");
 | 
			
		||||
 | 
			
		||||
    await certApplyUploadService.updateCert({
 | 
			
		||||
    const res = await certApplyUploadService.updateCert({
 | 
			
		||||
      certId: this.certInfoId,
 | 
			
		||||
      userId: this.ctx.user.id,
 | 
			
		||||
      cert: {
 | 
			
		||||
| 
						 | 
				
			
			@ -152,6 +150,12 @@ export class CertApplyUploadPlugin extends CertApplyBaseConvertPlugin {
 | 
			
		|||
        key: data.key,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      input: {
 | 
			
		||||
        domains: res.domains,
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <AConfigProvider :locale="locale" :theme="tokenTheme">
 | 
			
		||||
    <contextHolder />
 | 
			
		||||
    <fs-form-provider>
 | 
			
		||||
      <contextHolder />
 | 
			
		||||
      <router-view />
 | 
			
		||||
    </fs-form-provider>
 | 
			
		||||
  </AConfigProvider>
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ import AConfigProvider from "ant-design-vue/es/config-provider";
 | 
			
		|||
import { Modal } from "ant-design-vue";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "App"
 | 
			
		||||
  name: "App",
 | 
			
		||||
});
 | 
			
		||||
const [modal, contextHolder] = Modal.useModal();
 | 
			
		||||
provide("modal", modal);
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ const tokenTheme = computed(() => {
 | 
			
		|||
 | 
			
		||||
  return {
 | 
			
		||||
    algorithm,
 | 
			
		||||
    token: tokens
 | 
			
		||||
    token: tokens,
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
//其他初始化
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ import OutputSelector from "/@/components/plugins/common/output-selector/index.v
 | 
			
		|||
import DnsProviderSelector from "/@/components/plugins/cert/dns-provider-selector/index.vue";
 | 
			
		||||
import DomainsVerifyPlanEditor from "/@/components/plugins/cert/domains-verify-plan-editor/index.vue";
 | 
			
		||||
import AccessSelector from "/@/views/certd/access/access-selector/index.vue";
 | 
			
		||||
import CertInfoSelector from "/@/views/certd/monitor/cert/selector/index.vue";
 | 
			
		||||
import CertInfoUpdater from "/@/views/certd/monitor/cert/updater/index.vue";
 | 
			
		||||
import InputPassword from "./common/input-password.vue";
 | 
			
		||||
import ApiTest from "./common/api-test.vue";
 | 
			
		||||
export * from "./cert/index.js";
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ export default {
 | 
			
		|||
    app.component("DnsProviderSelector", DnsProviderSelector);
 | 
			
		||||
    app.component("DomainsVerifyPlanEditor", DomainsVerifyPlanEditor);
 | 
			
		||||
    app.component("AccessSelector", AccessSelector);
 | 
			
		||||
    app.component("CertInfoSelector", CertInfoSelector);
 | 
			
		||||
    app.component("CertInfoUpdater", CertInfoUpdater);
 | 
			
		||||
 | 
			
		||||
    app.component("ApiTest", ApiTest);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import { useRouter } from "vue-router";
 | 
			
		|||
import { useModal } from "/@/use/use-modal";
 | 
			
		||||
import { notification } from "ant-design-vue";
 | 
			
		||||
import CertView from "/@/views/certd/pipeline/cert-view.vue";
 | 
			
		||||
import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use";
 | 
			
		||||
 | 
			
		||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
 | 
			
		||||
  const api = certInfoApi;
 | 
			
		||||
| 
						 | 
				
			
			@ -51,69 +52,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
 | 
			
		|||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  async function openUpload(id?: any) {
 | 
			
		||||
    function createCrudOptions() {
 | 
			
		||||
      return {
 | 
			
		||||
        crudOptions: {
 | 
			
		||||
          request: {
 | 
			
		||||
            // addRequest: async (form: any) => {
 | 
			
		||||
            //   return await api.Upload(form);
 | 
			
		||||
            // },
 | 
			
		||||
            // editRequest: async (form: any) => {
 | 
			
		||||
            //   return await api.Upload(form);
 | 
			
		||||
            // }
 | 
			
		||||
          },
 | 
			
		||||
          columns: {
 | 
			
		||||
            id: {
 | 
			
		||||
              title: "ID",
 | 
			
		||||
              type: "number",
 | 
			
		||||
              form: {
 | 
			
		||||
                show: false,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            "cert.crt": {
 | 
			
		||||
              title: "证书",
 | 
			
		||||
              type: "textarea",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  rows: 4,
 | 
			
		||||
                },
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            "cert.key": {
 | 
			
		||||
              title: "私钥",
 | 
			
		||||
              type: "textarea",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  rows: 4,
 | 
			
		||||
                },
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
          form: {
 | 
			
		||||
            wrapper: {
 | 
			
		||||
              title: "上传自定义证书",
 | 
			
		||||
            },
 | 
			
		||||
            async doSubmit({ form }: any) {
 | 
			
		||||
              if (!id) {
 | 
			
		||||
                delete form.id;
 | 
			
		||||
              } else {
 | 
			
		||||
                form.id = id;
 | 
			
		||||
              }
 | 
			
		||||
              return await api.Upload(form);
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
    const { crudOptions } = createCrudOptions();
 | 
			
		||||
    const wrapperRef = await openCrudFormDialog({ crudOptions });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const { openUploadCreateDialog, openUpdateCertDialog } = useCertUpload();
 | 
			
		||||
  return {
 | 
			
		||||
    crudOptions: {
 | 
			
		||||
      request: {
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +84,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
 | 
			
		|||
            type: "primary",
 | 
			
		||||
            show: true,
 | 
			
		||||
            async click() {
 | 
			
		||||
              await openUpload();
 | 
			
		||||
              await openUploadCreateDialog();
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +118,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
 | 
			
		|||
            type: "link",
 | 
			
		||||
            icon: "ph:upload",
 | 
			
		||||
            async click({ row }) {
 | 
			
		||||
              await openUpload(row.id);
 | 
			
		||||
              await openUpdateCertDialog(row.id);
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
          remove: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,123 +0,0 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <div class="cert-info-selector w-full">
 | 
			
		||||
    <div class="flex-o w-full">
 | 
			
		||||
      <fs-table-select
 | 
			
		||||
        ref="tableSelectRef"
 | 
			
		||||
        class="flex-0"
 | 
			
		||||
        :model-value="modelValue"
 | 
			
		||||
        :dict="optionsDictRef"
 | 
			
		||||
        :create-crud-options="createCrudOptions"
 | 
			
		||||
        :crud-options-override="{
 | 
			
		||||
          search: { show: false },
 | 
			
		||||
          table: {
 | 
			
		||||
            scroll: {
 | 
			
		||||
              x: 540,
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        }"
 | 
			
		||||
        :show-current="false"
 | 
			
		||||
        :show-select="false"
 | 
			
		||||
        :dialog="{ width: 960 }"
 | 
			
		||||
        :destroy-on-close="false"
 | 
			
		||||
        height="400px"
 | 
			
		||||
        @update:model-value="onChange"
 | 
			
		||||
        @dialog-closed="doRefresh"
 | 
			
		||||
        @selected-change="onSelectedChange"
 | 
			
		||||
      />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="tsx" setup>
 | 
			
		||||
import { inject, ref, Ref, watch } from "vue";
 | 
			
		||||
import { message } from "ant-design-vue";
 | 
			
		||||
import createCrudOptions from "../crud";
 | 
			
		||||
import { dict } from "@fast-crud/fast-crud";
 | 
			
		||||
import { certInfoApi } from "../api";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "CertInfoSelector",
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  modelValue?: number | string;
 | 
			
		||||
  type?: string;
 | 
			
		||||
  placeholder?: string;
 | 
			
		||||
  size?: string;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
}>();
 | 
			
		||||
 | 
			
		||||
const onChange = async (value: number) => {
 | 
			
		||||
  await emitValue(value);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(["update:modelValue", "selectedChange", "change"]);
 | 
			
		||||
 | 
			
		||||
const tableSelectRef = ref();
 | 
			
		||||
 | 
			
		||||
const optionsDictRef = dict({
 | 
			
		||||
  value: "id",
 | 
			
		||||
  label: "domain",
 | 
			
		||||
  getNodesByValues: async (values: any[]) => {
 | 
			
		||||
    return await certInfoApi.GetOptionsByIds(values);
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// async function openTableSelectDialog() {
 | 
			
		||||
//   await tableSelectRef.value.open({});
 | 
			
		||||
//   await tableSelectRef.value.crudExpose.openAdd({});
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
const target: Ref<any> = ref({});
 | 
			
		||||
 | 
			
		||||
function clear() {
 | 
			
		||||
  if (props.disabled) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  emitValue(null);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function emitValue(value: any) {
 | 
			
		||||
  target.value = optionsDictRef.dataMap[value];
 | 
			
		||||
  if (value !== 0 && pipeline?.value && target && pipeline.value.userId !== target.value.userId) {
 | 
			
		||||
    message.error("对不起,您不能修改他人流水线的证书仓库ID");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  emit("change", value);
 | 
			
		||||
  emit("update:modelValue", value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onSelectedChange(value: any) {
 | 
			
		||||
  if (value && value.length > 0) {
 | 
			
		||||
    emit("selectedChange", value[0]);
 | 
			
		||||
  } else {
 | 
			
		||||
    emit("selectedChange", null);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// watch(
 | 
			
		||||
//   () => {
 | 
			
		||||
//     return props.modelValue;
 | 
			
		||||
//   },
 | 
			
		||||
//   async value => {
 | 
			
		||||
//     await optionsDictRef.loadDict();
 | 
			
		||||
//     target.value = optionsDictRef.dataMap[value];
 | 
			
		||||
//     emit("selectedChange", target.value);
 | 
			
		||||
//   },
 | 
			
		||||
//   {
 | 
			
		||||
//     immediate: true,
 | 
			
		||||
//   }
 | 
			
		||||
// );
 | 
			
		||||
 | 
			
		||||
//当不在pipeline中编辑时,可能为空
 | 
			
		||||
const pipeline = inject("pipeline", null);
 | 
			
		||||
 | 
			
		||||
async function doRefresh() {
 | 
			
		||||
  await optionsDictRef.reloadDict();
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="less">
 | 
			
		||||
.cert-info-selector {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <div class="cert-info-updater w-full flex items-center">
 | 
			
		||||
    <div class="flex-o">
 | 
			
		||||
      <fs-values-format :model-value="modelValue" :dict="certInfoDict" />
 | 
			
		||||
      <fs-button v-if="modelValue" type="primary" size="small" class="ml-1" icon="ion:upload" text="更新证书" @click="onUploadClick" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="tsx" setup>
 | 
			
		||||
import { inject } from "vue";
 | 
			
		||||
import { dict } from "@fast-crud/fast-crud";
 | 
			
		||||
import { certInfoApi } from "../api";
 | 
			
		||||
import { useCertUpload } from "/@/views/certd/pipeline/cert-upload/use";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "CertInfoUpdater",
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{
 | 
			
		||||
  modelValue?: number | string;
 | 
			
		||||
  type?: string;
 | 
			
		||||
  placeholder?: string;
 | 
			
		||||
  size?: string;
 | 
			
		||||
  disabled?: boolean;
 | 
			
		||||
}>();
 | 
			
		||||
const emit = defineEmits(["updated"]);
 | 
			
		||||
 | 
			
		||||
const certInfoDict = dict({
 | 
			
		||||
  value: "id",
 | 
			
		||||
  label: "domain",
 | 
			
		||||
  getNodesByValues: async (values: any[]) => {
 | 
			
		||||
    const res = await certInfoApi.GetOptionsByIds(values);
 | 
			
		||||
    if (res.length > 0) {
 | 
			
		||||
      emit("updated", {
 | 
			
		||||
        domains: res[0].domains,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const { openUpdateCertDialog } = useCertUpload();
 | 
			
		||||
function onUpdated(res: any) {
 | 
			
		||||
  emit("updated", res);
 | 
			
		||||
}
 | 
			
		||||
function onUploadClick() {
 | 
			
		||||
  openUpdateCertDialog(props.modelValue, onUpdated);
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="less">
 | 
			
		||||
.cert-info-selector {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			@ -48,25 +48,6 @@ export function useCertUpload() {
 | 
			
		|||
    }
 | 
			
		||||
    return inputs;
 | 
			
		||||
  }
 | 
			
		||||
  function topRender({ form, key }: any) {
 | 
			
		||||
    function onChange(e: any) {
 | 
			
		||||
      const file = e.target.files[0];
 | 
			
		||||
      const size = file.size;
 | 
			
		||||
      if (size > 100 * 1024) {
 | 
			
		||||
        notification.error({
 | 
			
		||||
          message: "文件超过100k,请选择正确的证书文件",
 | 
			
		||||
        });
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      const fileReader = new FileReader();
 | 
			
		||||
      fileReader.onload = function (e: any) {
 | 
			
		||||
        const value = e.target.result;
 | 
			
		||||
        set(form, key, value);
 | 
			
		||||
      };
 | 
			
		||||
      fileReader.readAsText(file); // 以文本形式读取文件
 | 
			
		||||
    }
 | 
			
		||||
    return <file-input class="mb-5" type="primary" text={"选择文件"} onChange={onChange} />;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async function openUploadCreateDialog() {
 | 
			
		||||
    //检查是否流水线数量超出限制
 | 
			
		||||
| 
						 | 
				
			
			@ -87,32 +68,38 @@ export function useCertUpload() {
 | 
			
		|||
          columns: {
 | 
			
		||||
            "cert.crt": {
 | 
			
		||||
              title: "证书",
 | 
			
		||||
              type: "textarea",
 | 
			
		||||
              type: "text",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  rows: 4,
 | 
			
		||||
                  placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                helper: "选择pem格式证书文件,或者粘贴到此",
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
                order: -9999,
 | 
			
		||||
                topRender,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            "cert.key": {
 | 
			
		||||
              title: "证书私钥",
 | 
			
		||||
              type: "textarea",
 | 
			
		||||
              type: "text",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  rows: 4,
 | 
			
		||||
                  placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                helper: "选择pem格式证书私钥文件,或者粘贴到此",
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
                order: -9999,
 | 
			
		||||
                topRender,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            ...inputs,
 | 
			
		||||
| 
						 | 
				
			
			@ -174,17 +161,22 @@ export function useCertUpload() {
 | 
			
		|||
    wrapperRef.value = wrapper;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async function openUpdateCertDialog(id: any) {
 | 
			
		||||
  async function openUpdateCertDialog(id: any, onSubmit?: any) {
 | 
			
		||||
    function createCrudOptions() {
 | 
			
		||||
      return {
 | 
			
		||||
        crudOptions: {
 | 
			
		||||
          columns: {
 | 
			
		||||
            "cert.crt": {
 | 
			
		||||
              title: "证书",
 | 
			
		||||
              type: "textarea",
 | 
			
		||||
              type: "text",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  rows: 4,
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN CERTIFICATE-----\n...\n...\n-----END CERTIFICATE-----",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +187,12 @@ export function useCertUpload() {
 | 
			
		|||
              type: "textarea",
 | 
			
		||||
              form: {
 | 
			
		||||
                component: {
 | 
			
		||||
                  rows: 4,
 | 
			
		||||
                  name: "pem-input",
 | 
			
		||||
                  vModel: "modelValue",
 | 
			
		||||
                  textarea: {
 | 
			
		||||
                    rows: 4,
 | 
			
		||||
                    placeholder: "-----BEGIN PRIVATE KEY-----\n...\n...\n-----END PRIVATE KEY----- ",
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                rules: [{ required: true, message: "此项必填" }],
 | 
			
		||||
                col: { span: 24 },
 | 
			
		||||
| 
						 | 
				
			
			@ -212,7 +209,10 @@ export function useCertUpload() {
 | 
			
		|||
                id: id,
 | 
			
		||||
                cert: form.cert,
 | 
			
		||||
              };
 | 
			
		||||
              return await api.UploadCert(form);
 | 
			
		||||
              const res = await api.UploadCert(req);
 | 
			
		||||
              if (onSubmit) {
 | 
			
		||||
                await onSubmit(res);
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,10 +7,10 @@
 | 
			
		|||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { doRequest } from "/@/components/plugins/lib";
 | 
			
		||||
import { ref, useAttrs } from "vue";
 | 
			
		||||
import { ref, useAttrs, inject } from "vue";
 | 
			
		||||
import { useFormWrapper } from "@fast-crud/fast-crud";
 | 
			
		||||
import { notification } from "ant-design-vue";
 | 
			
		||||
 | 
			
		||||
import { merge } from "lodash-es";
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "TaskShortcut",
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +32,22 @@ async function openDialog() {
 | 
			
		|||
  function createCrudOptions() {
 | 
			
		||||
    return {
 | 
			
		||||
      crudOptions: {
 | 
			
		||||
        columns: props.form.columns,
 | 
			
		||||
        columns: {
 | 
			
		||||
          ...props.form.columns,
 | 
			
		||||
          immediateRun: {
 | 
			
		||||
            title: "立即运行",
 | 
			
		||||
            type: "switch",
 | 
			
		||||
            span: 24,
 | 
			
		||||
            form: {
 | 
			
		||||
              value: true,
 | 
			
		||||
              component: {
 | 
			
		||||
                name: "a-switch",
 | 
			
		||||
                vModel: "checked",
 | 
			
		||||
              },
 | 
			
		||||
              helper: "保存后是否立即触发运行流水线",
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        form: {
 | 
			
		||||
          wrapper: {
 | 
			
		||||
            title: props.title,
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +67,7 @@ async function openDialog() {
 | 
			
		|||
  await openCrudFormDialog({ crudOptions });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const getPipelineScope: any = inject("getPipelineScope");
 | 
			
		||||
const doPluginFormSubmit = async (formData: any) => {
 | 
			
		||||
  if (loading.value) {
 | 
			
		||||
    return;
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +82,27 @@ const doPluginFormSubmit = async (formData: any) => {
 | 
			
		|||
      input: props.input,
 | 
			
		||||
      data: formData,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (res.input) {
 | 
			
		||||
      const { save, findStep } = getPipelineScope();
 | 
			
		||||
      const step = findStep(res.input);
 | 
			
		||||
      if (step) {
 | 
			
		||||
        // 数组覆盖合并
 | 
			
		||||
        mergeWith(step.input, res.input, (objValue, srcValue) => {
 | 
			
		||||
          if (isArray(objValue)) {
 | 
			
		||||
            return srcValue;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        //保存,但不改变当前编辑状态
 | 
			
		||||
        save(false);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (formData.immediateRun) {
 | 
			
		||||
      const { run } = getPipelineScope();
 | 
			
		||||
      run();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
  } finally {
 | 
			
		||||
    loading.value = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -647,31 +647,34 @@ export default defineComponent({
 | 
			
		|||
        validateErrors.value[taskId] = errors;
 | 
			
		||||
        errors.push(error);
 | 
			
		||||
      }
 | 
			
		||||
      function doValidate() {
 | 
			
		||||
        validateErrors.value = {};
 | 
			
		||||
 | 
			
		||||
        const stepIds: string[] = [];
 | 
			
		||||
        //校验output id是否正确
 | 
			
		||||
        const pp = pipeline.value;
 | 
			
		||||
        function eachSteps(callback: any) {
 | 
			
		||||
          if (pp.stages) {
 | 
			
		||||
            for (const stage of pp.stages) {
 | 
			
		||||
              if (stage.tasks) {
 | 
			
		||||
                for (const task of stage.tasks) {
 | 
			
		||||
                  if (task.steps) {
 | 
			
		||||
                    for (const step of task.steps) {
 | 
			
		||||
                      callback(step, task, stage);
 | 
			
		||||
                    }
 | 
			
		||||
      function eachSteps(pp: any, callback: any) {
 | 
			
		||||
        if (pp.stages) {
 | 
			
		||||
          for (const stage of pp.stages) {
 | 
			
		||||
            if (stage.tasks) {
 | 
			
		||||
              for (const task of stage.tasks) {
 | 
			
		||||
                if (task.steps) {
 | 
			
		||||
                  for (const step of task.steps) {
 | 
			
		||||
                    callback(step, task, stage);
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      function doValidate() {
 | 
			
		||||
        validateErrors.value = {};
 | 
			
		||||
 | 
			
		||||
        const stepIds: string[] = [];
 | 
			
		||||
        //校验output id是否正确
 | 
			
		||||
        const pp = pipeline.value;
 | 
			
		||||
 | 
			
		||||
        //检查输出的stepid是否存在
 | 
			
		||||
        let hasError = false;
 | 
			
		||||
        let errorMessage = "";
 | 
			
		||||
        eachSteps((step: any, task: any, stage: any) => {
 | 
			
		||||
        eachSteps(pp, (step: any, task: any, stage: any) => {
 | 
			
		||||
          stepIds.push(step.id);
 | 
			
		||||
          if (step.input) {
 | 
			
		||||
            for (const key in step.input) {
 | 
			
		||||
| 
						 | 
				
			
			@ -709,7 +712,7 @@ export default defineComponent({
 | 
			
		|||
      function hasValidateError(taskId: string) {
 | 
			
		||||
        return validateErrors.value[taskId] != null;
 | 
			
		||||
      }
 | 
			
		||||
      const save = async () => {
 | 
			
		||||
      const save = async (offEdit = true) => {
 | 
			
		||||
        doValidate();
 | 
			
		||||
 | 
			
		||||
        saveLoading.value = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -728,7 +731,9 @@ export default defineComponent({
 | 
			
		|||
 | 
			
		||||
            await props.options.doSave(pipeline.value);
 | 
			
		||||
          }
 | 
			
		||||
          toggleEditMode(false);
 | 
			
		||||
          if (offEdit) {
 | 
			
		||||
            toggleEditMode(false);
 | 
			
		||||
          }
 | 
			
		||||
        } finally {
 | 
			
		||||
          saveLoading.value = false;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -743,6 +748,17 @@ export default defineComponent({
 | 
			
		|||
        toggleEditMode(false);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      function findStep(id: string) {
 | 
			
		||||
        let found = null;
 | 
			
		||||
        const pp = pipeline.value;
 | 
			
		||||
        eachSteps(pp, (step: any, task: any, stage: any) => {
 | 
			
		||||
          if (step.id === id) {
 | 
			
		||||
            found = step;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        return found;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        run,
 | 
			
		||||
        save,
 | 
			
		||||
| 
						 | 
				
			
			@ -750,6 +766,7 @@ export default defineComponent({
 | 
			
		|||
        cancel,
 | 
			
		||||
        saveLoading,
 | 
			
		||||
        hasValidateError,
 | 
			
		||||
        findStep,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -821,6 +838,17 @@ export default defineComponent({
 | 
			
		|||
    const settingStore = useSettingStore();
 | 
			
		||||
    const userStore = useUserStore();
 | 
			
		||||
 | 
			
		||||
    const actions = useActions();
 | 
			
		||||
    const trigger = useTrigger();
 | 
			
		||||
    provide("getPipelineScope", () => {
 | 
			
		||||
      return {
 | 
			
		||||
        run: actions.run,
 | 
			
		||||
        pipeline: pipeline,
 | 
			
		||||
        save: actions.save,
 | 
			
		||||
        findStep: actions.findStep,
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      pipeline,
 | 
			
		||||
      currentHistory,
 | 
			
		||||
| 
						 | 
				
			
			@ -830,8 +858,8 @@ export default defineComponent({
 | 
			
		|||
      settingStore,
 | 
			
		||||
      ...useTaskRet,
 | 
			
		||||
      ...useStageRet,
 | 
			
		||||
      ...useTrigger(),
 | 
			
		||||
      ...useActions(),
 | 
			
		||||
      ...trigger,
 | 
			
		||||
      ...actions,
 | 
			
		||||
      ...useHistory(),
 | 
			
		||||
      ...useNotification(),
 | 
			
		||||
      ...useScroll(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,6 @@ import { BaseService, CommonException } from "@certd/lib-server";
 | 
			
		|||
import { InjectEntityModel } from "@midwayjs/typeorm";
 | 
			
		||||
import { EntityManager, Repository } from "typeorm";
 | 
			
		||||
import { CertInfoEntity } from "../entity/cert-info.js";
 | 
			
		||||
import { logger } from "@certd/basic";
 | 
			
		||||
import { CertInfo, CertReader } from "@certd/plugin-cert";
 | 
			
		||||
import { PipelineService } from "../../pipeline/service/pipeline-service.js";
 | 
			
		||||
import { CertInfoService } from "./cert-info-service.js";
 | 
			
		||||
| 
						 | 
				
			
			@ -69,9 +68,12 @@ export class CertUploadService extends BaseService<CertInfoEntity> {
 | 
			
		|||
      certReader: new CertReader(req.cert)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    if (certInfoEntity.pipelineId) {
 | 
			
		||||
      logger.info( `触发流水线部署:${certInfoEntity.pipelineId}`)
 | 
			
		||||
      await this.pipelineService.trigger(certInfoEntity.pipelineId)
 | 
			
		||||
    return {
 | 
			
		||||
      id: certInfoEntity.id,
 | 
			
		||||
      domains: certInfoEntity.domains.split(','),
 | 
			
		||||
      pipelineId: certInfoEntity.pipelineId,
 | 
			
		||||
      fromType: certInfoEntity.fromType,
 | 
			
		||||
      updateTime: certInfoEntity.updateTime,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +155,10 @@ export class CertUploadService extends BaseService<CertInfoEntity> {
 | 
			
		|||
 | 
			
		||||
      return {
 | 
			
		||||
        id:newCertInfo.id,
 | 
			
		||||
        pipelineId: newPipeline.id
 | 
			
		||||
        pipelineId: newPipeline.id,
 | 
			
		||||
        domains: newCertInfo.domains.split(','),
 | 
			
		||||
        fromType: newCertInfo.fromType,
 | 
			
		||||
        updateTime: newCertInfo.updateTime,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ export type DnslaRecord = {
 | 
			
		|||
// 这里通过IsDnsProvider注册一个dnsProvider
 | 
			
		||||
@IsDnsProvider({
 | 
			
		||||
  name: 'dnsla',
 | 
			
		||||
  title: 'dnsla',
 | 
			
		||||
  title: 'dns.la',
 | 
			
		||||
  desc: 'dns.la',
 | 
			
		||||
  icon: 'arcticons:dns-changer-3',
 | 
			
		||||
  // 这里是对应的 cloudflare的access类型名称
 | 
			
		||||
| 
						 | 
				
			
			@ -146,7 +146,7 @@ export class DnslaDnsProvider extends AbstractDnsProvider<DnslaRecord> {
 | 
			
		|||
      type: 16,
 | 
			
		||||
      host: fullRecord,
 | 
			
		||||
      data: value,
 | 
			
		||||
      ttl: 300,
 | 
			
		||||
      ttl: 1,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return res.data;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue