add
This commit is contained in:
parent
944fc48568
commit
fbbc919ca4
|
@ -1,34 +1,21 @@
|
|||
import { api } from '@nice/client';
|
||||
import { Button, Input, Pagination, Space, Modal, Form, message, Switch } from 'antd';
|
||||
import { SearchOutlined, EditOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
|
||||
// 定义 Staff 接口
|
||||
interface Staff {
|
||||
id: string;
|
||||
username: string;
|
||||
showname: string;
|
||||
absent: boolean;
|
||||
// trainSituations: TrainSituation[];
|
||||
}
|
||||
|
||||
interface PaginatedResponse {
|
||||
items: Staff[];
|
||||
total: number;
|
||||
}
|
||||
import { message, Form, Modal } from 'antd';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { SearchBar } from './components/SearchBar';
|
||||
import { StaffTable } from './components/StaffTable';
|
||||
import { StaffModal } from './components/StaffModal';
|
||||
import { Staff, PaginatedResponse } from './components/types';
|
||||
|
||||
const TestPage: React.FC = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
// 状态定义
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [editingStaff, setEditingStaff] = useState<Staff | null>(null);
|
||||
const [form] = Form.useForm();
|
||||
const pageSize = 10;
|
||||
|
||||
// 添加 useRef 处理查询
|
||||
const searchRef = useRef(false);
|
||||
|
||||
// 优化查询逻辑
|
||||
// API 调用
|
||||
const { data, isLoading, refetch } = api.staff.findManyWithPagination.useQuery<PaginatedResponse>({
|
||||
page: currentPage,
|
||||
pageSize: pageSize,
|
||||
|
@ -45,10 +32,6 @@ const TestPage: React.FC = () => {
|
|||
showname: true,
|
||||
absent: true,
|
||||
}
|
||||
}, {
|
||||
enabled: searchRef.current, // 控制查询启用
|
||||
refetchOnWindowFocus: false,
|
||||
keepPreviousData: true, // 保持之前的数据直到新数据加载完成
|
||||
});
|
||||
|
||||
// 删除方法
|
||||
|
@ -80,190 +63,95 @@ message.success('删除成功');
|
|||
}
|
||||
});
|
||||
|
||||
// 处理函数
|
||||
const handleSearch = () => {
|
||||
setCurrentPage(1);
|
||||
searchRef.current = true;
|
||||
refetch();
|
||||
};
|
||||
|
||||
// 修改分页处理
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
searchRef.current = true;
|
||||
refetch();
|
||||
};
|
||||
|
||||
// 添加数据监听
|
||||
useEffect(() => {
|
||||
if (data && searchRef.current) {
|
||||
searchRef.current = false;
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
// 处理删除的函数
|
||||
const handleDelete = async (id: string) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这条记录吗?',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await deleteMutation.mutateAsync({
|
||||
ids: [id],
|
||||
data: {} // 添加空的 data 对象
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleEdit = (staff: Staff) => {
|
||||
setEditingStaff(staff);
|
||||
form.setFieldsValue(staff);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
setEditingStaff(null);
|
||||
form.resetFields();
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleModalOk = () => {
|
||||
form.validateFields().then(values => {
|
||||
const handleEdit = (staff: Staff) => {
|
||||
setEditingStaff(staff);
|
||||
form.setFieldsValue(staff);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这条记录吗?',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await deleteMutation.mutateAsync({ ids: [id] });
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
refetch(); // 确保切换页面时重新获取数据
|
||||
};
|
||||
|
||||
const handleModalOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
if (editingStaff) {
|
||||
updateMutation.mutate({
|
||||
await updateMutation.mutateAsync({
|
||||
where: { id: editingStaff.id },
|
||||
data: values
|
||||
});
|
||||
} else {
|
||||
createMutation.mutate({
|
||||
await createMutation.mutateAsync({
|
||||
data: values
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
message.error('操作失败:' + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始加载
|
||||
useEffect(() => {
|
||||
refetch();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<h1 className="text-2xl font-bold mb-4 text-center">培训情况记录</h1>
|
||||
|
||||
{/* 搜索和添加按钮 */}
|
||||
<div className="mb-4 flex justify-between">
|
||||
<Space>
|
||||
<Input
|
||||
placeholder="搜索员工姓名或用户名"
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
onPressEnter={handleSearch}
|
||||
prefix={<SearchOutlined />}
|
||||
<SearchBar
|
||||
searchText={searchText}
|
||||
onSearchTextChange={setSearchText}
|
||||
onSearch={handleSearch}
|
||||
onAdd={handleAdd}
|
||||
/>
|
||||
<Button type="primary" onClick={handleSearch}>搜索</Button>
|
||||
</Space>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
||||
添加员工
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 修改表格,添加操作列 */}
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full bg-white shadow-md rounded-lg">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 border-b">
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">用户名</th>
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">名称</th>
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">是否在位</th>
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">
|
||||
操作
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200">
|
||||
{(data?.items || []).map((staff) => (
|
||||
<tr key={staff.id} className="hover:bg-gray-50">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
{staff.username}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
{staff.showname}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
{staff.absent ? '在位' : '不在位'}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => handleEdit(staff)}
|
||||
size="small"
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={() => handleDelete(staff.id)}
|
||||
size="small"
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<StaffTable
|
||||
data={data?.items || []}
|
||||
total={data?.total || 0}
|
||||
currentPage={currentPage}
|
||||
pageSize={pageSize}
|
||||
isLoading={isLoading}
|
||||
onPageChange={handlePageChange}
|
||||
onEdit={handleEdit}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
|
||||
{/* 编辑/添加模态框 */}
|
||||
<Modal
|
||||
title={editingStaff ? "编辑员工" : "添加员工"}
|
||||
open={isModalVisible}
|
||||
<StaffModal
|
||||
visible={isModalVisible}
|
||||
editingStaff={editingStaff}
|
||||
form={form}
|
||||
onOk={handleModalOk}
|
||||
onCancel={() => setIsModalVisible(false)}
|
||||
>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="用户名"
|
||||
rules={[{ required: true, message: '请输入用户名' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="showname"
|
||||
label="名称"
|
||||
rules={[{ required: true, message: '请输入名称' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="absent"
|
||||
label="是否在位"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch
|
||||
checkedChildren="在位"
|
||||
unCheckedChildren="不在位"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
<div className="mt-4 flex justify-center">
|
||||
<Pagination
|
||||
current={currentPage}
|
||||
total={data?.total || 0}
|
||||
pageSize={pageSize}
|
||||
onChange={handlePageChange}
|
||||
showTotal={(total) => `共 ${total} 条记录`}
|
||||
showSizeChanger={false}
|
||||
showQuickJumper
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
import { Button, Input, Space } from 'antd';
|
||||
import { SearchOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import React from 'react';
|
||||
|
||||
interface SearchBarProps {
|
||||
searchText: string;
|
||||
onSearchTextChange: (text: string) => void;
|
||||
onSearch: () => void;
|
||||
onAdd: () => void;
|
||||
}
|
||||
|
||||
export const SearchBar: React.FC<SearchBarProps> = ({
|
||||
searchText,
|
||||
onSearchTextChange,
|
||||
onSearch,
|
||||
onAdd,
|
||||
}) => {
|
||||
return (
|
||||
<div className="mb-4 flex justify-between">
|
||||
<Space>
|
||||
<Input
|
||||
placeholder="搜索员工姓名或用户名"
|
||||
value={searchText}
|
||||
onChange={(e) => onSearchTextChange(e.target.value)}
|
||||
onPressEnter={onSearch}
|
||||
prefix={<SearchOutlined />}
|
||||
/>
|
||||
<Button type="primary" onClick={onSearch}>搜索</Button>
|
||||
</Space>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={onAdd}>
|
||||
添加员工
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,55 @@
|
|||
import { Modal, Form, Input, Switch } from 'antd';
|
||||
import React from 'react';
|
||||
import { Staff } from './types';
|
||||
|
||||
interface StaffModalProps {
|
||||
visible: boolean;
|
||||
editingStaff: Staff | null;
|
||||
form: any;
|
||||
onOk: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
export const StaffModal: React.FC<StaffModalProps> = ({
|
||||
visible,
|
||||
editingStaff,
|
||||
form,
|
||||
onOk,
|
||||
onCancel,
|
||||
}) => {
|
||||
return (
|
||||
<Modal
|
||||
title={editingStaff ? "编辑员工" : "添加员工"}
|
||||
open={visible}
|
||||
onOk={onOk}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="用户名"
|
||||
rules={[{ required: true, message: '请输入用户名' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="showname"
|
||||
label="名称"
|
||||
rules={[{ required: true, message: '请输入名称' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="absent"
|
||||
label="是否在位"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch
|
||||
checkedChildren="在位"
|
||||
unCheckedChildren="不在位"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,131 @@
|
|||
import { Button, Space, Table, Tag, Input, Pagination, message } from 'antd';
|
||||
import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import React, { useState } from 'react';
|
||||
import { Staff } from './types';
|
||||
|
||||
interface StaffTableProps {
|
||||
data: Staff[];
|
||||
total: number;
|
||||
currentPage: number;
|
||||
pageSize: number;
|
||||
isLoading?: boolean;
|
||||
onPageChange: (page: number) => void;
|
||||
onEdit: (staff: Staff) => void;
|
||||
onDelete: (id: string) => void;
|
||||
}
|
||||
|
||||
export const StaffTable: React.FC<StaffTableProps> = ({
|
||||
data,
|
||||
total,
|
||||
currentPage,
|
||||
pageSize,
|
||||
isLoading = false,
|
||||
onPageChange,
|
||||
onEdit,
|
||||
onDelete,
|
||||
}) => {
|
||||
const [jumpPage, setJumpPage] = useState('');
|
||||
|
||||
const handleJumpPage = () => {
|
||||
const page = parseInt(jumpPage);
|
||||
if (!isNaN(page) && page > 0 && page <= Math.ceil(total / pageSize)) {
|
||||
onPageChange(page);
|
||||
setJumpPage('');
|
||||
} else {
|
||||
message.error('请输入有效的页码');
|
||||
}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'username',
|
||||
key: 'username',
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'showname',
|
||||
key: 'showname',
|
||||
},
|
||||
{
|
||||
title: '是否在位',
|
||||
dataIndex: 'absent',
|
||||
key: 'absent',
|
||||
render: (absent: boolean) => (
|
||||
<Tag color={absent ? 'success' : 'error'}>
|
||||
{absent ? '在位' : '不在位'}
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (_: any, record: Staff) => (
|
||||
<Space size="middle">
|
||||
<Button
|
||||
type="link"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => onEdit(record)}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="link"
|
||||
icon={<DeleteOutlined />}
|
||||
danger
|
||||
onClick={() => onDelete(record.id)}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
dataSource={data}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
loading={isLoading}
|
||||
/>
|
||||
<div className="mt-6 flex justify-center items-center">
|
||||
<div className="bg-white px-6 py-3 rounded-lg shadow-sm flex items-center space-x-6">
|
||||
<Pagination
|
||||
current={currentPage}
|
||||
total={total}
|
||||
pageSize={pageSize}
|
||||
onChange={onPageChange}
|
||||
showTotal={(total) => (
|
||||
<span className="text-gray-600">
|
||||
共 <span className="font-medium text-gray-900">{total}</span> 条记录
|
||||
</span>
|
||||
)}
|
||||
showSizeChanger={false}
|
||||
/>
|
||||
<div className="h-6 w-px bg-gray-200" /> {/* 分隔线 */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<Input
|
||||
size="small"
|
||||
style={{ width: 60 }}
|
||||
value={jumpPage}
|
||||
onChange={(e) => setJumpPage(e.target.value)}
|
||||
onPressEnter={handleJumpPage}
|
||||
placeholder="页码"
|
||||
className="text-center"
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
size="small"
|
||||
onClick={handleJumpPage}
|
||||
>
|
||||
跳转
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
export interface Staff {
|
||||
id: string;
|
||||
username: string;
|
||||
showname: string;
|
||||
absent: boolean;
|
||||
}
|
||||
|
||||
export interface PaginatedResponse {
|
||||
items: Staff[];
|
||||
total: number;
|
||||
}
|
|
@ -0,0 +1,265 @@
|
|||
import { api } from '@nice/client';
|
||||
import { Button, Input, Pagination, Space, Modal, Form, message, Switch } from 'antd';
|
||||
import { SearchOutlined, EditOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
|
||||
// 定义 Staff 接口
|
||||
interface Staff {
|
||||
id: string;
|
||||
username: string;
|
||||
showname: string;
|
||||
absent: boolean;
|
||||
// trainSituations: TrainSituation[];
|
||||
}
|
||||
|
||||
interface PaginatedResponse {
|
||||
items: Staff[];
|
||||
total: number;
|
||||
}
|
||||
|
||||
const TestPage: React.FC = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [editingStaff, setEditingStaff] = useState<Staff | null>(null);
|
||||
const [form] = Form.useForm();
|
||||
const pageSize = 10;
|
||||
|
||||
// 修改查询逻辑
|
||||
const { data, isLoading, refetch } = api.staff.findManyWithPagination.useQuery<PaginatedResponse>({
|
||||
page: currentPage,
|
||||
pageSize: pageSize,
|
||||
where: {
|
||||
deletedAt: null,
|
||||
OR: searchText ? [
|
||||
{ username: { contains: searchText } },
|
||||
{ showname: { contains: searchText } }
|
||||
] : undefined
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
showname: true,
|
||||
absent: true,
|
||||
}
|
||||
}, {
|
||||
// 移除 enabled 控制
|
||||
refetchOnWindowFocus: false,
|
||||
keepPreviousData: true,
|
||||
});
|
||||
|
||||
// 删除方法
|
||||
const deleteMutation = api.staff.softDeleteByIds.useMutation({
|
||||
onSuccess: () => {
|
||||
message.success('删除成功');
|
||||
refetch();
|
||||
},
|
||||
onError: (error) => {
|
||||
message.error('删除失败:' + error.message);
|
||||
}
|
||||
});
|
||||
|
||||
// 更新方法
|
||||
const updateMutation = api.staff.update.useMutation({
|
||||
onSuccess: () => {
|
||||
message.success('更新成功');
|
||||
setIsModalVisible(false);
|
||||
refetch();
|
||||
}
|
||||
});
|
||||
|
||||
// 创建方法
|
||||
const createMutation = api.staff.create.useMutation({
|
||||
onSuccess: () => {
|
||||
message.success('创建成功');
|
||||
setIsModalVisible(false);
|
||||
refetch();
|
||||
}
|
||||
});
|
||||
|
||||
// 修改搜索处理函数
|
||||
const handleSearch = () => {
|
||||
setCurrentPage(1);
|
||||
refetch();
|
||||
};
|
||||
|
||||
// 修改分页处理
|
||||
const handlePageChange = (page: number) => {
|
||||
setCurrentPage(page);
|
||||
refetch();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// 组件首次加载时执行查询
|
||||
refetch();
|
||||
}, []);
|
||||
|
||||
// 处理删除的函数
|
||||
const handleDelete = async (id: string) => {
|
||||
Modal.confirm({
|
||||
title: '确认删除',
|
||||
content: '确定要删除这条记录吗?',
|
||||
onOk: async () => {
|
||||
try {
|
||||
await deleteMutation.mutateAsync({
|
||||
ids: [id],
|
||||
data: {} // 添加空的 data 对象
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('删除失败:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleEdit = (staff: Staff) => {
|
||||
setEditingStaff(staff);
|
||||
form.setFieldsValue(staff);
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleAdd = () => {
|
||||
setEditingStaff(null);
|
||||
form.resetFields();
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
|
||||
const handleModalOk = () => {
|
||||
form.validateFields().then(values => {
|
||||
if (editingStaff) {
|
||||
updateMutation.mutate({
|
||||
where: { id: editingStaff.id },
|
||||
data: values
|
||||
});
|
||||
} else {
|
||||
createMutation.mutate({
|
||||
data: values
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-6">
|
||||
<h1 className="text-2xl font-bold mb-4 text-center">培训情况记录</h1>
|
||||
|
||||
{/* 搜索和添加按钮 */}
|
||||
<div className="mb-4 flex justify-between">
|
||||
<Space>
|
||||
<Input
|
||||
placeholder="搜索员工姓名或用户名"
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
onPressEnter={handleSearch}
|
||||
prefix={<SearchOutlined />}
|
||||
/>
|
||||
<Button type="primary" onClick={handleSearch}>搜索</Button>
|
||||
</Space>
|
||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleAdd}>
|
||||
添加员工
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* 修改表格,添加操作列 */}
|
||||
<div className="overflow-x-auto">
|
||||
<table className="min-w-full bg-white shadow-md rounded-lg">
|
||||
<thead>
|
||||
<tr className="bg-gray-100 border-b">
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">用户名</th>
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">名称</th>
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">是否在位</th>
|
||||
<th className="px-6 py-3 text-center text-xs font-medium text-gray-600 uppercase tracking-wider">
|
||||
操作
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200">
|
||||
{(data?.items || []).map((staff) => (
|
||||
<tr key={staff.id} className="hover:bg-gray-50">
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
{staff.username}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
{staff.showname}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
{staff.absent ? '在位' : '不在位'}
|
||||
</td>
|
||||
<td className="px-6 py-4 whitespace-nowrap text-center">
|
||||
<Space>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => handleEdit(staff)}
|
||||
size="small"
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={() => handleDelete(staff.id)}
|
||||
size="small"
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</Space>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* 编辑/添加模态框 */}
|
||||
<Modal
|
||||
title={editingStaff ? "编辑员工" : "添加员工"}
|
||||
open={isModalVisible}
|
||||
onOk={handleModalOk}
|
||||
onCancel={() => setIsModalVisible(false)}
|
||||
>
|
||||
<Form form={form} layout="vertical">
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="用户名"
|
||||
rules={[{ required: true, message: '请输入用户名' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="showname"
|
||||
label="名称"
|
||||
rules={[{ required: true, message: '请输入名称' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="absent"
|
||||
label="是否在位"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch
|
||||
checkedChildren="在位"
|
||||
unCheckedChildren="不在位"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
<div className="mt-4 flex justify-center">
|
||||
<Pagination
|
||||
current={currentPage}
|
||||
total={data?.total || 0}
|
||||
pageSize={pageSize}
|
||||
onChange={handlePageChange}
|
||||
showTotal={(total) => `共 ${total} 条记录`}
|
||||
showSizeChanger={false}
|
||||
showQuickJumper
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestPage;
|
|
@ -2,7 +2,7 @@ server {
|
|||
# 监听80端口
|
||||
listen 80;
|
||||
# 服务器域名/IP地址,使用环境变量
|
||||
server_name 192.168.217.194;
|
||||
server_name 192.168.239.194;
|
||||
|
||||
# 基础性能优化配置
|
||||
# 启用tcp_nopush以优化数据发送
|
||||
|
@ -100,7 +100,7 @@ server {
|
|||
# 仅供内部使用
|
||||
internal;
|
||||
# 代理到认证服务
|
||||
proxy_pass http://192.168.217.194:3001/auth/file;
|
||||
proxy_pass http://192.168.239.194:3001/auth/file;
|
||||
|
||||
# 请求优化:不传递请求体
|
||||
proxy_pass_request_body off;
|
||||
|
|
Loading…
Reference in New Issue