index.vue 22 KB

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