From ba4ad24ba29a2f55ebc6f8270d5cfa3677af9eb9 Mon Sep 17 00:00:00 2001 From: dark Date: Sun, 14 Jul 2024 23:40:10 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=AF=81=E4=B9=A6=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/ListPageLayout.tsx | 14 ++- src/pages/websites/cert/apply.tsx | 204 ++++++++++++++++++++++++++++++++++++++ src/pages/websites/cert/index.tsx | 16 +-- src/pages/websites/cert/style.ts | 103 +++++++++++++++---- src/routes.tsx | 9 +- src/service/websites.ts | 11 +- src/store/websites/cert.ts | 31 +++++- 7 files changed, 353 insertions(+), 35 deletions(-) create mode 100644 src/pages/websites/cert/apply.tsx diff --git a/src/layout/ListPageLayout.tsx b/src/layout/ListPageLayout.tsx index d404f2e..619cf75 100644 --- a/src/layout/ListPageLayout.tsx +++ b/src/layout/ListPageLayout.tsx @@ -11,7 +11,9 @@ import { useNavigate } from '@tanstack/react-router' interface IListPageLayoutProps extends PageContainerProps { children: React.ReactNode - authHeight?: boolean + authHeight?: boolean, + childrenStyle?: React.CSSProperties, + childrenClassName?: string, } const ListPageLayout: React.FC = ( @@ -19,6 +21,8 @@ const ListPageLayout: React.FC = ( className, children, authHeight = true, + childrenClassName, + childrenStyle, title, ...props }) => { @@ -61,9 +65,11 @@ const ListPageLayout: React.FC = ( {...props} > -
+
{children}
diff --git a/src/pages/websites/cert/apply.tsx b/src/pages/websites/cert/apply.tsx new file mode 100644 index 0000000..deb6ad1 --- /dev/null +++ b/src/pages/websites/cert/apply.tsx @@ -0,0 +1,204 @@ +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 { + Button, + Flex, + Form, + Input, + Select, + Space, + Table, Typography, +} from 'antd' +import google from '@/pages/websites/cert/assets/google.png' +import zerossl from '@/pages/websites/cert/assets/zerossl.png' +import lets_encrypt from '@/pages/websites/cert/assets/lets_encrypt.png' +import { useStyle } from './style' +import ListPageLayout from '@/layout/ListPageLayout.tsx' +import { ColumnsType } from 'antd/es/table' + +const i18nPrefix = 'cert.apply' + +const BrandSelect = (props: any) => { + + const { styles, cx } = useStyle() + const [ value, setValue ] = useState(() => props.value) + + useEffect(() => { + setValue(props.value) + }, [ props.value ]) + + const onChange = useCallback((val: string) => { + props.onChange?.(val) + }, []) + + return <> + + onChange('Google')} + className={cx('band-normal', { + 'band-active': value === 'Google' + })}> + + Google Trust Services + + onChange('ZeroSSL')} + className={cx('band-normal', { + 'band-active': value === 'ZeroSSL' + })}> + + ZeroSSL + + onChange('Let\'s Encrypt')} + className={cx('band-normal', { + 'band-active': value === 'Let\'s Encrypt' + })}> + + Let's Encrypt + + + +} + +const StatusTable = (props: { value: string }) => { + + + const { data, isFetching } = useAtomValue(useMemo(() => dnsConfigAtom(props.value), [ props.value ])) + + const columns = useMemo(() => { + + return [ + { + title: t(`${i18nPrefix}.status.columns.status`, '状态'), + tooltip: t(`${i18nPrefix}.status.columns.statusTip`, '正确配置DNS解析后,域名验证会自动通过'), + dataIndex: 'status', + }, + { + //服务商 + title: t(`${i18nPrefix}.status.columns.name_servers`, '服务商'), + dataIndex: 'name_servers', + }, + { + //域名 + title: t(`${i18nPrefix}.status.columns.domain`, '域名'), + dataIndex: 'domain', + }, + { + //主机记录 + title: t(`${i18nPrefix}.status.columns.record`, '主机记录'), + dataIndex: 'record', + }, + { + //记录类型 + title: t(`${i18nPrefix}.status.columns.record_type`, '记录类型'), + dataIndex: 'record_type', + }, + { + //记录值 + title: t(`${i18nPrefix}.status.columns.record_value`, '记录值'), + dataIndex: 'record_value', + render:(text)=>{ + return {text} + } + } + ] as ColumnsType + + }, []) + + + return <> +
+
请您添加以下DNS解析记录 参考文档
+
1. 只需要添加一次即可,添加后请勿删除记录。
+
2. 耐心等待1~2分钟。
+
+ + +} + +const Apply = (props: any) => { + const { styles, cx } = useStyle() + const [ form ] = Form.useForm() + const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateCertAtom) + const [ domains, setDomains ] = useState('') + + return ( + + +
{ + // console.log('onValuesChange', values) + if (values.domains) { + setDomains(values.domains) + } + }} + onFinish={async (values) => { + console.log(values) + saveOrUpdate(values) + }} + > + + + + + + + + + + + + + + + + +
+ ) +} + +export default Apply \ No newline at end of file diff --git a/src/pages/websites/cert/index.tsx b/src/pages/websites/cert/index.tsx index e11c70a..077a2f4 100644 --- a/src/pages/websites/cert/index.tsx +++ b/src/pages/websites/cert/index.tsx @@ -24,11 +24,13 @@ import google from './assets/google.png' import lets_encrypt from './assets/lets_encrypt.png' import zerossl from './assets/zerossl.png' import ModalPro from '@/components/modal-pro' +import { useNavigate } from '@tanstack/react-router' const i18nPrefix = 'cert.list' const Cert = () => { + const navigate = useNavigate() const { styles, cx } = useStyle() const { t } = useTranslation() const [ form ] = Form.useForm() @@ -222,11 +224,9 @@ const Cert = () => { headerTitle={ @@ -303,7 +303,7 @@ const Cert = () => { }, }} /> - { layout={'vertical'} scrollToFirstError={true} title={t(`${i18nPrefix}.title_${form.getFieldValue('id') !== 0 ? 'edit' : 'add'}`, form.getFieldValue('id') !== 0 ? '账号管理编辑' : '账号管理添加')} - layoutType={'DrawerForm'} + layoutType={'Embed'} open={open} drawerProps={{ maskClosable: false, @@ -326,7 +326,7 @@ const Cert = () => { onFinish={async (values) => { saveOrUpdate(values) }} - columns={columns as ProFormColumnsType[]}/> + columns={columns as ProFormColumnsType[]}/>*/} { - const prefix = `${prefixCls}-${token?.proPrefix}-domainGroup-list-page` - - const container = css` - .ant-table-cell{ - .ant-tag{ - padding-inline: 3px; - margin-inline-end: 3px; - } - } - .ant-table-empty { - .ant-table-body{ - height: calc(100vh - 350px) - } - } - .ant-pro-table-highlight{ + const prefix = `${prefixCls}-${token?.proPrefix}-domainGroup-list-page` + const { scrollbarBackground } = useScrollStyle() + + const container = css` + .ant-table-cell { + .ant-tag { + padding-inline: 3px; + margin-inline-end: 3px; + } + } + + .ant-table-empty { + .ant-table-body { + height: calc(100vh - 350px) + } + } + + .ant-pro-table-highlight { + + } + ` + const bandSelect = css` + .band-normal { + border: 2px solid #ebebeb; + border-radius: 4px; + color: #575757; + padding: 10px 20px; + user-select: none; + cursor: pointer; + + &:not(.band-active):hover { + border: 2px solid #d6d6d6; + color: #393939; } - ` - return { - container: cx(prefix, props?.className, container), + img { + object-fit: contain; + object-position: left; + } } + + .band-active { + border: 2px solid #3f9eff; + color: #3f9eff; + } + ` + + const applyContainer = css` + + .ant-pro-grid-content{ + + height: calc(100vh - 122px); + min-height: calc(100vh - 122px); + overflow: hidden; + + } + + //padding: 20px; + .ant-pro-card{ + border-radius: 0; + } + .ant-pro-card-header{ + border-bottom: 1px solid #ebebeb; + } + .ant-pro-card-body{ + padding-block-start: 24px; + } + ` + + const applyContent = css` + height: 100%; + overflow: auto; + ${scrollbarBackground} + + .ant-form{ + + padding-block-start: 44px; + } + + ` + + return { + container: cx(prefix, props?.className, container), + applyContainer, + applyContent, + bandSelect, + } }) \ No newline at end of file diff --git a/src/routes.tsx b/src/routes.tsx index 0d46e76..6e12e35 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -242,7 +242,14 @@ const generateDynamicRoutes = (menuData: MenuItem[], parentRoute: AnyRoute) => { component = component.replace(/\/index$/, '') } - const module = modules[`./pages/${component}/index.tsx`] || modules[`./pages/${component}/index.jsx`] + let module: () => Promise + //优先匹配无index的情况 + if (modules[`./pages/${component}.tsx`] || modules[`./pages/${component}.jsx`]) { + module = modules[`./pages/${component}.tsx`] || modules[`./pages/${component}.jsx`] + } else { + module = modules[`./pages/${component}/index.tsx`] || modules[`./pages/${component}/index.jsx`] + } + if (!module) { return NotFound } diff --git a/src/service/websites.ts b/src/service/websites.ts index 581139f..703da75 100644 --- a/src/service/websites.ts +++ b/src/service/websites.ts @@ -64,7 +64,16 @@ const websitesServ = { }, }) // return request.post('/website/cert/list', params) - } + }, + //dns_config + dnsConfig: async (params: any) => { + return request.post('/website/cert/dns_config', params) + }, + //dns_verify + dnsVerify: async (params: any) => { + return request.post('/website/cert/dns_verify', params) + }, + }, ssl: { ...createCURD('/website/ssl'), diff --git a/src/store/websites/cert.ts b/src/store/websites/cert.ts index 2eed857..6cf7b55 100644 --- a/src/store/websites/cert.ts +++ b/src/store/websites/cert.ts @@ -72,10 +72,10 @@ export const saveOrUpdateCertAtom = atomWithMutation(( mutationKey: [ 'updateCert' ], mutationFn: async (data) => { //data.status = data.status ? '1' : '0' - if (data.id === 0) { - return await websitesServ.cert.add(data) + if ( data.id) { + return await websitesServ.cert.update(data) } - return await websitesServ.cert.update(data) + return await websitesServ.cert.add(data) }, onSuccess: (res) => { const isAdd = !!res.data?.id @@ -105,3 +105,28 @@ export const deleteCertAtom = atomWithMutation((get) => { } } }) + +//dnsConfig +export const dnsConfigAtom = (domains: string[] | string) => atomWithQuery(() => { + if (typeof domains === 'string') { + domains = domains.split('\n').filter(Boolean) + } + + return { + enabled: domains.length > 0, + queryKey: [ 'dnsConfig', domains ], + queryFn: async ({ queryKey: [ , domains ] }) => { + + if ((domains as string[]).length === 0){ + return Promise.reject({ + data: [] + }) + } + + return await websitesServ.cert.dnsConfig({ dns_full_list: (domains as string[]).filter(Boolean), parse: true }) + }, + select: res => { + return res.data + } + } +})