feat: 月度数据-数据总览前后端

This commit is contained in:
LokerL 2024-09-12 16:50:29 +08:00
parent 6202f3765a
commit f10cb687fa
11 changed files with 347 additions and 51 deletions

View File

@ -1,11 +1,7 @@
package com.ruoyi.common.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import org.springframework.util.AntPathMatcher;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.text.StrFormatter;
@ -681,4 +677,27 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
}
return sb.toString();
}
public static String toLowerCaseCamelCase(String input) {
StringBuilder output = new StringBuilder();
String[] words = input.split("_");
output.append(words[0]);
for (int i = 1; i < words.length; i++) {
output.append(Character.toUpperCase(words[i].charAt(0)));
output.append(words[i].substring(1).toLowerCase());
}
return output.toString();
}
public static final List<Map<String, Object>> camelCaseMapListKey(List<Map<String, Object>> list) {
List<Map<String, Object>> result = new ArrayList<>();
for (Map<String, Object> map : list) {
Map<String, Object> lowerCaseMap = new HashMap<>();
for (String key : map.keySet()) {
lowerCaseMap.put(toLowerCaseCamelCase(key.toLowerCase()), map.get(key));
}
result.add(lowerCaseMap);
}
return result;
}
}

View File

@ -12,6 +12,7 @@ import com.ruoyi.project.oil.domain.monitor.ThDevice;
import com.ruoyi.project.oil.domain.monitor.ThDeviceReport;
import com.ruoyi.project.oil.service.IOilThDeviceService;
import com.ruoyi.project.oil.service.ThDeviceReportMonthService;
import com.ruoyi.project.oil.service.impl.OilThDeviceReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -32,6 +33,9 @@ public class OilStatisticsController extends BaseController {
@Autowired
private ThDeviceReportMonthService thDeviceReportMonthService;
@Autowired
private OilThDeviceReportService oilThDeviceReportService;
@GetMapping(value = "/getDeviceList/{id}")
public TableDataInfo getDeviceList(@PathVariable("id") Long id) {
startPage();
@ -77,7 +81,7 @@ public class OilStatisticsController extends BaseController {
public AjaxResult reportCenter(Long deptId, String month) {
List<Map<String, Object>> resultCurrMonth = oilThDeviceService.selectAllAvgByMonth(deptId, month);
// 根据month获取上个月 字符串 month: 2024-09 -> lastMonth: 2024-081月份的上个月是12月份
List<Map<String, Object>> resultLastMonth = oilThDeviceService.selectAllAvgByMonth(deptId, getLastMonth(month));
List<Map<String, Object>> resultLastMonth = oilThDeviceService.selectAllAvgByMonth(deptId, getPreviousMonth(month));
// 月度报表中的数据
List<Map<String, Object>> result = oilThDeviceService.selectDeptAvgByMonth(deptId, month);
// 将所有的数据放入一个map中
@ -88,7 +92,7 @@ public class OilStatisticsController extends BaseController {
return success(resultMap);
}
public static String getLastMonth(String month) {
public static String getPreviousMonth(String month) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
if (month.length() == 6) {
month = month.substring(0, 5) + "0" + month.substring(5);
@ -98,7 +102,7 @@ public class OilStatisticsController extends BaseController {
return lastMonthDate.format(formatter);
}
@GetMapping("/getDeviceReportMonthList")
@GetMapping("/monthData/getDeviceReportMonthList")
public TableDataInfo getDeviceReportMonthList(Long deptId, String year, String month, int pageNum, int pageSize) {
Page<Object> page = PageHelper.startPage(pageNum, pageSize);
List<Map<String, Object>> result = thDeviceReportMonthService.selectThDeviceReportMonthList(deptId, year, month);
@ -110,8 +114,20 @@ public class OilStatisticsController extends BaseController {
return rspData;
}
@PostMapping("/updateDeviceReportMonth")
@PostMapping("/monthData/updateDeviceReportMonth")
public AjaxResult updateDeviceReportMonth(@RequestBody ThDeviceReportMonth thDeviceReportMonth) {
return toAjax(thDeviceReportMonthService.updateThDeviceReportMonth(thDeviceReportMonth));
}
@GetMapping("/monthData/dataOverview")
public AjaxResult dataOverview(Long deptId, String month) {
List<Map<String, Object>> monthReportDataOverview = oilThDeviceReportService.monthReportDataOverview(deptId, month);
List<Map<String, Object>> preMonthReportDataOverview = oilThDeviceReportService.monthReportDataOverview(deptId, getPreviousMonth(month));
List<Map<String, Object>> monthReportDataOverviewDeviceDs = oilThDeviceReportService.monthReportDataOverviewDeviceDs(deptId, month);
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("monthReportDataOverview", monthReportDataOverview);
resultMap.put("preMonthReportDataOverview", preMonthReportDataOverview);
resultMap.put("monthReportDataOverviewDeviceDs", monthReportDataOverviewDeviceDs);
return success(resultMap);
}
}

View File

@ -52,4 +52,16 @@ public interface ThDeviceReportMapper {
*/
@MapKey("month")
List<Map<String, Object>> selectAllAvgByMonth(@Param("deptId") Long deptId, @Param("month") String month);
/**
* 按月度统计ds, gbz ,dbz的平均值
*/
@MapKey("month")
List<Map<String, Object>> monthReportDataOverview(@Param("deptId") Long deptId, @Param("month") String month);
/**
* 按月度统计ds, gbz ,dbz的平均值
*/
@MapKey("month")
List<Map<String, Object>> monthReportDataOverviewDeviceDs(@Param("deptId") Long deptId, @Param("month") String month);
}

View File

@ -0,0 +1,10 @@
package com.ruoyi.project.oil.service;
import java.util.List;
import java.util.Map;
public interface IOilThDeviceReportService {
List<Map<String, Object>> monthReportDataOverview(Long deptId, String month);
List<Map<String, Object>> monthReportDataOverviewDeviceDs(Long deptId, String month);
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.project.oil.service.impl;
import com.ruoyi.project.oil.mapper.ThDeviceReportMapper;
import com.ruoyi.project.oil.service.IOilThDeviceReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import static com.ruoyi.common.utils.StringUtils.camelCaseMapListKey;
@Service
public class OilThDeviceReportService implements IOilThDeviceReportService {
@Autowired
private ThDeviceReportMapper thDeviceReportMapper;
@Override
public List<Map<String, Object>> monthReportDataOverview(Long deptId, String month) {
return camelCaseMapListKey(thDeviceReportMapper.monthReportDataOverview(deptId, month));
}
@Override
public List<Map<String, Object>> monthReportDataOverviewDeviceDs(Long deptId, String month) {
return camelCaseMapListKey(thDeviceReportMapper.monthReportDataOverviewDeviceDs(deptId, month));
}
}

View File

@ -11,6 +11,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.ruoyi.common.utils.StringUtils.camelCaseMapListKey;
/**
* @author Lenovo
* @description 针对表TH_DEVICE_REPORT_MONTH1(设备月表)的数据库操作Service实现
@ -24,35 +26,13 @@ public class ThDeviceReportMonthServiceImpl implements ThDeviceReportMonthServic
@Override
public List<Map<String, Object>> selectThDeviceReportMonthList(Long deptId, String year, String month) {
// return thDeviceReportMonthMapper.selectThDeviceReportMonthList(deptId, year, month);
List<Map<String, Object>> result = new ArrayList<>();
List<Map<String, Object>> list = thDeviceReportMonthMapper.selectThDeviceReportMonthList(deptId, year, month);
for (Map<String, Object> map : list) {
Map<String, Object> lowerCaseMap = new HashMap<>();
for (String key : map.keySet()) {
lowerCaseMap.put(toLowerCaseCamelCase(key.toLowerCase()), map.get(key));
}
result.add(lowerCaseMap);
}
return result;
return camelCaseMapListKey(thDeviceReportMonthMapper.selectThDeviceReportMonthList(deptId, year, month));
}
@Override
public int updateThDeviceReportMonth(ThDeviceReportMonth thDeviceReportMonth) {
return thDeviceReportMonthMapper.updateThDeviceReportMonth(thDeviceReportMonth);
}
public static String toLowerCaseCamelCase(String input) {
StringBuilder output = new StringBuilder();
String[] words = input.split("_");
output.append(words[0]);
for (int i = 1; i < words.length; i++) {
output.append(Character.toUpperCase(words[i].charAt(0)));
output.append(words[i].substring(1).toLowerCase());
}
return output.toString();
}
}

View File

@ -122,4 +122,41 @@
AND TO_CHAR(d.report_time, 'YYYY-MM') = #{month}
GROUP BY TO_CHAR(d.report_time, 'YYYY-MM')
</select>
<select id="monthReportDataOverview" parameterType="map" resultType="map">
SELECT TO_CHAR(d.report_time, 'YYYY-MM') AS month,
ROUND(AVG(TO_NUMBER(d.ds)), 8) AS avg_ds,
ROUND(AVG(TO_NUMBER(d.dbz)), 8) AS avg_dbz,
ROUND(AVG(TO_NUMBER(d.gbz)), 8) AS avg_gbz
FROM th_device_report d
WHERE d.sn IN (SELECT d.sn
FROM th_device d
LEFT JOIN sys_dept p ON d.dept_id = p.dept_id
WHERE d.dept_id IN (SELECT dept_id
FROM sys_dept START WITH dept_id = #{deptId}
CONNECT BY PRIOR dept_id = parent_id))
AND TO_CHAR(d.report_time, 'YYYY-MM') = #{month}
GROUP BY TO_CHAR(d.report_time, 'YYYY-MM')
</select>
<select id="monthReportDataOverviewDeviceDs" parameterType="map" resultType="map">
SELECT d.sn,
p.dept_name,
pp.dept_name as "gang_qu",
ROUND(AVG(TO_NUMBER(d.ds)), 8) AS avg_ds
FROM th_device_report d
LEFT JOIN th_device td ON d.sn = td.sn
LEFT JOIN sys_dept p ON td.dept_id = p.dept_id
LEFT JOIN sys_dept pp ON p.parent_id = pp.dept_id
WHERE d.sn IN (SELECT d.sn
FROM th_device d
LEFT JOIN sys_dept p ON d.dept_id = p.dept_id
WHERE d.dept_id IN (SELECT dept_id
FROM sys_dept START WITH dept_id = #{deptId}
CONNECT BY PRIOR dept_id = parent_id))
AND TO_CHAR(d.report_time, 'YYYY-MM') = #{month}
GROUP BY d.sn, p.dept_name, pp.dept_name
ORDER BY pp.dept_name, p.dept_name
</select>
</mapper>

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getDeviceReportMonthList(params) {
return request({
url: '/statistics/getDeviceReportMonthList',
url: '/statistics/monthData/getDeviceReportMonthList',
params: params,
method: 'get',
})
@ -10,8 +10,16 @@ export function getDeviceReportMonthList(params) {
export function updateDeviceReportMonth(params) {
return request({
url: '/statistics/updateDeviceReportMonth',
url: '/statistics/monthData/updateDeviceReportMonth',
data: params,
method: 'post',
})
}
export function dataOverview(params) {
return request({
url: '/statistics/monthData/dataOverview',
params: params,
method: 'get',
})
}

View File

@ -38,6 +38,7 @@ import VueMeta from 'vue-meta'
// 字典数据组件
import DictData from '@/components/DictData'
import BaiduMap from 'vue-baidu-map'
import DeptTree from '@/components/DeptTree';
// 全局方法挂载
Vue.prototype.getDicts = getDicts
Vue.prototype.getConfigKey = getConfigKey
@ -50,6 +51,7 @@ Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
// 全局组件挂载
Vue.component('DeptTree', DeptTree)
Vue.component('DictTag', DictTag)
Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar)

View File

@ -27,7 +27,7 @@
>
<el-table-column prop="gangqu" label="归属港区" />
<el-table-column prop="deptName" label="归属企业" />
<el-table-column prop="deptId" label="部门编码" />
<el-table-column prop="sn" label="设备编码" />
<el-table-column prop="year" label="年份" />
<el-table-column prop="month" label="月份" />
<el-table-column prop="avgValue" label="平均值">
@ -67,7 +67,6 @@
</template>
<script>
import DeptTree from "@/components/DeptTree/index.vue";
import {
getDeviceReportMonthList,
updateDeviceReportMonth,
@ -75,9 +74,6 @@ import {
export default {
name: "CreateReport",
components: {
DeptTree,
},
data() {
return {
deptId: "",
@ -183,8 +179,6 @@ export default {
message: "取消修改",
});
});
// this.tableData[index].enable_edit = !this.tableData[index].enable_edit;
// this.tableData = [...this.tableData];
},
queryData() {
this.loading = true;

View File

@ -1,23 +1,212 @@
<template>
<div>
<h2>DataOverview</h2>
<el-row :gutter="10">
<el-col :span="6" style="margin-top: 10px; margin-bottom: 10px">
<dept-tree @deptChange="handleDeptChange" :showQuickGroup="true" />
</el-col>
<el-col :span="6" style="margin-top: 10px; margin-bottom: 10px">
<el-date-picker
v-model="dateValue"
type="month"
format="yyyy-MM"
value-format="yyyy-MM"
placeholder="选择月份"
@change="handleDateChange"
>
</el-date-picker>
</el-col>
<el-col :span="12">
<div class="export_btn"><el-button type="primary" icon="eel-icon-download" @click="exportToExcel">导出</el-button></div>
</el-col>
</el-row>
<el-row :gutter="10">
<div class="table-title">
<span>{{ dateValue.replace("-", "年") }}</span>
</div>
<el-table
:data="overViewTableData"
style="width: 100%"
:border="true"
:header-cell-style="headerStyle"
>
<el-table-column prop="month" label="名称">
<template slot-scope="scope">
{{ getTableFirstColumnName(scope.row) }}
</template>
</el-table-column>
<el-table-column
prop="avgDs"
label="读数"
align="center"
:formatter="dataFormatter"
></el-table-column>
<el-table-column
prop="avgDbz"
label="低报值"
align="center"
:formatter="dataFormatter"
></el-table-column>
<el-table-column
prop="avgGbz"
label="高报值"
align="center"
:formatter="dataFormatter"
></el-table-column>
</el-table>
<el-table
:data="cmDeviceDs"
style="width: 100%"
:border="true"
:header-cell-style="headerStyle"
>
<el-table-column prop="gangQu" label="港区"></el-table-column>
<el-table-column prop="deptName" label="企业名"></el-table-column>
<el-table-column prop="sn" label="设备编号"></el-table-column>
<el-table-column
prop="avgDs"
label="读数"
align="center"
:formatter="dataFormatter"
></el-table-column>
</el-table>
</el-row>
</div>
</template>
<script>
import * as XLSX from "xlsx";
import { dataOverview } from "@/api/statistics/monthData.js";
export default {
name: 'DataOverview',
name: "DataOverview",
data() {
return {
deptId: "",
deptName: "",
dateValue: "",
overViewTableData: [],
cmDeviceDs: [],
headerStyle: {
fontSize: '14px',
backgroundColor: '#f8f8f8',
color: '#333',
}
};
},
created() {
this.initDate();
},
methods: {
dataFormatter(row, column, cellValue, index) {
if (row.month === "") {
return cellValue;
}
return cellValue.toFixed(2);
},
initDate() {
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth() + 1;
const monthStr = month < 10 ? `0${month}` : month;
this.dateValue = `${year}-${monthStr}`;
},
handleDeptChange(value) {
this.deptId = value.deptId;
this.deptName = value.deptName;
this.queryData();
},
handleDateChange(value) {
this.queryData();
},
getTableFirstColumnName(row) {
if (row.month && row.month === this.month) {
return "本月均值";
}
if (row.month && row.month !== this.month) {
return "上月均值";
}
return "变化率";
},
queryData() {
dataOverview({
deptId: this.deptId,
month: this.dateValue,
}).then((res) => {
if (res.code === 200) {
const {
monthReportDataOverview: cmO,
preMonthReportDataOverview: pmO,
monthReportDataOverviewDeviceDs: cmDeviceDs,
} = res.data;
const currMonth = cmO[0];
const lastMonth = pmO[0];
const changeRate = {
month: "",
avgDs:
(
((currMonth.avgDs - lastMonth.avgDs) / lastMonth.avgDs) *
100
).toFixed(2) + "%",
avgDbz:
(
((currMonth.avgDbz - lastMonth.avgDbz) / lastMonth.avgDbz) *
100
).toFixed(2) + "%",
avgGbz:
(
((currMonth.avgGbz - lastMonth.avgGbz) / lastMonth.avgGbz) *
100
).toFixed(2) + "%",
};
this.overViewTableData = [currMonth, lastMonth, changeRate];
this.cmDeviceDs = cmDeviceDs;
}
});
},
exportToExcel() {
// 簿
const wb = XLSX.utils.book_new();
const filename = `${this.deptName} ${this.dateValue.replace("-", "年") + "月"}`;
//
const ws_name = "SheetJS";
const ws_data = [
[filename],
["名称", "读数", "低报值", "高报值"],
...this.overViewTableData.map(row => [this.getTableFirstColumnName(row), row.avgDs, row.avgDbz, row.avgGbz]),
["港区", "企业", "编号", "平均值"],
...this.cmDeviceDs.map(row => [row.gangQu, row.deptName, row.sn, row.avgDs]),
];
const ws = XLSX.utils.aoa_to_sheet(ws_data);
//
if(!ws['!merges']) ws['!merges'] = [];
ws['!merges'].push({s: {r: 0, c: 0}, e: {r: 0, c: 3}});
// 簿
XLSX.utils.book_append_sheet(wb, ws, ws_name);
XLSX.writeFile(wb, `${filename}.xlsx`);
},
},
};
</script>
<style scoped>
.table-title {
border: 1px solid #EBEEF5;
display: flex;
justify-content: center;
align-items: center;
height: 45px;
span {
font-size: 18px;
color: #333;
}
}
.export_btn {
padding: 10px;
display: flex;
justify-content: flex-end;
}
</style>