|
@ -6,6 +6,7 @@ import { |
|
|
checkDomainAtom, |
|
|
checkDomainAtom, |
|
|
applyTxtCertificateAtom, |
|
|
applyTxtCertificateAtom, |
|
|
Req_ApplyTxtCertificate, |
|
|
Req_ApplyTxtCertificate, |
|
|
|
|
|
getCertConfigAtom, |
|
|
} from "@/store/websites/cert.ts"; |
|
|
} from "@/store/websites/cert.ts"; |
|
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; |
|
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; |
|
|
import { Button, Flex, Form, Input, message, Radio, Select, Space, Steps, Table, Tooltip } from "antd"; |
|
|
import { Button, Flex, Form, Input, message, Radio, Select, Space, Steps, Table, Tooltip } from "antd"; |
|
@ -28,19 +29,60 @@ import { |
|
|
import { useQueryClient } from "@tanstack/react-query"; |
|
|
import { useQueryClient } from "@tanstack/react-query"; |
|
|
const i18nPrefix = "cert.apply"; |
|
|
const i18nPrefix = "cert.apply"; |
|
|
|
|
|
|
|
|
const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTxtCertificateData }) => { |
|
|
|
|
|
const { styles, cx } = useStyle(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const DomainsInput = (props: { domains; setDomains; currentDomainMod; setCurrentDomainMod; currentStep }) => { |
|
|
useEffect(() => { |
|
|
useEffect(() => { |
|
|
onChange(props.value); |
|
|
|
|
|
}, [props.value]); |
|
|
|
|
|
|
|
|
if (props.currentDomainMod === "single" && props.domains !== "") { |
|
|
|
|
|
props.setDomains(props.domains.replace(/[\r\n]/g, "")); |
|
|
|
|
|
} |
|
|
|
|
|
}, [props.currentDomainMod]); |
|
|
|
|
|
return ( |
|
|
|
|
|
<Space direction="vertical" style={{ width: "100%" }}> |
|
|
|
|
|
<Radio.Group |
|
|
|
|
|
style={{ marginBottom: 8 }} |
|
|
|
|
|
value={props.currentDomainMod} |
|
|
|
|
|
onChange={(e) => props.setCurrentDomainMod(e.target.value)} |
|
|
|
|
|
> |
|
|
|
|
|
<Radio.Button value="single" disabled={props.currentStep !== 0}> |
|
|
|
|
|
单证书申请 |
|
|
|
|
|
</Radio.Button> |
|
|
|
|
|
<Radio.Button value="multiple" disabled={props.currentStep !== 0}> |
|
|
|
|
|
多证书申请 |
|
|
|
|
|
</Radio.Button> |
|
|
|
|
|
</Radio.Group> |
|
|
|
|
|
{props.currentDomainMod === "single" && ( |
|
|
|
|
|
<Input |
|
|
|
|
|
disabled={props.currentStep !== 0} |
|
|
|
|
|
placeholder="请输入域名,支持泛解析域名。如果为多个域名注册到一个证书,域名之间用<逗号(英文输入)>分割。如:a.com,*.b.com" |
|
|
|
|
|
onChange={(e) => { |
|
|
|
|
|
props.setDomains(e.target.value); |
|
|
|
|
|
}} |
|
|
|
|
|
value={props.domains} // 设置输入框的值
|
|
|
|
|
|
/> |
|
|
|
|
|
)} |
|
|
|
|
|
{props.currentDomainMod === "multiple" && ( |
|
|
|
|
|
<Input.TextArea |
|
|
|
|
|
disabled={props.currentStep !== 0} |
|
|
|
|
|
rows={6} |
|
|
|
|
|
placeholder={`多个域名多个证书申请,用回车分隔。以下示例为6个域名申请3个证书,每行对应一个证书,支持泛解析域名;如:
|
|
|
|
|
|
*.a.baidu.com, *.baidu.com (两个域名一个证书) |
|
|
|
|
|
hello.alibaba.com,b.com,*.c.com (三个个域名一个证书) |
|
|
|
|
|
sss.ddd.com(单个域名一个证书)`}
|
|
|
|
|
|
onChange={(e) => { |
|
|
|
|
|
props.setDomains(e.target.value); |
|
|
|
|
|
}} |
|
|
|
|
|
value={props.domains} // 设置输入框的值
|
|
|
|
|
|
/> |
|
|
|
|
|
)} |
|
|
|
|
|
</Space> |
|
|
|
|
|
); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const BrandSelect = (props: { acme_type; setAcme_type }) => { |
|
|
|
|
|
const { styles, cx } = useStyle(); |
|
|
|
|
|
|
|
|
const onChange = useCallback((val: string) => { |
|
|
|
|
|
props.setApplyTxtCertificateData((prevState) => ({ |
|
|
|
|
|
...prevState, |
|
|
|
|
|
acme_type: val, |
|
|
|
|
|
})); |
|
|
|
|
|
}, []); |
|
|
|
|
|
|
|
|
const onChange = (val: string) => { |
|
|
|
|
|
props.setAcme_type(val); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<> |
|
|
<> |
|
@ -49,7 +91,7 @@ const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTx |
|
|
vertical={true} |
|
|
vertical={true} |
|
|
onClick={() => onChange("Google")} |
|
|
onClick={() => onChange("Google")} |
|
|
className={cx("band-normal", { |
|
|
className={cx("band-normal", { |
|
|
"band-active": props.applyTxtCertificateData.acme_type === "Google" || !props.value, |
|
|
|
|
|
|
|
|
"band-active": props.acme_type === "Google", |
|
|
})} |
|
|
})} |
|
|
> |
|
|
> |
|
|
<img src={google} style={{ height: "2rem" }} /> |
|
|
<img src={google} style={{ height: "2rem" }} /> |
|
@ -59,7 +101,7 @@ const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTx |
|
|
vertical={true} |
|
|
vertical={true} |
|
|
onClick={() => onChange("ZeroSSL")} |
|
|
onClick={() => onChange("ZeroSSL")} |
|
|
className={cx("band-normal", { |
|
|
className={cx("band-normal", { |
|
|
"band-active": props.applyTxtCertificateData.acme_type === "ZeroSSL", |
|
|
|
|
|
|
|
|
"band-active": props.acme_type === "ZeroSSL", |
|
|
})} |
|
|
})} |
|
|
> |
|
|
> |
|
|
<img src={zerossl} style={{ height: "2rem" }} /> |
|
|
<img src={zerossl} style={{ height: "2rem" }} /> |
|
@ -69,7 +111,7 @@ const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTx |
|
|
vertical={true} |
|
|
vertical={true} |
|
|
onClick={() => onChange("Let's Encrypt")} |
|
|
onClick={() => onChange("Let's Encrypt")} |
|
|
className={cx("band-normal", { |
|
|
className={cx("band-normal", { |
|
|
"band-active": props.applyTxtCertificateData.acme_type === "Let's Encrypt", |
|
|
|
|
|
|
|
|
"band-active": props.acme_type === "Let's Encrypt", |
|
|
})} |
|
|
})} |
|
|
> |
|
|
> |
|
|
<img src={lets_encrypt} style={{ height: "2rem" }} /> |
|
|
<img src={lets_encrypt} style={{ height: "2rem" }} /> |
|
@ -80,7 +122,7 @@ const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTx |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertificateData }) => { |
|
|
|
|
|
|
|
|
const StatusTable = (props: { value: string; setCurrentStep; setDns_list }) => { |
|
|
// const [data, setData] = useState<any>(null); // 临时状态来存储模拟数据
|
|
|
// const [data, setData] = useState<any>(null); // 临时状态来存储模拟数据
|
|
|
const [forceUpdate, setForceUpdate] = useState(0); |
|
|
const [forceUpdate, setForceUpdate] = useState(0); |
|
|
const { data, isFetching: isVerifyFetching } = useAtomValue( |
|
|
const { data, isFetching: isVerifyFetching } = useAtomValue( |
|
@ -249,7 +291,7 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific |
|
|
iconPosition={"end"} |
|
|
iconPosition={"end"} |
|
|
onClick={() => handleCopy(text)} |
|
|
onClick={() => handleCopy(text)} |
|
|
> |
|
|
> |
|
|
{t(`actions.clickCopy`)} |
|
|
|
|
|
|
|
|
{text} |
|
|
</Button> |
|
|
</Button> |
|
|
); |
|
|
); |
|
|
}, |
|
|
}, |
|
@ -262,10 +304,7 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific |
|
|
|
|
|
|
|
|
if ((data as any)?.check_ok === true) { |
|
|
if ((data as any)?.check_ok === true) { |
|
|
props.setCurrentStep(2); |
|
|
props.setCurrentStep(2); |
|
|
props.setApplyTxtCertificateData((prevState) => ({ |
|
|
|
|
|
...prevState, |
|
|
|
|
|
dns_list: (data as any).dns_list, |
|
|
|
|
|
})); |
|
|
|
|
|
|
|
|
props.setDns_list((data as any).dns_list); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -279,10 +318,7 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific |
|
|
// window.clearInterval(timerRef.current);
|
|
|
// window.clearInterval(timerRef.current);
|
|
|
if ((data as any)?.check_ok === true) { |
|
|
if ((data as any)?.check_ok === true) { |
|
|
props.setCurrentStep(2); |
|
|
props.setCurrentStep(2); |
|
|
props.setApplyTxtCertificateData((prevState) => ({ |
|
|
|
|
|
...prevState, |
|
|
|
|
|
dns_list: (data as any).dns_list, |
|
|
|
|
|
})); |
|
|
|
|
|
|
|
|
props.setDns_list((data as any).dns_list); |
|
|
window.clearInterval(timerRef.current); |
|
|
window.clearInterval(timerRef.current); |
|
|
} else { |
|
|
} else { |
|
|
refetch(); |
|
|
refetch(); |
|
@ -316,48 +352,9 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const DomainsInput = (props: { setDomains; currentDomainMod; setCurrentDomainMod; currentStep }) => { |
|
|
|
|
|
return ( |
|
|
|
|
|
<Space direction="vertical" style={{ width: "100%" }}> |
|
|
|
|
|
<Radio.Group |
|
|
|
|
|
style={{ marginBottom: 8 }} |
|
|
|
|
|
value={props.currentDomainMod} |
|
|
|
|
|
onChange={(e) => props.setCurrentDomainMod(e.target.value)} |
|
|
|
|
|
> |
|
|
|
|
|
<Radio.Button value="single" disabled={props.currentStep !== 0}> |
|
|
|
|
|
单证书申请 |
|
|
|
|
|
</Radio.Button> |
|
|
|
|
|
<Radio.Button value="multiple" disabled={props.currentStep !== 0}> |
|
|
|
|
|
多证书申请 |
|
|
|
|
|
</Radio.Button> |
|
|
|
|
|
</Radio.Group> |
|
|
|
|
|
{props.currentDomainMod === "single" && ( |
|
|
|
|
|
<Input |
|
|
|
|
|
disabled={props.currentStep !== 0} |
|
|
|
|
|
placeholder="请输入域名,支持泛解析域名。如果为多个域名注册到一个证书,域名之间用<逗号(英文输入)>分割。如:a.com,*.b.com" |
|
|
|
|
|
onBlur={(e) => { |
|
|
|
|
|
props.setDomains(e.target.value); |
|
|
|
|
|
}} |
|
|
|
|
|
/> |
|
|
|
|
|
)} |
|
|
|
|
|
{props.currentDomainMod === "multiple" && ( |
|
|
|
|
|
<Input.TextArea |
|
|
|
|
|
disabled={props.currentStep !== 0} |
|
|
|
|
|
rows={6} |
|
|
|
|
|
placeholder={`多个域名多个证书申请,用回车分隔。以下示例为6个域名申请3个证书,每行对应一个证书,支持泛解析域名;如:
|
|
|
|
|
|
*.a.baidu.com, *.baidu.com (两个域名一个证书) |
|
|
|
|
|
hello.alibaba.com,b.com,*.c.com (三个个域名一个证书) |
|
|
|
|
|
sss.ddd.com(单个域名一个证书)`}
|
|
|
|
|
|
onBlur={(e) => { |
|
|
|
|
|
props.setDomains(e.target.value); |
|
|
|
|
|
}} |
|
|
|
|
|
/> |
|
|
|
|
|
)} |
|
|
|
|
|
</Space> |
|
|
|
|
|
); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const domainsAtom = atomWithStorage<string>("domains", ""); |
|
|
|
|
|
|
|
|
const domainsAtom = atomWithStorage<string>("cert_domains", ""); |
|
|
|
|
|
// 打印初始值
|
|
|
|
|
|
console.log("初始文本值:", localStorage.getItem("cert_domains") || ""); |
|
|
|
|
|
|
|
|
const Apply = () => { |
|
|
const Apply = () => { |
|
|
const { styles } = useStyle(); |
|
|
const { styles } = useStyle(); |
|
@ -367,33 +364,36 @@ const Apply = () => { |
|
|
isPending: applyTxtCertificatePending, |
|
|
isPending: applyTxtCertificatePending, |
|
|
isSuccess: applyTxtCertificateIsSuccess, |
|
|
isSuccess: applyTxtCertificateIsSuccess, |
|
|
} = useAtomValue(applyTxtCertificateAtom); |
|
|
} = useAtomValue(applyTxtCertificateAtom); |
|
|
|
|
|
|
|
|
const [domains, setDomains] = useAtom(domainsAtom); |
|
|
const [domains, setDomains] = useAtom(domainsAtom); |
|
|
const [currentStep, setCurrentStep] = useState(0); |
|
|
const [currentStep, setCurrentStep] = useState(0); |
|
|
const [currentDomainMod, setCurrentDomainMod] = useState<"single" | "multiple">("single"); |
|
|
const [currentDomainMod, setCurrentDomainMod] = useState<"single" | "multiple">("single"); |
|
|
|
|
|
const [dns_list, setDns_list] = useState<ICertificate[]>([]); |
|
|
|
|
|
const [acme_type, setAcme_type] = useState<string>("Google"); |
|
|
|
|
|
const [key_rsa, setKey_rsa] = useState<string>(""); |
|
|
|
|
|
|
|
|
|
|
|
const { data: configData } = useAtomValue(useMemo(() => getCertConfigAtom(), [])); |
|
|
|
|
|
|
|
|
const [applyTxtCertificateData, setApplyTxtCertificateData] = useState<Req_ApplyTxtCertificate>({ |
|
|
|
|
|
is_sync: true, |
|
|
|
|
|
acme_type: "", |
|
|
|
|
|
key_rsa: "", |
|
|
|
|
|
dns_list: [], |
|
|
|
|
|
}); |
|
|
|
|
|
const handleAlgorithmChange = (value: string) => { |
|
|
const handleAlgorithmChange = (value: string) => { |
|
|
setApplyTxtCertificateData((prevState) => ({ |
|
|
|
|
|
...prevState, |
|
|
|
|
|
key_rsa: value, |
|
|
|
|
|
})); |
|
|
|
|
|
|
|
|
setKey_rsa(value); |
|
|
}; |
|
|
}; |
|
|
const applyTxtCertificateClick = () => { |
|
|
const applyTxtCertificateClick = () => { |
|
|
applyTxtCertificateFun(applyTxtCertificateData); |
|
|
|
|
|
|
|
|
const data: Req_ApplyTxtCertificate = { |
|
|
|
|
|
is_sync: true, |
|
|
|
|
|
acme_type: acme_type, |
|
|
|
|
|
key_rsa: key_rsa, |
|
|
|
|
|
dns_list: dns_list, |
|
|
|
|
|
remark: form.getFieldValue("remark"), |
|
|
|
|
|
}; |
|
|
|
|
|
applyTxtCertificateFun(data); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
useEffect(() => { |
|
|
if (domains) { |
|
|
|
|
|
form.setFieldsValue({ |
|
|
|
|
|
domains, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
}, [domains]); |
|
|
|
|
|
|
|
|
form.setFieldsValue({ domains: domains }); |
|
|
|
|
|
form.setFieldsValue({ brand: acme_type }); |
|
|
|
|
|
form.setFieldsValue({ algorithm: key_rsa }); |
|
|
|
|
|
}, [domains, acme_type, key_rsa, form]); |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<ListPageLayout |
|
|
<ListPageLayout |
|
|
childrenClassName={styles.applyContent} |
|
|
childrenClassName={styles.applyContent} |
|
@ -453,9 +453,10 @@ const Apply = () => { |
|
|
rules={[{ required: true, message: t(`${i18nPrefix}.columns.domains.required`, "请输入域名") }]} |
|
|
rules={[{ required: true, message: t(`${i18nPrefix}.columns.domains.required`, "请输入域名") }]} |
|
|
> |
|
|
> |
|
|
<DomainsInput |
|
|
<DomainsInput |
|
|
|
|
|
domains={domains} |
|
|
|
|
|
setDomains={setDomains} |
|
|
currentDomainMod={currentDomainMod} |
|
|
currentDomainMod={currentDomainMod} |
|
|
setCurrentDomainMod={setCurrentDomainMod} |
|
|
setCurrentDomainMod={setCurrentDomainMod} |
|
|
setDomains={setDomains} |
|
|
|
|
|
currentStep={currentStep} |
|
|
currentStep={currentStep} |
|
|
/> |
|
|
/> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
@ -465,11 +466,7 @@ const Apply = () => { |
|
|
label={t(`${i18nPrefix}.columns.type`, "域名验证")} |
|
|
label={t(`${i18nPrefix}.columns.type`, "域名验证")} |
|
|
rules={[{ required: true, message: t(`${i18nPrefix}.columns.type`, "域名验证没有通过") }]} |
|
|
rules={[{ required: true, message: t(`${i18nPrefix}.columns.type`, "域名验证没有通过") }]} |
|
|
> |
|
|
> |
|
|
<StatusTable |
|
|
|
|
|
value={domains} |
|
|
|
|
|
setCurrentStep={setCurrentStep} |
|
|
|
|
|
setApplyTxtCertificateData={setApplyTxtCertificateData} |
|
|
|
|
|
/> |
|
|
|
|
|
|
|
|
<StatusTable value={domains} setCurrentStep={setCurrentStep} setDns_list={setDns_list} /> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
|
|
|
|
|
|
<Form.Item |
|
|
<Form.Item |
|
@ -482,11 +479,7 @@ const Apply = () => { |
|
|
}, |
|
|
}, |
|
|
]} |
|
|
]} |
|
|
> |
|
|
> |
|
|
<BrandSelect |
|
|
|
|
|
value="Google" |
|
|
|
|
|
applyTxtCertificateData={applyTxtCertificateData} |
|
|
|
|
|
setApplyTxtCertificateData={setApplyTxtCertificateData} |
|
|
|
|
|
/> |
|
|
|
|
|
|
|
|
<BrandSelect acme_type={acme_type} setAcme_type={setAcme_type} /> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item |
|
|
<Form.Item |
|
|
name={"algorithm"} |
|
|
name={"algorithm"} |
|
@ -498,7 +491,7 @@ const Apply = () => { |
|
|
}, |
|
|
}, |
|
|
]} |
|
|
]} |
|
|
> |
|
|
> |
|
|
<Select style={{ width: 120 }} options={algorithmTypes} onChange={handleAlgorithmChange} /> |
|
|
|
|
|
|
|
|
<Select style={{ width: 120 }} options={(configData as any)?.key_rsa} onChange={handleAlgorithmChange} /> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item name={"remark"} label={t(`${i18nPrefix}.columns.remark`, "备注 ")}> |
|
|
<Form.Item name={"remark"} label={t(`${i18nPrefix}.columns.remark`, "备注 ")}> |
|
|
<Input style={{ width: 400 }} /> |
|
|
<Input style={{ width: 400 }} /> |
|
|