Files
d8d-vite-starter/src/client/admin/pages/pages_zichan_transfer.tsx
D8D Developer b9a3c991d0 update
2025-06-27 01:56:30 +00:00

436 lines
14 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import {
Button, Table, Space,
Form, Input, Select, message, Modal,
Card, Row, Col, Typography,
Tag, DatePicker
} from 'antd';
import {
useQuery,
} from '@tanstack/react-query';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import type { InferResponseType, InferRequestType } from 'hono/client';
import {
AssetTransferType,
AssetTransferTypeNameMap, AssetTransferTypeColorMap,
} from '@/share/monitorTypes';
// 定义类型
type TransferListRequest = InferRequestType<typeof zichanTransferClient.$get>['query']
type TransferItem = InferResponseType<typeof zichanTransferClient.$get, 200>['data'][0];
type TransferDetail = InferResponseType<typeof zichanTransferClient[':id']['$get'], 200>;
type CreateTransferRequest = InferRequestType<typeof zichanTransferClient.$post>['json'];
type UpdateTransferRequest = InferRequestType<typeof zichanTransferClient[':id']['$put']>['json'];
type ZichanInfo = InferResponseType<typeof zichanClient.$get, 200>['data'][0];
import { zichanClient, zichanTransferClient } from '@/client/api';
import { getEnumOptions } from '../utils';
const { Title } = Typography;
// 资产流转管理页面
export const ZichanTransferPage = () => {
const [form] = Form.useForm();
const [formMode, setFormMode] = useState<'create' | 'edit'>('create');
const [editingId, setEditingId] = useState<number | null>(null);
const [modalVisible, setModalVisible] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [zichanOptions, setZichanOptions] = useState<{ label: string, value: number }[]>([]);
const [searchParams, setSearchParams] = useState<TransferListRequest>({
page: 1,
pageSize: 10,
assetId: undefined,
transferType: undefined
});
// 资产流转类型选项
const transferTypeOptions = getEnumOptions(AssetTransferType, AssetTransferTypeNameMap);
// 获取资产列表用于下拉选择
useEffect(() => {
const fetchZichanList = async () => {
try {
const res = await zichanClient.$get({ query: { pageSize: 500 } });
if (res.status !== 200) {
throw new Error('获取资产列表失败');
}
const result = await res.json();
const options = result.data.map((item) => ({
label: `${item.assetName} (ID:${item.id})`,
value: item.id
}));
setZichanOptions(options);
} catch (error) {
console.error('获取资产列表失败', error);
}
};
fetchZichanList();
}, []);
// 查询资产流转记录列表
const {
data: transferResult = { data: [], pagination: { total: 0, current: 1, pageSize: 10 } },
isLoading: isFetching,
refetch
} = useQuery({
queryKey: ['zichan-transfer', searchParams],
queryFn: async () => {
const res = await zichanTransferClient.$get({ query: searchParams });
if (res.status !== 200) {
throw new Error('获取资产流转记录失败');
}
return await res.json();
},
});
// 提取数据和分页信息
const transferList = transferResult.data || [];
const pagination = transferResult.pagination || { total: 0, current: 1, pageSize: 10 };
// 处理表单提交
const handleSubmit = async (values: CreateTransferRequest | UpdateTransferRequest) => {
try {
setIsLoading(true);
// 创建一个新的对象以避免修改原始值
const submitData = { ...values };
// 处理流转时间格式
if (submitData.transferTime && dayjs.isDayjs(submitData.transferTime)) {
// 使用字符串格式,确保后端可以正确处理
submitData.transferTime = submitData.transferTime;
}
if (formMode === 'create') {
const res = await zichanTransferClient.$post({
json: submitData as CreateTransferRequest
});
if (res.status !== 200) {
throw new Error(await res.text());
}
message.success('资产流转记录创建成功');
} else {
if (editingId) {
const res = await zichanTransferClient[':id'].$put({
param: { id: editingId },
json: submitData
});
if (res.status !== 200) {
throw new Error(await res.text());
}
message.success('资产流转记录更新成功');
}
}
setModalVisible(false);
refetch();
} catch (error: any) {
message.error(error.response?.data?.error || '操作失败');
} finally {
setIsLoading(false);
}
};
// 处理编辑
const handleEdit = async (id: number): Promise<void> => {
try {
setIsLoading(true);
const res = await zichanTransferClient[':id'].$get({
param: { id: String(id) }
});
if (res.status !== 200) {
throw new Error('获取资产流转记录详情失败');
}
const data = await res.json();
form.setFieldsValue({
...data,
transferTime: dayjs(data.transferTime)
});
setEditingId(id);
setFormMode('edit');
setModalVisible(true);
} catch (error: any) {
message.error(error.response?.data?.error || '获取资产流转记录详情失败');
} finally {
setIsLoading(false);
}
};
// 处理删除
const handleDelete = async (id: number) => {
try {
const res = await zichanTransferClient[':id'].$delete({
param: { id }
});
if (res.status !== 200) {
throw new Error('删除资产流转记录失败');
}
message.success('资产流转记录删除成功');
refetch();
} catch (error: any) {
message.error(error.response?.data?.error || '删除资产流转记录失败');
}
};
// 处理搜索
const handleSearch = (values: TransferListRequest) => {
setSearchParams({
...searchParams,
page: 1, // 重置为第一页
assetId: values.assetId,
transferType: values.transferType
});
};
// 处理页码变化
const handlePageChange = (page: number, pageSize?: number) => {
setSearchParams({
...searchParams,
page,
pageSize: pageSize || 10
});
};
// 处理新增
const handleAdd = () => {
form.resetFields();
form.setFieldsValue({
transfer_time: dayjs() // 默认设置为当前时间
});
setFormMode('create');
setEditingId(null);
setModalVisible(true);
};
// 表格列定义
const columns = [
{
title: 'ID',
dataIndex: 'id',
key: 'id',
width: 80
},
{
title: '资产',
dataIndex: 'assetId',
key: 'assetId',
render: (assetId: number, record: TransferItem) => {
return record.zichanInfo ? record.zichanInfo.assetName : `资产ID: ${assetId}`;
}
},
{
title: '流转类型',
dataIndex: 'assetTransfer',
key: 'assetTransfer',
render: (type: number) => {
return <Tag color={AssetTransferTypeColorMap[type as AssetTransferType] || 'default'}>
{AssetTransferTypeNameMap[type as AssetTransferType] || '未知类型'}
</Tag>;
}
},
{
title: '人员',
dataIndex: 'person',
key: 'person'
},
{
title: '部门',
dataIndex: 'department',
key: 'department'
},
{
title: '联系电话',
dataIndex: 'phone',
key: 'phone'
},
{
title: '流转事由',
dataIndex: 'transferReason',
key: 'transferReason',
ellipsis: true
},
{
title: '流转时间',
dataIndex: 'transferTime',
key: 'transferTime',
render: (date: Date) => date ? dayjs(date).format('YYYY-MM-DD HH:mm:ss') : '-'
},
{
title: '操作',
key: 'action',
width: 200,
render: (_: any, record: TransferItem) => (
<Space>
<Button size="small" type="primary" onClick={() => handleEdit(record.id)}></Button>
<Button size="small" danger onClick={() =>
Modal.confirm({
title: '确认删除',
content: `确定要删除此资产流转记录吗?`,
onOk: () => handleDelete(record.id)
})
}></Button>
</Space>
)
}
];
return (
<div>
<Title level={2}></Title>
<Card>
<Form layout="inline" onFinish={handleSearch} style={{ marginBottom: 16 }}>
<Form.Item name="asset_id" label="选择资产">
<Select
placeholder="请选择资产"
style={{ width: 240 }}
allowClear
options={zichanOptions}
showSearch
filterOption={(input, option) =>
(String(option?.label ?? '')).toLowerCase().includes(input.toLowerCase())
}
/>
</Form.Item>
<Form.Item name="asset_transfer" label="流转类型">
<Select
placeholder="请选择流转类型"
style={{ width: 140 }}
allowClear
options={transferTypeOptions}
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit"></Button>
</Form.Item>
<Form.Item>
<Button type="primary" onClick={handleAdd}></Button>
</Form.Item>
</Form>
<Table
columns={columns}
dataSource={transferList}
rowKey="id"
loading={isFetching}
pagination={{
current: pagination.current,
pageSize: pagination.pageSize,
total: pagination.total,
onChange: handlePageChange,
showSizeChanger: true,
showTotal: (total) => `${total} 条记录`
}}
/>
<Modal
title={formMode === 'create' ? '新增资产流转记录' : '编辑资产流转记录'}
open={modalVisible}
onCancel={() => setModalVisible(false)}
footer={null}
width={720}
>
<Form
form={form}
layout="vertical"
onFinish={handleSubmit}
>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="assetId"
label="选择资产"
rules={[{ required: true, message: '请选择资产' }]}
>
<Select
placeholder="请选择资产"
options={zichanOptions}
showSearch
filterOption={(input, option) =>
(String(option?.label ?? '')).toLowerCase().includes(input.toLowerCase())
}
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="assetTransfer"
label="流转类型"
rules={[{ required: true, message: '请选择流转类型' }]}
>
<Select
placeholder="请选择流转类型"
options={transferTypeOptions}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="person"
label="人员"
rules={[{ required: true, message: '请输入人员姓名' }]}
>
<Input placeholder="请输入人员姓名" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="department"
label="部门"
>
<Input placeholder="请输入部门" />
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="phone"
label="联系电话"
>
<Input placeholder="请输入联系电话" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="transferTime"
label="流转时间"
rules={[{ required: true, message: '请选择流转时间' }]}
>
<DatePicker
showTime={{ format: 'HH:mm:ss' }}
format="YYYY-MM-DD HH:mm:ss"
style={{ width: '100%' }}
placeholder="请选择流转时间"
/>
</Form.Item>
</Col>
</Row>
<Form.Item
name="transferReason"
label="流转事由"
>
<Input.TextArea rows={4} placeholder="请输入流转事由" />
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit" loading={isLoading}>
{formMode === 'create' ? '创建' : '保存'}
</Button>
<Button onClick={() => setModalVisible(false)}></Button>
</Space>
</Form.Item>
</Form>
</Modal>
</Card>
</div>
);
};