index.vue 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. <template>
  2. <div class="rateAnalysis" :class="!theme ? 'themeDark' : 'themeLight'">
  3. <div class="rateAnalysisMain">
  4. <div class="main_top">
  5. <p class="topPsty">对风偏差分析</p>
  6. </div>
  7. <div class="main">
  8. <div class="treeDataMain">
  9. <tree-cop :data="treeData" @checkChange="funTreeCheckChange" :show-checkbox="false"
  10. :height="treeHeight" @currentChange="funCurrentChange" @refresh="funGetTree">
  11. </tree-cop>
  12. </div>
  13. <div class="excelDataMain">
  14. <excel-cop :checkIds="excelCheckIds" :showCheckbox="false" :data="excelList" :height="excelHeight"
  15. @excelChange="funExcelChange" @checkChange="funExcelCheckChange" :theme="theme"></excel-cop>
  16. </div>
  17. <div class="tableDataMain">
  18. <el-row :style="{ height: tableHeight }">
  19. <el-col :span="12" v-for="(item, index) in chartData" :key="item.id" style="height: 45%">
  20. <el-icon :style="!theme ? 'color: #fff' : ''" size="18"
  21. @click="funActCop(item, 'chartCop' + (index + 1))">
  22. <ZoomIn />
  23. </el-icon>
  24. <chart-cop class="" height="100%" width="100%" :xAxis="item.xAxis" :isRadar="item.isRadar"
  25. :theme="theme" :echartsTheme="echartsTheme" :subtext="item.subtext" :title="item.title"
  26. :series="item.series">
  27. </chart-cop>
  28. </el-col>
  29. <el-col :span="12" v-if="!!lineSeries.length" style="height: 50%">
  30. <el-icon :style="!theme ? 'color: #fff' : ''" size="18"
  31. @click="funActCop({ xAxis: linexAxis, yAxis: lineyAxis, series: lineSeries, dataset: lineDataSet }, 'lineChartCop')">
  32. <ZoomIn />
  33. </el-icon>
  34. <line-chart-cop class="" height="100%" width="100%" :xAxis="linexAxis" :yAxis="lineyAxis"
  35. :theme="theme" :echartsTheme="echartsTheme" :series="lineSeries" subtext="对风偏差分析图"
  36. :dataset="lineDataSet"></line-chart-cop>
  37. </el-col>
  38. <el-col :span="12" v-if="!!lineSeries.length" style="height: 50%">
  39. <el-icon :style="!theme ? 'color: #fff' : ''" size="18"
  40. @click="funActCop({ xAxis: scatterxData, yAxis: scatteryData, series: scatterSeries }, 'scatterSingleChartCop')">
  41. <ZoomIn />
  42. </el-icon>
  43. <scatter-single-chart-cop class="" height="95%" width="100%" :xAxis="scatterxData"
  44. :theme="theme" :echartsTheme="echartsTheme" :yAxis="scatteryData"
  45. :series="scatterSeries" subtext="静态偏航对风分析图">
  46. </scatter-single-chart-cop>
  47. </el-col>
  48. </el-row>
  49. </div>
  50. </div>
  51. </div>
  52. <el-dialog custom-class="windLifeDialog" v-model="wtDialog" draggable title="风机功率点位">
  53. <el-tabs v-model="wtTab">
  54. <el-tab-pane label="数据" name="table">
  55. <el-table :data="wtData" row-key="id" :max-height="550">
  56. <el-table-column property="wtId" align="center" label="风机" />
  57. <el-table-column property="time" sortable :width="160" align="center" label="时间" />
  58. <el-table-column property="speed" sortable align="center" label="风速(m/s)" />
  59. <el-table-column property="power" sortable align="center" label="功率(kW)" />
  60. <el-table-column property="rr" sortable align="center" label="转速" />
  61. <el-table-column property="filter" sortable align="center" label="是否有用点" />
  62. </el-table>
  63. </el-tab-pane>
  64. <el-tab-pane label="故障" name="problem" disabled>
  65. </el-tab-pane>
  66. <el-tab-pane label="预警" name="warning" disabled>
  67. </el-tab-pane>
  68. </el-tabs>
  69. </el-dialog>
  70. <el-dialog custom-class="windLifeDialog" draggable width="80%" v-model="dialog" :title="actDiaTitle">
  71. <el-form class="whitespace-nowrap" :inline="true" :model="queryForm">
  72. <el-form-item label="" class="!mb-0">
  73. <el-select v-model="queryForm.checkIds" clearable @clear="checkAll = false" collapse-tags multiple>
  74. <el-option label="全选" :class="{'selected': checkAll}" @click="funCheckAll"></el-option>
  75. <el-option v-for="item in chartExcelList" :key="item.id" :value="item.id" :label="item.name">
  76. </el-option>
  77. </el-select>
  78. </el-form-item>
  79. <el-form-item class="!mb-0">
  80. <submit-btn desc="查询" @click="funDiaSubmit"></submit-btn>
  81. <submit-btn desc="导出" @click="funDiaExport"></submit-btn>
  82. </el-form-item>
  83. </el-form>
  84. <div v-loading="exportLoading">
  85. <div ref="diaPanelRef" style="height: 650px">
  86. <component :is="item.actCop" :width="actCopList.length > 1 ? '50%' : '100%'" height="100%"
  87. v-for="item in actCopList" :key="item.id" :xAxis="item.xAxis" :subtext="item.subtext"
  88. :isRadar="item.isRadar" :title="item.title" :series="item.series" :theme="theme"
  89. :echartsTheme="echartsTheme" :isDiaAlone="(actCopList.length === 1)"
  90. @dblclick="funDbClick(item)" :yAxis="item.yAxis" :dataset="item.dataset" :brush="item.isBrush"
  91. @getSelected="funChartSelect"></component>
  92. </div>
  93. </div>
  94. </el-dialog>
  95. </div>
  96. </template>
  97. <script setup name="rateAnalysis">
  98. import excelCop from '@/components/generatingCapacityComponent/excel.vue'
  99. import treeCop from '@/components/generatingCapacityComponent/tree.vue'
  100. import chartCop from './components/chart.vue'
  101. import lineChartCop from './components/lineChart.vue'
  102. // import SubmitBtn from '../../../components/SubmitBtn.vue'
  103. import scatterSingleChartCop from './components/scatterSingleChart.vue'
  104. // import { ElMessage } from 'element-plus';
  105. import {
  106. onMounted,
  107. ref,
  108. onActivated,
  109. shallowRef,
  110. reactive,
  111. nextTick,
  112. watch
  113. } from 'vue'
  114. import {
  115. useStore
  116. } from 'vuex';
  117. import httpRequest from '@/utils/request.js'
  118. import tools from '@tools/htmlToPdf.js'
  119. // import flowerRes from '@/data/flower.json'
  120. // import lineChartRes from '@/data/lineNew.json'
  121. /**配置参数 */
  122. const treeHeight = ref(window.innerHeight - 125 + 'px') //tree高度
  123. const excelHeight = ref(window.innerHeight - 125 + 'px') //excel高度
  124. const tableHeight = ref(window.innerHeight - 125 + 'px')
  125. /**excel 开始 */
  126. const excelCheckIds = ref([])
  127. const excelList = ref([])
  128. //点击excel项时
  129. const funExcelChange = async (obj) => {
  130. excelCheckIds.value = [obj.id] //当为单选展示风机图表时
  131. chartExcelList.value = excelList.value.map(o => {
  132. return {
  133. ...o,
  134. name: o.windturbine
  135. }
  136. }) // 选中excel当前项时, excel列表赋值给dialog 下拉框
  137. queryForm.checkIds = excelList.value.map(o => o.id)
  138. checkAll.value = true
  139. funSubmit()
  140. }
  141. const funExcelCheckChange = ({
  142. checkArr,
  143. data
  144. }) => {
  145. excelCheckIds.value = checkArr
  146. }
  147. /**tree 开始 */
  148. const treeData = ref([])
  149. const actTreeNode = ref(null)
  150. const funRepeatMap = (arr) => {
  151. return arr.map(o => {
  152. if (o.children) {
  153. const findIndex = o.children.findIndex(p => !!p.type)
  154. if (findIndex !== -1) {
  155. o.childs = o.children
  156. o.children = []
  157. if (!actTreeNode.value) {
  158. actTreeNode.value = o
  159. }
  160. }
  161. }
  162. return {
  163. ...o,
  164. children: o.children.length ? funRepeatMap(o.children) : []
  165. }
  166. })
  167. }
  168. const funGetTree = async () => {
  169. const res = await httpRequest.get("/power/process/tree")
  170. actTreeNode.value = null
  171. excelList.value = []
  172. treeData.value = funRepeatMap(res.data)
  173. if (actTreeNode.value) {
  174. funCurrentChange({
  175. current: actTreeNode.value,
  176. currentNode: null
  177. })
  178. funExcelChange({
  179. id: actTreeNode.value.childs[0].id
  180. })
  181. }
  182. }
  183. const funTreeCheckChange = ({
  184. current,
  185. checkedNodes,
  186. checkedKeys,
  187. halfCheckedNodes,
  188. halfCheckedKeys
  189. }) => { //tree change -> excel change
  190. funCurrentChange({
  191. current,
  192. currentNode: ''
  193. })
  194. const checkIds = []
  195. if (checkedNodes.length) {
  196. for (const node of checkedNodes) {
  197. if (node.childs && node.childs.length) {
  198. for (const child of node.childs) {
  199. checkIds.push(child.id)
  200. }
  201. }
  202. }
  203. }
  204. excelCheckIds.value = checkIds
  205. }
  206. const funCurrentChange = ({
  207. current,
  208. currentNode
  209. }) => {
  210. if (current.childs) {
  211. excelList.value = current.childs.map(o => {
  212. return {
  213. id: o.id,
  214. interval: o.interval,
  215. path: o.path,
  216. prepareid: o.prepareid,
  217. station: o.station,
  218. time: o.time,
  219. type: o.type,
  220. windturbine: o.windturbine,
  221. name: o.path.substring(o.path.indexOf(o.station + '_') + (o.station + '_').length)
  222. }
  223. })
  224. } else {
  225. excelList.value = []
  226. }
  227. }
  228. /**chart */
  229. const funText = (index) => {
  230. let str = ''
  231. switch (index) {
  232. case 0:
  233. str = '0-2.5'
  234. break
  235. case 1:
  236. str = '2.5-5'
  237. break
  238. case 2:
  239. str = '5-7.5'
  240. break
  241. case 3:
  242. str = '7.5-10'
  243. break
  244. case 4:
  245. str = '10-12.5'
  246. break
  247. case 5:
  248. str = '12.5-15'
  249. break
  250. case 6:
  251. str = '15-17.5'
  252. break
  253. case 7:
  254. str = '17.5-20'
  255. break
  256. case 8:
  257. str = '20-22.5'
  258. break
  259. case 9:
  260. str = '22.5-25'
  261. break
  262. case 10:
  263. str = '25-inf'
  264. break
  265. }
  266. return str
  267. }
  268. const chartData = ref([]) //roses的chartList
  269. let chartId = 1
  270. /**submit */
  271. const funSubmit = async () => {
  272. const rosesRes = await httpRequest.get('/wind/roses', {
  273. params: {
  274. ids: excelCheckIds.value.join(','),
  275. mode: 0
  276. }
  277. })
  278. const lineRes = await httpRequest.get('/wind/deviation/ratio', {
  279. params: {
  280. ids: excelCheckIds.value.join(','),
  281. mode: 0
  282. }
  283. })
  284. // const rosesRes = flowerRes
  285. // const lineRes = lineChartRes
  286. if (rosesRes.code === 200) {
  287. if (rosesRes.data.length) {
  288. // console.log(rosesRes.data)
  289. chartData.value = []
  290. for (const chart of rosesRes.data) {
  291. chartData.value.push({
  292. id: chartId,
  293. title: '',
  294. subtext: '风速风向玫瑰图',
  295. xAxis: {
  296. type: 'category',
  297. boundaryGap: false,
  298. data: ['N', '', 'N-E', '', 'E', '', 'S-E', '', 'S', '', 'S-W', '', 'W', '',
  299. 'W-N', ''
  300. ],
  301. splitLine: {
  302. show: true
  303. },
  304. },
  305. isRadar: false,
  306. series: chart.roses.length ? chart.roses.map((o, index) => {
  307. return {
  308. type: 'bar',
  309. data: o,
  310. coordinateSystem: 'polar',
  311. name: funText(index),
  312. stack: 'a',
  313. emphasis: {
  314. focus: 'series'
  315. }
  316. }
  317. }) : []
  318. })
  319. chartId++
  320. chartData.value.push({
  321. id: chartId,
  322. title: '',
  323. subtext: '风速风向频次玫瑰图',
  324. isRadar: true,
  325. xAxis: {
  326. type: 'category',
  327. boundaryGap: false,
  328. data: ['N', '', 'N-E', '', 'E', '', 'S-E', '', 'S', '', 'S-W', '', 'W', '',
  329. 'W-N', ''
  330. ],
  331. splitLine: {
  332. show: true
  333. }
  334. },
  335. series: chart.count.length ? [...chart.count.map((o, index) => {
  336. return {
  337. type: 'bar',
  338. data: o,
  339. coordinateSystem: 'polar',
  340. name: funText(index),
  341. stack: 'a',
  342. emphasis: {
  343. focus: 'series'
  344. }
  345. }
  346. }), {
  347. type: 'radar',
  348. // coordinateSystem: 'polar',
  349. tooltip: {
  350. trigger: 'item',
  351. },
  352. // smooth: true,
  353. // areaStyle: {},
  354. name: '对风',
  355. data: [{
  356. value: chart.radar,
  357. }],
  358. }] : []
  359. })
  360. chartId++
  361. scatterSeries.value[0].data = chart.frequency.data.length ? chart.frequency.data.map((
  362. item) => {
  363. return [item[1] + '', item[0] + '', (item[2] * 15).toFixed(1)];
  364. }) : []
  365. scatterSeries.value[0].markLine.data = [{
  366. xAxis: `${chart.frequency.avg}`,
  367. name: `平均偏航:${chart.frequency.avg}度`,
  368. }]
  369. }
  370. }
  371. }
  372. if (lineRes.code === 200) {
  373. if (lineRes.data.length) {
  374. lineDataSet.value[0].source = lineRes.data[0].scatter.map(o => {
  375. return [o.x + '', o.y]
  376. })
  377. lineSeries.value = [{
  378. name: "对风频次",
  379. type: "line",
  380. symbol: "line", //设定为实心点
  381. symbolSize: 0, //设定实心点的大小
  382. smooth: true, //这个是把线变成曲线
  383. data: lineRes.data[0].count,
  384. yAxisIndex: 1,
  385. },
  386. {
  387. type: 'effectScatter',
  388. showEffectOn: "emphasis",
  389. rippleEffect: {
  390. scale: 1
  391. },
  392. legendHoverLink: false,
  393. name: '数据散点',
  394. symbolSize: 5,
  395. datasetIndex: 0,
  396. encode: {
  397. x: 'x',
  398. y: 'y'
  399. },
  400. yAxisIndex: 0,
  401. }
  402. ]
  403. }
  404. }
  405. }
  406. /**lineChart */
  407. const linexAxis = ref({
  408. type: 'category',
  409. data: new Array(101).fill(-50).map((o, index) => Number((o + index).toFixed(1))),
  410. splitLine: {
  411. show: false
  412. },
  413. axisTick: {
  414. show: true
  415. }
  416. })
  417. const lineyAxis = ref([{
  418. type: 'value',
  419. name: 'm/s',
  420. splitLine: {
  421. show: false
  422. },
  423. axisTick: {
  424. show: true
  425. }
  426. }, {
  427. type: 'value',
  428. name: '频次',
  429. splitLine: {
  430. show: false
  431. },
  432. axisTick: {
  433. show: true
  434. }
  435. }])
  436. const lineSeries = ref([])
  437. const lineDataSet = ref([{
  438. source: []
  439. }])
  440. // 圈选散点触发函数
  441. const funChartSelect = async (batch) => {
  442. const wDataArr = []
  443. const yDataArr = []
  444. let scatterls = []
  445. let dataSetObj = []
  446. wtData.value = []
  447. if (batch.length && actCopList.value[0].dataset) {
  448. scatterls = batch[0].selected[1].dataIndex
  449. if (scatterls.length) {
  450. dataSetObj = JSON.parse(actCopList.value[0].dataset)
  451. if (scatterls.length) {
  452. for (const scatterIndex of scatterls) {
  453. wDataArr.push(dataSetObj[0].source[scatterIndex].k)
  454. }
  455. }
  456. const wtRes = await httpRequest.get('/power/fitting/filter', {
  457. params: {
  458. yk: yDataArr.join(','),
  459. wk: wDataArr.join(',')
  460. }
  461. })
  462. if (wtRes.code === 200) {
  463. let id = 1
  464. const tempArr = [] //用于以风机id 聚合dataArr
  465. if (wtRes.data.length) {
  466. for (const data of wtRes.data) {
  467. if (tempArr.length) {
  468. const findIndex = tempArr.findIndex(o => o.wtId === data.wtId)
  469. if (findIndex !== -1) {
  470. if (!tempArr[findIndex].children) {
  471. tempArr[findIndex].children = []
  472. }
  473. tempArr[findIndex].children.push({
  474. ...data,
  475. id: id,
  476. filter: data.filter === 0 ? '是' : '否'
  477. })
  478. id++
  479. } else {
  480. tempArr.push({
  481. ...data,
  482. id: id,
  483. filter: data.filter === 0 ? '是' : '否'
  484. })
  485. id++
  486. }
  487. } else {
  488. tempArr.push({
  489. ...data,
  490. id: id,
  491. filter: data.filter === 0 ? '是' : '否'
  492. })
  493. id++
  494. }
  495. }
  496. wtDialog.value = true
  497. nextTick(() => {
  498. wtTab.value = 'table'
  499. wtData.value = tempArr
  500. })
  501. }
  502. }
  503. }
  504. }
  505. }
  506. /**scatter chart */
  507. const scatterxData = ref([{
  508. type: 'category',
  509. name: '度',
  510. data: new Array(61).fill(-30).map((o, index) => Number((o + index))),
  511. boundaryGap: false,
  512. splitLine: {
  513. show: true
  514. },
  515. axisLine: {
  516. show: true
  517. }
  518. }])
  519. const scatteryData = ref([{
  520. type: 'category',
  521. data: [5, 6, 7, 8, 9, 10],
  522. axisLine: {
  523. show: false
  524. },
  525. name: 'm/s',
  526. splitLine: {
  527. show: false
  528. },
  529. }, ])
  530. const scatterSeries = ref(
  531. [{
  532. name: '对风偏航',
  533. type: 'scatter',
  534. symbolSize: function (val) {
  535. return val[2];
  536. },
  537. data: [],
  538. markLine: {
  539. symbol: 'none',
  540. label: {
  541. show: false,
  542. },
  543. lineStyle: {
  544. color: '#F72C5B',
  545. width: '3',
  546. },
  547. data: [{
  548. // yAxis: powerproductionNum.value,
  549. }]
  550. },
  551. animationDelay: function (idx) {
  552. return idx * 5;
  553. }
  554. }]
  555. )
  556. /**dialog 数据 */
  557. const wtDialog = ref(false)
  558. const wtData = ref([])
  559. const wtTab = ref('table')
  560. /**dialog */
  561. const dialog = ref(false)
  562. const actChartName = ref('')
  563. const actDiaTitle = ref('')
  564. const diaPanelRef = ref()
  565. const exportLoading = ref(false)
  566. const actCopList = ref([
  567. // {
  568. // xAxis: [],
  569. // subtext: '',
  570. // title: '',
  571. // isRadar: false,
  572. // series: [],
  573. // yAxis: [],
  574. // dataset: []
  575. // }
  576. ])
  577. // 作为actCopList的备份 在actCopList赋值多个时 同时赋值, 在dialog弹出时清空. 作用: 在actCopList变化时, 重新赋值原始数据
  578. const actCopListBak = ref([])
  579. const checkAll = ref(true)
  580. const queryForm = reactive({
  581. checkIds: []
  582. })
  583. const funCheckAll = () => {
  584. checkAll.value = !checkAll.value
  585. if (checkAll.value) {
  586. queryForm.checkIds = chartExcelList.value.map(o => o.id)
  587. } else {
  588. queryForm.checkIds = []
  589. }
  590. }
  591. const chartExcelList = ref([]) //dialog 下拉项
  592. const funActCop = (obj, type) => {
  593. switch (type) {
  594. case 'chartCop1':
  595. actChartName.value = 'chartCop1'
  596. obj.actCop = shallowRef(chartCop)
  597. actDiaTitle.value = '风速风向玫瑰图'
  598. break
  599. case 'chartCop2':
  600. actChartName.value = 'chartCop2'
  601. obj.actCop = shallowRef(chartCop)
  602. actDiaTitle.value = '风速风向频次玫瑰图'
  603. break
  604. case 'lineChartCop':
  605. actChartName.value = 'lineChartCop'
  606. obj.actCop = shallowRef(lineChartCop)
  607. actDiaTitle.value = '对风偏差分析图'
  608. break
  609. case 'scatterSingleChartCop':
  610. actChartName.value = 'scatterSingleChartCop'
  611. obj.actCop = shallowRef(scatterSingleChartCop)
  612. actDiaTitle.value = '静态偏航对风分析图'
  613. break
  614. }
  615. obj.isBrush = type === 'lineChartCop' ? false : false
  616. obj.id = chartId
  617. chartId++
  618. dialog.value = true
  619. actCopListBak.value = []
  620. nextTick(() => {
  621. actCopList.value = [obj]
  622. })
  623. }
  624. const funDiaSubmit = async () => {
  625. let url = ''
  626. switch (actChartName.value) {
  627. case 'chartCop1':
  628. url = '/wind/roses'
  629. break
  630. case 'chartCop2':
  631. url = '/wind/roses'
  632. break
  633. case 'lineChartCop':
  634. url = '/wind/deviation/ratio'
  635. break
  636. case 'scatterSingleChartCop':
  637. url = '/wind/roses'
  638. break
  639. }
  640. if (url) {
  641. const res = await httpRequest.get(url, {
  642. params: {
  643. ids: queryForm.checkIds.join(','),
  644. mode: 0
  645. }
  646. })
  647. if (res.code === 200) {
  648. actCopList.value = []
  649. actCopListBak.value = [] //清空备份
  650. if (res.data.length) {
  651. for (const chart of res.data) {
  652. if (actChartName.value === 'chartCop1') {
  653. actCopList.value.push({
  654. id: chartId,
  655. isBrush: false,
  656. actCop: shallowRef(chartCop),
  657. title: chart.wt,
  658. subtext: '风速风向玫瑰图',
  659. xAxis: {
  660. type: 'category',
  661. boundaryGap: false,
  662. data: ['N', '', 'N-E', '', 'E', '', 'S-E', '', 'S', '', 'S-W', '',
  663. 'W', '', 'W-N', ''
  664. ],
  665. splitLine: {
  666. show: true
  667. },
  668. },
  669. isRadar: false,
  670. series: chart.roses.length ? chart.roses.map((o, index) => {
  671. return {
  672. type: 'bar',
  673. data: o,
  674. coordinateSystem: 'polar',
  675. name: funText(index),
  676. stack: 'a',
  677. emphasis: {
  678. focus: 'series'
  679. }
  680. }
  681. }) : []
  682. })
  683. chartId++
  684. }
  685. if (actChartName.value === 'chartCop2') {
  686. actCopList.value.push({
  687. id: chartId,
  688. isBrush: false,
  689. actCop: shallowRef(chartCop),
  690. title: chart.wt,
  691. subtext: '风速风向频次玫瑰图',
  692. xAxis: {
  693. type: 'category',
  694. boundaryGap: false,
  695. data: ['N', '', 'N-E', '', 'E', '', 'S-E', '', 'S', '', 'S-W', '',
  696. 'W', '', 'W-N', ''
  697. ],
  698. splitLine: {
  699. show: true
  700. }
  701. },
  702. isRadar: true,
  703. series: chart.count.length ? [...chart.count.map((o, index) => {
  704. return {
  705. type: 'bar',
  706. data: o,
  707. coordinateSystem: 'polar',
  708. name: funText(index),
  709. stack: 'a',
  710. emphasis: {
  711. focus: 'series'
  712. }
  713. }
  714. }), {
  715. type: 'radar',
  716. // coordinateSystem: 'polar',
  717. tooltip: {
  718. trigger: 'item'
  719. },
  720. // smooth: true,
  721. // areaStyle: {},
  722. name: '对风',
  723. data: [{
  724. value: chart.radar,
  725. }],
  726. }] : []
  727. })
  728. chartId++
  729. }
  730. if (actChartName.value === 'lineChartCop') {
  731. actCopList.value.push({
  732. id: chartId,
  733. isBrush: false,
  734. actCop: shallowRef(lineChartCop),
  735. title: chart.wtId,
  736. subtext: '对风偏差分析图',
  737. xAxis: linexAxis.value,
  738. yAxis: lineyAxis.value,
  739. dataset: [{
  740. source: chart.scatter.map(o => {
  741. return [o.x + '', o.y]
  742. })
  743. }],
  744. isRadar: false,
  745. series: [{
  746. name: "对风频次",
  747. type: "line",
  748. symbol: "line", //设定为实心点
  749. symbolSize: 0, //设定实心点的大小
  750. smooth: true, //这个是把线变成曲线
  751. data: chart.count,
  752. yAxisIndex: 1,
  753. },
  754. {
  755. type: 'effectScatter',
  756. showEffectOn: "emphasis",
  757. rippleEffect: {
  758. scale: 1
  759. },
  760. legendHoverLink: false,
  761. name: '数据散点',
  762. symbolSize: 5,
  763. datasetIndex: 0,
  764. encode: {
  765. x: 'x',
  766. y: 'y'
  767. },
  768. yAxisIndex: 0,
  769. }
  770. ]
  771. })
  772. chartId++
  773. }
  774. if (actChartName.value === 'scatterSingleChartCop') {
  775. actCopList.value.push({
  776. id: chartId,
  777. isBrush: false,
  778. actCop: shallowRef(scatterSingleChartCop),
  779. title: chart.wt,
  780. subtext: '静态偏航对风分析图',
  781. xAxis: scatterxData.value,
  782. yAxis: scatteryData.value,
  783. isRadar: false,
  784. series: [{
  785. name: '对风偏航',
  786. type: 'scatter',
  787. symbolSize: function (val) {
  788. return val[2];
  789. },
  790. markLine: {
  791. symbol: 'none',
  792. label: {
  793. show: false,
  794. },
  795. lineStyle: {
  796. color: '#F72C5B',
  797. width: '3'
  798. },
  799. data: [{
  800. name: `平均偏航:${chart.frequency.avg}度`,
  801. xAxis: `${chart.frequency.avg}`,
  802. }]
  803. },
  804. data: chart.frequency.data.length ? chart.frequency.data
  805. .map((item) => {
  806. return [item[1] + '', item[0] + '', (item[2] *
  807. 15).toFixed(1)];
  808. }) : [],
  809. animationDelay: function (idx) {
  810. return idx * 5;
  811. }
  812. }]
  813. })
  814. chartId++
  815. }
  816. }
  817. actCopListBak.value = actCopList.value
  818. }
  819. }
  820. }
  821. }
  822. const funDiaExport = () => {
  823. exportLoading.value = true
  824. tools.scrollToPDF(diaPanelRef.value, actDiaTitle.value, () => {
  825. exportLoading.value = false
  826. })
  827. }
  828. const funDbClick = (obj) => {
  829. if (actCopListBak.value.length > 1) { //判断大于1时, 才有双击放大功能
  830. if (actCopList.value.length === 1) {
  831. actCopList.value = actCopListBak.value
  832. } else {
  833. actCopList.value = [obj]
  834. }
  835. }
  836. }
  837. /**created */
  838. // funGetTree()
  839. const theme = ref(null)
  840. const echartsTheme = ref('')
  841. const store = useStore()
  842. watch(() => store.state.theme, (newVal, oldVal) => {
  843. theme.value = newVal
  844. echartsTheme.value = !newVal ? 'dark' : ''
  845. funGetTree()
  846. }, {
  847. deep: true
  848. })
  849. /**activated */
  850. onMounted(() => {
  851. funGetTree()
  852. //test
  853. // funSubmit()
  854. //
  855. theme.value = store.state.theme
  856. echartsTheme.value = !theme.value ? 'dark' : ''
  857. tableHeight.value = window.innerHeight - 125 + 'px'
  858. excelHeight.value = (window.innerHeight - 125) + 'px'
  859. treeHeight.value = (window.innerHeight - 125) + 'px'
  860. window.addEventListener('resize', () => {
  861. tableHeight.value = window.innerHeight - 125 + 'px'
  862. excelHeight.value = (window.innerHeight - 125) + 'px'
  863. treeHeight.value = (window.innerHeight - 125) + 'px'
  864. })
  865. })
  866. </script>
  867. <style lang="less">
  868. .rateAnalysis {
  869. height: 100%;
  870. .rateAnalysisMain {
  871. height: 100%;
  872. .main_top {
  873. height: 40px;
  874. display: flex;
  875. align-items: center;
  876. .topPsty {
  877. position: relative;
  878. top: 5px;
  879. padding: 7px 20px;
  880. font-size: 12px;
  881. font-weight: 600;
  882. margin-left: 10px;
  883. border-radius: 3px;
  884. }
  885. }
  886. .main {
  887. display: flex;
  888. justify-content: space-between;
  889. // width: calc(100% - 40px);
  890. width: 100%;
  891. .treeDataMain,
  892. .excelDataMain,
  893. .tableDataMain {
  894. padding: 10px;
  895. border-radius: 10px;
  896. }
  897. .treeDataMain {
  898. width: calc(20% - 20px);
  899. }
  900. .excelDataMain {
  901. width: calc(13% - 20px);
  902. .excelDataMain_top {
  903. padding: 5px 0;
  904. }
  905. .excelDataMain_bot {
  906. padding: 5px 0;
  907. }
  908. }
  909. .tableDataMain {
  910. width: calc(66% - 20px);
  911. .chartRowTop {
  912. display: flex;
  913. justify-content: space-between;
  914. }
  915. }
  916. }
  917. }
  918. }
  919. .themeDark {
  920. .rateAnalysisMain {
  921. .main_top {
  922. .topPsty {
  923. color: #1C99FF;
  924. background: #1E2126;
  925. }
  926. }
  927. .main {
  928. background: #13171e;
  929. .treeDataMain {
  930. background: transparent;
  931. }
  932. .excelDataMain {
  933. background: #313233;
  934. }
  935. .tableDataMain {
  936. margin-top: 5px;
  937. background: #212223;
  938. }
  939. }
  940. }
  941. }
  942. .themeLight {
  943. padding: 0;
  944. .rateAnalysisMain {
  945. .main_top {
  946. .topPsty {
  947. color: #2778FF;
  948. background: #FFFFFF;
  949. }
  950. }
  951. .main {
  952. background: #E6E8F2;
  953. .treeDataMain {
  954. background: transparent;
  955. }
  956. .excelDataMain {
  957. background: #F4F6FB;
  958. }
  959. .tableDataMain {
  960. background: #fff;
  961. margin-top: 5px;
  962. }
  963. }
  964. }
  965. }
  966. </style>