import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon } from "@ant-design/icons"; import { Alert, Button, Divider, Flex, Form, type FormInstance, Select, Switch, Tooltip, Typography } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; import AccessEditModal from "@/components/access/AccessEditModal"; import AccessSelect from "@/components/access/AccessSelect"; import DeployProviderPicker from "@/components/provider/DeployProviderPicker"; import DeployProviderSelect from "@/components/provider/DeployProviderSelect"; import Show from "@/components/Show"; import { ACCESS_USAGES, DEPLOY_PROVIDERS, accessProvidersMap, deployProvidersMap } from "@/domain/provider"; import { type WorkflowNode, type WorkflowNodeConfigForDeploy } from "@/domain/workflow"; import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks"; import { useWorkflowStore } from "@/stores/workflow"; import DeployNodeConfigFormAliyunALBConfig from "./DeployNodeConfigFormAliyunALBConfig"; import DeployNodeConfigFormAliyunCASDeployConfig from "./DeployNodeConfigFormAliyunCASDeployConfig"; import DeployNodeConfigFormAliyunCDNConfig from "./DeployNodeConfigFormAliyunCDNConfig"; import DeployNodeConfigFormAliyunCLBConfig from "./DeployNodeConfigFormAliyunCLBConfig"; import DeployNodeConfigFormAliyunDCDNConfig from "./DeployNodeConfigFormAliyunDCDNConfig"; import DeployNodeConfigFormAliyunESAConfig from "./DeployNodeConfigFormAliyunESAConfig"; import DeployNodeConfigFormAliyunLiveConfig from "./DeployNodeConfigFormAliyunLiveConfig"; import DeployNodeConfigFormAliyunNLBConfig from "./DeployNodeConfigFormAliyunNLBConfig"; import DeployNodeConfigFormAliyunOSSConfig from "./DeployNodeConfigFormAliyunOSSConfig"; import DeployNodeConfigFormAliyunWAFConfig from "./DeployNodeConfigFormAliyunWAFConfig"; import DeployNodeConfigFormAWSCloudFrontConfig from "./DeployNodeConfigFormAWSCloudFrontConfig"; import DeployNodeConfigFormBaiduCloudCDNConfig from "./DeployNodeConfigFormBaiduCloudCDNConfig"; import DeployNodeConfigFormBaotaPanelConsoleConfig from "./DeployNodeConfigFormBaotaPanelConsoleConfig"; import DeployNodeConfigFormBaotaPanelSiteConfig from "./DeployNodeConfigFormBaotaPanelSiteConfig"; import DeployNodeConfigFormBytePlusCDNConfig from "./DeployNodeConfigFormBytePlusCDNConfig"; import DeployNodeConfigFormDogeCloudCDNConfig from "./DeployNodeConfigFormDogeCloudCDNConfig"; import DeployNodeConfigFormEdgioApplicationsConfig from "./DeployNodeConfigFormEdgioApplicationsConfig"; import DeployNodeConfigFormHuaweiCloudCDNConfig from "./DeployNodeConfigFormHuaweiCloudCDNConfig"; import DeployNodeConfigFormHuaweiCloudELBConfig from "./DeployNodeConfigFormHuaweiCloudELBConfig"; import DeployNodeConfigFormHuaweiCloudWAFConfig from "./DeployNodeConfigFormHuaweiCloudWAFConfig"; import DeployNodeConfigFormKubernetesSecretConfig from "./DeployNodeConfigFormKubernetesSecretConfig"; import DeployNodeConfigFormLocalConfig from "./DeployNodeConfigFormLocalConfig"; import DeployNodeConfigFormQiniuCDNConfig from "./DeployNodeConfigFormQiniuCDNConfig"; import DeployNodeConfigFormQiniuPiliConfig from "./DeployNodeConfigFormQiniuPiliConfig"; import DeployNodeConfigFormSSHConfig from "./DeployNodeConfigFormSSHConfig.tsx"; import DeployNodeConfigFormTencentCloudCDNConfig from "./DeployNodeConfigFormTencentCloudCDNConfig.tsx"; import DeployNodeConfigFormTencentCloudCLBConfig from "./DeployNodeConfigFormTencentCloudCLBConfig.tsx"; import DeployNodeConfigFormTencentCloudCOSConfig from "./DeployNodeConfigFormTencentCloudCOSConfig.tsx"; import DeployNodeConfigFormTencentCloudCSSConfig from "./DeployNodeConfigFormTencentCloudCSSConfig.tsx"; import DeployNodeConfigFormTencentCloudECDNConfig from "./DeployNodeConfigFormTencentCloudECDNConfig.tsx"; import DeployNodeConfigFormTencentCloudEOConfig from "./DeployNodeConfigFormTencentCloudEOConfig.tsx"; import DeployNodeConfigFormTencentCloudSSLDeployConfig from "./DeployNodeConfigFormTencentCloudSSLDeployConfig"; import DeployNodeConfigFormTencentCloudWAFConfig from "./DeployNodeConfigFormTencentCloudWAFConfig"; import DeployNodeConfigFormUCloudUCDNConfig from "./DeployNodeConfigFormUCloudUCDNConfig.tsx"; import DeployNodeConfigFormUCloudUS3Config from "./DeployNodeConfigFormUCloudUS3Config.tsx"; import DeployNodeConfigFormVolcEngineCDNConfig from "./DeployNodeConfigFormVolcEngineCDNConfig.tsx"; import DeployNodeConfigFormVolcEngineCLBConfig from "./DeployNodeConfigFormVolcEngineCLBConfig.tsx"; import DeployNodeConfigFormVolcEngineDCDNConfig from "./DeployNodeConfigFormVolcEngineDCDNConfig.tsx"; import DeployNodeConfigFormVolcEngineImageXConfig from "./DeployNodeConfigFormVolcEngineImageXConfig.tsx"; import DeployNodeConfigFormVolcEngineLiveConfig from "./DeployNodeConfigFormVolcEngineLiveConfig.tsx"; import DeployNodeConfigFormVolcEngineTOSConfig from "./DeployNodeConfigFormVolcEngineTOSConfig.tsx"; import DeployNodeConfigFormWebhookConfig from "./DeployNodeConfigFormWebhookConfig.tsx"; type DeployNodeConfigFormFieldValues = Partial; export type DeployNodeConfigFormProps = { className?: string; style?: React.CSSProperties; disabled?: boolean; initialValues?: DeployNodeConfigFormFieldValues; nodeId: string; onValuesChange?: (values: DeployNodeConfigFormFieldValues) => void; }; export type DeployNodeConfigFormInstance = { getFieldsValue: () => ReturnType["getFieldsValue"]>; resetFields: FormInstance["resetFields"]; validateFields: FormInstance["validateFields"]; }; const initFormModel = (): DeployNodeConfigFormFieldValues => { return { skipOnLastSucceeded: true, }; }; const DeployNodeConfigForm = forwardRef( ({ className, style, disabled, initialValues, nodeId, onValuesChange }, ref) => { const { t } = useTranslation(); const { getWorkflowOuptutBeforeId } = useWorkflowStore(useZustandShallowSelector(["updateNode", "getWorkflowOuptutBeforeId"])); // TODO: 优化此处逻辑 const [previousNodes, setPreviousNodes] = useState([]); useEffect(() => { const previousNodes = getWorkflowOuptutBeforeId(nodeId, "certificate"); setPreviousNodes(previousNodes); }, [nodeId]); const formSchema = z.object({ certificate: z .string({ message: t("workflow_node.deploy.form.certificate.placeholder") }) .nonempty(t("workflow_node.deploy.form.certificate.placeholder")), provider: z.string({ message: t("workflow_node.deploy.form.provider.placeholder") }).nonempty(t("workflow_node.deploy.form.provider.placeholder")), providerAccessId: z .string({ message: t("workflow_node.deploy.form.provider_access.placeholder") }) .nonempty(t("workflow_node.deploy.form.provider_access.placeholder")) .refine(() => !!formInst.getFieldValue("provider"), t("workflow_node.deploy.form.provider.placeholder")), providerConfig: z.any(), skipOnLastSucceeded: z.boolean(), }); const formRule = createSchemaFieldRule(formSchema); const { form: formInst, formProps } = useAntdForm({ name: "workflowNodeDeployConfigForm", initialValues: initialValues ?? initFormModel(), }); const fieldProvider = Form.useWatch("provider", { form: formInst, preserve: true }); const [nestedFormInst] = Form.useForm(); const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "workflowNodeDeployConfigFormProviderConfigForm" }); const nestedFormEl = useMemo(() => { const nestedFormProps = { form: nestedFormInst, formName: nestedFormName, disabled: disabled, initialValues: initialValues?.providerConfig, }; /* 注意:如果追加新的子组件,请保持以 ASCII 排序。 NOTICE: If you add new child component, please keep ASCII order. */ switch (fieldProvider) { case DEPLOY_PROVIDERS.ALIYUN_ALB: return ; case DEPLOY_PROVIDERS.ALIYUN_CAS_DEPLOY: return ; case DEPLOY_PROVIDERS.ALIYUN_CLB: return ; case DEPLOY_PROVIDERS.ALIYUN_CDN: return ; case DEPLOY_PROVIDERS.ALIYUN_DCDN: return ; case DEPLOY_PROVIDERS.ALIYUN_ESA: return ; case DEPLOY_PROVIDERS.ALIYUN_LIVE: return ; case DEPLOY_PROVIDERS.ALIYUN_NLB: return ; case DEPLOY_PROVIDERS.ALIYUN_OSS: return ; case DEPLOY_PROVIDERS.ALIYUN_WAF: return ; case DEPLOY_PROVIDERS.AWS_CLOUDFRONT: return ; case DEPLOY_PROVIDERS.BAIDUCLOUD_CDN: return ; case DEPLOY_PROVIDERS.BAOTAPANEL_CONSOLE: return ; case DEPLOY_PROVIDERS.BAOTAPANEL_SITE: return ; case DEPLOY_PROVIDERS.BYTEPLUS_CDN: return ; case DEPLOY_PROVIDERS.DOGECLOUD_CDN: return ; case DEPLOY_PROVIDERS.EDGIO_APPLICATIONS: return ; case DEPLOY_PROVIDERS.HUAWEICLOUD_CDN: return ; case DEPLOY_PROVIDERS.HUAWEICLOUD_ELB: return ; case DEPLOY_PROVIDERS.HUAWEICLOUD_WAF: return ; case DEPLOY_PROVIDERS.KUBERNETES_SECRET: return ; case DEPLOY_PROVIDERS.LOCAL: return ; case DEPLOY_PROVIDERS.QINIU_CDN: return ; case DEPLOY_PROVIDERS.QINIU_PILI: return ; case DEPLOY_PROVIDERS.SSH: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_CDN: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_CLB: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_COS: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_CSS: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_ECDN: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_EO: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_SSL_DEPLOY: return ; case DEPLOY_PROVIDERS.TENCENTCLOUD_WAF: return ; case DEPLOY_PROVIDERS.UCLOUD_UCDN: return ; case DEPLOY_PROVIDERS.UCLOUD_US3: return ; case DEPLOY_PROVIDERS.VOLCENGINE_CDN: return ; case DEPLOY_PROVIDERS.VOLCENGINE_CLB: return ; case DEPLOY_PROVIDERS.VOLCENGINE_DCDN: return ; case DEPLOY_PROVIDERS.VOLCENGINE_IMAGEX: return ; case DEPLOY_PROVIDERS.VOLCENGINE_LIVE: return ; case DEPLOY_PROVIDERS.VOLCENGINE_TOS: return ; case DEPLOY_PROVIDERS.WEBHOOK: return ; } }, [disabled, initialValues?.providerConfig, fieldProvider, nestedFormInst, nestedFormName]); const handleProviderPick = (value: string) => { formInst.setFieldValue("provider", value); onValuesChange?.(formInst.getFieldsValue(true)); }; const handleProviderSelect = (value: string) => { if (fieldProvider === value) return; // 切换部署目标时重置表单,避免其他部署目标的配置字段影响当前部署目标 if (initialValues?.provider === value) { formInst.resetFields(); } else { const oldValues = formInst.getFieldsValue(); const newValues: Record = {}; for (const key in oldValues) { if (key === "provider" || key === "providerAccessId" || key === "certificate") { newValues[key] = oldValues[key]; } else { newValues[key] = undefined; } } (formInst as FormInstance).setFieldsValue(newValues); if (deployProvidersMap.get(fieldProvider)?.provider !== deployProvidersMap.get(value)?.provider) { formInst.setFieldValue("providerAccessId", undefined); onValuesChange?.(formInst.getFieldsValue(true)); } } }; const handleFormProviderChange = (name: string) => { if (name === nestedFormName) { formInst.setFieldValue("providerConfig", nestedFormInst.getFieldsValue()); onValuesChange?.(formInst.getFieldsValue(true)); } }; const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values as DeployNodeConfigFormFieldValues); }; useImperativeHandle(ref, () => { return { getFieldsValue: () => { const values = formInst.getFieldsValue(true); values.providerConfig = nestedFormInst.getFieldsValue(); return values; }, resetFields: (fields) => { formInst.resetFields(fields); if (!!fields && fields.includes("providerConfig")) { nestedFormInst.resetFields(fields); } }, validateFields: (nameList, config) => { const t1 = formInst.validateFields(nameList, config); const t2 = nestedFormInst.validateFields(undefined, config); return Promise.all([t1, t2]).then(() => t1); }, } as DeployNodeConfigFormInstance; }); return (
} > { if (fieldProvider) { return deployProvidersMap.get(fieldProvider)?.provider === record.provider; } const provider = accessProvidersMap.get(record.provider); return !!provider?.usages?.includes(ACCESS_USAGES.DEPLOY); }} /> } /> } >