From 9721c16da86aa5bf45ff2b1b1b255be87d2cff0d Mon Sep 17 00:00:00 2001 From: net <net@netdeMBP.lan> Date: 星期五, 14 二月 2025 11:17:31 +0800 Subject: [PATCH] 能耗对比分析:同比、环比页面完成 --- package-lock.json | 6 zhitan-vue/src/views/poweranalysis/perPassu/index.vue | 586 +++++++++++++++++++++ zhitan-vue/src/views/powerquality/load/index.vue | 409 +++++++++++++++ zhitan-vue/src/views/poweranalysis/pariPassu/index.vue | 586 +++++++++++++++++++++ zhitan-vue/src/views/policy/policyrule/components/EditModal.vue | 0 zhitan-system/.DS_Store | 0 zhitan-generator/.DS_Store | 0 zhitan-vue/vite.config.js | 2 zhitan-vue/src/views/policy/policyrule/policyRule.vue | 0 zhitan-vue/src/views/policy/projectmanage/projectmanage/components/EditModal.vue | 0 zhitan-admin/.DS_Store | 0 zhitan-vue/src/views/policy/policyrule/components/EditModal copy.vue | 0 .DS_Store | 0 zhitan-vue/.env.development | 2 zhitan-vue/src/views/policy/projectmanage/projectmanage/projectManage.vue | 0 zhitan-quartz/.DS_Store | 0 16 files changed, 1,590 insertions(+), 1 deletions(-) diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..e30a150 --- /dev/null +++ b/.DS_Store Binary files differ diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..56b8aee --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "zhitan-ems", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/zhitan-admin/.DS_Store b/zhitan-admin/.DS_Store new file mode 100644 index 0000000..83a9dc7 --- /dev/null +++ b/zhitan-admin/.DS_Store Binary files differ diff --git a/zhitan-generator/.DS_Store b/zhitan-generator/.DS_Store new file mode 100644 index 0000000..9c98af2 --- /dev/null +++ b/zhitan-generator/.DS_Store Binary files differ diff --git a/zhitan-quartz/.DS_Store b/zhitan-quartz/.DS_Store new file mode 100644 index 0000000..93d6ade --- /dev/null +++ b/zhitan-quartz/.DS_Store Binary files differ diff --git a/zhitan-system/.DS_Store b/zhitan-system/.DS_Store new file mode 100644 index 0000000..40087c1 --- /dev/null +++ b/zhitan-system/.DS_Store Binary files differ diff --git a/zhitan-vue/.env.development b/zhitan-vue/.env.development index 74bd43c..52eeab6 100644 --- a/zhitan-vue/.env.development +++ b/zhitan-vue/.env.development @@ -12,4 +12,4 @@ # weishuaishuai # VITE_APP_BASE_API = 'http://127.0.0.1:8080' # test -VITE_APP_BASE_API = 'http://127.0.0.1:8080' +VITE_APP_BASE_API = 'http://139.159.201.118:8201' diff --git a/zhitan-vue/src/views/energyconservation/policyrule/components/EditModal copy.vue b/zhitan-vue/src/views/policy/policyrule/components/EditModal copy.vue similarity index 100% rename from zhitan-vue/src/views/energyconservation/policyrule/components/EditModal copy.vue rename to zhitan-vue/src/views/policy/policyrule/components/EditModal copy.vue diff --git a/zhitan-vue/src/views/energyconservation/policyrule/components/EditModal.vue b/zhitan-vue/src/views/policy/policyrule/components/EditModal.vue similarity index 100% rename from zhitan-vue/src/views/energyconservation/policyrule/components/EditModal.vue rename to zhitan-vue/src/views/policy/policyrule/components/EditModal.vue diff --git a/zhitan-vue/src/views/energyconservation/policyrule/policyRule.vue b/zhitan-vue/src/views/policy/policyrule/policyRule.vue similarity index 100% rename from zhitan-vue/src/views/energyconservation/policyrule/policyRule.vue rename to zhitan-vue/src/views/policy/policyrule/policyRule.vue diff --git a/zhitan-vue/src/views/energyconservation/projectmanage/projectmanage/components/EditModal.vue b/zhitan-vue/src/views/policy/projectmanage/projectmanage/components/EditModal.vue similarity index 100% rename from zhitan-vue/src/views/energyconservation/projectmanage/projectmanage/components/EditModal.vue rename to zhitan-vue/src/views/policy/projectmanage/projectmanage/components/EditModal.vue diff --git a/zhitan-vue/src/views/energyconservation/projectmanage/projectmanage/projectManage.vue b/zhitan-vue/src/views/policy/projectmanage/projectmanage/projectManage.vue similarity index 100% rename from zhitan-vue/src/views/energyconservation/projectmanage/projectmanage/projectManage.vue rename to zhitan-vue/src/views/policy/projectmanage/projectmanage/projectManage.vue diff --git a/zhitan-vue/src/views/poweranalysis/pariPassu/index.vue b/zhitan-vue/src/views/poweranalysis/pariPassu/index.vue new file mode 100644 index 0000000..1b5d237 --- /dev/null +++ b/zhitan-vue/src/views/poweranalysis/pariPassu/index.vue @@ -0,0 +1,586 @@ +<template> + <div class="page"> + <div class="page-container"> + <div class="page-container-left"> + <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" /> + </div> + <div class="page-container-right"> + <div class="form-card"> + <el-form :model="queryParams" ref="queryRef" :inline="true"> + <el-form-item label="鏈熼棿" prop="timeType"> + <el-select v-model="queryParams.timeType" placeholder="鏈熼棿" clearable style="width: 120px" + @change="handleTimeType"> + <el-option v-for="dict in period" :key="dict.value" :label="dict.label" :value="dict.value" /> + </el-select> + </el-form-item> + <el-form-item label="鏃堕棿"> + <el-date-picker v-model="queryParams.dataTime" :type="queryParams.timeType == 'YEAR' + ? 'year' + : queryParams.timeType == 'MONTH' + ? 'month' + : 'date' + " :format="queryParams.timeType == 'YEAR' + ? 'YYYY' + : queryParams.timeType == 'MONTH' + ? 'YYYY-MM' + : 'YYYY-MM-DD' + " value-format="YYYY-MM-DD" placeholder="鏃堕棿" style="width: 100%" /> + </el-form-item> + <el-form-item label="鑳芥簮绫诲瀷" prop="energyType"> + <el-select v-model="queryParams.energyType" placeholder="鑳芥簮绫诲瀷" clearable style="width: 120px"> + <el-option :label="item.enername" :value="item.enersno" v-for="item in energyTypeList" + :key="item.enersno" @click="handleEnergyType(item)" /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="Search" @click="handleQuery"> + 鎼滅储 + </el-button> + <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + <!-- <el-form-item> + <el-button :type="queryParams.analysisType == 'YOY' ? 'primary' : ''" @click="handleAnalysisType('YOY')"> + 鍚屾瘮 + </el-button> + <el-button :type="queryParams.analysisType == 'MOM' ? 'primary' : ''" @click="handleAnalysisType('MOM')"> + 鐜瘮 + </el-button> + </el-form-item> --> + <el-form-item> + <el-button type="primary" icon="Download" @click="handleExport"> + 瀵煎嚭 + </el-button> + </el-form-item> + </el-form> + </div> + <div style=" + height: calc(100vh - 220px) !important; + max-height: calc(100vh - 220px) !important; + overflow-y: auto; + " v-loading="loading"> + + <BaseCard :title="queryParams.nodeName + '-鑳借�楀姣斿垎鏋�'"> + <div class="chart-box"> + <div id="Chart1" /> + </div> + </BaseCard> + + <BaseCard :title="queryParams.nodeName + + '-鑳借�楀姣斿垎鏋愬悓姣斿垎鏋愯〃-' + + queryParams.enername + "> + <div class="table-box"> + <el-table :data="departmentList" show-summary> + <el-table-column label="鏈湡鏃堕棿" align="center" key="currentTime" prop="currentTime" + :show-overflow-tooltip="true" /> + <el-table-column :label="'鏈湡鑰�' + + queryParams.enername + + '(' + + queryParams.muid + + ')' + " align="center" key="currentValue" prop="currentValue" :show-overflow-tooltip="true" /> + <el-table-column label="鍚屾湡鏃堕棿" align="center" key="compareTime" prop="compareTime" + :show-overflow-tooltip="true" /> + <el-table-column :label="'鍚屾湡鑰�' + + queryParams.enername + + '(' + + queryParams.muid + + ')' + " align="center" key="compareValue" prop="compareValue" :show-overflow-tooltip="true" /> + <el-table-column :label="(queryParams.analysisType == 'YOY' ? '鍚�' : '鐜�') + '姣�(%)' + " align="center" key="ratio" prop="ratio" :show-overflow-tooltip="true" width="200" /> + </el-table> + </div> + </BaseCard> + <!-- </el-col> + </el-row> --> + </div> + </div> + </div> + </div> +</template> + +<script setup name="department"> +import { + listRegion, + listDepartment, +} from "@/api/energyAnalysis/energyAnalysis"; +import { listEnergyTypeList } from "@/api/modelConfiguration/energyType"; +import * as echarts from "echarts"; +const { proxy } = getCurrentInstance(); +const { period } = proxy.useDict("period"); +import { useRoute } from "vue-router"; +import useSettingsStore from "@/store/modules/settings"; +const settingsStore = useSettingsStore(); +watch( + () => settingsStore.sideTheme, + (val) => { + getList(); + } +); +const energyTypeList = ref(undefined); +const departmentList = ref([]); +const loading = ref(false); +const data = reactive({ + queryParams: { + nodeId: null, + timeType: null, + dataTime: null, + analysisType: "YOY", + energyType: null, + }, + query: { + modelCode: null, + }, +}); +const { queryParams, query } = toRefs(data); +/** 鑺傜偣鍗曞嚮浜嬩欢 */ +function handleNodeClick(data) { + queryParams.value.nodeId = data.id; + queryParams.value.nodeName = data.label; + handleTimeType(period.value[1].value); + listEnergyTypeList().then((res) => { + energyTypeList.value = res.data; + queryParams.value.energyType = energyTypeList.value[0].enersno; + queryParams.value.enername = energyTypeList.value[0].enername; + queryParams.value.muid = energyTypeList.value[0].muid; + handleQuery(); + }); +} +function handleTimeType(e) { + queryParams.value.timeType = e; + queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD"); +} +function handleEnergyType(item) { + queryParams.value.enername = item.enername; + queryParams.value.muid = item.muid; + handleQuery(); +} +function handleAnalysisType(analysisType) { + queryParams.value.analysisType = analysisType; + getList(); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-鍒楄〃 +function getList() { + loading.value = true; + // 鍦ㄥ垵濮嬪寲涔嬪墠锛屽厛dispose鏃х殑瀹炰緥 + if (echarts.getInstanceByDom(document.getElementById("Chart1"))) { + echarts.dispose(document.getElementById("Chart1")); + } + // if (echarts.getInstanceByDom(document.getElementById("Chart2"))) { + // echarts.dispose(document.getElementById("Chart2")); + // } + const myChart1 = echarts.init(document.getElementById("Chart1")); + // const myChart2 = echarts.init(document.getElementById("Chart2")); + listRegion( + proxy.addDateRange({ + ...queryParams.value, + ...query.value, + }) + ).then((res) => { + if (!!res.code && res.code == 200) { + loading.value = false; + let xdata = []; + let yvalue = []; + let ycompareValue = []; + let yqoq = []; + if (!!res.data.chartDataList) { + res.data.chartDataList.map((item) => { + xdata.push( + proxy + .dayjs(item.xdata) + .format( + queryParams.value.timeType == "YEAR" + ? "MM鏈�" + : queryParams.value.timeType == "MONTH" + ? "DD鏃�" + : "HH鏃�" + ) + ); + yvalue.push(!!item.yvalue ? item.yvalue : 0); + ycompareValue.push(!!item.ycompareValue ? item.ycompareValue : 0); + yqoq.push(!!item.yqoq ? item.yqoq : 0); + }); + } + setTimeout(() => { + myChart1.setOption({ + color: ["#2979ff", "#19be6b", "#ff9900", "#fa3534"], + grid: { + top: "45", + left: "7%", + right: "5%", + bottom: "10", + containLabel: true, + }, + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + legend: { + icon: "rect", + itemWidth: 14, + itemHeight: 10, + textStyle: { + color: + settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + }, + }, + xAxis: { + type: "category", + axisPointer: { + type: "shadow", + }, + axisLine: { + show: true, + lineStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + axisTick: { + show: false, + }, + splitArea: { + show: false, + }, + splitLine: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + fontSize: 14, + padding: [5, 0, 0, 0], + // formatter: '{value} ml' + }, + data: xdata, + }, + yAxis: [ + { + type: "value", + name: + "鑰�" + + queryParams.value.enername + + "閲�(" + + queryParams.value.muid + + ")", + nameTextStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + padding: [0, 0, 5, 0], + }, + axisLine: { + show: false, + }, + splitLine: { + show: true, + lineStyle: { + type: "dashed", + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + axisTick: { + show: false, + }, + splitArea: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + }, + }, + { + type: "value", + name: queryParams.value.analysisType == "YOY" ? "鍚屾瘮(%)" : "鐜瘮(%)", + alignTicks: true, + nameTextStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + padding: [0, 0, 5, 0], + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + splitLine: { + show: true, + lineStyle: { + type: "dashed", + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + splitArea: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + }, + }, + ], + series: [ + { + name: "鏈湡鍊�", + type: "bar", + barWidth: "8", + tooltip: { + valueFormatter: function (value) { + return value + queryParams.value.muid; + }, + }, + itemStyle: { + borderRadius: [15, 15, 0, 0], + }, + data: yvalue, + markPoint: { + data: [ + { type: "max", name: "Max" }, + { type: "min", name: "Min" }, + ], + }, + }, + { + name: "鍚屾湡鍊�", + type: "bar", + barWidth: "8", + tooltip: { + valueFormatter: function (value) { + return value + queryParams.value.muid; + }, + }, + itemStyle: { + borderRadius: [15, 15, 0, 0], + }, + data: ycompareValue, + markPoint: { + data: [ + { type: "max", name: "Max" }, + { type: "min", name: "Min" }, + ], + }, + }, + { + name: queryParams.value.analysisType == "YOY" ? "鍚屾瘮" : "鐜瘮", + type: "line", + yAxisIndex: 1, + symbol: "none", // 璁剧疆涓� 'none' 鍘绘帀鍦嗙偣 + tooltip: { + valueFormatter: function (value) { + return value + "%"; + }, + }, + data: yqoq, + }, + ], + }); + }, 100); + departmentList.value = !!res.data.dataList ? res.data.dataList : []; + window.addEventListener( + "resize", + () => { + myChart1.resize(); + }, + { passive: true } + ); + } + }); + // listDepartment( + // proxy.addDateRange({ + // ...queryParams.value, + // ...query.value, + // }) + // ).then((res) => { + // if (!!res.code && res.code == 200) { + // loading.value = false; + // let seriesdata = []; + // let xdata = []; + // if (!!energyTypeList.value) { + // energyTypeList.value.map((item) => { + // seriesdata.push({ + // name: item.enername, + // type: "bar", + // barWidth: "16", + // stack: "total", + // data: [], + // }); + // }); + // } + // if (!!res.data) { + // res.data.map((dataItem) => { + // xdata.push(dataItem.nodeName) + // seriesdata.forEach((seriesdataItem) => { + // if ( + // dataItem.data.find( + // (dataItemItem) => + // dataItemItem.energyTypeName == seriesdataItem.name + // ) == undefined + // ) { + // dataItem.data.push({ + // nodeId: dataItem.nodeId, + // nodeName: dataItem.nodeName, + // energyTypeNo: null, + // energyTypeName: seriesdataItem.name, + // energyConsumption: 0, + // }); + // } + // dataItem.data.map(dataItemItem => { + // if (seriesdataItem.name == dataItemItem.energyTypeName) { + // seriesdataItem.data.push(dataItemItem.energyConsumption) + // } + // }) + // }); + // }); + // } + // setTimeout(() => { + // myChart2.setOption({ + // color: ["#2979ff", "#19be6b", "#ff9900", "#fa3534"], + // grid: { + // top: "45", + // left: "17%", + // right: "5%", + // bottom: "10", + // containLabel: true, + // }, + // tooltip: { + // trigger: "axis", + // axisPointer: { + // type: "shadow", + // }, + // }, + // legend: { + // icon: "rect", + // itemWidth: 14, + // itemHeight: 10, + // right: 0, + // textStyle: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // }, + // }, + // xAxis: { + // nameLocation: "start", + // type: "value", + // name: "鍗曚綅tce", + // nameTextStyle: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // fontSize: 14, + // padding: [0, 0, 5, 0], + // }, + // axisLine: { + // show: false, + // }, + // splitLine: { + // show: true, + // lineStyle: { + // type: "dashed", + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // }, + // }, + // axisTick: { + // show: false, + // }, + // splitArea: { + // show: false, + // }, + // axisLabel: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // fontSize: 14, + // // formatter: '{value} ml' + // }, + // }, + // yAxis: { + // type: "category", + // axisPointer: { + // type: "shadow", + // }, + // axisLine: { + // show: true, + // lineStyle: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // }, + // }, + // axisTick: { + // show: false, + // }, + // splitArea: { + // show: false, + // }, + // splitLine: { + // show: false, + // }, + // axisLabel: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // fontSize: 14, + // padding: [5, 0, 0, 0], + // // formatter: '{value} ml' + // }, + // data: xdata.splice(0, 6), + // }, + // series: seriesdata, + // }); + // }, 100); + // window.addEventListener("resize", () => { + // myChart2.resize(); + // },{passive: true}); + // } + // }); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-鎼滅储 +function handleQuery() { + getList(); +} +// 鑳借�楀姣斿垎鏋�-閲嶇疆 +function resetQuery() { + proxy.resetForm("queryRef"); + handleTimeType(period.value[0].value); + queryParams.value.energyType = energyTypeList.value[0].enersno; + queryParams.value.enername = energyTypeList.value[0].enername; + queryParams.value.muid = energyTypeList.value[0].muid; + queryParams.value.analysisType = "YOY"; + handleQuery(); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-瀵煎嚭 +function handleExport() { + proxy.download( + "consumptionanalysis/energyExport", + { + ...queryParams.value, + ...query.value, + }, + `${queryParams.value.nodeName}-鍘傚尯鑳借�楀垎鏋恄${new Date().getTime()}.xlsx` + ); +} +</script> +<style scoped lang="scss"> +@import "@/assets/styles/page.scss"; +</style> diff --git a/zhitan-vue/src/views/poweranalysis/perPassu/index.vue b/zhitan-vue/src/views/poweranalysis/perPassu/index.vue new file mode 100644 index 0000000..c5c5591 --- /dev/null +++ b/zhitan-vue/src/views/poweranalysis/perPassu/index.vue @@ -0,0 +1,586 @@ +<template> + <div class="page"> + <div class="page-container"> + <div class="page-container-left"> + <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" /> + </div> + <div class="page-container-right"> + <div class="form-card"> + <el-form :model="queryParams" ref="queryRef" :inline="true"> + <el-form-item label="鏈熼棿" prop="timeType"> + <el-select v-model="queryParams.timeType" placeholder="鏈熼棿" clearable style="width: 120px" + @change="handleTimeType"> + <el-option v-for="dict in period" :key="dict.value" :label="dict.label" :value="dict.value" /> + </el-select> + </el-form-item> + <el-form-item label="鏃堕棿"> + <el-date-picker v-model="queryParams.dataTime" :type="queryParams.timeType == 'YEAR' + ? 'year' + : queryParams.timeType == 'MONTH' + ? 'month' + : 'date' + " :format="queryParams.timeType == 'YEAR' + ? 'YYYY' + : queryParams.timeType == 'MONTH' + ? 'YYYY-MM' + : 'YYYY-MM-DD' + " value-format="YYYY-MM-DD" placeholder="鏃堕棿" style="width: 100%" /> + </el-form-item> + <el-form-item label="鑳芥簮绫诲瀷" prop="energyType"> + <el-select v-model="queryParams.energyType" placeholder="鑳芥簮绫诲瀷" clearable style="width: 120px"> + <el-option :label="item.enername" :value="item.enersno" v-for="item in energyTypeList" + :key="item.enersno" @click="handleEnergyType(item)" /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="Search" @click="handleQuery"> + 鎼滅储 + </el-button> + <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + <!-- <el-form-item> + <el-button :type="queryParams.analysisType == 'YOY' ? 'primary' : ''" @click="handleAnalysisType('YOY')"> + 鍚屾瘮 + </el-button> + <el-button :type="queryParams.analysisType == 'MOM' ? 'primary' : ''" @click="handleAnalysisType('MOM')"> + 鐜瘮 + </el-button> + </el-form-item> --> + <el-form-item> + <el-button type="primary" icon="Download" @click="handleExport"> + 瀵煎嚭 + </el-button> + </el-form-item> + </el-form> + </div> + <div style=" + height: calc(100vh - 220px) !important; + max-height: calc(100vh - 220px) !important; + overflow-y: auto; + " v-loading="loading"> + + <BaseCard :title="queryParams.nodeName + '-鑳借�楀姣斿垎鏋�'"> + <div class="chart-box"> + <div id="Chart1" /> + </div> + </BaseCard> + + <BaseCard :title="queryParams.nodeName + + '-鑳借�楀姣斿垎鏋愮幆姣斿垎鏋愯〃-' + + queryParams.enername + "> + <div class="table-box"> + <el-table :data="departmentList" show-summary> + <el-table-column label="鏈湡鏃堕棿" align="center" key="currentTime" prop="currentTime" + :show-overflow-tooltip="true" /> + <el-table-column :label="'鏈湡鑰�' + + queryParams.enername + + '(' + + queryParams.muid + + ')' + " align="center" key="currentValue" prop="currentValue" :show-overflow-tooltip="true" /> + <el-table-column label="鍚屾湡鏃堕棿" align="center" key="compareTime" prop="compareTime" + :show-overflow-tooltip="true" /> + <el-table-column :label="'鍚屾湡鑰�' + + queryParams.enername + + '(' + + queryParams.muid + + ')' + " align="center" key="compareValue" prop="compareValue" :show-overflow-tooltip="true" /> + <el-table-column :label="(queryParams.analysisType == 'YOY' ? '鍚�' : '鐜�') + '姣�(%)' + " align="center" key="ratio" prop="ratio" :show-overflow-tooltip="true" width="200" /> + </el-table> + </div> + </BaseCard> + <!-- </el-col> + </el-row> --> + </div> + </div> + </div> + </div> +</template> + +<script setup name="department"> +import { + listRegion, + listDepartment, +} from "@/api/energyAnalysis/energyAnalysis"; +import { listEnergyTypeList } from "@/api/modelConfiguration/energyType"; +import * as echarts from "echarts"; +const { proxy } = getCurrentInstance(); +const { period } = proxy.useDict("period"); +import { useRoute } from "vue-router"; +import useSettingsStore from "@/store/modules/settings"; +const settingsStore = useSettingsStore(); +watch( + () => settingsStore.sideTheme, + (val) => { + getList(); + } +); +const energyTypeList = ref(undefined); +const departmentList = ref([]); +const loading = ref(false); +const data = reactive({ + queryParams: { + nodeId: null, + timeType: null, + dataTime: null, + analysisType: "MOM", + energyType: null, + }, + query: { + modelCode: null, + }, +}); +const { queryParams, query } = toRefs(data); +/** 鑺傜偣鍗曞嚮浜嬩欢 */ +function handleNodeClick(data) { + queryParams.value.nodeId = data.id; + queryParams.value.nodeName = data.label; + handleTimeType(period.value[1].value); + listEnergyTypeList().then((res) => { + energyTypeList.value = res.data; + queryParams.value.energyType = energyTypeList.value[0].enersno; + queryParams.value.enername = energyTypeList.value[0].enername; + queryParams.value.muid = energyTypeList.value[0].muid; + handleQuery(); + }); +} +function handleTimeType(e) { + queryParams.value.timeType = e; + queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD"); +} +function handleEnergyType(item) { + queryParams.value.enername = item.enername; + queryParams.value.muid = item.muid; + handleQuery(); +} +function handleAnalysisType(analysisType) { + queryParams.value.analysisType = analysisType; + getList(); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-鍒楄〃 +function getList() { + loading.value = true; + // 鍦ㄥ垵濮嬪寲涔嬪墠锛屽厛dispose鏃х殑瀹炰緥 + if (echarts.getInstanceByDom(document.getElementById("Chart1"))) { + echarts.dispose(document.getElementById("Chart1")); + } + // if (echarts.getInstanceByDom(document.getElementById("Chart2"))) { + // echarts.dispose(document.getElementById("Chart2")); + // } + const myChart1 = echarts.init(document.getElementById("Chart1")); + // const myChart2 = echarts.init(document.getElementById("Chart2")); + listRegion( + proxy.addDateRange({ + ...queryParams.value, + ...query.value, + }) + ).then((res) => { + if (!!res.code && res.code == 200) { + loading.value = false; + let xdata = []; + let yvalue = []; + let ycompareValue = []; + let yqoq = []; + if (!!res.data.chartDataList) { + res.data.chartDataList.map((item) => { + xdata.push( + proxy + .dayjs(item.xdata) + .format( + queryParams.value.timeType == "YEAR" + ? "MM鏈�" + : queryParams.value.timeType == "MONTH" + ? "DD鏃�" + : "HH鏃�" + ) + ); + yvalue.push(!!item.yvalue ? item.yvalue : 0); + ycompareValue.push(!!item.ycompareValue ? item.ycompareValue : 0); + yqoq.push(!!item.yqoq ? item.yqoq : 0); + }); + } + setTimeout(() => { + myChart1.setOption({ + color: ["#2979ff", "#19be6b", "#ff9900", "#fa3534"], + grid: { + top: "45", + left: "7%", + right: "5%", + bottom: "10", + containLabel: true, + }, + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + legend: { + icon: "rect", + itemWidth: 14, + itemHeight: 10, + textStyle: { + color: + settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + }, + }, + xAxis: { + type: "category", + axisPointer: { + type: "shadow", + }, + axisLine: { + show: true, + lineStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + axisTick: { + show: false, + }, + splitArea: { + show: false, + }, + splitLine: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + fontSize: 14, + padding: [5, 0, 0, 0], + // formatter: '{value} ml' + }, + data: xdata, + }, + yAxis: [ + { + type: "value", + name: + "鑰�" + + queryParams.value.enername + + "閲�(" + + queryParams.value.muid + + ")", + nameTextStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + padding: [0, 0, 5, 0], + }, + axisLine: { + show: false, + }, + splitLine: { + show: true, + lineStyle: { + type: "dashed", + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + axisTick: { + show: false, + }, + splitArea: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + }, + }, + { + type: "value", + name: queryParams.value.analysisType == "YOY" ? "鍚屾瘮(%)" : "鐜瘮(%)", + alignTicks: true, + nameTextStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + padding: [0, 0, 5, 0], + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + splitLine: { + show: true, + lineStyle: { + type: "dashed", + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + splitArea: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + }, + }, + ], + series: [ + { + name: "鏈湡鍊�", + type: "bar", + barWidth: "8", + tooltip: { + valueFormatter: function (value) { + return value + queryParams.value.muid; + }, + }, + itemStyle: { + borderRadius: [15, 15, 0, 0], + }, + data: yvalue, + markPoint: { + data: [ + { type: "max", name: "Max" }, + { type: "min", name: "Min" }, + ], + }, + }, + { + name: "鍚屾湡鍊�", + type: "bar", + barWidth: "8", + tooltip: { + valueFormatter: function (value) { + return value + queryParams.value.muid; + }, + }, + itemStyle: { + borderRadius: [15, 15, 0, 0], + }, + data: ycompareValue, + markPoint: { + data: [ + { type: "max", name: "Max" }, + { type: "min", name: "Min" }, + ], + }, + }, + { + name: queryParams.value.analysisType == "YOY" ? "鍚屾瘮" : "鐜瘮", + type: "line", + yAxisIndex: 1, + symbol: "none", // 璁剧疆涓� 'none' 鍘绘帀鍦嗙偣 + tooltip: { + valueFormatter: function (value) { + return value + "%"; + }, + }, + data: yqoq, + }, + ], + }); + }, 100); + departmentList.value = !!res.data.dataList ? res.data.dataList : []; + window.addEventListener( + "resize", + () => { + myChart1.resize(); + }, + { passive: true } + ); + } + }); + // listDepartment( + // proxy.addDateRange({ + // ...queryParams.value, + // ...query.value, + // }) + // ).then((res) => { + // if (!!res.code && res.code == 200) { + // loading.value = false; + // let seriesdata = []; + // let xdata = []; + // if (!!energyTypeList.value) { + // energyTypeList.value.map((item) => { + // seriesdata.push({ + // name: item.enername, + // type: "bar", + // barWidth: "16", + // stack: "total", + // data: [], + // }); + // }); + // } + // if (!!res.data) { + // res.data.map((dataItem) => { + // xdata.push(dataItem.nodeName) + // seriesdata.forEach((seriesdataItem) => { + // if ( + // dataItem.data.find( + // (dataItemItem) => + // dataItemItem.energyTypeName == seriesdataItem.name + // ) == undefined + // ) { + // dataItem.data.push({ + // nodeId: dataItem.nodeId, + // nodeName: dataItem.nodeName, + // energyTypeNo: null, + // energyTypeName: seriesdataItem.name, + // energyConsumption: 0, + // }); + // } + // dataItem.data.map(dataItemItem => { + // if (seriesdataItem.name == dataItemItem.energyTypeName) { + // seriesdataItem.data.push(dataItemItem.energyConsumption) + // } + // }) + // }); + // }); + // } + // setTimeout(() => { + // myChart2.setOption({ + // color: ["#2979ff", "#19be6b", "#ff9900", "#fa3534"], + // grid: { + // top: "45", + // left: "17%", + // right: "5%", + // bottom: "10", + // containLabel: true, + // }, + // tooltip: { + // trigger: "axis", + // axisPointer: { + // type: "shadow", + // }, + // }, + // legend: { + // icon: "rect", + // itemWidth: 14, + // itemHeight: 10, + // right: 0, + // textStyle: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // }, + // }, + // xAxis: { + // nameLocation: "start", + // type: "value", + // name: "鍗曚綅tce", + // nameTextStyle: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // fontSize: 14, + // padding: [0, 0, 5, 0], + // }, + // axisLine: { + // show: false, + // }, + // splitLine: { + // show: true, + // lineStyle: { + // type: "dashed", + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // }, + // }, + // axisTick: { + // show: false, + // }, + // splitArea: { + // show: false, + // }, + // axisLabel: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // fontSize: 14, + // // formatter: '{value} ml' + // }, + // }, + // yAxis: { + // type: "category", + // axisPointer: { + // type: "shadow", + // }, + // axisLine: { + // show: true, + // lineStyle: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // }, + // }, + // axisTick: { + // show: false, + // }, + // splitArea: { + // show: false, + // }, + // splitLine: { + // show: false, + // }, + // axisLabel: { + // color: + // settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + // fontSize: 14, + // padding: [5, 0, 0, 0], + // // formatter: '{value} ml' + // }, + // data: xdata.splice(0, 6), + // }, + // series: seriesdata, + // }); + // }, 100); + // window.addEventListener("resize", () => { + // myChart2.resize(); + // },{passive: true}); + // } + // }); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-鎼滅储 +function handleQuery() { + getList(); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-閲嶇疆 +function resetQuery() { + proxy.resetForm("queryRef"); + handleTimeType(period.value[0].value); + queryParams.value.energyType = energyTypeList.value[0].enersno; + queryParams.value.enername = energyTypeList.value[0].enername; + queryParams.value.muid = energyTypeList.value[0].muid; + queryParams.value.analysisType = "YOY"; + handleQuery(); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-瀵煎嚭 +function handleExport() { + proxy.download( + "consumptionanalysis/energyExport", + { + ...queryParams.value, + ...query.value, + }, + `${queryParams.value.nodeName}-鍘傚尯鑳借�楀垎鏋恄${new Date().getTime()}.xlsx` + ); +} +</script> +<style scoped lang="scss"> +@import "@/assets/styles/page.scss"; +</style> diff --git a/zhitan-vue/src/views/powerquality/load/index.vue b/zhitan-vue/src/views/powerquality/load/index.vue new file mode 100644 index 0000000..1d2cc90 --- /dev/null +++ b/zhitan-vue/src/views/powerquality/load/index.vue @@ -0,0 +1,409 @@ +<template> + <div class="page"> + <div class="page-container"> + <div class="page-container-left"> + <LeftTree ref="leftTreeRef" @handleNodeClick="handleNodeClick" /> + </div> + <div class="page-container-right"> + <div class="form-card"> + <el-form :model="queryParams" ref="queryRef" :inline="true"> + <el-form-item label="鏈熼棿" prop="timeType"> + <el-select v-model="queryParams.timeType" placeholder="鏈熼棿" clearable style="width: 120px" + @change="handleTimeType"> + <el-option v-for="dict in period" :key="dict.value" :label="dict.label" :value="dict.value" /> + </el-select> + </el-form-item> + <el-form-item label="鏃堕棿"> + <el-date-picker v-model="queryParams.dataTime" :type="queryParams.timeType == 'YEAR'? 'year': queryParams.timeType == 'MONTH'? 'month': 'date'" :format="queryParams.timeType == 'YEAR'? 'YYYY': queryParams.timeType == 'MONTH'? 'YYYY-MM': 'YYYY-MM-DD'" value-format="YYYY-MM-DD" placeholder="鏃堕棿" style="width: 100%" /> + </el-form-item> + <el-form-item label="閫夋嫨鐢佃〃" prop="energyType"> + <el-select v-model="queryParams.energyType" placeholder="閫夋嫨鐢佃〃" clearable style="width: 120px"> + <el-option :label="item.enername" :value="item.enersno" v-for="item in energyTypeList" + :key="item.enersno" @click="handleEnergyType(item)" /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="Search" @click="handleQuery"> + 鎼滅储 + </el-button> + + </el-form-item> + + </el-form> + </div> + <div style=" + height: calc(100vh - 220px) !important; + max-height: calc(100vh - 220px) !important; + overflow-y: auto; + " v-loading="loading"> + <!-- <el-row :gutter="24"> + <el-col :span="16"> --> + <BaseCard :title="queryParams.nodeName + '-璐熻嵎鍒嗘瀽'"> + <div class="chart-box"> + <div id="Chart1" /> + </div> + </BaseCard> + + <BaseCard :title="queryParams.nodeName + + '-鍘傚尯鑳借�楀垎鏋愮粺璁″垎鏋愯〃-' + + queryParams.enername + "> + <div class="table-box"> + <el-table :data="departmentList" show-summary> + <el-table-column label="鏈湡鏃堕棿" align="center" key="currentTime" prop="currentTime" + :show-overflow-tooltip="true" /> + <el-table-column :label="'鏈湡鑰�' + + queryParams.enername + + '(' + + queryParams.muid + + ')' + " align="center" key="currentValue" prop="currentValue" :show-overflow-tooltip="true" /> + <el-table-column label="鍚屾湡鏃堕棿" align="center" key="compareTime" prop="compareTime" + :show-overflow-tooltip="true" /> + <el-table-column :label="'鍚屾湡鑰�' + + queryParams.enername + + '(' + + queryParams.muid + + ')' + " align="center" key="compareValue" prop="compareValue" :show-overflow-tooltip="true" /> + <el-table-column :label="(queryParams.analysisType == 'YOY' ? '鍚�' : '鐜�') + '姣�(%)' + " align="center" key="ratio" prop="ratio" :show-overflow-tooltip="true" width="200" /> + </el-table> + </div> + </BaseCard> + <!-- </el-col> + </el-row> --> + </div> + </div> + </div> + </div> +</template> + +<script setup name="department"> +import { + listRegion, + listDepartment, +} from "@/api/energyAnalysis/energyAnalysis"; +import { listEnergyTypeList } from "@/api/modelConfiguration/energyType"; +import * as echarts from "echarts"; +const { proxy } = getCurrentInstance(); +const { period } = proxy.useDict("period"); +import { useRoute } from "vue-router"; +import useSettingsStore from "@/store/modules/settings"; +const settingsStore = useSettingsStore(); +watch( + () => settingsStore.sideTheme, + (val) => { + // getList(); + } +); + //const energyTypeList = ref(undefined); +const energyTypeList =[ + { enerno: 1, enername: "鐢佃〃1" }, + { enerno: 2, enername: "鐢佃〃2" }, + { enerno: 3, enername: "鐢佃〃3" }, + { enerno: 4, enername: "鐢佃〃4"}, + ]; +// const departmentList = ref([]); +const loading = ref(false); +const data = reactive({ + queryParams: { + nodeId: null, + timeType: null, + dataTime: null, + analysisType: "YOY", + energyType: null, + }, + query: { + modelCode: null, + }, + + + +}); +const { queryParams, query } = toRefs(data); +/** 鑺傜偣鍗曞嚮浜嬩欢 */ +function handleNodeClick(data) { + queryParams.value.nodeId = data.id; + queryParams.value.nodeName = data.label; + handleTimeType(period.value[0].value); + listEnergyTypeList().then((res) => { + + + handleQuery(); + }); +} +function handleTimeType(e) { + queryParams.value.timeType = e; + queryParams.value.dataTime = proxy.dayjs(new Date()).format("YYYY-MM-DD"); +} +//閫夋嫨鐢佃〃 +function handleEnergyType(item) { + // queryParams.value.enername = item.enername; + // queryParams.value.muid = item.muid; + // handleQuery(); +} +function handleAnalysisType(analysisType) { + queryParams.value.analysisType = analysisType; + getList(); +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-鍒楄〃 +function getList() { + loading.value = true; + // 鍦ㄥ垵濮嬪寲涔嬪墠锛屽厛dispose鏃х殑瀹炰緥 + if (echarts.getInstanceByDom(document.getElementById("Chart1"))) { + echarts.dispose(document.getElementById("Chart1")); + } + // if (echarts.getInstanceByDom(document.getElementById("Chart2"))) { + // echarts.dispose(document.getElementById("Chart2")); + // } + const myChart1 = echarts.init(document.getElementById("Chart1")); + // const myChart2 = echarts.init(document.getElementById("Chart2")); + listRegion( + proxy.addDateRange({ + ...queryParams.value, + ...query.value, + }) + ).then((res) => { + if (!!res.code && res.code == 200) { + loading.value = false; + let xdata = []; + let yvalue = []; + let ycompareValue = []; + let yqoq = []; + if (!!res.data.chartDataList) { + res.data.chartDataList.map((item) => { + xdata.push( + proxy + .dayjs(item.xdata) + .format( + queryParams.value.timeType == "YEAR" + ? "MM鏈�" + : queryParams.value.timeType == "MONTH" + ? "DD鏃�" + : "HH鏃�" + ) + ); + yvalue.push(!!item.yvalue ? item.yvalue : 0); + ycompareValue.push(!!item.ycompareValue ? item.ycompareValue : 0); + yqoq.push(!!item.yqoq ? item.yqoq : 0); + }); + } + setTimeout(() => { + myChart1.setOption({ + color: ["#2979ff", "#19be6b", "#ff9900", "#fa3534"], + grid: { + top: "45", + left: "7%", + right: "5%", + bottom: "10", + containLabel: true, + }, + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + legend: { + icon: "rect", + itemWidth: 14, + itemHeight: 10, + textStyle: { + color: + settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + }, + }, + xAxis: { + type: "category", + axisPointer: { + type: "shadow", + }, + axisLine: { + show: true, + lineStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + axisTick: { + show: false, + }, + splitArea: { + show: false, + }, + splitLine: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" ? "#FFFFFF" : "#222222", + fontSize: 14, + padding: [5, 0, 0, 0], + // formatter: '{value} ml' + }, + data: xdata, + }, + yAxis: [ + { + type: "value", + name: + "鑰�" + + queryParams.value.enername + + "閲�(" + + queryParams.value.muid + + ")", + nameTextStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + padding: [0, 0, 5, 0], + }, + axisLine: { + show: false, + }, + splitLine: { + show: true, + lineStyle: { + type: "dashed", + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + axisTick: { + show: false, + }, + splitArea: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + }, + }, + { + type: "value", + name: queryParams.value.analysisType == "YOY" ? "鍚屾瘮(%)" : "鐜瘮(%)", + alignTicks: true, + nameTextStyle: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + padding: [0, 0, 5, 0], + }, + axisLine: { + show: false, + }, + axisTick: { + show: false, + }, + splitLine: { + show: true, + lineStyle: { + type: "dashed", + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + }, + }, + splitArea: { + show: false, + }, + axisLabel: { + color: + settingsStore.sideTheme == "theme-dark" + ? "#FFFFFF" + : "#222222", + fontSize: 14, + }, + }, + ], + series: [ + { + name: "鏈湡鍊�", + type: "bar", + barWidth: "8", + tooltip: { + valueFormatter: function (value) { + return value + queryParams.value.muid; + }, + }, + itemStyle: { + borderRadius: [15, 15, 0, 0], + }, + data: yvalue, + markPoint: { + data: [ + { type: "max", name: "Max" }, + { type: "min", name: "Min" }, + ], + }, + }, + { + name: "鍚屾湡鍊�", + type: "bar", + barWidth: "8", + tooltip: { + valueFormatter: function (value) { + return value + queryParams.value.muid; + }, + }, + itemStyle: { + borderRadius: [15, 15, 0, 0], + }, + data: ycompareValue, + markPoint: { + data: [ + { type: "max", name: "Max" }, + { type: "min", name: "Min" }, + ], + }, + }, + { + name: queryParams.value.analysisType == "YOY" ? "鍚屾瘮" : "鐜瘮", + type: "line", + yAxisIndex: 1, + symbol: "none", // 璁剧疆涓� 'none' 鍘绘帀鍦嗙偣 + tooltip: { + valueFormatter: function (value) { + return value + "%"; + }, + }, + data: yqoq, + }, + ], + }); + }, 100); + departmentList.value = !!res.data.dataList ? res.data.dataList : []; + window.addEventListener( + "resize", + () => { + myChart1.resize(); + }, + { passive: true } + ); + } + }); + +} +// 鑳借�楀姣斿垎鏋�-绉戝鑳借�楀垎鏋�-鎼滅储 +function handleQuery() { + getList(); +} + +</script> +<style scoped lang="scss"> +@import "@/assets/styles/page.scss"; +</style> diff --git a/zhitan-vue/vite.config.js b/zhitan-vue/vite.config.js index dcba260..e512399 100644 --- a/zhitan-vue/vite.config.js +++ b/zhitan-vue/vite.config.js @@ -4,7 +4,9 @@ // https://vitejs.dev/config/ export default defineConfig(({ mode, command }) => { + mode='production' const env = loadEnv(mode, process.cwd()) + console.log(mode,'==========env') const { VITE_APP_ENV } = env return { // 閮ㄧ讲鐢熶骇鐜鍜屽紑鍙戠幆澧冧笅鐨刄RL銆� -- Gitblit v1.9.3