2 Commits
4f80438b4b
...
f91d54b65f
Author | SHA1 | Message | Date |
---|---|---|---|
lk | f91d54b65f |
Merge remote-tracking branch 'origin/main'
|
3 months ago |
lk | 456043541f |
增加证书页面
|
3 months ago |
15 changed files with 1261 additions and 980 deletions
-
2.env.proxy.local
-
2mock/menus.ts
-
8src/pages/dashboard/index.tsx
-
4src/pages/globle/globle_style.css
-
829src/pages/websites/account/index.tsx
-
24src/pages/websites/account/style.ts
-
413src/pages/websites/cert/apply.tsx
-
837src/pages/websites/domain/index.tsx
-
10src/pages/websites/domain/style.ts
-
52src/pages/websites/mytest/index.tsx
-
4src/pages/websites/record/index.tsx
-
2src/service/website/domain_group.ts
-
26src/service/websites.ts
-
25src/store/websites/cert.ts
-
3vite.config.ts
@ -1 +1 @@ |
|||||
API_URL=http://47.113.117.106:10000 |
|
||||
|
API_URL=http://192.168.31.96:8686 |
@ -0,0 +1,4 @@ |
|||||
|
.disabled_text { |
||||
|
pointer-events: none; /* 禁用鼠标事件 */ |
||||
|
color: gray; /* 设置文本颜色为灰色 */ |
||||
|
} |
@ -1,482 +1,519 @@ |
|||||
import { useTranslation } from '../../../i18n.ts' |
|
||||
import { Button, Form, Space, Tooltip, Badge, Divider } from 'antd' |
|
||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai' |
|
||||
|
import { useTranslation } from "../../../i18n.ts"; |
||||
|
import { Button, Form, Space, Tooltip, Badge, Divider, Spin } from "antd"; |
||||
|
import { useAtom, useAtomValue, useSetAtom } from "jotai"; |
||||
import { |
import { |
||||
deleteWebsiteDnsAccountAtom, |
deleteWebsiteDnsAccountAtom, |
||||
saveOrUpdateWebsiteDnsAccountAtom, websiteDnsAccountAtom, websiteDnsAccountsAtom, websiteDnsAccountSearchAtom, |
|
||||
} from '@/store/websites/dns_account.ts' |
|
||||
import { useEffect, useMemo, useState } from 'react' |
|
||||
import Action from '@/components/action/Action.tsx' |
|
||||
import { |
|
||||
BetaSchemaForm, |
|
||||
ProColumns, |
|
||||
ProFormColumnsType, |
|
||||
} from '@ant-design/pro-components' |
|
||||
import ListPageLayout from '@/layout/ListPageLayout.tsx' |
|
||||
import { useStyle } from './style.ts' |
|
||||
import { FilterOutlined } from '@ant-design/icons' |
|
||||
import { getValueCount, unSetColumnRules } from '@/utils' |
|
||||
import { Table as ProTable } from '@/components/table' |
|
||||
import { DNSTypeEnum, DNSTypes, syncDNSAtom } from '@/store/websites/dns.ts' |
|
||||
import { WebSite } from '@/types' |
|
||||
import Switch from '@/components/switch' |
|
||||
import Popconfirm from '@/components/popconfirm' |
|
||||
|
saveOrUpdateWebsiteDnsAccountAtom, |
||||
|
websiteDnsAccountAtom, |
||||
|
websiteDnsAccountsAtom, |
||||
|
websiteDnsAccountSearchAtom, |
||||
|
} from "@/store/websites/dns_account.ts"; |
||||
|
import { useEffect, useMemo, useState } from "react"; |
||||
|
import Action from "@/components/action/Action.tsx"; |
||||
|
import { BetaSchemaForm, ProColumns, ProFormColumnsType } from "@ant-design/pro-components"; |
||||
|
import ListPageLayout from "@/layout/ListPageLayout.tsx"; |
||||
|
import { useStyle } from "./style.ts"; |
||||
|
import { FilterOutlined } from "@ant-design/icons"; |
||||
|
import { getValueCount, unSetColumnRules } from "@/utils"; |
||||
|
import { Table as ProTable } from "@/components/table"; |
||||
|
import { DNSTypeEnum, DNSTypes, syncDNSAtom } from "@/store/websites/dns.ts"; |
||||
|
import { WebSite } from "@/types"; |
||||
|
import Switch from "@/components/switch"; |
||||
|
import Popconfirm from "@/components/popconfirm"; |
||||
|
import { Link } from "@tanstack/react-router"; |
||||
|
import "@/pages/globle/globle_style.css"; |
||||
|
|
||||
const i18nPrefix = 'websiteDnsAccounts.list' |
|
||||
|
const i18nPrefix = "websiteDnsAccounts.list"; |
||||
const getKeyColumn = (type: string, t) => { |
const getKeyColumn = (type: string, t) => { |
||||
const columns: ProColumns<WebSite.IDnsAccount>[] = [] |
|
||||
|
const columns: ProColumns<WebSite.IDnsAccount>[] = []; |
||||
switch (type) { |
switch (type) { |
||||
case DNSTypeEnum.AliYun: { |
|
||||
columns.push(...[ |
|
||||
{ |
|
||||
title: t('website.ssl.dns.columns.accessKey', 'Access Key'), |
|
||||
dataIndex: [ 'authorization', 'accessKey' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: t('website.ssl.dns.columns.secretKey', 'Secret Key'), |
|
||||
dataIndex: [ 'authorization', 'secretKey' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, |
|
||||
]) |
|
||||
} |
|
||||
break |
|
||||
case DNSTypeEnum.TencentCloud: { |
|
||||
columns.push(...[ |
|
||||
{ |
|
||||
title: t('website.ssl.dns.columns.secretID', 'Secret ID'), |
|
||||
dataIndex: [ 'authorization', 'secretID' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, { |
|
||||
title: t('website.ssl.dns.columns.secretKey', 'Secret Key'), |
|
||||
dataIndex: [ 'authorization', 'secretKey' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, |
|
||||
]) |
|
||||
break |
|
||||
|
case DNSTypeEnum.AliYun: |
||||
|
{ |
||||
|
columns.push( |
||||
|
...[ |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.accessKey", "Access Key"), |
||||
|
dataIndex: ["authorization", "accessKey"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.secretKey", "Secret Key"), |
||||
|
dataIndex: ["authorization", "secretKey"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
); |
||||
|
} |
||||
|
break; |
||||
|
case DNSTypeEnum.TencentCloud: { |
||||
|
columns.push( |
||||
|
...[ |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.secretID", "Secret ID"), |
||||
|
dataIndex: ["authorization", "secretID"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.secretKey", "Secret Key"), |
||||
|
dataIndex: ["authorization", "secretKey"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
); |
||||
|
break; |
||||
} |
} |
||||
case DNSTypeEnum.DnsPod: { |
case DNSTypeEnum.DnsPod: { |
||||
columns.push(...[ |
|
||||
{ |
|
||||
title: t('website.ssl.dns.columns.apiId', 'ID'), |
|
||||
dataIndex: [ 'authorization', 'apiId' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, { |
|
||||
title: t('website.ssl.dns.columns.token', 'Token'), |
|
||||
dataIndex: [ 'authorization', 'token' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, |
|
||||
]) |
|
||||
break |
|
||||
|
columns.push( |
||||
|
...[ |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.apiId", "ID"), |
||||
|
dataIndex: ["authorization", "apiId"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.token", "Token"), |
||||
|
dataIndex: ["authorization", "token"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
); |
||||
|
break; |
||||
} |
} |
||||
case DNSTypeEnum.CloudFlare: { |
case DNSTypeEnum.CloudFlare: { |
||||
columns.push(...[ |
|
||||
{ |
|
||||
title: t('website.ssl.dns.columns.email', 'Email'), |
|
||||
dataIndex: [ 'authorization', 'email' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, { |
|
||||
title: t('website.ssl.dns.columns.apiKey', 'API ToKen'), |
|
||||
dataIndex: [ 'authorization', 'apiKey' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, |
|
||||
] |
|
||||
) |
|
||||
break |
|
||||
|
columns.push( |
||||
|
...[ |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.email", "Email"), |
||||
|
dataIndex: ["authorization", "email"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.apiKey", "API ToKen"), |
||||
|
dataIndex: ["authorization", "apiKey"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
); |
||||
|
break; |
||||
} |
} |
||||
case DNSTypeEnum.Godaddy: |
case DNSTypeEnum.Godaddy: |
||||
case DNSTypeEnum.NameCheap: |
case DNSTypeEnum.NameCheap: |
||||
case DNSTypeEnum.NameSilo: |
case DNSTypeEnum.NameSilo: |
||||
columns.push({ |
columns.push({ |
||||
title: t('website.ssl.dns.columns.apiKey', 'API Key'), |
|
||||
dataIndex: [ 'authorization', 'apiKey' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, |
|
||||
) |
|
||||
|
title: t("website.ssl.dns.columns.apiKey", "API Key"), |
||||
|
dataIndex: ["authorization", "apiKey"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}); |
||||
if (type === DNSTypeEnum.NameCheap) { |
if (type === DNSTypeEnum.NameCheap) { |
||||
columns.push({ |
columns.push({ |
||||
title: t('website.ssl.dns.columns.apiUser', 'API User'), |
|
||||
dataIndex: [ 'authorization', 'apiUser' ], |
|
||||
|
title: t("website.ssl.dns.columns.apiUser", "API User"), |
||||
|
dataIndex: ["authorization", "apiUser"], |
||||
formItemProps: { |
formItemProps: { |
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}) |
|
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}); |
||||
} else if (type === DNSTypeEnum.Godaddy) { |
} else if (type === DNSTypeEnum.Godaddy) { |
||||
columns.push({ |
columns.push({ |
||||
title: t('website.ssl.dns.columns.apiSecret', 'API Secret'), |
|
||||
dataIndex: [ 'authorization', 'apiSecret' ], |
|
||||
|
title: t("website.ssl.dns.columns.apiSecret", "API Secret"), |
||||
|
dataIndex: ["authorization", "apiSecret"], |
||||
formItemProps: { |
formItemProps: { |
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}) |
|
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}); |
||||
} |
} |
||||
break |
|
||||
|
break; |
||||
case DNSTypeEnum.NameCom: { |
case DNSTypeEnum.NameCom: { |
||||
columns.push( |
columns.push( |
||||
{ |
|
||||
title: t('website.ssl.dns.columns.apiUser', 'UserName'), |
|
||||
dataIndex: [ 'authorization', 'apiUser' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: t('website.ssl.dns.columns.token', 'Token'), |
|
||||
dataIndex: [ 'authorization', 'token' ], |
|
||||
formItemProps: { |
|
||||
rules: [ { required: true, message: t('message.required') } ] |
|
||||
} |
|
||||
} |
|
||||
) |
|
||||
break |
|
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.apiUser", "UserName"), |
||||
|
dataIndex: ["authorization", "apiUser"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: t("website.ssl.dns.columns.token", "Token"), |
||||
|
dataIndex: ["authorization", "token"], |
||||
|
formItemProps: { |
||||
|
rules: [{ required: true, message: t("message.required") }], |
||||
|
}, |
||||
|
}, |
||||
|
); |
||||
|
break; |
||||
} |
} |
||||
default: |
default: |
||||
break |
|
||||
|
|
||||
|
break; |
||||
} |
} |
||||
return columns |
|
||||
} |
|
||||
|
return columns; |
||||
|
}; |
||||
const WebsiteDnsAccount = () => { |
const WebsiteDnsAccount = () => { |
||||
|
const { styles, cx } = useStyle(); |
||||
|
const { t } = useTranslation(); |
||||
|
const [form] = Form.useForm(); |
||||
|
const [filterForm] = Form.useForm(); |
||||
|
const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateWebsiteDnsAccountAtom); |
||||
|
const [search, setSearch] = useAtom(websiteDnsAccountSearchAtom); |
||||
|
const setWebsiteDnsAccount = useSetAtom(websiteDnsAccountAtom); |
||||
|
const { data, isFetching, isLoading, refetch } = useAtomValue(websiteDnsAccountsAtom); |
||||
|
const { mutate: deleteWebsiteDnsAccount, isPending: isDeleting } = useAtomValue(deleteWebsiteDnsAccountAtom); |
||||
|
const { mutate: asyncDNS, isPending: isAsyncing } = useAtomValue(syncDNSAtom); |
||||
|
const [open, setOpen] = useState(false); |
||||
|
const [openFilter, setFilterOpen] = useState(false); |
||||
|
const [searchKey, setSearchKey] = useState(search?.title); |
||||
|
|
||||
const { styles, cx } = useStyle() |
|
||||
const { t } = useTranslation() |
|
||||
const [ form ] = Form.useForm() |
|
||||
const [ filterForm ] = Form.useForm() |
|
||||
const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateWebsiteDnsAccountAtom) |
|
||||
const [ search, setSearch ] = useAtom(websiteDnsAccountSearchAtom) |
|
||||
const setWebsiteDnsAccount = useSetAtom(websiteDnsAccountAtom) |
|
||||
const { data, isFetching, isLoading, refetch } = useAtomValue(websiteDnsAccountsAtom) |
|
||||
const { mutate: deleteWebsiteDnsAccount, isPending: isDeleting } = useAtomValue(deleteWebsiteDnsAccountAtom) |
|
||||
const { mutate: asyncDNS, isPending: isAsyncing } = useAtomValue(syncDNSAtom) |
|
||||
const [ open, setOpen ] = useState(false) |
|
||||
const [ openFilter, setFilterOpen ] = useState(false) |
|
||||
const [ searchKey, setSearchKey ] = useState(search?.title) |
|
||||
|
|
||||
const columns = useMemo(() => { |
const columns = useMemo(() => { |
||||
return [ |
return [ |
||||
{ |
{ |
||||
title: 'ID', |
|
||||
dataIndex: 'id', |
|
||||
|
title: "ID", |
||||
|
dataIndex: "id", |
||||
hideInTable: true, |
hideInTable: true, |
||||
hideInSearch: true, |
hideInSearch: true, |
||||
formItemProps: { hidden: true } |
|
||||
|
formItemProps: { hidden: true }, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.name`, '名称'), |
|
||||
dataIndex: 'name', |
|
||||
valueType: 'text', |
|
||||
|
title: t(`${i18nPrefix}.columns.name`, "名称"), |
||||
|
dataIndex: "name", |
||||
|
valueType: "text", |
||||
width: 250, |
width: 250, |
||||
fieldProps: { |
fieldProps: { |
||||
style: { |
style: { |
||||
width: '100%' |
|
||||
} |
|
||||
|
width: "100%", |
||||
|
}, |
||||
}, |
}, |
||||
formItemProps: { |
formItemProps: { |
||||
rules: [ |
|
||||
{ required: true, message: t('message.required', '请输入') } |
|
||||
] |
|
||||
} |
|
||||
|
rules: [{ required: true, message: t("message.required", "请输入") }], |
||||
|
}, |
||||
|
render: (text, record) => <Link to={`/cert/domain?id=${record.name}`}>{record.name}</Link>, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.name`, '标签'), |
|
||||
dataIndex: 'tag', |
|
||||
valueType: 'text', |
|
||||
|
title: t(`${i18nPrefix}.columns.name`, "标签"), |
||||
|
dataIndex: "tag", |
||||
|
valueType: "text", |
||||
hideInForm: true, |
hideInForm: true, |
||||
width: 200, |
width: 200, |
||||
fieldProps: { |
fieldProps: { |
||||
style: { |
style: { |
||||
width: '100%' |
|
||||
} |
|
||||
} |
|
||||
|
width: "100%", |
||||
|
}, |
||||
|
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.type`, '类型'), |
|
||||
dataIndex: 'type', |
|
||||
valueType: 'select', |
|
||||
|
title: t(`${i18nPrefix}.columns.type`, "类型"), |
||||
|
dataIndex: "type", |
||||
|
valueType: "select", |
||||
width: 200, |
width: 200, |
||||
fieldProps: { |
fieldProps: { |
||||
style: { |
style: { |
||||
width: '100%' |
|
||||
|
width: "100%", |
||||
}, |
}, |
||||
options: DNSTypes |
|
||||
|
options: DNSTypes, |
||||
}, |
}, |
||||
formItemProps: { |
formItemProps: { |
||||
rules: [ |
|
||||
{ required: true, message: t('message.required', '请选择') } |
|
||||
] |
|
||||
|
rules: [{ required: true, message: t("message.required", "请选择") }], |
||||
}, |
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
name: [ 'type' ], |
|
||||
valueType: 'dependency', |
|
||||
|
name: ["type"], |
||||
|
valueType: "dependency", |
||||
hideInSetting: true, |
hideInSetting: true, |
||||
hideInTable: true, |
hideInTable: true, |
||||
columns: ({ type }) => { |
columns: ({ type }) => { |
||||
return getKeyColumn(type, t) |
|
||||
} |
|
||||
|
return getKeyColumn(type, t); |
||||
|
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.status`, '状态'), |
|
||||
dataIndex: 'status', |
|
||||
valueType: 'switch', |
|
||||
|
title: t(`${i18nPrefix}.columns.status`, "状态111111"), |
||||
|
dataIndex: "status", |
||||
|
valueType: "switch", |
||||
width: 200, |
width: 200, |
||||
|
//disable禁用,enable正常,syncing正在同步中
|
||||
render(_dom, record) { |
render(_dom, record) { |
||||
return <Switch size={'small'} value={record.status}/> |
|
||||
} |
|
||||
|
// return <Switch size={"small"} checked={false} />;
|
||||
|
if (record.status == "syncing") { |
||||
|
return ( |
||||
|
<div className={cx('loadingStyle')}> |
||||
|
<Spin tip={t(`${i18nPrefix}.columns.syncing`, "同步中")} size="small"> |
||||
|
</Spin> |
||||
|
<div className={cx('loadingStyle_table')} >{t(`${i18nPrefix}.columns.syncing`, "同步中")}</div> |
||||
|
</div> |
||||
|
); |
||||
|
} else { |
||||
|
return <Switch size={"small"} checked={record.status==='enable'} />; |
||||
|
} |
||||
|
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.option`, '操作'), |
|
||||
key: 'option', |
|
||||
|
title: t(`${i18nPrefix}.columns.option`, "操作"), |
||||
|
key: "option", |
||||
width: 300, |
width: 300, |
||||
valueType: 'option', |
|
||||
fixed: 'right', |
|
||||
|
valueType: "option", |
||||
|
fixed: "right", |
||||
render: (_, record) => [ |
render: (_, record) => [ |
||||
<Action key="edit" |
|
||||
as={'a'} |
|
||||
disabled={record.status === 2} |
|
||||
onClick={() => { |
|
||||
record.status = record.status > 0 |
|
||||
if (typeof record.authorization === 'string') { |
|
||||
record.authorization = JSON.parse(record.authorization) |
|
||||
} |
|
||||
form.setFieldsValue(record) |
|
||||
setOpen(true) |
|
||||
}}>{t('actions.edit')}</Action>, |
|
||||
<Divider type={'vertical'}/>, |
|
||||
|
<Action |
||||
|
key="edit" |
||||
|
as={"a"} |
||||
|
disabled={record.status === "syncing"} |
||||
|
onClick={() => { |
||||
|
form.setFieldsValue(record); |
||||
|
setOpen(true); |
||||
|
}} |
||||
|
> |
||||
|
{t("actions.edit", "编辑")} |
||||
|
</Action>, |
||||
|
<Divider type={"vertical"} />, |
||||
<Popconfirm |
<Popconfirm |
||||
key={'sync_confirm'} |
|
||||
disabled={isAsyncing || record.status === 2} |
|
||||
onConfirm={() => { |
|
||||
asyncDNS(record.id) |
|
||||
}} |
|
||||
title={t('message.syncConfirm', '您确定要同步吗?')}> |
|
||||
{t('actions.sync', '同步')} |
|
||||
|
key={"sync_confirm"} |
||||
|
disabled={record.status == "syncing"} |
||||
|
onConfirm={() => { |
||||
|
asyncDNS(record.id); |
||||
|
}} |
||||
|
title={t("message.syncConfirm", "您确定要同步吗?")} |
||||
|
> |
||||
|
{t("actions.sync", "同步")} |
||||
</Popconfirm>, |
</Popconfirm>, |
||||
<Divider type={'vertical'}/>, |
|
||||
|
<Divider type={"vertical"} />, |
||||
<Popconfirm |
<Popconfirm |
||||
key={'del_confirm'} |
|
||||
disabled={isDeleting} |
|
||||
onConfirm={() => { |
|
||||
deleteWebsiteDnsAccount([ record.id ]) |
|
||||
}} |
|
||||
title={t('message.deleteConfirm')}> |
|
||||
{t('actions.delete', '删除')} |
|
||||
</Popconfirm> |
|
||||
] |
|
||||
} |
|
||||
] as ProColumns[] |
|
||||
}, [ isAsyncing, isDeleting, form, asyncDNS, deleteWebsiteDnsAccount ]) |
|
||||
|
key={"del_confirm"} |
||||
|
disabled={isDeleting} |
||||
|
onConfirm={() => { |
||||
|
deleteWebsiteDnsAccount([record.id]); |
||||
|
}} |
||||
|
title={t("message.deleteConfirm")} |
||||
|
> |
||||
|
{t("actions.delete", "删除")} |
||||
|
</Popconfirm>, |
||||
|
], |
||||
|
}, |
||||
|
] as ProColumns[]; |
||||
|
}, [isAsyncing, isDeleting, form, asyncDNS, deleteWebsiteDnsAccount]); |
||||
|
|
||||
useEffect(() => { |
useEffect(() => { |
||||
setSearchKey(search?.title) |
|
||||
filterForm.setFieldsValue(search) |
|
||||
}, [ search ]) |
|
||||
|
setSearchKey(search?.title); |
||||
|
filterForm.setFieldsValue(search); |
||||
|
}, [search]); |
||||
|
|
||||
useEffect(() => { |
useEffect(() => { |
||||
if (isSuccess) { |
if (isSuccess) { |
||||
setOpen(false) |
|
||||
|
setOpen(false); |
||||
} |
} |
||||
}, [ isSuccess ]) |
|
||||
|
}, [isSuccess]); |
||||
|
|
||||
return ( |
return ( |
||||
<ListPageLayout className={styles.container}> |
|
||||
<ProTable |
|
||||
rowKey="id" |
|
||||
headerTitle={ |
|
||||
<Space> |
|
||||
<Button key={'add'} |
|
||||
onClick={() => { |
|
||||
form.resetFields() |
|
||||
form.setFieldsValue({ |
|
||||
id: 0, |
|
||||
}) |
|
||||
setOpen(true) |
|
||||
}} |
|
||||
type={'primary'}>{t(`${i18nPrefix}.add`, '添加帐号')}</Button> |
|
||||
</Space> |
|
||||
} |
|
||||
toolbar={{ |
|
||||
search: { |
|
||||
loading: isFetching && !!search?.title, |
|
||||
onSearch: (value: string) => { |
|
||||
setSearch(prev => ({ |
|
||||
...prev, |
|
||||
title: value |
|
||||
})) |
|
||||
}, |
|
||||
allowClear: true, |
|
||||
onChange: (e) => { |
|
||||
setSearchKey(e.target?.value) |
|
||||
}, |
|
||||
value: searchKey, |
|
||||
placeholder: t(`${i18nPrefix}.placeholder`, '输入账号管理名称') |
|
||||
}, |
|
||||
actions: [ |
|
||||
<Tooltip key={'filter'} title={t(`${i18nPrefix}.filter.tooltip`, '高级查询')}> |
|
||||
<Badge count={getValueCount(search)}> |
|
||||
<Button |
|
||||
onClick={() => { |
|
||||
setFilterOpen(true) |
|
||||
}} |
|
||||
icon={<FilterOutlined/>} shape={'circle'} size={'small'}/> |
|
||||
</Badge> |
|
||||
</Tooltip>, |
|
||||
<Divider type={'vertical'} key={'divider'}/>, |
|
||||
] |
|
||||
}} |
|
||||
scroll={{ |
|
||||
// x: 2500,
|
|
||||
y: 'calc(100vh - 290px)' |
|
||||
}} |
|
||||
search={false} |
|
||||
onRow={(record) => { |
|
||||
return { |
|
||||
className: cx({ |
|
||||
// 'ant-table-row-selected': currentWebsiteDnsAccount?.id === record.id
|
|
||||
}), |
|
||||
onClick: () => { |
|
||||
setWebsiteDnsAccount(record as any) |
|
||||
} |
|
||||
} |
|
||||
}} |
|
||||
dateFormatter="string" |
|
||||
loading={isLoading || isFetching} |
|
||||
dataSource={data?.rows ?? []} |
|
||||
columns={columns} |
|
||||
options={{ |
|
||||
reload: () => { |
|
||||
refetch() |
|
||||
}, |
|
||||
}} |
|
||||
pagination={{ |
|
||||
total: data?.total, |
|
||||
pageSize: search.pageSize, |
|
||||
current: search.page, |
|
||||
onShowSizeChange: (current: number, size: number) => { |
|
||||
setSearch({ |
|
||||
...search, |
|
||||
pageSize: size, |
|
||||
page: current |
|
||||
}) |
|
||||
}, |
|
||||
onChange: (current, pageSize) => { |
|
||||
setSearch(prev => { |
|
||||
return { |
|
||||
...prev, |
|
||||
page: current, |
|
||||
pageSize: pageSize, |
|
||||
} |
|
||||
}) |
|
||||
}, |
|
||||
}} |
|
||||
/> |
|
||||
<BetaSchemaForm |
|
||||
grid={true} |
|
||||
shouldUpdate={false} |
|
||||
width={1000} |
|
||||
form={form} |
|
||||
layout={'vertical'} |
|
||||
scrollToFirstError={true} |
|
||||
title={t(`${i18nPrefix}.title_${form.getFieldValue('id') !== 0 ? 'edit' : 'add'}`, form.getFieldValue('id') !== 0 ? '账号管理编辑' : '账号管理添加')} |
|
||||
layoutType={'DrawerForm'} |
|
||||
open={open} |
|
||||
drawerProps={{ |
|
||||
maskClosable: false, |
|
||||
}} |
|
||||
onOpenChange={(open) => { |
|
||||
setOpen(open) |
|
||||
}} |
|
||||
loading={isSubmitting} |
|
||||
// onValuesChange={(values) => {
|
|
||||
//
|
|
||||
// }}
|
|
||||
onFinish={async (values) => { |
|
||||
values.status = values.status ? 1 : 0 |
|
||||
saveOrUpdate(values) |
|
||||
}} |
|
||||
columns={columns as ProFormColumnsType[]}/> |
|
||||
|
<ListPageLayout className={styles.container}> |
||||
|
<ProTable |
||||
|
rowKey="id" |
||||
|
headerTitle={ |
||||
|
<Space> |
||||
|
<Button |
||||
|
key={"add"} |
||||
|
onClick={() => { |
||||
|
form.resetFields(); |
||||
|
form.setFieldsValue({ |
||||
|
id: 0, |
||||
|
}); |
||||
|
setOpen(true); |
||||
|
}} |
||||
|
type={"primary"} |
||||
|
> |
||||
|
{t(`${i18nPrefix}.add`, "添加帐号")} |
||||
|
</Button> |
||||
|
</Space> |
||||
|
} |
||||
|
toolbar={{ |
||||
|
search: { |
||||
|
loading: isFetching && !!search?.title, |
||||
|
onSearch: (value: string) => { |
||||
|
setSearch((prev) => ({ |
||||
|
...prev, |
||||
|
title: value, |
||||
|
})); |
||||
|
}, |
||||
|
allowClear: true, |
||||
|
onChange: (e) => { |
||||
|
setSearchKey(e.target?.value); |
||||
|
}, |
||||
|
value: searchKey, |
||||
|
placeholder: t(`${i18nPrefix}.placeholder`, "输入账号管理名称"), |
||||
|
}, |
||||
|
actions: [ |
||||
|
<Tooltip key={"filter"} title={t(`${i18nPrefix}.filter.tooltip`, "高级查询")}> |
||||
|
<Badge count={getValueCount(search)}> |
||||
|
<Button |
||||
|
onClick={() => { |
||||
|
setFilterOpen(true); |
||||
|
}} |
||||
|
icon={<FilterOutlined />} |
||||
|
shape={"circle"} |
||||
|
size={"small"} |
||||
|
/> |
||||
|
</Badge> |
||||
|
</Tooltip>, |
||||
|
<Divider type={"vertical"} key={"divider"} />, |
||||
|
], |
||||
|
}} |
||||
|
scroll={{ |
||||
|
// x: 2500,
|
||||
|
y: "calc(100vh - 290px)", |
||||
|
}} |
||||
|
search={false} |
||||
|
onRow={(record) => { |
||||
|
return { |
||||
|
className: cx({ |
||||
|
// 'ant-table-row-selected': currentWebsiteDnsAccount?.id === record.id
|
||||
|
}), |
||||
|
onClick: () => { |
||||
|
setWebsiteDnsAccount(record as any); |
||||
|
}, |
||||
|
}; |
||||
|
}} |
||||
|
dateFormatter="string" |
||||
|
loading={isLoading || isFetching} |
||||
|
dataSource={data?.rows ?? []} |
||||
|
columns={columns} |
||||
|
options={{ |
||||
|
reload: () => { |
||||
|
refetch(); |
||||
|
}, |
||||
|
}} |
||||
|
pagination={{ |
||||
|
total: data?.total, |
||||
|
pageSize: search.pageSize, |
||||
|
current: search.page, |
||||
|
onShowSizeChange: (current: number, size: number) => { |
||||
|
setSearch({ |
||||
|
...search, |
||||
|
pageSize: size, |
||||
|
page: current, |
||||
|
}); |
||||
|
}, |
||||
|
onChange: (current, pageSize) => { |
||||
|
setSearch((prev) => { |
||||
|
return { |
||||
|
...prev, |
||||
|
page: current, |
||||
|
pageSize: pageSize, |
||||
|
}; |
||||
|
}); |
||||
|
}, |
||||
|
}} |
||||
|
/> |
||||
|
<BetaSchemaForm |
||||
|
grid={true} |
||||
|
shouldUpdate={false} |
||||
|
width={1000} |
||||
|
form={form} |
||||
|
layout={"vertical"} |
||||
|
scrollToFirstError={true} |
||||
|
title={t( |
||||
|
`${i18nPrefix}.title_${form.getFieldValue("id") !== 0 ? "edit" : "add"}`, |
||||
|
form.getFieldValue("id") !== 0 ? "账号管理编辑" : "账号管理添加", |
||||
|
)} |
||||
|
layoutType={"DrawerForm"} |
||||
|
open={open} |
||||
|
drawerProps={{ |
||||
|
maskClosable: false, |
||||
|
}} |
||||
|
onOpenChange={(open) => { |
||||
|
setOpen(open); |
||||
|
}} |
||||
|
loading={isSubmitting} |
||||
|
// onValuesChange={(values) => {
|
||||
|
//
|
||||
|
// }}
|
||||
|
//disable禁用,enable正常,syncing正在同步中
|
||||
|
onFinish={async (values) => { |
||||
|
values.status = values.status ?'enable': 'disable'; |
||||
|
saveOrUpdate(values); |
||||
|
}} |
||||
|
columns={columns as ProFormColumnsType[]} |
||||
|
/> |
||||
|
|
||||
<BetaSchemaForm |
|
||||
title={t(`${i18nPrefix}.filter.title`, '账号管理高级查询')} |
|
||||
grid={true} |
|
||||
shouldUpdate={false} |
|
||||
width={500} |
|
||||
form={filterForm} |
|
||||
open={openFilter} |
|
||||
onOpenChange={open => { |
|
||||
setFilterOpen(open) |
|
||||
|
<BetaSchemaForm |
||||
|
title={t(`${i18nPrefix}.filter.title`, "账号管理高级查询")} |
||||
|
grid={true} |
||||
|
shouldUpdate={false} |
||||
|
width={500} |
||||
|
form={filterForm} |
||||
|
open={openFilter} |
||||
|
onOpenChange={(open) => { |
||||
|
setFilterOpen(open); |
||||
|
}} |
||||
|
layout={"vertical"} |
||||
|
scrollToFirstError={true} |
||||
|
layoutType={"DrawerForm"} |
||||
|
drawerProps={{ |
||||
|
maskClosable: false, |
||||
|
mask: false, |
||||
|
}} |
||||
|
submitter={{ |
||||
|
searchConfig: { |
||||
|
resetText: t(`${i18nPrefix}.filter.reset`, "清空"), |
||||
|
submitText: t(`${i18nPrefix}.filter.submit`, "查询"), |
||||
|
}, |
||||
|
onReset: () => { |
||||
|
filterForm.resetFields(); |
||||
|
}, |
||||
|
render: (props) => { |
||||
|
return ( |
||||
|
<div style={{ textAlign: "right" }}> |
||||
|
<Space> |
||||
|
<Button |
||||
|
onClick={() => { |
||||
|
props.reset(); |
||||
}} |
}} |
||||
layout={'vertical'} |
|
||||
scrollToFirstError={true} |
|
||||
layoutType={'DrawerForm'} |
|
||||
drawerProps={{ |
|
||||
maskClosable: false, |
|
||||
mask: false, |
|
||||
|
> |
||||
|
{props.searchConfig?.resetText} |
||||
|
</Button> |
||||
|
<Button |
||||
|
type="primary" |
||||
|
onClick={() => { |
||||
|
props.submit(); |
||||
}} |
}} |
||||
submitter={{ |
|
||||
searchConfig: { |
|
||||
resetText: t(`${i18nPrefix}.filter.reset`, '清空'), |
|
||||
submitText: t(`${i18nPrefix}.filter.submit`, '查询'), |
|
||||
}, |
|
||||
onReset: () => { |
|
||||
filterForm.resetFields() |
|
||||
}, |
|
||||
render: (props,) => { |
|
||||
return ( |
|
||||
<div style={{ textAlign: 'right' }}> |
|
||||
<Space> |
|
||||
<Button onClick={() => { |
|
||||
props.reset() |
|
||||
|
|
||||
}}>{props.searchConfig?.resetText}</Button> |
|
||||
<Button type="primary" |
|
||||
onClick={() => { |
|
||||
props.submit() |
|
||||
}} |
|
||||
>{props.searchConfig?.submitText}</Button> |
|
||||
</Space> |
|
||||
</div> |
|
||||
) |
|
||||
}, |
|
||||
|
|
||||
}} |
|
||||
// onValuesChange={(values) => {
|
|
||||
//
|
|
||||
// }}
|
|
||||
|
|
||||
onFinish={async (values) => { |
|
||||
//处理,变成数组
|
|
||||
Object.keys(values).forEach(key => { |
|
||||
if (typeof values[key] === 'string' && values[key].includes(',')) { |
|
||||
values[key] = values[key].split(',') |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
setSearch(values) |
|
||||
|
> |
||||
|
{props.searchConfig?.submitText} |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</div> |
||||
|
); |
||||
|
}, |
||||
|
}} |
||||
|
// onValuesChange={(values) => {
|
||||
|
//
|
||||
|
// }}
|
||||
|
|
||||
}} |
|
||||
columns={unSetColumnRules(columns.filter(item => !item.hideInSearch) as ProFormColumnsType[])}/> |
|
||||
|
onFinish={async (values) => { |
||||
|
//处理,变成数组
|
||||
|
Object.keys(values).forEach((key) => { |
||||
|
if (typeof values[key] === "string" && values[key].includes(",")) { |
||||
|
values[key] = values[key].split(","); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
</ListPageLayout> |
|
||||
) |
|
||||
} |
|
||||
|
setSearch(values); |
||||
|
}} |
||||
|
columns={unSetColumnRules(columns.filter((item) => !item.hideInSearch) as ProFormColumnsType[])} |
||||
|
/> |
||||
|
</ListPageLayout> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
export default WebsiteDnsAccount |
|
||||
|
export default WebsiteDnsAccount; |
@ -1,448 +1,529 @@ |
|||||
import { useTranslation } from '@/i18n.ts' |
|
||||
import { Button, Form, Divider, Space, Tooltip, Badge, Tag, Input, Flex, Select } from 'antd' |
|
||||
import { useAtom, useAtomValue } from 'jotai' |
|
||||
|
import { useTranslation } from "@/i18n.ts"; |
||||
|
import { Button, Form, Divider, Space, Tooltip, Badge, Tag, Input, Flex, Select, Spin } from "antd"; |
||||
|
import { useAtom, useAtomValue } from "jotai"; |
||||
import { |
import { |
||||
deleteWebsiteDomainAtom, |
deleteWebsiteDomainAtom, |
||||
saveOrUpdateWebsiteDomainAtom, updateGroupWebsiteDomainAtom, |
|
||||
updateRemarkWebsiteDomainAtom, updateTagWebsiteDomainAtom, |
|
||||
|
saveOrUpdateWebsiteDomainAtom, |
||||
|
updateGroupWebsiteDomainAtom, |
||||
|
updateRemarkWebsiteDomainAtom, |
||||
|
updateTagWebsiteDomainAtom, |
||||
websiteDomainAtom, |
websiteDomainAtom, |
||||
websiteDomainsAtom, |
websiteDomainsAtom, |
||||
websiteDomainSearchAtom, |
websiteDomainSearchAtom, |
||||
} from '@/store/websites/domain' |
|
||||
import { useEffect, useMemo, useState } from 'react' |
|
||||
import Action from '@/components/action/Action.tsx' |
|
||||
import { |
|
||||
BetaSchemaForm, |
|
||||
ProColumns, |
|
||||
ProFormColumnsType, |
|
||||
} from '@ant-design/pro-components' |
|
||||
import ListPageLayout from '@/layout/ListPageLayout.tsx' |
|
||||
import { useStyle } from './style' |
|
||||
import { FilterOutlined } from '@ant-design/icons' |
|
||||
import { getValueCount, unSetColumnRules } from '@/utils' |
|
||||
import { Table as ProTable } from '@/components/table' |
|
||||
import { Link } from '@tanstack/react-router' |
|
||||
import Popconfirm from '@/components/popconfirm' |
|
||||
import { accountStatus, accountStatusColor } from '@/store/websites/dns_account.ts' |
|
||||
import Icon from '@/components/icon' |
|
||||
import { useDialog } from '@/components/dialog' |
|
||||
import { dnsListAtom } from '@/store/websites/dns.ts' |
|
||||
import ModalPro from '@/components/modal-pro' |
|
||||
import { domainGroupsAtom } from '@/store/websites/domain_groups.ts' |
|
||||
import NameServer from '@/pages/websites/domain/components/NameServer.tsx' |
|
||||
|
} from "@/store/websites/domain"; |
||||
|
import { useEffect, useMemo, useState } from "react"; |
||||
|
import Action from "@/components/action/Action.tsx"; |
||||
|
import { BetaSchemaForm, ProColumns, ProFormColumnsType } from "@ant-design/pro-components"; |
||||
|
import ListPageLayout from "@/layout/ListPageLayout.tsx"; |
||||
|
import { useStyle } from "./style"; |
||||
|
import { FilterOutlined } from "@ant-design/icons"; |
||||
|
import { getValueCount, unSetColumnRules } from "@/utils"; |
||||
|
import { Table as ProTable } from "@/components/table"; |
||||
|
import { Link, useNavigate } from "@tanstack/react-router"; |
||||
|
import Popconfirm from "@/components/popconfirm"; |
||||
|
import { accountStatus, accountStatusColor } from "@/store/websites/dns_account.ts"; |
||||
|
import Icon from "@/components/icon"; |
||||
|
import { useDialog } from "@/components/dialog"; |
||||
|
import { dnsListAtom } from "@/store/websites/dns.ts"; |
||||
|
import ModalPro from "@/components/modal-pro"; |
||||
|
import { domainGroupsAtom } from "@/store/websites/domain_groups.ts"; |
||||
|
import NameServer from "@/pages/websites/domain/components/NameServer.tsx"; |
||||
|
import Switch from "@/components/switch"; |
||||
|
|
||||
const i18nPrefix = 'websites.domain.list' |
|
||||
|
const i18nPrefix = "websites.domain.list"; |
||||
|
|
||||
const WebsiteDomain = () => { |
const WebsiteDomain = () => { |
||||
|
const { styles, cx } = useStyle(); |
||||
|
const { t } = useTranslation(); |
||||
|
const [form] = Form.useForm(); |
||||
|
const [filterForm] = Form.useForm(); |
||||
|
const navigate = useNavigate(); |
||||
|
const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateWebsiteDomainAtom); |
||||
|
const { mutate: updateRemark } = useAtomValue(updateRemarkWebsiteDomainAtom); |
||||
|
const { mutate: updateTags } = useAtomValue(updateTagWebsiteDomainAtom); |
||||
|
const { mutate: updateGroup } = useAtomValue(updateGroupWebsiteDomainAtom); |
||||
|
const [search, setSearch] = useAtom(websiteDomainSearchAtom); |
||||
|
const [currentWebsiteDomain, setWebsiteDomain] = useAtom(websiteDomainAtom); |
||||
|
const { data, isFetching, isLoading, refetch } = useAtomValue(websiteDomainsAtom); |
||||
|
const { data: groupData, isFetching: isGroupLoading } = useAtomValue(domainGroupsAtom); |
||||
|
|
||||
const { styles, cx } = useStyle() |
|
||||
const { t } = useTranslation() |
|
||||
const [ form ] = Form.useForm() |
|
||||
const [ filterForm ] = Form.useForm() |
|
||||
const { mutate: saveOrUpdate, isPending: isSubmitting, isSuccess } = useAtomValue(saveOrUpdateWebsiteDomainAtom) |
|
||||
const { mutate: updateRemark } = useAtomValue(updateRemarkWebsiteDomainAtom) |
|
||||
const { mutate: updateTags } = useAtomValue(updateTagWebsiteDomainAtom) |
|
||||
const { mutate: updateGroup } = useAtomValue(updateGroupWebsiteDomainAtom) |
|
||||
const [ search, setSearch ] = useAtom(websiteDomainSearchAtom) |
|
||||
const [ currentWebsiteDomain, setWebsiteDomain ] = useAtom(websiteDomainAtom) |
|
||||
const { data, isFetching, isLoading, refetch } = useAtomValue(websiteDomainsAtom) |
|
||||
const { data: groupData, isFetching: isGroupLoading } = useAtomValue(domainGroupsAtom) |
|
||||
|
|
||||
const { mutate: deleteWebsiteDomain, isPending: isDeleting } = useAtomValue(deleteWebsiteDomainAtom) |
|
||||
const { data: dnsData } = useAtomValue(dnsListAtom) |
|
||||
|
const { mutate: deleteWebsiteDomain, isPending: isDeleting } = useAtomValue(deleteWebsiteDomainAtom); |
||||
|
const { data: dnsData } = useAtomValue(dnsListAtom); |
||||
|
|
||||
const [ open, setOpen ] = useState(false) |
|
||||
const [ openFilter, setFilterOpen ] = useState(false) |
|
||||
const [ searchKey, setSearchKey ] = useState(search?.title) |
|
||||
|
const [open, setOpen] = useState(false); |
||||
|
const [openFilter, setFilterOpen] = useState(false); |
||||
|
const [searchKey, setSearchKey] = useState(search?.title); |
||||
|
|
||||
const [ , dialog, openDialog ] = useDialog({ |
|
||||
title: '编辑备注', |
|
||||
children: <Form form={form}> |
|
||||
<Form.Item name={'remark'} |
|
||||
label={t(`${i18nPrefix}.domain.columns.remark`, '备注信息')}> |
|
||||
<Input/> |
|
||||
</Form.Item> |
|
||||
</Form>, |
|
||||
|
const [, dialog, openDialog] = useDialog({ |
||||
|
title: "编辑备注", |
||||
|
children: ( |
||||
|
<Form form={form}> |
||||
|
<Form.Item name={"remark"} label={t(`${i18nPrefix}.domain.columns.remark`, "备注信息")}> |
||||
|
<Input /> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
), |
||||
onOk: () => { |
onOk: () => { |
||||
const id = form.getFieldValue('id') |
|
||||
const remark = form.getFieldValue('remark') |
|
||||
return updateRemark({ remark, id } as any) |
|
||||
} |
|
||||
}) |
|
||||
|
const id = form.getFieldValue("id"); |
||||
|
const remark = form.getFieldValue("remark"); |
||||
|
return updateRemark({ remark, id } as any); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
const columns = useMemo(() => { |
const columns = useMemo(() => { |
||||
return [ |
return [ |
||||
{ |
{ |
||||
title: 'ID', |
|
||||
dataIndex: 'id', |
|
||||
|
title: "ID", |
||||
|
dataIndex: "id", |
||||
hideInTable: true, |
hideInTable: true, |
||||
hideInSearch: true, |
hideInSearch: true, |
||||
formItemProps: { hidden: true } |
|
||||
|
formItemProps: { hidden: true }, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.name`, '域名'), |
|
||||
dataIndex: 'name', |
|
||||
|
title: t(`${i18nPrefix}.columns.name`, "域名"), |
||||
|
dataIndex: "name", |
||||
width: 300, |
width: 300, |
||||
fieldProps: { |
fieldProps: { |
||||
style: { width: '100%' } |
|
||||
|
style: { width: "100%" }, |
||||
}, |
}, |
||||
render(_text, record) { |
render(_text, record) { |
||||
const edit = <Icon className={'hover'} |
|
||||
onClick={() => { |
|
||||
form.setFieldsValue(record) |
|
||||
openDialog(record) |
|
||||
}} |
|
||||
style={{ paddingBlockStart: 0 }} type={'EditTwo'} size={14}/> |
|
||||
return <Flex vertical={true} style={{ paddingInlineStart: 5 }}> |
|
||||
<Space> |
|
||||
<Link to={`/websites/record?id=${record.id}`}>{record.name}</Link> |
|
||||
{edit} |
|
||||
</Space> |
|
||||
<Flex className={'color-gray'}>{record.remark}</Flex> |
|
||||
</Flex> |
|
||||
} |
|
||||
|
const edit = ( |
||||
|
<Icon |
||||
|
className={"hover"} |
||||
|
onClick={() => { |
||||
|
form.setFieldsValue(record); |
||||
|
openDialog(record); |
||||
|
}} |
||||
|
style={{ paddingBlockStart: 0 }} |
||||
|
type={"EditTwo"} |
||||
|
size={14} |
||||
|
/> |
||||
|
); |
||||
|
return ( |
||||
|
<Flex vertical={true} style={{ paddingInlineStart: 5 }}> |
||||
|
<Space> |
||||
|
<Link to={`/websites/record?id=${record.id}`}>{record.name}</Link> |
||||
|
{edit} |
||||
|
</Space> |
||||
|
<Flex className={"color-gray"}>{record.remark}</Flex> |
||||
|
</Flex> |
||||
|
); |
||||
|
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.record_count`, '记录数'), |
|
||||
dataIndex: 'record_count', |
|
||||
|
title: t(`${i18nPrefix}.columns.record_count`, "记录数"), |
||||
|
dataIndex: "record_count", |
||||
hideInForm: true, |
hideInForm: true, |
||||
hideInSearch: true, |
hideInSearch: true, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.dns_account_id`, 'DNS账号'), |
|
||||
dataIndex: 'dns_account_id', |
|
||||
valueType: 'select', |
|
||||
|
title: t(`${i18nPrefix}.columns.dns_account_id`, "DNS账号"), |
||||
|
dataIndex: "dns_account_id", |
||||
|
valueType: "select", |
||||
fieldProps: { |
fieldProps: { |
||||
options: dnsData?.rows?.map?.(item => { |
|
||||
|
options: dnsData?.rows?.map?.((item) => { |
||||
return { |
return { |
||||
data: item, |
data: item, |
||||
label: item.name, |
label: item.name, |
||||
value: item.id, |
value: item.id, |
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
}; |
||||
|
}), |
||||
|
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.status`, '状态'), |
|
||||
dataIndex: 'status', |
|
||||
|
title: t(`${i18nPrefix}.columns.status`, "状态"), |
||||
|
dataIndex: "status", |
||||
hideInForm: true, |
hideInForm: true, |
||||
valueType: 'select', |
|
||||
|
valueType: "select", |
||||
valueEnum: accountStatus, |
valueEnum: accountStatus, |
||||
render(_dom, record) { |
render(_dom, record) { |
||||
const loading = [ 'pending', 'syncing' ].includes(record.status) ? |
|
||||
<Icon type={'LoadingTwo'} size={14} isLoading={true}/> : null |
|
||||
return <Tag |
|
||||
style={{ paddingInline: 5 }} |
|
||||
color={accountStatusColor[record.status]}> |
|
||||
<div style={{ display: 'inline-flex', justifyContent: 'center', alignItems: 'center' }}> |
|
||||
<span style={{ paddingInlineEnd: 3 }}> {t(`websites.common.status.${record.status!}`, record.status + '')} |
|
||||
</span> |
|
||||
{loading} |
|
||||
</div> |
|
||||
</Tag> |
|
||||
} |
|
||||
|
switch (record.status) { |
||||
|
//active活动,pending等待,delete已经删除,disable禁用,syn正在同步
|
||||
|
case "enable": |
||||
|
case "active": |
||||
|
return ( |
||||
|
<Tag style={{ paddingInline: 5 }} color={accountStatusColor[record.status]}> |
||||
|
<div style={{ display: "inline-flex", justifyContent: "center", alignItems: "center" }}> |
||||
|
<span style={{ paddingInlineEnd: 3 }}> |
||||
|
{t(`websites.common.status.${record.status!}`, record.status + "")} |
||||
|
</span> |
||||
|
</div> |
||||
|
</Tag> |
||||
|
); |
||||
|
case "pending": |
||||
|
// return <Icon type={"LoadingTwo"} size={14} isLoading={true} />;
|
||||
|
return ( |
||||
|
<div className={cx("loadingStyle")}> |
||||
|
<Spin tip={t(`${i18nPrefix}.columns.pending`, "等待")} size="small"></Spin> |
||||
|
<div className={cx("loadingStyle_table")}>{t(`${i18nPrefix}.columns.syncing`, "等待")}</div> |
||||
|
</div> |
||||
|
); |
||||
|
case "delete": |
||||
|
case "disable": |
||||
|
return ( |
||||
|
<Tag style={{ paddingInline: 5 }} color={accountStatusColor[record.status]}> |
||||
|
<div style={{ display: "inline-flex", justifyContent: "center", alignItems: "center" }}> |
||||
|
<span style={{ paddingInlineEnd: 3 }}> |
||||
|
{t(`websites.common.status.${record.status!}`, record.status + "")} |
||||
|
</span> |
||||
|
</div> |
||||
|
</Tag> |
||||
|
); |
||||
|
case "syncing": |
||||
|
return ( |
||||
|
<div className={cx("loadingStyle")}> |
||||
|
<Spin tip={t(`${i18nPrefix}.columns.syncing`, "同步中")} size="small"></Spin> |
||||
|
<div className={cx("loadingStyle_table")}>{t(`${i18nPrefix}.columns.syncing`, "同步中")}</div> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.nameservers`, 'DNS服务器地址'), |
|
||||
dataIndex: 'nameservers', |
|
||||
|
title: t(`${i18nPrefix}.columns.nameservers`, "DNS服务器地址"), |
||||
|
dataIndex: "nameservers", |
||||
width: 150, |
width: 150, |
||||
hideInSearch: true, |
hideInSearch: true, |
||||
hideInForm: true, |
hideInForm: true, |
||||
render(_dom, record) { |
render(_dom, record) { |
||||
return <NameServer data={record}/> |
|
||||
} |
|
||||
|
return <NameServer data={record} />; |
||||
|
}, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.created`, '创建时间'), |
|
||||
dataIndex: 'created', |
|
||||
|
title: t(`${i18nPrefix}.columns.created`, "创建时间"), |
||||
|
dataIndex: "created", |
||||
hideInSearch: true, |
hideInSearch: true, |
||||
hideInForm: true, |
hideInForm: true, |
||||
}, |
}, |
||||
{ |
{ |
||||
title: t(`${i18nPrefix}.columns.option`, '操作'), |
|
||||
key: 'option', |
|
||||
valueType: 'option', |
|
||||
fixed: 'right', |
|
||||
|
title: t(`${i18nPrefix}.columns.option`, "操作"), |
||||
|
key: "option", |
||||
|
valueType: "option", |
||||
|
fixed: "right", |
||||
render: (_, record) => [ |
render: (_, record) => [ |
||||
<Link to={`/websites/record?id=${record.id}`}>解析设置</Link>, |
|
||||
|
|
||||
/*<Action key="edit" |
|
||||
as={'a'} |
|
||||
onClick={() => { |
|
||||
// form.setFieldsValue(record)
|
|
||||
// setOpen(true)
|
|
||||
|
|
||||
}}>{t('actions.recordSet', '解析设置')}</Action>,*/ |
|
||||
<Divider type={'vertical'}/>, |
|
||||
<Action key="sync" |
|
||||
as={'a'} |
|
||||
disabled={record.status === 'syncing'} |
|
||||
onClick={() => { |
|
||||
|
// <Link to={`/cert/record?id=${record.id}`}>解析设置</Link>,
|
||||
|
|
||||
}}>{t('actions.sync', '同步')}</Action>, |
|
||||
|
<Action |
||||
|
key="edit" |
||||
|
as={"a"} |
||||
|
onClick={() => { |
||||
|
form.setFieldsValue(record); |
||||
|
setOpen(true); |
||||
|
}} |
||||
|
> |
||||
|
{t("actions.recordSet", "设置")} |
||||
|
</Action>, |
||||
|
<Divider type={"vertical"} />, |
||||
|
<Action |
||||
|
key="record" |
||||
|
as={"a"} |
||||
|
onClick={() => { |
||||
|
navigate({ |
||||
|
to: `/cert/record`, |
||||
|
search: { id: record.id }, |
||||
|
}); |
||||
|
}} |
||||
|
> |
||||
|
{t("actions.recordSet", "记录")} |
||||
|
</Action>, |
||||
|
<Divider type={"vertical"} />, |
||||
|
<Action key="sync" as={"a"} disabled={record.status === "syncing"} onClick={() => {}}> |
||||
|
{t("actions.sync", "同步")} |
||||
|
</Action>, |
||||
|
|
||||
<Divider type={'vertical'}/>, |
|
||||
|
<Divider type={"vertical"} />, |
||||
<Popconfirm |
<Popconfirm |
||||
key={'del_confirm'} |
|
||||
disabled={isDeleting} |
|
||||
onConfirm={() => { |
|
||||
deleteWebsiteDomain([ record.id ]) |
|
||||
}} |
|
||||
title={t('message.deleteConfirm')}> |
|
||||
{t('actions.delete', '删除')} |
|
||||
</Popconfirm> |
|
||||
] |
|
||||
} |
|
||||
] as ProColumns[] |
|
||||
}, [ isDeleting, currentWebsiteDomain, search, dnsData ]) |
|
||||
|
key={"del_confirm"} |
||||
|
disabled={isDeleting} |
||||
|
onConfirm={() => { |
||||
|
deleteWebsiteDomain([record.id]); |
||||
|
}} |
||||
|
title={t("message.deleteConfirm")} |
||||
|
> |
||||
|
{t("actions.delete", "删除")} |
||||
|
</Popconfirm>, |
||||
|
], |
||||
|
}, |
||||
|
] as ProColumns[]; |
||||
|
}, [isDeleting, currentWebsiteDomain, search, dnsData]); |
||||
|
|
||||
useEffect(() => { |
useEffect(() => { |
||||
|
const queryParams = new URLSearchParams(location.search); |
||||
|
const dnsAccountId = queryParams.get("id"); |
||||
|
|
||||
setSearchKey(search?.title) |
|
||||
filterForm.setFieldsValue(search) |
|
||||
|
if (dnsAccountId) { |
||||
|
setSearch((prev) => ({ |
||||
|
...prev, |
||||
|
name: "", |
||||
|
dns_account_id: dnsAccountId, |
||||
|
})); |
||||
|
} |
||||
|
}, [location.search]); |
||||
|
|
||||
}, [ search ]) |
|
||||
|
useEffect(() => { |
||||
|
setSearchKey(search?.title); |
||||
|
filterForm.setFieldsValue(search); |
||||
|
}, [search]); |
||||
|
|
||||
useEffect(() => { |
useEffect(() => { |
||||
if (isSuccess) { |
if (isSuccess) { |
||||
setOpen(false) |
|
||||
|
setOpen(false); |
||||
} |
} |
||||
}, [ isSuccess ]) |
|
||||
|
}, [isSuccess]); |
||||
|
|
||||
return ( |
return ( |
||||
<ListPageLayout className={styles.container}> |
|
||||
<ProTable |
|
||||
rowKey="id" |
|
||||
headerTitle={ |
|
||||
<Space> |
|
||||
<Button key={'add'} |
|
||||
onClick={() => { |
|
||||
form.resetFields() |
|
||||
form.setFieldsValue({ |
|
||||
id: 0, |
|
||||
}) |
|
||||
setOpen(true) |
|
||||
}} |
|
||||
type={'primary'}>{t(`${i18nPrefix}.add`, '添加域名')}</Button> |
|
||||
</Space> |
|
||||
} |
|
||||
tableAlertRender={(props) => { |
|
||||
return <Space> |
|
||||
<ModalPro |
|
||||
alterType={'confirm'} |
|
||||
title={'删除域名提示'} |
|
||||
content={<span>确认删除此域名?<br/>删除域名,解析记录会同步删除,且无法恢复。</span>} |
|
||||
onOk={() => { |
|
||||
deleteWebsiteDomain(props.selectedRows?.map(item => item.id)) |
|
||||
}} |
|
||||
> |
|
||||
<Button disabled={props.selectedRows?.length == 0}>{t('actions.delete', '删除')}</Button> |
|
||||
</ModalPro> |
|
||||
<ModalPro |
|
||||
alterType={'dialog'} |
|
||||
title={t(`${i18nPrefix}.group.title`, '移动分组')} |
|
||||
content={<> |
|
||||
<Form form={form}> |
|
||||
<Form.Item |
|
||||
name={'group_id'} |
|
||||
label={t(`${i18nPrefix}.group.columns.group`, '移动分组')}> |
|
||||
<Select |
|
||||
loading={isGroupLoading} |
|
||||
options={ |
|
||||
[ |
|
||||
{ |
|
||||
label: t(`${i18nPrefix}.group.default`, '默认分组'), |
|
||||
value: 0, |
|
||||
}, |
|
||||
...(groupData?.rows?.map(item => { |
|
||||
return { |
|
||||
label: item.name, |
|
||||
value: item.id, |
|
||||
} |
|
||||
}) ?? []) |
|
||||
] |
|
||||
}/> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</>} |
|
||||
onLoad={() => { |
|
||||
form.setFieldsValue({ group_id: 0 }) |
|
||||
}} |
|
||||
onOk={() => { |
|
||||
const group_id = form.getFieldValue('group_id') |
|
||||
updateGroup({ id: props.selectedRows?.map(item => item.id), group_id }) |
|
||||
}} |
|
||||
> |
|
||||
<Button disabled={props.selectedRows?.length == 0}>{t(`${i18nPrefix}.actions.changeGroup`, '更换分组')}</Button> |
|
||||
</ModalPro> |
|
||||
</Space> |
|
||||
}} |
|
||||
tableAlertOptionRender={false} |
|
||||
toolbar={{ |
|
||||
search: { |
|
||||
loading: isFetching && !!search?.title, |
|
||||
onSearch: (value: string) => { |
|
||||
setSearch(prev => ({ |
|
||||
...prev, |
|
||||
title: value |
|
||||
})) |
|
||||
}, |
|
||||
allowClear: true, |
|
||||
onChange: (e) => { |
|
||||
setSearchKey(e.target?.value) |
|
||||
}, |
|
||||
value: searchKey, |
|
||||
placeholder: t(`${i18nPrefix}.placeholder`, '输入域名管理名称') |
|
||||
}, |
|
||||
actions: [ |
|
||||
<Tooltip key={'filter'} title={t(`${i18nPrefix}.filter.tooltip`, '高级查询')}> |
|
||||
<Badge count={getValueCount(search)}> |
|
||||
<Button |
|
||||
onClick={() => { |
|
||||
setFilterOpen(true) |
|
||||
}} |
|
||||
icon={<FilterOutlined/>} shape={'circle'} size={'small'}/> |
|
||||
</Badge> |
|
||||
</Tooltip>, |
|
||||
<Divider type={'vertical'} key={'divider'}/>, |
|
||||
|
|
||||
] |
|
||||
}} |
|
||||
scroll={{ |
|
||||
// x: 2500,
|
|
||||
y: 'calc(100vh - 290px)' |
|
||||
}} |
|
||||
search={false} |
|
||||
onRow={(record) => { |
|
||||
return { |
|
||||
className: cx({ |
|
||||
// 'ant-table-row-selected': currentWebsiteDomain?.id === record.id
|
|
||||
}), |
|
||||
onClick: () => { |
|
||||
setWebsiteDomain(record) |
|
||||
} |
|
||||
} |
|
||||
}} |
|
||||
rowSelection={{ |
|
||||
type: 'checkbox', |
|
||||
alwaysShowAlert: true, |
|
||||
}} |
|
||||
dateFormatter="string" |
|
||||
loading={isLoading || isFetching} |
|
||||
dataSource={data?.rows ?? []} |
|
||||
columns={columns} |
|
||||
options={{ |
|
||||
reload: () => { |
|
||||
refetch() |
|
||||
}, |
|
||||
}} |
|
||||
pagination={{ |
|
||||
total: data?.total, |
|
||||
pageSize: search.pageSize, |
|
||||
current: search.page, |
|
||||
onShowSizeChange: (current: number, size: number) => { |
|
||||
setSearch({ |
|
||||
...search, |
|
||||
pageSize: size, |
|
||||
page: current |
|
||||
}) |
|
||||
}, |
|
||||
onChange: (current, pageSize) => { |
|
||||
setSearch(prev => { |
|
||||
return { |
|
||||
...prev, |
|
||||
page: current, |
|
||||
pageSize: pageSize, |
|
||||
} |
|
||||
}) |
|
||||
}, |
|
||||
}} |
|
||||
/> |
|
||||
<BetaSchemaForm |
|
||||
grid={true} |
|
||||
shouldUpdate={false} |
|
||||
width={1000} |
|
||||
form={form} |
|
||||
layout={'vertical'} |
|
||||
scrollToFirstError={true} |
|
||||
title={t(`${i18nPrefix}.title_${form.getFieldValue('id') !== 0 ? 'edit' : 'add'}`, form.getFieldValue('id') !== 0 ? '域名管理编辑' : '域名管理添加')} |
|
||||
layoutType={'DrawerForm'} |
|
||||
open={open} |
|
||||
drawerProps={{ |
|
||||
maskClosable: false, |
|
||||
}} |
|
||||
onOpenChange={(open) => { |
|
||||
setOpen(open) |
|
||||
}} |
|
||||
loading={isSubmitting} |
|
||||
|
|
||||
onFinish={async (values) => { |
|
||||
saveOrUpdate(values) |
|
||||
}} |
|
||||
columns={columns as ProFormColumnsType[]}/> |
|
||||
<BetaSchemaForm |
|
||||
title={t(`${i18nPrefix}.filter.title`, '域名管理高级查询')} |
|
||||
grid={true} |
|
||||
shouldUpdate={false} |
|
||||
width={500} |
|
||||
form={filterForm} |
|
||||
open={openFilter} |
|
||||
onOpenChange={open => { |
|
||||
setFilterOpen(open) |
|
||||
}} |
|
||||
layout={'vertical'} |
|
||||
scrollToFirstError={true} |
|
||||
layoutType={'DrawerForm'} |
|
||||
drawerProps={{ |
|
||||
maskClosable: false, |
|
||||
mask: false, |
|
||||
}} |
|
||||
submitter={{ |
|
||||
searchConfig: { |
|
||||
resetText: t(`${i18nPrefix}.filter.reset`, '清空'), |
|
||||
submitText: t(`${i18nPrefix}.filter.submit`, '查询'), |
|
||||
}, |
|
||||
onReset: () => { |
|
||||
filterForm.resetFields() |
|
||||
}, |
|
||||
render: (props,) => { |
|
||||
return ( |
|
||||
<div style={{ textAlign: 'right' }}> |
|
||||
<Space> |
|
||||
<Button onClick={() => { |
|
||||
props.reset() |
|
||||
|
|
||||
}}>{props.searchConfig?.resetText}</Button> |
|
||||
<Button type="primary" |
|
||||
onClick={() => { |
|
||||
props.submit() |
|
||||
}} |
|
||||
>{props.searchConfig?.submitText}</Button> |
|
||||
</Space> |
|
||||
</div> |
|
||||
) |
|
||||
}, |
|
||||
|
|
||||
|
<ListPageLayout className={styles.container}> |
||||
|
<ProTable |
||||
|
rowKey="id" |
||||
|
headerTitle={ |
||||
|
<Space> |
||||
|
<Button |
||||
|
key={"add"} |
||||
|
onClick={() => { |
||||
|
form.resetFields(); |
||||
|
form.setFieldsValue({ |
||||
|
id: 0, |
||||
|
}); |
||||
|
setOpen(true); |
||||
|
}} |
||||
|
type={"primary"} |
||||
|
> |
||||
|
{t(`${i18nPrefix}.add`, "添加域名")} |
||||
|
</Button> |
||||
|
</Space> |
||||
|
} |
||||
|
tableAlertRender={(props) => { |
||||
|
return ( |
||||
|
<Space> |
||||
|
<ModalPro |
||||
|
alterType={"confirm"} |
||||
|
title={"删除域名提示"} |
||||
|
content={ |
||||
|
<span> |
||||
|
确认删除此域名? |
||||
|
<br /> |
||||
|
删除域名,解析记录会同步删除,且无法恢复。 |
||||
|
</span> |
||||
|
} |
||||
|
onOk={() => { |
||||
|
deleteWebsiteDomain(props.selectedRows?.map((item) => item.id)); |
||||
|
}} |
||||
|
> |
||||
|
<Button disabled={props.selectedRows?.length == 0}>{t("actions.delete", "删除")}</Button> |
||||
|
</ModalPro> |
||||
|
<ModalPro |
||||
|
alterType={"dialog"} |
||||
|
title={t(`${i18nPrefix}.group.title`, "移动分组")} |
||||
|
content={ |
||||
|
<> |
||||
|
<Form form={form}> |
||||
|
<Form.Item name={"group_id"} label={t(`${i18nPrefix}.group.columns.group`, "移动分组")}> |
||||
|
<Select |
||||
|
loading={isGroupLoading} |
||||
|
options={[ |
||||
|
{ |
||||
|
label: t(`${i18nPrefix}.group.default`, "默认分组"), |
||||
|
value: 0, |
||||
|
}, |
||||
|
...(groupData?.rows?.map((item) => { |
||||
|
return { |
||||
|
label: item.name, |
||||
|
value: item.id, |
||||
|
}; |
||||
|
}) ?? []), |
||||
|
]} |
||||
|
/> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</> |
||||
|
} |
||||
|
onLoad={() => { |
||||
|
form.setFieldsValue({ group_id: 0 }); |
||||
|
}} |
||||
|
onOk={() => { |
||||
|
const group_id = form.getFieldValue("group_id"); |
||||
|
updateGroup({ id: props.selectedRows?.map((item) => item.id), group_id }); |
||||
|
}} |
||||
|
> |
||||
|
<Button disabled={props.selectedRows?.length == 0}> |
||||
|
{t(`${i18nPrefix}.actions.changeGroup`, "更换分组")} |
||||
|
</Button> |
||||
|
</ModalPro> |
||||
|
</Space> |
||||
|
); |
||||
|
}} |
||||
|
tableAlertOptionRender={false} |
||||
|
toolbar={{ |
||||
|
search: { |
||||
|
loading: isFetching && !!search?.title, |
||||
|
onSearch: (value: string) => { |
||||
|
setSearch((prev) => ({ |
||||
|
...prev, |
||||
|
title: value, |
||||
|
})); |
||||
|
}, |
||||
|
allowClear: true, |
||||
|
onChange: (e) => { |
||||
|
setSearchKey(e.target?.value); |
||||
|
}, |
||||
|
value: searchKey, |
||||
|
placeholder: t(`${i18nPrefix}.placeholder`, "输入域名管理名称"), |
||||
|
}, |
||||
|
actions: [ |
||||
|
<Tooltip key={"filter"} title={t(`${i18nPrefix}.filter.tooltip`, "高级查询")}> |
||||
|
<Badge count={getValueCount(search)}> |
||||
|
<Button |
||||
|
onClick={() => { |
||||
|
setFilterOpen(true); |
||||
|
}} |
||||
|
icon={<FilterOutlined />} |
||||
|
shape={"circle"} |
||||
|
size={"small"} |
||||
|
/> |
||||
|
</Badge> |
||||
|
</Tooltip>, |
||||
|
<Divider type={"vertical"} key={"divider"} />, |
||||
|
], |
||||
|
}} |
||||
|
scroll={{ |
||||
|
// x: 2500,
|
||||
|
y: "calc(100vh - 290px)", |
||||
|
}} |
||||
|
search={false} |
||||
|
onRow={(record) => { |
||||
|
return { |
||||
|
className: cx({ |
||||
|
// 'ant-table-row-selected': currentWebsiteDomain?.id === record.id
|
||||
|
}), |
||||
|
onClick: () => { |
||||
|
setWebsiteDomain(record); |
||||
|
}, |
||||
|
}; |
||||
|
}} |
||||
|
rowSelection={{ |
||||
|
type: "checkbox", |
||||
|
alwaysShowAlert: true, |
||||
|
}} |
||||
|
dateFormatter="string" |
||||
|
loading={isLoading || isFetching} |
||||
|
dataSource={data?.rows ?? []} |
||||
|
columns={columns} |
||||
|
options={{ |
||||
|
reload: () => { |
||||
|
refetch(); |
||||
|
}, |
||||
|
}} |
||||
|
pagination={{ |
||||
|
total: data?.total, |
||||
|
pageSize: search.pageSize, |
||||
|
current: search.page, |
||||
|
onShowSizeChange: (current: number, size: number) => { |
||||
|
setSearch({ |
||||
|
...search, |
||||
|
pageSize: size, |
||||
|
page: current, |
||||
|
}); |
||||
|
}, |
||||
|
onChange: (current, pageSize) => { |
||||
|
setSearch((prev) => { |
||||
|
return { |
||||
|
...prev, |
||||
|
page: current, |
||||
|
pageSize: pageSize, |
||||
|
}; |
||||
|
}); |
||||
|
}, |
||||
|
}} |
||||
|
/> |
||||
|
<BetaSchemaForm |
||||
|
grid={true} |
||||
|
shouldUpdate={false} |
||||
|
width={1000} |
||||
|
form={form} |
||||
|
layout={"vertical"} |
||||
|
scrollToFirstError={true} |
||||
|
title={t( |
||||
|
`${i18nPrefix}.title_${form.getFieldValue("id") !== 0 ? "edit" : "add"}`, |
||||
|
form.getFieldValue("id") !== 0 ? "域名管理编辑" : "域名管理添加", |
||||
|
)} |
||||
|
layoutType={"DrawerForm"} |
||||
|
open={open} |
||||
|
drawerProps={{ |
||||
|
maskClosable: false, |
||||
|
}} |
||||
|
onOpenChange={(open) => { |
||||
|
setOpen(open); |
||||
|
}} |
||||
|
loading={isSubmitting} |
||||
|
onFinish={async (values) => { |
||||
|
saveOrUpdate(values); |
||||
|
}} |
||||
|
columns={columns as ProFormColumnsType[]} |
||||
|
/> |
||||
|
<BetaSchemaForm |
||||
|
title={t(`${i18nPrefix}.filter.title`, "域名管理高级查询")} |
||||
|
grid={true} |
||||
|
shouldUpdate={false} |
||||
|
width={500} |
||||
|
form={filterForm} |
||||
|
open={openFilter} |
||||
|
onOpenChange={(open) => { |
||||
|
setFilterOpen(open); |
||||
|
}} |
||||
|
layout={"vertical"} |
||||
|
scrollToFirstError={true} |
||||
|
layoutType={"DrawerForm"} |
||||
|
drawerProps={{ |
||||
|
maskClosable: false, |
||||
|
mask: false, |
||||
|
}} |
||||
|
submitter={{ |
||||
|
searchConfig: { |
||||
|
resetText: t(`${i18nPrefix}.filter.reset`, "清空"), |
||||
|
submitText: t(`${i18nPrefix}.filter.submit`, "查询"), |
||||
|
}, |
||||
|
onReset: () => { |
||||
|
filterForm.resetFields(); |
||||
|
}, |
||||
|
render: (props) => { |
||||
|
return ( |
||||
|
<div style={{ textAlign: "right" }}> |
||||
|
<Space> |
||||
|
<Button |
||||
|
onClick={() => { |
||||
|
props.reset(); |
||||
}} |
}} |
||||
|
|
||||
|
|
||||
onFinish={async (values) => { |
|
||||
//处理,变成数组
|
|
||||
Object.keys(values).forEach(key => { |
|
||||
if (typeof values[key] === 'string' && values[key].includes(',')) { |
|
||||
values[key] = values[key].split(',') |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
setSearch(values) |
|
||||
|
|
||||
|
> |
||||
|
{props.searchConfig?.resetText} |
||||
|
</Button> |
||||
|
<Button |
||||
|
type="primary" |
||||
|
onClick={() => { |
||||
|
props.submit(); |
||||
}} |
}} |
||||
columns={unSetColumnRules(columns.filter(item => !item.hideInSearch) as ProFormColumnsType[])}/> |
|
||||
{ |
|
||||
dialog |
|
||||
|
> |
||||
|
{props.searchConfig?.submitText} |
||||
|
</Button> |
||||
|
</Space> |
||||
|
</div> |
||||
|
); |
||||
|
}, |
||||
|
}} |
||||
|
onFinish={async (values) => { |
||||
|
//处理,变成数组
|
||||
|
Object.keys(values).forEach((key) => { |
||||
|
if (typeof values[key] === "string" && values[key].includes(",")) { |
||||
|
values[key] = values[key].split(","); |
||||
} |
} |
||||
</ListPageLayout> |
|
||||
) |
|
||||
} |
|
||||
|
}); |
||||
|
|
||||
|
setSearch(values); |
||||
|
}} |
||||
|
columns={unSetColumnRules(columns.filter((item) => !item.hideInSearch) as ProFormColumnsType[])} |
||||
|
/> |
||||
|
{dialog} |
||||
|
</ListPageLayout> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
export default WebsiteDomain |
|
||||
|
export default WebsiteDomain; |
@ -0,0 +1,52 @@ |
|||||
|
import React, { useMemo } from 'react'; |
||||
|
import { ProTable } from '@ant-design/pro-components'; |
||||
|
import type { ProColumns } from '@ant-design/pro-components'; |
||||
|
|
||||
|
type DataType = { |
||||
|
key: number; |
||||
|
name: string; |
||||
|
age: number; |
||||
|
address: string; |
||||
|
}; |
||||
|
|
||||
|
const data: DataType[] = [ |
||||
|
{ key: 1, name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park' }, |
||||
|
{ key: 2, name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park' }, |
||||
|
{ key: 3, name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park' }, |
||||
|
]; |
||||
|
|
||||
|
const MyTable: React.FC = () => { |
||||
|
const columns: ProColumns<DataType>[] = useMemo(() => [ |
||||
|
{ |
||||
|
title: 'Name', |
||||
|
dataIndex: 'name', |
||||
|
key: 'name', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Age', |
||||
|
dataIndex: 'age', |
||||
|
key: 'age', |
||||
|
}, |
||||
|
{ |
||||
|
title: 'Address', |
||||
|
dataIndex: 'address', |
||||
|
key: 'address', |
||||
|
}, |
||||
|
], []); |
||||
|
|
||||
|
const memoizedData = useMemo(() => data, []); |
||||
|
|
||||
|
return ( |
||||
|
<ProTable<DataType> |
||||
|
columns={columns} |
||||
|
dataSource={memoizedData} |
||||
|
rowKey="key" |
||||
|
search={false} |
||||
|
pagination={{ |
||||
|
pageSize: 5, |
||||
|
}} |
||||
|
/> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default MyTable; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue