wangyunfei 2 weeks ago
parent 571efe96cb
commit da37f16483

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useMemo, useState } from 'react';
import { Select, Tree } from 'antd';
import styles from './BasicAttribute.less';
@ -13,33 +13,69 @@ const factoryOptions = [
{ label: '南京油库', value: 'nanjing' },
];
const treeData = [
const rawTreeData = [
{
title: '上海油库',
key: 'shanghai',
tag: { label: '油库', type: 'depot' },
children: [
{
title: '汽油罐区',
key: 'gasoline-area',
tag: { label: '罐区', type: 'area' },
children: [
{
title: '汽油调合罐组',
key: 'blend-group',
tag: { label: '罐组', type: 'group' },
children: [
{
title: 'T-101 汽油储罐',
key: 't101',
tag: { label: '储罐', type: 'tank' },
children: [
{ title: 'LT-101 液位变送器', key: 'lt101' },
{ title: 'TT-101 温度变送器', key: 'tt101' },
{ title: 'PT-101 压力变送器', key: 'pt101' },
{ title: 'P-101A 输送泵', key: 'p101a' },
{ title: 'P-101B 输送泵', key: 'p101b' },
{ title: 'SP-101 密度计', key: 'sp101' },
{
title: 'LT-101 液位变送器',
key: 'lt101',
tag: { label: '测点', type: 'sensor' },
},
{
title: 'TT-101 温度变送器',
key: 'tt101',
tag: { label: '测点', type: 'sensor' },
},
{
title: 'PT-101 压力变送器',
key: 'pt101',
tag: { label: '测点', type: 'sensor' },
},
{
title: 'P-101A 输送泵',
key: 'p101a',
tag: { label: '设备', type: 'device' },
},
{
title: 'P-101B 输送泵',
key: 'p101b',
tag: { label: '设备', type: 'device' },
},
{
title: 'SP-101 密度计',
key: 'sp101',
tag: { label: '测点', type: 'sensor' },
},
],
},
{ title: 'T-102 汽油储罐', key: 't102' },
{ title: 'T-103 汽油储罐', key: 't103' },
{
title: 'T-102 汽油储罐',
key: 't102',
tag: { label: '储罐', type: 'tank' },
},
{
title: 'T-103 汽油储罐',
key: 't103',
tag: { label: '储罐', type: 'tank' },
},
],
},
],
@ -47,15 +83,35 @@ const treeData = [
{
title: '柴油罐区',
key: 'diesel-area',
tag: { label: '罐区', type: 'area' },
},
{
title: '化危品库',
key: 'hazard',
tag: { label: '库区', type: 'depot' },
},
],
},
];
const TreeNodeTitle = ({ text, tag }) => (
<span className={styles.treeNodeTitle}>
<span className={styles.nodeText}>{text}</span>
{tag ? (
<span className={`${styles.nodeTag} ${styles[`tag-${tag.type}`] || ''}`}>
{tag.label}
</span>
) : null}
</span>
);
const formatTreeNodes = data =>
data.map(item => ({
key: item.key,
title: <TreeNodeTitle text={item.title} tag={item.tag} />,
children: item.children ? formatTreeNodes(item.children) : undefined,
}));
const infoCards = [
{
title: '基本信息',
@ -107,6 +163,10 @@ const infoCards = [
const BasicAttribute = () => {
const [buildingType, setBuildingType] = useState('plant');
const [factory, setFactory] = useState('all');
const [selectedKeys, setSelectedKeys] = useState(['t101']);
const [checkedKeys, setCheckedKeys] = useState(['t101']);
const treeData = useMemo(() => formatTreeNodes(rawTreeData), []);
return (
<div className={styles.container}>
@ -136,9 +196,17 @@ const BasicAttribute = () => {
<div className={styles.treeWrapper}>
<Tree
showIcon={false}
showLine={{ showLeafIcon: false }}
defaultExpandAll
checkable
selectable
treeData={treeData}
checkedKeys={checkedKeys}
selectedKeys={selectedKeys}
onCheck={keys => setCheckedKeys(keys.checked || keys)}
onSelect={keys => setSelectedKeys(keys)}
className={styles.tree}
virtual={false}
/>
</div>
</section>

@ -65,13 +65,70 @@
padding: 12px;
border: 1px solid #e4e9f2;
.tree :global(.ant-tree-node-content-wrapper) {
font-size: 13px;
padding: 4px 8px;
}
.tree {
height: 100%;
:global(.ant-tree) {
color: #1f2f3d;
}
:global(.ant-tree-treenode) {
display: flex;
align-items: center;
gap: 8px;
position: relative;
padding-right: 86px;
}
:global(.ant-tree-switcher) {
width: 18px;
color: #41c1c7;
position: absolute;
right: 60px;
top: 50%;
transform: translateY(-50%);
margin-left: 0;
}
.tree :global(.ant-tree-switcher) {
width: 18px;
:global(.ant-tree-switcher-line-icon) {
stroke: #a6c6d3;
}
:global(.ant-tree-node-content-wrapper) {
flex: 1;
width: 100%;
font-size: 13px;
padding: 4px 8px;
border-radius: 8px;
transition: background 0.2s ease;
}
:global(.ant-tree-node-content-wrapper:hover),
:global(.ant-tree-node-content-wrapper.ant-tree-node-selected) {
background: rgba(12, 141, 255, 0.12);
}
:global(.ant-tree-checkbox-inner) {
width: 14px;
height: 14px;
border-radius: 4px;
border-color: #6db8ff;
}
:global(.ant-tree-checkbox-checked .ant-tree-checkbox-inner),
:global(.ant-tree-checkbox-indeterminate .ant-tree-checkbox-inner) {
background: #0c8dff;
border-color: #0c8dff;
box-shadow: 0 2px 6px rgba(12, 141, 255, 0.35);
}
:global(.ant-tree-checkbox-checked .ant-tree-checkbox-inner::after) {
border-color: #fff;
}
:global(.ant-tree-line .ant-tree-switcher) {
background-color: transparent;
}
}
}
@ -140,13 +197,63 @@
}
}
.tree :global(.ant-tree-node-content-wrapper) {
font-size: 13px;
padding: 4px 8px;
.treeNodeTitle {
display: inline-flex;
align-items: center;
width: 100%;
gap: 12px;
position: relative;
padding-right: 64px;
}
.tree :global(.ant-tree-switcher) {
width: 18px;
.nodeText {
flex: 1;
color: #1f2f3d;
font-weight: 500;
}
.nodeTag {
min-width: 48px;
text-align: center;
padding: 2px 8px;
border-radius: 999px;
font-size: 12px;
font-weight: 600;
background: rgba(12, 141, 255, 0.08);
color: #0c8dff;
position: absolute;
right: 0;
margin-right: 0;
&.tag-depot {
background: rgba(30, 199, 188, 0.14);
color: #13a79c;
}
&.tag-area {
background: rgba(126, 196, 255, 0.22);
color: #0c8dff;
}
&.tag-group {
background: rgba(255, 193, 111, 0.2);
color: #d97a00;
}
&.tag-tank {
background: rgba(55, 172, 255, 0.2);
color: #0970c3;
}
&.tag-device {
background: rgba(161, 134, 255, 0.22);
color: #6b4de6;
}
&.tag-sensor {
background: rgba(75, 226, 183, 0.18);
color: #0d9b7d;
}
}
// @media (max-width: 1400px) {

Loading…
Cancel
Save