165 lines
4.8 KiB
TypeScript
Executable File
165 lines
4.8 KiB
TypeScript
Executable File
import { Select, Spin } from "antd";
|
||
import { api } from "@nice/client";
|
||
import { useEffect, useState } from "react";
|
||
import React from "react";
|
||
interface DeviceTypeSelectProps {
|
||
value?: string;
|
||
onChange?: (value: string) => void;
|
||
placeholder?: string;
|
||
disabled?: boolean;
|
||
className?: string;
|
||
style?: React.CSSProperties;
|
||
systemTypeId?: string; // 添加网系类别ID作为过滤条件
|
||
}
|
||
export default function DeviceTypeSelect({
|
||
value,
|
||
onChange,
|
||
placeholder = "选择故障类型",
|
||
disabled = false,
|
||
className,
|
||
style,
|
||
systemTypeId,
|
||
}: DeviceTypeSelectProps) {
|
||
const [options, setOptions] = useState<{ label: string; value: string }[]>(
|
||
[]
|
||
);
|
||
const [loading, setLoading] = useState(false);
|
||
// 获取所有故障类型数据(包括子项)
|
||
const { data: allDeviceTypes, isLoading, refetch: refetchDeviceType } = api.term.findMany.useQuery({
|
||
where: {
|
||
taxonomy: { slug: "device_type" },
|
||
deletedAt: null,
|
||
},
|
||
include: {
|
||
children: true,
|
||
parent: {
|
||
select: {
|
||
id: true,
|
||
name: true,
|
||
taxonomyId: true,
|
||
},
|
||
},
|
||
},
|
||
orderBy: { order: "asc" },
|
||
});
|
||
// 获取网系类别下的所有故障
|
||
const { data: systemTypeTerms, refetch: refetchSystemType } = api.term.findMany.useQuery(
|
||
{
|
||
where: {
|
||
taxonomy: { slug: "system_type" },
|
||
id: systemTypeId,
|
||
deletedAt: null,
|
||
},
|
||
include: {
|
||
children: true, // 获取网系类别的直接子项(故障类型)
|
||
},
|
||
},
|
||
{
|
||
enabled: !!systemTypeId,
|
||
}
|
||
);
|
||
// 处理数据显示
|
||
useEffect(() => {
|
||
setLoading(isLoading);
|
||
if (allDeviceTypes) {
|
||
// 有选中的网系类别
|
||
if (systemTypeId && systemTypeTerms && systemTypeTerms.length > 0) {
|
||
const systemTerm = systemTypeTerms[0];
|
||
|
||
// 查找直接关联到此网系类别的故障类型ID
|
||
const childrenIds = (systemTerm as any).children?.map((child) => child.id) || [];
|
||
|
||
// 查找具有此网系类别parentId的故障类型
|
||
const relatedByParentId = allDeviceTypes.filter(
|
||
(device) => device.parentId === systemTypeId
|
||
);
|
||
|
||
// 查找所有与该网系类别直接相关的故障类型
|
||
const relatedDeviceTypes = allDeviceTypes.filter(
|
||
(device) =>
|
||
childrenIds.includes(device.id) || device.parentId === systemTypeId
|
||
);
|
||
|
||
console.log("已选系统:", systemTerm.name);
|
||
console.log("相关故障类型数量:", relatedDeviceTypes.length);
|
||
|
||
setOptions(
|
||
relatedDeviceTypes.map((term) => ({
|
||
label: term.name,
|
||
value: term.id,
|
||
}))
|
||
);
|
||
} else {
|
||
// 没有选中网系类别,显示所有故障类型(按系统分组)
|
||
const deviceTypesWithParent = allDeviceTypes.map((term) => {
|
||
// 只处理没有子项的故障类型(最底层的故障类型)
|
||
const parentName = (term as any).parent?.name || "";
|
||
const displayName = parentName
|
||
? `${parentName} - ${term.name}`
|
||
: term.name;
|
||
|
||
return {
|
||
label: displayName,
|
||
value: term.id,
|
||
};
|
||
});
|
||
|
||
setOptions(deviceTypesWithParent);
|
||
}
|
||
}
|
||
}, [systemTypeId, allDeviceTypes, systemTypeTerms, isLoading]);
|
||
|
||
// 当systemTypeId改变时,如果当前选中的故障类型不在新的网系类别下,则清空选择
|
||
useEffect(() => {
|
||
if (
|
||
systemTypeId &&
|
||
value &&
|
||
allDeviceTypes &&
|
||
systemTypeTerms &&
|
||
systemTypeTerms.length > 0
|
||
) {
|
||
const selectedDeviceType = allDeviceTypes.find((t) => t.id === value);
|
||
const systemTerm = systemTypeTerms[0];
|
||
const childrenIds = (systemTerm as any).children?.map((child) => child.id) || [];
|
||
|
||
// 检查所选故障类型是否与当前网系类别相关
|
||
if (
|
||
selectedDeviceType &&
|
||
selectedDeviceType.parentId !== systemTypeId &&
|
||
!childrenIds.includes(selectedDeviceType.id)
|
||
) {
|
||
onChange?.("");
|
||
}
|
||
}
|
||
}, [systemTypeId, value, allDeviceTypes, systemTypeTerms, onChange]);
|
||
|
||
// 如果真的需要在组件初始加载时获取一次数据,可以添加这个useEffect
|
||
useEffect(() => {
|
||
// 组件挂载时获取一次数据
|
||
refetchDeviceType();
|
||
refetchSystemType();
|
||
// 空依赖数组,只在组件挂载时执行一次
|
||
}, []);
|
||
|
||
return (
|
||
<Select
|
||
loading={loading}
|
||
value={value}
|
||
onChange={onChange}
|
||
options={options}
|
||
placeholder={placeholder}
|
||
disabled={disabled}
|
||
className={className}
|
||
style={style}
|
||
showSearch
|
||
filterOption={(input, option) =>
|
||
(option?.label?.toString() || "")
|
||
.toLowerCase()
|
||
.includes(input.toLowerCase())
|
||
}
|
||
allowClear
|
||
notFoundContent={loading ? <Spin size="small" /> : null}
|
||
/>
|
||
);
|
||
}
|