import React, { useState, useEffect, useCallback } from 'react';
import {
Table,
Button,
Modal,
Form,
Input,
Select,
DatePicker,
message,
Card,
Space,
Tag,
Row,
Col,
Statistic,
Popconfirm,
Tooltip,
Empty,
Progress,
Tabs,
} from 'antd';
import {
PlusOutlined,
EditOutlined,
DeleteOutlined,
PlayCircleOutlined,
CheckCircleOutlined,
SearchOutlined,
ReloadOutlined,
InboxOutlined,
InfoCircleOutlined,
FileSearchOutlined,
ClockCircleOutlined,
CheckSquareOutlined,
SyncOutlined,
} from '@ant-design/icons';
import api from '../api';
import dayjs from 'dayjs';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { designTokens } from '../config/theme';
import CloseButton from '../components/CloseButton';
const { RangePicker } = DatePicker;
const { TabPane } = Tabs;
const InventoryManagement = () => {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const planIdParam = searchParams.get('planId');
const [activeTab, setActiveTab] = useState(planIdParam ? 'execution' : 'list');
const [plans, setPlans] = useState([]);
const [loading, setLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const [editingPlan, setEditingPlan] = useState(null);
const [rooms, setRooms] = useState([]);
const [racks, setRacks] = useState([]);
const [filteredRacks, setFilteredRacks] = useState([]);
const [selectedRooms, setSelectedRooms] = useState([]);
const [stats, setStats] = useState({
totalPlans: 0,
completedPlans: 0,
inProgressPlans: 0,
});
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
total: 0,
});
const [searchParamsObj, setSearchParamsObj] = useState({});
const [form] = Form.useForm();
const fetchPlans = useCallback(async () => {
setLoading(true);
try {
const params = {
page: pagination.current,
pageSize: pagination.pageSize,
...searchParamsObj,
};
const res = await api.get('/inventory/plans', { params });
setPlans(res.data.plans || []);
setPagination(prev => ({
...prev,
total: res.data.total || 0,
}));
} catch (error) {
message.error('获取盘点计划失败');
} finally {
setLoading(false);
}
}, [pagination.current, pagination.pageSize, searchParamsObj]);
const fetchStats = async () => {
try {
const res = await api.get('/inventory/stats/dashboard');
setStats({
totalPlans: res.data.totalPlans || 0,
completedPlans: res.data.completedPlans || 0,
inProgressPlans: res.data.inProgressPlans || 0,
});
} catch (error) {
console.error('获取统计失败', error);
}
};
const fetchRooms = async () => {
try {
const res = await api.get('/rooms', { params: { pageSize: 1000 } });
setRooms(Array.isArray(res.data) ? res.data : res.data.rooms || []);
} catch (error) {
console.error('获取机房失败', error);
}
};
const fetchRacks = async () => {
try {
const res = await api.get('/racks', { params: { pageSize: 1000 } });
const allRacks = Array.isArray(res.data) ? res.data : res.data.racks || [];
setRacks(allRacks);
setFilteredRacks(allRacks);
} catch (error) {
console.error('获取机柜失败', error);
}
};
useEffect(() => {
fetchPlans();
fetchStats();
fetchRooms();
fetchRacks();
}, [fetchPlans]);
useEffect(() => {
if (planIdParam) {
setActiveTab('execution');
}
}, [planIdParam]);
const handleAdd = () => {
setEditingPlan(null);
form.resetFields();
setSelectedRooms([]);
setFilteredRacks(racks);
setModalVisible(true);
};
const handleEdit = record => {
setEditingPlan(record);
const targetRooms = record.targetRooms || [];
setSelectedRooms(targetRooms);
if (targetRooms.length > 0) {
const filtered = racks.filter(
rack =>
targetRooms.includes(rack.roomId) || (rack.Room && targetRooms.includes(rack.Room.roomId))
);
setFilteredRacks(filtered);
} else {
setFilteredRacks(racks);
}
form.setFieldsValue({
name: record.name,
type: record.type,
description: record.description,
scheduledDate: record.scheduledDate ? dayjs(record.scheduledDate) : null,
targetRooms: targetRooms,
targetRacks: record.targetRacks || [],
});
setModalVisible(true);
};
const handleDelete = async planId => {
Modal.confirm({
title: '确认删除',
content: '确定要删除这个盘点计划吗?此操作不可恢复!',
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk: async () => {
try {
await api.delete(`/inventory/plans/${planId}`);
message.success('删除成功');
fetchPlans();
fetchStats();
} catch (error) {
message.error('删除失败');
}
},
});
};
const handleSubmit = async values => {
try {
const data = {
...values,
scheduledDate: values.scheduledDate?.toISOString(),
targetRooms: values.targetRooms || [],
targetRacks: values.targetRacks || [],
};
if (editingPlan) {
await api.put(`/inventory/plans/${editingPlan.planId}`, data);
message.success('更新成功');
} else {
await api.post('/inventory/plans', data);
message.success('创建成功');
}
setModalVisible(false);
fetchPlans();
fetchStats();
} catch (error) {
message.error(error.response?.data?.error || '操作失败');
}
};
const handleStart = async plan => {
try {
await api.post(`/inventory/plans/${plan.planId}/start`);
message.success('盘点任务已启动');
fetchPlans();
fetchStats();
} catch (error) {
message.error(error.response?.data?.error || '启动失败');
}
};
const handleComplete = async plan => {
try {
await api.post(`/inventory/plans/${plan.planId}/complete`);
message.success('盘点已完成');
fetchPlans();
fetchStats();
} catch (error) {
message.error(error.response?.data?.error || '完成失败');
}
};
const handleViewTasks = plan => {
navigate(`/inventory/execution?planId=${plan.planId}`);
};
const handleRoomsChange = roomIds => {
setSelectedRooms(roomIds || []);
if (!roomIds || roomIds.length === 0) {
setFilteredRacks(racks);
} else {
const filtered = racks.filter(
rack => roomIds.includes(rack.roomId) || (rack.Room && roomIds.includes(rack.Room.roomId))
);
setFilteredRacks(filtered);
}
};
const getStatusTag = status => {
const statusMap = {
draft: { color: 'default', text: '草稿', icon: