|
@ -1,7 +1,12 @@ |
|
|
import { t } from '@/i18n.ts' |
|
|
import { t } from '@/i18n.ts' |
|
|
import { useAtomValue } from 'jotai' |
|
|
|
|
|
import { algorithmTypes, bandTypes, dnsConfigAtom, saveOrUpdateCertAtom, StatusText } from '@/store/websites/cert.ts' |
|
|
|
|
|
import { useCallback, useEffect, useMemo, useState } from 'react' |
|
|
|
|
|
|
|
|
import { useAtom, useAtomValue, useSetAtom } from 'jotai' |
|
|
|
|
|
import { |
|
|
|
|
|
algorithmTypes, |
|
|
|
|
|
dnsConfigAtom, |
|
|
|
|
|
dnsVerifyAtom, dnsVerifyOKAtom, |
|
|
|
|
|
saveOrUpdateCertAtom, |
|
|
|
|
|
} from '@/store/websites/cert.ts' |
|
|
|
|
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' |
|
|
import { |
|
|
import { |
|
|
Button, |
|
|
Button, |
|
|
Flex, |
|
|
Flex, |
|
@ -9,7 +14,7 @@ import { |
|
|
Input, |
|
|
Input, |
|
|
Select, |
|
|
Select, |
|
|
Space, |
|
|
Space, |
|
|
Table, Typography, |
|
|
|
|
|
|
|
|
Table, Tooltip, |
|
|
} from 'antd' |
|
|
} from 'antd' |
|
|
import google from '@/pages/websites/cert/assets/google.png' |
|
|
import google from '@/pages/websites/cert/assets/google.png' |
|
|
import zerossl from '@/pages/websites/cert/assets/zerossl.png' |
|
|
import zerossl from '@/pages/websites/cert/assets/zerossl.png' |
|
@ -17,6 +22,9 @@ import lets_encrypt from '@/pages/websites/cert/assets/lets_encrypt.png' |
|
|
import { useStyle } from './style' |
|
|
import { useStyle } from './style' |
|
|
import ListPageLayout from '@/layout/ListPageLayout.tsx' |
|
|
import ListPageLayout from '@/layout/ListPageLayout.tsx' |
|
|
import { ColumnsType } from 'antd/es/table' |
|
|
import { ColumnsType } from 'antd/es/table' |
|
|
|
|
|
import { atomWithStorage } from 'jotai/utils' |
|
|
|
|
|
import Copy from '@/components/copy' |
|
|
|
|
|
import { InfoCircleOutlined, LoadingOutlined } from '@ant-design/icons' |
|
|
|
|
|
|
|
|
const i18nPrefix = 'cert.apply' |
|
|
const i18nPrefix = 'cert.apply' |
|
|
|
|
|
|
|
@ -68,46 +76,117 @@ const StatusTable = (props: { value: string }) => { |
|
|
|
|
|
|
|
|
const { data, isFetching } = useAtomValue(useMemo(() => dnsConfigAtom(props.value), [ props.value ])) |
|
|
const { data, isFetching } = useAtomValue(useMemo(() => dnsConfigAtom(props.value), [ props.value ])) |
|
|
|
|
|
|
|
|
|
|
|
const { |
|
|
|
|
|
data: dnsVerifyStatus, |
|
|
|
|
|
isFetching: isVerifyFetching, |
|
|
|
|
|
refetch |
|
|
|
|
|
} = useAtomValue(useMemo(() => dnsVerifyAtom(props.value, isFetching), [ props.value, isFetching ])) |
|
|
|
|
|
|
|
|
|
|
|
const setDnsVerifyOK = useSetAtom(dnsVerifyOKAtom) |
|
|
|
|
|
|
|
|
|
|
|
const timerRef = useRef<number>() |
|
|
|
|
|
|
|
|
const columns = useMemo<ColumnsType>(() => { |
|
|
const columns = useMemo<ColumnsType>(() => { |
|
|
|
|
|
|
|
|
return [ |
|
|
return [ |
|
|
{ |
|
|
{ |
|
|
title: t(`${i18nPrefix}.status.columns.status`, '状态'), |
|
|
|
|
|
tooltip: t(`${i18nPrefix}.status.columns.statusTip`, '正确配置DNS解析后,域名验证会自动通过'), |
|
|
|
|
|
|
|
|
title: <>{t(`${i18nPrefix}.status.columns.status`, '状态')}<Tooltip |
|
|
|
|
|
title={t(`${i18nPrefix}.status.columns.statusTip`, '正确配置DNS解析后,域名验证会自动通过')}><InfoCircleOutlined |
|
|
|
|
|
style={{ paddingInlineStart: 5 }}/></Tooltip> </>, |
|
|
dataIndex: 'status', |
|
|
dataIndex: 'status', |
|
|
|
|
|
width: 100, |
|
|
|
|
|
render: (_, record) => { |
|
|
|
|
|
if (isFetching) { |
|
|
|
|
|
return <span>{t(`${i18nPrefix}.actions.dnsVerifyStatus.0`, '等待')}</span> |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (isVerifyFetching) { |
|
|
|
|
|
//0,等待 1,域名OK,2,域名分析错误,3:检测中 4:检测成功,匹配失败 5:检测失败,9:检测成功
|
|
|
|
|
|
return <span><LoadingOutlined |
|
|
|
|
|
style={{ paddingInlineEnd: 5 }}/>{t(`${i18nPrefix}.actions.dnsVerifyStatus.3`, '检测中')}</span> |
|
|
|
|
|
} |
|
|
|
|
|
const dns = record.dns_name |
|
|
|
|
|
const info = (dnsVerifyStatus as any)?.find((item) => item.dns_name === dns) as any |
|
|
|
|
|
if (info) { |
|
|
|
|
|
return <span>{t(`${i18nPrefix}.actions.dnsVerifyStatus.${info.status}`, `${info?.status_txt}`)}</span> |
|
|
|
|
|
} |
|
|
|
|
|
return <span>{t(`${i18nPrefix}.actions.dnsVerifyStatus.0`, '等待')}</span> |
|
|
|
|
|
}, |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
//服务商
|
|
|
//服务商
|
|
|
title: t(`${i18nPrefix}.status.columns.name_servers`, '服务商'), |
|
|
title: t(`${i18nPrefix}.status.columns.name_servers`, '服务商'), |
|
|
dataIndex: 'name_servers', |
|
|
dataIndex: 'name_servers', |
|
|
|
|
|
width: 150, |
|
|
|
|
|
render(text) { |
|
|
|
|
|
if (text) { |
|
|
|
|
|
return <span className={'color-green1'}>{text}</span> |
|
|
|
|
|
} |
|
|
|
|
|
return <span className={'color-yellow'}>未知</span> |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
//域名
|
|
|
//域名
|
|
|
title: t(`${i18nPrefix}.status.columns.domain`, '域名'), |
|
|
title: t(`${i18nPrefix}.status.columns.domain`, '域名'), |
|
|
dataIndex: 'domain', |
|
|
|
|
|
|
|
|
dataIndex: 'dns_name', |
|
|
|
|
|
width: 200, |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
//主机记录
|
|
|
//主机记录
|
|
|
title: t(`${i18nPrefix}.status.columns.record`, '主机记录'), |
|
|
title: t(`${i18nPrefix}.status.columns.record`, '主机记录'), |
|
|
dataIndex: 'record', |
|
|
|
|
|
|
|
|
dataIndex: 'host', |
|
|
|
|
|
width: 200, |
|
|
|
|
|
render: (text) => { |
|
|
|
|
|
return <Copy {...{ text: text, tooltips: t(`actions.clickCopy`) }} /> |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
//记录类型
|
|
|
//记录类型
|
|
|
title: t(`${i18nPrefix}.status.columns.record_type`, '记录类型'), |
|
|
title: t(`${i18nPrefix}.status.columns.record_type`, '记录类型'), |
|
|
dataIndex: 'record_type', |
|
|
|
|
|
|
|
|
dataIndex: 'type', |
|
|
|
|
|
width: 100, |
|
|
|
|
|
render: (text) => { |
|
|
|
|
|
return <span className={'color-red'}>{text}</span> |
|
|
|
|
|
} |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
//记录值
|
|
|
//记录值
|
|
|
title: t(`${i18nPrefix}.status.columns.record_value`, '记录值'), |
|
|
title: t(`${i18nPrefix}.status.columns.record_value`, '记录值'), |
|
|
dataIndex: 'record_value', |
|
|
dataIndex: 'record_value', |
|
|
|
|
|
width: 200, |
|
|
render: (text) => { |
|
|
render: (text) => { |
|
|
return <Typography.Text copyable={{ text: text }}>{text}</Typography.Text> |
|
|
|
|
|
|
|
|
return <Copy {...{ text: text, tooltips: t(`actions.clickCopy`) }} /> |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
] as ColumnsType |
|
|
] as ColumnsType |
|
|
|
|
|
|
|
|
}, []) |
|
|
|
|
|
|
|
|
}, [ isFetching, isVerifyFetching, dnsVerifyStatus ]) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
|
|
|
|
|
|
if ((dnsVerifyStatus as any)?.every((item) => item.status === 9)) { |
|
|
|
|
|
setDnsVerifyOK(true) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
timerRef.current = window.setInterval(() => { |
|
|
|
|
|
if (isVerifyFetching) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
//dnsVerifyStatus 如果所有status 为 9 则说明域名验证通过
|
|
|
|
|
|
if ((dnsVerifyStatus as any)?.every((item) => item.status === 9)) { |
|
|
|
|
|
setDnsVerifyOK(true) |
|
|
|
|
|
window.clearInterval(timerRef.current) |
|
|
|
|
|
} else { |
|
|
|
|
|
refetch() |
|
|
|
|
|
} |
|
|
|
|
|
}, 2000) |
|
|
|
|
|
|
|
|
|
|
|
return () => { |
|
|
|
|
|
window.clearInterval(timerRef.current) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
}, [ dnsVerifyStatus, isVerifyFetching ]) |
|
|
|
|
|
|
|
|
return <> |
|
|
return <> |
|
|
<div style={{ paddingBlock: 5, color: '#5a5a5a' }}> |
|
|
<div style={{ paddingBlock: 5, color: '#5a5a5a' }}> |
|
@ -124,11 +203,24 @@ const StatusTable = (props: { value: string }) => { |
|
|
</> |
|
|
</> |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
const Apply = (props: any) => { |
|
|
|
|
|
const { styles, cx } = useStyle() |
|
|
|
|
|
|
|
|
const domainsAtom = atomWithStorage<string>('domains', '') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const Apply = ( ) => { |
|
|
|
|
|
const { styles } = useStyle() |
|
|
const [ form ] = Form.useForm() |
|
|
const [ form ] = Form.useForm() |
|
|
const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateCertAtom) |
|
|
|
|
|
const [ domains, setDomains ] = useState<string>('') |
|
|
|
|
|
|
|
|
const { mutate: saveOrUpdate, isPending: isSubmitting } = useAtomValue(saveOrUpdateCertAtom) |
|
|
|
|
|
const [ domains, setDomains ] = useAtom(domainsAtom) |
|
|
|
|
|
const dnsVerifyOK = useAtomValue(dnsVerifyOKAtom) |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
|
|
|
|
|
|
if (domains) { |
|
|
|
|
|
form.setFieldsValue({ |
|
|
|
|
|
domains |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
}, [ domains ]) |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<ListPageLayout |
|
|
<ListPageLayout |
|
@ -144,12 +236,13 @@ const Apply = (props: any) => { |
|
|
onValuesChange={(values) => { |
|
|
onValuesChange={(values) => { |
|
|
// console.log('onValuesChange', values)
|
|
|
// console.log('onValuesChange', values)
|
|
|
if (values.domains) { |
|
|
if (values.domains) { |
|
|
setDomains(values.domains) |
|
|
|
|
|
|
|
|
// setDomains(values.domains)
|
|
|
} |
|
|
} |
|
|
}} |
|
|
}} |
|
|
onFinish={async (values) => { |
|
|
onFinish={async (values) => { |
|
|
console.log(values) |
|
|
|
|
|
|
|
|
if (dnsVerifyOK) { |
|
|
saveOrUpdate(values) |
|
|
saveOrUpdate(values) |
|
|
|
|
|
} |
|
|
}} |
|
|
}} |
|
|
> |
|
|
> |
|
|
<Form.Item |
|
|
<Form.Item |
|
@ -161,7 +254,11 @@ const Apply = (props: any) => { |
|
|
placeholder={`请输入域名,每行一个,支持泛解析域名;如:
|
|
|
placeholder={`请输入域名,每行一个,支持泛解析域名;如:
|
|
|
*.google.com |
|
|
*.google.com |
|
|
*.a.baidu.com |
|
|
*.a.baidu.com |
|
|
hello.alibaba.com`}/>
|
|
|
|
|
|
|
|
|
hello.alibaba.com`}
|
|
|
|
|
|
onBlur={(e) => { |
|
|
|
|
|
setDomains(e.target.value) |
|
|
|
|
|
}} |
|
|
|
|
|
/> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item |
|
|
<Form.Item |
|
|
label={t(`${i18nPrefix}.columns.type`, '域名验证')} |
|
|
label={t(`${i18nPrefix}.columns.type`, '域名验证')} |
|
@ -194,7 +291,9 @@ const Apply = (props: any) => { |
|
|
<Input/> |
|
|
<Input/> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
<Form.Item label={' '} colon={false}> |
|
|
<Form.Item label={' '} colon={false}> |
|
|
<Button type={'primary'} htmlType={'submit'}>{t(`${i18nPrefix}.apply.submit`, '提交申请')}</Button> |
|
|
|
|
|
|
|
|
<Button type={'primary'} |
|
|
|
|
|
disabled={!dnsVerifyOK || isSubmitting} |
|
|
|
|
|
htmlType={'submit'}>{t(`${i18nPrefix}.apply.submit`, '提交申请')}</Button> |
|
|
</Form.Item> |
|
|
</Form.Item> |
|
|
</Form> |
|
|
</Form> |
|
|
</ListPageLayout> |
|
|
</ListPageLayout> |
|
|