From 160650c0862c4077191b66356db6385e1c48f412 Mon Sep 17 00:00:00 2001 From: huguanghan Date: Mon, 13 Jan 2025 17:33:39 +0800 Subject: [PATCH 01/20] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=A4=87=E4=BB=BD?= =?UTF-8?q?=E6=96=B0=E5=A2=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/data/service/TDEngineService.java | 3 + .../data/service/impl/DataServiceImpl.java | 1 + .../service/impl/ExportTdDataServiceImpl.java | 120 ++++++++++++++++++ das/src/main/resources/application-dev.yml | 4 +- das/src/main/resources/application.yml | 4 +- 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java diff --git a/das/src/main/java/com/das/modules/data/service/TDEngineService.java b/das/src/main/java/com/das/modules/data/service/TDEngineService.java index 184ed25a..625ab571 100644 --- a/das/src/main/java/com/das/modules/data/service/TDEngineService.java +++ b/das/src/main/java/com/das/modules/data/service/TDEngineService.java @@ -67,6 +67,9 @@ public class TDEngineService { } } + public HikariDataSource getHikariDataSource(){ + return hikariDataSource; + } /** * 创建超级表 */ diff --git a/das/src/main/java/com/das/modules/data/service/impl/DataServiceImpl.java b/das/src/main/java/com/das/modules/data/service/impl/DataServiceImpl.java index e88d9d07..3495fd23 100644 --- a/das/src/main/java/com/das/modules/data/service/impl/DataServiceImpl.java +++ b/das/src/main/java/com/das/modules/data/service/impl/DataServiceImpl.java @@ -25,6 +25,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StopWatch; +import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; diff --git a/das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java b/das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java new file mode 100644 index 00000000..4bd1aecc --- /dev/null +++ b/das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java @@ -0,0 +1,120 @@ +package com.das.modules.data.service.impl; + +import cn.hutool.core.util.ZipUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.das.modules.data.service.TDEngineService; +import com.das.modules.equipment.entity.SysEquipment; +import com.das.modules.equipment.mapper.SysEquipmentMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.util.StopWatch; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.sql.*; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +public class ExportTdDataServiceImpl { + + @Autowired + SysEquipmentMapper sysEquipmentMapper; + + @Autowired + private TDEngineService tdEngineService; + + @Value("${zipUrl}") + private String fileUrl; + + + public void exportDataCsvZip() throws IOException, SQLException { + StopWatch stopWatch = new StopWatch(); + stopWatch.start("导出风机数据zip"); + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, -1); + String yesterday = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()); + + //获取所有风机数据 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("object_type", 10002); + List sysEquipments = sysEquipmentMapper.selectList(queryWrapper); + //获取临时目录文件路径 + String tempDir = String.valueOf(Files.createTempDirectory(null)); + File zipFile = new File(fileUrl + "/data_"+yesterday+".zip"); + List fileList = new ArrayList<>(); + try { + for (SysEquipment item : sysEquipments) { + + String hTableName = "h" + item.getId(); + String lTableName = "l" + item.getId(); + File fileHighSpeed = new File(tempDir +"/" + "h_"+item.getCode()+"_"+yesterday + ".csv"); + File fileLowSpeed = new File(tempDir +"/" + "l_"+item.getCode()+"_"+yesterday + ".csv"); + getYesterdayData(hTableName, yesterday, fileHighSpeed.getPath()); + getYesterdayData(lTableName, yesterday, fileLowSpeed.getPath()); + fileList.add(fileLowSpeed); + fileList.add(fileHighSpeed); + } + //压缩文件 + // 将文件添加到压缩文件中 + ZipUtil.zip(zipFile, false, fileList.toArray(new File[0])); + stopWatch.stop(); + log.debug(stopWatch.prettyPrint(TimeUnit.SECONDS)); + }catch (Exception e){ + log.error("导出风机数据zip失败{}",e); + } +// finally { +// if (!CollectionUtils.isEmpty(fileList)){ +// FileUtil.del(new File(fileList.get(0).getParent())); +// } +// } + + } + + public void getYesterdayData(String tableName, String time, String csvFilePath) { + // TDengine 查询语句 + String query = "SELECT * FROM " + tableName + " WHERE updatetime >= '" + time + " 00:00:00' AND updatetime < '" + time + " 23:59:59.999'"; + try (Connection conn = tdEngineService.getHikariDataSource().getConnection(); + Statement smt = conn.createStatement(); + ResultSet rs = smt.executeQuery(query)) { + writeResultSetToCsv(rs, csvFilePath); + }catch (Exception e){ + log.error(tableName +"获取数据异常{}",e); + } + + } + + private void writeResultSetToCsv(ResultSet resultSet, String csvFilePath) throws IOException, SQLException { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvFilePath))) { + // 写入列名 + ResultSetMetaData metaData = resultSet.getMetaData(); + int columnCount = metaData.getColumnCount(); + for (int i = 1; i <= columnCount; i++) { + writer.write(metaData.getColumnName(i)); + if (i < columnCount) writer.write(","); + } + writer.newLine(); + + // 写入数据 + while (resultSet.next()) { + for (int i = 1; i <= columnCount; i++) { + String value = resultSet.getString(i); + writer.write(value == null ? "" : resultSet.getString(i)); + if (i < columnCount) writer.write(","); + } + writer.newLine(); + } + }catch (Exception e){ + log.error("数据写入csv文件失败{}",e); + } + } +} diff --git a/das/src/main/resources/application-dev.yml b/das/src/main/resources/application-dev.yml index bb481740..1c1a88fb 100644 --- a/das/src/main/resources/application-dev.yml +++ b/das/src/main/resources/application-dev.yml @@ -110,4 +110,6 @@ minio: url: http://192.168.109.187:9000 bucket: das accessKey: das - secretKey: zaq12WSX \ No newline at end of file + secretKey: zaq12WSX + +zipUrl: /log/zip/ \ No newline at end of file diff --git a/das/src/main/resources/application.yml b/das/src/main/resources/application.yml index cdd4455a..4dcd6bb7 100644 --- a/das/src/main/resources/application.yml +++ b/das/src/main/resources/application.yml @@ -113,4 +113,6 @@ minio: bucket: das publicBucket: das-dock accessKey: das - secretKey: zaq12WSX \ No newline at end of file + secretKey: zaq12WSX + +zipUrl: /log/zip/ \ No newline at end of file From 6c50871947c1c150781b2c7212912521b27e3959 Mon Sep 17 00:00:00 2001 From: huguanghan Date: Mon, 13 Jan 2025 17:35:33 +0800 Subject: [PATCH 02/20] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=A4=87=E4=BB=BD?= =?UTF-8?q?=E6=96=B0=E5=A2=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/service/impl/ExportTdDataServiceImpl.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java b/das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java index 4bd1aecc..a9d9754b 100644 --- a/das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java +++ b/das/src/main/java/com/das/modules/data/service/impl/ExportTdDataServiceImpl.java @@ -1,5 +1,6 @@ package com.das.modules.data.service.impl; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.ZipUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.das.modules.data.service.TDEngineService; @@ -9,6 +10,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.util.StopWatch; import java.io.BufferedWriter; @@ -72,11 +74,11 @@ public class ExportTdDataServiceImpl { }catch (Exception e){ log.error("导出风机数据zip失败{}",e); } -// finally { -// if (!CollectionUtils.isEmpty(fileList)){ -// FileUtil.del(new File(fileList.get(0).getParent())); -// } -// } + finally { + if (!CollectionUtils.isEmpty(fileList)){ + FileUtil.del(new File(fileList.get(0).getParent())); + } + } } From 14e00ae08f295b5d6844a7df7411d57bdccd3bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E4=BA=91=E9=B9=8F?= Date: Mon, 13 Jan 2025 17:45:55 +0800 Subject: [PATCH 03/20] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9E=E9=A1=B5=E9=9D=A2=20=E5=AE=9E?= =?UTF-8?q?=E6=97=B6=E6=95=B0=E6=8D=AE=EF=BC=9A=E6=B7=BB=E5=8A=A0=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E6=B5=8B=E7=82=B9=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/backend/historyData/request.ts | 57 ++ .../backend/equipment/airBlower/index.vue | 21 +- .../src/views/backend/historyData/index.vue | 964 ++++++++++++++++++ .../src/views/backend/historyData/type.ts | 10 + 4 files changed, 1048 insertions(+), 4 deletions(-) create mode 100644 ui/dasadmin/src/api/backend/historyData/request.ts create mode 100644 ui/dasadmin/src/views/backend/historyData/index.vue create mode 100644 ui/dasadmin/src/views/backend/historyData/type.ts diff --git a/ui/dasadmin/src/api/backend/historyData/request.ts b/ui/dasadmin/src/api/backend/historyData/request.ts new file mode 100644 index 00000000..1411e4b3 --- /dev/null +++ b/ui/dasadmin/src/api/backend/historyData/request.ts @@ -0,0 +1,57 @@ +import createAxios from '/@/utils/axios' + +export const getTemplateListReq = (data: { category: '历史数据' & string; pageNum: number; pageSize: number }) => { + return createAxios< + never, + Promise<{ + code: number + msg: string + data: { + total: number + rows: { id: string; category: '历史数据' & string; template: string }[] + code: number + msg: string + } + success: boolean + }> + >({ + url: '/api/page/report/template/getList', + method: 'post', + data, + }) +} + +export const addTemplateListReq = (data: { category: '历史数据' & string; template: string }) => { + return createAxios< + never, + Promise<{ + code: number + msg: string + data: { + id: string + category: '历史数据' & string + template: string + }[] + success: boolean + }> + >({ + url: '/api/page/report/template/add', + method: 'post', + data, + }) +} + +export const delTemplateListReq = (data: { id: string }) => { + return createAxios< + never, + Promise<{ + code: number + msg: string + success: boolean + }> + >({ + url: '/api/page/report/template/del', + method: 'post', + data, + }) +} \ No newline at end of file diff --git a/ui/dasadmin/src/views/backend/equipment/airBlower/index.vue b/ui/dasadmin/src/views/backend/equipment/airBlower/index.vue index 746a13f5..fbc938cf 100644 --- a/ui/dasadmin/src/views/backend/equipment/airBlower/index.vue +++ b/ui/dasadmin/src/views/backend/equipment/airBlower/index.vue @@ -237,6 +237,7 @@ import { getRealValueListReq } from '/@/api/backend/deviceModel/request' import SelectPoint from '/@/views/backend/equipment/airBlower/selectPoint.vue' import RealDataChart from '/@/views/backend/equipment/airBlower/realDataChart.vue' import { permission } from '/@/utils/directive' +import { table } from 'console' const vPermission = permission() const router = useRouter() @@ -423,7 +424,7 @@ const defaultColumn: TableColumnType[] = [ width: 100, }, ] -const dynamicColumn: TableColumnType[] = [ +let dynamicColumn: TableColumnType[] = [ { label: '风速 (m/s)', prop: 'iwindspeed', @@ -523,6 +524,17 @@ const dynamicColumn: TableColumnType[] = [ }, ] const tableColumn = ref([...defaultColumn, ...dynamicColumn]) +const getSaveColumn = () => { + const saveColumn = localStorage.getItem('airBlowerTableColumnList') + console.log(saveColumn,'saveColumn'); + + if (saveColumn) { + tableColumn.value = JSON.parse(saveColumn) + console.log(tableColumn.value,'tableColumn.value'); + dynamicColumn = tableColumn.value.slice(4) + } +} +getSaveColumn() const tableRef = ref() const tableData = ref([]) @@ -611,7 +623,7 @@ const getTableData = () => { } }) .catch((err) => { - ElMessage.error(err) + // ElMessage.error(err) }) } @@ -702,9 +714,10 @@ const selectPointDialogRef = ref() const selectPointVisible = ref(false) const defaultAttr = computed(() => { return dynamicColumn.map((item) => { + tableColumn.value.length return { attributeName: item.label.split(' ')[0], - unit: item.label.split(' ')[1] ?? '', + unit:item.label.split(' ')[1] ?? '', attributeCode: item.prop as string, } }) @@ -728,7 +741,7 @@ const saveSelectPoint = () => { } }) tableColumn.value = [...defaultColumn, ...addCoulmn] - + localStorage.setItem('airBlowerTableColumnList', JSON.stringify(tableColumn.value)) getTableData() selectPointVisible.value = false ElMessage.success('选择成功') diff --git a/ui/dasadmin/src/views/backend/historyData/index.vue b/ui/dasadmin/src/views/backend/historyData/index.vue new file mode 100644 index 00000000..3d77eabf --- /dev/null +++ b/ui/dasadmin/src/views/backend/historyData/index.vue @@ -0,0 +1,964 @@ + + + + + diff --git a/ui/dasadmin/src/views/backend/historyData/type.ts b/ui/dasadmin/src/views/backend/historyData/type.ts new file mode 100644 index 00000000..4c1a7598 --- /dev/null +++ b/ui/dasadmin/src/views/backend/historyData/type.ts @@ -0,0 +1,10 @@ +export type selectData = + { + id: string + attributeName: string + attributeCode: string + interpolation: boolean + average: boolean + max: boolean + min: boolean + } From 12b809879c1748116cc51629619c0a01418fd1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E4=BA=91=E9=B9=8F?= Date: Tue, 14 Jan 2025 09:29:31 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=EF=BC=9A=E6=95=B0=E6=8D=AE=E4=BF=9D=E7=95=99=E4=B8=A4=E4=BD=8D?= =?UTF-8?q?=E5=B0=8F=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/backend/historyData/index.vue | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ui/dasadmin/src/views/backend/historyData/index.vue b/ui/dasadmin/src/views/backend/historyData/index.vue index 3d77eabf..9dd78781 100644 --- a/ui/dasadmin/src/views/backend/historyData/index.vue +++ b/ui/dasadmin/src/views/backend/historyData/index.vue @@ -184,6 +184,7 @@ import { getModelAttributeListReq, getRealValueRangeReq } from '/@/api/backend/d import { getTemplateListReq, addTemplateListReq, delTemplateListReq } from '/@/api/backend/historyData/request' import { windowReq } from '/@/api/backend/statAnalysis/request' import { selectData } from '/@/views/backend/historyData/type' +import { getCutDecimalsValue } from '/@/views/backend/equipment/airBlower/utils' const shortcuts = [ { @@ -399,10 +400,11 @@ const getRealValueRange = () => { interpolationAttr.forEach((attr) => { device[attr].times.forEach((t: number, index: number) => { const attrNameKey = attr + '--interpolation' + const val = getCutDecimalsValue(device[attr].values[index], 2) tableDataList.push({ name: deviceNameData[deviceId], time: dayjs(t).format('YYYY-MM-DD HH:mm:ss'), - [attrNameKey]: device[attr].values[index], + [attrNameKey]: val, }) }) }) @@ -414,10 +416,11 @@ const getRealValueRange = () => { averageAttr.forEach((attr) => { device[attr].times.forEach((t: number, index: number) => { const attrNameKey = attr + '--average' + const val = getCutDecimalsValue(device[attr].values[index], 2) const tableDataIndex = tableDataList.findIndex( (data: any) => data.name == deviceNameData[deviceId] && data.time == dayjs(t).format('YYYY-MM-DD HH:mm:ss') ) - tableDataList[tableDataIndex][attrNameKey] = device[attr].values[index] + tableDataList[tableDataIndex][attrNameKey] = val }) }) }) @@ -428,10 +431,11 @@ const getRealValueRange = () => { maxAttr.forEach((attr) => { device[attr].times.forEach((t: number, index: number) => { const attrNameKey = attr + '--max' + const val = getCutDecimalsValue(device[attr].values[index], 2) const tableDataIndex = tableDataList.findIndex( (data: any) => data.name == deviceNameData[deviceId] && data.time == dayjs(t).format('YYYY-MM-DD HH:mm:ss') ) - tableDataList[tableDataIndex][attrNameKey] = device[attr].values[index] + tableDataList[tableDataIndex][attrNameKey] = val }) }) }) @@ -442,10 +446,11 @@ const getRealValueRange = () => { minAttr.forEach((attr) => { device[attr].times.forEach((t: number, index: number) => { const attrNameKey = attr + '--min' + const val = getCutDecimalsValue(device[attr].values[index], 2) const tableDataIndex = tableDataList.findIndex( (data: any) => data.name == deviceNameData[deviceId] && data.time == dayjs(t).format('YYYY-MM-DD HH:mm:ss') ) - tableDataList[tableDataIndex][attrNameKey] = device[attr].values[index] + tableDataList[tableDataIndex][attrNameKey] = val }) }) }) @@ -458,7 +463,6 @@ const getRealValueRange = () => { }) } -const exportData = () => {} const addTemplate = () => { ElMessageBox.prompt('请输入模板名称', '添加模板', { confirmButtonText: '确定', From 959673b0116ec1084845e0d528bea6e64fed06b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E4=BA=91=E9=B9=8F?= Date: Tue, 14 Jan 2025 09:42:58 +0800 Subject: [PATCH 05/20] =?UTF-8?q?=E5=8E=86=E5=8F=B2=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=EF=BC=9A=E4=BF=AE=E6=94=B9=E6=A8=A1=E6=9D=BF=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E6=A1=86=E6=98=BE=E7=A4=BA=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/dasadmin/src/views/backend/historyData/index.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/dasadmin/src/views/backend/historyData/index.vue b/ui/dasadmin/src/views/backend/historyData/index.vue index 9dd78781..0e128ae6 100644 --- a/ui/dasadmin/src/views/backend/historyData/index.vue +++ b/ui/dasadmin/src/views/backend/historyData/index.vue @@ -28,7 +28,7 @@