123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790 |
- <template>
- <div class="dataAnalysisSpaceAna" :class="!theme ? 'themeDark' : 'themeLight'">
- <div class="dataAnalysisSpaceAnaMain">
- <div class="main_top">
- <p class="topPsty">毛容量分析</p>
- </div>
- <div class="main">
- <div class="treeDataMain">
- <tree-cop :data="treeData" @checkChange="funTreeCheckChange" :show-checkbox="false"
- :height="treeHeight" @currentChange="funCurrentChange" @refresh="funGetTree">
- </tree-cop>
- </div>
- <div class="excelDataMain">
- <excel-cop :checkIds="excelCheckIds" :showCheckbox="false" :data="excelList" :height="excelHeight"
- :theme="theme" @excelChange="funExcelChange" @checkChange="funExcelCheckChange"></excel-cop>
- </div>
- <div class="tableDataMain">
- <div :style="{ height: tableHeight }">
- <div style="height: 49%">
- <el-icon :style="!theme ? 'color: #fff' : ''" class="chartIcon" size="18"
- @click="funActCop({xAxis:barxAxis, yAxis:baryAxis, series: barSeries}, 'barChartCop')">
- <ZoomIn />
- </el-icon>
- <bar-chart-cop width="100%" height="100%" :subtext="`${windName} 平均风速 ${avgSpeed}`"
- :theme="theme" :echartsTheme="echartsTheme" :xAxis="barxAxis" :yAxis="baryAxis"
- :series="barSeries"></bar-chart-cop>
- </div>
- <div style="height: 49%">
- <el-icon :style="!theme ? 'color: #fff' : ''" class="chartIcon" size="18"
- @click="funActCop({xAxis:linexAxis, yAxis:lineyAxis, series: lineSeries}, 'lineChartCop')">
- <ZoomIn />
- </el-icon>
- <bar-chart-cop width="100%" height="100%" :subtext="`${windName} 平均毛容量系数 ${avgMrxs}`"
- :theme="theme" :echartsTheme="echartsTheme" :xAxis="linexAxis" :yAxis="lineyAxis"
- :series="lineSeries"></bar-chart-cop>
- </div>
- </div>
- </div>
- </div>
- </div>
- <el-dialog custom-class="windLifeDialog" draggable width="80%" v-model="dialog" :title="actDiaTitle">
- <el-form class="whitespace-nowrap" :inline="true" :model="queryForm">
- <el-form-item label="" class="!mb-0">
- <el-select v-model="queryForm.checkIds" clearable @clear="checkAll = false" collapse-tags multiple>
- <el-option label="全选" :class="{'selected': checkAll}" @click="funCheckAll"></el-option>
- <el-option v-for="item in chartExcelList" :key="item.id" :value="item.id" :label="item.name">
- </el-option>
- </el-select>
- </el-form-item>
- <el-form-item class="!mb-0">
- <submit-btn desc="查询" @click="funDiaSubmit"></submit-btn>
- <submit-btn desc="导出" @click="funDiaExport"></submit-btn>
- </el-form-item>
- </el-form>
- <div v-loading="exportLoading">
- <el-row ref="diaPanelRef" style="height: 650px;overflow-y:auto;over-x:hidden">
- <el-col :span="actCopList.length > 1 ? 12 : 24" v-for="item in actCopList" :key="item.id"
- style="height: 650px">
- <component :is="item.actCop" width="100%" height="100%" :xAxis="item.xAxis"
- :subtext="item.subtext" :title="item.title" :series="item.series"
- :isDiaAlone="(actCopList.length === 1)" @dblclick="funDbClick(item)" :yAxis="item.yAxis"
- :dataset="item.dataset" :brush="item.isBrush" :theme="theme" :echartsTheme="echartsTheme"
- @getSelected="funChartSelect"></component>
- </el-col>
- </el-row>
- </div>
- </el-dialog>
- </div>
- </template>
- <script setup name="rateAnalysis">
- import excelCop from '@/components/generatingCapacityComponent/excel.vue'
- import treeCop from '@/components/generatingCapacityComponent/tree.vue'
- import barChartCop from './components/barChart.vue'
- import {
- onMounted,
- ref,
- onActivated,
- shallowRef,
- reactive,
- nextTick,
- watch
- } from 'vue'
- import {
- useStore
- } from 'vuex';
- import httpRequest from '@/utils/request.js'
- import tools from '@tools/htmlToPdf.js'
- /**配置参数 */
- const treeHeight = ref(window.innerHeight - 125 + 'px') //tree高度
- const excelHeight = ref(window.innerHeight - 125 + 'px') //excel高度
- const tableHeight = ref(window.innerHeight - 125 + 'px')
- /**excel 开始 */
- const excelCheckIds = ref([])
- const excelList = ref([])
- /** 额定功率 */
- const powerproduction = ref("")
- //点击excel项时
- const funExcelChange = async (obj) => {
- excelCheckIds.value = [obj.id] //当为单选展示风机图表时
- chartExcelList.value = excelList.value.map(o => {
- return {
- ...o,
- name: o.windturbine
- }
- }) // 选中excel当前项时, excel列表赋值给dialog 下拉框
- queryForm.checkIds = excelList.value.map(o => o.id)
- checkAll.value = true
- funSubmit()
- }
- const funExcelCheckChange = ({
- checkArr,
- data
- }) => {
- excelCheckIds.value = checkArr
- }
- /**tree 开始 */
- const treeData = ref([])
- const actTreeNode = ref(null)
- const funRepeatMap = (arr) => {
- return arr.map(o => {
- if (o.children) {
- const findIndex = o.children.findIndex(p => !!p.type)
- if (findIndex !== -1) {
- o.childs = o.children
- o.children = []
- if (!actTreeNode.value) {
- actTreeNode.value = o
- }
- }
- }
- return {
- ...o,
- children: o.children.length ? funRepeatMap(o.children) : []
- }
- })
- }
- const funGetTree = async () => {
- const res = await httpRequest.get("/power/process/tree")
- actTreeNode.value = null
- excelList.value = []
- treeData.value = funRepeatMap(res.data)
- if (actTreeNode.value) {
- funCurrentChange({
- current: actTreeNode.value,
- currentNode: null
- })
- funExcelChange({
- id: actTreeNode.value.childs[0].id
- })
- }
- }
- const funTreeCheckChange = ({
- current,
- checkedNodes,
- checkedKeys,
- halfCheckedNodes,
- halfCheckedKeys
- }) => { //tree change -> excel change
- funCurrentChange({
- current,
- currentNode: ''
- })
- const checkIds = []
- if (checkedNodes.length) {
- for (const node of checkedNodes) {
- if (node.childs && node.childs.length) {
- for (const child of node.childs) {
- checkIds.push(child.id)
- }
- }
- }
- }
- excelCheckIds.value = checkIds
- }
- const funCurrentChange = ({
- current,
- currentNode
- }) => {
- if (current.childs) {
- excelList.value = current.childs.map(o => {
- return {
- id: o.id,
- interval: o.interval,
- path: o.path,
- prepareid: o.prepareid,
- station: o.station,
- time: o.time,
- type: o.type,
- windturbine: o.windturbine,
- name: o.path.substring(o.path.indexOf(o.station + '_') + (o.station + '_').length)
- }
- })
- if (excelList.value.length > 0) {
- funExcelChange(excelList.value[0])
- }
- } else {
- excelList.value = []
- }
- }
- /**chart */
- let chartId = 1
- const powerproductionNum = ref(0)
- const avgSpeed = ref('')
- const avgMrxs = ref('')
- const windName = ref('')
- /**submit */
- const funSubmit = async () => {
- const tempRes = await httpRequest.get('/wind/avg/speed', {
- params: {
- ids: excelCheckIds.value.join(','),
- }
- })
- if (tempRes.code === 200) {
- if (tempRes.data.length) {
- for (const chart of tempRes.data) {
- chart.currentData.sort((a, b) => {
- return new Date(a.time).getTime() - new Date(b.time).getTime()
- })
- chart.preData.sort((a, b) => {
- return new Date(a.time).getTime() - new Date(b.time).getTime()
- })
- let xAxisData = [],
- barData1 = [],
- barData2 = [],
- lineData1 = [],
- lineData2 = []
- let avgSpeedSum = 0,
- avgMrxsSum = 0
- chart.currentData.forEach(current => {
- xAxisData.push(current.time)
- barData1.push(current.avgspeed)
- avgSpeedSum += current.avgspeed
- avgMrxsSum += current.mrxs
- lineData1.push((current.mrxs * 100).toFixed(2))
- });
- chart.preData.forEach(current => {
- xAxisData.push(current.time)
- barData2.push(current.avgspeed)
- lineData2.push((current.mrxs * 100).toFixed(2))
- });
- avgSpeed.value = (avgSpeedSum / barData1.length).toFixed(2) + ' m/s'
- avgMrxs.value = (avgMrxsSum / lineData1.length * 100).toFixed(2) + ' %'
- // windName.value = chart.wtId
- windName.value = chart.code
- barxAxis.data = xAxisData
- linexAxis.data = xAxisData
- barSeries[0].data = barData1
- barSeries[1].data = barData2
- chartId++
- lineSeries[0].data = lineData1
- lineSeries[1].data = lineData2
- chartId++
- }
- }
- }
- }
- /**lineChart */
- const linexAxis = reactive({
- type: 'category',
- name: '月',
- data: [],
- splitLine: {
- show: false
- },
- axisTick: {
- show: true
- },
- axisLine: {
- onZero: false
- }
- })
- const lineyAxis = reactive({
- type: 'value',
- name: '%',
- splitLine: {
- show: false
- },
- axisTick: {
- show: true
- },
- axisLine: {
- onZero: false
- }
- })
- const lineSeries = reactive([{
- name: "最新",
- type: "line",
- data: [],
- symbol: "line", //设定为实心点
- symbolSize: 0, //设定实心点的大小
- markLine: {
- symbol: 'none',
- label: {
- show: true,
- },
- lineStyle: {
- color: '#F72C5B'
- },
- data: []
- }
- }, {
- name: "历史",
- type: "line",
- data: [],
- symbol: "line", //设定为实心点
- symbolSize: 0, //设定实心点的大小
- markLine: {
- symbol: 'none',
- label: {
- show: false,
- },
- lineStyle: {
- color: '#F72C5B'
- },
- data: []
- }
- }])
- // 圈选散点触发函数
- const funChartSelect = async (batch) => {
- const wDataArr = []
- const yDataArr = []
- let scatterls = []
- let dataSetObj = []
- wtData.value = []
- if (batch.length && actCopList.value[0].dataset) {
- scatterls = batch[0].selected[1].dataIndex
- if (scatterls.length) {
- dataSetObj = JSON.parse(actCopList.value[0].dataset)
- if (scatterls.length) {
- for (const scatterIndex of scatterls) {
- wDataArr.push(dataSetObj[0].source[scatterIndex].k)
- }
- }
- const wtRes = await httpRequest.get('/power/fitting/filter', {
- params: {
- yk: yDataArr.join(','),
- wk: wDataArr.join(',')
- }
- })
- if (wtRes.code === 200) {
- let id = 1
- const tempArr = [] //用于以风机id 聚合dataArr
- if (wtRes.data.length) {
- for (const data of wtRes.data) {
- if (tempArr.length) {
- const findIndex = tempArr.findIndex(o => o.wtId === data.wtId)
- if (findIndex !== -1) {
- if (!tempArr[findIndex].children) {
- tempArr[findIndex].children = []
- }
- tempArr[findIndex].children.push({
- ...data,
- id: id,
- filter: data.filter === 0 ? '是' : '否'
- })
- id++
- } else {
- tempArr.push({
- ...data,
- id: id,
- filter: data.filter === 0 ? '是' : '否'
- })
- id++
- }
- } else {
- tempArr.push({
- ...data,
- id: id,
- filter: data.filter === 0 ? '是' : '否'
- })
- id++
- }
- }
- wtDialog.value = true
- nextTick(() => {
- wtTab.value = 'table'
- wtData.value = tempArr
- })
- }
- }
- }
- }
- }
- /**barChart */
- const barxAxis = reactive({
- type: 'category',
- name: '月',
- data: [],
- splitLine: {
- show: false
- },
- axisTick: {
- show: true
- },
- axisLine: {
- onZero: false
- }
- })
- const baryAxis = reactive({
- type: 'value',
- name: 'm/s',
- splitLine: {
- show: false
- },
- axisTick: {
- show: true
- },
- axisLine: {
- onZero: false
- }
- })
- const barSeries = reactive([{
- name: "机舱风速(最近)",
- type: "line",
- symbol: "line", //设定为实心点
- symbolSize: 0, //设定实心点的大小
- data: [],
- markLine: {
- symbol: 'none',
- label: {
- show: true,
- },
- lineStyle: {
- color: '#F72C5B'
- },
- data: []
- }
- }, {
- name: "机舱风速(历史)",
- type: "line",
- symbol: "line", //设定为实心点
- symbolSize: 0, //设定实心点的大小
- data: [],
- markLine: {
- symbol: 'none',
- label: {
- show: false,
- },
- lineStyle: {
- color: '#F72C5B'
- },
- data: []
- }
- }])
- /**dialog 数据 */
- const wtDialog = ref(false)
- const wtData = ref([])
- const wtTab = ref('table')
- /**dialog */
- const dialog = ref(false)
- const actChartName = ref('')
- const actDiaTitle = ref('')
- const diaPanelRef = ref()
- const exportLoading = ref(false)
- const actCopList = ref([
- // {
- // xAxis: [],
- // subtext: '',
- // title: '',
- // isRadar: false,
- // series: [],
- // yAxis: [],
- // dataset: []
- // }
- ])
- // 作为actCopList的备份 在actCopList赋值多个时 同时赋值, 在dialog弹出时清空. 作用: 在actCopList变化时, 重新赋值原始数据
- const actCopListBak = ref([])
- const checkAll = ref(true)
- const queryForm = reactive({
- checkIds: []
- })
- const funCheckAll = () => {
- checkAll.value = !checkAll.value
- if (checkAll.value) {
- queryForm.checkIds = chartExcelList.value.map(o => o.id)
- } else {
- queryForm.checkIds = []
- }
- }
- const chartExcelList = ref([]) //dialog 下拉项
- const funActCop = (obj, type) => {
- switch (type) {
- case 'barChartCop':
- actChartName.value = 'barChartCop'
- obj.actCop = shallowRef(barChartCop)
- actDiaTitle.value = '风速'
- break
- case 'lineChartCop':
- actChartName.value = 'lineChartCop'
- obj.actCop = shallowRef(barChartCop)
- actDiaTitle.value = '毛容量系数'
- break
- // case 'CurrentScatterChartCop':
- // actChartName.value = 'CurrentScatterChartCop'
- // obj.actCop = shallowRef(CurrentScatte // console.log(res)rChartCop)
- // actDiaTitle.value = '静态偏航对风分析图'
- // break
- }
- obj.isBrush = false
- obj.id = chartId
- chartId++
- dialog.value = true
- actCopListBak.value = []
- nextTick(() => {
- actCopList.value = [obj]
- })
- }
- const funDiaSubmit = async () => {
- let url = ''
- switch (actChartName.value) {
- case 'barChartCop':
- url = '/wind/avg/speed'
- break
- case 'lineChartCop':
- url = '/wind/avg/speed'
- break
- // case 'CurrentScatterChartCop':
- // url = '' //暂无接口
- // break
- }
- if (url) {
- const res = await httpRequest.get(url, {
- params: {
- ids: queryForm.checkIds.join(','),
- mode: 0
- }
- })
- if (res.code === 200) {
- actCopList.value = []
- actCopListBak.value = [] //清空备份
- if (res.data.length) {
- for (const chart of res.data) {
- chart.currentData.sort((a, b) => {
- return new Date(a.time).getTime() - new Date(b.time).getTime()
- })
- chart.preData.sort((a, b) => {
- return new Date(a.time).getTime() - new Date(b.time).getTime()
- })
- const xAxisData = [],
- barData1 = [],
- barData2 = [],
- lineData1 = [],
- lineData2 = []
- let avgSpeedSum = 0,
- avgMrxsSum = 0
- let avgSpeedDesc = '',
- avgMrxsDesc = ''
- for (const current of chart.currentData) {
- xAxisData.push(current.time)
- barData1.push(current.avgspeed)
- avgSpeedSum += current.avgspeed
- avgMrxsSum += current.mrxs
- lineData1.push((current.mrxs * 100).toFixed(2))
- }
- for (const current of chart.preData) {
- barData2.push(current.avgspeed)
- lineData2.push((current.mrxs * 100).toFixed(2))
- }
- avgSpeedDesc = (avgSpeedSum / barData1.length).toFixed(2) + ' m/s'
- avgMrxsDesc = (avgMrxsSum / lineData1.length * 100).toFixed(2) + ' %'
- if (actChartName.value === 'barChartCop') {
- actCopList.value.push({
- id: chartId,
- isBrush: false,
- actCop: shallowRef(barChartCop),
- // title: chart.windturbine,
- subtext: `${chart.wtId} 平均风速 ${avgSpeedDesc}`,
- xAxis: {
- ...barxAxis,
- data: xAxisData
- },
- yAxis: baryAxis,
- series: [{
- ...barSeries[0],
- data: barData1
- }, {
- ...barSeries[1],
- data: barData2
- }]
- })
- chartId++
- }
- if (actChartName.value === 'lineChartCop') {
- actCopList.value.push({
- id: chartId,
- isBrush: false,
- actCop: shallowRef(barChartCop),
- // title: chart.windturbine,
- subtext: `${chart.wtId} 平均毛容量系数 ${avgMrxsDesc}`,
- xAxis: {
- ...linexAxis,
- data: xAxisData
- },
- yAxis: lineyAxis,
- series: [{
- ...lineSeries[0],
- data: lineData1
- }, {
- ...lineSeries[1],
- data: lineData2
- }]
- })
- chartId++
- }
- }
- actCopListBak.value = actCopList.value
- }
- }
- }
- }
- const funDiaExport = () => {
- exportLoading.value = true
- tools.scrollToPDF(diaPanelRef.value, actDiaTitle.value, () => {
- exportLoading.value = false
- })
- }
- const funDbClick = (obj) => {
- if (actCopListBak.value.length > 1) { //判断大于1时, 才有双击放大功能
- if (actCopList.value.length === 1) {
- actCopList.value = actCopListBak.value
- } else {
- actCopList.value = [obj]
- }
- }
- }
- /**created */
- // funGetTree()
- const theme = ref(null)
- const echartsTheme = ref('')
- const store = useStore()
- watch(() => store.state.theme, (newVal, oldVal) => {
- theme.value = newVal
- echartsTheme.value = !newVal ? 'dark' : ''
- funGetTree()
- }, {
- deep: true
- })
- /**activated */
- onMounted(() => {
- //test
- // funSubmit()
- //
- funGetTree()
- theme.value = store.state.theme
- echartsTheme.value = !theme.value ? 'dark' : ''
- tableHeight.value = window.innerHeight - 125 + 'px'
- excelHeight.value = (window.innerHeight - 125) + 'px'
- treeHeight.value = (window.innerHeight - 125) + 'px'
- window.addEventListener('resize', () => {
- tableHeight.value = window.innerHeight - 125 + 'px'
- excelHeight.value = (window.innerHeight - 125) + 'px'
- treeHeight.value = (window.innerHeight - 125) + 'px'
- })
- })
- onActivated(() => {
- // funGetTree()
- })
- </script>
- <style lang="less" scoped>
- .dataAnalysisSpaceAna {
- height: 100%;
- .dataAnalysisSpaceAnaMain {
- height: 100%;
- .main_top {
- height: 40px;
- display: flex;
- align-items: center;
- .topPsty {
- position: relative;
- top: 5px;
- padding: 7px 20px;
- font-size: 12px;
- font-weight: 600;
- margin-left: 10px;
- border-radius: 3px;
- }
- }
- .main {
- display: flex;
- justify-content: space-between;
- // width: calc(100% - 40px);
- width: 100%;
- .treeDataMain,
- .excelDataMain,
- .tableDataMain {
- padding: 10px;
- border-radius: 10px;
- }
- .treeDataMain {
- width: calc(20% - 20px);
- }
- .excelDataMain {
- width: calc(13% - 20px);
- }
- .tableDataMain {
- width: calc(66% - 20px);
- position: relative;
- .chartIcon {
- cursor: pointer;
- }
- .butten_com {
- position: absolute;
- right: 20px;
- z-index: 111111;
- }
- }
- }
- }
- }
- .themeDark {
- .dataAnalysisSpaceAnaMain {
- .main_top {
- .topPsty {
- color: #1C99FF;
- background: #1E2126;
- }
- }
- .main {
- background: #13171e;
- .treeDataMain {
- background: transparent;
- }
- .excelDataMain {
- background: #313233;
- }
- .tableDataMain {
- margin-top: 5px;
- background: #212223;
- }
- }
- }
- }
- .themeLight {
- padding: 0;
- .dataAnalysisSpaceAnaMain {
- .main_top {
- .topPsty {
- color: #2778FF;
- background: #FFFFFF;
- }
- }
- .main {
- background: #E6E8F2;
- .treeDataMain {
- background: transparent;
- }
- .excelDataMain {
- background: #F4F6FB;
- }
- .tableDataMain {
- background: #fff;
- margin-top: 5px;
- }
- }
- }
- }
- </style>
|