poweruse.vue 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987
  1. <template>
  2. <div class="app-container">
  3. <el-tabs v-model="activeName" @tab-click="tabClick">
  4. <el-tab-pane label="总览" name="summery">
  5. <div class="First">
  6. <div class="time-range-buttons">
  7. <el-button :class="{ 'is-active': selectedTimeRange === 'day' }"
  8. @click="changeTimeRange('day')">今日</el-button>
  9. <el-button :class="{ 'is-active': selectedTimeRange === 'month' }"
  10. @click="changeTimeRange('month')">本月</el-button>
  11. <el-button :class="{ 'is-active': selectedTimeRange === 'year' }"
  12. @click="changeTimeRange('year')">本年</el-button>
  13. </div>
  14. <div class="first-content">
  15. <div>
  16. <SubTitle title="能耗统计" />
  17. <!-- 图表容器 -->
  18. <div ref="sumBySubCategoryChart" style="height: 380px;" />
  19. </div>
  20. <div>
  21. <SubTitle title="能耗总览" />
  22. <el-table border stripe show-summary :data="tableData" style="width: 100%;margin-top: 20px;">
  23. <el-table-column prop="name" align="center" label="设施名称">
  24. </el-table-column>
  25. <el-table-column prop="value" align="center" label="能耗(kW·h)">
  26. </el-table-column>
  27. </el-table>
  28. </div>
  29. </div>
  30. </div>
  31. </el-tab-pane>
  32. <el-tab-pane v-for="item in facsCategoryOptions" :key="item.code" :label="item.name" :name="item.code">
  33. <el-col :span="4" :xs="24">
  34. <div class="head-container">
  35. <el-input
  36. v-model="areaName"
  37. placeholder="请输入区域名称"
  38. clearable
  39. size="small"
  40. prefix-icon="el-icon-search"
  41. style="margin-bottom: 20px"
  42. />
  43. </div>
  44. <div class="head-container tree-container">
  45. <el-tree
  46. :data="areaOptions"
  47. :props="defaultProps"
  48. :expand-on-click-node="false"
  49. :filter-node-method="filterNode"
  50. ref="tree"
  51. node-key="id"
  52. default-expand-all
  53. highlight-current
  54. @node-click="handleNodeClick"
  55. >
  56. <template #default="{ node, data }">
  57. <el-tooltip
  58. class="tree-node-tooltip"
  59. effect="dark"
  60. :content="data.label"
  61. placement="right"
  62. :disabled="!isTextOverflow(data.label)"
  63. >
  64. <div class="tree-node">
  65. <i class="el-icon-office-building node-icon"></i>
  66. <span class="node-label">{{ data.label }}</span>
  67. </div>
  68. </el-tooltip>
  69. </template>
  70. </el-tree>
  71. </div>
  72. </el-col>
  73. <el-col :span="20" :xs="24">
  74. <div class="container-block">
  75. <div class="ctl-container">
  76. <SubTitle :title="`设施汇总电耗【${selectedLabel}】`" />
  77. <div>
  78. <el-select v-model="objCode" placeholder="选择设施" clearable @visible-change="handleObjSelectClick"
  79. @change="getList">
  80. <el-option v-for="item in objOptions" :label="item.objName" :value="item.objCode"
  81. :key="item.objCode" />
  82. </el-select>
  83. <el-date-picker v-model="dateRange" type="datetimerange" @change="getList"
  84. :picker-options="pickerOptions" value-format="yyyy-MM-dd hh:mm:ss" range-separator="至"
  85. start-placeholder="开始日期" end-placeholder="结束日期" :clearable="false" align="right">
  86. </el-date-picker>
  87. </div>
  88. </div>
  89. <!-- 表格 -->
  90. <el-table v-loading="loading" :data="sumByFacsList" style="width: 100%; margin-top: 10px">
  91. <el-table-column label="设施编码" align="center" prop="objCode">
  92. <template slot-scope="scope">
  93. <span>{{ scope.row.objCode }}</span>
  94. </template>
  95. </el-table-column>
  96. <el-table-column label="设施名称" align="center" prop="objName">
  97. <template slot-scope="scope">
  98. <span>{{ scope.row.objName }}</span>
  99. </template>
  100. </el-table-column>
  101. <el-table-column label="用电量(kW·h)" align="center" prop="elecQuantity">
  102. <template slot-scope="scope">
  103. <span>{{ scope.row.quantity }}</span>
  104. </template>
  105. </el-table-column>
  106. </el-table>
  107. <SubTitle title="设施时段电耗" style="margin-top: 20px;" />
  108. <!--柱状图-->
  109. <div class="container-block" style="margin-top: 20px;">
  110. <BaseChart width="100%" height="300px" :option="barChartOptions" />
  111. </div>
  112. </div>
  113. </el-col>
  114. </el-tab-pane>
  115. </el-tabs>
  116. </div>
  117. </template>
  118. <script>
  119. import * as echarts from 'echarts/core';
  120. import {listByFacs,listFacsMeter} from '@/api/device/elecMeterH'
  121. import { getPowerData, getPowerMaxLoad} from '@/api/mgr/elecUseH'
  122. import {getFacsCategorygetByCode} from '@/api/basecfg/emsfacs'
  123. import {areaTreeByFacsCategory} from '@/api/basecfg/area'
  124. import dayjs from 'dayjs'
  125. import {DateTool} from '@/utils/DateTool'
  126. import {dateFormat} from '@/utils';
  127. import BaseChart from '@/components/BaseChart/index.vue'
  128. import SubTitle from '@/components/SubTitle'
  129. import Block from '@/components/Block/block.vue'
  130. import Treeselect from '@riophae/vue-treeselect'
  131. import '@riophae/vue-treeselect/dist/vue-treeselect.css'
  132. export default {
  133. name: 'PowerUse',
  134. components: {
  135. Treeselect,
  136. BaseChart,
  137. Block,
  138. SubTitle
  139. },
  140. data () {
  141. const today = dateFormat(new Date(), 'yyyy-MM-dd')
  142. return {
  143. activeName: 'summery',
  144. // 遮罩层
  145. loading: true,
  146. // 选中数组
  147. ids: [],
  148. // 非单个禁用
  149. single: true,
  150. // 非多个禁用
  151. multiple: true,
  152. // 显示搜索条件
  153. showSearch: true,
  154. // 总条数
  155. total: 0,
  156. // 用能计量-小时表格数据
  157. hList: [],
  158. //查能耗
  159. sumByFacsList: [],
  160. // 弹出层标题
  161. title: '',
  162. // 是否显示弹出层
  163. open: false,
  164. facsCategory: undefined,
  165. facsSubCategory: undefined,
  166. // 区域名称
  167. areaName: undefined,
  168. selectedLabel: '全部',
  169. defaultProps: {
  170. children: 'children',
  171. label: 'label'
  172. },
  173. areaOptions: [],
  174. facsCategoryOptions: [],
  175. sumBySubCategoryChartOption: {},
  176. // 存储图表配置的变量
  177. selectedTimeRange: 'day',
  178. chartInstance: null,
  179. // 用于存储 ECharts 实例
  180. totalElecQuantity: 0,
  181. objOptions: [],
  182. objCode: undefined,
  183. dateRange: [dayjs().format(DateTool.DateFormat.YYYY_MM_DD_00_00_00), dayjs().format(DateTool.DateFormat.YYYY_MM_DD_23_59_59)],
  184. pickerOptions: {
  185. shortcuts: [
  186. {
  187. text: '最近一周',
  188. onClick (picker) {
  189. const end = new Date()
  190. const start = new Date()
  191. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
  192. picker.$emit('pick', [start, end])
  193. }
  194. }, {
  195. text: '最近一个月',
  196. onClick (picker) {
  197. const end = new Date()
  198. const start = new Date()
  199. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
  200. picker.$emit('pick', [start, end])
  201. }
  202. }, {
  203. text: '最近三个月',
  204. onClick (picker) {
  205. const end = new Date()
  206. const start = new Date()
  207. start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
  208. picker.$emit('pick', [start, end])
  209. }
  210. }
  211. ]
  212. },
  213. // 查询参数
  214. queryParams: {
  215. pageNum: 1,
  216. pageSize: 10,
  217. areaCode: '-1',
  218. objType: 2,
  219. objCode: null,
  220. facsCategory: 'Z',
  221. facsSubCategory: null,
  222. date: null,
  223. time: null,
  224. timeIndex: null,
  225. },
  226. queryObjParams: {
  227. refArea: null,
  228. facsCategory: null,
  229. subCategory: null
  230. },
  231. // 表单参数
  232. form: {},
  233. tableData: [],
  234. powerDate: [`${today} 00:00:00`, `${today} 23:59:59`],
  235. powerChartData: [],
  236. powerMaxLoad: '',
  237. equipPowerChartData: [],
  238. equipPowerMaxLoad: ''
  239. }
  240. },
  241. watch: {
  242. // 根据名称筛选区域树
  243. areaName (val) {
  244. this.$refs.tree.filter(val)
  245. }
  246. },
  247. created () {
  248. this.facsCategory = 'Z'
  249. this.facsSubCategory = ''
  250. this.getFacsCategory(this.facsCategory)
  251. this.getAreaTree(this.facsCategory, this.facsSubCategory)
  252. this.getList()
  253. this.getsumByFacsH()
  254. this.getSumBySubCategoryH();
  255. this.getPowerChart()
  256. },
  257. computed: {
  258. barChartOptions () {
  259. const xAxisData = this.hList.map(item => item.time);
  260. const seriesData = this.hList.map(item => item.elecQuantity);
  261. return {
  262. toolbox: {
  263. itemGap: 10,
  264. itemSize: 16,
  265. right: 10,
  266. top: 0,
  267. show: true,
  268. feature: {
  269. magicType: {
  270. show: true,
  271. type: ['bar', 'line']
  272. },
  273. saveAsImage: {
  274. show: true
  275. }
  276. }
  277. },
  278. tooltip: {
  279. trigger: 'axis',
  280. axisPointer: {
  281. type: 'shadow'
  282. },
  283. formatter: (params) => {
  284. var relVal = params[0].name
  285. for (var i = 0, l = params.length; i < l; i++) {
  286. relVal =
  287. relVal +
  288. '<br/>' +
  289. params[i].marker +
  290. params[i].seriesName +
  291. '&nbsp;&nbsp;&nbsp;' +
  292. params[i].value +
  293. 'kW·h'
  294. }
  295. return relVal
  296. }
  297. },
  298. legend: {
  299. data: ['用电量']
  300. },
  301. xAxis: {
  302. type: 'category',
  303. data: xAxisData
  304. },
  305. yAxis: {
  306. name: 'kW·h(千瓦时)',
  307. type: 'value',
  308. },
  309. series: [{
  310. name: '用电量',
  311. type: 'bar',
  312. data: seriesData,
  313. barWidth: 20,
  314. itemStyle: {
  315. normal: {
  316. color: '#6395FA'
  317. }
  318. }
  319. }]
  320. };
  321. },
  322. powerLineOptions () {
  323. const xAxisData = this.powerChartData.map(item => `${item.date.substr(5)} ${item.time.substr(0, 5)} `);
  324. const yData1 = this.powerChartData.map(item => parseFloat(item.s).toFixed(2));
  325. const yData2 = this.powerChartData.map(item => item.p);
  326. const yData3 = this.powerChartData.map(item => item.q);
  327. return {
  328. toolbox: {
  329. itemGap: 10,
  330. itemSize: 16,
  331. right: 10,
  332. top: 0,
  333. show: true,
  334. feature: {
  335. magicType: {
  336. show: true,
  337. type: ['bar', 'line']
  338. },
  339. saveAsImage: {
  340. show: true
  341. }
  342. }
  343. },
  344. tooltip: {
  345. trigger: 'axis',
  346. axisPointer: {
  347. type: 'shadow'
  348. },
  349. formatter: (params) => {
  350. var relVal = params[0].name
  351. for (var i = 0, l = params.length; i < l; i++) {
  352. relVal =
  353. relVal +
  354. '<br/>' +
  355. params[i].marker +
  356. params[i].seriesName +
  357. '&nbsp;&nbsp;&nbsp;' +
  358. params[i].value +
  359. 'kW'
  360. }
  361. return relVal
  362. }
  363. },
  364. xAxis: {
  365. type: 'category',
  366. data: xAxisData
  367. },
  368. yAxis: {
  369. name: 'kW(千瓦)',
  370. type: 'value',
  371. },
  372. legend: {},
  373. dataZoom: [
  374. {
  375. type: "slider",
  376. start: 0,
  377. end: 100,
  378. height: 10,
  379. bottom: '10%',
  380. showDetail: false,
  381. showDataShadow: false,
  382. borderColor: "transparent"
  383. },
  384. {
  385. type: "inside",
  386. start: 0,
  387. end: 100,
  388. },
  389. ],
  390. series: [{
  391. name: '视在功率',
  392. type: 'line',
  393. data: yData1,
  394. markLine: {
  395. symbol: 'none',
  396. silent: true,
  397. lineStyle: {normal: {type: 'dashed'}},
  398. label: {position: 'end'},
  399. data: [
  400. {
  401. yAxis: this.powerMaxLoad,
  402. lineStyle: {width: 1.656, color: '#ff6367'},
  403. label: {
  404. show: true,
  405. textStyle: {
  406. color: '#ff6367'
  407. }
  408. }
  409. },
  410. ]
  411. },
  412. markPoint: {
  413. silent: true,
  414. data: [
  415. {
  416. yAxis: this.powerMaxLoad,
  417. x: '100%',
  418. symbolSize: 0.1,
  419. symbolOffset: [0, 0],
  420. label: {
  421. textStyle: {color: '#ff6367'},
  422. fontSize: 12,
  423. position: 'left',
  424. formatter: '最高负荷'
  425. }
  426. },
  427. ]
  428. },
  429. },
  430. {
  431. name: '有功功率',
  432. type: 'line',
  433. data: yData2,
  434. },
  435. {
  436. name: '无功功率',
  437. type: 'line',
  438. data: yData3,
  439. },
  440. ]
  441. };
  442. },
  443. equipPowerLineOptions () {
  444. const xAxisData = this.equipPowerChartData.map(item => `${item.date.substr(5)} ${item.time.substr(0, 5)} `);
  445. const yData1 = this.equipPowerChartData.map(item => parseFloat(item.s).toFixed(2));
  446. const yData2 = this.equipPowerChartData.map(item => item.p);
  447. const yData3 = this.equipPowerChartData.map(item => item.q);
  448. return {
  449. toolbox: {
  450. itemGap: 10,
  451. itemSize: 16,
  452. right: 10,
  453. top: 0,
  454. show: true,
  455. feature: {
  456. magicType: {
  457. show: true,
  458. type: ['bar', 'line']
  459. },
  460. saveAsImage: {
  461. show: true
  462. }
  463. }
  464. },
  465. legend: {},
  466. tooltip: {
  467. trigger: 'axis',
  468. axisPointer: {
  469. type: 'shadow'
  470. },
  471. formatter: (params) => {
  472. var relVal = params[0].name
  473. for (var i = 0, l = params.length; i < l; i++) {
  474. relVal =
  475. relVal +
  476. '<br/>' +
  477. params[i].marker +
  478. params[i].seriesName +
  479. '&nbsp;&nbsp;&nbsp;' +
  480. params[i].value +
  481. 'kW'
  482. }
  483. return relVal
  484. }
  485. },
  486. xAxis: {
  487. type: 'category',
  488. data: xAxisData
  489. },
  490. yAxis: {
  491. name: 'kW(千瓦)',
  492. type: 'value',
  493. },
  494. dataZoom: [
  495. {
  496. type: "slider",
  497. start: 0,
  498. end: 100,
  499. height: 10,
  500. bottom: '10%',
  501. showDetail: false,
  502. showDataShadow: false,
  503. borderColor: "transparent"
  504. },
  505. {
  506. type: "inside",
  507. start: 0,
  508. end: 100,
  509. },
  510. ],
  511. series: [{
  512. name: '视在功率',
  513. type: 'line',
  514. data: yData1,
  515. markLine: {
  516. symbol: 'none',
  517. silent: true,
  518. lineStyle: {normal: {type: 'dashed'}},
  519. label: {position: 'end'},
  520. data: [
  521. {
  522. yAxis: this.equipPowerMaxLoad,
  523. lineStyle: {width: 1.656, color: '#ff6367'},
  524. label: {
  525. show: true,
  526. textStyle: {
  527. color: '#ff6367'
  528. }
  529. }
  530. },
  531. ]
  532. },
  533. markPoint: {
  534. silent: true,
  535. data: [
  536. {
  537. yAxis: this.equipPowerMaxLoad,
  538. x: '100%',
  539. symbolSize: 0.1,
  540. symbolOffset: [0, 0],
  541. label: {
  542. textStyle: {color: '#ff6367'},
  543. fontSize: 12,
  544. position: 'left',
  545. formatter: '最高负荷'
  546. }
  547. },
  548. ]
  549. },
  550. },
  551. {
  552. name: '有功功率',
  553. type: 'line',
  554. data: yData2,
  555. },
  556. {
  557. name: '无功功率',
  558. type: 'line',
  559. data: yData3,
  560. },
  561. ]
  562. };
  563. }
  564. },
  565. methods: {
  566. // 新增方法:判断文本是否溢出
  567. isTextOverflow(text) {
  568. // 简单判断:超过一定字符数就显示tooltip
  569. // 可以根据实际情况调整这个数值
  570. return text && text.length > 8
  571. },
  572. /**平均功率-15分钟*/
  573. getPowerChart () {
  574. this.powerMaxLoad = ''
  575. this.powerChartData = []
  576. const [startRecTime, endRecTime] = this.powerDate
  577. const params = {
  578. startRecTime,
  579. endRecTime,
  580. areaCode: '-1',
  581. objType: '2',
  582. }
  583. getPowerData({
  584. ...params,
  585. pageNum: 1,
  586. pageSize: 999
  587. }).then(({code, rows}) => {
  588. if (code === 200) {
  589. this.powerChartData = rows
  590. }
  591. })
  592. getPowerMaxLoad(params).then(({code, data}) => {
  593. if (code === 200 && data) {
  594. this.powerMaxLoad = parseFloat(data.s).toFixed(2)
  595. }
  596. })
  597. },
  598. getEquipPowerChart () {
  599. this.equipPowerMaxLoad = ''
  600. this.equipPowerChartData = []
  601. const [startRecTime, endRecTime] = this.dateRange
  602. const params = {
  603. startRecTime,
  604. endRecTime,
  605. areaCode: '-1',
  606. objType: '2',
  607. facsCategory: 'Z',
  608. facsSubCategory: this.activeName,
  609. objCode: this.objCode
  610. }
  611. getPowerData({
  612. ...params,
  613. pageNum: 1,
  614. pageSize: 999
  615. }).then(({code, rows}) => {
  616. if (code === 200) {
  617. this.equipPowerChartData = rows
  618. }
  619. })
  620. getPowerMaxLoad(params).then(({code, data}) => {
  621. if (code === 200) {
  622. this.equipPowerMaxLoad = parseFloat(data).toFixed(2)
  623. }
  624. })
  625. },
  626. /** 查询用能计量-小时列表 */
  627. getList () {
  628. this.loading = true
  629. this.queryParams.objCode = this.objCode
  630. const params = {
  631. startRecTime: dayjs(this.dateRange[0]).format('YYYY-MM-DD HH:mm:ss'),
  632. endRecTime: dayjs(this.dateRange[1]).format('YYYY-MM-DD HH:mm:ss'),
  633. meterCls:45,
  634. areaCode: this.queryParams.areaCode,
  635. facsCategory:this.queryParams.facsCategory,
  636. facsSubCategory: this.activeName,
  637. };
  638. listFacsMeter(params).then(response => {
  639. this.hList = response.rows
  640. this.total = response.total
  641. this.loading = false
  642. })
  643. this.getsumByFacsH()
  644. this.getEquipPowerChart()
  645. },
  646. /**根据设施查询能耗统计 */
  647. getsumByFacsH () {
  648. const params = {
  649. startRecTime: dayjs(this.dateRange[0]).format('YYYY-MM-DD HH:mm:ss'),
  650. endRecTime: dayjs(this.dateRange[1]).format('YYYY-MM-DD HH:mm:ss'),
  651. meterCls:45,
  652. areaCode: this.queryParams.areaCode,
  653. facsCategory:this.queryParams.facsCategory,
  654. facsSubCategory: this.activeName,
  655. };
  656. listByFacs(params).then(response => {
  657. this.sumByFacsList = response.data.map(item => ({
  658. objCode: item.objCode,
  659. objName: item.objName,
  660. quantity: item.quantity || 0,
  661. }));
  662. console.log(" this.sumByFacsList ", this.sumByFacsList )
  663. })
  664. },
  665. /**时间范围切换按钮点击事件处理器*/
  666. changeTimeRange (rangeType) {
  667. this.selectedTimeRange = rangeType;
  668. let start = dayjs();
  669. let end = dayjs();
  670. if (rangeType === 'day') {
  671. // 日:当前日期的 00:00:00 到 23:59:59
  672. start = start.startOf('day');
  673. end = end.endOf('day');
  674. } else if (rangeType === 'month') {
  675. // 月:当前月份的第一天 00:00:00 到 最后一天 23:59:59
  676. start = start.date(1).hour(0).minute(0).second(0);
  677. end = end.endOf('month').hour(23).minute(59).second(59);
  678. } else if (rangeType === 'year') {
  679. // 年:当前年份的第一天 00:00:00 到 最后一天 23:59:59
  680. start = start.startOf('year');
  681. end = end.endOf('year').hour(23).minute(59).second(59);
  682. }
  683. this.dateRange = [start.format('YYYY-MM-DD HH:mm:ss'), end.format('YYYY-MM-DD HH:mm:ss')];
  684. this.getSumBySubCategoryH(); // 重新获取数据
  685. },
  686. /**总览饼图*/
  687. getSumBySubCategoryH () {
  688. const params = {
  689. startRecTime: dayjs(this.dateRange[0]).format('YYYY-MM-DD HH:mm:ss'),
  690. endRecTime: dayjs(this.dateRange[1]).format('YYYY-MM-DD HH:mm:ss'),
  691. areaCode: this.queryParams.areaCode,
  692. meterCls:45,
  693. facsCategory:this.queryParams.facsCategory,
  694. };
  695. listByFacs(params).then(response => {
  696. console.log("pie图", response.data)
  697. this.tableData = response.data.map(item => ({
  698. name: item.objName,
  699. value: item.quantity || 0
  700. }))
  701. console.log("能耗总览",this.tableData)
  702. this.processDataForChart(response.data); // 处理数据并生成图表配置
  703. })
  704. },
  705. processDataForChart(data) {
  706. console.log("data", data);
  707. this.totalElecQuantity = data.reduce((sum, item) => sum + (item.quantity || 0), 0);
  708. // 处理数据,生成图表配置
  709. const seriesData = data.map(item => ({
  710. name: item.objName,
  711. value: item.quantity || 0,
  712. percent: ((item.quantity || 0) / this.totalElecQuantity * 100).toFixed(2),
  713. }));
  714. console.log("seriesData", seriesData);
  715. // 设置图表配置
  716. this.sumBySubCategoryChartOption = {
  717. tooltip: {
  718. trigger: 'item',
  719. formatter: function(params) {
  720. const { name, value, percent } = params;
  721. return `<div><h4>${name}</h4><p>${value}kW·h (${percent}%)</p></div>`;
  722. }
  723. },
  724. legend: {
  725. orient: 'vertical',
  726. top: '5%',
  727. left: '5%'
  728. },
  729. series: [
  730. {
  731. name: '能耗',
  732. type: 'pie',
  733. radius: ['35%', '55%'],
  734. data: seriesData,
  735. emphasis: {
  736. itemStyle: {
  737. shadowBlur: 10,
  738. shadowOffsetX: 0,
  739. shadowColor: 'rgba(0, 0, 0, 0.5)',
  740. }
  741. },
  742. label: {
  743. show: true,
  744. position: 'outside',
  745. formatter: '{b}\n{d}%',
  746. },
  747. labelLine: {
  748. show: true,
  749. length: 30, // 标签线长度
  750. lineStyle: {
  751. width: 1,
  752. type: 'dashed', // 设置虚线样式
  753. }
  754. }
  755. }
  756. ]
  757. };
  758. // 渲染图表
  759. this.$nextTick(() => {
  760. const chart = echarts.init(this.$refs.sumBySubCategoryChart);
  761. chart.setOption(this.sumBySubCategoryChartOption);
  762. });
  763. },
  764. async getFacsCategory (code) {
  765. getFacsCategorygetByCode(code).then(response => {
  766. this.facsCategoryOptions = response.data.subtypeList
  767. })
  768. },
  769. async getAreaTree (category, subCategory) {
  770. await areaTreeByFacsCategory(category, subCategory, false).then(response => {
  771. this.areaOptions = [{
  772. id: '-1',
  773. label: '全部',
  774. children: []
  775. }].concat(response.data)
  776. })
  777. },
  778. async getFacsObj (areaCode, category, subCategory) {
  779. this.queryObjParams.refArea = areaCode
  780. this.queryObjParams.facsCategory = category
  781. this.queryObjParams.subCategory = subCategory
  782. // listAllFacs(this.queryObjParams).then(response => {
  783. // this.objOptions = response.data
  784. // })
  785. const params = {
  786. startRecTime: dayjs(this.dateRange[0]).format('YYYY-MM-DD HH:mm:ss'),
  787. endRecTime: dayjs(this.dateRange[1]).format('YYYY-MM-DD HH:mm:ss'),
  788. meterCls:45,
  789. areaCode: this.queryParams.areaCode,
  790. facsCategory:this.queryParams.facsCategory,
  791. facsSubCategory: this.activeName,
  792. };
  793. listByFacs(params).then(response => {
  794. this.objOptions = response.data
  795. console.log(" this.objOptions ",this.objOptions )
  796. })
  797. },
  798. tabClick () {
  799. this.reset()
  800. if (this.activeName !== 'summery') {
  801. this.dateRange = [dayjs().format(DateTool.DateFormat.YYYY_MM_DD_00_00_00), dayjs().format(DateTool.DateFormat.YYYY_MM_DD_23_59_59)]
  802. this.queryParams.facsCategory = this.facsCategory
  803. this.queryParams.facsSubCategory = this.activeName
  804. this.queryParams.pageNum = 1
  805. this.selectedLabel = '全部'
  806. this.getList()
  807. } else {
  808. }
  809. },
  810. /** 搜索按钮操作 */
  811. handleQuery () {
  812. this.queryParams.pageNum = 1
  813. this.getList()
  814. this.getsumByFacsH()
  815. },
  816. handleObjSelectClick () {
  817. this.getFacsObj(this.queryParams.areaCode, this.facsCategory, this.activeName)
  818. },
  819. // 筛选节点
  820. filterNode (value, data) {
  821. if (!value) return true
  822. return data.label.indexOf(value) !== -1
  823. },
  824. // 节点单击事件
  825. handleNodeClick (data) {
  826. this.queryParams.areaCode = data.id
  827. this.selectedLabel = data.label
  828. this.objCode = null
  829. this.handleQuery()
  830. },
  831. reset () {
  832. this.objCode = null
  833. this.queryParams.areaCode = '-1'
  834. this.queryParams.facsCategory = 'Z'
  835. this.queryParams.facsSubCategory = null
  836. this.queryParams.objCode = null
  837. this.objOptions = []
  838. }
  839. }
  840. }
  841. </script>
  842. <style lang="scss" scoped>
  843. .time-range-buttons {
  844. .is-active {
  845. background-color: #409eff;
  846. color: white;
  847. }
  848. }
  849. .first-content {
  850. display: flex;
  851. margin-top: 20px;
  852. >div:first-child {
  853. flex: 3;
  854. }
  855. >div:last-child {
  856. flex: 2;
  857. }
  858. }
  859. .container-block {
  860. padding-left: 20px;
  861. }
  862. .ctl-container {
  863. display: flex;
  864. justify-content: space-between;
  865. }
  866. /* 树容器样式 - 统一美化设计 */
  867. .tree-container {
  868. height: calc(100vh - 200px);
  869. overflow-y: auto;
  870. border: 1px solid #e8e8e8;
  871. border-radius: 4px;
  872. padding: 10px;
  873. background-color: #fafafa;
  874. }
  875. /* 树节点样式 */
  876. .tree-node {
  877. display: flex;
  878. align-items: center;
  879. width: 100%;
  880. padding: 2px 0;
  881. transition: all 0.3s;
  882. cursor: pointer;
  883. }
  884. .node-icon {
  885. margin-right: 8px;
  886. font-size: 16px;
  887. transition: all 0.3s;
  888. color: #409EFF;
  889. }
  890. .node-label {
  891. flex: 1;
  892. font-size: 14px;
  893. overflow: hidden;
  894. text-overflow: ellipsis;
  895. white-space: nowrap;
  896. }
  897. /* 节点hover效果 */
  898. .tree-node:hover {
  899. background-color: #f0f7ff;
  900. border-radius: 4px;
  901. padding-left: 4px;
  902. }
  903. .tree-node:hover .node-icon {
  904. color: #2b7bff;
  905. transform: scale(1.1);
  906. }
  907. /* 高亮当前选中的节点 */
  908. .el-tree-node.is-current > .el-tree-node__content .tree-node {
  909. background-color: #e6f7ff;
  910. border-radius: 4px;
  911. padding-left: 4px;
  912. }
  913. .el-tree-node.is-current > .el-tree-node__content .node-icon {
  914. color: #1890ff;
  915. }
  916. /* 覆盖默认的el-tree样式,确保自定义样式生效 */
  917. .el-tree-node__content {
  918. height: auto;
  919. padding: 0 !important;
  920. }
  921. .el-tree-node__content:hover {
  922. background-color: transparent;
  923. }
  924. .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
  925. background-color: transparent;
  926. }
  927. /* 树节点展开图标调整 */
  928. .el-tree-node__expand-icon {
  929. color: #909399;
  930. font-size: 14px;
  931. }
  932. .el-tree-node__expand-icon:hover {
  933. color: #409EFF;
  934. }
  935. /* 滚动条美化 */
  936. .tree-container::-webkit-scrollbar {
  937. width: 6px;
  938. }
  939. .tree-container::-webkit-scrollbar-track {
  940. background: #f1f1f1;
  941. border-radius: 3px;
  942. }
  943. .tree-container::-webkit-scrollbar-thumb {
  944. background: #c1c1c1;
  945. border-radius: 3px;
  946. }
  947. .tree-container::-webkit-scrollbar-thumb:hover {
  948. background: #a8a8a8;
  949. }
  950. </style>