一、功能需求

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

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

二、功能分析

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

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/

  

【Java】在树结构中给节点追加数据的更多相关文章

  1. C#程序中:如何修改xml文件中的节点(数据)

    要想在web等程序中实现动态的数据内容给新(如网页中的Flash),不会更新xml文件中的节点(数据)是远远不够的,今天在这里说一个简单的xml文件的更新,方法比较基础,很适合初学者看的,保证一看就懂 ...

  2. C#程序中:如何向xml文件中插入节点(数据)

    向xml文件中动态的添加节点(数据)是一件很爽的事,可以给你的程序带来很多的方便,比如在web中,如果你的Flash用到了xml文件,这个方法可以让你在后台就轻轻松松的更新你的Flash内容哦!一起研 ...

  3. 在 Java 应用程序中绑定 Bean 和数据

    本指南介绍了 NetBeans IDE 对 Java 应用程序中 Bean 绑定和数据绑定的支持. 要学完本教程,您需要具备以下软件和资源. 软件或资源 要求的版本 NetBeans IDE 版本 7 ...

  4. [转载]Java读取Excel中的单元格数据

    目前网上能找到的读取Excel表格中数据的两种比较好的方案:PageOffice好用开发效率高:POI免费.供大家参考,针对具体情况选择具体方案. 1. PageOffice读取excel impor ...

  5. java将数据库中查询到的数据导入到Excel表格

    1.Maven需要的依赖 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> ...

  6. Java向数据库中一次性插入大量数据

    String sql = “insert into username.tablename(id) values(?)”; PreparedStatement stmt = conn.prepareSt ...

  7. java程序向hdfs中追加数据,异常以及解决方案

    今天在学习hdfs时,遇到问题,就是在向hdfs中追加数据总是报错,在经过好几个小时的努力之下终于将他搞定 解决方案如下:在hadoop的hdfs-sit.xml中添加一下三项 <propert ...

  8. java jxl 向Excel中追加数据而不覆盖原来数据的例子

    向先原来就有数据的Excel写数据是不会覆盖原有的数据,只是在追加数据. public class Excel {     public Excel() {     }     public void ...

  9. Java通过poi创建Excel文件并分页追加数据

    以下的main函数,先生成一个excel文件,并设置sheet的名称,设置excel头:而后,以分页的方式,向文件中追加数据 maven依赖 <dependency> <groupI ...

  10. POI向Excel中写入数据及追加数据

    import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import ...

随机推荐

  1. 椭圆曲线密码学(ECC)加解密,附带python代码

    想起来很久没写博客了,刚好今天要写实验报告,随便把之前的也完成吧 1.椭圆曲线概念 椭圆曲线在经过化解后,可以用这条式子表达:E:y²=x³+ax+b 其背后的密码学原理,是基于椭圆曲线离散对数问题, ...

  2. Qt信号与槽的使用

    参考视频:黑马程序员https://www.bilibili.com/video/BV1XW411x7NU?p=4 1  新建工程 先创建一个控件基础工程,创建后的界面如下: 主函数我们不需要修改,就 ...

  3. 【Java】JVM字节码分析

    一.功能 1.工作原理 2.解释和运行 jvm本质上是运行在计算机上的程序,负责运行java字节码文件 对字节码文件中的指令,实时的解释成机器码,供计算机执行 3.内存管理 自动为对象.方法等分配内存 ...

  4. 2023 Hive 面试大纲

    先说一些废话 总结一下Hive面试宝典中的要点,方便读者快速过一遍Hive面试所需要的知识点. 本文请搭配 Hive面试宝典 来食用更美味哟 ┗( ▔, ▔ )┛ 方便自己系统性回忆,根据*的数量来标 ...

  5. OpenCV简单实现AR需用到的算法函数介绍

    目前的AR需求(想要达到的目标) 公司目前的需求是要能够指定一个物体开始追踪,将一张预先准备好的图像覆盖在被追踪的物体上, 然后镜头偏转缩放各类操作,再转回来仍然可以识别到,并且同样依旧覆盖图片到先前 ...

  6. kettle从入门到精通 第三十三课 再谈 kettle 表输出 分区/分片

    1.之前第九章有讲过kettle 表输出步骤,里面有简单的提到过表输出步骤里面的表分区设置,这里详细介绍下. 表分区数据:选择此选项可根据"分区"字段中指定的日期字段的值将数据拆分 ...

  7. 微信小程序-手持弹幕_文字内容横屏滚动_小程序弹幕源码

    哈喽,大家好,我是SCLQ. 最近在抖音刷到手持弹幕的视频,觉得是一个非常有趣应用,在手持弹幕小程序这个软件当中,你可以设置很长一段话,很适合追星.挑战一下自己,做一个小程序的手持弹幕应用. 微信小程 ...

  8. 有点东西,template可以直接使用setup语法糖中的变量原来是因为这个

    前言 我们每天写vue3代码的时候都会使用到setup语法糖,那你知道为什么setup语法糖中的顶层绑定可以在template中直接使用的呢?setup语法糖是如何编译成setup函数的呢?本文将围绕 ...

  9. java读取txt文件行的两种方式对比

    import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import ja ...

  10. Excel Wps 透视表去重计数方法

    Excel Wps 透视表去重计数方法 在处理表格,遇到处理根据某个列去重后统计数量,而不是仅仅统计数量.在网上查找资料,不确定EXCEL或者WPS某个版本可以支持该功能的实现. 折中的方案,分两步来 ...