import { MyBetaModalFormProps, MyButtons } from '@/common'; import { MyModal } from '@/components/MyModal'; import { Apis } from '@/gen/Apis'; import { ProCard } from '@ant-design/pro-components'; import { Alert, Button, Checkbox, message, Space, Tree, Typography, } from 'antd'; import { CheckboxChangeEvent } from 'antd/es/checkbox'; import type { DataNode } from 'antd/es/tree'; import { useEffect, useRef, useState } from 'react'; const { Title } = Typography; interface TreeNodeType extends DataNode { id: number; key: string; title: string; isLeaf?: boolean; children?: TreeNodeType[]; asset_buildings_id?: number; asset_units_id?: number; } // 扩展 MyBetaModalFormProps 接口,添加 onCancel 属性 interface ChargeStandardHasHouseProps extends MyBetaModalFormProps { onCancel?: () => void; } export default function ChargeStandardHasHouse( props: ChargeStandardHasHouseProps, ) { const [treeData, setTreeData] = useState([]); const [expandedKeys, setExpandedKeys] = useState([]); const [checkedKeys, setCheckedKeys] = useState([]); const [selectedKeys, setSelectedKeys] = useState([]); const [autoExpandParent, setAutoExpandParent] = useState(true); const [loading, setLoading] = useState(false); const [selectAll, setSelectAll] = useState(false); const [selectedHouses, setSelectedHouses] = useState< { id: number; name: string }[] >([]); const modalRef: any = useRef(null); // 加载楼栋数据 const loadBuildings = async () => { setLoading(true); try { const res = await Apis.Asset.AssetBuildings.List({ asset_projects_id: props?.item?.asset_projects_id, }); if (res?.data) { const buildings = res.data.map((building: any) => ({ id: building.id, key: `building-${building.id}`, title: building.name, children: [], isLeaf: false, })); setTreeData(buildings); } } catch (error) { console.error('加载楼栋失败:', error); } finally { setLoading(false); } }; // 加载单元数据 const loadUnits = async (buildingId: number, buildingKey: string) => { setLoading(true); try { const res = await Apis.Asset.AssetUnits.List({ asset_projects_id: props?.item?.asset_projects_id, asset_buildings_id: buildingId, }); if (res?.data) { const units = res.data.map((unit: any) => ({ id: unit.id, key: `unit-${unit.id}`, title: unit.name, children: [], isLeaf: false, asset_buildings_id: buildingId, })); // 更新树形数据 const newTreeData = [...treeData]; const buildingNode = newTreeData.find( (node) => node.key === buildingKey, ); if (buildingNode) { buildingNode.children = units; } setTreeData(newTreeData); } } catch (error) { console.error('加载单元失败:', error); } finally { setLoading(false); } }; // 加载房屋数据 const loadHouses = async ( buildingId: number, unitId: number, unitKey: string, ) => { setLoading(true); try { const res = await Apis.Asset.AssetHouses.List({ asset_projects_id: props?.item?.asset_projects_id, asset_buildings_id: buildingId, asset_units_id: unitId, }); if (res?.data) { const houses = res.data.map((house: any) => ({ id: house.id, key: `house-${house.id}`, title: `${house.name} (${house.floor}层)`, isLeaf: true, asset_buildings_id: buildingId, asset_units_id: unitId, })); // 更新树形数据 const newTreeData = [...treeData]; const buildingNode = newTreeData.find( (node) => node.asset_buildings_id === undefined && node.id === buildingId, ); if (buildingNode && buildingNode.children) { const unitNode = buildingNode.children.find( (node) => node.key === unitKey, ); if (unitNode) { unitNode.children = houses; } } setTreeData(newTreeData); } } catch (error) { console.error('加载房屋失败:', error); } finally { setLoading(false); } }; // 初始化加载数据 useEffect(() => { if (props?.item?.asset_projects_id) { loadBuildings(); } else { console.warn('缺少 asset_projects_id 参数'); } }, [props?.item?.id]); // 处理节点展开 const onExpand = (expandedKeysValue: React.Key[]) => { setExpandedKeys(expandedKeysValue); setAutoExpandParent(false); }; // 处理节点选中 const onCheck = ( checkedKeysValue: | React.Key[] | { checked: React.Key[]; halfChecked: React.Key[] }, ) => { // 处理不同格式的返回值 const keys = Array.isArray(checkedKeysValue) ? checkedKeysValue : checkedKeysValue.checked; // 获取之前的选中状态,用于比较变化 const prevKeys = new Set(checkedKeys); const newKeys = new Set(keys); // 找出新取消选中的节点 const uncheckedKeys = [...prevKeys].filter((key) => !newKeys.has(key)); // 如果有节点被取消选中,同步取消其所有子节点 if (uncheckedKeys.length > 0) { const keysToRemove = new Set(); const findChildKeys = (nodes: TreeNodeType[], parentKey: React.Key) => { nodes.forEach((node) => { if (node.key === parentKey) { // 将当前节点及其所有子节点的key加入待移除集合 const collectKeys = (n: TreeNodeType) => { keysToRemove.add(n.key); if (n.children) { n.children.forEach(collectKeys); } }; collectKeys(node); } else if (node.children) { findChildKeys(node.children, parentKey); } }); }; uncheckedKeys.forEach((key) => { findChildKeys(treeData, key); }); // 从选中keys中移除所有需要取消的节点 const finalKeys = keys.filter((key) => !keysToRemove.has(key)); setCheckedKeys(finalKeys); } else { setCheckedKeys(keys); } // 收集所有选中的房屋 const selectedHousesList: { id: number; name: string }[] = []; // 遍历树形数据,收集选中节点下的所有房屋 const collectHouses = (nodes: TreeNodeType[], checkedKeys: React.Key[]) => { nodes.forEach((node) => { if (checkedKeys.includes(node.key)) { if (node.isLeaf) { // 如果是房屋节点,直接添加 selectedHousesList.push({ id: node.id, name: node.title as string, }); } else { // 如果是楼栋或单元节点,递归收集其下的所有房屋 if (node.children) { collectHouses(node.children, checkedKeys); } } } }); }; collectHouses(treeData, keys); setSelectedHouses(selectedHousesList); setSelectAll( selectedHousesList.length > 0 && selectedHousesList.length === treeData.reduce( (total, building) => total + (building.children?.reduce( (unitTotal, unit) => unitTotal + (unit.children?.length || 0), 0, ) || 0), 0, ), ); }; // 处理节点选择 const onSelect = (selectedKeysValue: React.Key[]) => { setSelectedKeys(selectedKeysValue); }; // 处理动态加载数据 const onLoadData = async (node: TreeNodeType) => { if (node.isLeaf) { return Promise.resolve(); } // 加载楼栋下的单元 if (node.key.toString().startsWith('building-')) { const buildingId = node.id; await loadUnits(buildingId, node.key as string); // 如果楼栋被选中,加载并选中其下所有单元和房屋 if (checkedKeys.includes(node.key)) { const newTreeData = [...treeData]; const buildingNode = newTreeData.find((n) => n.key === node.key); if (buildingNode?.children) { // 加载每个单元下的房屋 for (const unit of buildingNode.children) { await loadHouses(buildingId, unit.id, unit.key as string); } // 更新树形数据 setTreeData(newTreeData); // 收集所有房屋的key const allKeys: React.Key[] = []; const collectKeys = (nodes: TreeNodeType[]) => { nodes.forEach((node) => { allKeys.push(node.key); if (node.children) { collectKeys(node.children); } }); }; collectKeys([buildingNode]); // 更新选中状态 setCheckedKeys(Array.from(new Set([...checkedKeys, ...allKeys]))); } } return Promise.resolve(); } // 加载单元下的房屋 if (node.key.toString().startsWith('unit-')) { const unitId = node.id; const buildingId = node.asset_buildings_id as number; await loadHouses(buildingId, unitId, node.key as string); // 如果单元被选中,选中其下所有房屋 if (checkedKeys.includes(node.key)) { const newTreeData = [...treeData]; const buildingNode = newTreeData.find((n) => n.children?.some((unit) => unit.key === node.key), ); const unitNode = buildingNode?.children?.find( (n) => n.key === node.key, ); if (unitNode?.children) { const houseKeys = unitNode.children.map((house) => house.key); setCheckedKeys(Array.from(new Set([...checkedKeys, ...houseKeys]))); } } return Promise.resolve(); } return Promise.resolve(); }; // 处理全选 const handleSelectAll = (e: CheckboxChangeEvent) => { setSelectAll(e.target.checked); if (e.target.checked) { // 收集所有房屋节点的key const allHouseKeys: React.Key[] = []; const allHouses: { id: number; name: string }[] = []; treeData.forEach((building) => { building.children?.forEach((unit) => { unit.children?.forEach((house) => { if (house.isLeaf) { allHouseKeys.push(house.key); allHouses.push({ id: house.id, name: house.title as string, }); } }); }); }); setCheckedKeys(allHouseKeys); setSelectedHouses(allHouses); } else { // 取消全选 setCheckedKeys([]); setSelectedHouses([]); } }; // 提交选中的房屋 const handleSubmit = async () => { if (selectedHouses.length === 0) { message.warning('请至少选择一个房屋'); return; } try { setLoading(true); // 将 number[] 转换为 string[] const houses_ids = selectedHouses.map((house) => house.id.toString()); await Apis.HouseCharage.HouseChargeHasHouses.Store({ house_charge_standards_id: props?.item?.id, houses_ids, }); message.success('绑定房屋成功'); props?.reload?.(); props?.onCancel?.(); } catch (error) { console.error('绑定房屋失败:', error); message.error('绑定房屋失败'); } finally { setLoading(false); } }; return ( } node={ } >
全选
{loading &&
加载中...
}
已选房屋 ({selectedHouses.length})
{selectedHouses.length > 0 ? (
    {selectedHouses.map((house) => (
  • {house.name}
  • ))}
) : (
暂无选中房屋{' '}
)}
} /> ); }