duyufeng 3 weeks ago
parent
commit
c76dcaa7c5
  1. 8
      hx-ai-intelligent/src/api/planToAdd.ts
  2. 12
      hx-ai-intelligent/src/components/ns-modal-form.vue
  3. 22
      hx-ai-intelligent/src/icon/fenzujiedian.svg
  4. 11
      hx-ai-intelligent/src/icon/jisuanjiedian.svg
  5. 210
      hx-ai-intelligent/src/util/ExcelUtil.js
  6. 220
      hx-ai-intelligent/src/util/Export2Excel.js
  7. 30
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonAssets/carbonAssetsDetail/index.vue
  8. 5
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonAssets/index.vue
  9. 45
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/energyConsumption/index.vue
  10. 26
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index.vue
  11. 110
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/config.ts
  12. 104
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/fillInPage/index.vue
  13. 7
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/index.vue
  14. 231
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/categoryDeatil.vue
  15. 7
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/index.vue
  16. 36
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/index.vue
  17. 76
      hx-ai-intelligent/src/view/equipmentControl/planToAdd/index.vue
  18. 13
      hx-ai-intelligent/src/view/monitor/environmentMonitor/averageData/index.vue
  19. 62
      hx-ai-intelligent/src/view/monitor/environmentMonitor/historyData/index.vue
  20. 8
      lib/component/table/table.vue
  21. 5
      lib/component/tree/tree-api.vue

8
hx-ai-intelligent/src/api/planToAdd.ts

@ -1,7 +1,9 @@
import { BASE_URL } from './index';
export enum planToAddApi {
getActivatedPlanTree = `${BASE_URL}/api/deviceCtrlPlan/getActivatedPlanTree`, //计划树
getActivatedPlanListByTree = `${BASE_URL}/api/deviceCtrlPlan/getActivatedPlanListByTree`, //计划列表
updPlan = `${BASE_URL}/api/deviceCtrlPlan/updateActivatedPlan`, //修改计划
getActivatedPlanTree = `${BASE_URL}/api/deviceCtrlPlan/getPlanLibTree`, //计划树
getActivatedPlanListByTree = `${BASE_URL}/api/deviceCtrlPlan/getPageAblePlanListByTree`, //计划列表
updPlan = `${BASE_URL}/api/deviceCtrlPlan/updateCtrlPlan`, //修改计划
delPlan = `${BASE_URL}/api/deviceCtrlPlan/deleteCtrlPlanByIdList`, //修改计划
addPlan = `${BASE_URL}/api/deviceCtrlPlan/addCtrlPlan`, //添加计划
}

12
hx-ai-intelligent/src/components/ns-modal-form.vue

@ -66,10 +66,14 @@
httpRequest({ api, params: data, pathParams: params, requestConfig })
.then((res) => {
NsMessage.success('操作成功', 1, () => {
toggle();
success && success(res);
});
if (res.msg === 'success') {
NsMessage.success('操作成功', 1, () => {
toggle();
success && success(res);
});
} else {
NsMessage.error(res.msg);
}
})
.finally(() => {
setLoading(false);

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

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

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;

76
hx-ai-intelligent/src/view/equipmentControl/planToAdd/index.vue

@ -1,12 +1,33 @@
<template>
<ns-view-list-table ref="mainRef" v-bind="config">
<template #bodyCell="{ record, column }">
<template v-if="column.dataIndex === 'executionTime'">
{{ getData(record) }}
<div style="width: 100%; height: 100%; position: relative">
<ns-view-list-table ref="mainRef" v-bind="config">
<template #bodyCell="{ record, column }">
<template v-if="column.dataIndex === 'executionTime'">
{{ getData(record) }}
</template>
<template v-if="column.dataIndex === 'executeStatus'">
<div
:style="{
color: {
'0': '#ccc',
'1': 'rgba(255, 165, 0, 1)',
'2': 'rgb(57, 215, 187)',
'3': 'rgb(255, 0, 0)',
}[record.executeStatus.value],
}">
{{ record.executeStatus.label }}</div
>
</template>
</template>
</template>
</ns-view-list-table>
<NsModalFrom ref="modalFormRef" v-bind="nsModalFormConfig" />
</ns-view-list-table>
<a-button
type="primary"
style="position: absolute; bottom: 20px; height: 30px; left: 13%"
@click="addPlan"
>添加</a-button
>
<NsModalFrom ref="modalFormRef" v-bind="nsModalFormConfig" />
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
@ -14,6 +35,7 @@
import { planToAddApi } from '/@/api/planToAdd';
import { NsMessage } from '/nerv-lib/component';
import { getEnum } from '/@/api';
import { http } from '/nerv-lib/util';
//
const orgId = ref('');
@ -24,6 +46,24 @@
projectId.value = results.projectId;
const mainRef = ref(null);
const modalFormRef = ref(null);
const addPlan = () => {
if (mainRef.value.nsTableRef.treeElRef.selectedRow.node.planLib) {
http
.get(planToAddApi.addPlan, {
libId: mainRef.value.nsTableRef.treeElRef.selectedRow.node.planLib.id,
})
.then((res) => {
if (res.msg === 'success') {
NsMessage.success('添加成功');
mainRef.value?.nsTableRef.reload();
} else {
NsMessage.error(res.msg);
}
});
} else {
NsMessage.warning('只有最后一级才能添加');
}
};
const getData = (record: any) => {
return record.startTime
? record.startTime.substring(0, 10) + ' - ' + record.endTime.substring(0, 10)
@ -67,8 +107,6 @@
success: (data: any) => {
if (data.msg === 'success') {
mainRef.value?.nsTableRef.reload();
} else {
NsMessage.error(data.msg);
}
},
});
@ -81,7 +119,7 @@
config.value = {
title: '计划库',
api: planToAddApi.getActivatedPlanListByTree,
params: { orgId, projectId, ctrlType: enumData.data[0].value },
params: { orgId, projectId },
treeConfig: {
defaultExpandAll: true,
header: {
@ -90,20 +128,13 @@
},
params: { projectId, ctrlType: enumData.data[0].value },
dynamicParams: {
id: 'id',
pid: 'pid',
level: 'level',
projectId: 'projectId',
ctrlType: 'ctrlType',
treeId: 'id',
},
api: planToAddApi.getActivatedPlanTree,
fieldNames: {
title: 'name',
key: 'id',
pid: 'pid',
level: 'level',
projectId: 'projectId',
ctrlType: 'ctrlType',
children: 'childList',
},
formConfig: {
@ -151,6 +182,10 @@
dataIndex: 'planName',
},
{
title: '执行状态',
dataIndex: 'executeStatus',
},
{
title: '执行时间',
dataIndex: 'executionTime',
},
@ -166,9 +201,8 @@
name: 'energyAlarmEdit',
dynamicParams: ['uuid', 'appealType'],
handle: (data: any) => {
console.log(mainRef.value, '数据');
if (data?.executeStatus?.value === 2) {
NsMessage.warning('当前计划正在执行,无法进行编辑。如需编辑,请先停止计划.');
NsMessage.warning('当前计划正在执行,无法进行编辑。如需编辑,请先停止计划');
} else {
const obj = { ...data };
nsModalFormConfig.value.title = '编辑';
@ -192,7 +226,7 @@
dynamicParams: ['uuid', 'appealType'],
confirm: true,
handle: (data: any) => {
http.post(planToAddApi.updPlan, [data.id]).then((res) => {
http.post(planToAddApi.delPlan, [data.id]).then((res) => {
if (res.msg === 'success') {
NsMessage.success('操作成功');
mainRef.value?.nsTableRef.reload();

13
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,13 @@
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 () => {
//
let frequency = await getEnum({ params: { enumType: 'TimeFlagEnum' } });

62
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';
@ -352,60 +351,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, 1, 3);
};
onMounted(async () => {
//

8
lib/component/table/table.vue

@ -17,7 +17,11 @@
<!-- todo drag -->
<div class="ns-part-tree" v-if="!isEmpty(treeConfig)">
<ns-tree-api v-bind="getTreeBindValue" @reload="reload" @select="treeSelect" />
<ns-tree-api
ref="treeElRef"
v-bind="getTreeBindValue"
@reload="reload"
@select="treeSelect" />
</div>
<div class="ns-part-table">
<a-spin :spinning="tableState.loading">
@ -220,6 +224,7 @@
setup(props, { attrs, emit }) {
const tableElRef = ref(null);
const formElRef = ref(null);
const treeElRef = ref(null);
const dataRef = ref([]);
const treeParamsRef = ref({});
const formParamsRef = ref({});
@ -632,6 +637,7 @@
reload,
clearCheck,
formElRef,
treeElRef,
tableElRef,
getColumnActions,
getTableBindValues,

5
lib/component/tree/tree-api.vue

@ -43,6 +43,7 @@
const treeData = ref(props.treeData);
const selectedKeys = ref(props.selectedKeys || []);
const selectedRow = ref(props.selectedRow || {});
const { httpRequest } = useApi();
const requestConfig: AxiosRequestConfig = { method: 'get' };
const route = useRoute();
@ -87,6 +88,7 @@
const handleSelect = (keys: any, selectedRows: any) => {
if (props.cancelable || !isEmpty(keys)) {
selectedKeys.value = keys;
selectedRow.value = selectedRows;
// props.onSelect && props.onSelect(keys, selectedRows);
emit('select', keys, selectedRows);
}
@ -147,9 +149,10 @@
const clearSelectedKeys = () => {
selectedKeys.value = [];
selectedRow.value = {};
};
defineExpose({ treeReload, clearSelectedKeys });
defineExpose({ treeReload, clearSelectedKeys, selectedKeys, selectedRow });
</script>
<style lang="less" scoped>
@gap: 16px;

Loading…
Cancel
Save