浩杰测试bug优化
This commit is contained in:
parent
4f0183b6b9
commit
243696230a
|
@ -15,6 +15,7 @@ import {
|
||||||
ExclamationCircleOutlined,
|
ExclamationCircleOutlined,
|
||||||
ImportOutlined,
|
ImportOutlined,
|
||||||
ExportOutlined,
|
ExportOutlined,
|
||||||
|
DatabaseOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { utils, writeFile, read } from "xlsx";
|
import { utils, writeFile, read } from "xlsx";
|
||||||
|
@ -165,18 +166,22 @@ const DeviceTable = forwardRef(
|
||||||
dataIndex: "systemType",
|
dataIndex: "systemType",
|
||||||
key: "systemType",
|
key: "systemType",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => {
|
render: (text, record) => (
|
||||||
return getTermNameById(record.systemType, "system_type");
|
<span className="inline-block bg-blue-50 text-blue-700 px-2 py-1 rounded text-sm border border-blue-200">
|
||||||
},
|
{getTermNameById(record.systemType, "system_type")}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "故障类型",
|
title: "故障类型",
|
||||||
dataIndex: "deviceType",
|
dataIndex: "deviceType",
|
||||||
key: "deviceType",
|
key: "deviceType",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => {
|
render: (text, record) => (
|
||||||
return getTermNameById(record.deviceType, "device_type");
|
<span className="inline-block bg-gray-50 text-gray-700 px-2 py-1 rounded text-sm border border-gray-200">
|
||||||
},
|
{getTermNameById(record.deviceType, "device_type")}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "单位",
|
title: "单位",
|
||||||
|
@ -184,16 +189,15 @@ const DeviceTable = forwardRef(
|
||||||
key: "deptId",
|
key: "deptId",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
// 如果有部门关联,显示部门名称
|
const unitName =
|
||||||
if (record.deptId && (record as any)?.department?.name) {
|
(record as any)?.department?.name ||
|
||||||
return (record as any)?.department?.name;
|
record.responsiblePerson ||
|
||||||
}
|
"未知";
|
||||||
// 否则显示responsiblePerson(如果存在)
|
return (
|
||||||
if (record.responsiblePerson) {
|
<span className="inline-block bg-gray-50 text-gray-700 px-2 py-1 rounded text-sm border border-gray-200">
|
||||||
return record.responsiblePerson;
|
{unitName}
|
||||||
}
|
</span>
|
||||||
// 最后才显示未知
|
);
|
||||||
return "未知";
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -204,14 +208,11 @@ const DeviceTable = forwardRef(
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<div
|
<div
|
||||||
onClick={() => handleShowDesc(record)}
|
onClick={() => handleShowDesc(record)}
|
||||||
style={{
|
className="cursor-pointer p-2 bg-gray-50 hover:bg-blue-50 rounded border border-gray-200 hover:border-blue-300 transition-colors duration-200"
|
||||||
cursor: "pointer",
|
|
||||||
padding: "8px 0",
|
|
||||||
// backgroundColor: 'black',
|
|
||||||
fontWeight: "bold",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{text || "未命名故障"}
|
<span className="font-medium text-gray-800 hover:text-blue-700">
|
||||||
|
{text || "未命名故障"}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -224,30 +225,29 @@ const DeviceTable = forwardRef(
|
||||||
const statusConfig = {
|
const statusConfig = {
|
||||||
normal: {
|
normal: {
|
||||||
text: "已修复",
|
text: "已修复",
|
||||||
color: "success",
|
className: "bg-green-100 text-green-800 border-green-200",
|
||||||
},
|
},
|
||||||
maintenance: {
|
maintenance: {
|
||||||
text: "维修中",
|
text: "维修中",
|
||||||
color: "processing",
|
className: "bg-blue-100 text-blue-800 border-blue-200",
|
||||||
},
|
},
|
||||||
broken: {
|
broken: {
|
||||||
text: "未修复",
|
text: "未修复",
|
||||||
color: "error",
|
className: "bg-red-100 text-red-800 border-red-200",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = statusConfig[status] || {
|
const config = statusConfig[status] || {
|
||||||
text: "未知",
|
text: "未知",
|
||||||
color: "default",
|
className: "bg-gray-100 text-gray-800 border-gray-200",
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tag
|
<span
|
||||||
color={config.color}
|
className={`inline-block px-3 py-1 rounded-full text-sm font-medium border ${config.className}`}
|
||||||
style={{ minWidth: "60px", textAlign: "center" }}
|
|
||||||
>
|
>
|
||||||
{config.text}
|
{config.text}
|
||||||
</Tag>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -256,25 +256,30 @@ const DeviceTable = forwardRef(
|
||||||
dataIndex: "createdAt",
|
dataIndex: "createdAt",
|
||||||
key: "createdAt",
|
key: "createdAt",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (text, record) =>
|
render: (text, record) => (
|
||||||
record.createdAt
|
<span className="text-gray-600 text-sm">
|
||||||
? dayjs(record.createdAt).format("YYYY-MM-DD HH:mm:ss")
|
{record.createdAt
|
||||||
: "未知",
|
? dayjs(record.createdAt).format("YYYY-MM-DD HH:mm:ss")
|
||||||
|
: "未知"}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
key: "action",
|
key: "action",
|
||||||
align: "center",
|
align: "center",
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<div className="flex space-x-2 justify-center">
|
<div className="flex gap-2 justify-center">
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
key={record.id}
|
key={record.id}
|
||||||
onClick={() => handleEdit(record)}
|
onClick={() => handleEdit(record)}
|
||||||
|
className="bg-blue-600 hover:bg-blue-700 border-blue-600"
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
</Button>
|
</Button>
|
||||||
<Button danger onClick={() => handleDelete(record)}>
|
<Button danger onClick={() => handleDelete(record)} size="small">
|
||||||
删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -503,7 +508,7 @@ const DeviceTable = forwardRef(
|
||||||
单位: "单位名称",
|
单位: "单位名称",
|
||||||
故障名称: "示例故障名称",
|
故障名称: "示例故障名称",
|
||||||
故障状态: "未修复", // 可选值:已修复, 维修中, 未修复
|
故障状态: "未修复", // 可选值:已修复, 维修中, 未修复
|
||||||
描述: "这是一个示例描述",
|
描述: "示例描述",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -530,7 +535,7 @@ const DeviceTable = forwardRef(
|
||||||
const rowSelection = {
|
const rowSelection = {
|
||||||
selectedRowKeys,
|
selectedRowKeys,
|
||||||
onChange: onSelectChange,
|
onChange: onSelectChange,
|
||||||
columnWidth: 70,
|
columnWidth: 60,
|
||||||
columnTitle: (
|
columnTitle: (
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
@ -550,16 +555,28 @@ const DeviceTable = forwardRef(
|
||||||
onSelectChange(newSelectedRowKeys, checked ? devices : []);
|
onSelectChange(newSelectedRowKeys, checked ? devices : []);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<span className="ml-1.5 text-xs whitespace-nowrap">全选</span>
|
<span className="ml-1 text-xs text-gray-600 whitespace-nowrap items-center">
|
||||||
|
全选
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
preserveSelectedRowKeys: true, // 这个属性保证翻页时选中状态不丢失
|
preserveSelectedRowKeys: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const TableHeader = () => (
|
const TableHeader = () => (
|
||||||
<div className="w-full flex justify-between mb-2">
|
<div className="w-full flex justify-between items-center mb-4 p-4 bg-gray-50 rounded-lg border border-gray-200">
|
||||||
<span></span>
|
<div className="flex items-center gap-3">
|
||||||
<div className="flex space-x-2">
|
<div className="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center">
|
||||||
|
<DatabaseOutlined className="text-white text-sm" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="font-medium text-gray-800 mb-0">数据管理</h3>
|
||||||
|
<p className="text-sm text-gray-500">
|
||||||
|
{devices?.length ? `共 ${devices.length} 条记录` : "暂无数据"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
ref={uploadRef}
|
ref={uploadRef}
|
||||||
|
@ -569,34 +586,40 @@ const DeviceTable = forwardRef(
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
icon={<ImportOutlined />}
|
icon={<ImportOutlined />}
|
||||||
type="primary"
|
|
||||||
onClick={handleExportTemplate}
|
onClick={handleExportTemplate}
|
||||||
|
className="border-gray-300 hover:border-blue-500 hover:text-blue-600"
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
下载模板文件
|
下载模板
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
icon={<ImportOutlined />}
|
icon={<ImportOutlined />}
|
||||||
type="primary"
|
|
||||||
onClick={handleImportClick}
|
onClick={handleImportClick}
|
||||||
|
className="border-gray-300 hover:border-green-500 hover:text-green-600"
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
导入
|
导入数据
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
|
||||||
onClick={handleExportSelected}
|
onClick={handleExportSelected}
|
||||||
disabled={!selectedRowKeys || selectedRowKeys.length === 0}
|
disabled={!selectedRowKeys || selectedRowKeys.length === 0}
|
||||||
icon={<ExportOutlined />}
|
icon={<ExportOutlined />}
|
||||||
|
type={selectedRowKeys?.length > 0 ? "primary" : "default"}
|
||||||
|
className={
|
||||||
|
selectedRowKeys?.length > 0 ? "bg-blue-600 hover:bg-blue-700" : ""
|
||||||
|
}
|
||||||
|
size="small"
|
||||||
>
|
>
|
||||||
{selectedRowKeys?.length > 0
|
{selectedRowKeys?.length > 0
|
||||||
? `导出 (${selectedRowKeys.length})项数据`
|
? `导出 (${selectedRowKeys.length})`
|
||||||
: "导出选中数据"}
|
: "导出选中"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="space-y-4">
|
||||||
<TableHeader />
|
<TableHeader />
|
||||||
<Table
|
<Table
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
|
@ -606,57 +629,52 @@ const DeviceTable = forwardRef(
|
||||||
size="middle"
|
size="middle"
|
||||||
tableLayout="fixed"
|
tableLayout="fixed"
|
||||||
rowClassName={(record, index) =>
|
rowClassName={(record, index) =>
|
||||||
index % 2 === 0
|
`${
|
||||||
? "bg-white hover:bg-blue-100"
|
index % 2 === 0
|
||||||
: "bg-gray-100 hover:bg-blue-100"
|
? "bg-white hover:bg-blue-50"
|
||||||
|
: "bg-gray-50 hover:bg-blue-50"
|
||||||
|
} transition-colors duration-200`
|
||||||
}
|
}
|
||||||
onRow={(record) => {
|
onRow={(record) => ({
|
||||||
return {
|
style: { cursor: "pointer" },
|
||||||
style: { cursor: "pointer" },
|
})}
|
||||||
onMouseEnter: () => {},
|
onHeaderRow={() => ({
|
||||||
};
|
style: {
|
||||||
}}
|
backgroundColor: "#f8fafc",
|
||||||
onHeaderRow={() => {
|
},
|
||||||
return {
|
})}
|
||||||
style: {
|
|
||||||
backgroundColor: "#d6e4ff",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
scroll={{ x: "max-content" }}
|
scroll={{ x: "max-content" }}
|
||||||
pagination={{
|
pagination={{
|
||||||
position: ["bottomCenter"],
|
position: ["bottomCenter"],
|
||||||
className: "flex justify-center mt-4",
|
className: "mt-4",
|
||||||
pageSize: pageSize,
|
pageSize: pageSize,
|
||||||
current: currentPage,
|
current: currentPage,
|
||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
pageSizeOptions: ["10", "15", "20"],
|
pageSizeOptions: ["10", "15", "20"],
|
||||||
responsive: true,
|
responsive: true,
|
||||||
showTotal: (total, range) => `共${total} 条数据`,
|
showTotal: (total, range) => (
|
||||||
|
<span className="text-gray-600">
|
||||||
|
显示第 {range[0]}-{range[1]} 条,共 {total} 条数据
|
||||||
|
</span>
|
||||||
|
),
|
||||||
showQuickJumper: true,
|
showQuickJumper: true,
|
||||||
onChange: handlePageChange,
|
onChange: handlePageChange,
|
||||||
onShowSizeChange: handlePageSizeChange,
|
onShowSizeChange: handlePageSizeChange,
|
||||||
}}
|
}}
|
||||||
components={{
|
|
||||||
header: {
|
|
||||||
cell: (props) => (
|
|
||||||
<th
|
|
||||||
{...props}
|
|
||||||
style={{
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
overflow: "hidden",
|
|
||||||
textOverflow: "ellipsis",
|
|
||||||
textAlign: "center",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
bordered
|
bordered
|
||||||
className="device-table-no-wrap"
|
className="bg-white rounded-lg shadow-sm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* 简化的模态框 */}
|
||||||
<Modal
|
<Modal
|
||||||
title={currentDesc.title}
|
title={
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<DatabaseOutlined className="text-blue-600" />
|
||||||
|
<span className="text-lg font-medium text-gray-800">
|
||||||
|
{currentDesc.title}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
open={descModalVisible}
|
open={descModalVisible}
|
||||||
onCancel={() => setDescModalVisible(false)}
|
onCancel={() => setDescModalVisible(false)}
|
||||||
footer={[
|
footer={[
|
||||||
|
@ -664,22 +682,33 @@ const DeviceTable = forwardRef(
|
||||||
关闭
|
关闭
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
|
width={800}
|
||||||
>
|
>
|
||||||
<div className="py-4">
|
<div className="py-4 space-y-4">
|
||||||
<div className="text-lg font-medium mb-2">故障详情</div>
|
<div>
|
||||||
<div className="bg-gray-50 p-4 rounded-md whitespace-pre-wrap">
|
<div className="text-base font-medium mb-3 text-gray-800">
|
||||||
{currentDesc.desc}
|
故障详情
|
||||||
|
</div>
|
||||||
|
<div className="bg-gray-50 p-4 rounded-lg border border-gray-200">
|
||||||
|
<div className="text-gray-700 whitespace-pre-wrap leading-relaxed">
|
||||||
|
{currentDesc.desc}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* 添加附件展示区域 */}
|
|
||||||
{currentDesc?.id && (
|
{currentDesc?.id && (
|
||||||
<div className="mt-4">
|
<div>
|
||||||
<div className="text-lg font-medium mb-2">相关附件</div>
|
<div className="text-base font-medium mb-3 text-gray-800">
|
||||||
<ResourceFileList deviceId={currentDesc.id} />
|
相关附件
|
||||||
|
</div>
|
||||||
|
<div className="bg-white p-4 rounded-lg border border-gray-200">
|
||||||
|
<ResourceFileList deviceId={currentDesc.id} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,10 @@ import {
|
||||||
Tag,
|
Tag,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Space,
|
Space,
|
||||||
|
Card,
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
Typography,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { useCallback, useEffect, useState, useRef } from "react";
|
import { useCallback, useEffect, useState, useRef } from "react";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
@ -27,6 +31,8 @@ import {
|
||||||
DownOutlined,
|
DownOutlined,
|
||||||
HistoryOutlined,
|
HistoryOutlined,
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
|
FilterOutlined,
|
||||||
|
DatabaseOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import DepartmentSelect from "@web/src/components/models/department/department-select";
|
import DepartmentSelect from "@web/src/components/models/department/department-select";
|
||||||
import SystemTypeSelect from "@web/src/app/main/devicepage/select/System-select";
|
import SystemTypeSelect from "@web/src/app/main/devicepage/select/System-select";
|
||||||
|
@ -36,7 +42,7 @@ import FixTypeSelect from "./select/Fix-select";
|
||||||
import { api } from "@nice/client";
|
import { api } from "@nice/client";
|
||||||
|
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
|
const { Title } = Typography;
|
||||||
// 添加筛选条件类型
|
// 添加筛选条件类型
|
||||||
type SearchCondition = {
|
type SearchCondition = {
|
||||||
deletedAt: null;
|
deletedAt: null;
|
||||||
|
@ -378,112 +384,199 @@ export default function DeviceMessage() {
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-2 min-h-screen bg-white">
|
<div className="min-h-screen bg-gray-50 p-4">
|
||||||
<div className="flex justify-between items-center mb-4">
|
{/* 页面标题区域 */}
|
||||||
<h1 className="text-xl font-normal">故障收录检索</h1>
|
<div className="mb-6">
|
||||||
<div className="flex items-center gap-2 justify-end">
|
<Card className="shadow-sm border border-gray-200">
|
||||||
<Dropdown
|
<div className="flex justify-between items-center">
|
||||||
menu={{ items: historyMenuItems }}
|
<div className="flex items-center gap-3">
|
||||||
trigger={["click"]}
|
<div className="w-10 h-10 bg-blue-600 rounded-lg flex items-center justify-center">
|
||||||
open={showHistory}
|
<DatabaseOutlined className="text-lg text-white" />
|
||||||
onOpenChange={setShowHistory}
|
</div>
|
||||||
placement="bottomRight"
|
<div>
|
||||||
>
|
<Title level={3} className="!mb-0 text-gray-800">
|
||||||
<Button icon={<HistoryOutlined />} title="搜索历史">
|
故障收录检索
|
||||||
历史
|
</Title>
|
||||||
</Button>
|
<p className="text-gray-500 text-sm mt-1">
|
||||||
</Dropdown>
|
设备故障信息管理与查询系统
|
||||||
<Button type="primary" icon={<PlusOutlined />} onClick={handleNew}>
|
</p>
|
||||||
新建
|
</div>
|
||||||
</Button>
|
</div>
|
||||||
</div>
|
<div className="flex items-center gap-3">
|
||||||
</div>
|
<Dropdown
|
||||||
|
menu={{ items: historyMenuItems }}
|
||||||
<div className="flex flex-wrap items-center gap-2 mb-4">
|
trigger={["click"]}
|
||||||
<div className="flex-1 min-w-[200px]">
|
open={showHistory}
|
||||||
<SystemTypeSelect
|
onOpenChange={setShowHistory}
|
||||||
value={selectedSystem}
|
placement="bottomRight"
|
||||||
onChange={setSelectedSystem}
|
|
||||||
placeholder="选择网系类别"
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 min-w-[200px]">
|
|
||||||
<DeviceTypeSelect
|
|
||||||
value={selectedDeviceType}
|
|
||||||
onChange={setSelectedDeviceType}
|
|
||||||
placeholder="选择故障类型"
|
|
||||||
className="w-full"
|
|
||||||
systemTypeId={selectedSystemTypeId}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 min-w-[200px]">
|
|
||||||
<FixTypeSelect
|
|
||||||
value={selectedFixType}
|
|
||||||
onChange={setSelectedFixType}
|
|
||||||
placeholder="选择故障状态"
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 min-w-[200px]">
|
|
||||||
<DepartmentSelect
|
|
||||||
placeholder="单位"
|
|
||||||
className="w-full"
|
|
||||||
value={selectedDept}
|
|
||||||
onChange={handleDeptChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 min-w-[250px]">
|
|
||||||
<RangePicker
|
|
||||||
placeholder={["开始日期", "结束日期"]}
|
|
||||||
className="w-full"
|
|
||||||
value={dateRange}
|
|
||||||
onChange={(dates) => setDateRange(dates)}
|
|
||||||
format="YYYY-MM-DD"
|
|
||||||
allowClear
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Button type="primary" icon={<SearchOutlined />} onClick={handleSearch}>
|
|
||||||
查询
|
|
||||||
</Button>
|
|
||||||
<Button icon={<ReloadOutlined />} onClick={handleReset}>
|
|
||||||
重置
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 显示当前搜索历史标签 */}
|
|
||||||
{searchHistory.length > 0 && (
|
|
||||||
<div className="mb-4 flex items-center gap-3 p-3 bg-gray-50 rounded-lg border border-gray-200">
|
|
||||||
<div className="text-sm font-medium text-gray-700 whitespace-nowrap">
|
|
||||||
最近搜索:
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-wrap gap-2 flex-1 min-w-0">
|
|
||||||
{searchHistory.slice(0, 5).map((history) => (
|
|
||||||
<Tag
|
|
||||||
key={history.id}
|
|
||||||
className="cursor-pointer hover:bg-blue-50 transition-colors duration-200 border-blue-200 text-blue-700"
|
|
||||||
onClick={() => applyHistorySearch(history)}
|
|
||||||
closable
|
|
||||||
onClose={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
removeSearchHistory(history.id, e as any);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<span className="text-xs">
|
<Button
|
||||||
{history.label.length > 25
|
icon={<HistoryOutlined />}
|
||||||
? `${history.label.substring(0, 25)}...`
|
className="border-gray-300 hover:border-blue-500 hover:text-blue-600"
|
||||||
: history.label}
|
>
|
||||||
</span>
|
历史
|
||||||
</Tag>
|
</Button>
|
||||||
))}
|
</Dropdown>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={handleNew}
|
||||||
|
className="bg-blue-600 hover:bg-blue-700 border-blue-600"
|
||||||
|
>
|
||||||
|
新建故障记录
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Card>
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
<div>
|
{/* 搜索筛选区域 */}
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 搜索历史标签 */}
|
||||||
|
{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>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* 表格区域 */}
|
||||||
|
<Card className="shadow-sm border border-gray-200">
|
||||||
<DeviceTable ref={tableRef} onSelectedChange={handleSelectedChange} />
|
<DeviceTable ref={tableRef} onSelectedChange={handleSelectedChange} />
|
||||||
<DeviceModal />
|
<DeviceModal />
|
||||||
</div>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,15 +87,15 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
orderBy: { order: "asc" },
|
orderBy: { order: "asc" },
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlePageChange = (page: number, size: number) => {
|
const handlePageChange = (page: number, size: number) => {
|
||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
setPageSize(size);
|
setPageSize(size);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageSizeChange = (current: number, size: number) => {
|
const handlePageSizeChange = (current: number, size: number) => {
|
||||||
setCurrentPage(1); // 重置到第一页
|
setCurrentPage(1); // 重置到第一页
|
||||||
setPageSize(size);
|
setPageSize(size);
|
||||||
};
|
};
|
||||||
// 构建包含两种分类的树形数据
|
// 构建包含两种分类的树形数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (systemTypeTerms && deviceTypeTerms) {
|
if (systemTypeTerms && deviceTypeTerms) {
|
||||||
|
@ -261,14 +261,18 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: "确认删除",
|
title: "确认删除",
|
||||||
content: `确定要删除"${term.name}"吗?这将同时删除其下所有子项!`,
|
content: `确定要删除"${term.name}"吗?这将同时删除其下所有子项!`,
|
||||||
onOk: () => softDeleteByIds({ ids: [term.id] },{
|
onOk: () =>
|
||||||
onSuccess: () => {
|
softDeleteByIds(
|
||||||
message.success("删除成功");
|
{ ids: [term.id] },
|
||||||
},
|
{
|
||||||
onError: () => {
|
onSuccess: () => {
|
||||||
message.error("删除失败");
|
message.success("删除成功");
|
||||||
},
|
},
|
||||||
}),
|
onError: () => {
|
||||||
|
message.error("删除失败");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
});
|
});
|
||||||
refetchSystemType();
|
refetchSystemType();
|
||||||
refetchDeviceType();
|
refetchDeviceType();
|
||||||
|
@ -277,6 +281,12 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
if (!termName.trim() || !taxonomyId) return;
|
if (!termName.trim() || !taxonomyId) return;
|
||||||
|
|
||||||
|
// 如果是故障类型,上级分类为必填
|
||||||
|
if (taxonomyId === deviceTypeTaxonomy?.id && !parentId) {
|
||||||
|
message.error("故障类型必须选择上级分类(网系类别)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (editingTerm) {
|
if (editingTerm) {
|
||||||
updateTerm({
|
updateTerm({
|
||||||
where: { id: editingTerm.id },
|
where: { id: editingTerm.id },
|
||||||
|
@ -371,7 +381,7 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
<div className="p-6 min-h-screen bg-gray-50">
|
<div className="p-6 min-h-screen bg-gray-50">
|
||||||
{/* 主要内容卡片 */}
|
{/* 主要内容卡片 */}
|
||||||
<Card className="shadow-sm" bodyStyle={{ padding: 0 }}>
|
<Card className="shadow-sm" bodyStyle={{ padding: 0 }}>
|
||||||
{/* 统计信息区域 */}
|
{/* 统计信息区域 */}
|
||||||
<div className="p-4 bg-gray-50 border-b border-gray-100">
|
<div className="p-4 bg-gray-50 border-b border-gray-100">
|
||||||
<Row gutter={16} justify="center">
|
<Row gutter={16} justify="center">
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
|
@ -395,15 +405,15 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
{/* <Col span={8}> */}
|
{/* <Col span={8}> */}
|
||||||
{/* <div className="text-center"> */}
|
{/* <div className="text-center"> */}
|
||||||
{/* <div className="text-2xl font-bold text-orange-600">
|
{/* <div className="text-2xl font-bold text-orange-600">
|
||||||
{deviceTypeTerms?.filter(term =>
|
{deviceTypeTerms?.filter(term =>
|
||||||
!systemTypeTerms?.some(sysType => sysType.id === term.parentId) &&
|
!systemTypeTerms?.some(sysType => sysType.id === term.parentId) &&
|
||||||
deviceTypeTerms?.some(devType => devType.id === term.parentId)
|
deviceTypeTerms?.some(devType => devType.id === term.parentId)
|
||||||
).length || 0}
|
).length || 0}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-600">具体故障</div> */}
|
<div className="text-sm text-gray-600">具体故障</div> */}
|
||||||
{/* </div>
|
{/* </div>
|
||||||
</Col> */}
|
</Col> */}
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -438,8 +448,6 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* 表格区域 */}
|
{/* 表格区域 */}
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<Table
|
<Table
|
||||||
|
@ -455,7 +463,7 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
dataIndex: "name",
|
dataIndex: "name",
|
||||||
key: "name",
|
key: "name",
|
||||||
width: "50%", // 增加名称列的宽度
|
width: "50%", // 增加名称列的宽度
|
||||||
render: (text, record, index, ) => (
|
render: (text, record, index) => (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{/* 根据层级添加不同的图标 */}
|
{/* 根据层级添加不同的图标 */}
|
||||||
{record.taxonomyId === systemTypeTaxonomy?.id ? (
|
{record.taxonomyId === systemTypeTaxonomy?.id ? (
|
||||||
|
@ -537,7 +545,7 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
showSizeChanger: true,
|
showSizeChanger: true,
|
||||||
showQuickJumper: true,
|
showQuickJumper: true,
|
||||||
showTotal: (total) => `共 ${total} 条记录`,
|
showTotal: (total) => `共 ${total} 条记录`,
|
||||||
pageSizeOptions: [ "10", "15", "20"],
|
pageSizeOptions: ["10", "15", "20"],
|
||||||
onChange: handlePageChange,
|
onChange: handlePageChange,
|
||||||
onShowSizeChange: handlePageSizeChange,
|
onShowSizeChange: handlePageSizeChange,
|
||||||
}}
|
}}
|
||||||
|
@ -546,8 +554,8 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
record.taxonomyId === systemTypeTaxonomy?.id
|
record.taxonomyId === systemTypeTaxonomy?.id
|
||||||
? "bg-blue-25"
|
? "bg-blue-25"
|
||||||
: record.taxonomyId === deviceTypeTaxonomy?.id
|
: record.taxonomyId === deviceTypeTaxonomy?.id
|
||||||
? "bg-green-25"
|
? "bg-green-25"
|
||||||
: "bg-orange-25"
|
: "bg-orange-25"
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
onHeaderRow={() => ({
|
onHeaderRow={() => ({
|
||||||
|
@ -621,11 +629,27 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||||
上级分类
|
上级分类
|
||||||
|
{/* 根据分类类型动态显示是否必填 */}
|
||||||
|
{taxonomyId === deviceTypeTaxonomy?.id && (
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
)}
|
||||||
|
{/* 当选择故障类型时显示提示信息 */}
|
||||||
|
{taxonomyId === deviceTypeTaxonomy?.id && (
|
||||||
|
<div className="text-xs text-gray-500 mt-1 flex">
|
||||||
|
故障类型必须归属于某个网系类别
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</label>
|
</label>
|
||||||
<TreeSelect
|
<TreeSelect
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
dropdownStyle={{ maxHeight: 400, overflow: "auto" }}
|
dropdownStyle={{ maxHeight: 400, overflow: "auto" }}
|
||||||
placeholder="请选择上级分类(可选)"
|
placeholder={
|
||||||
|
taxonomyId === systemTypeTaxonomy?.id
|
||||||
|
? "请选择上级网系(可选)"
|
||||||
|
: taxonomyId === deviceTypeTaxonomy?.id
|
||||||
|
? "请选择上级网系类别(必选)"
|
||||||
|
: "请选择上级分类(可选)"
|
||||||
|
}
|
||||||
allowClear
|
allowClear
|
||||||
treeDefaultExpandAll
|
treeDefaultExpandAll
|
||||||
value={parentId}
|
value={parentId}
|
||||||
|
@ -633,6 +657,7 @@ export default function DeviceManager({ title }: TermManagerProps) {
|
||||||
treeData={getParentOptions()}
|
treeData={getParentOptions()}
|
||||||
size="large"
|
size="large"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -76,10 +76,10 @@ export default function DeviceTypeSelect({
|
||||||
|
|
||||||
// 查找所有与该网系类别直接相关的故障类型
|
// 查找所有与该网系类别直接相关的故障类型
|
||||||
const relatedDeviceTypes = allDeviceTypes.filter(
|
const relatedDeviceTypes = allDeviceTypes.filter(
|
||||||
(device) =>
|
// (device) =>
|
||||||
childrenIds.includes(device.id) || device.parentId === systemTypeId
|
// childrenIds.includes(device.id) || device.parentId === systemTypeId
|
||||||
|
(device) => device.parentId === systemTypeId
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("已选系统:", systemTerm.name);
|
console.log("已选系统:", systemTerm.name);
|
||||||
console.log("相关故障类型数量:", relatedDeviceTypes.length);
|
console.log("相关故障类型数量:", relatedDeviceTypes.length);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue