index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <template>
  2. <div class="dataAnalysisWindAna" :class="!theme ? 'themeDark' : 'themeLight'">
  3. <div class="dataAnalysisWindAnaMain">
  4. <p>损失电量分析</p>
  5. <div class="main">
  6. <div class="treeDataMain">
  7. <tree-cop ref="treeCopRef" :data="treeData" @checkChange="funTreeCheckChange" :show-checkbox="true"
  8. :height="treeHeight" @currentChange="funCurrentChange" @refresh="funGetTree"></tree-cop>
  9. </div>
  10. <div class="excelDataMain">
  11. <excel-cop :checkIds="excelCheckIds" :showCheckbox="excelCheckboxShow" :data="excelList"
  12. :height="excelHeight" @excelChange="funExcelChange" @checkChange="funExcelCheckChange">
  13. </excel-cop>
  14. </div>
  15. <div class="tableDataMain">
  16. <div class="px-[10px] shadow rounded-[6px] shadow-blue-500 ">
  17. <el-tabs v-model="activeTab">
  18. <el-tab-pane label="表格数据" name="1">
  19. </el-tab-pane>
  20. <el-tab-pane label="图表展示" name="2">
  21. </el-tab-pane>
  22. <table-cop class="" v-show="activeTab === '1'" :data="tableData" :showSummary="true"
  23. :summaryMethod="funSummary" :column="tableColumn" :loading="tableLoading"
  24. :height="tableHeight" :tableId="tableShowId" :tableName="tableName"></table-cop>
  25. <div v-show="activeTab === '2'"
  26. :style="{ height: typeof tableHeight === 'string' ? tableHeight : tableHeight + 'px' }"
  27. class="p-[10px]">
  28. <bar-line-chart-cop v-show="lineData.length" :height="tableHeight" :bardata="barData"
  29. :lineData="lineData" :color="barColor" lineName="理论发电量"></bar-line-chart-cop>
  30. <el-empty v-show="!lineData.length" description="请选择条件"></el-empty>
  31. </div>
  32. </el-tabs>
  33. </div>
  34. </div>
  35. </div>
  36. </div>
  37. </div>
  38. </template>
  39. <script setup name="prepare">
  40. import tableCop from '@/components/generatingCapacityComponent/table.vue'
  41. import excelCop from '@/components/generatingCapacityComponent/excel.vue'
  42. import treeCop from '@/components/generatingCapacityComponent/tree.vue'
  43. import barLineChartCop from './components/barLineChart.vue'
  44. import {
  45. ElMessage
  46. } from 'element-plus';
  47. import {
  48. onMounted,
  49. ref,
  50. onActivated,
  51. watch
  52. } from 'vue'
  53. import {
  54. useStore
  55. } from 'vuex';
  56. import httpRequest from '@/utils/request.js'
  57. /**配置参数 */
  58. const treeHeight = ref(window.innerHeight - 160 + 'px') //tree高度
  59. const excelHeight = ref(window.innerHeight - 160 + 'px') //excel高度
  60. const tableHeight = ref(window.innerHeight - 214 + 'px')
  61. /**table 开始 */
  62. const tableShowId = ref('')
  63. const tableName = ref('损失电量分析')
  64. const tableColumn = ref([])
  65. const tableLoading = ref(false)
  66. const tableData = ref([])
  67. const funSummary = ({
  68. columns,
  69. data
  70. }) => {
  71. const sums = []
  72. columns.forEach((column, index) => {
  73. if (index === 0) {
  74. sums[index] = '合计'
  75. return
  76. }
  77. const values = data.map((item) => Number(item[column.property]))
  78. if (!values.every((value) => Number.isNaN(value))) {
  79. sums[index] = values.reduce((prev, curr) => {
  80. const value = Number(curr)
  81. if (!Number.isNaN(value)) {
  82. return Number((prev + curr).toFixed(2))
  83. } else {
  84. return Number(prev.toFixed(2))
  85. }
  86. }, 0)
  87. } else {
  88. sums[index] = '--'
  89. }
  90. if (['speed', 'fnlly'].includes(column.property)) {
  91. if (!Number.isNaN(sums[index])) {
  92. sums[index] = Number((sums[index] / data.length).toFixed(2))
  93. }
  94. }
  95. })
  96. return sums
  97. }
  98. const funSubmit = async () => {
  99. if (!excelCheckIds.value.length) {
  100. ElMessage.error('请勾选要展现的项')
  101. return false
  102. }
  103. tableLoading.value = true
  104. tableData.value = []
  105. tableShowId.value = ''
  106. barData.value = {
  107. area: [],
  108. legend: [],
  109. data: [],
  110. }
  111. lineData.value = []
  112. const res = await httpRequest.get('/fjjxb/five/loss/cal', {
  113. params: {
  114. ids: excelCheckIds.value.join()
  115. }
  116. })
  117. if (res.code !== 200 || !res.data.title) {
  118. tableLoading.value = false;
  119. return false
  120. }
  121. ElMessage.success(res.msg)
  122. tableColumn.value = res.data.title.map(o => {
  123. return {
  124. prop: o.key,
  125. label: o.des,
  126. width: o.des === '时间' ? 100 : 80,
  127. }
  128. })
  129. tableData.value = res.data.data
  130. const name = [],
  131. data = [],
  132. llfdl = [],
  133. legend = [
  134. "实际电量",
  135. "计划检修损失",
  136. "非计划检修损失",
  137. "限电损失",
  138. "受累损失",
  139. "性能损失",
  140. ],
  141. data2 = []; //项目列表
  142. // if (params.station) {
  143. // let arr = [];
  144. // let hj = res.data.data.pop();
  145. // res.data.data.forEach((ele, index) => {
  146. // arr[ele.id.split('_')[1] - 1] = ele
  147. // })
  148. // arr.push(hj);
  149. // res.data.data = arr;
  150. // }
  151. res.data.data.forEach((item, index) => {
  152. name.push(item.name);
  153. data.push([
  154. item.sjfdl,
  155. item.jhjx,
  156. item.fjhjx,
  157. item.xd,
  158. item.sl,
  159. item.xn,
  160. ]);
  161. llfdl.push(item.llfdl);
  162. data2.push({
  163. index: index + 1,
  164. name: item.name,
  165. llfdl: item.llfdl,
  166. sjfdl: item.sjfdl,
  167. speed: item.speed,
  168. fjhjx: item.fjhjx,
  169. jhjx: item.jhjx,
  170. sl: item.sl,
  171. xd: item.xd,
  172. xn: item.xn,
  173. fnlly: item.fnlly,
  174. is_light: false,
  175. });
  176. });
  177. if (data.length > 0) {
  178. let arr1 = [];
  179. const length = data[0].length;
  180. for (var i = 0; i < length; i++) {
  181. let arr2 = [];
  182. data.forEach((ele) => {
  183. arr2.push(ele[i]);
  184. });
  185. arr1.push(arr2);
  186. }
  187. lineData.value = llfdl;
  188. barData.value = {
  189. area: name,
  190. legend: legend,
  191. data: arr1,
  192. };
  193. }
  194. tableLoading.value = false
  195. tableShowId.value = '1'
  196. activeTab.value = '2'
  197. }
  198. /**barlineChart 开始 */
  199. const barData = ref({
  200. area: [],
  201. legend: [],
  202. data: [],
  203. })
  204. const lineData = ref([])
  205. const barColor = [
  206. "#4b55ae",
  207. "#e17e23",
  208. "#ba3237",
  209. "#c531c7",
  210. "rgb(63,177,227)",
  211. "#05bb4c",
  212. ]
  213. /**tabs */
  214. const activeTab = ref('1')
  215. /**excel 开始 */
  216. const excelCheckboxShow = ref(false)
  217. const excelType = ref('')
  218. const treeCopRef = ref() //treeCop ref
  219. const excelCheckIds = ref([])
  220. const excelList = ref([])
  221. const funExcelChange = async (obj) => { //点击excel项时
  222. return false
  223. }
  224. const funExcelCheckChange = ({
  225. checkArr,
  226. data
  227. }) => { //bug
  228. excelCheckIds.value = checkArr
  229. funSubmit()
  230. }
  231. /**prepare tree 开始 */
  232. const treeData = ref([])
  233. const actTreeNode = ref(null) //当前激活的treeNode
  234. const funRepeatMap = (arr) => {
  235. return arr.map(o => {
  236. if (o.children) {
  237. const findIndex = o.children.findIndex(p => !!p.type)
  238. if (findIndex !== -1) {
  239. o.childs = o.children
  240. o.children = []
  241. if (!actTreeNode.value) { //判断当且仅有process获取tree时 赋值
  242. actTreeNode.value = o
  243. }
  244. }
  245. }
  246. return {
  247. ...o,
  248. children: o.children ? funRepeatMap(o.children) : []
  249. }
  250. })
  251. }
  252. const funGetTree = async () => {
  253. actTreeNode.value = null
  254. const res = await httpRequest.get("/power/prepare/tree")
  255. treeData.value = funRepeatMap(res.data)
  256. excelList.value = []
  257. if (actTreeNode.value) {
  258. funCurrentChange({
  259. current: actTreeNode.value,
  260. currentNode: null
  261. })
  262. if (treeCopRef.value) {
  263. treeCopRef.value.$refs.tree.setCheckedKeys([actTreeNode.value.id])
  264. excelCheckIds.value = actTreeNode.value.childs.map(o => o.id)
  265. funSubmit()
  266. }
  267. }
  268. }
  269. const funCurrentChange = ({
  270. current,
  271. currentNode
  272. }) => {
  273. excelCheckboxShow.value = true
  274. if (current.childs) {
  275. excelList.value = current.childs.map(o => {
  276. return {
  277. id: o.id,
  278. interval: o.interval,
  279. path: o.path,
  280. prepareid: o.prepareid,
  281. station: o.station,
  282. time: o.time,
  283. type: o.type,
  284. windturbine: o.windturbine,
  285. name: o.path.substring(o.path.indexOf(o.station + '_') + (o.station + '_').length)
  286. }
  287. })
  288. } else {
  289. excelList.value = []
  290. }
  291. }
  292. const funTreeCheckChange = ({
  293. current,
  294. checkedNodes,
  295. checkedKeys,
  296. halfCheckedNodes,
  297. halfCheckedKeys
  298. }) => { //tree change -> excel change
  299. funCurrentChange({
  300. current,
  301. currentNode: ''
  302. })
  303. const checkIds = []
  304. if (checkedNodes.length) {
  305. for (const node of checkedNodes) {
  306. if (node.childs && node.childs.length) {
  307. for (const child of node.childs) {
  308. checkIds.push(child.id)
  309. }
  310. }
  311. }
  312. }
  313. excelCheckIds.value = checkIds
  314. funSubmit()
  315. }
  316. /**created */
  317. const theme = ref(null)
  318. const echartsTheme = ref('')
  319. const store = useStore()
  320. watch(() => store.state.theme, (newVal, oldVal) => {
  321. theme.value = newVal
  322. echartsTheme.value = !newVal ? 'dark' : ''
  323. funGetTree()
  324. }, {
  325. deep: true
  326. })
  327. /**mounted */
  328. onMounted(() => {
  329. funGetTree()
  330. theme.value = store.state.theme
  331. echartsTheme.value = !theme.value ? 'dark' : ''
  332. tableHeight.value = window.innerHeight - 214 + 'px'
  333. excelHeight.value = window.innerHeight - 160 + 'px'
  334. treeHeight.value = window.innerHeight - 160 + 'px'
  335. window.addEventListener('resize', () => {
  336. tableHeight.value = window.innerHeight - 214 + 'px'
  337. excelHeight.value = window.innerHeight - 160 + 'px'
  338. treeHeight.value = window.innerHeight - 160 + 'px'
  339. })
  340. })
  341. /**activated */
  342. onActivated(() => {
  343. // funGetTree()
  344. })
  345. </script>
  346. <style lang="less" scoped>
  347. .dataAnalysisWindAna {
  348. padding: 20px;
  349. p {
  350. font-size: 16px;
  351. margin-left: 20px;
  352. margin-bottom: 10px;
  353. }
  354. .main {
  355. display: flex;
  356. justify-content: space-between;
  357. // width: calc(100% - 40px);
  358. width: 100%;
  359. .treeDataMain,
  360. .excelDataMain,
  361. .tableDataMain {
  362. padding: 10px;
  363. border-radius: 10px;
  364. }
  365. .treeDataMain {
  366. width: calc(20% - 20px);
  367. }
  368. .excelDataMain {
  369. width: calc(13% - 20px);
  370. }
  371. .tableDataMain {
  372. width: calc(66% - 20px);
  373. position: relative;
  374. .butten_com {
  375. position: absolute;
  376. right: 20px;
  377. z-index: 111111;
  378. }
  379. }
  380. }
  381. }
  382. .themeDark {
  383. p {
  384. color: #fff;
  385. }
  386. .treeDataMain,
  387. .excelDataMain,
  388. .tableDataMain {
  389. background: #161f1e;
  390. }
  391. }
  392. .themeLight {
  393. padding: 0;
  394. p {
  395. color: #000;
  396. }
  397. .treeDataMain,
  398. .excelDataMain,
  399. .tableDataMain {
  400. background: #edeffb;
  401. }
  402. .dataAnalysisWindAnaMain {
  403. padding: 20px 0;
  404. border-radius: 10px;
  405. background: #fff;
  406. }
  407. }
  408. </style>