Browse Source

1. 新增 监控中心 - 环境监测 - 历史数据 导出功能

2. 新增 监控中心 - 环境监测 - 平均数据 导出功能
3. 修改 分组管理 左侧树图表
temp
fks-yangshouda 3 months ago
parent
commit
ce97741978
  1. 22
      hx-ai-intelligent/src/icon/fenzujiedian.svg
  2. 11
      hx-ai-intelligent/src/icon/jisuanjiedian.svg
  3. 210
      hx-ai-intelligent/src/util/ExcelUtil.js
  4. 220
      hx-ai-intelligent/src/util/Export2Excel.js
  5. 13
      hx-ai-intelligent/src/view/monitor/environmentMonitor/averageData/index.vue
  6. 62
      hx-ai-intelligent/src/view/monitor/environmentMonitor/historyData/index.vue

22
hx-ai-intelligent/src/icon/fenzujiedian.svg

@ -1,10 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8.98974609375" height="8.14453125" viewBox="0 0 8.98974609375 8.14453125" fill="none"> <svg xmlns="http://www.w3.org/2000/svg" width="12.34" height="10.758" viewBox="0 0 12.34 10.758">
<path d="M7.93101 4.53462L6.23624 4.53462L5.52032 3.46466L6.49265 1.79796L5.44381 0L3.32621 0L2.27236 1.79796L3.29704 3.54617L2.62652 4.54987L1.05875 4.54987L0 6.34726L1.05875 8.1452L3.17144 8.1452L4.06128 6.62695L4.93729 6.62695L5.81886 8.13029L7.93102 8.13029L8.98978 6.33258L7.93101 4.53462ZM3.19734 4.59392L3.8643 3.59569L5.00553 3.59569L5.73168 4.68208L4.88461 6.1274L4.09644 6.1274L3.19734 4.59392Z" fill="url(#linear_fill_60_2513)" > <g id="组_6" data-name="组 6" transform="translate(-614 -150.796)">
</path> <g id="组_2" data-name="组 2" transform="translate(614 150.796)">
<defs> <path id="路径_4" data-name="路径 4" d="M67.653,196.269H56.4a.537.537,0,0,1-.541-.533v-8.743a.537.537,0,0,1,.541-.533H67.653a.537.537,0,0,1,.541.533v8.743A.537.537,0,0,1,67.653,196.269Z" transform="translate(-55.854 -185.512)" fill="#ffa000"/>
<linearGradient id="linear_fill_60_2513" x1="4.494873046875" y1="0" x2="4.494873046875" y2="8.14453125" gradientUnits="userSpaceOnUse"> <path id="路径_5" data-name="路径 5" d="M61.866,119.866H55.854v-2.911a.55.55,0,0,1,.527-.569H60.5a.535.535,0,0,1,.507.406l.863,3.074Z" transform="translate(-55.854 -116.387)" fill="#ffa000"/>
<stop offset="0" stop-color="#4DACE6" /> <path id="路径_6" data-name="路径 6" d="M158.881,264.762h-9.094a.521.521,0,0,1-.516-.526v-7.173a.521.521,0,0,1,.516-.526h9.094a.521.521,0,0,1,.516.526v7.173A.517.517,0,0,1,158.881,264.762Z" transform="translate(-148.006 -254.637)" fill="#fff"/>
<stop offset="1" stop-color="#2A93D5" /> <path id="路径_7" data-name="路径 7" d="M67.653,334.52H56.4a.535.535,0,0,1-.541-.528v-6.855a.535.535,0,0,1,.541-.528H67.653a.535.535,0,0,1,.541.528v6.855A.535.535,0,0,1,67.653,334.52Z" transform="translate(-55.854 -323.762)" fill="#ffca28"/>
</linearGradient> <path id="路径_8" data-name="路径 8" d="M129.146,444H126.2a.291.291,0,0,1,0-.58h2.941a.291.291,0,0,1,.007.581Zm0,1.951H126.2a.281.281,0,0,1-.27-.29.277.277,0,0,1,.27-.291h2.941a.281.281,0,0,1,.27.291.276.276,0,0,1-.263.29Z" transform="translate(-124.979 -438.985)" fill="#fff8e1"/>
</defs> </g>
<g id="组_3" data-name="组 3" transform="translate(622.818 153.637)">
<path id="路径_12" data-name="路径 12" d="M667.159,350.215V355.2l1.215-1.327,1.3,1.42v-5.076" transform="translate(-667.159 -350.215)" fill="#2778ff"/>
</g>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 888 B

After

Width:  |  Height:  |  Size: 1.7 KiB

11
hx-ai-intelligent/src/icon/jisuanjiedian.svg

@ -1,10 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="9.1005859375" height="9.099609375" viewBox="0 0 9.1005859375 9.099609375" fill="none"> <svg xmlns="http://www.w3.org/2000/svg" width="8" height="13" viewBox="0 0 8 13">
<path d="M7.01762 4.69157L2.30136 4.69157C2.04227 4.66303 1.84615 4.44409 1.84615 4.18343C1.84615 3.92276 2.04227 3.70384 2.30136 3.67525L7.01762 3.67525C7.27673 3.70384 7.47285 3.92276 7.47285 4.18343C7.47285 4.44409 7.27673 4.66303 7.01762 4.69157ZM7.01762 6.69587L2.30136 6.69587C2.04227 6.6673 1.84615 6.44837 1.84615 6.18771C1.84615 5.92704 2.04227 5.70809 2.30136 5.67952L7.01762 5.67952C7.27673 5.70809 7.47285 5.92704 7.47285 6.18771C7.47285 6.44837 7.27673 6.6673 7.01762 6.69587ZM9.09498 8.33346L9.09498 1.98149C9.09498 1.21918 8.46167 1.27564 8.46167 1.27564L4.88941 1.27564C4.77006 1.27634 4.65399 1.23653 4.56021 1.16271C4.56021 1.16271 4.40816 0.880585 4.12926 0.428757C3.87605 -0.0795288 3.54708 0.00531769 3.54708 0.00531769L0.785301 0.00531769C0 0.00531769 0 0.824379 0 0.824379L0 8.27722C0 9.2087 0.633301 9.09628 0.633301 9.09628L8.53744 9.09628C9.19643 9.09547 9.09498 8.33345 9.09498 8.33345L9.09498 8.33346Z" fill="url(#linear_fill_60_2485)" > <path id="路径_14" data-name="路径 14" d="M320.7,183.7h-6a1,1,0,0,0-1,1v11.875a.124.124,0,0,0,.2.1l3.65-2.875a.252.252,0,0,1,.3,0l3.65,2.875a.124.124,0,0,0,.2-.1V184.7A1,1,0,0,0,320.7,183.7Zm-.656,3.334a.486.486,0,0,1-.486.486h-4a.486.486,0,1,1,0-.973h4A.486.486,0,0,1,320.044,187.034Zm0-2.039a.486.486,0,0,1-.486.486h-4a.486.486,0,1,1,0-.973h4A.488.488,0,0,1,320.044,184.995Z" transform="translate(-313.7 -183.7)" fill="#2778ff"/>
</path>
<defs>
<linearGradient id="linear_fill_60_2485" x1="4.55029296875" y1="0" x2="4.55029296875" y2="9.099609375" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#4DACE6" />
<stop offset="1" stop-color="#2A93D5" />
</linearGradient>
</defs>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 527 B

210
hx-ai-intelligent/src/util/ExcelUtil.js

@ -0,0 +1,210 @@
/* eslint-disable */
/** Excel
* npm install xlsx file-saver -S
* npm install script-loader -S -D
*/
import ExcelJS from 'exceljs';
import FileSaver from 'file-saver';
// export default exportExcel;
// 导出excel文件
export function exportExcel (tableColumns,data,fillName,isMerge,start,end) {
if (!data || data.length == 0) {
return;
}
// 创建工作簿
const workbook = new ExcelJS.Workbook();
// 添加工作表,名为sheet1
const sheet1 = workbook.addWorksheet('sheet1');
// 导出的表头名
let tHeader = ['序号'];
// 字段名
let filterVal = ['index'];
// 表格columns
let columns = [{ header: '序号', key: 'index', width: 10 }];
for (let i = 0; i < tableColumns.length; i++) {
if (tableColumns[i].dataIndex) {
tHeader.push(tableColumns[i].title);
filterVal.push(tableColumns[i].dataIndex);
columns.push({
header: tableColumns[i].title,
key: tableColumns[i].dataIndex,
width: tableColumns[i].width / 5,
});
}
}
//传入的数据
const list = data;
const datas = formatJson(filterVal, list);
// // 导出数据列表
// const data = [
// { 姓名: '张三', 年龄: 18, 身高: 175, 体重: 74 },
// { 姓名: '李四', 年龄: 22, 身高: 177, 体重: 84 },
// { 姓名: '王五', 年龄: 53, 身高: 155, 体重: 64 },
// ];
// 获取表头所有键
// const headers = Object.keys(data[0]);
sheet1.columns = columns;
// // 将标题写入第一行
// sheet1.addRow(tHeader);
// 将数据写入工作表
datas.forEach((row) => {
// const values = Object.values(row);
sheet1.addRow(row);
});
// 判断是否合并单元格
if (isMerge) {
debugger
// 遍历列,从第一列到 end 列
for (let col = start; col <= end; col++) {
// let mergeStartRow = 2; // 每次新列开始时,重置起始行
for (let row = 3; row <= datas.length + 1; row++) {
const currentCellValue = sheet1.getCell(row, col).value;
const previousCellValue = sheet1.getCell(row - 1, col).value;
let currentCellValue_1 = ''
let previousCellValue_1 = ''
if (col > 1) {
currentCellValue_1 = sheet1.getCell(row, col-1).value;
previousCellValue_1 = sheet1.getCell(row - 1, col-1).value;
}
if (currentCellValue === previousCellValue && currentCellValue_1 === previousCellValue_1) {
// 当前列有变化,检查是否需要合并前面的单元格
// if (mergeStartRow < row - 1) {
// 只有在前面的行有超过1个时才合并
sheet1.mergeCells(row, col, row - 1, col);
// }
// 更新起始行
// mergeStartRow = row;
}
// // 如果是最后一行,检查是否需要合并
// if (row === datas.length + 1 && mergeStartRow < row) {
// sheet1.mergeCells(mergeStartRow, col, row, col);
// }
}
}
// 从第一列开始逐列检查,前提是前面的列已合并
// for (let col = start; col <= end; col++) {
// let startRow = 2; // 从数据开始的第二行开始检查
// let endRow = 2;
// while (endRow <= sheet1.rowCount) {
// let currentValue = sheet1.getCell(endRow, col).value;
// let prevValue = sheet1.getCell(endRow - 1, col).value;
// // 如果当前值等于前一个值,且前面的列是合并的,则继续合并
// if (currentValue === prevValue) {
// let mergeAllowed = true;
// for (let prevCol = 1; prevCol < col; prevCol++) {
// let range = sheet1.getCell(endRow - 1, prevCol).master;
// if (range && range.row !== startRow) {
// mergeAllowed = false;
// break;
// }
// }
// if (mergeAllowed) {
// endRow++;
// } else {
// // 不允许合并,直接移动起始行到当前行
// startRow = endRow;
// endRow++;
// }
// } else {
// // 当前值不等于前一个值或合并不允许,进行合并操作
// if (startRow < endRow - 1) {
// sheet1.mergeCells(startRow, col, endRow - 1, col);
// }
// startRow = endRow;
// endRow++;
// }
// }
// // 处理最后一段相同的单元格
// if (startRow < endRow - 1) {
// sheet1.mergeCells(startRow, col, endRow - 1, col);
// }
// }
}
// 修改所有单元格样式
// 遍历每一行
sheet1.eachRow((row, rowNumber) => {
// 遍历每个单元格
row.eachCell((cell) => {
// 设置边框样式
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' },
};
// 设置居中对齐
cell.alignment = {
vertical: 'middle',
horizontal: 'center',
};
});
});
// 获取标题行数据
const titleCell = sheet1.getRow(1);
// 设置行高为30
titleCell.height = 30;
// 设置标题行单元格样式
titleCell.eachCell((cell) => {
// 设置标题行背景颜色为黄色
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFFFF' },
};
// 设置标题行字体
cell.font = {
// color: { argb: 'FF0000' }, //颜色为红色
bold: true, // 字体粗体
size: 18, // 设置字体大小为18
};
});
// 获取第二行到最后一行的内容数据
const bodyRows = sheet1.getRows(2, sheet1.rowCount);
// 处理内容行的数据
bodyRows.forEach((bodyRow) => {
// 设置行高为20
bodyRow.height = 20;
bodyRow.eachCell((cell) => {
cell.font = {
size: 16, // 设置内容行字体大小为16
};
});
});
// 导出表格文件
workbook.xlsx
.writeBuffer()
.then((buffer) => {
let file = new Blob([buffer], { type: 'application/octet-stream' });
FileSaver.saveAs(file, fillName + '.xlsx');
})
.catch((error) => console.log('Error writing excel export', error));
};
/**
* 格式化表格数据
* @filterVal 格式头
* @jsonData 用来格式化的表格数据
*/
function formatJson (filterVal, jsonData) {
return jsonData.map((v) => filterVal.map((j) => v[j]));
};

220
hx-ai-intelligent/src/util/Export2Excel.js

@ -1,220 +0,0 @@
/* eslint-disable */
import { saveAs } from 'file-saver'
import XLSX from 'xlsx'
function generateArray(table) {
var out = [];
var rows = table.querySelectorAll('tr');
var ranges = [];
for (var R = 0; R < rows.length; ++R) {
var outRow = [];
var row = rows[R];
var columns = row.querySelectorAll('td');
for (var C = 0; C < columns.length; ++C) {
var cell = columns[C];
var colspan = cell.getAttribute('colspan');
var rowspan = cell.getAttribute('rowspan');
var cellValue = cell.innerText;
if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
//Skip ranges
ranges.forEach(function (range) {
if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
}
});
//Handle Row Span
if (rowspan || colspan) {
rowspan = rowspan || 1;
colspan = colspan || 1;
ranges.push({
s: {
r: R,
c: outRow.length
},
e: {
r: R + rowspan - 1,
c: outRow.length + colspan - 1
}
});
};
//Handle Value
outRow.push(cellValue !== "" ? cellValue : null);
//Handle Colspan
if (colspan)
for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
}
out.push(outRow);
}
return [out, ranges];
};
function datenum(v, date1904) {
if (date1904) v += 1462;
var epoch = Date.parse(v);
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}
function sheet_from_array_of_arrays(data, opts) {
var ws = {};
var range = {
s: {
c: 10000000,
r: 10000000
},
e: {
c: 0,
r: 0
}
};
for (var R = 0; R != data.length; ++R) {
for (var C = 0; C != data[R].length; ++C) {
if (range.s.r > R) range.s.r = R;
if (range.s.c > C) range.s.c = C;
if (range.e.r < R) range.e.r = R;
if (range.e.c < C) range.e.c = C;
var cell = {
v: data[R][C]
};
if (cell.v == null) continue;
var cell_ref = XLSX.utils.encode_cell({
c: C,
r: R
});
if (typeof cell.v === 'number') cell.t = 'n';
else if (typeof cell.v === 'boolean') cell.t = 'b';
else if (cell.v instanceof Date) {
cell.t = 'n';
cell.z = XLSX.SSF._table[14];
cell.v = datenum(cell.v);
} else cell.t = 's';
ws[cell_ref] = cell;
}
}
if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
return ws;
}
function Workbook() {
if (!(this instanceof Workbook)) return new Workbook();
this.SheetNames = [];
this.Sheets = {};
}
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
export function export_table_to_excel(id) {
var theTable = document.getElementById(id);
var oo = generateArray(theTable);
var ranges = oo[1];
/* original data */
var data = oo[0];
var ws_name = "SheetJS";
var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
/* add ranges to worksheet */
// ws['!cols'] = ['apple', 'banan'];
ws['!merges'] = ranges;
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), "test.xlsx")
}
export function export_json_to_excel({
multiHeader = [],
header,
data,
filename,
merges = [],
autoWidth = true,
bookType = 'xlsx'
} = {}) {
/* original data */
filename = filename || 'excel-list'
data = [...data]
data.unshift(header);
for (let i = multiHeader.length - 1; i > -1; i--) {
data.unshift(multiHeader[i])
}
var ws_name = "SheetJS";
var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
if (merges.length > 0) {
if (!ws['!merges']) ws['!merges'] = [];
merges.forEach(item => {
ws['!merges'].push(XLSX.utils.decode_range(item))
})
}
if (autoWidth) {
/*设置worksheet每列的最大宽度*/
const colWidth = data.map(row => row.map(val => {
/*先判断是否为null/undefined*/
if (val == null) {
return {
'wch': 10
};
}
/*再判断是否为中文*/
else if (val.toString().charCodeAt(0) > 255) {
return {
'wch': val.toString().length * 2
};
} else {
return {
'wch': val.toString().length
};
}
}))
/*以第一行为初始值*/
let result = colWidth[0];
for (let i = 1; i < colWidth.length; i++) {
for (let j = 0; j < colWidth[i].length; j++) {
if (result[j]['wch'] < colWidth[i][j]['wch']) {
result[j]['wch'] = colWidth[i][j]['wch'];
}
}
}
ws['!cols'] = result;
}
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {
bookType: bookType,
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), `${filename}.${bookType}`);
}

13
hx-ai-intelligent/src/view/monitor/environmentMonitor/averageData/index.vue

@ -38,7 +38,10 @@
查询 查询
</a-button> </a-button>
</div> </div>
<a-button type="primary" style="position: absolute; right: 40px; top: -45px"> <a-button
type="primary"
style="position: absolute; right: 40px; top: -45px"
@click="export1()">
导出 导出
</a-button> </a-button>
</div> </div>
@ -66,6 +69,7 @@
<!-- </a-spin> --> <!-- </a-spin> -->
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { exportExcel } from '/@/util/ExcelUtil.js';
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
// import { http } from '/nerv-lib/util/http'; // import { http } from '/nerv-lib/util/http';
import { Pagination, SelectProps, TreeSelectProps, TableColumnType } from 'ant-design-vue'; import { Pagination, SelectProps, TreeSelectProps, TableColumnType } from 'ant-design-vue';
@ -200,6 +204,13 @@
loading.value = false; loading.value = false;
}); });
}; };
// excel
const export1 = () => {
for (let i = 0; i < data.value.length; i++) {
data.value[i].index = i + 1;
}
exportExcel(tableColumns.value, data.value, '平均数据导出', false);
};
onMounted(async () => { onMounted(async () => {
// //
let frequency = await getEnum({ params: { enumType: 'TimeFlagEnum' } }); let frequency = await getEnum({ params: { enumType: 'TimeFlagEnum' } });

62
hx-ai-intelligent/src/view/monitor/environmentMonitor/historyData/index.vue

@ -62,7 +62,7 @@
<a-button <a-button
type="primary" type="primary"
style="position: absolute; right: 40px; top: -45px" style="position: absolute; right: 40px; top: -45px"
@click="exportExcel()"> @click="export1()">
导出 导出
</a-button> </a-button>
</div> </div>
@ -87,8 +87,7 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import XLSX from 'xlsx'; import { exportExcel } from '/@/util/ExcelUtil.js';
// import Export2Excel from '/@/util/Export2Excel.js';
import { ref, onMounted, defineOptions } from 'vue'; import { ref, onMounted, defineOptions } from 'vue';
// import { http } from '/nerv-lib/util/http'; // import { http } from '/nerv-lib/util/http';
@ -352,60 +351,9 @@
} }
}); });
}; };
// excel // excel
/** const export1 = () => {
* @前期准备 npm install -S xlsx file-saver Export2Excel.js exportExcel(tableColumns.value, data.value, '历史数据导出', true, 1, 3);
*/
const exportExcel = () => {
import('/@/util/Export2Excel.js').then((excel) => {
//
let tHeader = [];
let filterVal = [];
for (let i = 0; i < tableColumns.value.length; i++) {
if (tableColumns.value[i].dataIndex) {
tHeader.push(tableColumns.value[i].title);
filterVal.push(tableColumns.value[i].dataIndex);
}
}
// const tHeader = [
// 'ID',
// '',
// 'ID',
// '',
// '',
// '',
// '',
// '',
// ];
// //
// const filterVal = [
// 'id',
// 'name',
// 'videoId',
// 'videoTitle',
// 'release',
// 'videoType',
// 'playVolume',
// 'updateTime',
// ];
//
const list = data.value;
const datas = formatJson(filterVal, list);
excel.export_json_to_excel({
header: tHeader, //
data: datas, //
filename: '表格导出测试', // excel
});
});
};
/**
* 格式化表格数据
* @filterVal 格式头
* @jsonData 用来格式化的表格数据
*/
const formatJson = (filterVal: any, jsonData: any) => {
return jsonData.map((v: any) => filterVal.map((j: any) => v[j]));
}; };
onMounted(async () => { onMounted(async () => {
// //

Loading…
Cancel
Save