diff --git a/package.json b/package.json index c7b048c..a5222fb 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "antd-style": "^3.6.2", "axios": "^1.7.7", "bunshi": "^2.1.5", + "date-fns": "^3.6.0", "dayjs": "^1.11.13", "fast-copy": "^3.0.2", "fast-deep-equal": "^3.1.3", diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index b61c222..389d8e3 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -1,97 +1,102 @@ -import SelectLang from '@/components/select-lang' -import { createFileRoute } from '@tanstack/react-router' -import { Button, Form, Input, Space } from 'antd' -import { useAtom, useAtomValue } from 'jotai' -import { useTranslation } from '@/i18n.ts' -import { loginAtom, loginFormAtom } from '@/store/system/user.ts' -import { memo, useLayoutEffect } from 'react' -import { useStyles } from './style.ts' +import SelectLang from "@/components/select-lang"; +import { createFileRoute } from "@tanstack/react-router"; +import { Button, Form, Input, Radio, Space } from "antd"; +import { useAtom, useAtomValue } from "jotai"; +import { useTranslation } from "@/i18n.ts"; +import { loginAtom, loginFormAtom } from "@/store/system/user.ts"; +import React, {memo, useLayoutEffect, useState} from "react"; +import { useStyles } from "./style.ts"; const Login = memo(() => { + const { styles } = useStyles(); + const { t } = useTranslation(); + const [values, setValues] = useAtom(loginFormAtom); + const { isPending, mutate } = useAtomValue(loginAtom); + const [form] = Form.useForm(); - const { styles } = useStyles() - const { t } = useTranslation() - const [ values, setValues ] = useAtom(loginFormAtom) - const { isPending, mutate } = useAtomValue(loginAtom) - const [ form ] = Form.useForm() + const handleSubmit = () => { + form.validateFields().then(() => { + mutate(values); + }); + }; - const handleSubmit = () => { - form.validateFields().then(() => { - mutate(values) - }) - } + const [loginMod, setLoginMod] = useState([ + { value: "single", info: "帐号密码登录" }, + { value: "multiple-email", info: "邮箱登录" }, + { value: "multiple-plane", info: "飞机登录" }, + ]); + const [selectedMode, setSelectedMode] = useState(loginMod[0].value); - useLayoutEffect(() => { + const handleModeChange = (e: any) => { + setSelectedMode(e.target.value); + }; - document.body.className = 'login' - return () => { - document.body.className = document.body.className.replace('login', '') - } + useLayoutEffect(() => { + document.body.className = "login"; + return () => { + document.body.className = document.body.className.replace("login", ""); + }; + }, []); - }, []) + return ( +
+
+ +
+
+
+ + {loginMod.map((mod) => ( + + {mod.info} + + ))} + +
{ + setValues(allValues); + }} + size="large" + > + + + + + + + + + + + {/*验证码*/} + + + + + + +
+
+
+
+ ); +}); - return ( -
-
- -
-
-
+export const Route = createFileRoute("/login")({ + component: Login, +}); -
- - {t('login.title')} - - -
- -
{ - setValues(allValues) - }} - size="large"> - - - - - - - - - - - {/*验证码*/} - - - - - - -
-
-
- -
- ) -}) - -export const Route = createFileRoute('/login')({ - component: Login -}) - -export default Login \ No newline at end of file +export default Login; diff --git a/src/pages/websites/cert/apply.tsx b/src/pages/websites/cert/apply.tsx index fd95dbe..9ec33ea 100644 --- a/src/pages/websites/cert/apply.tsx +++ b/src/pages/websites/cert/apply.tsx @@ -6,6 +6,7 @@ import { checkDomainAtom, applyTxtCertificateAtom, Req_ApplyTxtCertificate, + getCertConfigAtom, } from "@/store/websites/cert.ts"; import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; 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"; const i18nPrefix = "cert.apply"; -const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTxtCertificateData }) => { - const { styles, cx } = useStyle(); - +const DomainsInput = (props: { domains; setDomains; currentDomainMod; setCurrentDomainMod; currentStep }) => { useEffect(() => { - onChange(props.value); - }, [props.value]); + if (props.currentDomainMod === "single" && props.domains !== "") { + props.setDomains(props.domains.replace(/[\r\n]/g, "")); + } + }, [props.currentDomainMod]); + return ( + + props.setCurrentDomainMod(e.target.value)} + > + + 单证书申请 + + + 多证书申请 + + + {props.currentDomainMod === "single" && ( + { + props.setDomains(e.target.value); + }} + value={props.domains} // 设置输入框的值 + /> + )} + {props.currentDomainMod === "multiple" && ( + { + props.setDomains(e.target.value); + }} + value={props.domains} // 设置输入框的值 + /> + )} + + ); +}; - const onChange = useCallback((val: string) => { - props.setApplyTxtCertificateData((prevState) => ({ - ...prevState, - acme_type: val, - })); - }, []); +const BrandSelect = (props: { acme_type; setAcme_type }) => { + const { styles, cx } = useStyle(); + + const onChange = (val: string) => { + props.setAcme_type(val); + }; return ( <> @@ -49,7 +91,7 @@ const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTx vertical={true} onClick={() => onChange("Google")} className={cx("band-normal", { - "band-active": props.applyTxtCertificateData.acme_type === "Google" || !props.value, + "band-active": props.acme_type === "Google", })} > @@ -59,7 +101,7 @@ const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTx vertical={true} onClick={() => onChange("ZeroSSL")} className={cx("band-normal", { - "band-active": props.applyTxtCertificateData.acme_type === "ZeroSSL", + "band-active": props.acme_type === "ZeroSSL", })} > @@ -69,7 +111,7 @@ const BrandSelect = (props: { value: string; applyTxtCertificateData; setApplyTx vertical={true} onClick={() => onChange("Let's Encrypt")} className={cx("band-normal", { - "band-active": props.applyTxtCertificateData.acme_type === "Let's Encrypt", + "band-active": props.acme_type === "Let's Encrypt", })} > @@ -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(null); // 临时状态来存储模拟数据 const [forceUpdate, setForceUpdate] = useState(0); const { data, isFetching: isVerifyFetching } = useAtomValue( @@ -249,7 +291,7 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific iconPosition={"end"} onClick={() => handleCopy(text)} > - {t(`actions.clickCopy`)} + {text} ); }, @@ -262,10 +304,7 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific if ((data as any)?.check_ok === true) { props.setCurrentStep(2); - props.setApplyTxtCertificateData((prevState) => ({ - ...prevState, - dns_list: (data as any).dns_list, - })); + props.setDns_list((data as any).dns_list); return; } @@ -279,10 +318,7 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific // window.clearInterval(timerRef.current); if ((data as any)?.check_ok === true) { 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); } else { refetch(); @@ -316,48 +352,9 @@ const StatusTable = (props: { value: string; setCurrentStep; setApplyTxtCertific ); }; -const DomainsInput = (props: { setDomains; currentDomainMod; setCurrentDomainMod; currentStep }) => { - return ( - - props.setCurrentDomainMod(e.target.value)} - > - - 单证书申请 - - - 多证书申请 - - - {props.currentDomainMod === "single" && ( - { - props.setDomains(e.target.value); - }} - /> - )} - {props.currentDomainMod === "multiple" && ( - { - props.setDomains(e.target.value); - }} - /> - )} - - ); -}; - -const domainsAtom = atomWithStorage("domains", ""); +const domainsAtom = atomWithStorage("cert_domains", ""); +// 打印初始值 +console.log("初始文本值:", localStorage.getItem("cert_domains") || ""); const Apply = () => { const { styles } = useStyle(); @@ -367,33 +364,36 @@ const Apply = () => { isPending: applyTxtCertificatePending, isSuccess: applyTxtCertificateIsSuccess, } = useAtomValue(applyTxtCertificateAtom); + const [domains, setDomains] = useAtom(domainsAtom); const [currentStep, setCurrentStep] = useState(0); const [currentDomainMod, setCurrentDomainMod] = useState<"single" | "multiple">("single"); + const [dns_list, setDns_list] = useState([]); + const [acme_type, setAcme_type] = useState("Google"); + const [key_rsa, setKey_rsa] = useState(""); + + const { data: configData } = useAtomValue(useMemo(() => getCertConfigAtom(), [])); - const [applyTxtCertificateData, setApplyTxtCertificateData] = useState({ - is_sync: true, - acme_type: "", - key_rsa: "", - dns_list: [], - }); const handleAlgorithmChange = (value: string) => { - setApplyTxtCertificateData((prevState) => ({ - ...prevState, - key_rsa: value, - })); + setKey_rsa(value); }; 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(() => { - 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 ( { rules={[{ required: true, message: t(`${i18nPrefix}.columns.domains.required`, "请输入域名") }]} > @@ -465,11 +466,7 @@ const Apply = () => { label={t(`${i18nPrefix}.columns.type`, "域名验证")} rules={[{ required: true, message: t(`${i18nPrefix}.columns.type`, "域名验证没有通过") }]} > - + { }, ]} > - + { }, ]} > - diff --git a/src/service/websites.ts b/src/service/websites.ts index 0294812..2f7f1fc 100644 --- a/src/service/websites.ts +++ b/src/service/websites.ts @@ -1,18 +1,24 @@ -import { createCURD } from '@/service/base.ts' -import { WebSite } from '@/types' -import request from '@/request.ts' -import { IWebsiteDomain, INameServer } from '@/types/website/domain' -import { IWebsiteDnsRecords } from '@/types/website/record' -import { IWebsiteDnsAccount } from '@/types/website/dns_account' +import { createCURD } from "@/service/base.ts"; +import { WebSite } from "@/types"; +import request from "@/request.ts"; +import { IWebsiteDomain, INameServer } from "@/types/website/domain"; +import { IWebsiteDnsRecords } from "@/types/website/record"; +import { IWebsiteDnsAccount } from "@/types/website/dns_account"; const websitesServ = { cert: { - ...createCURD("/website/cert"), // 发起域名检测 checkDomain: async (params: any) => { return request.post("/cert/apply/dns_config", params); }, + getCertConfig: async () => { + return request.get("/cert/apply/acme/key"); + }, + // 申请list + getCertList: async (arams: any) => { + return request.post("/cert/apply/list"); + }, // 证书续签 renewCertificate: async (params: any) => { return request.post("/website/cert/renew_certificate", params); @@ -32,66 +38,63 @@ const websitesServ = { applyTxtCertificate: async (params: any) => { return request.post("/cert/apply/resolve", params); }, - - }, ssl: { - ...createCURD('/website/ssl'), + ...createCURD("/website/ssl"), upload: async (params: WebSite.SSLUploadDto) => { - return request.post('/website/ssl/upload', params) + return request.post("/website/ssl/upload", params); }, download: async (params: any) => { - return request.download('/website/ssl/download', params) + return request.download("/website/ssl/download", params); }, }, acme: { - ...createCURD('/website/acme') + ...createCURD("/website/acme"), }, dns: { - ...createCURD('/cert/dns_account'), + ...createCURD("/cert/dns_account"), sync: async (id: any) => { - return request.post('/cert/dns_account/sync', { id: id }) - } + return request.post("/cert/dns_account/sync", { id: id }); + }, }, ca: { - ...createCURD('/website/ca'), + ...createCURD("/website/ca"), obtainSsl: async (params: WebSite.ISSLObtainByCA) => { - return request.post('/website/ca/obtain_ssl', params) + return request.post("/website/ca/obtain_ssl", params); }, }, domain: { - ...createCURD('/cert/domain'), + ...createCURD("/cert/domain"), //remark - remark: async (params: { id: string, remark: string }) => { - return request.post('/cert/domain/remark', params) + remark: async (params: { id: string; remark: string }) => { + return request.post("/cert/domain/remark", params); }, //tag - tag: async (params: { id: string, tags: string }) => { - return request.post('/cert/domain/tag', params) + tag: async (params: { id: string; tags: string }) => { + return request.post("/cert/domain/tag", params); }, //binding - binding: async (params: { id: string, user_id: string }) => { - return request.post('/cert/domain/binding', params) + binding: async (params: { id: string; user_id: string }) => { + return request.post("/cert/domain/binding", params); }, //group - group: async (params: { id: string[], group_id: string }) => { - return request.post('/cert/domain/group', params) + group: async (params: { id: string[]; group_id: string }) => { + return request.post("/cert/domain/group", params); }, describeDomainNS: async (params: { id: number }) => { - return request.post('/cert/domain/describe_domain_ns', params) + return request.post("/cert/domain/describe_domain_ns", params); }, - }, record: { - ...createCURD('/cert/dns_records'), + ...createCURD("/cert/dns_records"), // }, dnsAccount: { - ...createCURD('/cert/dns_account'), + ...createCURD("/cert/dns_account"), sync: async (params: IWebsiteDnsAccount) => { - return request.post('/cert/dns_account/sync', params) - } + return request.post("/cert/dns_account/sync", params); + }, }, -} +}; -export default websitesServ \ No newline at end of file +export default websitesServ; diff --git a/src/store/websites/cert.ts b/src/store/websites/cert.ts index b4d174f..a34458c 100644 --- a/src/store/websites/cert.ts +++ b/src/store/websites/cert.ts @@ -9,22 +9,45 @@ export type Req_SearchParams = IPage & { name?: string; }; -export type Req_AddCname = { +export interface Req_AddCname { is_sync: boolean; dns_list: ICertificate[]; -}; +} -export type Req_ApplyTxtCertificate = { +export interface Req_ApplyTxtCertificate { is_sync: boolean; acme_type: string; key_rsa: string; dns_list: ICertificate[]; -}; - + remark: string; +} +//=========================证书列表 +export interface Req_CertList { + order: string; + prop: string; + page: number; + pageSize: number; +} +export interface Resp_CertList { + page: number; + pageSize: number; + total: number; + rows: any; +} +//=========================证书列表 export const bandTypes = [ - { label: "Google", value: "Google" }, - { label: "ZeroSSL", value: "ZeroSSL" }, - { label: "Let's Encrypt", value: "Let's Encrypt" }, + { + label: "LetsEncrypt", + value: "LetsEncrypt", + }, + { + label: "ZeroSsl", + value: "ZeroSsl", + }, + { + label: "Google", + value: "Google", + }, ]; export const algorithmTypes = [ @@ -56,6 +79,19 @@ export const certPageAtom = atom({ }); //=================================================================================================================================================kelis +export const getCertConfigAtom = () => + atomWithQuery(() => { + return { + queryKey: ["getCertConfig"], + queryFn: async () => { + return await websitesServ.cert.getCertConfig(); + }, + select: (res) => { + return res.data; + }, + }; + }); + export const checkDomainAtom = (domains: string, isClear: boolean) => atomWithQuery(() => { return { @@ -80,24 +116,18 @@ export const checkDomainAtom = (domains: string, isClear: boolean) => }; }); -export const certListAtom = atomWithQuery((get) => { - return { - queryKey: ["certList", get(certSearchAtom)], - queryFn: async ({ queryKey: [, params] }) => { - return await websitesServ.cert.list(params as Req_SearchParams); - }, - select: (res) => { - const data = res.data; - data.rows = data.rows?.map((row) => { - return { - ...row, - //status: convertToBool(row.status) - }; - }); - return data; - }, - }; -}); +export const certListAtom = (params: Req_CertList) => + atomWithQuery(() => { + return { + queryKey: ["certList", params], + queryFn: async ({ queryKey: [, params] }) => { + return await websitesServ.cert.getCertList(params); + }, + select: (res) => { + return res.data; + }, + }; + }); export const certAddCnameAtom = atomWithMutation(() => { return {