feat: 添加container列表

This commit is contained in:
2024-09-17 23:56:47 +08:00
parent 596c50cd0b
commit a36a390d25
16 changed files with 969 additions and 15 deletions

View File

@@ -1,5 +1,24 @@
const a = 1
import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
import { ConfigProvider } from 'antd';
import { App as ContainerApp } from './pages/container';
export const App = () => {
return <div className="bg-slate-200 w-20 h-10 border">App</div>;
return (
<div className='w-full h-full'>
<ConfigProvider
theme={{
token: {},
}}>
<Router>
<Routes>
<Route path='/' element={<Navigate to='/container/' />} />
<Route path='/container/*' element={<ContainerApp />} />
<Route path='/404' element={<div>404</div>} />
<Route path='*' element={<div>404</div>} />
</Routes>
</Router>
</ConfigProvider>
<div id='for-modal'></div>
</div>
);
};

5
src/modules/index.ts Normal file
View File

@@ -0,0 +1,5 @@
import { Query } from '@kevisual/query';
export const query = new Query({});
export const request = query.post;

View File

@@ -0,0 +1,32 @@
import CodeEditor from '@uiw/react-textarea-code-editor';
import { useEffect, useState } from 'react';
import { clsx } from 'clsx';
type Props = {
value?: string;
onChange?: (evn: React.ChangeEvent<HTMLTextAreaElement>) => void;
readonly?: boolean;
className?: string;
};
export const TextArea = (props: Props) => {
const [code, setCode] = useState<string>('');
useEffect(() => {
setCode(props.value || '');
}, []);
return (
<div className={clsx('min-h-16 max-h-52 overflow-scroll p-1')}>
<CodeEditor
value={code}
language='js'
readOnly={props.readonly}
placeholder='Please enter JS code.'
onChange={(evn) => setCode(evn.target.value)}
padding={10}
style={{
backgroundColor: '#f5f5f5',
fontFamily: 'ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace',
}}
/>
</div>
);
};

View File

@@ -0,0 +1,143 @@
import { query } from '@/modules';
import { Button, Input, message, Modal, Table } from 'antd';
import { useEffect, useState } from 'react';
import { TextArea } from '../components/TextArea';
import { useContainerStore } from '../store';
import { useShallow } from 'zustand/react/shallow';
import { Form } from 'antd';
const FormModal = () => {
const [form] = Form.useForm();
const containerStore = useContainerStore(
useShallow((state) => {
return {
showEdit: state.showEdit,
setShowEdit: state.setShowEdit,
formData: state.formData,
};
}),
);
useEffect(() => {
const open = containerStore.showEdit;
if (open) {
form.setFieldsValue(containerStore.formData || {});
}
}, [containerStore.showEdit]);
const onFinish = async (values: any) => {
console.log(values);
onClose();
};
const onClose = () => {
containerStore.setShowEdit(false);
form.setFieldsValue({});
};
const isEdit = containerStore.formData.id;
return (
<Modal
title={isEdit ? 'Edit' : 'Add'}
open={containerStore.showEdit}
onClose={() => containerStore.setShowEdit(false)}
destroyOnClose
footer={false}
onCancel={onClose}>
<Form
form={form}
onFinish={onFinish}
labelCol={{
span: 4,
offset: 2,
}}>
<Form.Item name='id' hidden>
<Input />
</Form.Item>
<Form.Item name='title' label='title'>
<Input />
</Form.Item>
<Form.Item name='code' label='code'>
<TextArea value={containerStore.formData.code} />
</Form.Item>
<Form.Item label=' ' colon={false}>
<Button type='primary' htmlType='submit'>
Submit
</Button>
<Button htmlType='reset' onClick={onClose}>
Cancel
</Button>
</Form.Item>
</Form>
</Modal>
);
};
export const ContainerList = () => {
const containerStore = useContainerStore(
useShallow((state) => {
return {
setFormData: state.setFormData,
setShowEdit: state.setShowEdit,
list: state.list,
getList: state.getList,
};
}),
);
useEffect(() => {
containerStore.getList();
}, []);
const columns = [
{
title: 'ID',
dataIndex: 'id',
},
{
title: 'Title',
dataIndex: 'title',
},
{
title: 'Code',
dataIndex: 'code',
render: (text: string, record: any) => {
return <TextArea value={text} readonly />;
},
},
{
title: 'Source',
dataIndex: 'source',
},
{
title: 'Operation',
dataIndex: 'operation',
render: (text: string, record: any) => {
return (
<div className='flex gap-2'>
<Button
type='primary'
onClick={() => {
containerStore.setFormData(record);
containerStore.setShowEdit(true);
}}>
Edit
</Button>
<Button danger>Delete</Button>
</div>
);
},
},
];
return (
<div className='w-full h-full '>
<div className='mb-2 w-full p-2 bg-white rounded-lg'>
<Button
className='w-20 '
type='primary'
onClick={() => {
containerStore.setFormData({});
containerStore.setShowEdit(true);
}}>
Add
</Button>
</div>
<Table dataSource={containerStore.list} rowKey='id' columns={columns} />
<FormModal />
</div>
);
};

View File

@@ -0,0 +1,15 @@
import { Navigate, Route, Routes } from 'react-router-dom';
import { ContainerList } from './edit/List';
import { Main } from './layouts';
export const App = () => {
return (
<Routes>
<Route element={<Main />}>
<Route path='/' element={<Navigate to='/container/edit/list' />}></Route>
<Route path='edit/list' element={<ContainerList />} />
<Route path='/' element={<div>Home</div>} />
</Route>
</Routes>
);
};

View File

@@ -0,0 +1,20 @@
import { Outlet } from 'react-router';
export const Main = () => {
return (
<div className='flex w-full h-full flex-col bg-gray-200'>
<div className='h-12 bg-white p-2 mb-2'>Container</div>
<div
className='flex'
style={{
height: 'calc(100vh - 4rem)',
}}>
<div className='flex-grow overflow-hidden mx-2'>
<div className='w-full h-full rounded-lg'>
<Outlet />
</div>
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,63 @@
import { create } from 'zustand';
import { query } from '@/modules';
import { message } from 'antd';
type ContainerStore = {
showEdit: boolean;
setShowEdit: (showEdit: boolean) => void;
formData: any;
setFormData: (formData: any) => void;
loading: boolean;
setLoading: (loading: boolean) => void;
list: any[];
getList: () => Promise<void>;
postData: (data: any) => Promise<void>;
deleteData: (id: string) => Promise<void>;
};
export const useContainerStore = create<ContainerStore>((set, get) => {
return {
showEdit: false,
setShowEdit: (showEdit) => set({ showEdit }),
formData: {},
setFormData: (formData) => set({ formData }),
loading: false,
setLoading: (loading) => set({ loading }),
list: [],
getList: async () => {
const res = await query.post({
path: 'container',
key: 'list',
});
if (res.code === 200) {
set({ list: res.data });
} else {
message.error(res.msg || 'Request failed');
}
},
postData: async (data) => {
const { getList } = get();
const res = await query.post({
path: 'container',
key: 'update',
data,
});
if (res.code === 200) {
getList();
} else {
message.error(res.msg || 'Request failed');
}
},
deleteData: async (id) => {
const { getList } = get();
const res = await query.post({
path: 'container',
key: 'delete',
id,
});
if (res.code === 200) {
getList();
} else {
message.error(res.msg || 'Request failed');
}
},
};
});