zhaohy 3 months ago
parent
commit
5803e3cdd9
  1. 22
      hx-ai-intelligent/src/icon/fenzujiedian.svg
  2. 11
      hx-ai-intelligent/src/icon/jisuanjiedian.svg
  3. 228
      hx-ai-intelligent/src/util/ExcelUtil.js
  4. 220
      hx-ai-intelligent/src/util/Export2Excel.js
  5. 30
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonAssets/carbonAssetsDetail/index.vue
  6. 5
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonAssets/index.vue
  7. 45
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/energyConsumption/index.vue
  8. 26
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index.vue
  9. 110
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/config.ts
  10. 104
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/fillInPage/index.vue
  11. 7
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/index.vue
  12. 231
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/categoryDeatil.vue
  13. 7
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/index.vue
  14. 36
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/index.vue
  15. 4
      hx-ai-intelligent/src/view/monitor/deviceMonitor/page.vue
  16. 5
      hx-ai-intelligent/src/view/monitor/deviceMonitor/table/index.vue
  17. 22
      hx-ai-intelligent/src/view/monitor/deviceMonitor/tree/index.vue
  18. 150
      hx-ai-intelligent/src/view/monitor/energyMonitor/analysisTable/index.vue
  19. 5
      hx-ai-intelligent/src/view/monitor/energyMonitor/graphTable/index.vue
  20. 26
      hx-ai-intelligent/src/view/monitor/energyMonitor/page.vue
  21. 26
      hx-ai-intelligent/src/view/monitor/energyMonitor/tree/index.vue
  22. 10
      hx-ai-intelligent/src/view/monitor/environmentMonitor/averageData/index.vue
  23. 66
      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">
<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)" >
</path>
<defs>
<linearGradient id="linear_fill_60_2513" x1="4.494873046875" y1="0" x2="4.494873046875" y2="8.14453125" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#4DACE6" />
<stop offset="1" stop-color="#2A93D5" />
</linearGradient>
</defs>
<svg xmlns="http://www.w3.org/2000/svg" width="12.34" height="10.758" viewBox="0 0 12.34 10.758">
<g id="组_6" data-name="组 6" transform="translate(-614 -150.796)">
<g id="组_2" data-name="组 2" transform="translate(614 150.796)">
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
</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>

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">
<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>
<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 xmlns="http://www.w3.org/2000/svg" width="8" height="13" viewBox="0 0 8 13">
<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"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 527 B

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

@ -0,0 +1,228 @@
/* 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文件
/**
*
* @param {*} tableColumns 表头
* @param {*} data 数据
* @param {*} fillName 文件名
* @param {*} isMerge 是否合并单元格
* @param {*} firstKey 第一个字段的key用来判断序号列是否合并
* @param {*} start 合并单元格开始列
* @param {*} end 合并单元格结束列
* @returns
*/
export function exportExcel (tableColumns,data,fillName,isMerge = false, firstKey = '',start = 0, end = 0) {
debugger
if (!data || data.length == 0) {
return;
}
if (isMerge) {
// 需要合并序号
for (let i = 0; i < data.length; i++) {
// 自定义单元格内容,这里返回序号
if (i == 0) {
data[i].index = 1;
// return 1;
} else if (data[i - 1][firstKey] == data[i][firstKey]) {
data[i].index = data[i - 1].index;
// return data.value[index].index;
} else {
data[i].index = data[i - 1].index + 1;
}
}
} else {
// 不需要合并序号
for (let i = 0; i < data.length; i++) {
data[i].index = i + 1;
}
}
// 创建工作簿
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 ? tableColumns[i].width / 5 : 20,
});
}
}
//传入的数据
const list = data;
//格式化数据
const datas = formatJson(filterVal, list);
// 获取表头所有键
// const headers = Object.keys(data[0]);
// 获取表头
sheet1.columns = columns;
// 将数据写入工作表
datas.forEach((row) => {
// const values = Object.values(row);
sheet1.addRow(row);
});
// 判断是否合并单元格
if (isMerge) {
// 遍历列,从 start 列到 end 列
for (let col = start; col <= end; col++) {
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 isMerged = true
if (col > 1) {
isMerged = ifMerged(sheet1,row - 1, col-1,row, col-1)
}
if (currentCellValue === previousCellValue && isMerged) {
// 检查是上边需要合并的单元格是否已经合并
const mergeInfo = getMergeInfo(sheet1, row - 1, col)
if ( mergeInfo.isMerged ) {
sheet1.unMergeCells( mergeInfo.startRow, col, row - 1, col);
sheet1.mergeCells(mergeInfo.startRow, col, row, col);
} else {
sheet1.mergeCells(row, col, row - 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]));
};
/**
* 获取给定行和列的单元格是否为合并单元格并返回合并起始行
* @param {Worksheet} worksheet - ExcelJS 工作表对象
* @param {number} row - 单元格的行号 ( 1 开始)
* @param {number} col - 单元格的列号 ( 1 开始)
* @returns {Object} - 返回一个对象包含 isMerged startRow 属性
*/
function getMergeInfo(worksheet, row, col) {
// 遍历所有的合并范围
for (const mergeRange in worksheet._merges) {
if (worksheet._merges.hasOwnProperty(mergeRange)) {
const { top, left, bottom, right } = worksheet._merges[mergeRange];
// 检查行列是否在当前合并范围内
if (row >= top && row <= bottom && col >= left && col <= right) {
return { isMerged: true, startRow: top }; // 找到合并范围,返回合并信息
}
}
}
return { isMerged: false, startRow: null }; // 单元格不在任何合并范围内
}
// 函数:检查两个单元格是否属于同一个合并区域
function ifMerged(worksheet, row1, col1, row2, col2) {
const merges = worksheet._merges; // 获取所有的合并区域
for (let mergeAddress in merges) {
const mergeRange = merges[mergeAddress];
const { top, left, bottom, right } = mergeRange;
const isCell1InRange = (row1 >= top && row1 <= bottom && col1 >= left && col1 <= right);
const isCell2InRange = (row2 >= top && row2 <= bottom && col2 >= left && col2 <= right);
if (isCell1InRange && isCell2InRange) {
return true;
}
}
return false;
}

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}`);
}

30
hx-ai-intelligent/src/view/carbonEmissionManage/carbonAssets/carbonAssetsDetail/index.vue

@ -20,10 +20,11 @@
</a-form-item>
<a-form-item>
<a-cascader
v-model:value="queryParams.transactionType"
v-model:value="transactionType"
multiple
style="width: 200px"
:options="options"
@change="changeSelect"
placeholder="请选择交易类型"
suffix-icon="Shopping Around">
<template #tagRender="data">
@ -49,7 +50,7 @@
</div>
<div style="display: flex; margin-top: 20px; height: calc(84% - 20px)">
<div class="detailTable">
<ns-view-list-table v-bind="tableConfig" :model="data" ref="mainRef" :scroll="{ x: 2000 }">
<ns-view-list-table v-bind="tableConfig" :model="data" ref="mainRef" :scroll="{ x: 1280 }">
<template #bodyCell="{ column, text, record }">
<template v-if="column.dataIndex === 'accountType'">
<span v-if="record.accountType">{{ record.accountType.label }}</span>
@ -195,6 +196,7 @@
};
const total = ref<number>();
const year = ref(new Date().getFullYear().toString());
const transactionType = ref();
const queryParams = ref({
pageNum: 1,
pageSize: 10,
@ -202,9 +204,16 @@
accountType: props.parentId,
year: year.value,
});
const transactionTypeValue = ref();
const changeSelect = (value, selectedOptions) => {
transactionTypeValue.value = selectedOptions.flatMap((group) =>
group.flatMap((node) => [node.value, ...(node.children?.map((child) => child.value) || [])]),
);
};
const searchTableList = () => {
year.value = queryParams.value.year;
transactionType.value = queryParams.value.transactionType;
transactionTypeList.value = transactionTypeValue.value;
queryParams.value.transactionTypeList = transactionTypeValue.value;
accountType.value = queryParams.value.accountType;
getTotalTable(queryParams.value.accountType);
mainRef.value?.nsTableRef.reload();
@ -283,6 +292,9 @@
accountType.value = props.parentId;
year.value = new Date().getFullYear();
transactionType.value = '';
transactionTypeList.value = [];
queryParams.value.transactionTypeList = transactionTypeList.value;
getTotalTable();
mainRef.value?.nsTableRef.reload();
// getDetailList();
};
@ -364,7 +376,7 @@
};
const mainRef = ref();
const transactionType = ref();
const transactionTypeList = ref([]);
const accountType = ref();
accountType.value = props.parentId;
const tableConfig = ref({
@ -373,6 +385,7 @@
params: {
orgId,
accountType,
transactionTypeList,
year,
},
headerActions: [
@ -467,40 +480,49 @@
{
title: '资产类别',
dataIndex: 'accountType',
width: 100,
},
{
title: '交易方式',
dataIndex: 'transactionTypeName',
width: 100,
},
{
title: '交易日期',
dataIndex: 'transactionDate',
width: 100,
sorter: (a, b) => a.transactionDate - b.transactionDate,
},
{
title: '本期收入(tCO2)',
dataIndex: 'income',
width: 150,
sorter: (a, b) => a.income - b.income,
},
{
title: '本期支出(tCO2)',
dataIndex: 'expenditure',
width: 150,
sorter: (a, b) => a.expenditure - b.expenditure,
},
{
title: '发生金额(¥)',
width: 150,
dataIndex: 'amountIncurredValue',
},
{
title: '交易对象',
width: 100,
dataIndex: 'tradingPartner',
},
{
title: '更新人',
width: 100,
dataIndex: 'updateUser',
},
{
title: '更新时间',
width: 150,
dataIndex: 'updateTime',
},
],

5
hx-ai-intelligent/src/view/carbonEmissionManage/carbonAssets/index.vue

@ -2,7 +2,9 @@
<div class="mainContant" v-if="homePage">
<a-card class="card" v-if="nationwide" style="margin-right: 1%; margin-bottom: 1%">
<div class="top" style="background: rgba(252, 139, 78, 0.05)">
<div class="moneyImg"><img width="68" height="68" src="../../../../src/icon/carbonAssetsMoney-1.svg" /></div>
<div class="moneyImg"
><img width="68" height="68" src="../../../../src/icon/carbonAssetsMoney-1.svg"
/></div>
<div class="moneyTitle">全国碳账户估值CNY</div>
<div class="moneyTotal" style="color: rgba(229, 102, 22, 1)">{{
nationwide.valuation
@ -369,6 +371,7 @@
background: linear-gradient(180deg, rgba(244, 252, 250, 1) 0%, rgba(255, 255, 255, 1) 100%);
border: 1px solid rgba(42, 197, 155, 0.3);
padding: 10px;
border-radius: 8px;
.money {
opacity: 1;
font-size: 28px;

45
hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/energyConsumption/index.vue

@ -85,7 +85,7 @@
<div class="ns-form-title" style="display: flex">
<div class="title">凭证上传</div>
</div>
<a-upload
<!-- <a-upload
:file-list="fileList"
name="file"
accept=".pdf"
@ -109,33 +109,26 @@
<span>1.仅支持pdf格式文件或文件夹</span>
<span>2.文件名命名规则为能源种类_年份</span>
<span>3.每次上传自动覆盖</span>
</div>
<template #footer>
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
<a-button type="primary" @click="onSubmit">确定</a-button>
</template>
</a-drawer>
<!-- 上传凭证弹窗 -->
<!-- <a-modal :visible="openUpload" title="凭证上传" @ok="handleOk" @cancel="closeOpenUpload">
</div> -->
<a-upload-dragger
v-model:fileList="fileList"
accept=".pdf"
name="file"
:multiple="true"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
@change="handleChange"
@drop="handleDrop"
>
@remove="handleFileRemove"
:before-upload="beforeUpload"
@change="handleChange">
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>
</p>
<p class="ant-upload-hint" style="display: flex;flex-direction: column;">
<p>1.仅支持pdf格式文件或文件夹</p>
<p>2.文件命名规则为能源种类_年份</p>
<p>3.每次上传自动覆盖</p>
</p>
<p class="ant-upload-hint">1.仅支持pdf格式文件或文件夹</p>
<p class="ant-upload-hint">2.文件名命名规则为能源种类_年份</p>
<p class="ant-upload-hint">3.每次上传自动覆盖</p>
</a-upload-dragger>
</a-modal> -->
<template #footer>
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
<a-button type="primary" @click="onSubmit">确定</a-button>
</template>
</a-drawer>
<!-- 凭证下载 -->
<a-drawer
:visible="downLoadVisible"
@ -172,10 +165,10 @@
</template>
</template>
</a-table>
<template #footer>
<!-- <template #footer>
<a-button style="margin-right: 8px" @click="onCloseDownLoad">取消</a-button>
<a-button type="primary" @click="onSubmitDownLoad">确定</a-button>
</template>
</template> -->
</a-drawer>
</div>
</template>
@ -183,7 +176,7 @@
import { ref, toRaw, defineExpose, createVNode } from 'vue';
import type { Rule } from 'ant-design-vue/es/form';
import { Pagination, message, Modal, Upload } from 'ant-design-vue';
import { UploadOutlined } from '@ant-design/icons-vue';
import { UploadOutlined, InboxOutlined } from '@ant-design/icons-vue';
import type { TreeSelectProps, UploadChangeParam, UploadProps } from 'ant-design-vue';
import { NsMessage } from '/nerv-lib/component';
import dayjs, { Dayjs } from 'dayjs';
@ -1174,6 +1167,10 @@
:deep(.ant-table-container) {
padding: unset;
}
:deep(.ant-upload.ant-upload-drag) {
height: 18vh;
margin-top: 10px;
}
</style>
<style scoped>
th.column-money,

26
hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index.vue

@ -119,10 +119,11 @@
<!-- 选择因子 -->
<a-modal
v-model:visible="openVisible"
v-if="openVisible"
width="60%"
title="选择因子"
@ok="onSubmit"
@cancel="onClose">
@ok="btnClick"
@cancel="onCloseClick">
<ns-view-list-table v-bind="config" ref="setFactorRef" style="height: 500px" />
</a-modal>
</div>
@ -140,6 +141,7 @@
} from '/@/api/carbonEmissionFactorLibrary';
import { or } from '@vueuse/core';
import { setFactorConfig } from '../config';
import { NsMessage } from '/nerv-lib/saas';
defineOptions({
energyType: 'quickCalculation', // name
components: {
@ -340,8 +342,8 @@
formState.value.factorId = record.factorId;
text.value = '编辑';
visible.value = true;
emissionSources.value = record.emissionSources;
queryData.value.emissionSources = emissionSources.value;
emissionSources.value = record.factorId; //todo
queryData.value.factorId = emissionSources.value; //todo
getNewTable();
},
},
@ -484,10 +486,26 @@
});
};
const openVisible = ref(false);
const setFactorRef = ref();
const config = setFactorConfig(orgId.value);
const selectFactor = () => {
openVisible.value = true;
};
const btnClick = () => {
let selectRowKeys = setFactorRef.value?.nsTableRef.tableState.selectedRowKeys;
if (selectRowKeys.length === 0) {
NsMessage.warn('请选择因子');
return;
} else {
newTableData.value = setFactorRef.value?.nsTableRef.tableState.selectedRows;
selectedRowKeys.value = setFactorRef.value?.nsTableRef.tableState.selectedRowKeys;
formState.value.factorId = selectedRowKeys.value[0];
openVisible.value = false;
}
};
const onCloseClick = () => {
openVisible.value = false;
};
//
const onClose = () => {
visible.value = false;

110
hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/config.ts

@ -1,3 +1,5 @@
import { quickCalculation, carbonEmissionFactorLibrary } from '/@/api/carbonEmissionFactorLibrary';
import { ref } from 'vue';
// 凭证弹窗表头
export const voucherColumns = [
{
@ -9,8 +11,8 @@ export const voucherColumns = [
},
{
title: '日期',
dataIndex: 'updateTime',
key: 'updateTime',
dataIndex: 'bizName',
key: 'bizName',
ellipsis: true,
},
{
@ -42,3 +44,107 @@ export const drawerColumns = [
dataIndex: 'dataSources',
},
];
export const setFactorConfig = (orgId) => {
return ref({
api: carbonEmissionFactorLibrary.getTableList,
params: { orgId, pageNum: 1, pageSize: 9999, emissionList: [0] },
treeConfig: {
header: {
icon: 'deviceType',
title: '排放分类',
},
params: { orgId},
dynamicParams: { emissionList: 'id[]' },
defaultExpandAll: true,
// checkable:true,
api: carbonEmissionFactorLibrary.getCarbonFactorTree,
fieldNames: { title: 'emissionName', key: 'id' },
formConfig: {
schemas: [
{
field: 'deviceType',
label: '设备名称',
component: 'NsInput',
autoSubmit: true,
componentProps: {
placeholder: '请输入关键字',
},
},
],
},
},
rowSelection: { type: 'radio' },
columns: [
{
title: '序号',
textNumber: 2,
dataIndex: 'address',
customRender: (text: any) => {
return text.index + 1;
},
},
{
title: '名称',
dataIndex: 'emissionSources',
textNumber: 3,
},
{
title: '排放因子',
dataIndex: 'emissionFactors',
textNumber: 4,
textEllipsis: true,
},
{
title: '排放因子单位',
dataIndex: 'emissionFactorUnits',
width: 100,
textEllipsis: true,
},
{
title: '排放环节',
dataIndex: 'emissionProcess',
textWidth: 88,
textEllipsis: true,
},
{
title: '数据来源',
dataIndex: 'dataSources',
textNumber: 5,
textEllipsis: true,
},
],
formConfig: {
schemas: [
{
field: 'emissionSources',
label: '排放源',
component: 'NsInput',
componentProps: {
placeholder: '请输入排放源',
maxLength: 20,
},
},
{
field: 'emissionProcess',
label: '排放环节',
component: 'NsSelectApi',
componentProps: {
placeholder: '请选择排放环节',
api: carbonEmissionFactorLibrary.gasAndDatabase,
resultField: 'data',
params: {
orgId: orgId.value,
type: 'emissionProcess',
},
immediate: true,
labelField: 'label',
valueField: 'value',
},
},
],
params: {},
},
// pagination: { pageSizeOptions: false },
rowKey: 'id',
});
};

104
hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/fillInPage/index.vue

@ -106,8 +106,13 @@
<span>{{ data.emissionSource }}</span>
</div>
<div class="actionMore">
<EditOutlined @click="editUnit(data)" />
<MinusCircleOutlined style="margin-left: 6px" @click="delUnit(data)" />
<EditOutlined
@click="editUnit(data)"
v-if="data.emissionSource !== '全部'" />
<MinusCircleOutlined
v-if="data.emissionSource !== '全部'"
style="margin-left: 6px"
@click="delUnit(data)" />
<PlusCircleOutlined
v-if="data.emissionSource === '全部'"
style="margin-left: 6px"
@ -131,7 +136,7 @@
:pagination="false"
bordered
size="middle"
:scroll="{ y: 380 }">
:scroll="{ x: 660, y: 380 }">
<template #title>
<a-button type="primary" @click="downLoadVoucher">凭证</a-button>
</template>
@ -373,20 +378,21 @@
@keydown="handleKeyDown" />
</a-form-item>
</a-col>
<a-col :span="24">
<!-- <a-col :span="24">
<a-form-item ref="name" label="关键字" name="key">
<a-input-search
v-model:value="editFormState.key"
@search="searchKey"
placeholder="请输入关键字" />
</a-form-item>
</a-col>
</a-col> -->
</a-row>
</a-form>
</a-spin>
<div class="ns-form-title-edit" style="display: flex">
<!-- <div class="ns-form-title-edit" style="display: flex">
<div class="titleEdit">因子列表</div>
</div>
</div> -->
<a-button type="primary" style="margin-bottom: 10px" @click="selectFactor">选择因子</a-button>
<a-table
:columns="drawerColumns"
:data-source="newTableData"
@ -430,14 +436,23 @@
<inbox-outlined></inbox-outlined>
</p>
<p class="ant-upload-hint">1.仅支持pdf格式文件或文件夹</p>
<p class="ant-upload-hint">2.文件名命名规则为能源种类_年份</p>
<p class="ant-upload-hint">3.每次上传自动覆盖</p>
<p class="ant-upload-hint">2.每次上传自动覆盖</p>
</a-upload-dragger>
<template #footer>
<a-button style="margin-right: 8px" @click="onCloseEditData">取消</a-button>
<a-button type="primary" @click="submitEditData">确定</a-button>
</template>
</a-drawer>
<!-- 选择因子 -->
<a-modal
v-model:visible="openVisible"
v-if="openVisible"
width="60%"
title="选择因子"
@ok="btnClick"
@cancel="onCloseClick">
<ns-view-list-table v-bind="config" ref="setFactorRef" style="height: 500px" />
</a-modal>
</div>
</template>
@ -464,6 +479,8 @@
import { group } from '/@/api/deviceManage';
import { debug, log } from 'node:console';
import { dict } from '/@/api';
import { NsMessage } from '/nerv-lib/saas';
import { setFactorConfig } from '../config';
defineOptions({
energyType: 'fillInPage', // name
components: {
@ -673,12 +690,14 @@
}
};
//
const carbonEmission = ref();
const getTableHeardUnit = (id) => {
fetch(carbonInventoryCheck.findUnitById, { id: id }).then((res) => {
if (res.data) {
columns.value[1].title = '消耗量【' + res.data.unit + '】';
columns.value[2].title = '碳排因子【' + res.data.carbonEmission + '】';
columns.value[3].title = '排放量【' + res.data.carbonUnits + '】';
carbonEmission.value = res.data.carbonEmission;
}
});
};
@ -879,6 +898,7 @@
{
title: '日期',
dataIndex: 'acquisitionDate',
width: 80,
key: 'acquisitionDate',
},
{
@ -887,11 +907,13 @@
{
title: '数据来源',
dataIndex: 'dataSources',
width: 100,
key: 'dataSources',
},
{
title: '数值',
dataIndex: 'consumption',
width: 100,
key: 'consumption',
},
],
@ -902,11 +924,13 @@
{
title: '数据来源',
dataIndex: 'carbonSource',
width: 100,
key: 'carbonSource',
},
{
title: '数值',
dataIndex: 'emissionFactors',
width: 100,
key: 'emissionFactors',
},
],
@ -914,6 +938,7 @@
{
title: '排放量',
dataIndex: 'emissions',
width: 100,
key: 'emissions',
fixed: 'right',
},
@ -1069,12 +1094,23 @@
//
const options = await dict({ params: { dicKey: 'ENERGY_TYPE' } });
energyTypeOptions.value = options.data.data;
editFormState.value.key = record.factorName;
editFormState.value.key = record.factorId;
searchKey();
editFormState.value.id = record.id;
editFormState.value.dataSources = record.dataSources;
if (record.dataSources !== undefined) {
if (record.dataSources.value === 3) {
canEdit.value = true;
automatic.value = true;
} else {
canEdit.value = false;
automatic.value = false;
}
}
editFormState.value.consumption = record.consumption;
editFormState.value.collectionNode = record.carbonSource;
editFormState.value.energyConsumptionType = record.energyConsumptionType;
changeEnergyType(record.energyConsumptionType);
editFormState.value.collectionNode = record.collectionNode;
editFormState.value.factorId = record.factorId;
editFormState.value.emissionFactors = record.emissionFactors;
selectedRowKeysEdit.value = [record.factorId];
@ -1097,9 +1133,9 @@
};
const searchKey = () => {
if (editFormState.value.key) {
queryData.value.emissionSources = editFormState.value.key;
queryData.value.factorId = editFormState.value.key;
} else {
queryData.value.emissionSources = '';
queryData.value.factorId = 0;
}
getNewTable();
};
@ -1137,6 +1173,7 @@
};
const spinning = ref(false);
const selectNode = (value) => {
editFormState.value.collectionNode = value;
spinning.value = true;
const getConsumeData = ref({
acquisitionDate: acquisitionDate.value,
@ -1198,9 +1235,9 @@
if (editFormState.value.dataSources.value) {
editFormState.value.dataSources = editFormState.value.dataSources.value;
}
if (editFormState.value.collectionNode) {
editFormState.value.collectionNode = editFormState.value.collectionNode.value;
}
// if (editFormState.value.collectionNode) {
// editFormState.value.collectionNode = editFormState.value.collectionNode.value;
// }
fetch(carbonInventoryCheck.updateTable, editFormState.value).then((res) => {
if (fileList.value.length !== 0) {
const formData = ref(new FormData());
@ -1235,6 +1272,32 @@
console.log('error', error);
});
};
const openVisible = ref(false);
const setFactorRef = ref();
const config = setFactorConfig(orgId.value);
const selectFactor = () => {
openVisible.value = true;
};
const btnClick = () => {
let selectRowKeys = setFactorRef.value?.nsTableRef.tableState.selectedRowKeys;
if (selectRowKeys.length === 0) {
NsMessage.warn('请选择因子');
return;
} else {
if (newTableData.value.emissionFactorUnits === carbonEmission.value) {
newTableData.value = setFactorRef.value?.nsTableRef.tableState.selectedRows;
selectedRowKeysEdit.value = setFactorRef.value?.nsTableRef.tableState.selectedRowKeys;
editFormState.value.emissionFactors = newTableData.value[0].emissionFactors;
editFormState.value.factorId = selectedRowKeysEdit.value[0];
openVisible.value = false;
} else {
NsMessage.warn('因子值单位不统一,请重新选择!');
}
}
};
const onCloseClick = () => {
openVisible.value = false;
};
const onCloseEditData = () => {
editData.value = false;
delIds.value = [];
@ -1249,7 +1312,7 @@
const onChange = (pageNumber: number, size: number) => {
queryData.value.pageNum = pageNumber;
queryData.value.pageSize = size;
getNewTable();
// getNewTable();
};
// /
const fillInPage = ref(true);
@ -1730,9 +1793,11 @@
.mainLeft {
width: 19%;
margin-right: 1%;
border-right: 1px solid #f2f2f2;
position: relative;
height: 96%;
height: 100%;
border: 1px solid #f2f2f2;
border-radius: 8px;
padding: 4px;
.treeRow {
display: flex;
justify-content: space-between;
@ -1757,6 +1822,7 @@
}
.mainRight {
width: 80%;
border-left: 1px solid #f2f2f2;
}
}

7
hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/index.vue

@ -79,7 +79,7 @@
</template>
<script lang="ts" setup>
import { ref, toRaw } from 'vue';
import { ref, toRaw, watch, nextTick } from 'vue';
import { http } from '/nerv-lib/util/http';
import { carbonInventoryCheck } from '/@/api/carbonEmissionFactorLibrary';
import fillIn from './fillInPage/index.vue';
@ -118,7 +118,10 @@
const openChange = (status) => {
if (status === false) {
if (formState.value.reportYear) {
defaultPickerValue.value = [dayjs('2022'), dayjs('2022')];
defaultPickerValue.value = [
dayjs(formState.value.reportYear),
dayjs(formState.value.reportYear),
];
}
}
};

231
hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/categoryDeatil.vue

@ -100,7 +100,6 @@
<a-table-summary-row>
<a-table-summary-cell></a-table-summary-cell>
<a-table-summary-cell :colSpan="2">合计</a-table-summary-cell>
<a-table-summary-cell></a-table-summary-cell>
<a-table-summary-cell>
<a-typography-text>{{ totalLastYearActualUsage + unit }}</a-typography-text>
</a-table-summary-cell>
@ -153,88 +152,120 @@
</a-form>
</a-modal>
<!-- 基准值设置 -->
<a-modal :visible="visible" @ok="onSubmit" @cancel="onClose">
<a-tooltip placement="top">
<template #title>
<span>月基准值设置使用基准年相应月份的数据作为当前年相应月份的基准值</span>
</template>
<QuestionCircleOutlined style="position: absolute; right: 60px; top: 22px; z-index: 7" />
</a-tooltip>
<div style="display: flex; margin-top: 20px; justify-content: space-between">
<span> 节点{{ props.nodeName }} </span>
<a-date-picker
v-if="activeKey === '1'"
v-model:value="selectYear"
picker="year"
valueFormat="YYYY"
@change="changeYearData" />
</div>
<a-tabs v-model:activeKey="activeKey" @change="handleTabChange">
<a-tab-pane key="1" tab="年基准值设置">
<a-table
:columns="yearColumns"
:data-source="yearTableData"
bordered
:rowKey="(record, index) => record.referenceYear"
:rowSelection="{
selectedRowKeys: selectedRowKeysSet,
onChange: onSelectionChangeSet,
type: 'radio',
}"
:pagination="false">
</a-table>
</a-tab-pane>
<a-tab-pane key="2" tab="月基准值设置" force-render>
<a-table :columns="monthColumns" :data-source="dataSource" bordered :pagination="false">
<template #bodyCell="{ column, text, record }">
<template v-if="['referenceValue'].includes(column.dataIndex)">
<div>
<a-input
v-if="editableData[record.yearMonth]"
v-model:value="editableData[record.yearMonth][column.dataIndex]"
style="margin: -5px 0" />
<template v-else>
{{ text }}
</template>
</div>
</template>
<template v-else-if="column.dataIndex === 'operation'">
<div class="editable-row-operations">
<span v-if="editableData[record.yearMonth]">
<a-popconfirm
title="确定要保存?"
ok-text="确定"
cancel-text="取消"
@confirm="save(record.yearMonth)"
@cancel="cancel(record.yearMonth)">
<a>保存</a>
</a-popconfirm>
</span>
<span v-else>
<a-button
type="link"
@click="edit(record.yearMonth)"
:disabled="record.isAutoObtained === 0 ? true : false">
编辑
</a-button>
</span>
</div>
</template>
<template v-if="column.key === 'isAutoObtained'">
<a-switch
checked-children="是"
un-checked-children="否"
:checked="record.isAutoObtained === 0 ? true : false"
:class="{
'blue-background': record.isAutoObtained === 0 ? true : false,
'grey-background': record.isAutoObtained === 0 ? false : true,
}"
@click="changeSwitch(record)" />
<a-modal
:visible="visible"
@ok="onSubmit"
@cancel="onClose"
:style="{ top: '20px', left: '-100px' }"
:bodyStyle="{ maxHeight: '800px', overflowY: 'auto' }">
<a-spin :spinning="loading">
<a-tooltip placement="top">
<template #title>
<span>月基准值设置使用基准年相应月份的数据作为当前年相应月份的基准值</span>
</template>
<QuestionCircleOutlined style="position: absolute; right: 60px; top: 22px; z-index: 7" />
</a-tooltip>
<a-tabs v-model:activeKey="activeKey" @change="handleTabChange">
<a-tab-pane key="1" tab="年基准值设置">
<div
style="
display: flex;
margin-bottom: 10px;
justify-content: space-between;
margin-top: 10px;
">
<span> 节点{{ props.nodeName }} </span>
<a-date-picker
v-model:value="selectYear"
picker="year"
valueFormat="YYYY"
@change="changeYearData" />
</div>
<a-table
:columns="yearColumns"
:data-source="yearTableData"
bordered
:rowKey="(record, index) => record.referenceYear"
:rowSelection="{
selectedRowKeys: selectedRowKeysSet,
onChange: onSelectionChangeSet,
type: 'radio',
}"
:pagination="false">
</a-table>
<a-pagination
v-model:current="queryData.pageNum"
simple
:total="total"
@change="onChange"
style="display: flex; justify-content: end; margin-top: 10px" />
</a-tab-pane>
<a-tab-pane key="2" tab="月基准值设置" force-render>
<div
style="
display: flex;
margin-bottom: 10px;
justify-content: space-between;
margin-top: 10px;
">
<span> 节点{{ props.nodeName }} </span>
</div>
<a-table
:columns="monthColumns"
:data-source="dataSource"
size="small"
bordered
:pagination="false">
<template #bodyCell="{ column, text, record }">
<template v-if="['referenceValue'].includes(column.dataIndex)">
<div>
<a-input
v-if="editableData[record.yearMonth]"
v-model:value="editableData[record.yearMonth][column.dataIndex]"
style="margin: -5px 0" />
<template v-else>
{{ text }}
</template>
</div>
</template>
<template v-else-if="column.dataIndex === 'operation'">
<div class="editable-row-operations">
<span v-if="editableData[record.yearMonth]">
<a-popconfirm
title="确定要保存?"
ok-text="确定"
cancel-text="取消"
@confirm="save(record.yearMonth)"
@cancel="cancel(record.yearMonth)">
<a>保存</a>
</a-popconfirm>
</span>
<span v-else>
<a-button
type="link"
@click="edit(record.yearMonth)"
:disabled="record.isAutoObtained === 0 ? true : false">
编辑
</a-button>
</span>
</div>
</template>
<template v-if="column.key === 'isAutoObtained'">
<a-switch
checked-children="是"
un-checked-children="否"
:checked="record.isAutoObtained === 0 ? true : false"
:class="{
'blue-background': record.isAutoObtained === 0 ? true : false,
'grey-background': record.isAutoObtained === 0 ? false : true,
}"
@click="changeSwitch(record)" />
</template>
</template>
</template>
</a-table>
</a-tab-pane>
</a-tabs>
</a-table>
</a-tab-pane>
</a-tabs>
</a-spin>
</a-modal>
</div>
</template>
@ -255,7 +286,13 @@
import * as echarts from 'echarts';
import { any, string } from 'vue-types';
import type { Dayjs } from 'dayjs';
import { Pagination } from 'ant-design-vue';
defineOptions({
components: {
'a-pagination': Pagination,
},
});
// id
const props = defineProps({
parentId: {
@ -383,8 +420,10 @@
formState.value.ids = [record.id];
if (record.lastYear === '是') {
formState.value.isLastYear = 1;
disabled.value = false;
} else {
formState.value.isLastYear = 0;
disabled.value = true;
}
formState.value.conversionRate = record.conversionRate;
formState.value.lastYearList = [record.lastYearActualUsage];
@ -454,7 +493,14 @@
orgId: orgId.value,
type: props.type,
itemizeId: props.parentId,
pageSize: 10,
pageNum: 1,
});
const total = ref();
const onChange = (page, pageSize) => {
queryData.value.pageNum = page;
setBasicData();
};
const changeYearData = () => {
queryData.value.referenceYear = selectYear.value;
setBasicData();
@ -462,7 +508,8 @@
const yearTableData = ref([]);
const setBasicData = () => {
fetch(carbonPlanning.benchmarkSetting, queryData.value).then((res) => {
yearTableData.value = res.data;
yearTableData.value = res.data.records;
total.value = res.data.total;
});
visible.value = true;
};
@ -507,6 +554,7 @@
{
title: '日期',
dataIndex: 'yearMonth',
width: '20%',
},
{
title: '用电量',
@ -543,7 +591,9 @@
const cancel = (yearMonth: string) => {
delete editableData[yearMonth];
};
const loading = ref(false);
const onSubmit = () => {
loading.value = true;
const benchmark = monthData.value;
fetch(carbonPlanning.benchmarkSubmit, {
benchmark: benchmark,
@ -555,6 +605,7 @@
visible.value = false;
activeKey.value = '1';
selectedRowKeysSet.value = [];
loading.value = false;
getTableData();
});
};
@ -623,8 +674,8 @@
props.year + '年预算',
'基准值',
],
top: '0',
right: '0',
top: '1%',
right: '1%',
textStyle: {
color: '#666',
fontSize: 12,
@ -781,7 +832,6 @@
<style lang="less" scoped>
.detailContant {
height: 100%;
margin: 12px;
}
.ns-form-title {
font-weight: bold;
@ -791,7 +841,7 @@
align-items: center;
width: 100%;
height: 5vh;
padding: 12px 12px 0 12px;
.title {
text-align: left;
height: 32px;
@ -826,11 +876,15 @@
width: 100%;
height: calc(95% - 5vh);
overflow: auto;
padding: 12px;
.chartsPart {
width: 100%;
height: 63%;
display: flex;
justify-content: space-between;
border-radius: 12px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 2px 20px rgb(69 123 234 / 20%);
.chart {
width: 100%;
height: 65%;
@ -938,6 +992,9 @@
right: 10px;
top: 5px;
}
:deep(.ant-card-bordered) {
border: unset;
}
</style>
<style scoped>
.editable-row-operations a {

7
hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/index.vue

@ -126,6 +126,9 @@
energyType: {
type: String,
},
energyTypeName: {
type: String,
},
});
const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
@ -216,7 +219,9 @@
const option = {
backgroundColor: 'transparent',
title: {
text: '历年用电量分析',
text: selectedTime.value
? '历年' + props.energyTypeName + '分析'
: '每月' + props.energyTypeName + '分析',
x: '0',
textStyle: {
color: 'rgba(51, 51, 51, 1)',

36
hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/index.vue

@ -4,19 +4,39 @@
<all ref="allRef" />
</a-tab-pane>
<a-tab-pane key="2" tab="用电量">
<category ref="electricRef" :tabId="tabId" :energyType="energyType" />
<category
ref="electricRef"
:tabId="tabId"
:energyType="energyType"
:energyTypeName="energyTypeName" />
</a-tab-pane>
<a-tab-pane key="3" tab="用水量">
<category ref="useWaterRef" :tabId="tabId" :energyType="energyType" />
<category
ref="useWaterRef"
:tabId="tabId"
:energyType="energyType"
:energyTypeName="energyTypeName" />
</a-tab-pane>
<a-tab-pane key="4" tab="用气量">
<category ref="provideWaterRef" :tabId="tabId" :energyType="energyType" />
<category
ref="provideWaterRef"
:tabId="tabId"
:energyType="energyType"
:energyTypeName="energyTypeName" />
</a-tab-pane>
<a-tab-pane key="5" tab="供热量">
<category ref="carbonEmissionsRef" :tabId="tabId" :energyType="energyType" />
<category
ref="carbonEmissionsRef"
:tabId="tabId"
:energyType="energyType"
:energyTypeName="energyTypeName" />
</a-tab-pane>
<a-tab-pane key="6" tab="碳排量">
<category ref="provideHotRef" :tabId="tabId" :energyType="energyType" />
<category
ref="provideHotRef"
:tabId="tabId"
:energyType="energyType"
:energyTypeName="energyTypeName" />
</a-tab-pane>
</a-tabs>
</template>
@ -41,6 +61,7 @@
// tab
const tabId = ref(1);
const energyType = ref();
const energyTypeName = ref();
const handleTabChange = (key) => {
console.log('Tab changed:', key);
//
@ -53,6 +74,7 @@
} else if (key === '2') {
tabId.value = 4;
energyType.value = 'ELECTRICITY_USAGE';
energyTypeName.value = '用电量';
nextTick(() => {
if (electricRef.value) {
electricRef.value.electricTotal = true;
@ -62,6 +84,7 @@
} else if (key === '3') {
tabId.value = 5;
energyType.value = 'WATER_USAGE';
energyTypeName.value = '用水量';
nextTick(() => {
if (useWaterRef.value) {
useWaterRef.value.electricTotal = true;
@ -71,6 +94,7 @@
} else if (key === '4') {
tabId.value = 6;
energyType.value = 'GAS_USAGE';
energyTypeName.value = '用气量';
nextTick(() => {
if (provideWaterRef.value) {
provideWaterRef.value.electricTotal = true;
@ -80,6 +104,7 @@
} else if (key === '5') {
tabId.value = 7;
energyType.value = 'CARBON_EMISSIONS';
energyTypeName.value = '供热量';
nextTick(() => {
if (carbonEmissionsRef.value) {
carbonEmissionsRef.value.electricTotal = true;
@ -89,6 +114,7 @@
} else if (key === '6') {
tabId.value = 8;
energyType.value = 'HEAT_SUPPLY';
energyTypeName.value = '碳排量';
nextTick(() => {
if (provideHotRef.value) {
provideHotRef.value.electricTotal = true;

4
hx-ai-intelligent/src/view/monitor/deviceMonitor/page.vue

@ -52,6 +52,10 @@
if (graphRef.value) {
graphRef.value.downloadChart();
}
} else {
if (tableRef.value) {
tableRef.value.export1();
}
}
};

5
hx-ai-intelligent/src/view/monitor/deviceMonitor/table/index.vue

@ -16,6 +16,7 @@
</template>
<script lang="ts">
import { exportExcel } from '/@/util/ExcelUtil.js';
import { defineComponent, watch, ref, onMounted } from 'vue';
import type { TableColumnType } from 'ant-design-vue';
import { Pagination } from 'ant-design-vue';
@ -245,6 +246,9 @@
columns.value = columnA;
total.value = dataList.value.length;
onChange(1, 10);
}; // excel
const export1 = () => {
exportExcel(columns.value, dataList.value, '历史数据导出', true, 'deviceName', 1, 4);
};
onMounted(() => {
init();
@ -257,6 +261,7 @@
total,
onChange,
x,
export1,
};
},
});

22
hx-ai-intelligent/src/view/monitor/deviceMonitor/tree/index.vue

@ -15,17 +15,17 @@
:tree-data="treeData1"
@change="changeDeviceType" />
<a-spin :spinning="treeLoading">
<a-tree
v-model:expandedKeys="expandedKeys"
v-model:selectedKeys="selectedKeys"
v-model:checkedKeys="checkedKeys"
:show-line="{ showLeafIcon: false }"
checkable
:height="560"
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
:tree-data="treeData2" />
</a-spin>
<!-- <a-spin :spinning="treeLoading"> -->
<a-tree
v-model:expandedKeys="expandedKeys"
v-model:selectedKeys="selectedKeys"
v-model:checkedKeys="checkedKeys"
:show-line="{ showLeafIcon: false }"
checkable
:height="560"
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
:tree-data="treeData2" />
<!-- </a-spin> -->
<!-- <div class="fixed-bottom"> -->
<div>

150
hx-ai-intelligent/src/view/monitor/energyMonitor/analysisTable/index.vue

@ -18,6 +18,8 @@
</template>
<script lang="ts">
import ExcelJS from 'exceljs';
import FileSaver from 'file-saver';
import { defineComponent, ref, inject, watch, onMounted } from 'vue';
export default defineComponent({
@ -130,6 +132,153 @@
},
{ deep: true },
);
// excel
//
const export1 = () => {
if (!data.value || data.value.length == 0) {
return;
}
//
for (let i = 0; i < data.value.length; i++) {
data.value[i].index = i + 1;
}
// 簿
const workbook = new ExcelJS.Workbook();
// sheet1
const sheet1 = workbook.addWorksheet('sheet1');
//
let filterVal = [
'name',
'value',
'yoyDiff',
'yoyRate',
'momDiff',
'momRate',
'zongxiangDiff',
'zongxiangRate',
];
// columns
//
sheet1.addRows([
['设备/节点', '统计值', '同比', '', '环比', '', '纵向对比', ''],
['', '', '△差值', '增长率', '△差值', '增长率', '△差值', '增长率'],
]);
//
sheet1.mergeCells('A1:A2'); // '/'
sheet1.mergeCells('B1:B2'); // ''
sheet1.mergeCells('C1:D1'); // ''
sheet1.mergeCells('E1:F1'); // ''
sheet1.mergeCells('G1:H1'); // ''
//
const list = data.value;
//
const datas = formatJson(filterVal, list);
//
datas.forEach((row: any) => {
// const values = Object.values(row);
sheet1.addRow(row);
});
let column = sheet1.columns;
for (let i = 0; i < column.length; i++) {
column[i].width = 20;
}
//
//
sheet1.eachRow((row) => {
//
row.eachCell((cell) => {
//
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' },
};
//
cell.alignment = {
vertical: 'middle',
horizontal: 'center',
};
});
});
//
const titleCell1 = sheet1.getRow(1);
// 30
titleCell1.height = 30;
//
titleCell1.eachCell((cell) => {
//
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFFFF' },
};
//
cell.font = {
// color: { argb: 'FF0000' }, //
bold: true, //
size: 18, // 18
};
});
const titleCell2 = sheet1.getRow(2);
// 30
titleCell2.height = 30;
//
titleCell2.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(3, sheet1.rowCount);
if (bodyRows) {
//
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, '分析数据导出.xlsx');
})
.catch((error) => console.log('Error writing excel export', error));
};
/**
* 格式化表格数据
* @filterVal 格式头
* @jsonData 用来格式化的表格数据
*/
function formatJson(filterVal: any, jsonData: any) {
return jsonData.map((v: any) => filterVal.map((j: any) => v[j]));
}
onMounted(() => {
//
data.value = JSON.parse(JSON.stringify(pageData.analysisTableList));
@ -165,6 +314,7 @@
rowSelection,
selectedKey,
setStandard,
export1,
};
},
});

5
hx-ai-intelligent/src/view/monitor/energyMonitor/graphTable/index.vue

@ -16,6 +16,7 @@
</template>
<script lang="ts">
import { exportExcel } from '/@/util/ExcelUtil.js';
import { defineComponent, watch, inject, ref, onMounted } from 'vue';
import type { TableColumnType } from 'ant-design-vue';
import { Pagination } from 'ant-design-vue';
@ -152,6 +153,9 @@
columns.value = columnA;
total.value = dataList.value.length;
onChange(1, 10);
}; // excel
const export1 = () => {
exportExcel(columns.value, dataList.value, '图表数据导出');
};
onMounted(() => {
init();
@ -167,6 +171,7 @@
columns,
total,
onChange,
export1,
};
},
});

26
hx-ai-intelligent/src/view/monitor/energyMonitor/page.vue

@ -28,7 +28,7 @@
</template> -->
</a-tabs>
<div class="button">
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="downloadChart" />
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="download" />
<ns-icon :name="iconName" size="18" style="margin-right: 10px" @click="change" />
</div>
</div>
@ -74,14 +74,26 @@
name: 'EnvironmentMonitorIndex', // name
});
const downloadChart = () => {
if (activeKey.value == '1' && isGraph) {
if (graphRef.value) {
graphRef.value.downloadChart();
const download = () => {
if (activeKey.value == '1') {
if (isGraph.value) {
if (graphRef.value) {
graphRef.value.downloadChart();
}
} else {
if (tableRef.value) {
tableRef.value.export1();
}
}
} else {
if (analysisGraphRef.value) {
analysisGraphRef.value.downloadChart();
if (isGraph.value) {
if (analysisGraphRef.value) {
analysisGraphRef.value.downloadChart();
}
} else {
if (analysisTableRef.value) {
analysisTableRef.value.export1();
}
}
}
};

26
hx-ai-intelligent/src/view/monitor/energyMonitor/tree/index.vue

@ -35,17 +35,17 @@
v-if="mode == '0'"
@change="changeMode" />
<a-input v-model:value="pointName" placeholder="请输入节点名称" v-else @change="changeMode" />
<a-spin :spinning="treeLoading">
<a-tree
v-model:expandedKeys="expandedKeys"
v-model:selectedKeys="selectedKeys"
v-model:checkedKeys="checkedKeys"
:show-line="{ showLeafIcon: false }"
checkable
:height="600"
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
:tree-data="treeData2">
<!-- <template #title="{ title }">
<!-- <a-spin :spinning="treeLoading"> -->
<a-tree
v-model:expandedKeys="expandedKeys"
v-model:selectedKeys="selectedKeys"
v-model:checkedKeys="checkedKeys"
:show-line="{ showLeafIcon: false }"
checkable
:height="500"
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
:tree-data="treeData2">
<!-- <template #title="{ title }">
<span v-if="title.indexOf(mode == '0' ? deviceName : pointName) > -1">
{{ title.substr(0, title.indexOf(mode == '0' ? deviceName : pointName)) }}
<span style="color: #f50">{{ mode == '0' ? deviceName : pointName }}</span>
@ -58,8 +58,8 @@
</span>
<span v-else>{{ title }}</span>
</template> -->
</a-tree>
</a-spin>
</a-tree>
<!-- </a-spin> -->
<!-- <div class="fixed-bottom"> -->
<div>

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

@ -38,7 +38,10 @@
查询
</a-button>
</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>
</div>
@ -66,6 +69,7 @@
<!-- </a-spin> -->
</template>
<script lang="ts" setup>
import { exportExcel } from '/@/util/ExcelUtil.js';
import { ref, onMounted } from 'vue';
// import { http } from '/nerv-lib/util/http';
import { Pagination, SelectProps, TreeSelectProps, TableColumnType } from 'ant-design-vue';
@ -200,6 +204,10 @@
loading.value = false;
});
};
// excel
const export1 = () => {
exportExcel(tableColumns.value, data.value, '平均数据导出');
};
onMounted(async () => {
//
let frequency = await getEnum({ params: { enumType: 'TimeFlagEnum' } });

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

@ -62,7 +62,7 @@
<a-button
type="primary"
style="position: absolute; right: 40px; top: -45px"
@click="exportExcel()">
@click="export1()">
导出
</a-button>
</div>
@ -87,8 +87,7 @@
</div>
</template>
<script lang="ts" setup>
import XLSX from 'xlsx';
// import Export2Excel from '/@/util/Export2Excel.js';
import { exportExcel } from '/@/util/ExcelUtil.js';
import { ref, onMounted, defineOptions } from 'vue';
// import { http } from '/nerv-lib/util/http';
@ -289,6 +288,10 @@
//
const getTableList = () => {
loading.value = true;
tableColumns.value = [];
data.value = [];
total.value = 0;
pageData.value = [];
let environmentType = '';
for (let i = 0; i < typeList.value.length; i++) {
if (typeList.value[i].value == typeValue.value) {
@ -352,60 +355,9 @@
}
});
};
// excel
/**
* @前期准备 npm install -S xlsx file-saver Export2Excel.js
*/
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]));
// excel
const export1 = () => {
exportExcel(tableColumns.value, data.value, '历史数据导出', true, 'location', 1, 3);
};
onMounted(async () => {
//

Loading…
Cancel
Save