Browse Source

完善域名页面

main
dark 4 months ago
parent
commit
0f37ee728a
  1. 53
      src/App.css
  2. 96
      src/pages/websites/domain/components/NameServer.tsx
  3. 15
      src/pages/websites/domain/components/style.ts
  4. 8
      src/service/website/domain_group.ts
  5. 23
      src/service/websites.ts
  6. 2
      src/store/websites/dns_account.ts
  7. 82
      src/store/websites/domain.ts
  8. 90
      src/store/websites/domain_groups.ts
  9. 6
      src/theme/index.ts
  10. 7
      src/types/website/domain.d.ts
  11. 9
      src/types/website/domain_group.d.ts

53
src/App.css

@ -1,47 +1,60 @@
.i-icon { .i-icon {
display: flex;
display: flex;
} }
.ant-tree-iconEle{
.i-icon {
display: inherit;
line-height: 28px;
}
.ant-tree-iconEle {
.i-icon {
display: inherit;
line-height: 28px;
}
} }
.top-breadcrumb { .top-breadcrumb {
.item {
.item {
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
}
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
}
} }
.ant-drawer .ant-drawer-footer{
.ant-drawer .ant-drawer-footer {
background-color: #fcfcfc; background-color: #fcfcfc;
} }
.hover{
.hover {
cursor: pointer; cursor: pointer;
&:hover{
&:hover {
color: #1c7ed6; color: #1c7ed6;
} }
} }
/*灰色*/ /*灰色*/
.color-gray{
.color-gray {
color: #999; color: #999;
} }
.color-65{
color:rgba(0, 0, 0, 0.65);
.color-65 {
color: rgba(0, 0, 0, 0.65);
} }
.color-333{
.color-333 {
color: #333; color: #333;
} }
.text-bold{
.color-green {
color: green;
}
.color-yellow {
color: rgb(250 145 0)
}
.text-bold {
font-weight: bold; font-weight: bold;
} }

96
src/pages/websites/domain/components/NameServer.tsx

@ -0,0 +1,96 @@
import { INameServer, IWebsiteDomain } from '@/types/website/domain'
import { Typography, Popover, Table } from 'antd'
import { memo, useCallback, useMemo } from 'react'
import { useAtomValue } from 'jotai'
import { describeDomainNSAtom } from '@/store/websites/domain.ts'
import {
CheckCircleFilled,
CheckCircleOutlined,
ExclamationCircleFilled,
ExclamationCircleOutlined,
LoadingOutlined
} from '@ant-design/icons'
export interface NameServerProps {
data: IWebsiteDomain
}
interface FormattedDnsData {
expectDnsServers: string;
dnsServers: string;
}
function formatNameServerData(data?: INameServer) {
if (!data) {
return []
}
const formattedData: FormattedDnsData[] = []
const maxLength = Math.max(data.expectDnsServers.length, data.dnsServers.length)
for (let i = 0; i < maxLength; i++) {
formattedData.push({
expectDnsServers: data.expectDnsServers[i] || '',
dnsServers: data.dnsServers[i] || '',
})
}
return formattedData
}
const NameServer = memo(({ data }: NameServerProps) => {
const { data: result, isFetching } = useAtomValue(useMemo(() => describeDomainNSAtom(data?.id), []))
const columns = [
{
title: '当前DNS',
dataIndex: 'dnsServers'
},
{
title: '系统分配DNS',
dataIndex: 'expectDnsServers',
render: (text: string) => {
return <Typography.Text copyable={{ text }}>{text}</Typography.Text>
}
},
]
const content = useCallback(() => {
return (
<Table columns={columns}
style={{ width: 300}}
dataSource={formatNameServerData(result)}
pagination={false}
bordered={true}
size={'small'}
/>
)
}, [ result ])
const title = useCallback(() => {
if (result?.success)
return <span><CheckCircleFilled className={'color-green'} style={{ paddingInlineEnd: 5 }}/>DNS信息配置正确</span>
return <span><ExclamationCircleFilled className={'color-yellow'} style={{ paddingInlineEnd: 5 }}/></span>
}, [ result ])
if (data?.nameservers?.length === 0) {
return null
}
return (
<Popover content={content()} title={title()} trigger="hover">
{isFetching ? <LoadingOutlined/> : null}
{
result?.success ?
<span className={'color-green'}><CheckCircleOutlined style={{ paddingInlineEnd: 5 }}/></span>
: <span className={'color-yellow'}><ExclamationCircleOutlined
style={{ paddingInlineEnd: 5 }}/>{result?.message || '探测超时'}</span>
}
</Popover>
)
})
export default NameServer

15
src/pages/websites/domain/components/style.ts

@ -0,0 +1,15 @@
import { createStyles } from '@/theme'
export const useStyle = createStyles(({ token, css, cx, prefixCls }, props: any) => {
const prefix = `${prefixCls}-${token?.proPrefix}-name-server-component`
const container = css`
.green {
color: green;
}
`
return {
container: cx(prefix, props?.className, container),
}
})

8
src/service/website/domain_group.ts

@ -0,0 +1,8 @@
import { createCURD } from '@/service/base.ts'
import { WebSite } from '@/types/website/domain_group'
const domain_group = {
...createCURD<any, WebSite.IDomainGroup >('/website/group'),
}
export default domain_group

23
src/service/websites.ts

@ -1,7 +1,7 @@
import { createCURD } from '@/service/base.ts' import { createCURD } from '@/service/base.ts'
import { WebSite } from '@/types' import { WebSite } from '@/types'
import request from '@/request.ts' import request from '@/request.ts'
import { IWebsiteDomain } from '@/types/website/domain'
import { IWebsiteDomain, INameServer } from '@/types/website/domain'
import { IWebsiteDnsRecords } from '@/types/website/record' import { IWebsiteDnsRecords } from '@/types/website/record'
import { IWebsiteDnsAccount } from '@/types/website/dns_account' import { IWebsiteDnsAccount } from '@/types/website/dns_account'
@ -32,9 +32,30 @@ const websitesServ = {
}, },
domain: { domain: {
...createCURD<any, IWebsiteDomain>('/website/domain'), ...createCURD<any, IWebsiteDomain>('/website/domain'),
//remark
remark: async (params: { id: string, remark: string }) => {
return request.post<any, any>('/website/domain/remark', params)
},
//tag
tag: async (params: { id: string, tags: string}) => {
return request.post<any, any>('/website/domain/tag', params)
},
//binding
binding: async (params: { id:string , user_id: string }) => {
return request.post<any, any>('/website/domain/binding', params)
},
//group
group: async (params: { id: string[], group_id: string }) => {
return request.post<any, any>('/website/domain/group', params)
},
describeDomainNS: async (params: { id: number }) => {
return request.post<INameServer, any>('/website/domain/describe_domain_ns', params)
},
}, },
record: { record: {
...createCURD<any, IWebsiteDnsRecords>('/website/dns_records'), ...createCURD<any, IWebsiteDnsRecords>('/website/dns_records'),
//
}, },
dnsAccount: { dnsAccount: {
...createCURD<any, IWebsiteDnsAccount>('/website/dns_account'), ...createCURD<any, IWebsiteDnsAccount>('/website/dns_account'),

2
src/store/websites/dns_account.ts

@ -50,7 +50,7 @@ export const websiteDnsAccountIdsAtom = atom<number[]>([])
export const websiteDnsAccountAtom = atom<IWebsiteDnsAccount>(undefined as unknown as IWebsiteDnsAccount) export const websiteDnsAccountAtom = atom<IWebsiteDnsAccount>(undefined as unknown as IWebsiteDnsAccount)
export const websiteDnsAccountSearchAtom = atom<SearchParams>({ export const websiteDnsAccountSearchAtom = atom<SearchParams>({
key: '',
// key: '',
pageSize: 10, pageSize: 10,
page: 1, page: 1,
} as SearchParams) } as SearchParams)

82
src/store/websites/domain.ts

@ -16,10 +16,10 @@ export const websiteDomainIdAtom = atom(0)
export const websiteDomainIdsAtom = atom<number[]>([]) export const websiteDomainIdsAtom = atom<number[]>([])
export const websiteDomainAtom = atom<IWebsiteDomain>(undefined as unknown as IWebsiteDomain )
export const websiteDomainAtom = atom<IWebsiteDomain>(undefined as unknown as IWebsiteDomain)
export const websiteDomainSearchAtom = atom<SearchParams>({ export const websiteDomainSearchAtom = atom<SearchParams>({
key: '',
// key: '',
pageSize: 10, pageSize: 10,
page: 1, page: 1,
} as SearchParams) } as SearchParams)
@ -89,3 +89,81 @@ export const deleteWebsiteDomainAtom = atomWithMutation((get) => {
} }
} }
}) })
//updateRemark
export const updateRemarkWebsiteDomainAtom = atomWithMutation<IApiResult, { id: string, remark: string }>((get) => {
return {
mutationKey: [ 'updateRemarkWebsiteDomain' ],
mutationFn: async (data) => {
return await websitesServ.domain.remark(data)
},
onSuccess: (res) => {
message.success(t('message.editSuccess', '编辑成功'))
//更新列表
get(queryClientAtom).invalidateQueries({ queryKey: [ 'websiteDomains', get(websiteDomainSearchAtom) ] })
return res
}
}
})
//updateTag
export const updateTagWebsiteDomainAtom = atomWithMutation<IApiResult, { id: string, tags: string }>((get) => {
return {
mutationKey: [ 'updateTagWebsiteDomain' ],
mutationFn: async (data) => {
return await websitesServ.domain.tag(data)
},
onSuccess: (res) => {
message.success(t('message.editSuccess', '编辑成功'))
//更新列表
get(queryClientAtom).invalidateQueries({ queryKey: [ 'websiteDomains', get(websiteDomainSearchAtom) ] })
return res
}
}
})
//updateBanding
export const updateBandingWebsiteDomainAtom = atomWithMutation<IApiResult, { id: string, user_id: string }>((get) => {
return {
mutationKey: [ 'updateBandingWebsiteDomain' ],
mutationFn: async (data) => {
return await websitesServ.domain.binding(data)
},
onSuccess: (res) => {
message.success(t('message.editSuccess', '编辑成功'))
//更新列表
get(queryClientAtom).invalidateQueries({ queryKey: [ 'websiteDomains', get(websiteDomainSearchAtom) ] })
return res
}
}
})
//updateGroup
export const updateGroupWebsiteDomainAtom = atomWithMutation<IApiResult, { id: string[], group_id: string }>((get) => {
return {
mutationKey: [ 'updateGroupWebsiteDomain' ],
mutationFn: async (data) => {
return await websitesServ.domain.group(data)
},
onSuccess: (res) => {
message.success(t('message.editSuccess', '编辑成功'))
//更新列表
get(queryClientAtom).invalidateQueries({ queryKey: [ 'websiteDomains', get(websiteDomainSearchAtom) ] })
return res
}
}
})
//describeDomainNS
export const describeDomainNSAtom = (id: number) => atomWithQuery(() => {
return {
queryKey: [ 'describeDomainNS', id ],
queryFn: async ({ queryKey: [ , id ] }) => {
return await websitesServ.domain.describeDomainNS({ id: id as number })
},
select: (data) => {
return data.data
}
}
})

90
src/store/websites/domain_groups.ts

@ -0,0 +1,90 @@
import { atom } from 'jotai'
import { IApiResult, IPage } from '@/global'
import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query'
import { message } from 'antd'
import { t } from 'i18next'
import { WebSite } from '@/types/website/domain_group'
import webSiteServ from '@/service/website/domain_group'
type SearchParams = IPage & {
key?: string
[key: string]: any
}
export const domainGroupIdAtom = atom(0)
export const domainGroupIdsAtom = atom<number[]>([])
export const domainGroupAtom = atom<WebSite.IDomainGroup>(undefined as unknown as WebSite.IDomainGroup )
export const domainGroupSearchAtom = atom<SearchParams>({
key: '',
pageSize: 10,
page: 1,
} as SearchParams)
export const domainGroupPageAtom = atom<IPage>({
pageSize: 10,
page: 1,
})
export const domainGroupsAtom = atomWithQuery((get) => {
return {
queryKey: [ 'domainGroups', get(domainGroupSearchAtom) ],
queryFn: async ({ queryKey: [ , params ] }) => {
return await webSiteServ.list(params as SearchParams)
},
select: res => {
const data = res.data
data.rows = data.rows?.map(row => {
return {
...row,
//status: convertToBool(row.status)
}
})
return data
}
}
})
//saveOrUpdateAtom
export const saveOrUpdateDomainGroupAtom = atomWithMutation<IApiResult, WebSite.IDomainGroup>((get) => {
return {
mutationKey: [ 'updateDomainGroup' ],
mutationFn: async (data) => {
//data.status = data.status ? '1' : '0'
if (data.id === 0) {
return await webSiteServ.add(data)
}
return await webSiteServ.update(data)
},
onSuccess: (res) => {
const isAdd = !!res.data?.id
message.success(t(isAdd ? 'message.saveSuccess' : 'message.editSuccess', '保存成功'))
//更新列表
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore fix
get(queryClientAtom).invalidateQueries({ queryKey: [ 'domainGroups', get(domainGroupSearchAtom) ] })
return res
}
}
})
export const deleteDomainGroupAtom = atomWithMutation((get) => {
return {
mutationKey: [ 'deleteDomainGroup' ],
mutationFn: async (ids: number[]) => {
return await webSiteServ.batchDelete(ids ?? get(domainGroupIdsAtom))
},
onSuccess: (res) => {
message.success('message.deleteSuccess')
//更新列表
get(queryClientAtom).invalidateQueries({ queryKey: [ 'domainGroups', get(domainGroupSearchAtom) ] })
return res
}
}
})

6
src/theme/index.ts

@ -1,4 +1,4 @@
import { createInstance, } from 'antd-style'
import { createInstance, } from 'antd-style'
import { ProThemeToken } from './themes' import { ProThemeToken } from './themes'
type ProToken = { type ProToken = {
@ -19,8 +19,8 @@ const { createStyles, ThemeProvider } = createInstance<ProToken>({
export { export {
createGlobalStyle, createGlobalStyle,
extractStaticStyle, extractStaticStyle,
createStylish,
styleManager,
createStylish,
styleManager,
css, css,
cx, cx,
injectGlobal, injectGlobal,

7
src/types/website/domain.d.ts

@ -10,3 +10,10 @@ export interface IWebsiteDomain {
tag: string; tag: string;
remark: string; remark: string;
} }
export interface INameServer {
dnsServers: string[];
expectDnsServers: string[]
success: boolean;
message: string
}

9
src/types/website/domain_group.d.ts

@ -0,0 +1,9 @@
export namespace WebSite {
export interface IDomainGroup {
id: number;
user_id: number;
sort: number;
name: string;
created_at: string;
}
}
Loading…
Cancel
Save