add domain manager

This commit is contained in:
2025-03-25 19:19:09 +08:00
parent 45443709af
commit d649666379
9 changed files with 319 additions and 16 deletions

View File

@@ -0,0 +1,174 @@
import { useEffect } from 'react';
import { appDomainStatus, useDomainStore } from '../store';
import {
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
Button,
Modal,
TextField,
Dialog,
DialogContent,
DialogTitle,
useTheme,
} from '@mui/material';
import { useForm, Controller } from 'react-hook-form';
import { pick } from 'lodash-es';
import { Select } from '@kevisual/components/select/index.tsx';
const TableList = () => {
const { list, setList, getDomainList, updateDomain, setShowEditModal, setFormData, deleteDomain } = useDomainStore();
useEffect(() => {
getDomainList();
}, []);
return (
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>ID</TableCell>
<TableCell>Domain</TableCell>
<TableCell>App ID</TableCell>
<TableCell>UID</TableCell>
<TableCell>Status</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
{list.map((domain) => (
<TableRow key={domain.id}>
<TableCell>{domain.id}</TableCell>
<TableCell>{domain.domain}</TableCell>
<TableCell>{domain.appId}</TableCell>
<TableCell>{domain.uid}</TableCell>
<TableCell>{domain.status}</TableCell>
<TableCell>
<Button
variant='contained'
color='primary'
onClick={() => {
setShowEditModal(true);
setFormData(domain);
}}>
</Button>
<Button variant='contained' color='error' onClick={() => deleteDomain(domain)}>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
};
const FomeModal = () => {
const { showEditModal, setShowEditModal, formData, updateDomain } = useDomainStore();
const {
register,
handleSubmit,
formState: { errors },
reset,
getValues,
setValue,
control,
} = useForm();
useEffect(() => {
if (!showEditModal) return;
if (formData?.id) {
reset(formData);
} else {
reset({
status: 'running',
});
}
}, [formData]);
const onSubmit = async (data: any) => {
// 处理表单提交逻辑
const _formData = pick(data, ['domain', 'appId', 'status', 'id']);
if (formData.id) {
_formData.id = formData.id;
}
const res = await updateDomain(_formData);
if (res.code === 200) {
setShowEditModal(false);
}
};
const theme = useTheme();
const defultProps = theme.components?.MuiTextField?.defaultProps;
return (
<Dialog open={showEditModal} onClose={() => setShowEditModal(false)}>
<DialogTitle></DialogTitle>
<DialogContent>
<div className='p-4 w-[500px]'>
<form className='w-full h-full flex flex-col gap-4' onSubmit={handleSubmit(onSubmit)}>
<Controller
name='domain'
control={control}
defaultValue=''
rules={{ required: 'Domain is required' }}
render={({ field }) => <TextField {...defultProps} label='Domain' {...field} error={!!errors.domain} />}
/>
<Controller
name='appId'
control={control}
defaultValue=''
rules={{ required: 'App ID is required' }}
render={({ field }) => <TextField {...defultProps} label='App ID' {...field} error={!!errors.appId} />}
/>
<Controller
name='status'
control={control}
defaultValue=''
render={({ field }) => (
<Select
{...field}
options={[
...appDomainStatus.map((item) => ({
label: item,
value: item,
})),
]}
error={!!errors.status}
/>
)}
/>
<Button type='submit' variant='contained' color='primary'>
</Button>
</form>
</div>
</DialogContent>
</Dialog>
);
};
export const List = () => {
const { setShowEditModal, setFormData } = useDomainStore();
return (
<div className='p-4 w-full h-full bg-amber-900'>
<div className='flex'>
<Button
variant='contained'
color='primary'
onClick={() => {
setShowEditModal(true);
setFormData({});
}}>
</Button>
</div>
<div>
<TableList />
</div>
<FomeModal />
</div>
);
};

View File

@@ -0,0 +1,14 @@
import { Route, Routes } from 'react-router-dom';
import { Main } from './layouts';
import { List } from './edit/List';
import { Redirect } from '@/modules/Redirect';
export const App = () => {
return (
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Redirect to='/domain/edit/list' />}></Route>
<Route path='edit/list' element={<List />} />
</Route>
</Routes>
);
};

View File

@@ -0,0 +1,5 @@
import { LayoutMain } from '@/modules/layout';
export const Main = () => {
return <LayoutMain title='Domain' />;
};

View File

@@ -0,0 +1,91 @@
import { create } from 'zustand';
import { query } from '@/modules/query';
import { toast } from 'react-toastify';
// 审核,通过,驳回
export const appDomainStatus = ['audit', 'auditReject', 'auditPending', 'running', 'stop'] as const;
type AppDomainStatus = (typeof appDomainStatus)[number];
type Domain = {
id: string;
domain: string;
appId?: string;
status: AppDomainStatus;
data?: any;
uid?: string;
createdAt: string;
updatedAt: string;
};
interface Store {
getDomainList: () => Promise<any>;
updateDomain: (data: { domain: string; id: string; [key: string]: any }, opts?: { refresh?: boolean }) => Promise<any>;
deleteDomain: (data: { id: string }) => Promise<any>;
getDomainDetail: (data: { domain?: string; id?: string }) => Promise<any>;
list: Domain[];
setList: (list: Domain[]) => void;
formData: any;
setFormData: (formData: any) => void;
showEditModal: boolean;
setShowEditModal: (showEditModal: boolean) => void;
}
export const useDomainStore = create<Store>((set, get) => ({
getDomainList: async () => {
const res = await query.get({
path: 'app.domain.manager',
key: 'list',
});
if (res.code === 200) {
set({ list: res.data?.list || [] });
}
return res;
},
updateDomain: async (data: any, opts?: { refresh?: boolean }) => {
const res = await query.post({
path: 'app.domain.manager',
key: 'update',
data,
});
if (res.code === 200) {
const list = get().list;
set({ list: list.map((item) => (item.id === data.id ? res.data : item)) });
toast.success('更新成功');
if (opts?.refresh ?? true) {
get().getDomainList();
}
} else {
toast.error(res.message || '更新失败');
}
return res;
},
deleteDomain: async (data: any) => {
const res = await query.post({
path: 'app.domain.manager',
key: 'delete',
data,
});
if (res.code === 200) {
const list = get().list;
set({ list: list.filter((item) => item.id !== data.id) });
toast.success('删除成功');
}
return res;
},
getDomainDetail: async (data: any) => {
const res = await query.post({
path: 'app.domain.manager',
key: 'get',
data,
});
if (res.code === 200) {
set({ formData: res.data });
}
return res;
},
list: [],
setList: (list: any[]) => set({ list }),
formData: {},
setFormData: (formData: any) => set({ formData }),
showEditModal: false,
setShowEditModal: (showEditModal: boolean) => set({ showEditModal }),
}));