zhaohy 3 months ago
parent
commit
fddba152fc
  1. 3
      hx-ai-intelligent/src/api/carbonEmissionFactorLibrary.ts
  2. 2
      hx-ai-intelligent/src/api/monitor.ts
  3. 10
      hx-ai-intelligent/src/icon/xianshiqi.svg
  4. 11
      hx-ai-intelligent/src/icon/xiazai.svg
  5. 21
      hx-ai-intelligent/src/icon/zongheshuju.svg
  6. 63
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonAssets/carbonAssetsDetail/index.vue
  7. 11
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionFactorLibrary/index.vue
  8. 952
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/energyConsumption/index copy.vue
  9. 56
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/energyConsumption/index.vue
  10. 587
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index copy.vue
  11. 14
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionStatistics/quickCalculation/index.vue
  12. 61
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/fillInPage/index.vue
  13. 29
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonInventoryCheck/index.vue
  14. 74
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/all/index.vue
  15. 49
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/categoryDeatil.vue
  16. 36
      hx-ai-intelligent/src/view/carbonEmissionManage/carbonPlanning/category/index.vue
  17. 15
      hx-ai-intelligent/src/view/monitor/deviceMonitor/page.vue
  18. 13
      hx-ai-intelligent/src/view/monitor/deviceMonitor/tree/index.vue
  19. 85
      hx-ai-intelligent/src/view/monitor/energyMonitor/analysisGraph/index.vue
  20. 21
      hx-ai-intelligent/src/view/monitor/energyMonitor/graphGraph/index.vue
  21. 38
      hx-ai-intelligent/src/view/monitor/energyMonitor/page.vue
  22. 43
      hx-ai-intelligent/src/view/monitor/energyMonitor/tree/index.vue
  23. 225
      hx-ai-intelligent/src/view/monitor/environmentMonitor/aggregateData/index.vue
  24. 32
      hx-ai-intelligent/src/view/monitor/environmentMonitor/averageData/index.vue
  25. 37
      hx-ai-intelligent/src/view/monitor/environmentMonitor/historyData/index.vue
  26. 27
      hx-ai-intelligent/src/view/monitor/environmentMonitor/index.vue

3
hx-ai-intelligent/src/api/carbonEmissionFactorLibrary.ts

@ -49,6 +49,7 @@ export enum carbonInventoryCheck {
createOrUpdate = '/carbon-smart/api/carbon/report/createOrUpdate',
findById = '/carbon-smart/api/carbon/report/findById',
delete = '/carbon-smart/api/carbon/report/delete',
downloadZip = '/carbon-smart/api/carbon/report/downloadZip',
// 填报页面接口
// 最左侧碳盘查报告树
getCategoryTree = '/carbon-smart/api/carbon/inventory/contact/getCategoryTree',
@ -77,6 +78,8 @@ export enum carbonAssets {
createOrUpdate = '/carbon-smart/api/carbon/trade/details/createOrUpdate',
delete = '/carbon-smart/api/carbon/trade/details/delete',
quotaStatistics = '/carbon-smart/api/carbon/trade/details/quotaStatistics',
import = '/carbon-smart/api/carbon/trade/details/import',
export = '/carbon-smart/api/carbon/trade/details/export',
}
// 上传图片接口
export enum uploadPic {

2
hx-ai-intelligent/src/api/monitor.ts

@ -1,7 +1,7 @@
// 设备监测
export enum deviceMonitor {
getDeviceGraph = '/carbon-smart/api/monitor/getDeviceGraph',
getDevicePointToMonitor = '/carbon-smart//api/monitor/getDevicePointToMonitor',
getDevicePointToMonitor = '/carbon-smart/api/monitor/getDevicePointToMonitor',
}
// 能耗监测

10
hx-ai-intelligent/src/icon/xianshiqi.svg

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="37.921875" height="30.218994140625" viewBox="0 0 37.921875 30.218994140625" fill="none">
<path d="M37.6256 11.8506L0.296264 11.8506C0.133319 11.8506 0 11.9839 0 12.1469L0 21.9236C0 22.5791 0.529573 23.1086 1.18506 23.1086L17.4796 23.1086C17.6426 23.1086 17.7759 23.242 17.7759 23.4049L17.7759 26.3676C17.7759 26.5305 17.6426 26.6638 17.4796 26.6638L10.9618 26.6638C10.7988 26.6638 10.6655 26.7972 10.6655 26.9601L10.6655 28.8118C10.6655 28.9747 10.7988 29.108 10.9618 29.108L17.4796 29.108C17.6426 29.108 17.7759 29.2413 17.7759 29.4043L17.7759 30.0709C17.7759 30.1523 17.8425 30.219 17.924 30.219L19.9979 30.219C20.0793 30.219 20.146 30.1523 20.146 30.0709L20.146 29.4043C20.146 29.2413 20.2793 29.108 20.4422 29.108L26.9601 29.108C27.123 29.108 27.2563 28.9747 27.2563 28.8118L27.2563 26.9601C27.2563 26.7972 27.123 26.6638 26.9601 26.6638L20.4422 26.6638C20.2793 26.6638 20.146 26.5305 20.146 26.3676L20.146 23.4049C20.146 23.242 20.2793 23.1086 20.4422 23.1086L36.7368 23.1086C37.3923 23.1086 37.9219 22.5791 37.9219 21.9236L37.9219 12.1469C37.9219 11.9839 37.7885 11.8506 37.6256 11.8506ZM4.74023 16.5908C4.74023 15.9353 5.2698 15.4057 5.92529 15.4057C6.58078 15.4057 7.11035 15.9353 7.11035 16.5908C7.11035 17.2463 6.58078 17.7759 5.92529 17.7759C5.2698 17.7759 4.74023 17.2463 4.74023 16.5908ZM32.8335 17.4278C32.6187 17.6425 32.3225 17.7759 31.9966 17.7759L10.6655 17.7759C10.01 17.7759 9.48046 17.2463 9.48046 16.5908C9.48046 15.9353 10.01 15.4057 10.6655 15.4057L31.9966 15.4057C32.6521 15.4057 33.1816 15.9353 33.1816 16.5908C33.1816 16.9167 33.0483 17.213 32.8335 17.4278ZM36.7368 0L1.18506 0C0.529573 0 0 0.529572 0 1.18507L0 10.9618C0 11.1247 0.133319 11.2581 0.296264 11.2581L37.6256 11.2581C37.7885 11.2581 37.9219 11.1247 37.9219 10.9618L37.9219 1.18507C37.9219 0.529572 37.3923 0 36.7368 0ZM4.74023 4.74022C4.74023 4.08473 5.2698 3.55516 5.92529 3.55516C6.58078 3.55516 7.11035 4.08473 7.11035 4.74022C7.11035 5.39571 6.58078 5.92529 5.92529 5.92529C5.2698 5.92529 4.74023 5.39571 4.74023 4.74022ZM32.8335 5.57718C32.6187 5.79196 32.3225 5.92529 31.9966 5.92529L10.6655 5.92529C10.01 5.92529 9.48046 5.39571 9.48046 4.74022C9.48046 4.08473 10.01 3.55516 10.6655 3.55516L31.9966 3.55516C32.6521 3.55516 33.1816 4.08473 33.1816 4.74022C33.1816 5.06613 33.0483 5.36238 32.8335 5.57718Z" fill="url(#linear_fill_0_5271)" >
</path>
<defs>
<linearGradient id="linear_fill_0_5271" x1="18.9609375" y1="0" x2="18.9609375" y2="30.218994140625" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#2BC69C" />
<stop offset="1" stop-color="#0CA87E" />
</linearGradient>
</defs>
</svg>

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

@ -1 +1,10 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1720430904326" class="icon" viewBox="0 0 1354 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3403" xmlns:xlink="http://www.w3.org/1999/xlink" width="21.15625" height="16"><path d="M1034.83248 645.406063l-191.508238 191.508238a53.622507 53.622507 0 0 1-75.964301 0l-191.508238-191.508238a53.622507 53.622507 0 0 1 0-75.964301 53.622507 53.622507 0 0 1 75.965301 0l102.775054 102.775054V303.884205a53.622507 53.622507 0 1 1 107.245014 0v368.332611l95.753119-102.775054a53.622507 53.622507 0 0 1 75.965301 0 53.622507 53.622507 0 0 1 1.276988 75.964301z m262.364587-175.548385a365.141641 365.141641 0 0 0-97.030108-98.94609 378.546518 378.546518 0 0 0-29.364729-123.202867 397.697341 397.697341 0 0 0-89.369178-127.671825 404.719277 404.719277 0 0 0-133.418773-91.28516A408.549242 408.549242 0 0 0 792.894706 0.026a400.251318 400.251318 0 0 0-225.977921 67.665377 410.464224 410.464224 0 0 0-97.669102 91.285161 261.088598 261.088598 0 0 0-63.836412-7.65993 247.044727 247.044727 0 0 0-176.18738 70.857348 245.129745 245.129745 0 0 0-72.134336 202.360139 324.925011 324.925011 0 0 0-84.263225 72.77333A308.965158 308.965158 0 0 0 0.053 702.22054a310.242146 310.242146 0 0 0 97.029107 228.531898 331.307952 331.307952 0 0 0 105.969025 69.58136 330.030964 330.030964 0 0 0 127.670826 23.619782h656.233963A360.034688 360.034688 0 0 0 1242.298572 919.261544a360.034688 360.034688 0 0 0 81.071254-116.181932 354.288741 354.288741 0 0 0 27.449748-138.523725 344.713829 344.713829 0 0 0-54.260501-194.699209z" fill="#16B187" p-id="3404"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="14.6600341796875" viewBox="0 0 20 14.6600341796875" fill="none">
<path d="M20 11.96C20 12.2933 19.9433 12.6067 19.83 12.9C19.7167 13.1933 19.56 13.46 19.36 13.7C19.16 13.94 18.9233 14.1367 18.65 14.29C18.3767 14.4433 18.08 14.5467 17.76 14.6L17.76 14.64L17.34 14.64L17.32 14.64L4.34 14.64C4.31333 14.64 4.29667 14.6433 4.29 14.65C4.28333 14.6567 4.26667 14.66 4.24 14.66C4.21333 14.66 4.19333 14.6567 4.18 14.65C4.16667 14.6433 4.14667 14.64 4.12 14.64L4 14.64L4 14.62C3.44 14.5933 2.91667 14.4667 2.43 14.24C1.94333 14.0133 1.52 13.71 1.16 13.33C0.8 12.95 0.516667 12.51 0.31 12.01C0.103333 11.51 -7.45058e-08 10.98 0 10.42C7.45058e-08 9.86 0.103333 9.33333 0.31 8.84C0.516667 8.34666 0.796667 7.91333 1.15 7.54001C1.50333 7.16667 1.91667 6.86 2.39 6.62C2.86333 6.37999 3.37333 6.24001 3.92 6.20001C4.01333 5.33333 4.25333 4.52335 4.64 3.77C5.02667 3.01666 5.52333 2.36 6.13 1.8C6.73667 1.24001 7.43333 0.799988 8.22 0.479996C9.00667 0.160004 9.84667 0 10.74 0C11.6867 0 12.58 0.180008 13.42 0.539993C14.26 0.899994 14.99 1.39333 15.61 2.02C16.23 2.64667 16.72 3.37666 17.08 4.20999C17.44 5.04333 17.62 5.93333 17.62 6.88C17.62 7.30667 17.58 7.72334 17.5 8.13C17.42 8.53668 17.3067 8.92665 17.16 9.3C17.1867 9.3 17.2167 9.29666 17.25 9.29001C17.2833 9.28333 17.3133 9.28 17.34 9.28C17.7133 9.28 18.06 9.35001 18.38 9.48999C18.7 9.62999 18.98 9.81999 19.22 10.06C19.46 10.3 19.65 10.5833 19.79 10.91C19.93 11.2367 20 11.5867 20 11.96L20 11.96ZM13.42 9C13.58 8.73334 13.6267 8.57999 13.56 8.54001C13.4933 8.5 13.3267 8.48001 13.06 8.48001C12.9 8.48001 12.6767 8.47667 12.39 8.47C12.1033 8.46333 11.8867 8.45999 11.74 8.45999C11.5267 8.45999 11.39 8.37332 11.33 8.2C11.27 8.02666 11.24 7.78667 11.24 7.48C11.24 7.05333 11.2367 6.70999 11.23 6.45C11.2233 6.19 11.22 5.90666 11.22 5.59999C11.22 5.25333 11.1967 5 11.15 4.84C11.1033 4.67999 10.9133 4.60001 10.58 4.60001C10.34 4.60001 10.16 4.60333 10.04 4.61C9.92 4.61665 9.75333 4.61998 9.54 4.61998C9.18 4.61998 8.95667 4.72334 8.87 4.93001C8.78333 5.13666 8.74 5.34 8.74 5.53999L8.74 6.17999C8.74 6.35332 8.74333 6.52 8.75 6.68001C8.75667 6.84 8.76 7.00667 8.76 7.17999L8.76 7.75999C8.76 7.97333 8.73333 8.13667 8.68 8.25C8.62667 8.36334 8.5 8.42 8.3 8.42C8.22 8.43332 8.11 8.44333 7.97 8.45C7.83 8.45667 7.68667 8.46333 7.54 8.47C7.39333 8.47667 7.25333 8.48 7.12 8.48001L6.8 8.48001C6.52 8.48001 6.35333 8.56667 6.3 8.74001C6.24667 8.91333 6.33333 9.13333 6.56 9.40001C6.78667 9.67999 7.03 9.98334 7.29 10.31C7.55 10.6367 7.80667 10.9667 8.06 11.3C8.31333 11.6333 8.55667 11.9567 8.79 12.27C9.02333 12.5833 9.24 12.8533 9.44 13.08C9.8 13.48 10.1467 13.4733 10.48 13.06C10.68 12.8333 10.9133 12.54 11.18 12.18C11.4467 11.82 11.72 11.4433 12 11.05C12.28 10.6567 12.5467 10.2767 12.8 9.90999C13.0533 9.54332 13.26 9.24001 13.42 9L13.42 9Z" fill="url(#linear_fill_0_2380)" >
</path>
<defs>
<linearGradient id="linear_fill_0_2380" x1="10" y1="0" x2="10" y2="14.6600341796875" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#2BC69C" />
<stop offset="1" stop-color="#0CA87E" />
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

21
hx-ai-intelligent/src/icon/zongheshuju.svg

@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42">
<defs>
<linearGradient id="linear-gradient" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#50a6ff"/>
<stop offset="1" stop-color="#4182fb"/>
</linearGradient>
<filter id="矩形_8514" x="0" y="0" width="42" height="42" filterUnits="userSpaceOnUse">
<feOffset dy="6" input="SourceAlpha"/>
<feGaussianBlur stdDeviation="3" result="blur"/>
<feFlood flood-color="#4886fb" flood-opacity="0.2"/>
<feComposite operator="in" in2="blur"/>
<feComposite in="SourceGraphic"/>
</filter>
</defs>
<g id="组_21753" data-name="组 21753" transform="translate(-1578 -238)">
<g transform="matrix(1, 0, 0, 1, 1578, 238)" filter="url(#矩形_8514)">
<rect id="矩形_8514-2" data-name="矩形 8514" width="24" height="24" rx="8" transform="translate(9 3)" fill="url(#linear-gradient)"/>
</g>
<path id="wodeshenqing" d="M130.422,98.2H123.2a1.211,1.211,0,0,0-1.2,1.215v8.1a1.21,1.21,0,0,0,1.2,1.215h7.221a1.21,1.21,0,0,0,1.2-1.215v-8.1A1.21,1.21,0,0,0,130.422,98.2Zm-3.62,2.041a.606.606,0,1,1-.6.606A.606.606,0,0,1,126.8,100.241Zm-2.6,0a.606.606,0,1,1-.6.606A.6.6,0,0,1,124.206,100.241Zm-.2,2.827h4.429a.406.406,0,0,1,0,.812H124a.406.406,0,0,1,0-.812Zm5.606,3.224H124a.406.406,0,0,1,0-.812h5.606a.406.406,0,0,1,0,.812Zm-.2-4.836a.606.606,0,1,1,.6-.606A.6.6,0,0,1,129.413,101.455Z" transform="translate(1471.873 149.182)" fill="#fff"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

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

@ -51,10 +51,17 @@
<a-card>
<div class="ns-form-title">
<div class="title">交易明细</div>
<div class="operation">
<div class="operation" style="display: flex">
<a-button type="primary" @click="addDetail">新增</a-button>
<a-button type="primary" style="margin-left: 6px">导入</a-button>
<a-button type="primary" style="margin-left: 6px">导出</a-button>
<a-upload
v-model:file-list="importFileList"
name="file"
accept=".xlsx"
:showUploadList="false"
:custom-request="importFile">
<a-button type="primary" style="margin-left: 6px">导入</a-button>
</a-upload>
<a-button type="primary" style="margin-left: 6px" @click="exportFile">导出</a-button>
<a-button
type="primary"
style="margin-left: 6px"
@ -196,8 +203,8 @@
const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
orgId.value = result;
const fetch = (api, params = { orgId }) => {
return http.post(api, params);
const fetch = (api, params = { orgId }, config) => {
return http.post(api, params, config);
};
//
const selectedRowKeys = ref([]);
@ -400,6 +407,52 @@
visible.value = true;
getDictList();
};
const importFileList = ref<UploadProps['fileList']>([]);
const importFile = (options: UploadRequestOption) => {
const { file, onSuccess, onError } = options;
const formData = ref(new FormData());
formData.value.append('file', file as any);
formData.value.append('orgId', orgId.value);
formData.value.append('year', queryParams.value.year);
fetch(carbonAssets.import, formData.value)
.then((res) => {
message.success('操作成功!');
getDetailList();
})
.catch((error) => {
console.log('error', error);
});
};
const exportFile = () => {
const exportQuery = ref({
orgId: orgId.value,
pageNum: 1,
pageSize: 999,
year: queryParams.value.year,
ids: selectedRowKeys.value,
});
const config = {
responseType: 'blob',
};
fetch(carbonAssets.export, exportQuery.value, config)
.then((res) => {
// URL blob
const url = window.URL.createObjectURL(new Blob([res]));
// <a>
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'carbonTradeDetails.xlsx'); //
document.body.appendChild(link);
link.click();
// URL
window.URL.revokeObjectURL(url);
selectedRowKeys.value = []
})
.catch((error) => {
console.error('下载失败:', error);
});
};
//
const fileList = ref<UploadProps['fileList']>([]);
const beforeUpload: UploadProps['beforeUpload'] = (file) => {

11
hx-ai-intelligent/src/view/carbonEmissionManage/carbonEmissionFactorLibrary/index.vue

@ -429,7 +429,7 @@
};
//
const checkedIds = ref([]);
const emissionType = ref();
const emissionList = ref([]);
const checkTreeNode = (checkedKeys, info) => {
checkedTreeNodeKeys.value = checkedKeys;
checkedIds.value = [];
@ -437,7 +437,7 @@
checkedIds.value.push(item.id);
});
sessionStorage.setItem('checkedTreeNode', checkedIds.value);
emissionType.value = checkedIds.value.join(',');
emissionList.value = checkedIds.value;
mainRef.value?.nsTableRef.reload();
};
//
@ -522,7 +522,7 @@
getDefaultIds(items.children);
}
});
emissionType.value = defaultIds.value.join(',');
emissionList.value = defaultIds.value.join(',');
checkedIds.value = defaultIds.value;
sessionStorage.setItem('checkedTreeNode', checkedIds.value);
};
@ -609,7 +609,7 @@
api: carbonEmissionFactorLibrary.getTableList,
params: {
orgId,
emissionType,
emissionList,
},
headerActions: [
{
@ -661,10 +661,12 @@
label: '导出',
type: 'primary',
handle: () => {
// console.log( mainRef.value.nsTableRef.tableState.selectedRowKeys)
const exportQuery = {
orgId: orgId.value,
pageNum: 1,
pageSize: 999,
ids: mainRef.value.nsTableRef.tableState.selectedRowKeys,
};
const config = {
responseType: 'blob',
@ -682,6 +684,7 @@
// URL
window.URL.revokeObjectURL(url);
mainRef.value.nsTableRef.tableState.selectedRowKeys = [];
})
.catch((error) => {
console.error('下载失败:', error);

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

@ -1,952 +0,0 @@
<template>
<div>
<!-- <a-table
:columns="tableColumns"
:data-source="data"
bordered
:pagination="false"
:scroll="{ x: 2000 }">
<template #bodyCell="{ column, text, record }">
<template v-if="column.key === 'action'">
<span>
<a @click="editData(record)">编辑</a>
<a-divider type="vertical" />
<a @click="delData(record)">删除</a>
</span>
</template>
</template>
<template #title>
<a-date-picker v-model:value="selectYear" picker="year" @change="changeYearData" valueFormat="YYYY" />
<div class="buttonGroup">
<a-button type="primary" @click="addNewData">新增</a-button>
<a-button type="primary">导入</a-button>
<a-button type="primary">导出</a-button>
<a-button type="primary">模板下载</a-button>
<a-button type="primary" @click="uploadVoucher">上传凭证</a-button>
<a-button type="primary">凭证下载</a-button>
</div>
</template>
</a-table> -->
<ns-view-list-table
v-bind="tableConfig"
:model="data"
ref="mainRef"
:scroll="{ x: 1500, y: 350 }">
<!-- <template #bodyCell="{ column, text, record }">
<template v-if="column.dataIndex === 'janFlag'">
<span v-if="record.janFlag===1" style="color: rgba(243, 97, 99, 1);">{{text}}</span>
<span v-else style="color: rgba(57, 215, 287, 1);">{{text}}</span>
</template>
</template> -->
</ns-view-list-table>
<!-- <a-pagination
:current="queryParams.pageNum"
:total="total"
:page-size="queryParams.pageSize"
style="display: flex;justify-content: center;margin-top: 16px;"
:show-size-changer="true"
:show-quick-jumper="true"
@change="onChange" /> -->
<!-- 新增数据库数据 -->
<a-drawer
:width="500"
:visible="visible"
:body-style="{ paddingBottom: '80px' }"
:footer-style="{ textAlign: 'right' }"
destroyOnClose
@close="onClose">
<a-form
ref="formRef"
:model="formState"
:rules="rules"
:label-col="labelCol"
:wrapper-col="wrapperCol">
<a-form-item ref="name" label="能耗名称" name="energyType">
<a-input v-model:value="formState.energyType" placeholder="请输入能源种类" />
</a-form-item>
<a-form-item label="计量单位" name="unit">
<a-cascader v-model:value="formState.unit" :options="measurementUnit" />
</a-form-item>
<a-form-item label="能耗类型" name="emissionType" :required="isRequired">
<a-select v-model:value="formState.emissionType" placeholder="请选择能耗类型">
<a-select-option v-for="(item, index) in energyTypeOptions" :key="index" :value="item.dicKey">
{{ item.cnValue }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="自动采集节点" name="collectionNode">
<a-tree-select
v-model:value="formState.collectionNode"
:tree-line="true"
:tree-data="treeData">
</a-tree-select>
</a-form-item>
<a-form-item label="计算碳排" name="isComputeCarbon">
<a-radio-group v-model:value="formState.isComputeCarbon" @change="changeRadio">
<a-radio :value="0"></a-radio>
<a-radio :value="1"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排放类型" name="emissionType" :required="isRequired">
<a-select v-model:value="formState.emissionType" placeholder="请选择排放类型">
<a-select-option v-for="(item, index) in emissionTypeDic" :key="index" :value="item.id">
{{ item.cnValue }}
</a-select-option>
</a-select>
</a-form-item>
<a-row>
<a-col :span="24" style="display: flex; justify-content: space-around">
<a-form-item
label="1月"
name="janFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.janFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="2月"
name="febFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.febFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="3月"
name="marFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.marFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
</a-col>
<a-col :span="24" style="display: flex; justify-content: space-around">
<a-form-item
label="4月"
name="aprFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.aprFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="5月"
name="mayFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.mayFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="6月"
name="junFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.junFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
</a-col>
<a-col :span="24" style="display: flex; justify-content: space-around">
<a-form-item
label="7月"
name="julFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.julFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="8月"
name="augFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.augFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="9月"
name="sepFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.sepFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
</a-col>
<a-col :span="24" style="display: flex; justify-content: space-around">
<a-form-item
label="10月"
name="octFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.octFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="11月"
name="novFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.novFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
<a-form-item
label="12月"
name="decFlag"
:label-col="switchLabelCol"
:wrapper-col="switchWrapperCol">
<a-switch
v-model:checked="formState.decFlag"
:checked-value="1"
:unCheckedValue="0" />
</a-form-item>
</a-col>
</a-row>
<a-form-item ref="name" label="上传凭证">
<a-upload
:file-list="fileList"
name="file"
accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf"
@remove="handleFileRemove"
:before-upload="beforeUpload"
@change="handleChange">
<a-button>
<upload-outlined></upload-outlined>
上传
</a-button>
</a-upload>
</a-form-item>
</a-form>
<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">
<a-upload-dragger
v-model:fileList="fileList"
name="file"
:multiple="true"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
@change="handleChange"
@drop="handleDrop"
>
<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>
</a-upload-dragger>
</a-modal> -->
<!-- 凭证下载 -->
<a-drawer
:visible="downLoadVisible"
title="凭证列表"
:width="500"
@close="onCloseDownLoad"
:footer-style="{ textAlign: 'right' }">
<div></div>
<a-table
:columns="downLoadColumns"
:data-source="downLoadData"
bordered
rowKey="id"
:rowSelection="{
selectedRowKeys: selectedRowKeysSet,
onChange: onSelectionChangeSet,
}"
:pagination="false">
<template #bodyCell="{ column, text, record }">
<template v-if="column.key === 'action'">
<span>
<a @click="downLoad(record)">下载</a>
</span>
</template>
</template>
</a-table>
<template #footer>
<a-button style="margin-right: 8px" @click="onCloseDownLoad">取消</a-button>
<a-button type="primary" @click="onSubmitDownLoad">确定</a-button>
</template>
</a-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref, toRaw, defineExpose } from 'vue';
import type { Rule } from 'ant-design-vue/es/form';
import { Pagination, message, Modal } from 'ant-design-vue';
import { UploadOutlined } 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';
import { http } from '/nerv-lib/util/http';
import { Cookies } from '/nerv-lib/util/cookie';
import { tableColumns } from '../config';
import {
energyConsumption,
carbonEmissionFactorLibrary,
uploadPic,
} from '/@/api/carbonEmissionFactorLibrary';
import { dict } from '/@/api';
import { group } from '/@/api/deviceManage';
defineOptions({
energyType: 'EnergyConsumption', // name
components: {
'a-pagination': Pagination,
},
});
const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
orgId.value = result;
const fetch = (api, params = { orgId }, config) => {
return http.post(api, params, config);
};
const selectYear = ref<Dayjs>(dayjs(new Date().getFullYear().toString()));
const total = ref<number>();
const queryParams = ref({
pageNum: 1,
pageSize: 10,
orgId: orgId.value,
year: selectYear.value.format('YYYY'),
});
const isRequired = ref(false);
const visible = ref(false);
const openUpload = ref<boolean>(false);
const data = ref([]);
interface FormState {
energyType: string;
unit: string;
collectionNode: string;
emissionType: string | undefined;
isComputeCarbon: string;
janFlag: string;
febFlag: string;
marFlag: string;
aprFlag: string;
mayFlag: string;
junFlag: string;
julFlag: string;
augFlag: string;
sepFlag: string;
octFlag: string;
novFlag: string;
decFlag: string;
}
const formRef = ref();
const labelCol = { span: 5 };
const wrapperCol = { span: 19 };
const switchLabelCol = { span: 10 };
const switchWrapperCol = { span: 14 };
const formState = ref({
orgId: orgId.value,
});
// form
const rules: Record<string, Rule[]> = {
energyType: [{ required: true, message: '请输入能源种类', trigger: 'change' }],
isComputeCarbon: [{ required: true, message: '请选择是否计算碳排', trigger: 'change' }],
unit: [{ required: true, message: '请选择计量单位', trigger: 'change' }],
};
//
const emissionTypeDic = ref();
//
const measurementUnit = ref([]);
//
const treeData = ref<TreeSelectProps['treeData']>([]);
//
const changeYearData = () => {
queryParams.value.year = selectYear.value;
getTableList();
};
const mainRef = ref();
const year = selectYear.value.format('YYYY');
const tableConfig = ref({
title: '能耗统计',
api: energyConsumption.pageList,
params: queryParams.value,
headerActions: [
{
label: '新增',
name: 'userAdd',
type: 'primary',
handle: () => {
getDictList();
visible.value = true;
},
},
{
label: '导入',
type: 'primary',
name: 'userImport',
handle: () => {},
},
{
label: '导出',
type: 'primary',
name: 'userExports',
},
{
label: '模板下载',
type: 'primary',
},
// {
// label: '',
// type: 'primary',
// handle: () => {
// openUpload.value = true;
// },
// },
{
label: '凭证下载',
type: 'primary',
handle: () => {
fetch(energyConsumption.voucherDownloadList, { bizType: 3 }).then((res) => {
downLoadData.value = res.data;
});
downLoadVisible.value = true;
},
},
],
columns: [
{
title: '序号',
customRender: (text: any) => {
return text.index + 1;
},
},
{
title: '能源种类',
dataIndex: 'energyType',
},
{
title: '计量单位',
className: 'unitName',
dataIndex: 'unitName',
},
{
title: '全年',
dataIndex: 'yearly',
},
{
title: '1月',
dataIndex: 'jan',
// customRender: ({ text }: { text: string }) => {
// return <span :style="{ color: getColor(text) }">{text}</span>;
// }
},
{
title: '2月',
dataIndex: 'feb',
},
{
title: '3月',
dataIndex: 'mar',
},
{
title: '4月',
dataIndex: 'apr',
},
{
title: '5月',
dataIndex: 'may',
},
{
title: '6月',
dataIndex: 'jun',
},
{
title: '7月',
dataIndex: 'jul',
},
{
title: '8月',
dataIndex: 'aug',
},
{
title: '9月',
dataIndex: 'sep',
},
{
title: '10月',
dataIndex: 'oct',
},
{
title: '11月',
dataIndex: 'nov',
},
{
title: '12月',
dataIndex: 'dec',
},
],
columnActions: {
title: '操作',
actions: [
{
label: '编辑',
name: 'userEdit',
handle: (record: any) => {
getDictList();
visible.value = true;
fetch(energyConsumption.findById, { id: record.id }).then((res) => {
if (res.data.emissionType) {
res.data.emissionType = Number(res.data.emissionType);
}
if (res.data.unit) {
let selectDevice = ref([Number(res.data.unit)]);
findParentIds(measurementUnit.value, res.data.unit, selectDevice.value);
res.data.unit = selectDevice;
}
formState.value = res.data;
emissionType.value = res.data.emissionType;
if (formState.value.isComputeCarbon === 0) {
isRequired.value = true;
} else {
isRequired.value = false;
}
});
fetch(uploadPic.select, { bizId: record.id, bizType: 3 }).then((res) => {
fileList.value = res.data.map((item) => ({
uid: item.id.toString(), // 使id
name: item.fileName, //
status: 'done', //
type: 'done',
url: item.filePath, // URLURL
}));
});
},
},
{
label: '删除',
name: 'userDelete',
dynamicParams: { id: 'id' },
confirm: true,
isReload: true,
api: energyConsumption.del,
},
],
},
formConfig: {
schemas: [
{
field: 'year',
label: '年份',
component: 'NsDatePicker',
componentProps: {
picker: 'year',
valueFormat: 'YYYY',
defaultValue: selectYear.value.format('YYYY'),
},
},
],
params: {},
},
rowKey: 'id',
});
const getColor = (value: string | number): string => {
debugger;
if (typeof value === 'string') {
switch (value) {
case 'active':
return 'green';
case 'inactive':
return 'red';
default:
return 'black';
}
} else if (typeof value === 'number') {
return value > 30 ? 'blue' : 'purple'; //
}
return 'black';
};
defineExpose({
mainRef,
});
// id
function findParentIds(tree: any, targetId: number, result: any) {
for (let item of tree) {
if (item.children && item.children.length > 0) {
if (item.children.some((child: any) => child.value === targetId)) {
result.unshift(item.value); // id
findParentIds(tree, item.value, result); // id
break; // 退
}
}
}
}
//
const getTableList = () => {
fetch(energyConsumption.pageList, queryParams.value).then((res) => {
data.value = res.data.records;
});
};
//
const onChange = (pageNumber: number, size: number) => {
queryParams.value.pageNum = pageNumber;
queryParams.value.pageSize = size;
mainRef.value?.nsTableRef.reload();
};
//
const emissionType = ref();
const changeRadio = (e) => {
if (e.target.value === 0) {
isRequired.value = true;
if (emissionType.value) {
formState.value.emissionType = emissionType.value;
}
} else {
isRequired.value = false;
formState.value.emissionType = '';
}
};
//
const onSubmit = () => {
formRef.value
.validate()
.then(() => {
console.log('values', formState, toRaw(formState));
formState.value.year = selectYear.value.format('YYYY');
if (formState.value.unit) {
formState.value.unit = formState.value.unit.join(',').split(',')[1];
}
if (formState.value.id) {
fetch(energyConsumption.update, formState.value).then((res) => {
if (fileList.value.length !== 0) {
const formData = ref(new FormData());
fileList.value.forEach((file) => {
if (file.type !== 'done') {
formData.value.append('files', file.originFileObj);
}
});
formData.value.append('bizType', 3);
formData.value.append('bizId', formState.value.id);
delIds.value.forEach((item) => {
formData.value.append('deleteList', item);
});
fetch(uploadPic.uploadfiles, formData.value)
.then((res) => {
message.success('操作成功!');
visible.value = false;
delIds.value = [];
formState.value = {
orgId: orgId.value,
};
mainRef.value?.nsTableRef.reload();
})
.catch((error) => {
console.log('error', error);
});
} else {
visible.value = false;
delIds.value = [];
formState.value = {
orgId: orgId.value,
};
message.success('操作成功!');
mainRef.value?.nsTableRef.reload();
}
});
} else {
fetch(energyConsumption.creat, formState.value).then((res) => {
if (res.data === '新增数据已存在') {
visible.value = false;
delIds.value = [];
NsMessage.warning(res.data);
} else {
if (fileList.value.length !== 0) {
const formData = ref(new FormData());
fileList.value.forEach((file) => {
formData.value.append('files', file.originFileObj);
});
formData.value.append('bizType', 3);
formData.value.append('bizId', res.data);
fetch(uploadPic.uploadfiles, formData.value)
.then((res) => {
message.success('操作成功!');
visible.value = false;
delIds.value = [];
formState.value = {
orgId: orgId.value,
};
mainRef.value?.nsTableRef.reload();
})
.catch((error) => {
console.log('error', error);
});
} else {
visible.value = false;
delIds.value = [];
formState.value = {
orgId: orgId.value,
};
message.success('操作成功!');
mainRef.value?.nsTableRef.reload();
}
}
});
}
})
.catch((error) => {
console.log('error', error);
});
};
const energyTypeOptions = ref([]);
//
const getDictList = async () => {
//
const options = await dict({ params: { dicKey: 'ENERGY_TYPE' } });
energyTypeOptions.value = options.data.data
console.log(energyTypeOptions);
debugger
//
fetch(energyConsumption.getDicList, { grp: 'EMISSION_TYPE' }).then((res) => {
emissionTypeDic.value = res.data;
});
//
fetch(carbonEmissionFactorLibrary.dictionaryUnitManagement, { grp: 'MEASUREMENT_UNIT' }).then(
(res) => {
measurementUnit.value = res.data;
measurementUnit.value = measurementUnit.value.map((item) => ({
value: item.id,
label: item.cnValue,
children: item.children
? item.children.map((child) => ({
value: child.id,
label: child.cnValue,
}))
: [],
}));
},
);
//
fetch(group.queryDeviceGroupTree, { energyType: 'ELECTRICITY_USAGE', orgId: orgId.value }).then(
(res) => {
treeData.value = res.data;
treeData.value = treeData.value.map((item) => ({
value: item.id,
label: item.pointName,
children: item.children
? item.children.map((child) => ({
value: child.id,
label: child.pointName,
}))
: [],
}));
},
);
};
//
const addNewData = () => {
getDictList();
visible.value = true;
};
//
const editData = (record) => {
getDictList();
visible.value = true;
fetch(energyConsumption.findById, { id: record.id }).then((res) => {
if (res.data.unitName) {
res.data.unitName = res.data.unitName.split(',');
}
formState.value = res.data;
});
};
//
const delData = (record) => {
Modal.confirm({
title: '警告',
content: '确定要删除吗?',
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
fetch(energyConsumption.del, { id: record.id }).then((res) => {
message.success('操作成功!');
mainRef.value?.nsTableRef.reload();
});
},
onCancel() {
console.log('Cancel');
},
});
};
//
const onClose = () => {
visible.value = false;
delIds.value = [];
formState.value = {
orgId: orgId.value,
};
formRef.value.resetFields();
};
//
const uploadVoucher = () => {
openUpload.value = true;
};
//
const handleOk = (e: MouseEvent) => {
console.log(e);
openUpload.value = false;
};
//
const fileList = ref<UploadProps['fileList']>([]);
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
return false;
};
const handleChange = (info: UploadChangeParam) => {
fileList.value = [...info.fileList];
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
message.success(`${info.file.name} 文件上传成功`);
} else if (info.file.status === 'error') {
message.error(`${info.file.name} 文件上传失败`);
}
};
const delIds = ref([]);
const handleFileRemove = (file) => {
delIds.value.push(file.uid);
const newFileList = [];
fileList.value.forEach((item) => {
if (item.uid !== file.uid) {
newFileList.push(item);
}
});
fileList.value = newFileList;
};
//
const closeOpenUpload = () => {
openUpload.value = false;
};
//
const downLoadVisible = ref(false);
const downLoadColumns = [
{
title: '序号',
customRender: (text: any) => {
return text.index + 1;
},
},
{
title: '能源类型',
dataIndex: 'bizName',
},
{
title: '文件名',
dataIndex: 'fileName',
ellipsis: true,
},
{
title: '操作',
key: 'action',
},
];
const downLoadData = ref([]);
const selectedRowKeysSet = ref([]);
const onSelectionChangeSet = (selectedKeys, selectedRows) => {
selectedRowKeysSet.value = selectedKeys;
};
const downLoad = (record) => {
const deleteId = ref(new FormData());
deleteId.value.append('id', record.id);
const config = {
headers: {
responseType: 'blob',
},
};
fetch(uploadPic.download, deleteId.value, config)
.then((res) => {
// URL blob
const url = window.URL.createObjectURL(new Blob([res.data]));
// <a>
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', record.fileName); //
document.body.appendChild(link);
link.click();
// URL
window.URL.revokeObjectURL(url);
})
.catch((error) => {
console.error('下载图片失败:', error);
});
};
const onSubmitDownLoad = () => {
const deleteIds = ref(new FormData());
selectedRowKeysSet.value.forEach((item) => {
deleteIds.value.append('ids', item);
});
fetch(uploadPic.downloadZip, deleteIds.value)
.then((res) => {
// URL blob
const url = window.URL.createObjectURL(new Blob([res.data]));
// <a>
const link = document.createElement('a');
link.href = url;
debugger;
link.setAttribute('download', ''); //
document.body.appendChild(link);
link.click();
// URL
window.URL.revokeObjectURL(url);
onCloseDownLoad();
})
.catch((error) => {
console.error('下载图片失败:', error);
});
};
const onCloseDownLoad = () => {
selectedRowKeysSet.value = [];
downLoadVisible.value = false;
};
</script>
<style scoped lang="less">
:deep(.ant-table-title) {
display: flex;
}
:deep(.ant-table-container) {
padding: 0px 16px;
}
.buttonGroup {
margin-left: 1vw;
width: 30vw;
display: flex;
justify-content: space-around;
}
</style>
<style scoped>
th.column-money,
td.column-money {
text-align: right !important;
}
</style>

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

@ -210,22 +210,33 @@
</template>
</template>
</a-table>
<div class="ns-form-title"><div class="title">凭证上传</div></div>
<div class="ns-form-title" style="display: flex">
<div class="title">凭证上传</div>
</div>
<a-upload
:file-list="fileList"
name="file"
accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf"
accept=".pdf"
@remove="handleFileRemove"
:before-upload="beforeUpload"
@change="handleChange">
<a-button>
<a-button style="margin-left: 6px; color: #4f95ff; border-color: #4f95ff">
<upload-outlined></upload-outlined>
上传
上传凭证
</a-button>
</a-upload>
<div style="display: flex; flex-direction: column">
<div
style="
display: flex;
flex-direction: column;
border-radius: 4px;
background: rgba(250, 250, 250, 1);
color: rgba(153, 153, 153, 1);
padding: 5px;
">
<span>1.仅支持pdf格式文件或文件夹</span>
<span>2.文件名命名规则为能源种类_年份</span>
<span>3.每次上传自动覆盖</span>
</div>
<template #footer>
@ -289,7 +300,7 @@
<script lang="ts" setup>
import { ref, toRaw, defineExpose, createVNode } from 'vue';
import type { Rule } from 'ant-design-vue/es/form';
import { Pagination, message, Modal } from 'ant-design-vue';
import { Pagination, message, Modal, Upload } from 'ant-design-vue';
import { UploadOutlined } from '@ant-design/icons-vue';
import type { TreeSelectProps, UploadChangeParam, UploadProps } from 'ant-design-vue';
import { NsMessage } from '/nerv-lib/component';
@ -1058,19 +1069,29 @@
};
//
const fileList = ref<UploadProps['fileList']>([]);
const isValidFileName = (filename: string): boolean => {
const regex = /^[\s\S]+_\d{4}\.pdf$/;
return regex.test(filename);
};
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const filename = file.name;
if (!isValidFileName(filename)) {
message.error('文件名不符合规则');
return Upload.LIST_IGNORE; //
}
return false;
};
const handleChange = (info: UploadChangeParam) => {
fileList.value = [...info.fileList];
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
message.success(`${info.file.name} 文件上传成功`);
} else if (info.file.status === 'error') {
message.error(`${info.file.name} 文件上传失败`);
// fileList.value = [...info.fileList];
const { fileList: newFileList } = info;
delIds.value.push(info.fileList[0].uid);
// fileList
if (newFileList.length > 1) {
newFileList.shift(); //
}
// fileList
fileList.value = [...newFileList];
};
const delIds = ref([]);
const handleFileRemove = (file) => {
@ -1229,6 +1250,13 @@
.grey-background.ant-switch .ant-switch-handle {
background-color: rgba(238, 238, 238, 1) !important;
}
.ant-switch-checked {
background-color: rgba(57, 215, 187, 1) !important;
}
.grey-background.ant-switch .ant-switch-handle {
background-color: rgba(238, 238, 238, 1) !important;
}
</style>
<style scoped>
th.column-money,

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

@ -0,0 +1,587 @@
<template>
<div class="main">
<div class="left">
<div class="top">
<a-form style="width: 100%; margin: 0 auto">
<div class="ns-form-title"><div class="title">因子分类</div></div>
<div style="padding: 0 16px !important; width: 100%">
<a-row>
<a-col :span="24" style="margin-bottom: 16px">
<a-input-search
v-model:value="searchValue"
placeholder="请输入关键词"
@search="onSearchTreeData" />
</a-col>
</a-row>
</div>
</a-form>
<a-tree
v-if="gData && gData.length > 0"
:expanded-keys="expandedKeys"
:auto-expand-parent="autoExpandParent"
:selectedKeys="selectedKeys"
:tree-data="gData"
show-line
@expand="onExpand"
@select="onSelect"
style="padding: 0 16px !important">
<template #title="data">
<span
v-if="data.energyType && searchValue && data.energyType.indexOf(searchValue) > -1">
{{ data.energyType.substring(0, data.energyType.indexOf(searchValue)) }}
<span style="color: #f50">{{ searchValue }}</span>
{{
data.energyType.substring(data.energyType.indexOf(searchValue) + searchValue.length)
}}
</span>
<span v-else>{{ data.energyType }}</span>
</template>
</a-tree>
</div>
</div>
<div class="right">
<!-- <a-table
:columns="columns"
:data-source="tableData"
bordered
:pagination="false">
<template #bodyCell="{ column, text, record }">
<template v-if="column.key === 'action'">
<span>
<a @click="editData(record)">编辑</a>
<a-divider type="vertical" />
<a @click="delData(record)">删除</a>
</span>
</template>
</template>
<template #title>
<div class="ns-table-title"><span>排放因子库</span></div>
<div class="buttonGroup">
<a-button type="primary" @click="addNewData">新增</a-button>
</div>
</template>
</a-table> -->
<ns-view-list-table
v-bind="tableConfig"
:model="tableData"
ref="mainRef"
:scroll="{ x: 1000 }" />
<a-pagination
:current="queryParams.pageNum"
:total="total"
:page-size="queryParams.pageSize"
style="display: flex; justify-content: center; margin-top: 16px"
:show-size-changer="true"
:show-quick-jumper="true"
@change="onChange" />
<!-- 新增/编辑 -->
<a-drawer
:width="500"
:visible="visible"
:body-style="{ paddingBottom: '80px' }"
:footer-style="{ textAlign: 'right' }"
destroyOnClose
@close="onClose">
<a-form
ref="formRef"
:model="formState"
:rules="rules"
:label-col="labelCol"
:wrapper-col="wrapperCol">
<a-row>
<a-col :span="24">
<a-form-item ref="name" label="日期范围" name="dateRange">
<a-range-picker
v-model:value="formState.dateRange"
picker="month"
valueFormat="YYYY-MM" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item ref="name" label="排放因子" name="emissionFactors">
<ns-input v-model:value="formState.emissionFactors" disabled />
</a-form-item>
</a-col>
</a-row>
<span
key=""
style="font-size: 16px; font-weight: 700; color: rgba(51, 51, 51, 1); text-align: left">
因子列表
</span>
<a-row>
<a-col :span="12">
<a-form-item ref="name">
<ns-input style="margin-top: 5px" v-model:value="selectData" @change="keyChange" />
</a-form-item>
</a-col>
</a-row>
</a-form>
<a-table
:columns="drawerColumns"
:data-source="newTableData"
bordered
rowKey="id"
:rowSelection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectionChange,
type: 'radio',
}"
:pagination="false">
</a-table>
<template #footer>
<a-button style="margin-right: 8px" @click="onClose">取消</a-button>
<a-button type="primary" @click="onSubmit">确定</a-button>
</template>
</a-drawer>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, toRaw, defineExpose } from 'vue';
import type { TreeProps } from 'ant-design-vue';
import { Pagination, Modal } from 'ant-design-vue';
import { columns, drawerColumns } from '../config';
import { http } from '/nerv-lib/util/http';
import {
quickCalculation,
carbonEmissionFactorLibrary,
} from '/@/api/carbonEmissionFactorLibrary';
import { or } from '@vueuse/core';
defineOptions({
energyType: 'quickCalculation', // name
components: {
'a-pagination': Pagination,
},
});
const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
orgId.value = result;
const fetch = (api, params = { orgId }) => {
return http.post(api, params);
};
const mainRef = ref();
//
const x = 3;
const y = 2;
const z = 1;
const genData: TreeProps['treeData'] = [];
const generateData = (_level: number, _preKey?: string, _tns?: TreeProps['treeData']) => {
const preKey = _preKey || '0';
const tns = _tns || genData;
const children = [];
for (let i = 0; i < x; i++) {
const key = `${preKey}-${i}`;
tns.push({ title: key, key });
if (i < y) {
children.push(key);
}
}
if (_level < 0) {
return tns;
}
const level = _level - 1;
children.forEach((key, index) => {
tns[index].children = [];
return generateData(level, key, tns[index].children);
});
};
generateData(z);
const dataList: TreeProps['treeData'] = [];
const generateList = (data: TreeProps['treeData']) => {
for (let i = 0; i < data.length; i++) {
const node = data[i];
const key = node.key;
dataList.push({ key, title: key });
if (node.children) {
generateList(node.children);
}
}
};
generateList(genData);
const getParentKey = (
key: string | number,
tree: TreeProps['treeData'],
): string | number | undefined => {
let parentKey;
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
if (node.children) {
if (node.children.some((item) => item.key === key)) {
parentKey = node.key;
} else if (getParentKey(key, node.children)) {
parentKey = getParentKey(key, node.children);
}
}
}
return parentKey;
};
const expandedKeys = ref<(string | number)[]>(['0-0']);
const selectedKeys = ref<string[]>(['0-0-0']);
const searchValue = ref<string>('');
const autoExpandParent = ref<boolean>(true);
const gData = ref<TreeProps['treeData']>(genData);
const onExpand = (keys: string[]) => {
expandedKeys.value = keys;
autoExpandParent.value = false;
};
//
const energyType = ref();
const onSelect = (selectedKey: string[], info: any) => {
selectedKeys.value = selectedKey;
if (info.selected) {
energyType.value = info.node.id;
statsId.value = info.node.id;
mainRef.value?.nsTableRef.reload();
}
};
watch(searchValue, (value) => {
const expanded = dataList
.map((item: TreeProps['treeData'][number]) => {
if (item.title.indexOf(value) > -1) {
return getParentKey(item.key, gData.value);
}
return null;
})
.filter((item, i, self) => item && self.indexOf(item) === i);
expandedKeys.value = expanded;
searchValue.value = value;
autoExpandParent.value = true;
});
//
const onSearchTreeData = () => {};
const statsId = ref();
//
const getTreeData = () => {
fetch(quickCalculation.carbonQuickTree, { orgId: orgId.value }).then((res) => {
gData.value = res.data;
energyType.value = gData.value[0].children[0].id;
statsId.value = gData.value[0].children[0].id;
mainRef.value?.nsTableRef.reload();
});
};
getTreeData();
//
const total = ref<number>();
const queryParams = ref({
pageNum: 1,
pageSize: 10,
orgId: orgId.value,
});
const tableData = ref([]);
const emissionSources = ref();
const tableConfig = ref({
title: '排放因子库',
api: quickCalculation.queryCarbonEmissionPage,
params: {
orgId,
energyType,
},
headerActions: [
{
label: '新增',
name: 'userAdd',
type: 'primary',
handle: () => {
visible.value = true;
// getNewTable();
},
},
],
columns: [
{
title: '序号',
customRender: (text: any) => {
return text.index + 1;
},
},
{
title: '因子值',
dataIndex: 'emissionFactors',
},
{
title: '计量单位',
className: 'carbonEmissionSuffix',
dataIndex: 'carbonEmissionSuffix',
},
{
title: '更新时间',
className: 'updateTime',
dataIndex: 'updateTime',
ellipsis: true,
},
{
title: '启用时间',
className: 'startTime',
dataIndex: 'startTime',
},
{
title: '结束时间',
className: 'endTime',
dataIndex: 'endTime',
},
{
title: '数据来源',
className: 'dataSources',
dataIndex: 'dataSources',
},
],
columnActions: {
title: '操作',
actions: [
{
label: '编辑',
name: 'userEdit',
handle: (record: any) => {
selectedRowKeys.value = [record.factorId];
formState.value.id = record.id;
formState.value.emissionFactors = record.emissionFactors;
formState.value.dateRange = [record.startTime, record.endTime];
formState.value.factorId = record.factorId;
visible.value = true;
emissionSources.value = record.emissionSources;
queryData.value.emissionSources = emissionSources.value;
getNewTable();
},
},
{
label: '删除',
name: 'userDelete',
dynamicParams: { id: 'id' },
confirm: true,
isReload: true,
api: quickCalculation.del,
},
],
},
rowKey: 'id',
});
defineExpose({
getTreeData,
});
//
const getTableList = () => {
fetch(quickCalculation.queryCarbonEmissionPage, queryParams.value).then((res) => {
tableData.value = res.data.records;
total.value = res.data.total;
});
};
//
const onChange = (pageNumber: number, size: number) => {
queryParams.value.pageNum = pageNumber;
queryParams.value.pageSize = size;
mainRef.value?.nsTableRef.reload();
};
// /
const formRef = ref();
const labelCol = { span: 6 };
const wrapperCol = { span: 18 };
const formState = ref({
orgId: orgId.value,
});
const visible = ref(false);
// form
const rules: Record<string, Rule[]> = {
dateRange: [{ required: true, message: '请选择日期范围', trigger: 'change' }],
emissionFactors: [{ required: true, message: '请输入能源种类', trigger: 'change' }],
};
//
const addNewData = () => {
visible.value = true;
// getNewTable();
};
//
const selectedRowKeys = ref([]);
const onSelectionChange = (selectedKeys, selectedRows) => {
selectedRowKeys.value = selectedKeys;
formState.value.emissionFactors = selectedRows[0].emissionFactors;
formState.value.factorId = selectedRows[0].id;
};
const queryData = ref({
orgId: orgId.value,
pageNum: 1,
pageSize: 999,
});
const newTableData = ref([]);
const getNewTable = () => {
fetch(carbonEmissionFactorLibrary.getTableList, queryData.value).then((res) => {
newTableData.value = res.data.records;
});
};
const selectData = ref();
const keyChange = () => {
if (selectData.value === '') {
queryData.value.emissionSources = emissionSources.value;
} else {
queryData.value.emissionSources = selectData.value;
}
getNewTable();
};
//
const editData = (record) => {
selectedRowKeys.value = [record.factorId];
formState.value.id = record.id;
formState.value.emissionFactors = record.emissionFactors;
formState.value.dateRange = [record.startTime, record.endTime];
formState.value.factorId = record.factorId;
visible.value = true;
getNewTable();
};
//
const onSubmit = () => {
formRef.value
.validate()
.then(() => {
formState.value.statsId = statsId.value;
formState.value.startTime = formState.value.dateRange[0];
formState.value.endTime = formState.value.dateRange[1];
console.log('values', formState, toRaw(formState));
if (formState.value.id) {
fetch(quickCalculation.update, formState.value).then((res) => {
visible.value = false;
selectedRowKeys.value = [];
formState.value = {};
formRef.value.resetFields();
mainRef.value?.nsTableRef.reload();
});
} else {
fetch(quickCalculation.creat, formState.value).then((res) => {
visible.value = false;
selectedRowKeys.value = [];
formState.value = {};
formRef.value.resetFields();
mainRef.value?.nsTableRef.reload();
});
}
})
.catch((error) => {
console.log('error', error);
});
};
//
const delData = (record) => {
Modal.confirm({
title: '警告',
content: '确定要删除吗?',
okText: '确定',
okType: 'primary',
cancelText: '取消',
onOk() {
fetch(quickCalculation.del, { id: record.id }).then((res) => {
message.success('操作成功!');
getTableList();
});
},
onCancel() {
console.log('Cancel');
},
});
};
//
const onClose = () => {
visible.value = false;
selectedRowKeys.value = [];
formState.value = {};
formRef.value.resetFields();
};
</script>
<style lang="less" scoped>
.main {
background-color: @ns-content-bg;
display: flex;
height: 100%;
}
.left {
width: 300px;
margin-right: @ns-gap;
min-width: fit-content;
> div {
background-color: @white;
flex: 1;
}
display: flex;
flex-direction: column;
.top {
position: relative;
.addTreeNode {
width: 100%;
padding: 16px;
position: absolute;
bottom: 0;
}
}
}
.right {
flex: 1;
min-width: 0;
height: 100%;
background: #ffffff;
}
:deep(.ant-table-container) {
padding: 0px 16px;
}
:deep(.ns-table-main) {
margin-top: unset !important;
}
.top {
overflow: auto;
}
.ns-form-title {
font-weight: bold;
user-select: text;
padding: 16px;
margin-bottom: 16px;
padding-bottom: 10px;
border-bottom: 1px solid #e9e9e9;
}
.title {
text-align: left;
height: 32px;
line-height: 32px;
font-weight: bold;
user-select: text;
position: relative;
padding-left: 9px;
}
.title::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
height: 13px;
width: 3px;
border-radius: 1px;
background-color: #2778ff;
}
:deep(.ant-table-title) {
display: flex;
height: 100%;
align-items: center;
}
.ns-table-title {
font-weight: bold;
}
.buttonGroup {
margin-left: 1vw;
width: 5vw;
display: flex;
justify-content: space-around;
}
</style>
<style scoped>
th.column-money,
td.column-money {
text-align: right !important;
}
</style>

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

@ -66,14 +66,14 @@
:model="tableData"
ref="mainRef"
:scroll="{ x: 1000 }" />
<a-pagination
<!-- <a-pagination
:current="queryParams.pageNum"
:total="total"
:page-size="queryParams.pageSize"
style="display: flex; justify-content: center; margin-top: 16px"
:show-size-changer="true"
:show-quick-jumper="true"
@change="onChange" />
@change="onChange" /> -->
<!-- 新增/编辑 -->
<a-drawer
:width="500"
@ -499,14 +499,19 @@
background-color: @ns-content-bg;
display: flex;
height: 100%;
padding: 16px;
}
.left {
width: 300px;
margin-right: @ns-gap;
min-width: fit-content;
border-radius: 8px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 2px 20px rgb(69 123 234 / 20%);
> div {
background-color: @white;
flex: 1;
border-radius: 8px;
}
display: flex;
@ -526,6 +531,11 @@
min-width: 0;
height: 100%;
background: #ffffff;
border-radius: 8px !important;
box-shadow: 0px 2px 20px rgb(69 123 234 / 20%);
:deep(.ns-table-main) {
border-radius: 8px !important;
}
}
:deep(.ant-table-container) {
padding: 0px 16px;

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

@ -248,7 +248,7 @@
</a-drawer>
<!-- 点击编辑弹出框 -->
<a-drawer
:width="700"
:width="500"
:visible="editData"
:body-style="{ paddingBottom: '80px' }"
:footer-style="{ textAlign: 'right' }"
@ -260,7 +260,7 @@
:label-col="labelCol"
:wrapper-col="wrapperCol">
<a-row>
<a-col :span="12">
<a-col :span="24">
<a-form-item ref="name" label="数据来源" name="dataSources">
<a-select
ref="select"
@ -272,14 +272,14 @@
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-col :span="24">
<a-form-item ref="name" label="消耗量" name="consumption">
<ns-input v-model:value="editFormState.consumption" :disabled="canEdit" />
</a-form-item>
</a-col>
</a-row>
<a-row v-if="automatic">
<a-col :span="12">
<a-col :span="24">
<a-form-item ref="name" label="采集节点" name="collectionNode">
<a-tree-select
v-model:value="editFormState.collectionNode"
@ -291,12 +291,12 @@
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-col :span="24">
<a-form-item ref="name" label="因子值" name="factorId">
<ns-input v-model:value="editFormState.factorId" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-col :span="24">
<a-form-item ref="name" label="关键字" name="emissionFactors">
<a-input-search
v-model:value="editFormState.emissionFactors"
@ -325,24 +325,14 @@
:current="queryData.pageNum"
:total="total"
:page-size="queryData.pageSize"
:pageSizeOptions="['5']"
style="display: flex; justify-content: center; margin-top: 16px"
:show-size-changer="true"
:show-quick-jumper="true"
@change="onChange" />
<!-- <a-upload
v-model:file-list="fileList"
name="file"
accept=".jpg,.jpeg,.png,.gif,.bmp,.pdf"
@remove="handleFileRemove"
:before-upload="beforeUpload"
@change="handleChange">
<a-button>
<upload-outlined></upload-outlined>
点击上传凭证
</a-button>
</a-upload> -->
<a-upload-dragger
v-model:fileList="fileList"
accept=".pdf"
name="file"
@remove="handleFileRemove"
:before-upload="beforeUpload"
@ -365,7 +355,7 @@
<script lang="ts" setup>
import { ref, watch, toRaw, defineEmits, nextTick } from 'vue';
import { http } from '/nerv-lib/util/http';
import { Pagination, Modal, message } from 'ant-design-vue';
import { Pagination, Modal, message, Upload } from 'ant-design-vue';
import type { TreeProps, UploadChangeParam } from 'ant-design-vue';
import {
EditOutlined,
@ -935,7 +925,7 @@
const queryData = ref({
orgId: orgId.value,
pageNum: 1,
pageSize: 10,
pageSize: 5,
});
const edit = (record) => {
getDictList();
@ -975,6 +965,8 @@
if (value === '3') {
canEdit.value = true;
automatic.value = true;
} else {
automatic.value = false;
}
};
//
@ -997,24 +989,31 @@
},
);
};
const selectNode = (value) => {
debugger;
};
//
const fileList = ref<UploadProps['fileList']>([]);
const isValidFileName = (filename: string): boolean => {
const regex = /^[\s\S]+_\d{4}\.pdf$/;
return regex.test(filename);
};
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
const filename = file.name;
if (!isValidFileName(filename)) {
message.error('文件名不符合规则');
return Upload.LIST_IGNORE; //
}
return false;
};
const handleChange = (info: UploadChangeParam) => {
fileList.value = [...info.fileList];
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
message.success(`${info.file.name} 文件上传成功`);
} else if (info.file.status === 'error') {
message.error(`${info.file.name} 文件上传失败`);
// fileList.value = [...info.fileList];
const { fileList: newFileList } = info;
delIds.value.push(info.fileList[0].uid);
// fileList
if (newFileList.length > 1) {
newFileList.shift(); //
}
// fileList
fileList.value = [...newFileList];
};
const delIds = ref([]);
const handleFileRemove = (file) => {

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

@ -68,8 +68,8 @@
const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
orgId.value = result;
const fetch = (api, params = { orgId }) => {
return http.post(api, params);
const fetch = (api, params = { orgId }, config) => {
return http.post(api, params, config);
};
//
const isMainPage = ref(true);
@ -205,7 +205,30 @@
{
label: '下载',
name: 'download',
handle: (record: any) => {},
handle: (record: any) => {
const deleteId = ref(new FormData());
deleteId.value.append('id', record.id);
const config = {
responseType: 'blob',
};
fetch(carbonInventoryCheck.downloadZip, deleteId.value, config)
.then((res) => {
// URL blob
const url = window.URL.createObjectURL(new Blob([res]));
// <a>
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', '碳盘查凭证.zip'); //
document.body.appendChild(link);
link.click();
// URL
window.URL.revokeObjectURL(url);
})
.catch((error) => {
console.error('下载图片失败:', error);
});
},
},
{
label: '删除',

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

@ -100,8 +100,20 @@
const drawEcharts = () => {
data.value.forEach((item, index) => {
const chart = echarts.init(document.getElementById(`ydlChart_${index}`)!);
const handred = 100;
const bottomColor = [
'rgba(219, 222, 232, 1)',
'rgba(221, 226, 223, 1)',
'rgba(233, 228, 219, 1)',
'rgba(221, 216, 235, 1)',
'rgba(240, 228, 228, 1)',
];
const mianColor = [
'rgba(24, 106, 255, 1)',
'rgba(58, 194, 127, 1)',
'rgba(249, 183, 50, 1)',
'rgba(120, 76, 212, 1)',
'rgba(255, 55, 103, 1)',
];
let point = parseInt(item.budgetAchievement.replace('%', ''));
const option = {
backgroundColor: 'transparent',
@ -127,55 +139,61 @@
},
},
],
// tooltip: {
// formatter: function (params) {
// return params.name + '' + params.percent + ' %';
// },
// },
series: [
{
name: 'circle',
type: 'pie',
clockWise: true,
radius: ['40%', '50%'],
center: ['50%', '40%'],
itemStyle: {
label: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
show: false,
},
},
hoverAnimation: false,
data: [
{
name: '',
value: 100,
itemStyle: {
normal: {
color: bottomColor[index],
},
},
},
],
zlevel: 1,
},
{
name: 'main',
type: 'pie',
radius: ['38%', '55%'],
center: ['50%', '40%'],
data: [
{
value: point,
name: '占比',
label: {
show: true,
position: 'center',
fontSize: 40,
},
labelLine: { show: false },
itemStyle: {
normal: {
color: '#4FADFD',
label: {
show: false,
},
labelLine: {
show: false,
},
color: mianColor[index],
shadowBlur: 10,
shadowColor: mianColor[index],
},
},
},
{
name: '剩余',
value: handred - point,
value: 100 - point,
itemStyle: {
normal: {
color: '#E1E8EE',
color: 'transparent',
},
},
},
],
zlevel: 2,
},
],
};

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

@ -459,7 +459,26 @@
barWidth: 18,
itemStyle: {
normal: {
color: '#6395f9',
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: 'rgba(45, 178, 246, 1)', // 0%
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0)', // 100%
},
],
false,
),
borderWidth: 2,
borderColor: 'rgba(45, 178, 246, 1)',
padding: 0,
},
},
data: lastYearActualUsageList.value,
@ -469,9 +488,26 @@
type: 'bar',
barWidth: 18,
itemStyle: {
normal: {
color: '#62daab',
},
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: 'rgba(28, 184, 142, 1)', // 0%
},
{
offset: 1,
color: 'rgba(255, 255, 255, 0)', // 100%
},
],
false,
),
borderWidth: 2,
borderColor: 'rgba(28, 184, 142, 1)',
padding: 0,
},
data: actualUsageList.value,
},
@ -481,7 +517,7 @@
smooth: true, // 线
symbol: 'none', //
lineStyle: {
color: '#f4664a',
color: 'rgba(255, 188, 70, 1)',
width: 2,
},
data: budgetList.value,
@ -492,7 +528,7 @@
smooth: true, // 线
symbol: 'none', //
lineStyle: {
color: '#f4664a',
color: 'rgba(195, 142, 255, 1)',
width: 2,
},
data: referenceValueList.value,
@ -559,6 +595,7 @@
.contant {
width: 100%;
height: calc(100% - 5vh);
overflow: auto;
.chartsPart {
width: 100%;
height: 63%;

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

@ -260,25 +260,45 @@
series: [
{
name: '实际用量',
type: 'bar',
barWidth: 18,
type: 'pictorialBar',
symbol: 'rect',
itemStyle: {
color: '#6395f9',
},
symbolRepeat: true,
symbolSize: [14, 4],
symbolMargin: 0.5,
symbolPosition: 'start',
z: -20,
data: actualUsage.value,
label: {
normal: {
color: '#6395f9',
show: false,
position: 'top',
verticalAlign: 'top',
},
},
data: actualUsage.value,
},
{
name: '预算量',
type: 'bar',
barWidth: 18,
type: 'pictorialBar',
symbol: 'rect',
itemStyle: {
color: '#62daab',
},
symbolRepeat: true,
symbolSize: [14, 4],
symbolMargin: 0.5,
symbolPosition: 'start',
z: -20,
data: budget.value,
label: {
normal: {
color: '#62daab',
show: false,
position: 'top',
verticalAlign: 'top',
},
},
data: budget.value,
},
{
name: '基准线',

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

@ -1,18 +1,25 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<a-row type="flex" style="display: flex; position: relative">
<a-row type="flex" style="display: flex; position: relative; background: #f1f2f6">
<a-col :span="4">
<div style="padding: 0 20px; width: 100%; height: 100%">
<div style="width: 100%; height: 100%">
<tree ref="treeRef" />
</div>
</a-col>
<a-col :span="20">
<div style="width: 100%; height: 100%">
<div
style="
width: 98%;
height: 100%;
border-radius: 10px;
background: #ffffff;
margin-left: 1.5%;
">
<div class="ns-right-title">
<span><ns-icon name="title" size="11" style="margin-right: 3px" />历史数据</span>
<div class="button">
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="downloadChart" />
<ns-icon :name="iconName" size="18" style="margin-right: 10px" @click="change" />
<ns-icon :name="iconName" size="15" style="margin-right: 10px" @click="change" />
</div>
</div>
<graph ref="graphRef" v-if="isGraph" />

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

@ -33,7 +33,7 @@
placeholder="请选择点位"
:style="{
top: '50px',
left: `${divWidth + 40}px`,
left: `${divWidth + 55}px`,
zIndex: 9,
position: 'absolute',
width: `${divWidth}px`,
@ -44,7 +44,7 @@
placeholder="请选择频率"
:style="{
top: '50px',
left: `${divWidth * 2 + 50}px`,
left: `${divWidth * 2 + 65}px`,
zIndex: 9,
position: 'absolute',
width: `${divWidth}px`,
@ -58,7 +58,7 @@
@calendarChange="onCalendarChange"
:style="{
top: '50px',
left: `${divWidth * 3 + 60}px`,
left: `${divWidth * 3 + 75}px`,
zIndex: 9,
position: 'absolute',
width: `${divWidth}px`,
@ -68,7 +68,7 @@
type="primary"
:style="{
top: '50px',
left: `${divWidth * 4 + 70}px`,
left: `${divWidth * 4 + 85}px`,
zIndex: 9,
position: 'absolute',
}"
@ -212,6 +212,7 @@
.post(deviceMonitor.getDevicePointToMonitor, {
deviceIds: checkedKeys.value,
orgId: orgId.value,
type: 0,
})
.then((res) => {
if (res.retcode == 0) {
@ -390,6 +391,10 @@
}
.parent-container {
// position: relative;
border-radius: 10px;
background: #ffffff;
padding-left: 10px;
padding-right: 10px;
height: 100%;
}

85
hx-ai-intelligent/src/view/monitor/energyMonitor/analysisGraph/index.vue

@ -1,9 +1,10 @@
<template>
<a-row type="flex" style="height: 90%">
<a-row type="flex" style="height: 100%">
<a-col :span="8" style="height: 100%">
<div
style="
box-shadow: 0 0 0 2px rgba(218, 218, 218, 0.5); /* 灰色阴影 */
box-shadow: 0 0 15px rgba(69, 123, 234, 0.2);
border-radius: 10px;
width: 98%;
height: 96%;
margin: 2%;
@ -32,7 +33,8 @@
style="
width: 98%;
height: 38%;
box-shadow: 0 0 0 2px rgba(218, 218, 218, 0.5);
box-shadow: 0 0 15px rgba(69, 123, 234, 0.2);
border-radius: 10px;
margin: 1%;
"></div>
<div
@ -40,7 +42,8 @@
style="
width: 98%;
height: 57%;
box-shadow: 0 0 0 2px rgba(218, 218, 218, 0.5);
box-shadow: 0 0 15px rgba(69, 123, 234, 0.2);
border-radius: 10px;
margin: 1%;
"></div>
</a-col>
@ -242,7 +245,9 @@
var seriesdata = [];
var dateX = [];
// var legendList: string | any[] = [];
let sum = 0;
for (let i = 0; i < data.value.length; i++) {
sum += data.value[i].value;
dateX.push(data.value[i].name);
seriesdata.push({
@ -262,7 +267,7 @@
clockwise: '10',
// hoverAnimation: true,
//
radius: ['70%', '90%'],
radius: ['60%', '80%'],
center: ['30%', '50%'], //
// 线
labelLine: {
@ -294,6 +299,29 @@
tooltip: {
trigger: 'item',
},
graphic: [
{
type: 'text',
left: '28%',
top: '33%',
style: {
text: '总计',
fill: '#000',
fontSize: 14,
},
},
{
type: 'text',
left: sum > 100 ? '24%' : '30%',
top: '50%',
style: {
text: sum,
fill: '#000',
fontSize: 30,
fontWeight: 700,
},
},
],
//
legend: {
@ -334,7 +362,9 @@
chartRight1.on('click', function (params) {
//
console.log(params.name + ' 被点击了');
drawRight2(params);
if (params.name && params.name != '') {
drawRight2(params);
}
});
}
};
@ -360,18 +390,18 @@
});
const option = {
//
legend: {
data: [
{ name: '对比值', icon: 'rect' }, // 使
{
name: '参考线',
icon: 'path://M234.666667 490.666667h-153.6a25.6 25.6 0 1 0 0 51.2h153.6a25.6 25.6 0 1 0 0-51.2zM473.6 490.666667h-153.6a25.6 25.6 0 1 0 0 51.2h153.6a25.6 25.6 0 1 0 0-51.2zM934.4 490.666667h-136.533333a25.6 25.6 0 1 0 0 51.2h136.533333a25.6 25.6 0 1 0 0-51.2zM712.533333 490.666667h-153.6a25.6 25.6 0 1 0 0 51.2h153.6a25.6 25.6 0 1 0 0-51.2z',
}, // 线使线
],
orient: 'horizontal',
bottom: 10,
left: 60,
},
// legend: {
// data: [
// { name: '', icon: 'rect' }, // 使
// {
// name: '线',
// icon: 'path://M234.666667 490.666667h-153.6a25.6 25.6 0 1 0 0 51.2h153.6a25.6 25.6 0 1 0 0-51.2zM473.6 490.666667h-153.6a25.6 25.6 0 1 0 0 51.2h153.6a25.6 25.6 0 1 0 0-51.2zM934.4 490.666667h-136.533333a25.6 25.6 0 1 0 0 51.2h136.533333a25.6 25.6 0 1 0 0-51.2zM712.533333 490.666667h-153.6a25.6 25.6 0 1 0 0 51.2h153.6a25.6 25.6 0 1 0 0-51.2z',
// }, // 线使线
// ],
// orient: 'horizontal',
// bottom: 10,
// left: 60,
// },
tooltip: {
trigger: 'axis',
axisPointer: {
@ -409,7 +439,7 @@
zoomLock: true,
startValue: 0, //
endValue: 5,
bottom: '0%',
bottom: 20,
height: 10,
showDetail: false,
},
@ -526,4 +556,19 @@
},
});
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
::v-deep .ant-radio-button-wrapper-checked {
border: none !important; /* 移除选中时的边框 */
box-shadow: none !important; /* 移除选中时的阴影 */
background-color: #2778ff !important; /* 使用 !important 强制覆盖背景颜色 */
color: #ffffff !important; /* 使用 !important 强制覆盖文字颜色 */
}
/* 未选中时的颜色 */
::v-deep .ant-radio-button-wrapper {
// border: none !important; /* */
box-shadow: none !important; /* 去掉阴影(如果有的话) */
background-color: #f9f9f9;
color: #2778ff;
border-color: #2778ff;
}
</style>

21
hx-ai-intelligent/src/view/monitor/energyMonitor/graphGraph/index.vue

@ -1,5 +1,5 @@
<template>
<div ref="graphGraphchart" style="width: 100%; height: 80%"></div>
<div ref="graphGraphchart" style="width: 100%; height: 100%"></div>
</template>
<script lang="ts">
@ -77,6 +77,10 @@
legendList.push(data.value[i].name);
}
const option = {
grid: {
top: 40,
bottom: 50,
},
legend: {
data: legendList,
orient: 'horizontal',
@ -107,6 +111,21 @@
type: 'value',
},
series: seriesList,
// 使 ECharts graphic
graphic:
data.value.length === 0
? {
type: 'text',
left: 'center',
top: 'middle',
style: {
text: '无数据',
fontSize: 20,
fontWeight: 'bold',
fill: '#999',
},
}
: null,
};
chartInstance = echarts.init(graphGraphchart.value);

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

@ -1,13 +1,20 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<a-row type="flex" style="height: 92%; display: flex; position: relative">
<a-row type="flex" style="height: 100%; display: flex; position: relative; background: #f1f2f6">
<a-col :span="4">
<div style="padding: 0 20px; width: 100%; height: 100%">
<div style="width: 100%; height: 100%">
<tree ref="treeRef" />
</div>
</a-col>
<a-col :span="20">
<div style="width: 100%; height: 100%">
<div
style="
width: 98%;
height: 100%;
border-radius: 10px;
background: #ffffff;
margin-left: 1.5%;
">
<div style="height: 22%">
<div class="ns-right-title">
<a-tabs
@ -16,6 +23,9 @@
@change="changeActive">
<a-tab-pane key="1" tab="图表" />
<a-tab-pane key="2" tab="分析" />
<!-- <template #renderTabBar="{ DefaultTabBar, ...props }">
<component :is="DefaultTabBar" v-bind="props" :style="{ opacity: 0.5 }" />
</template> -->
</a-tabs>
<div class="button">
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="downloadChart" />
@ -27,11 +37,11 @@
>
</div>
<div v-if="activeKey == '1'" style="height: 82%; width: 100%">
<div v-if="activeKey == '1'" style="height: 72%; width: 100%">
<graph-graph ref="graphRef" v-if="isGraph" />
<environment-table ref="tableRef" v-else style="width: 100%" />
</div>
<div v-else style="height: 82%; width: 100%">
<div v-else style="height: 78%; width: 100%">
<analysis-graph ref="analysisGraphRef" v-if="isGraph" style="height: 100%; width: 100%" />
<analysis-table ref="analysisTableRef" v-else />
</div>
@ -110,4 +120,22 @@
display: inline-block;
padding-right: 10px;
}
::v-deep .ant-tabs-tab {
font-weight: bold; /* 选中标签的加粗 */
// font-size: 16px;
// letter-spacing: 1.33px;
color: #666666 !important;
}
::v-deep .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
// background-color: #f0f0f0; /* */
// color: #1890ff; /* */
// border-radius: 5px; /* */
// font-weight: bold; /* */
color: #000000 !important;
}
::v-deep .ant-tabs-tab:hover {
color: #000000; /* 悬停时的文字颜色 */
}
</style>

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

@ -11,10 +11,17 @@
v-model:value="mode"
@change="changeMode"
style="padding-bottom: 10px; width: 100%">
<a-radio-button value="0" style="width: 50%; text-align: center" :disabled="shebei">
<a-radio-button
value="0"
style="width: 47.5%; margin-right: 2.5%; text-align: center; border-radius: 4px"
:disabled="shebei">
设备
</a-radio-button>
<a-radio-button value="1" style="width: 50%; text-align: center">节点</a-radio-button>
<a-radio-button
value="1"
style="width: 47.5%; margin-left: 2.5%; text-align: center; border-radius: 4px"
>节点</a-radio-button
>
</a-radio-group>
<a-input
v-model:value="deviceName"
@ -55,7 +62,7 @@
placeholder="请选择能耗类型"
:style="{
top: '100px',
left: `${divWidth + 40}px`,
left: `${divWidth + 55}px`,
zIndex: 9,
position: 'absolute',
width: `${divWidth}px`,
@ -67,7 +74,7 @@
placeholder="请选择日期类型"
:style="{
top: '100px',
left: `${divWidth * 2 + 50}px`,
left: `${divWidth * 2 + 65}px`,
zIndex: 9,
position: 'absolute',
width: `${divWidth}px`,
@ -77,7 +84,7 @@
<a-range-picker
:style="{
top: '100px',
left: `${divWidth * 3 + 60}px`,
left: `${divWidth * 3 + 75}px`,
zIndex: 9,
position: 'absolute',
width: `${divWidth}px`,
@ -90,7 +97,7 @@
<a-date-picker
:style="{
top: '100px',
left: `${divWidth * 3 + 60}px`,
left: `${divWidth * 3 + 75}px`,
zIndex: 9,
position: 'absolute',
width: `${divWidth}px`,
@ -103,7 +110,7 @@
type="primary"
:style="{
top: '100px',
left: `${divWidth * 4 + 70}px`,
left: `${divWidth * 4 + 85}px`,
zIndex: 9,
position: 'absolute',
}"
@ -601,6 +608,10 @@
}
.parent-container {
// position: relative;
border-radius: 10px;
background: #ffffff;
padding-left: 10px;
padding-right: 10px;
height: 100%;
}
@ -610,4 +621,22 @@
// width: 100%;
// margin-bottom: 10px;
// }
/* 选中状态的背景色和文字颜色 */
::v-deep .ant-radio-button-wrapper-checked {
border: none !important; /* 移除选中时的边框 */
box-shadow: none !important; /* 移除选中时的阴影 */
background-color: #ecf3ff !important; /* 使用 !important 强制覆盖背景颜色 */
color: #4388fb !important; /* 使用 !important 强制覆盖文字颜色 */
}
/* 未选中时的颜色 */
::v-deep .ant-radio-button-wrapper {
border: none !important; /* 移除所有边框 */
box-shadow: none !important; /* 去掉阴影(如果有的话) */
background-color: #f9f9f9;
// color: #333333;
}
.ant-radio-button-wrapper:not(:first-child)::before {
width: 0;
}
</style>

225
hx-ai-intelligent/src/view/monitor/environmentMonitor/aggregateData/index.vue

File diff suppressed because one or more lines are too long

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

@ -1,19 +1,22 @@
<!-- eslint-disable vue/v-on-event-hyphenation -->
<template>
<!-- <a-spin :spinning="loading"> -->
<div style="background: #ffffff; height: 95%">
<div style="background: #ffffff; height: 95%; position: relative">
<a-spin :spinning="loading">
<a-table
:columns="tableColumns"
:data-source="pageData"
bordered
:pagination="false"
style="height: 75%"
:scroll="{ x: 100, y: 450 }">
<template #title>
<div
style="display: flex; align-items: center; justify-content: space-between; width: 100%">
<div style="display: flex; align-items: center; width: 85%">
<div style="width: 10%">数据报表</div>
<div style="width: 10%"
><ns-icon name="title" size="11" style="margin-right: 3px" />数据报表</div
>
<a-select
v-model:value="frequencyValue"
@ -39,15 +42,24 @@
</div>
</template>
</a-table>
<a-pagination
:current="queryParams.pageNum"
:total="total"
:page-size="queryParams.pageSize"
style="display: flex; justify-content: center; margin-top: 16px"
:show-size-changer="true"
:show-quick-jumper="true"
@change="onChange" />
</a-spin>
<a-pagination
:current="queryParams.pageNum"
:total="total"
:show-total="(total, range) => ` 共 ${total} 条`"
:page-size="queryParams.pageSize"
style="
display: flex;
position: absolute;
bottom: 20px;
right: 30px;
justify-content: right;
margin-top: 16px;
margin-right: 30px;
"
:show-size-changer="true"
:show-quick-jumper="true"
@change="onChange" />
</div>
<!-- </a-spin> -->
</template>

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

@ -1,18 +1,21 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<div style="background: #ffffff; height: 95%">
<a-spin :spinning="loading">
<div style="background: #ffffff; height: 95%; position: relative">
<a-spin :spinning="loading" style="height: 100%">
<a-table
:columns="tableColumns"
:data-source="pageData"
bordered
:pagination="false"
:scroll="{ x: 100 }">
:height="500"
:scroll="{ x: 3000, y: 440 }">
<template #title>
<div
style="display: flex; align-items: center; justify-content: space-between; width: 100%">
<div style="display: flex; align-items: center; width: 85%">
<div style="width: 10%">数据报表</div>
<div style="width: 10%"
><ns-icon name="title" size="11" style="margin-right: 3px" />数据报表</div
>
<a-select
v-model:value="typeValue"
placeholder="请选择环境参数"
@ -20,7 +23,7 @@
:options="typeList" />
<a-tree-select
v-model:value="quyuvalue"
style="width: 17%; margin-left: 10px"
style="width: 22%; margin-left: 10px"
:tree-data="treeData2"
:field-names="{
children: 'childList',
@ -54,13 +57,22 @@
</div>
</template>
</a-table>
<a-pagination
:total="total"
show-size-changer
show-quick-jumper
@change="onChange"
style="display: flex; justify-content: center; margin-top: 10px" />
</a-spin>
<a-pagination
:total="total"
:show-total="(total, range) => ` 共 ${total} 条`"
show-size-changer
show-quick-jumper
@change="onChange"
style="
display: flex;
position: absolute;
bottom: 20px;
right: 30px;
justify-content: right;
margin-top: 10px;
margin-right: 30px;
" />
</div>
</template>
<script lang="ts" setup>
@ -138,6 +150,7 @@
{
title: '区域名称',
dataIndex: 'location',
width: 100,
customCell: (record, rowIndex) => {
if (rowIndex == undefined) {
return {
@ -160,6 +173,7 @@
{
title: '点位',
dataIndex: 'pointName',
width: 100,
customCell: (record, rowIndex) => {
if (rowIndex == undefined) {
return {
@ -186,6 +200,7 @@
{
title: '日期',
dataIndex: 'time',
width: 110,
},
];

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

@ -1,7 +1,9 @@
<template>
<div style="background: #f2f6fd; width: 100%; height: 100%">
<div style="width: 100%; height: 100%">
<div style="display: flex">
<a-tabs v-model:activeKey="activeKey" style="height: 5%; width: 100%; background: #ffffff">
<a-tabs
v-model:activeKey="activeKey"
style="height: 5%; width: 100%; margin-top: 0.5%; background: #ffffff">
<a-tab-pane key="1" tab="综合数据" />
<a-tab-pane key="2" tab="历史数据" />
<a-tab-pane key="3" tab="平均数据" />
@ -444,4 +446,23 @@
queryDeviceInfoListPage();
});
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
::v-deep .ant-tabs-tab {
font-weight: bold; /* 选中标签的加粗 */
// font-size: 16px;
// letter-spacing: 1.33px;
color: #666666 !important;
}
::v-deep .ant-tabs-tab.ant-tabs-tab-active .ant-tabs-tab-btn {
// background-color: #f0f0f0; /* */
// color: #1890ff; /* */
// border-radius: 5px; /* */
// font-weight: bold; /* */
color: #000000 !important;
}
::v-deep .ant-tabs-tab:hover {
color: #000000; /* 悬停时的文字颜色 */
}
</style>

Loading…
Cancel
Save