436 lines
14 KiB
TypeScript
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>
|
|
);
|
|
}; |