【Java】在树结构中给节点追加数据

一、功能需求

有个树状组件,展示区域层级,每个区域节点需要展示该地区下的统计信息

从来没做过,给我整不会了属实是

 

二、功能分析

原型有功能和老系统代码,查看源码后发现的结构框架

1、树组件是自己用ul + li 封装的,牛逼

2、数据加载逻辑是: 先加载区域树接口,然后加载区域所有统计数据的接口,

  再对树或者统计数据遍历,对节点进行赋值,完成渲染

3、统计数据的接口只提供有数据的区域

 

三、我的实现:

我菜逼写不来,想了想还是拿el-tree改改样式来实现

1、前端实现样式

<el-tree
  v-show="treeToggleFlag"
  ref="treeRef2"
  class="tree-expanded"
  node-key="regionCode"
  :default-expanded-keys="['360000']"
  highlight-current
  :expand-on-click-node="false"
  :data="treeData"
  :props="treeProps"
  @node-click="handleTreeNodeClick"
>
  <span slot-scope="{ node, data }" class="custom-tree-node2">
    <div class="region-bar"><span class="region-label">{{ node.label }}</span> <span class="link-color">数据统计</span></div>
    <div class="statistic-panel">
      <el-row :gutter="10">
        <el-col :span="12">
          <el-statistic group-separator="," :precision="2" :value="data.licenseCount" title="车牌号码" />
        </el-col>
        <el-col :span="12">
          <el-statistic group-separator="," :precision="2" :value="data.obuCount" title="ETC/MTC" />
        </el-col>
      </el-row>
      <el-row :gutter="10" style="margin-top: 10px;">
        <el-col :span="12">
          <el-statistic group-separator="," :precision="2" :value="data.apCount" title="行车记录仪" />
        </el-col>
        <el-col :span="12">
          <el-statistic group-separator="," :precision="2" :value="data.bleCount" title="车载蓝牙" />
        </el-col>
      </el-row>
      <el-row :gutter="10" style="margin-top: 10px;">
        <el-col :span="12">
          <el-statistic group-separator="," :precision="2" :value="data.allCount" title="设备总数" />
        </el-col>
        <el-col :span="12">
          <el-statistic title="设备在线率">
            <template slot="formatter">
              {{ data.onlineRatio }}
            </template>
          </el-statistic>
        </el-col>
      </el-row>
    </div>
  </span>
</el-tree>

组件需要的变量:

treeToggleFlag: false,
treeData: [],
treeProps: {
  label: 'regionName',
  children: 'subRegions'
},

点击事件:

handleTreeNodeClick(region, val2) {
  console.log(region, val2)
  this.currentRegion = { code: region.regionCode, level: region.levelNo }
  this.initializeOverviewData()
  this.trIdx = 0
  const option = this.tendencyRangeOption[this.trIdx]
  this.tendencyRangeChoose(option, this.trIdx)
},

修改的样式:

/* - - - - - - - - - - - 展开的树节点样式 - - - - - - - - - - - */
.custom-tree-node2 {
  display: block;
  width: 100%;
  /*flex: 1;*/
  /*display: flex;*/
  /*align-items: center;*/
  /*justify-content: space-between;*/
  /*font-size: 14px;*/
  /*color: white;*/
  /*padding-right: 8px;*/
  /*border: 1px dashed black;*/
}
.custom-tree-node2 .region-bar {
  width: 100%;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
.custom-tree-node2 .statistic-panel {
  width: 100%;
  height: 100%;
  margin-top: 10px;
}
.custom-tree-node2 .region-bar .region-label {
  color: white;
  font-size: 14px;
}
/*.custom-tree-node2 .region-bar .region-statistic {*/
  /*color: rgb(102, 177, 255);*/
/*}*/
/* 节点内容高度 */
/deep/ .tree-expanded .el-tree-node__content {
  height: 180px;
  width: 100%;
  border-bottom: #b8b9c226 1px dashed;
  background-color: #1A1F3E;
}
/* 点击选中的节点 */
/deep/ .el-tree-node:focus > .el-tree-node__content {
  background-color: #024588;
}
/* 高亮节点颜色 */
/deep/  .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
  background-color: #024588;
}
/* - - - - - - - - - - - 展开的树节点样式 - - - - - - - - - - - */
/* 没有展开且有子节点 */
/deep/ .el-tree .el-icon-caret-right:before {
  background: url("./../../../assets/image/draw-out.png") no-repeat 0 0;
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  margin-left: 3px;
  background-size: 16px 16px;
}
/* 已经展开且有子节点 */
/deep/ .el-tree .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
  background: url("./../../../assets/image/draw-back.png") no-repeat 0 0;
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  transform: rotate(-90deg);
  background-size: 16px 16px;
}
/* 没有子节点 */
/deep/ .el-tree .el-tree-node__expand-icon.is-leaf::before {
  background: none;
}
/* 统计数据样式 */
/deep/ .custom-tree-node2 .statistic-panel .el-statistic .con .number { color: white; font-size: 18px; }
/deep/ .custom-tree-node2 .statistic-panel .el-statistic .head { font-size: 13px; color: #989AA8;  }

  

实现效果:

做不到完全一样,但是想表达的东西到位了,我尽力了

 

2、数据来源解决

Java接口:

/**
 * @author OnCloud9
 * @date 2023/9/25 15:18
 * @description
 * @params []
 * @return java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Long>>
 */
@GetMapping("/region-count-data")
public Map<String, List<Map<String, Object>>> getStatisticDataRegionCountData() {
    return statisticDataService.getStatisticDataRegionCountData();
}

Service:

@Override
public Map<String, List<Map<String, Object>>> getStatisticDataRegionCountData() {
    /* distinct 获取存在数据的区域,无数据区域不查询 */
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DAY_OF_MONTH, -1);
    Date previousDate = calendar.getTime();
    String formatDate = DateUtil.format(previousDate, "yyyy-MM-dd");
    /* 查找当日统计的区域 */
    List<Map<String, Object>> regionData1 = obuStatisticService.selectAllRegionData(formatDate);
    List<Map<String, Object>> regionData2 = obuTDeviceService.selectAllRegionData();
    Map<String, List<Map<String, Object>>> result = new HashMap<>();
    result.put("list1", regionData1);
    result.put("list2", regionData2);
    return result;
}

统计表的SQL,三次分组查询Union结合成一张表结果:

SELECT 
 region_code AS regionCode, 
 SUM(license_count) AS licenseCount, 
 SUM(obu_count) AS obuCount, 
 SUM(ap_count) AS apCount, 
 SUM(ble_count) AS bleCount 
FROM obu_statistic 
WHERE statistic_day = #{formatDate} 
GROUP BY region_code 
UNION 
SELECT 
 CONCAT(LEFT(region_code, 4), '00') AS regionCode, 
 SUM(license_count) AS licenseCount, 
 SUM(obu_count) AS obuCount, 
 SUM(ap_count) AS apCount, 
 SUM(ble_count) AS bleCount 
FROM obu_statistic 
WHERE statistic_day = #{formatDate} 
GROUP BY LEFT(region_code, 4) 
UNION 
SELECT 
 CONCAT(LEFT(region_code, 2), '0000') AS regionCode, 
 SUM(license_count) AS licenseCount, 
 SUM(obu_count) AS obuCount, 
 SUM(ap_count) AS apCount, 
 SUM(ble_count) AS bleCount 
FROM obu_statistic 
WHERE statistic_day = #{formatDate} 
GROUP BY LEFT(region_code, 2)"

查询结果:

+------------+--------------+----------+---------+----------+
| regionCode | licenseCount | obuCount | apCount | bleCount |
+------------+--------------+----------+---------+----------+
| 360111     | 106777       | 104264   | 161533  | 246934   |
| 360100     | 106777       | 104264   | 161533  | 246934   |
| 360000     | 106777       | 104264   | 161533  | 246934   |
+------------+--------------+----------+---------+----------+

  

设备表的SQL需要统计设备在线率,这一步要把分组的表联表JOIN合并:

SELECT a.county_code, a.allCount, IFNULL(b.onlineCount, 0) AS onlineCount, ROUND(IFNULL(b.onlineCount, 0) / a.allCount, 4) AS onlineRatio
FROM (SELECT county_code, COUNT(county_code) AS allCount FROM obu_t_device GROUP BY county_code) AS a
LEFT JOIN (SELECT county_code, COUNT(county_code) AS onlineCount FROM obu_t_device WHERE run_status = 1 GROUP BY county_code) AS b
ON a.county_code = b.county_code
UNION 
SELECT a.county_code, a.allCount, IFNULL(b.onlineCount, 0) AS onlineCount, ROUND(IFNULL(b.onlineCount, 0) / a.allCount, 4) AS onlineRatio
FROM (SELECT CONCAT( LEFT(county_code, 4), '00') AS county_code, COUNT(1) AS allCount FROM obu_t_device GROUP BY CONCAT(LEFT(county_code, 4), '00')) AS a
LEFT JOIN (SELECT CONCAT( LEFT(county_code, 4), '00') AS county_code, COUNT(1) AS onlineCount FROM obu_t_device WHERE run_status = 1 GROUP BY CONCAT(LEFT(county_code, 4), '00')) AS b
ON a.county_code = b.county_code
UNION 
SELECT a.county_code, a.allCount, IFNULL(b.onlineCount, 0) AS onlineCount, ROUND(IFNULL(b.onlineCount, 0) / a.allCount, 4) AS onlineRatio
FROM (SELECT CONCAT( LEFT(county_code, 2), '0000') AS county_code, COUNT(1) AS allCount FROM obu_t_device GROUP BY CONCAT( LEFT(county_code, 2), '0000')) AS a
LEFT JOIN (SELECT CONCAT( LEFT(county_code, 2), '0000') AS county_code, COUNT(1) AS onlineCount FROM obu_t_device WHERE run_status = 1 GROUP BY CONCAT( LEFT(county_code, 2), '0000')) AS b
ON a.county_code = b.county_code

查询结果:

+-------------+----------+-------------+-------------+
| county_code | allCount | onlineCount | onlineRatio |
+-------------+----------+-------------+-------------+
| 360111      |        4 |           1 | 0.2500      |
| 360100      |        4 |           1 | 0.2500      |
| 360000      |        4 |           1 | 0.2500      |
+-------------+----------+-------------+-------------+

3、数据结果联动

async initializeTreeData() {
  const { data: treeData } = await getSysRegionTreeData('36', {})
  const { data: result } = await getStatisticDataRegionCountData()
  const list1 = result.list1
  const list2 = result.list2
  console.log(treeData)
  this.treeForeach(treeData, 'subRegions', node => {
    const d1 = list1.find(x => x.regionCode === node.regionCode)
    const d2 = list2.find(x => x.regionCode === node.regionCode)
    if (!d1 && !d2) {
      node.licenseCount = 0
      node.obuCount = 0
      node.apCount = 0
      node.bleCount = 0
      node.allCount = 0
      node.onlineCount = 0
      node.onlineRatio = `0%`
      return
    }
    if (d1) {
      const { licenseCount, obuCount, apCount, bleCount } = d1
      node.licenseCount = licenseCount
      node.obuCount = obuCount
      node.apCount = apCount
      node.bleCount = bleCount
    }
    if (d2) {
      const { allCount, onlineCount, onlineRatio } = d2
      node.allCount = allCount
      node.onlineCount = onlineCount
      node.onlineRatio = `${onlineRatio * 100}%`
    }
  })
  this.treeData = treeData
},

递归方法:

treeForeach(tree, childrenField, func) {
  tree.forEach(data => {
    func(data)
    data[childrenField] && this.treeForeach(data[childrenField], childrenField, func) // 遍历子树
  })
},

  

四、参考资料:

El-tree组件:

https://element.eleme.io/#/zh-CN/component/tree#scoped-slot

树结构的操作方法:

https://blog.csdn.net/OUalen/article/details/131438154

样式优化修改参考:

https://blog.csdn.net/Sabrina_cc/article/details/125319257

节点的操作图标:

https://www.iconfont.cn/

  

 

posted @ 2023-09-25 21:04  emdzz  阅读(220)  评论(0编辑  收藏  举报