2025-05-20 10:29:13 +08:00
|
|
|
|
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
2025-05-29 11:14:03 +08:00
|
|
|
|
import {
|
|
|
|
|
Button,
|
|
|
|
|
DatePicker,
|
|
|
|
|
Form,
|
|
|
|
|
Input,
|
|
|
|
|
Modal,
|
|
|
|
|
Select,
|
|
|
|
|
AutoComplete,
|
|
|
|
|
Tag,
|
|
|
|
|
Dropdown,
|
|
|
|
|
Space,
|
2025-06-02 19:35:10 +08:00
|
|
|
|
Card,
|
|
|
|
|
Row,
|
|
|
|
|
Col,
|
|
|
|
|
Typography,
|
2025-05-29 11:14:03 +08:00
|
|
|
|
} from "antd";
|
2025-05-20 10:29:13 +08:00
|
|
|
|
import { useCallback, useEffect, useState, useRef } from "react";
|
|
|
|
|
import _ from "lodash";
|
|
|
|
|
import { useMainContext } from "../layout/MainProvider";
|
|
|
|
|
import DeviceTable from "./devicetable/page";
|
|
|
|
|
import DeviceModal from "./devicemodal/page";
|
|
|
|
|
import React from "react";
|
|
|
|
|
import {
|
|
|
|
|
SearchOutlined,
|
|
|
|
|
ReloadOutlined,
|
|
|
|
|
PlusOutlined,
|
|
|
|
|
ImportOutlined,
|
|
|
|
|
ExportOutlined,
|
|
|
|
|
UpOutlined,
|
|
|
|
|
DownOutlined,
|
2025-05-29 11:14:03 +08:00
|
|
|
|
HistoryOutlined,
|
|
|
|
|
CloseOutlined,
|
2025-06-02 19:35:10 +08:00
|
|
|
|
FilterOutlined,
|
|
|
|
|
DatabaseOutlined,
|
2025-05-20 10:29:13 +08:00
|
|
|
|
} from "@ant-design/icons";
|
|
|
|
|
import DepartmentSelect from "@web/src/components/models/department/department-select";
|
|
|
|
|
import SystemTypeSelect from "@web/src/app/main/devicepage/select/System-select";
|
|
|
|
|
import DeviceTypeSelect from "@web/src/app/main/devicepage/select/Device-select";
|
|
|
|
|
import dayjs from "dayjs";
|
2025-05-23 08:18:31 +08:00
|
|
|
|
import FixTypeSelect from "./select/Fix-select";
|
2025-05-29 11:14:03 +08:00
|
|
|
|
import { api } from "@nice/client";
|
|
|
|
|
|
|
|
|
|
const { RangePicker } = DatePicker;
|
2025-06-02 19:35:10 +08:00
|
|
|
|
const { Title } = Typography;
|
2025-05-20 10:29:13 +08:00
|
|
|
|
// 添加筛选条件类型
|
|
|
|
|
type SearchCondition = {
|
|
|
|
|
deletedAt: null;
|
|
|
|
|
systemType?: string;
|
|
|
|
|
deviceType?: string;
|
|
|
|
|
deptId?: string;
|
|
|
|
|
responsiblePerson?: { contains: string };
|
|
|
|
|
createdAt?: {
|
|
|
|
|
gte: string;
|
|
|
|
|
lte: string;
|
2025-05-26 10:13:21 +08:00
|
|
|
|
};
|
2025-05-20 10:29:13 +08:00
|
|
|
|
};
|
|
|
|
|
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 搜索历史类型
|
|
|
|
|
type SearchHistory = {
|
|
|
|
|
id: string;
|
|
|
|
|
keyword: string;
|
|
|
|
|
conditions: SearchCondition;
|
|
|
|
|
timestamp: number;
|
|
|
|
|
label: string; // 用于显示的标签
|
|
|
|
|
};
|
|
|
|
|
|
2025-05-20 10:29:13 +08:00
|
|
|
|
export default function DeviceMessage() {
|
|
|
|
|
const {
|
|
|
|
|
form,
|
|
|
|
|
formValue,
|
|
|
|
|
setFormValue,
|
|
|
|
|
setVisible,
|
|
|
|
|
setSearchValue,
|
|
|
|
|
editingRecord,
|
|
|
|
|
} = useMainContext();
|
2025-05-29 11:14:03 +08:00
|
|
|
|
|
2025-05-20 10:29:13 +08:00
|
|
|
|
// 控制展开/收起状态
|
|
|
|
|
const [expanded, setExpanded] = useState(false);
|
2025-05-29 11:14:03 +08:00
|
|
|
|
|
2025-05-20 10:29:13 +08:00
|
|
|
|
// 添加所有筛选条件的状态
|
|
|
|
|
const [selectedSystem, setSelectedSystem] = useState<string | null>(null);
|
2025-05-26 10:13:21 +08:00
|
|
|
|
const [selectedDeviceType, setSelectedDeviceType] = useState<string | null>(
|
|
|
|
|
null
|
|
|
|
|
);
|
|
|
|
|
const [selectedDept, setSelectedDept] = useState<string | null>(null);
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 修改为日期范围
|
|
|
|
|
const [dateRange, setDateRange] = useState<
|
|
|
|
|
[dayjs.Dayjs | null, dayjs.Dayjs | null] | null
|
|
|
|
|
>(null);
|
2025-05-20 10:29:13 +08:00
|
|
|
|
const [ipAddress, setIpAddress] = useState<string>("");
|
|
|
|
|
const [macAddress, setMacAddress] = useState<string>("");
|
|
|
|
|
const [serialNumber, setSerialNumber] = useState<string>("");
|
|
|
|
|
const [assetNumber, setAssetNumber] = useState<string>("");
|
|
|
|
|
const [manufacturer, setManufacturer] = useState<string>("");
|
|
|
|
|
const [model, setModel] = useState<string>("");
|
|
|
|
|
const [location, setLocation] = useState<string>("");
|
|
|
|
|
const [status, setStatus] = useState<string | null>(null);
|
|
|
|
|
const [selectedSystemTypeId, setSelectedSystemTypeId] = useState<string>("");
|
2025-05-23 08:18:31 +08:00
|
|
|
|
const [selectedFixType, setSelectedFixType] = useState<string | null>(null);
|
2025-05-20 10:29:13 +08:00
|
|
|
|
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 搜索历史相关状态
|
|
|
|
|
const [searchHistory, setSearchHistory] = useState<SearchHistory[]>([]);
|
|
|
|
|
const [searchKeyword, setSearchKeyword] = useState<string>("");
|
|
|
|
|
const [showHistory, setShowHistory] = useState(false);
|
|
|
|
|
|
2025-05-20 10:29:13 +08:00
|
|
|
|
// 创建ref以访问DeviceTable内部方法
|
|
|
|
|
const tableRef = useRef(null);
|
|
|
|
|
// 存储选中行的状态
|
|
|
|
|
const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
|
|
|
|
|
const [selectedData, setSelectedData] = useState<any[]>([]);
|
|
|
|
|
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 添加数据查询以获取名称信息
|
|
|
|
|
const { data: systemTypeTerms } = api.term.findMany.useQuery({
|
|
|
|
|
where: { taxonomy: { slug: "system_type" }, deletedAt: null },
|
|
|
|
|
orderBy: { order: "asc" },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const { data: deviceTypeTerms } = api.term.findMany.useQuery({
|
|
|
|
|
where: { taxonomy: { slug: "device_type" }, deletedAt: null },
|
|
|
|
|
orderBy: { order: "asc" },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const { data: departments } = api.department.findMany.useQuery({
|
|
|
|
|
where: { deletedAt: null },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 根据ID获取名称的辅助函数
|
|
|
|
|
const getSystemTypeName = (id: string) => {
|
|
|
|
|
const term = systemTypeTerms?.find((t) => t.id === id);
|
|
|
|
|
return term?.name || id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getDeviceTypeName = (id: string) => {
|
|
|
|
|
const term = deviceTypeTerms?.find((t) => t.id === id);
|
|
|
|
|
return term?.name || id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getDepartmentName = (id: string) => {
|
|
|
|
|
const dept = departments?.find((d) => d.id === id);
|
|
|
|
|
return dept?.name || id;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 初始化时加载搜索历史
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const savedHistory = localStorage.getItem("device-search-history");
|
|
|
|
|
if (savedHistory) {
|
|
|
|
|
try {
|
|
|
|
|
setSearchHistory(JSON.parse(savedHistory));
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("加载搜索历史失败:", error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
// 保存搜索历史到localStorage
|
|
|
|
|
const saveSearchHistory = (history: SearchHistory[]) => {
|
|
|
|
|
localStorage.setItem("device-search-history", JSON.stringify(history));
|
|
|
|
|
setSearchHistory(history);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 生成搜索标签 - 修改为显示名称而不是ID,并支持日期范围
|
|
|
|
|
const generateSearchLabel = (
|
|
|
|
|
conditions: SearchCondition,
|
|
|
|
|
keyword: string
|
|
|
|
|
) => {
|
|
|
|
|
const parts = [];
|
|
|
|
|
if (keyword) parts.push(`关键词: ${keyword}`);
|
|
|
|
|
if (conditions.systemType)
|
|
|
|
|
parts.push(`网系: ${getSystemTypeName(conditions.systemType)}`);
|
|
|
|
|
if (conditions.deviceType)
|
|
|
|
|
parts.push(`故障类型: ${getDeviceTypeName(conditions.deviceType)}`);
|
|
|
|
|
if (conditions.deptId)
|
|
|
|
|
parts.push(`单位: ${getDepartmentName(conditions.deptId)}`);
|
|
|
|
|
if (conditions.createdAt) {
|
|
|
|
|
const startDate = dayjs(conditions.createdAt.gte).format("YYYY-MM-DD");
|
|
|
|
|
const endDate = dayjs(conditions.createdAt.lte).format("YYYY-MM-DD");
|
|
|
|
|
if (startDate === endDate) {
|
|
|
|
|
parts.push(`日期: ${startDate}`);
|
|
|
|
|
} else {
|
|
|
|
|
parts.push(`日期: ${startDate} ~ ${endDate}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return parts.length > 0 ? parts.join(" | ") : "全部故障";
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 添加搜索历史
|
|
|
|
|
const addSearchHistory = (
|
|
|
|
|
conditions: SearchCondition,
|
|
|
|
|
keyword: string = ""
|
|
|
|
|
) => {
|
|
|
|
|
const newHistory: SearchHistory = {
|
|
|
|
|
id: Date.now().toString(),
|
|
|
|
|
keyword,
|
|
|
|
|
conditions,
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
label: generateSearchLabel(conditions, keyword),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const updatedHistory = [
|
|
|
|
|
newHistory,
|
|
|
|
|
...searchHistory.filter((h) => h.label !== newHistory.label),
|
|
|
|
|
].slice(0, 10); // 只保留最近10条
|
|
|
|
|
|
|
|
|
|
saveSearchHistory(updatedHistory);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 应用历史搜索 - 修改为支持日期范围
|
|
|
|
|
const applyHistorySearch = (history: SearchHistory) => {
|
|
|
|
|
const { conditions, keyword } = history;
|
|
|
|
|
|
|
|
|
|
// 恢复搜索条件
|
|
|
|
|
setSelectedSystem(conditions.systemType || null);
|
|
|
|
|
setSelectedDeviceType(conditions.deviceType || null);
|
|
|
|
|
setSelectedDept(conditions.deptId || null);
|
|
|
|
|
setSelectedFixType(conditions.responsiblePerson?.contains || null);
|
|
|
|
|
setSearchKeyword(keyword);
|
|
|
|
|
|
|
|
|
|
if (conditions.createdAt) {
|
|
|
|
|
const startDate = dayjs(conditions.createdAt.gte);
|
|
|
|
|
const endDate = dayjs(conditions.createdAt.lte);
|
|
|
|
|
setDateRange([startDate, endDate]);
|
|
|
|
|
} else {
|
|
|
|
|
setDateRange(null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 应用搜索条件
|
|
|
|
|
setSearchValue(conditions as any);
|
|
|
|
|
setShowHistory(false);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 删除搜索历史
|
|
|
|
|
const removeSearchHistory = (historyId: string, event: React.MouseEvent) => {
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
const updatedHistory = searchHistory.filter((h) => h.id !== historyId);
|
|
|
|
|
saveSearchHistory(updatedHistory);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 清空所有搜索历史
|
|
|
|
|
const clearAllHistory = () => {
|
|
|
|
|
saveSearchHistory([]);
|
|
|
|
|
};
|
|
|
|
|
|
2025-05-20 10:29:13 +08:00
|
|
|
|
const handleNew = () => {
|
|
|
|
|
form.setFieldsValue(formValue);
|
|
|
|
|
console.log(editingRecord);
|
|
|
|
|
setVisible(true);
|
|
|
|
|
};
|
|
|
|
|
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 查询按钮点击处理 - 修改为支持日期范围
|
2025-05-20 10:29:13 +08:00
|
|
|
|
const handleSearch = () => {
|
|
|
|
|
// 构建查询条件
|
|
|
|
|
const whereCondition: SearchCondition = {
|
|
|
|
|
deletedAt: null,
|
|
|
|
|
...(selectedSystem && { systemType: selectedSystem }),
|
|
|
|
|
...(selectedDeviceType && { deviceType: selectedDeviceType }),
|
2025-05-23 08:18:31 +08:00
|
|
|
|
...(selectedFixType && { deviceStatus: selectedFixType }),
|
2025-05-20 10:29:13 +08:00
|
|
|
|
...(selectedDept && { deptId: selectedDept }),
|
2025-05-29 11:14:03 +08:00
|
|
|
|
...(dateRange &&
|
|
|
|
|
dateRange[0] &&
|
|
|
|
|
dateRange[1] && {
|
|
|
|
|
createdAt: {
|
|
|
|
|
gte: dateRange[0].startOf("day").toISOString(),
|
|
|
|
|
lte: dateRange[1].endOf("day").toISOString(),
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
...(searchKeyword && {
|
|
|
|
|
OR: [
|
|
|
|
|
{ description: { contains: searchKeyword } },
|
|
|
|
|
{ location: { contains: searchKeyword } },
|
|
|
|
|
{ responsiblePerson: { contains: searchKeyword } },
|
|
|
|
|
],
|
2025-05-20 10:29:13 +08:00
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 添加到搜索历史
|
|
|
|
|
addSearchHistory(whereCondition, searchKeyword);
|
|
|
|
|
|
2025-05-20 10:29:13 +08:00
|
|
|
|
// 更新查询条件到全局上下文
|
|
|
|
|
setSearchValue(whereCondition as any);
|
|
|
|
|
};
|
|
|
|
|
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 重置按钮处理 - 修改为重置日期范围
|
2025-05-20 10:29:13 +08:00
|
|
|
|
const handleReset = () => {
|
|
|
|
|
setSelectedSystem(null);
|
|
|
|
|
setSelectedDeviceType(null);
|
|
|
|
|
setSelectedDept(null);
|
2025-05-29 11:14:03 +08:00
|
|
|
|
setDateRange(null); // 重置日期范围
|
|
|
|
|
setSearchKeyword("");
|
2025-05-20 10:29:13 +08:00
|
|
|
|
setIpAddress("");
|
|
|
|
|
setMacAddress("");
|
|
|
|
|
setSerialNumber("");
|
|
|
|
|
setAssetNumber("");
|
|
|
|
|
setManufacturer("");
|
|
|
|
|
setModel("");
|
|
|
|
|
setLocation("");
|
2025-05-29 11:14:03 +08:00
|
|
|
|
saveSearchHistory([]);
|
2025-05-20 10:29:13 +08:00
|
|
|
|
|
|
|
|
|
// 重置为只查询未删除的记录
|
|
|
|
|
setSearchValue({ deletedAt: null } as any);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 修复DepartmentSelect的onChange类型
|
|
|
|
|
const handleDeptChange = (value: string | string[]) => {
|
|
|
|
|
setSelectedDept(value as string);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理选择变更的回调
|
2025-05-26 10:13:21 +08:00
|
|
|
|
const handleSelectedChange = (keys: React.Key[], data: any[]) => {
|
2025-05-20 10:29:13 +08:00
|
|
|
|
console.log("选中状态变化:", keys.length);
|
|
|
|
|
setSelectedKeys(keys);
|
|
|
|
|
setSelectedData(data);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 处理导出按钮点击
|
|
|
|
|
const handleExport = () => {
|
|
|
|
|
if (tableRef.current) {
|
|
|
|
|
tableRef.current.handleExportSelected();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 系统类别变化处理
|
|
|
|
|
const handleSystemTypeChange = (value: string) => {
|
|
|
|
|
setSelectedSystemTypeId(value);
|
2025-05-26 10:13:21 +08:00
|
|
|
|
form.setFieldValue("deviceType", undefined); // 清空已选故障类型
|
2025-05-20 10:29:13 +08:00
|
|
|
|
};
|
|
|
|
|
|
2025-05-29 11:14:03 +08:00
|
|
|
|
// 搜索历史下拉菜单
|
|
|
|
|
const historyMenuItems = [
|
|
|
|
|
{
|
|
|
|
|
key: "header",
|
|
|
|
|
label: (
|
|
|
|
|
<div className="flex justify-between items-center p-2 border-b">
|
|
|
|
|
<span className="font-medium">搜索历史</span>
|
|
|
|
|
{searchHistory.length > 0 && (
|
|
|
|
|
<Button
|
|
|
|
|
type="link"
|
|
|
|
|
size="small"
|
|
|
|
|
onClick={clearAllHistory}
|
|
|
|
|
className="text-red-500"
|
|
|
|
|
>
|
|
|
|
|
清空全部
|
|
|
|
|
</Button>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
),
|
|
|
|
|
disabled: true,
|
|
|
|
|
},
|
|
|
|
|
...searchHistory.map((history) => ({
|
|
|
|
|
key: history.id,
|
|
|
|
|
label: (
|
|
|
|
|
<div
|
|
|
|
|
className="flex justify-between items-center p-2 hover:bg-gray-50 cursor-pointer"
|
|
|
|
|
onClick={() => applyHistorySearch(history)}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex-1">
|
|
|
|
|
<div className="text-sm font-medium truncate">{history.label}</div>
|
|
|
|
|
<div className="text-xs text-gray-500">
|
|
|
|
|
{dayjs(history.timestamp).format("MM-DD HH:mm")}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<Button
|
|
|
|
|
type="text"
|
|
|
|
|
size="small"
|
|
|
|
|
icon={<CloseOutlined />}
|
|
|
|
|
onClick={(e) => removeSearchHistory(history.id, e)}
|
|
|
|
|
className="ml-2 opacity-60 hover:opacity-100"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
),
|
|
|
|
|
})),
|
|
|
|
|
...(searchHistory.length === 0
|
|
|
|
|
? [
|
|
|
|
|
{
|
|
|
|
|
key: "empty",
|
|
|
|
|
label: (
|
|
|
|
|
<div className="text-center text-gray-500 p-4">暂无搜索历史</div>
|
|
|
|
|
),
|
|
|
|
|
disabled: true,
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
: []),
|
|
|
|
|
];
|
|
|
|
|
|
2025-05-20 10:29:13 +08:00
|
|
|
|
return (
|
2025-06-02 19:35:10 +08:00
|
|
|
|
<div className="min-h-screen bg-gray-50 p-4">
|
|
|
|
|
{/* 页面标题区域 */}
|
|
|
|
|
<div className="mb-6">
|
|
|
|
|
<Card className="shadow-sm border border-gray-200">
|
|
|
|
|
<div className="flex justify-between items-center">
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<div className="w-10 h-10 bg-blue-600 rounded-lg flex items-center justify-center">
|
|
|
|
|
<DatabaseOutlined className="text-lg text-white" />
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<Title level={3} className="!mb-0 text-gray-800">
|
|
|
|
|
故障收录检索
|
|
|
|
|
</Title>
|
|
|
|
|
<p className="text-gray-500 text-sm mt-1">
|
|
|
|
|
设备故障信息管理与查询系统
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex items-center gap-3">
|
|
|
|
|
<Dropdown
|
|
|
|
|
menu={{ items: historyMenuItems }}
|
|
|
|
|
trigger={["click"]}
|
|
|
|
|
open={showHistory}
|
|
|
|
|
onOpenChange={setShowHistory}
|
|
|
|
|
placement="bottomRight"
|
|
|
|
|
>
|
|
|
|
|
<Button
|
|
|
|
|
icon={<HistoryOutlined />}
|
|
|
|
|
className="border-gray-300 hover:border-blue-500 hover:text-blue-600"
|
|
|
|
|
>
|
|
|
|
|
历史
|
|
|
|
|
</Button>
|
|
|
|
|
</Dropdown>
|
|
|
|
|
<Button
|
|
|
|
|
type="primary"
|
|
|
|
|
icon={<PlusOutlined />}
|
|
|
|
|
onClick={handleNew}
|
|
|
|
|
className="bg-blue-600 hover:bg-blue-700 border-blue-600"
|
|
|
|
|
>
|
|
|
|
|
新建故障记录
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Card>
|
2025-05-20 15:37:08 +08:00
|
|
|
|
</div>
|
2025-05-29 11:14:03 +08:00
|
|
|
|
|
2025-06-02 19:35:10 +08:00
|
|
|
|
{/* 搜索筛选区域 */}
|
|
|
|
|
<Card className="mb-6 shadow-sm border border-gray-200">
|
|
|
|
|
<div className="mb-4">
|
|
|
|
|
<div className="flex items-center gap-2 mb-4">
|
|
|
|
|
<FilterOutlined className="text-gray-600" />
|
|
|
|
|
<span className="font-medium text-gray-700">筛选条件</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Row gutter={[16, 16]}>
|
|
|
|
|
<Col xs={24} sm={12} md={8} lg={6}>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<label className="text-sm font-medium text-gray-600">
|
|
|
|
|
网系类别
|
|
|
|
|
</label>
|
|
|
|
|
<SystemTypeSelect
|
|
|
|
|
value={selectedSystem}
|
|
|
|
|
onChange={(value) => {
|
|
|
|
|
setSelectedSystem(value);
|
|
|
|
|
setSelectedSystemTypeId(value || ""); // 同步更新
|
|
|
|
|
setSelectedDeviceType(null); // 清空故障类型选择
|
|
|
|
|
}}
|
|
|
|
|
placeholder="选择网系类别"
|
|
|
|
|
className="w-full"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col xs={24} sm={12} md={8} lg={6}>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<label className="text-sm font-medium text-gray-600">
|
|
|
|
|
故障类型
|
|
|
|
|
</label>
|
|
|
|
|
<DeviceTypeSelect
|
|
|
|
|
value={selectedDeviceType}
|
|
|
|
|
onChange={setSelectedDeviceType}
|
|
|
|
|
placeholder="选择故障类型"
|
|
|
|
|
className="w-full"
|
|
|
|
|
systemTypeId={selectedSystemTypeId}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col xs={24} sm={12} md={8} lg={6}>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<label className="text-sm font-medium text-gray-600">
|
|
|
|
|
故障状态
|
|
|
|
|
</label>
|
|
|
|
|
<FixTypeSelect
|
|
|
|
|
value={selectedFixType}
|
|
|
|
|
onChange={setSelectedFixType}
|
|
|
|
|
placeholder="选择故障状态"
|
|
|
|
|
className="w-full"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col xs={24} sm={12} md={8} lg={6}>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<label className="text-sm font-medium text-gray-600">
|
|
|
|
|
单位
|
|
|
|
|
</label>
|
|
|
|
|
<DepartmentSelect
|
|
|
|
|
placeholder="选择单位"
|
|
|
|
|
className="w-full"
|
|
|
|
|
value={selectedDept}
|
|
|
|
|
onChange={handleDeptChange}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col xs={24} sm={12} md={16} lg={12}>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<label className="text-sm font-medium text-gray-600">
|
|
|
|
|
时间范围
|
|
|
|
|
</label>
|
|
|
|
|
<RangePicker
|
|
|
|
|
placeholder={["开始日期", "结束日期"]}
|
|
|
|
|
className="w-full"
|
|
|
|
|
value={dateRange}
|
|
|
|
|
onChange={(dates) => setDateRange(dates)}
|
|
|
|
|
format="YYYY-MM-DD"
|
|
|
|
|
allowClear
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col xs={24} sm={12} md={8} lg={6}>
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
<label className="text-sm font-medium text-gray-600 opacity-0">
|
|
|
|
|
操作
|
|
|
|
|
</label>
|
|
|
|
|
<div className="flex gap-2">
|
|
|
|
|
<Button
|
|
|
|
|
type="primary"
|
|
|
|
|
icon={<SearchOutlined />}
|
|
|
|
|
onClick={handleSearch}
|
|
|
|
|
className="bg-blue-600 hover:bg-blue-700 border-blue-600"
|
|
|
|
|
block
|
|
|
|
|
>
|
|
|
|
|
查询
|
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
icon={<ReloadOutlined />}
|
|
|
|
|
onClick={handleReset}
|
|
|
|
|
className="border-gray-300 hover:border-gray-400"
|
|
|
|
|
>
|
|
|
|
|
重置
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Col>
|
|
|
|
|
</Row>
|
2025-05-20 10:29:13 +08:00
|
|
|
|
</div>
|
2025-05-29 11:14:03 +08:00
|
|
|
|
|
2025-06-02 19:35:10 +08:00
|
|
|
|
{/* 搜索历史标签 */}
|
|
|
|
|
{searchHistory.length > 0 && (
|
|
|
|
|
<div className="mt-4 p-4 bg-gray-50 rounded-lg border border-gray-200">
|
|
|
|
|
<div className="flex items-center gap-3 mb-3">
|
|
|
|
|
<HistoryOutlined className="text-gray-600" />
|
|
|
|
|
<span className="text-sm font-medium text-gray-700">
|
|
|
|
|
最近搜索
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-wrap gap-2">
|
|
|
|
|
{searchHistory.slice(0, 5).map((history) => (
|
|
|
|
|
<Tag
|
|
|
|
|
key={history.id}
|
|
|
|
|
className="cursor-pointer bg-white border-gray-300 text-gray-700 hover:bg-gray-50 hover:border-blue-400 hover:text-blue-600 transition-colors duration-200"
|
|
|
|
|
onClick={() => applyHistorySearch(history)}
|
|
|
|
|
closable
|
|
|
|
|
onClose={(e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
removeSearchHistory(history.id, e as any);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<span className="text-xs">
|
|
|
|
|
{history.label.length > 25
|
|
|
|
|
? `${history.label.substring(0, 25)}...`
|
|
|
|
|
: history.label}
|
|
|
|
|
</span>
|
|
|
|
|
</Tag>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
2025-05-29 11:14:03 +08:00
|
|
|
|
</div>
|
2025-06-02 19:35:10 +08:00
|
|
|
|
)}
|
|
|
|
|
</Card>
|
2025-05-29 11:14:03 +08:00
|
|
|
|
|
2025-06-02 19:35:10 +08:00
|
|
|
|
{/* 表格区域 */}
|
|
|
|
|
<Card className="shadow-sm border border-gray-200">
|
2025-05-26 10:13:21 +08:00
|
|
|
|
<DeviceTable ref={tableRef} onSelectedChange={handleSelectedChange} />
|
2025-05-20 15:37:08 +08:00
|
|
|
|
<DeviceModal />
|
2025-06-02 19:35:10 +08:00
|
|
|
|
</Card>
|
2025-05-20 10:29:13 +08:00
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|