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