mirror of
https://github.com/usual2970/certimate.git
synced 2025-07-17 08:29:58 +00:00
feat: separate access providers and dns providers
This commit is contained in:
parent
8ed2b2475c
commit
a0c08e841d
internal
ui/src
@ -53,6 +53,7 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) {
|
|||||||
return nil, fmt.Errorf("failed to get access #%s record: %w", accessId, err)
|
return nil, fmt.Errorf("failed to get access #%s record: %w", accessId, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyProvider := node.GetConfigString("provider")
|
||||||
applyConfig := &applyConfig{
|
applyConfig := &applyConfig{
|
||||||
Domains: node.GetConfigString("domains"),
|
Domains: node.GetConfigString("domains"),
|
||||||
ContactEmail: node.GetConfigString("contactEmail"),
|
ContactEmail: node.GetConfigString("contactEmail"),
|
||||||
@ -63,7 +64,7 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) {
|
|||||||
DisableFollowCNAME: node.GetConfigBool("disableFollowCNAME"),
|
DisableFollowCNAME: node.GetConfigBool("disableFollowCNAME"),
|
||||||
}
|
}
|
||||||
|
|
||||||
challengeProvider, err := createChallengeProvider(domain.AccessProviderType(access.Provider), access.Config, applyConfig)
|
challengeProvider, err := createChallengeProvider(domain.ApplyDNSProviderType(applyProvider), access.Config, applyConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,13 @@ import (
|
|||||||
providerVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine"
|
providerVolcEngine "github.com/usual2970/certimate/internal/pkg/core/applicant/acme-dns-01/lego-providers/volcengine"
|
||||||
)
|
)
|
||||||
|
|
||||||
func createChallengeProvider(provider domain.AccessProviderType, accessConfig string, applyConfig *applyConfig) (challenge.Provider, error) {
|
func createChallengeProvider(provider domain.ApplyDNSProviderType, accessConfig string, applyConfig *applyConfig) (challenge.Provider, error) {
|
||||||
/*
|
/*
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
*/
|
*/
|
||||||
switch provider {
|
switch provider {
|
||||||
case domain.AccessProviderTypeACMEHttpReq:
|
case domain.ApplyDNSProviderTypeACMEHttpReq:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForACMEHttpReq{}
|
access := &domain.AccessConfigForACMEHttpReq{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -43,7 +43,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeAliyun:
|
case domain.ApplyDNSProviderTypeAliyun, domain.ApplyDNSProviderTypeAliyunDNS:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForAliyun{}
|
access := &domain.AccessConfigForAliyun{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -58,7 +58,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeAWS:
|
case domain.ApplyDNSProviderTypeAWS, domain.ApplyDNSProviderTypeAWSRoute53:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForAWS{}
|
access := &domain.AccessConfigForAWS{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -75,7 +75,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeCloudflare:
|
case domain.ApplyDNSProviderTypeCloudflare:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForCloudflare{}
|
access := &domain.AccessConfigForCloudflare{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -89,7 +89,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeGoDaddy:
|
case domain.ApplyDNSProviderTypeGoDaddy:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForGoDaddy{}
|
access := &domain.AccessConfigForGoDaddy{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -104,7 +104,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeHuaweiCloud:
|
case domain.ApplyDNSProviderTypeHuaweiCloud, domain.ApplyDNSProviderTypeHuaweiCloudDNS:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForHuaweiCloud{}
|
access := &domain.AccessConfigForHuaweiCloud{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -120,7 +120,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeNameDotCom:
|
case domain.ApplyDNSProviderTypeNameDotCom:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForNameDotCom{}
|
access := &domain.AccessConfigForNameDotCom{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -135,7 +135,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeNameSilo:
|
case domain.ApplyDNSProviderTypeNameSilo:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForNameSilo{}
|
access := &domain.AccessConfigForNameSilo{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -149,7 +149,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypePowerDNS:
|
case domain.ApplyDNSProviderTypePowerDNS:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForPowerDNS{}
|
access := &domain.AccessConfigForPowerDNS{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -164,7 +164,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeTencentCloud:
|
case domain.ApplyDNSProviderTypeTencentCloud, domain.ApplyDNSProviderTypeTencentCloudDNS:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForTencentCloud{}
|
access := &domain.AccessConfigForTencentCloud{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
@ -179,7 +179,7 @@ func createChallengeProvider(provider domain.AccessProviderType, accessConfig st
|
|||||||
return applicant, err
|
return applicant, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case domain.AccessProviderTypeVolcEngine:
|
case domain.ApplyDNSProviderTypeVolcEngine, domain.ApplyDNSProviderTypeVolcEngineDNS:
|
||||||
{
|
{
|
||||||
access := &domain.AccessConfigForVolcEngine{}
|
access := &domain.AccessConfigForVolcEngine{}
|
||||||
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
if err := json.Unmarshal([]byte(accessConfig), access); err != nil {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
type AccessProviderType string
|
type AccessProviderType string
|
||||||
|
|
||||||
/*
|
/*
|
||||||
提供商类型常量值。
|
授权提供商类型常量值。
|
||||||
|
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
@ -30,11 +30,39 @@ const (
|
|||||||
AccessProviderTypeWebhook = AccessProviderType("webhook")
|
AccessProviderTypeWebhook = AccessProviderType("webhook")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ApplyDNSProviderType string
|
||||||
|
|
||||||
|
/*
|
||||||
|
申请证书 DNS 提供商常量值。
|
||||||
|
短横线前的部分始终等于授权提供商类型。
|
||||||
|
|
||||||
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
|
*/
|
||||||
|
const (
|
||||||
|
ApplyDNSProviderTypeACMEHttpReq = ApplyDNSProviderType("acmehttpreq")
|
||||||
|
ApplyDNSProviderTypeAliyun = ApplyDNSProviderType("aliyun") // 兼容旧值,等同于 [ApplyDNSProviderTypeAliyunDNS]
|
||||||
|
ApplyDNSProviderTypeAliyunDNS = ApplyDNSProviderType("aliyun-dns")
|
||||||
|
ApplyDNSProviderTypeAWS = ApplyDNSProviderType("aws") // 兼容旧值,等同于 [ApplyDNSProviderTypeAWSRoute53]
|
||||||
|
ApplyDNSProviderTypeAWSRoute53 = ApplyDNSProviderType("aws-route53")
|
||||||
|
ApplyDNSProviderTypeCloudflare = ApplyDNSProviderType("cloudflare")
|
||||||
|
ApplyDNSProviderTypeGoDaddy = ApplyDNSProviderType("godaddy")
|
||||||
|
ApplyDNSProviderTypeHuaweiCloud = ApplyDNSProviderType("huaweicloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeHuaweiCloudDNS]
|
||||||
|
ApplyDNSProviderTypeHuaweiCloudDNS = ApplyDNSProviderType("huaweicloud-dns")
|
||||||
|
ApplyDNSProviderTypeNameDotCom = ApplyDNSProviderType("namedotcom")
|
||||||
|
ApplyDNSProviderTypeNameSilo = ApplyDNSProviderType("namesilo")
|
||||||
|
ApplyDNSProviderTypePowerDNS = ApplyDNSProviderType("powerdns")
|
||||||
|
ApplyDNSProviderTypeTencentCloud = ApplyDNSProviderType("tencentcloud") // 兼容旧值,等同于 [ApplyDNSProviderTypeTencentCloudDNS]
|
||||||
|
ApplyDNSProviderTypeTencentCloudDNS = ApplyDNSProviderType("tencentcloud-dns")
|
||||||
|
ApplyDNSProviderTypeVolcEngine = ApplyDNSProviderType("volcengine") // 兼容旧值,等同于 [ApplyDNSProviderTypeVolcEngineDNS]
|
||||||
|
ApplyDNSProviderTypeVolcEngineDNS = ApplyDNSProviderType("volcengine-dns")
|
||||||
|
)
|
||||||
|
|
||||||
type DeployProviderType string
|
type DeployProviderType string
|
||||||
|
|
||||||
/*
|
/*
|
||||||
提供商部署目标常量值。
|
部署目标提供商常量值。
|
||||||
短横线前的部分始终等于提供商类型。
|
短横线前的部分始终等于授权提供商类型。
|
||||||
|
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
|
67
ui/src/components/provider/ApplyDNSProviderPicker.tsx
Normal file
67
ui/src/components/provider/ApplyDNSProviderPicker.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { memo, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Avatar, Card, Col, Empty, Flex, Input, Row, Typography } from "antd";
|
||||||
|
|
||||||
|
import Show from "@/components/Show";
|
||||||
|
import { applyDNSProvidersMap } from "@/domain/provider";
|
||||||
|
|
||||||
|
export type ApplyDNSProviderPickerProps = {
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
|
placeholder?: string;
|
||||||
|
onSelect?: (value: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ApplyDNSProviderPicker = ({ className, style, placeholder, onSelect }: ApplyDNSProviderPickerProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const [keyword, setKeyword] = useState<string>();
|
||||||
|
|
||||||
|
const providers = Array.from(applyDNSProvidersMap.values());
|
||||||
|
const filteredProviders = providers.filter((provider) => {
|
||||||
|
if (keyword) {
|
||||||
|
const value = keyword.toLowerCase();
|
||||||
|
return provider.type.toLowerCase().includes(value) || provider.name.toLowerCase().includes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleProviderTypeSelect = (value: string) => {
|
||||||
|
onSelect?.(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={className} style={style}>
|
||||||
|
<Input.Search placeholder={placeholder} onChange={(e) => setKeyword(e.target.value.trim())} />
|
||||||
|
|
||||||
|
<div className="mt-4">
|
||||||
|
<Show when={filteredProviders.length > 0} fallback={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
{filteredProviders.map((provider, index) => {
|
||||||
|
return (
|
||||||
|
<Col key={index} span={12}>
|
||||||
|
<Card
|
||||||
|
className="h-16 w-full overflow-hidden shadow-sm"
|
||||||
|
styles={{ body: { height: "100%", padding: "0.5rem 1rem" } }}
|
||||||
|
hoverable
|
||||||
|
onClick={() => {
|
||||||
|
handleProviderTypeSelect(provider.type);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Flex className="size-full overflow-hidden" align="center" gap={8}>
|
||||||
|
<Avatar src={provider.icon} size="small" />
|
||||||
|
<Typography.Text className="line-clamp-2">{t(provider.name)}</Typography.Text>
|
||||||
|
</Flex>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Row>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ApplyDNSProviderPicker);
|
51
ui/src/components/provider/ApplyDNSProviderSelect.tsx
Normal file
51
ui/src/components/provider/ApplyDNSProviderSelect.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { memo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Avatar, Select, type SelectProps, Space, Typography } from "antd";
|
||||||
|
|
||||||
|
import { applyDNSProvidersMap } from "@/domain/provider";
|
||||||
|
|
||||||
|
export type ApplyDNSProviderSelectProps = Omit<
|
||||||
|
SelectProps,
|
||||||
|
"filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender"
|
||||||
|
>;
|
||||||
|
|
||||||
|
const ApplyDNSProviderSelect = (props: ApplyDNSProviderSelectProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const options = Array.from(applyDNSProvidersMap.values()).map((item) => ({
|
||||||
|
key: item.type,
|
||||||
|
value: item.type,
|
||||||
|
label: t(item.name),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const renderOption = (key: string) => {
|
||||||
|
const provider = applyDNSProvidersMap.get(key);
|
||||||
|
return (
|
||||||
|
<Space className="max-w-full grow overflow-hidden truncate" size={4}>
|
||||||
|
<Avatar src={provider?.icon} size="small" />
|
||||||
|
<Typography.Text className="leading-loose" ellipsis>
|
||||||
|
{t(provider?.name ?? "")}
|
||||||
|
</Typography.Text>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
{...props}
|
||||||
|
labelRender={({ label, value }) => {
|
||||||
|
if (label) {
|
||||||
|
return renderOption(value as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Typography.Text type="secondary">{props.placeholder}</Typography.Text>;
|
||||||
|
}}
|
||||||
|
options={options}
|
||||||
|
optionFilterProp={undefined}
|
||||||
|
optionLabelProp={undefined}
|
||||||
|
optionRender={(option) => renderOption(option.data.value)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(ApplyDNSProviderSelect);
|
@ -8,10 +8,11 @@ import { deployProvidersMap } from "@/domain/provider";
|
|||||||
export type DeployProviderPickerProps = {
|
export type DeployProviderPickerProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
placeholder?: string;
|
||||||
onSelect?: (value: string) => void;
|
onSelect?: (value: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DeployProviderPicker = ({ className, style, onSelect }: DeployProviderPickerProps) => {
|
const DeployProviderPicker = ({ className, style, placeholder, onSelect }: DeployProviderPickerProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [keyword, setKeyword] = useState<string>();
|
const [keyword, setKeyword] = useState<string>();
|
||||||
@ -32,7 +33,7 @@ const DeployProviderPicker = ({ className, style, onSelect }: DeployProviderPick
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className} style={style}>
|
<div className={className} style={style}>
|
||||||
<Input.Search placeholder={t("workflow_node.deploy.search.provider.placeholder")} onChange={(e) => setKeyword(e.target.value.trim())} />
|
<Input.Search placeholder={placeholder} onChange={(e) => setKeyword(e.target.value.trim())} />
|
||||||
|
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Show when={filteredProviders.length > 0} fallback={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}>
|
<Show when={filteredProviders.length > 0} fallback={<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}>
|
||||||
|
@ -21,7 +21,6 @@ const ApplyNode = ({ node, disabled }: ApplyNodeProps) => {
|
|||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { accesses } = useAccessesStore(useZustandShallowSelector("accesses"));
|
|
||||||
const { addEmail } = useContactEmailsStore(useZustandShallowSelector(["addEmail"]));
|
const { addEmail } = useContactEmailsStore(useZustandShallowSelector(["addEmail"]));
|
||||||
const { updateNode } = useWorkflowStore(useZustandShallowSelector(["updateNode"]));
|
const { updateNode } = useWorkflowStore(useZustandShallowSelector(["updateNode"]));
|
||||||
|
|
||||||
@ -58,7 +57,6 @@ const ApplyNode = ({ node, disabled }: ApplyNodeProps) => {
|
|||||||
const newNode = produce(node, (draft) => {
|
const newNode = produce(node, (draft) => {
|
||||||
draft.config = {
|
draft.config = {
|
||||||
...newValues,
|
...newValues,
|
||||||
provider: accesses.find((e) => e.id === newValues.providerAccessId)?.provider,
|
|
||||||
};
|
};
|
||||||
draft.validated = true;
|
draft.validated = true;
|
||||||
});
|
});
|
||||||
|
@ -10,9 +10,11 @@ import ModalForm from "@/components/ModalForm";
|
|||||||
import MultipleInput from "@/components/MultipleInput";
|
import MultipleInput from "@/components/MultipleInput";
|
||||||
import AccessEditModal from "@/components/access/AccessEditModal";
|
import AccessEditModal from "@/components/access/AccessEditModal";
|
||||||
import AccessSelect from "@/components/access/AccessSelect";
|
import AccessSelect from "@/components/access/AccessSelect";
|
||||||
import { ACCESS_USAGES, accessProvidersMap } from "@/domain/provider";
|
import ApplyDNSProviderSelect from "@/components/provider/ApplyDNSProviderSelect";
|
||||||
|
import { ACCESS_USAGES, accessProvidersMap, applyDNSProvidersMap } from "@/domain/provider";
|
||||||
import { type WorkflowNodeConfigForApply } from "@/domain/workflow";
|
import { type WorkflowNodeConfigForApply } from "@/domain/workflow";
|
||||||
import { useAntdForm } from "@/hooks";
|
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
||||||
|
import { useAccessesStore } from "@/stores/access";
|
||||||
import { useContactEmailsStore } from "@/stores/contact";
|
import { useContactEmailsStore } from "@/stores/contact";
|
||||||
import { validDomainName, validIPv4Address, validIPv6Address } from "@/utils/validators";
|
import { validDomainName, validIPv4Address, validIPv6Address } from "@/utils/validators";
|
||||||
|
|
||||||
@ -46,6 +48,8 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
|||||||
({ className, style, disabled, initialValues, onValuesChange }, ref) => {
|
({ className, style, disabled, initialValues, onValuesChange }, ref) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const { accesses } = useAccessesStore(useZustandShallowSelector("accesses"));
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
domains: z.string({ message: t("workflow_node.apply.form.domains.placeholder") }).refine((v) => {
|
domains: z.string({ message: t("workflow_node.apply.form.domains.placeholder") }).refine((v) => {
|
||||||
return String(v)
|
return String(v)
|
||||||
@ -53,6 +57,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
|||||||
.every((e) => validDomainName(e, { allowWildcard: true }));
|
.every((e) => validDomainName(e, { allowWildcard: true }));
|
||||||
}, t("common.errmsg.domain_invalid")),
|
}, t("common.errmsg.domain_invalid")),
|
||||||
contactEmail: z.string({ message: t("workflow_node.apply.form.contact_email.placeholder") }).email(t("common.errmsg.email_invalid")),
|
contactEmail: z.string({ message: t("workflow_node.apply.form.contact_email.placeholder") }).email(t("common.errmsg.email_invalid")),
|
||||||
|
provider: z.string({ message: t("workflow_node.apply.form.provider.placeholder") }).nonempty(t("workflow_node.apply.form.provider.placeholder")),
|
||||||
providerAccessId: z
|
providerAccessId: z
|
||||||
.string({ message: t("workflow_node.apply.form.provider_access.placeholder") })
|
.string({ message: t("workflow_node.apply.form.provider_access.placeholder") })
|
||||||
.min(1, t("workflow_node.apply.form.provider_access.placeholder")),
|
.min(1, t("workflow_node.apply.form.provider_access.placeholder")),
|
||||||
@ -82,9 +87,34 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
|||||||
initialValues: initialValues ?? initFormModel(),
|
initialValues: initialValues ?? initFormModel(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const fieldProvider = Form.useWatch<string>("provider", { form: formInst, preserve: true });
|
||||||
|
const fieldProviderAccessId = Form.useWatch<string>("providerAccessId", formInst);
|
||||||
const fieldDomains = Form.useWatch<string>("domains", formInst);
|
const fieldDomains = Form.useWatch<string>("domains", formInst);
|
||||||
const fieldNameservers = Form.useWatch<string>("nameservers", formInst);
|
const fieldNameservers = Form.useWatch<string>("nameservers", formInst);
|
||||||
|
|
||||||
|
const handleProviderSelect = (value: string) => {
|
||||||
|
if (fieldProvider === value) return;
|
||||||
|
|
||||||
|
if (initialValues?.provider === value) {
|
||||||
|
formInst.setFieldValue("providerAccessId", initialValues?.providerAccessId);
|
||||||
|
onValuesChange?.(formInst.getFieldsValue(true));
|
||||||
|
} else {
|
||||||
|
if (applyDNSProvidersMap.get(fieldProvider)?.provider !== applyDNSProvidersMap.get(value)?.provider) {
|
||||||
|
formInst.setFieldValue("providerAccessId", undefined);
|
||||||
|
onValuesChange?.(formInst.getFieldsValue(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleProviderAccessSelect = (value: string) => {
|
||||||
|
if (fieldProviderAccessId === value) return;
|
||||||
|
|
||||||
|
// DNS 提供商和授权提供商目前一一对应,因此切换授权时,自动切换到相应提供商
|
||||||
|
const access = accesses.find((access) => access.id === value);
|
||||||
|
formInst.setFieldValue("provider", Array.from(applyDNSProvidersMap.values()).find((provider) => provider.provider === access?.provider)?.type);
|
||||||
|
onValuesChange?.(formInst.getFieldsValue(true));
|
||||||
|
};
|
||||||
|
|
||||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||||
onValuesChange?.(values as ApplyNodeConfigFormFieldValues);
|
onValuesChange?.(values as ApplyNodeConfigFormFieldValues);
|
||||||
};
|
};
|
||||||
@ -136,6 +166,16 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
|||||||
<EmailInput placeholder={t("workflow_node.apply.form.contact_email.placeholder")} />
|
<EmailInput placeholder={t("workflow_node.apply.form.contact_email.placeholder")} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="provider" label={t("workflow_node.apply.form.provider.label")} hidden rules={[formRule]}>
|
||||||
|
<ApplyDNSProviderSelect
|
||||||
|
allowClear
|
||||||
|
disabled
|
||||||
|
placeholder={t("workflow_node.apply.form.provider.placeholder")}
|
||||||
|
showSearch
|
||||||
|
onSelect={handleProviderSelect}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item className="mb-0">
|
<Form.Item className="mb-0">
|
||||||
<label className="mb-1 block">
|
<label className="mb-1 block">
|
||||||
<div className="flex w-full items-center justify-between gap-4">
|
<div className="flex w-full items-center justify-between gap-4">
|
||||||
@ -173,6 +213,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
|||||||
const provider = accessProvidersMap.get(record.provider);
|
const provider = accessProvidersMap.get(record.provider);
|
||||||
return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage;
|
return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage;
|
||||||
}}
|
}}
|
||||||
|
onChange={handleProviderAccessSelect}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -216,7 +216,10 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
|||||||
return (
|
return (
|
||||||
<Form.Provider onFormChange={handleFormProviderChange}>
|
<Form.Provider onFormChange={handleFormProviderChange}>
|
||||||
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||||
<Show when={!!fieldProvider} fallback={<DeployProviderPicker onSelect={handleProviderPick} />}>
|
<Show
|
||||||
|
when={!!fieldProvider}
|
||||||
|
fallback={<DeployProviderPicker placeholder={t("workflow_node.deploy.search.provider.placeholder")} onSelect={handleProviderPick} />}
|
||||||
|
>
|
||||||
<Form.Item name="provider" label={t("workflow_node.deploy.form.provider.label")} rules={[formRule]}>
|
<Form.Item name="provider" label={t("workflow_node.deploy.form.provider.label")} rules={[formRule]}>
|
||||||
<DeployProviderSelect
|
<DeployProviderSelect
|
||||||
allowClear
|
allowClear
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// #region AccessProvider
|
||||||
/*
|
/*
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
@ -47,25 +48,25 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
|||||||
NOTICE: The following order determines the order displayed at the frontend.
|
NOTICE: The following order determines the order displayed at the frontend.
|
||||||
*/
|
*/
|
||||||
[
|
[
|
||||||
[ACCESS_PROVIDERS.LOCAL, "common.provider.local", "/imgs/providers/local.svg", "deploy"],
|
[ACCESS_PROVIDERS.LOCAL, "common.provider.local", "/imgs/providers/local.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.SSH, "common.provider.ssh", "/imgs/providers/ssh.svg", "deploy"],
|
[ACCESS_PROVIDERS.SSH, "common.provider.ssh", "/imgs/providers/ssh.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.WEBHOOK, "common.provider.webhook", "/imgs/providers/webhook.svg", "deploy"],
|
[ACCESS_PROVIDERS.WEBHOOK, "common.provider.webhook", "/imgs/providers/webhook.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.KUBERNETES, "common.provider.kubernetes", "/imgs/providers/kubernetes.svg", "deploy"],
|
[ACCESS_PROVIDERS.KUBERNETES, "common.provider.kubernetes", "/imgs/providers/kubernetes.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.ALIYUN, "common.provider.aliyun", "/imgs/providers/aliyun.svg", "all"],
|
[ACCESS_PROVIDERS.ALIYUN, "common.provider.aliyun", "/imgs/providers/aliyun.svg", ACCESS_USAGES.ALL],
|
||||||
[ACCESS_PROVIDERS.TENCENTCLOUD, "common.provider.tencentcloud", "/imgs/providers/tencentcloud.svg", "all"],
|
[ACCESS_PROVIDERS.TENCENTCLOUD, "common.provider.tencentcloud", "/imgs/providers/tencentcloud.svg", ACCESS_USAGES.ALL],
|
||||||
[ACCESS_PROVIDERS.HUAWEICLOUD, "common.provider.huaweicloud", "/imgs/providers/huaweicloud.svg", "all"],
|
[ACCESS_PROVIDERS.HUAWEICLOUD, "common.provider.huaweicloud", "/imgs/providers/huaweicloud.svg", ACCESS_USAGES.ALL],
|
||||||
[ACCESS_PROVIDERS.BAIDUCLOUD, "common.provider.baiducloud", "/imgs/providers/baiducloud.svg", "all"],
|
[ACCESS_PROVIDERS.BAIDUCLOUD, "common.provider.baiducloud", "/imgs/providers/baiducloud.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.QINIU, "common.provider.qiniu", "/imgs/providers/qiniu.svg", "deploy"],
|
[ACCESS_PROVIDERS.QINIU, "common.provider.qiniu", "/imgs/providers/qiniu.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.DOGECLOUD, "common.provider.dogecloud", "/imgs/providers/dogecloud.svg", "deploy"],
|
[ACCESS_PROVIDERS.DOGECLOUD, "common.provider.dogecloud", "/imgs/providers/dogecloud.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.VOLCENGINE, "common.provider.volcengine", "/imgs/providers/volcengine.svg", "all"],
|
[ACCESS_PROVIDERS.VOLCENGINE, "common.provider.volcengine", "/imgs/providers/volcengine.svg", ACCESS_USAGES.ALL],
|
||||||
[ACCESS_PROVIDERS.BYTEPLUS, "common.provider.byteplus", "/imgs/providers/byteplus.svg", "all"],
|
[ACCESS_PROVIDERS.BYTEPLUS, "common.provider.byteplus", "/imgs/providers/byteplus.svg", ACCESS_USAGES.DEPLOY],
|
||||||
[ACCESS_PROVIDERS.AWS, "common.provider.aws", "/imgs/providers/aws.svg", "apply"],
|
[ACCESS_PROVIDERS.AWS, "common.provider.aws", "/imgs/providers/aws.svg", ACCESS_USAGES.APPLY],
|
||||||
[ACCESS_PROVIDERS.CLOUDFLARE, "common.provider.cloudflare", "/imgs/providers/cloudflare.svg", "apply"],
|
[ACCESS_PROVIDERS.CLOUDFLARE, "common.provider.cloudflare", "/imgs/providers/cloudflare.svg", ACCESS_USAGES.APPLY],
|
||||||
[ACCESS_PROVIDERS.NAMEDOTCOM, "common.provider.namedotcom", "/imgs/providers/namedotcom.svg", "apply"],
|
[ACCESS_PROVIDERS.NAMEDOTCOM, "common.provider.namedotcom", "/imgs/providers/namedotcom.svg", ACCESS_USAGES.APPLY],
|
||||||
[ACCESS_PROVIDERS.NAMESILO, "common.provider.namesilo", "/imgs/providers/namesilo.svg", "apply"],
|
[ACCESS_PROVIDERS.NAMESILO, "common.provider.namesilo", "/imgs/providers/namesilo.svg", ACCESS_USAGES.APPLY],
|
||||||
[ACCESS_PROVIDERS.GODADDY, "common.provider.godaddy", "/imgs/providers/godaddy.svg", "apply"],
|
[ACCESS_PROVIDERS.GODADDY, "common.provider.godaddy", "/imgs/providers/godaddy.svg", ACCESS_USAGES.APPLY],
|
||||||
[ACCESS_PROVIDERS.POWERDNS, "common.provider.powerdns", "/imgs/providers/powerdns.svg", "apply"],
|
[ACCESS_PROVIDERS.POWERDNS, "common.provider.powerdns", "/imgs/providers/powerdns.svg", ACCESS_USAGES.APPLY],
|
||||||
[ACCESS_PROVIDERS.ACMEHTTPREQ, "common.provider.acmehttpreq", "/imgs/providers/acmehttpreq.svg", "apply"],
|
[ACCESS_PROVIDERS.ACMEHTTPREQ, "common.provider.acmehttpreq", "/imgs/providers/acmehttpreq.svg", ACCESS_USAGES.APPLY],
|
||||||
].map(([type, name, icon, usage]) => [
|
].map(([type, name, icon, usage]) => [
|
||||||
type,
|
type,
|
||||||
{
|
{
|
||||||
@ -76,7 +77,66 @@ export const accessProvidersMap: Map<AccessProvider["type"] | string, AccessProv
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region DNSProvider
|
||||||
|
/*
|
||||||
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
|
*/
|
||||||
|
export const APPLY_DNS_PROVIDERS = Object.freeze({
|
||||||
|
ACMEHTTPREQ: `${ACCESS_PROVIDERS.ACMEHTTPREQ}`,
|
||||||
|
ALIYUN_DNS: `${ACCESS_PROVIDERS.ALIYUN}-dns`,
|
||||||
|
AWS_ROUTE53: `${ACCESS_PROVIDERS.AWS}-route53`,
|
||||||
|
CLOUDFLARE: `${ACCESS_PROVIDERS.CLOUDFLARE}`,
|
||||||
|
GODADDY: `${ACCESS_PROVIDERS.GODADDY}`,
|
||||||
|
HUAWEICLOUD_DNS: `${ACCESS_PROVIDERS.HUAWEICLOUD}-dns`,
|
||||||
|
NAMEDOTCOM: `${ACCESS_PROVIDERS.NAMEDOTCOM}`,
|
||||||
|
NAMESILO: `${ACCESS_PROVIDERS.NAMESILO}`,
|
||||||
|
POWERDNS: `${ACCESS_PROVIDERS.POWERDNS}`,
|
||||||
|
TENCENTCLOUD_DNS: `${ACCESS_PROVIDERS.TENCENTCLOUD}-dns`,
|
||||||
|
VOLCENGINE_DNS: `${ACCESS_PROVIDERS.VOLCENGINE}-dns`,
|
||||||
|
} as const);
|
||||||
|
|
||||||
|
export type ApplyDNSProviderType = (typeof APPLY_DNS_PROVIDERS)[keyof typeof APPLY_DNS_PROVIDERS];
|
||||||
|
|
||||||
|
export type ApplyDNSProvider = {
|
||||||
|
type: ApplyDNSProviderType;
|
||||||
|
name: string;
|
||||||
|
icon: string;
|
||||||
|
provider: AccessProviderType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const applyDNSProvidersMap: Map<ApplyDNSProvider["type"] | string, ApplyDNSProvider> = new Map(
|
||||||
|
/*
|
||||||
|
注意:此处的顺序决定显示在前端的顺序。
|
||||||
|
NOTICE: The following order determines the order displayed at the frontend.
|
||||||
|
*/
|
||||||
|
[
|
||||||
|
[APPLY_DNS_PROVIDERS.ALIYUN_DNS, "common.provider.aliyun.dns"],
|
||||||
|
[APPLY_DNS_PROVIDERS.TENCENTCLOUD_DNS, "common.provider.tencentcloud.dns"],
|
||||||
|
[APPLY_DNS_PROVIDERS.HUAWEICLOUD_DNS, "common.provider.huaweicloud.dns"],
|
||||||
|
[APPLY_DNS_PROVIDERS.VOLCENGINE_DNS, "common.provider.volcengine.dns"],
|
||||||
|
[APPLY_DNS_PROVIDERS.AWS_ROUTE53, "common.provider.aws.route53"],
|
||||||
|
[APPLY_DNS_PROVIDERS.CLOUDFLARE, "common.provider.cloudflare"],
|
||||||
|
[APPLY_DNS_PROVIDERS.GODADDY, "common.provider.godaddy"],
|
||||||
|
[APPLY_DNS_PROVIDERS.NAMEDOTCOM, "common.provider.namedotcom"],
|
||||||
|
[APPLY_DNS_PROVIDERS.NAMESILO, "common.provider.namesilo"],
|
||||||
|
[APPLY_DNS_PROVIDERS.POWERDNS, "common.provider.powerdns"],
|
||||||
|
[APPLY_DNS_PROVIDERS.ACMEHTTPREQ, "common.provider.acmehttpreq"],
|
||||||
|
].map(([type, name]) => [
|
||||||
|
type,
|
||||||
|
{
|
||||||
|
type: type as ApplyDNSProviderType,
|
||||||
|
name: name,
|
||||||
|
icon: accessProvidersMap.get(type.split("-")[0])!.icon,
|
||||||
|
provider: type.split("-")[0] as AccessProviderType,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region DeployProvider
|
||||||
/*
|
/*
|
||||||
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
注意:如果追加新的常量值,请保持以 ASCII 排序。
|
||||||
NOTICE: If you add new constant, please keep ASCII order.
|
NOTICE: If you add new constant, please keep ASCII order.
|
||||||
@ -155,3 +215,4 @@ export const deployProvidersMap: Map<DeployProvider["type"] | string, DeployProv
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
// #endregion
|
||||||
|
@ -41,9 +41,11 @@
|
|||||||
"common.provider.aliyun.cdn": "Alibaba Cloud - CDN",
|
"common.provider.aliyun.cdn": "Alibaba Cloud - CDN",
|
||||||
"common.provider.aliyun.clb": "Alibaba Cloud - CLB",
|
"common.provider.aliyun.clb": "Alibaba Cloud - CLB",
|
||||||
"common.provider.aliyun.dcdn": "Alibaba Cloud - DCDN",
|
"common.provider.aliyun.dcdn": "Alibaba Cloud - DCDN",
|
||||||
|
"common.provider.aliyun.dns": "Alibaba Cloud - DNS",
|
||||||
"common.provider.aliyun.nlb": "Alibaba Cloud - NLB",
|
"common.provider.aliyun.nlb": "Alibaba Cloud - NLB",
|
||||||
"common.provider.aliyun.oss": "Alibaba Cloud - OSS",
|
"common.provider.aliyun.oss": "Alibaba Cloud - OSS",
|
||||||
"common.provider.aws": "AWS",
|
"common.provider.aws": "AWS",
|
||||||
|
"common.provider.aws.route53": "AWS - Route53",
|
||||||
"common.provider.baiducloud": "Baidu Cloud",
|
"common.provider.baiducloud": "Baidu Cloud",
|
||||||
"common.provider.baiducloud.cdn": "Baidu Cloud - CDN",
|
"common.provider.baiducloud.cdn": "Baidu Cloud - CDN",
|
||||||
"common.provider.byteplus": "BytePlus",
|
"common.provider.byteplus": "BytePlus",
|
||||||
@ -54,6 +56,7 @@
|
|||||||
"common.provider.godaddy": "GoDaddy",
|
"common.provider.godaddy": "GoDaddy",
|
||||||
"common.provider.huaweicloud": "Huawei Cloud",
|
"common.provider.huaweicloud": "Huawei Cloud",
|
||||||
"common.provider.huaweicloud.cdn": "Huawei Cloud - CDN",
|
"common.provider.huaweicloud.cdn": "Huawei Cloud - CDN",
|
||||||
|
"common.provider.huaweicloud.dns": "Huawei Cloud - DNS",
|
||||||
"common.provider.huaweicloud.elb": "Huawei Cloud - ELB",
|
"common.provider.huaweicloud.elb": "Huawei Cloud - ELB",
|
||||||
"common.provider.kubernetes": "Kubernetes",
|
"common.provider.kubernetes": "Kubernetes",
|
||||||
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
||||||
@ -68,10 +71,12 @@
|
|||||||
"common.provider.tencentcloud.cdn": "Tencent Cloud - CDN",
|
"common.provider.tencentcloud.cdn": "Tencent Cloud - CDN",
|
||||||
"common.provider.tencentcloud.clb": "Tencent Cloud - CLB",
|
"common.provider.tencentcloud.clb": "Tencent Cloud - CLB",
|
||||||
"common.provider.tencentcloud.cos": "Tencent Cloud - COS",
|
"common.provider.tencentcloud.cos": "Tencent Cloud - COS",
|
||||||
|
"common.provider.tencentcloud.dns": "Tencent Cloud - DNS",
|
||||||
"common.provider.tencentcloud.ecdn": "Tencent Cloud - ECDN",
|
"common.provider.tencentcloud.ecdn": "Tencent Cloud - ECDN",
|
||||||
"common.provider.tencentcloud.eo": "Tencent Cloud - EdgeOne",
|
"common.provider.tencentcloud.eo": "Tencent Cloud - EdgeOne",
|
||||||
"common.provider.volcengine": "Volcengine",
|
"common.provider.volcengine": "Volcengine",
|
||||||
"common.provider.volcengine.cdn": "Volcengine - CDN",
|
"common.provider.volcengine.cdn": "Volcengine - CDN",
|
||||||
|
"common.provider.volcengine.dns": "Volcengine - DNS",
|
||||||
"common.provider.volcengine.live": "Volcengine - Live",
|
"common.provider.volcengine.live": "Volcengine - Live",
|
||||||
"common.provider.webhook": "Webhook",
|
"common.provider.webhook": "Webhook",
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
"workflow_node.apply.form.contact_email.label": "Contact email",
|
"workflow_node.apply.form.contact_email.label": "Contact email",
|
||||||
"workflow_node.apply.form.contact_email.placeholder": "Please enter contact email",
|
"workflow_node.apply.form.contact_email.placeholder": "Please enter contact email",
|
||||||
"workflow_node.apply.form.contact_email.tooltip": "Contact information required for SSL certificate application. Please pay attention to the <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">rate limits</a>.",
|
"workflow_node.apply.form.contact_email.tooltip": "Contact information required for SSL certificate application. Please pay attention to the <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">rate limits</a>.",
|
||||||
|
"workflow_node.apply.form.provider.label": "DNS provider",
|
||||||
|
"workflow_node.apply.form.provider.placeholder": "Please select DNS provider of the domains",
|
||||||
"workflow_node.apply.form.provider_access.label": "DNS provider authorization",
|
"workflow_node.apply.form.provider_access.label": "DNS provider authorization",
|
||||||
"workflow_node.apply.form.provider_access.placeholder": "Please select an authorization of DNS provider",
|
"workflow_node.apply.form.provider_access.placeholder": "Please select an authorization of DNS provider",
|
||||||
"workflow_node.apply.form.provider_access.tooltip": "Used to manage DNS records during ACME DNS-01 authentication.",
|
"workflow_node.apply.form.provider_access.tooltip": "Used to manage DNS records during ACME DNS-01 authentication.",
|
||||||
|
@ -41,9 +41,11 @@
|
|||||||
"common.provider.aliyun.cdn": "阿里云 - 内容分发网络 CDN",
|
"common.provider.aliyun.cdn": "阿里云 - 内容分发网络 CDN",
|
||||||
"common.provider.aliyun.clb": "阿里云 - 传统型负载均衡 CLB",
|
"common.provider.aliyun.clb": "阿里云 - 传统型负载均衡 CLB",
|
||||||
"common.provider.aliyun.dcdn": "阿里云 - 全站加速 DCDN",
|
"common.provider.aliyun.dcdn": "阿里云 - 全站加速 DCDN",
|
||||||
|
"common.provider.aliyun.dns": "阿里云 - 云解析 DNS",
|
||||||
"common.provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB",
|
"common.provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB",
|
||||||
"common.provider.aliyun.oss": "阿里云 - 对象存储 OSS",
|
"common.provider.aliyun.oss": "阿里云 - 对象存储 OSS",
|
||||||
"common.provider.aws": "AWS",
|
"common.provider.aws": "AWS",
|
||||||
|
"common.provider.aws.route53": "AWS - Route53",
|
||||||
"common.provider.baiducloud": "百度智能云",
|
"common.provider.baiducloud": "百度智能云",
|
||||||
"common.provider.baiducloud.cdn": "百度智能云 - 内容分发网络 CDN",
|
"common.provider.baiducloud.cdn": "百度智能云 - 内容分发网络 CDN",
|
||||||
"common.provider.byteplus": "BytePlus",
|
"common.provider.byteplus": "BytePlus",
|
||||||
@ -54,6 +56,7 @@
|
|||||||
"common.provider.godaddy": "GoDaddy",
|
"common.provider.godaddy": "GoDaddy",
|
||||||
"common.provider.huaweicloud": "华为云",
|
"common.provider.huaweicloud": "华为云",
|
||||||
"common.provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN",
|
"common.provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN",
|
||||||
|
"common.provider.huaweicloud.dns": "华为云 - 云解析 DNS",
|
||||||
"common.provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB",
|
"common.provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB",
|
||||||
"common.provider.kubernetes": "Kubernetes",
|
"common.provider.kubernetes": "Kubernetes",
|
||||||
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
||||||
@ -68,10 +71,12 @@
|
|||||||
"common.provider.tencentcloud.cdn": "腾讯云 - 内容分发网络 CDN",
|
"common.provider.tencentcloud.cdn": "腾讯云 - 内容分发网络 CDN",
|
||||||
"common.provider.tencentcloud.clb": "腾讯云 - 负载均衡 CLB",
|
"common.provider.tencentcloud.clb": "腾讯云 - 负载均衡 CLB",
|
||||||
"common.provider.tencentcloud.cos": "腾讯云 - 对象存储 COS",
|
"common.provider.tencentcloud.cos": "腾讯云 - 对象存储 COS",
|
||||||
|
"common.provider.tencentcloud.dns": "腾讯云 - 云解析 DNS",
|
||||||
"common.provider.tencentcloud.ecdn": "腾讯云 - 全站加速网络 ECDN",
|
"common.provider.tencentcloud.ecdn": "腾讯云 - 全站加速网络 ECDN",
|
||||||
"common.provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne",
|
"common.provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne",
|
||||||
"common.provider.volcengine": "火山引擎",
|
"common.provider.volcengine": "火山引擎",
|
||||||
"common.provider.volcengine.cdn": "火山引擎 - 内容分发网络 CDN",
|
"common.provider.volcengine.cdn": "火山引擎 - 内容分发网络 CDN",
|
||||||
|
"common.provider.volcengine.dns": "火山引擎 - 云解析 DNS",
|
||||||
"common.provider.volcengine.live": "火山引擎 - 视频直播 Live",
|
"common.provider.volcengine.live": "火山引擎 - 视频直播 Live",
|
||||||
"common.provider.webhook": "Webhook",
|
"common.provider.webhook": "Webhook",
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
"workflow_node.apply.form.contact_email.label": "联系邮箱",
|
"workflow_node.apply.form.contact_email.label": "联系邮箱",
|
||||||
"workflow_node.apply.form.contact_email.placeholder": "请输入联系邮箱",
|
"workflow_node.apply.form.contact_email.placeholder": "请输入联系邮箱",
|
||||||
"workflow_node.apply.form.contact_email.tooltip": "申请签发 SSL 证书时所需的联系方式。请注意 Let's Encrypt 账户注册的速率限制。<br><a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">点此了解更多</a>。",
|
"workflow_node.apply.form.contact_email.tooltip": "申请签发 SSL 证书时所需的联系方式。请注意 Let's Encrypt 账户注册的速率限制。<br><a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">点此了解更多</a>。",
|
||||||
|
"workflow_node.apply.form.provider.label": "DNS 提供商",
|
||||||
|
"workflow_node.apply.form.provider.placeholder": "请选择 DNS 提供商",
|
||||||
"workflow_node.apply.form.provider_access.label": "DNS 提供商授权",
|
"workflow_node.apply.form.provider_access.label": "DNS 提供商授权",
|
||||||
"workflow_node.apply.form.provider_access.placeholder": "请选择 DNS 提供商授权",
|
"workflow_node.apply.form.provider_access.placeholder": "请选择 DNS 提供商授权",
|
||||||
"workflow_node.apply.form.provider_access.tooltip": "用于 ACME DNS-01 认证时操作域名解析记录,注意与部署阶段所需的主机提供商相区分。",
|
"workflow_node.apply.form.provider_access.tooltip": "用于 ACME DNS-01 认证时操作域名解析记录,注意与部署阶段所需的主机提供商相区分。",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user