index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. <template>
  2. <div>
  3. <div class="query mg-b-8">
  4. <div class="query-items">
  5. <div class="query-item">
  6. <div class="lable">点名:</div>
  7. <div class="search-input">
  8. <el-input style="width: 250px;" placeholder="请输入点名" size="middle" v-model="form.pointId" clearable></el-input>
  9. </div>
  10. </div>
  11. <div class="query-item">
  12. <div class="lable">描述:</div>
  13. <div class="search-input">
  14. <el-input placeholder="请输入描述" size="middle" v-model="form.pointName" clearable></el-input>
  15. </div>
  16. </div>
  17. <div class="query-item">
  18. <div class="lable"></div>
  19. <div class="search-input">
  20. <el-checkbox v-model="form.autoReq" label="刷新" border @change="reReqAjax"></el-checkbox>
  21. </div>
  22. </div>
  23. </div>
  24. <div class="query-actions">
  25. <button class="btn green" @click="getTableData">查询</button>
  26. <button class="btn green" @click="exportExcel('tableData')">导出</button>
  27. </div>
  28. </div>
  29. <div class="searchPage">
  30. <div style="width:200px;height:100vh">
  31. <CollapseList :list="menus" @click="clickMenu" />
  32. </div>
  33. <div class="df-table">
  34. <ComTable height="78vh" :data="tableData" :pageSize="20" @onPagging="onChangePage"></ComTable>
  35. </div>
  36. </div>
  37. <el-dialog title="查看详情" v-model="showDialog" width="85%" top="10vh" custom-class="modal" :close-on-click-modal="true" @closed="(res) => { pointId=''; }">
  38. <div class="query mg-b-8">
  39. <div class="query-items">
  40. <div class="query-item">
  41. <div class="lable">点名:</div>
  42. <div class="search-input">
  43. <el-input readonly style="width: 300px;" size="middle" v-model="pointId" clearable></el-input>
  44. </div>
  45. </div>
  46. <div class="query-item">
  47. <div class="lable">日期:</div>
  48. <div class="search-input">
  49. <el-date-picker size="medium" v-model="form.dateArea" type="datetimerange"
  50. :picker-options="pickerOptions" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" align="right"
  51. @change="(res) => { getDatePickerChange(res); }">
  52. </el-date-picker>
  53. </div>
  54. </div>
  55. <div class="query-item">
  56. <div class="lable">间隔:</div>
  57. <div class="search-input">
  58. <el-input placeholder="请输入间隔" clearable v-model="form.interval" type="number"></el-input>
  59. </div>
  60. </div>
  61. </div>
  62. <div class="query-actions">
  63. <button class="btn green" @click="getDetails">查询</button>
  64. <button class="btn green" @click="exportExcel('detailsTableData')" v-if="detailsTableData.data.length">导出</button>
  65. <button class="btn green" @click="renderCharts" v-if="detailsTableData.data.length">查看折线图</button>
  66. </div>
  67. </div>
  68. <ComTable height="50vh" :data="detailsTableData"></ComTable>
  69. </el-dialog>
  70. <el-dialog title="查看折线图" v-model="chartDialogShow" width="60%" top="10vh" custom-class="modal" :close-on-click-modal="true">
  71. <div id="lineChart" style="width:100%;height:500px;"></div>
  72. </el-dialog>
  73. </div>
  74. </template>
  75. <script>
  76. import { Message } from 'element-plus';
  77. import CollapseList from "@com/coms/collapse/collapse-list.vue";
  78. import ComTable from "@com/coms/table/table.vue";
  79. import * as echarts from "echarts";
  80. export default {
  81. data () {
  82. const that=this;
  83. return {
  84. menus:[],
  85. tableid: "",
  86. pointId: "",
  87. form: {
  88. pointId: "",
  89. pointName: "",
  90. autoReq: false,
  91. dateArea: [
  92. this.fmtDate(new Date(new Date().setTime(new Date().getTime() - 3600 * 1000 * 24))),
  93. this.fmtDate(new Date())
  94. ],
  95. interval: ""
  96. },
  97. showDialog: false,
  98. chartDialogShow: false,
  99. tableData: {
  100. column: [
  101. {
  102. name: "序号",
  103. field: "index",
  104. is_num: false,
  105. is_light: false,
  106. sortable: true
  107. },
  108. {
  109. name: "点名",
  110. field: "pointId",
  111. is_num: false,
  112. is_light: false,
  113. sortable: true
  114. },
  115. {
  116. name: "描述",
  117. field: "pointName",
  118. is_num: false,
  119. is_light: false,
  120. sortable: true
  121. },
  122. {
  123. name: "值",
  124. field: "value",
  125. is_num: true,
  126. is_light: false,
  127. sortable: true
  128. },
  129. {
  130. name: "时间戳",
  131. field: "timeDate",
  132. is_num: false,
  133. is_light: false,
  134. sortable: true
  135. },
  136. {
  137. name: "操作",
  138. field: "",
  139. is_num: false,
  140. is_light: false,
  141. template() {
  142. return "<el-button type='text' style='cursor: pointer;'>详情</el-button>";
  143. },
  144. click(e, row){
  145. that.goDetails(row);
  146. }
  147. }
  148. ],
  149. data: [],
  150. },
  151. detailsTableData: {
  152. column: [
  153. {
  154. name: "序号",
  155. field: "index",
  156. is_num: false,
  157. is_light: false,
  158. sortable: true
  159. },
  160. {
  161. name: "时间戳",
  162. field: "timeDate",
  163. is_num: false,
  164. is_light: false,
  165. sortable: true
  166. },
  167. {
  168. name: "值",
  169. field: "value",
  170. is_num: true,
  171. is_light: false,
  172. sortable: true
  173. }
  174. ],
  175. data: [],
  176. },
  177. autoReqTimmer: null,
  178. currentPage: 1,
  179. pagesize: 10,
  180. pagesizereal: 100,
  181. currentPageTotal: 0,
  182. pickerOptions: {
  183. shortcuts: [{
  184. text: '最近一天',
  185. onClick (picker) {
  186. const end = new Date();
  187. const start = new Date();
  188. start.setTime(start.getTime() - 3600 * 1000 * 24);
  189. picker.$emit('pick', [start, end]);
  190. }
  191. }, {
  192. text: '最近一周',
  193. onClick (picker) {
  194. const end = new Date();
  195. const start = new Date();
  196. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
  197. picker.$emit('pick', [start, end]);
  198. }
  199. }, {
  200. text: '最近一个月',
  201. onClick (picker) {
  202. const end = new Date();
  203. const start = new Date();
  204. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
  205. picker.$emit('pick', [start, end]);
  206. }
  207. }, {
  208. text: '最近三个月',
  209. onClick (picker) {
  210. const end = new Date();
  211. const start = new Date();
  212. start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
  213. picker.$emit('pick', [start, end]);
  214. }
  215. }]
  216. },
  217. }
  218. },
  219. components:{
  220. CollapseList,
  221. ComTable
  222. },
  223. mounted () {
  224. let that = this;
  225. that.$nextTick(() => {
  226. that.tableid = that.$route.query.tableid || "JSFW";
  227. that.getTableData();
  228. that.getMenuList();
  229. });
  230. },
  231. unmounted () {
  232. clearInterval(this.autoReqTimmer);
  233. this.autoReqTimmer = null;
  234. },
  235. methods: {
  236. // 获取左侧菜单
  237. getMenuList(){
  238. let that=this;
  239. that.API.requestData({
  240. method: "GET",
  241. baseURL: "http://10.155.32.4:8031/",
  242. subUrl: "datacenter/tables",
  243. success(res){
  244. let JSFW = {
  245. text: '计算服务',
  246. children: []
  247. };
  248. let MHS_FDC = {
  249. text: "麻黄山",
  250. children: []
  251. };
  252. let NSS_FDC = {
  253. text: "牛首山",
  254. children: []
  255. };
  256. let QS_FDC = {
  257. text: "青山",
  258. children: []
  259. };
  260. let SBQ_FDC = {
  261. text: "石板泉",
  262. children: []
  263. };
  264. let XS_FDC = {
  265. text: "香山",
  266. children: []
  267. };
  268. let DWK_GDC = {
  269. text: "大武口",
  270. children: []
  271. };
  272. let PL_GDC = {
  273. name: "平罗",
  274. children: []
  275. };
  276. let XH_GDC = {
  277. text: "宣和",
  278. children: []
  279. };
  280. let MCH_GDC = {
  281. text: "马场湖",
  282. children: []
  283. };
  284. res.data.forEach(ele => {
  285. ele.text=ele.tablename;
  286. if (ele.windpowerstationid === 'MHS_FDC') {
  287. MHS_FDC.children.push(ele);
  288. } else if (ele.windpowerstationid === 'NSS_FDC') {
  289. NSS_FDC.children.push(ele);
  290. } else if (ele.windpowerstationid === 'QS_FDC') {
  291. QS_FDC.children.push(ele);
  292. } else if (ele.windpowerstationid === 'SBQ_FDC') {
  293. SBQ_FDC.children.push(ele);
  294. } else if (ele.windpowerstationid === 'XS_FDC') {
  295. XS_FDC.children.push(ele);
  296. } else if (ele.windpowerstationid === 'DWK_GDC') {
  297. DWK_GDC.children.push(ele);
  298. } else if (ele.windpowerstationid === 'PL_GDC') {
  299. PL_GDC.children.push(ele);
  300. } else if (ele.windpowerstationid === 'XH_GDC') {
  301. XH_GDC.children.push(ele);
  302. } else if (ele.windpowerstationid === 'MCH_GDC') {
  303. MCH_GDC.children.push(ele);
  304. } else {
  305. JSFW.children.push(ele);
  306. }
  307. });
  308. that.menus.push(JSFW, MHS_FDC, NSS_FDC, QS_FDC, SBQ_FDC, XS_FDC, DWK_GDC, PL_GDC, XH_GDC, MCH_GDC);
  309. }
  310. });
  311. },
  312. // 获取表格数据
  313. getTableData () {
  314. let that=this;
  315. that.API.requestData({
  316. baseURL:"http://10.155.32.4:8031/",
  317. subUrl:"datacenter/realtimeData",
  318. method:"GET",
  319. data:{
  320. tableid:that.tableid,
  321. pointId:that.pointId,
  322. pointName:that.form.pointName || "",
  323. pageNum:that.currentPage,
  324. pageSize:that.pagesizereal,
  325. },
  326. success(res){
  327. res.data.forEach((ele,index) => {
  328. ele.index = (index+1);
  329. ele.timeDate = that.fmtDate(new Date(ele.time));
  330. if (ele.value > 0) {
  331. ele.value = parseFloat(ele.value).toFixed(4);
  332. }
  333. });
  334. that.tableData.data = res.data || [];
  335. that.currentPageTotal = res.count || [];
  336. }
  337. });
  338. },
  339. // index渲染函数
  340. indexMethod (index) {
  341. return index + 1;
  342. },
  343. // 查看详情按钮被点击
  344. goDetails (row) {
  345. this.pointId = row.pointId;
  346. this.getDetails();
  347. },
  348. // 获取详情
  349. getDetails () {
  350. let that=this;
  351. if (!that.form.dateArea || !that.form.dateArea.length) {
  352. that.BASE.showMsg({
  353. msg:"请先选择要查询的日期区间后再试"
  354. });
  355. } else {
  356. let begin = (this.form.dateArea.length ? new Date(this.form.dateArea[0]).formatDate("yyyy-MM-dd hh:mm:ss") : '');
  357. let end = (this.form.dateArea.length ? new Date(this.form.dateArea[1]).formatDate("yyyy-MM-dd hh:mm:ss") : '');
  358. let data = {
  359. pointId:that.pointId || "",
  360. begin,
  361. end,
  362. };
  363. if(this.form.interval) data.interval = that.form.interval;
  364. that.API.requestData({
  365. baseURL:"http://10.155.32.4:8031/",
  366. subUrl:"datacenter/historyData",
  367. method:"GET",
  368. data,
  369. success(res){
  370. if (res.data.length) {
  371. res.data.forEach((ele,index) => {
  372. ele.index = (index+1);
  373. ele.timeDate = that.fmtDate(new Date(ele.time));
  374. if (ele.value > 0) {
  375. ele.value = parseFloat(ele.value).toFixed(4);
  376. }
  377. });
  378. that.detailsTableData.data = res.data || [];
  379. } else {
  380. that.BASE.showMsg({
  381. type:"warning",
  382. msg:"所选日期区间之内暂无数据,请重试"
  383. });
  384. }
  385. that.showDialog = true;
  386. }
  387. });
  388. }
  389. },
  390. // 初始页currentPage、初始每页数据数pagesize和数据data
  391. handleSizeChange: function (size) {
  392. this.pagesize = size;
  393. },
  394. handleSizerealChange: function (size) {
  395. this.currentPage = 1;
  396. this.pagesizereal = size;
  397. this.getTableData();
  398. },
  399. handleCurrentChange: function (currentPage) {
  400. this.currentPage = currentPage;
  401. },
  402. // 导出excel
  403. exportExcel (tableDataName) {
  404. let that = this;
  405. if (tableDataName === 'tableData') {
  406. let tableid = that.tableid;
  407. let pointId = that.form.pointId || '';
  408. let pointName = that.form.pointName || '';
  409. that.API.requestData({
  410. baseURL:"http://10.155.32.4:8031/",
  411. subUrl:"datacenter/realtimeExport",
  412. method:"GET",
  413. data:{
  414. tableid,
  415. pointId,
  416. pointName
  417. },
  418. success(res){
  419. const { export_json_to_excel } = require('@tools/excel/Export2Excel.js'); // 注意这个Export2Excel路径
  420. const tHeader = ['点名', '描述']; // 上面设置Excel的表格第一行的标题
  421. const filterVal = ['id', 'name']; // 上面的index、nickName、name是tableData里对象的属性key值
  422. const list = res.data; //把要导出的数据tableData存到list
  423. const data = that.formatJson(filterVal, list);
  424. export_json_to_excel(tHeader, data, '导出的Excel'); // 最后一个是表名字
  425. }
  426. });
  427. } else {
  428. const { export_json_to_excel } = require('@tools/excel/Export2Excel.js'); // 注意这个Export2Excel路径
  429. const tHeader = ['点名', '描述', '时间戳', '值']; // 上面设置Excel的表格第一行的标题
  430. const filterVal = ['pointId', 'pointName', 'timeDate', 'value']; // 上面的index、nickName、name是tableData里对象的属性key值
  431. const list = that[tableDataName].data; //把要导出的数据tableData存到list
  432. const data = that.formatJson(filterVal, list);
  433. export_json_to_excel(tHeader, data, '导出的Excel'); // 最后一个是表名字
  434. }
  435. },
  436. formatJson (filterVal, jsonData) {
  437. return jsonData.map(v => filterVal.map(j => v[j]));
  438. },
  439. // 刷新开关
  440. reReqAjax () {
  441. clearInterval(this.autoReqTimmer);
  442. this.autoReqTimmer = null;
  443. if (this.form.autoReq) {
  444. this.BASE.showMsg({
  445. type:"success",
  446. msg:"已开启自动刷新数据,每间隔 1 秒自动刷新一次数据"
  447. });
  448. this.autoReqTimmer = setInterval(() => {
  449. this.getTableData(true);
  450. }, 1000);
  451. } else {
  452. this.BASE.showMsg({
  453. type:"warning",
  454. msg:"已关闭自动刷新数据"
  455. });
  456. }
  457. },
  458. // 分页器每页数量修改
  459. getPaginationSize (value) {
  460. this.currentPageSize = value;
  461. this.getDetails();
  462. },
  463. // 分页器页数修改
  464. getPaginationCurrent (value) {
  465. this.currentPage = value;
  466. this.getTableData();
  467. },
  468. onChangePage(page) {
  469. this.getPaginationCurrent(page.pageIndex);
  470. },
  471. // 获取选中的时间
  472. getDatePickerChange (value) {
  473. this.detailsTableData.data = [];
  474. },
  475. // 渲染折线图
  476. renderCharts () {
  477. this.chartDialogShow = true;
  478. this.$nextTick(() => {
  479. let xAxisData = [];
  480. let seriesData = [];
  481. this.detailsTableData.data.forEach(ele => {
  482. xAxisData.push(ele.timeDate);
  483. seriesData.push(ele.value);
  484. });
  485. document.getElementById("lineChart").removeAttribute("_echarts_instance_");
  486. let chartDom = document.getElementById('lineChart');
  487. let myChart = echarts.init(chartDom);
  488. let option = {
  489. xAxis: {
  490. type: 'category',
  491. data: xAxisData
  492. },
  493. yAxis: {
  494. type: 'value'
  495. },
  496. series: [{
  497. data: seriesData,
  498. type: 'line',
  499. smooth: true,
  500. name: "值"
  501. }],
  502. tooltip: {
  503. trigger: 'axis',
  504. axisPointer: {
  505. type: 'cross',
  506. label: {
  507. backgroundColor: '#6a7985'
  508. }
  509. }
  510. }
  511. };
  512. option && myChart.setOption(option);
  513. });
  514. },
  515. // 格式化日期
  516. fmtDate (date) {
  517. let curDate = date || new Date();
  518. let year = curDate.getFullYear();
  519. let mouth = curDate.getUTCMonth() + 1;
  520. let day = curDate.getDate();
  521. let hour = curDate.getHours();
  522. let minutes = curDate.getMinutes();
  523. let seconds = curDate.getSeconds();
  524. return year + '-' + (mouth < 10 ? '0' + mouth : mouth) + '-' + (day < 10 ? '0' + day : day) + ' ' + (hour < 10 ? '0' + hour : hour) + ':' + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
  525. },
  526. // 点击左侧菜单
  527. clickMenu(item){
  528. this.tableid = item.tableid;
  529. this.getTableData();
  530. }
  531. }
  532. }
  533. </script>
  534. <style lang="less" scoped>
  535. .searchBox {
  536. width: 80%;
  537. display: flex;
  538. justify-content: start;
  539. align-items: center;
  540. position: relative;
  541. .btnBox {
  542. position: absolute;
  543. left: calc(100% + 20px);
  544. top: 0;
  545. display: flex;
  546. justify-content: start;
  547. align-items: center;
  548. }
  549. .el-input {
  550. width: 150px;
  551. }
  552. }
  553. .tableBox {
  554. margin-top: 10px;
  555. }
  556. .paginationBox {
  557. width: 100%;
  558. margin-top: 20px;
  559. display: flex;
  560. justify-content: flex-end;
  561. align-items: center;
  562. }
  563. .df-table {
  564. border: 0.093vh solid fade(@darkgray, 50%);
  565. position: relative;
  566. overflow: auto;
  567. width:calc(100% - 220px);
  568. height: 87vh;
  569. margin-left:20px;
  570. &:before {
  571. content: "";
  572. width: 0.37vh;
  573. height: 0.37vh;
  574. background: @write;
  575. position: absolute;
  576. left: 0.278vh;
  577. top: 0.278vh;
  578. }
  579. tbody {
  580. height: calc(100vh - 166px);
  581. }
  582. }
  583. </style>
  584. <style lang="less">
  585. .tableBox {
  586. .cell {
  587. text-align: center;
  588. }
  589. }
  590. .searchPage {
  591. margin-top: 1.481vh;
  592. display: flex;
  593. justify-content: start;
  594. align-items: flex-start;
  595. width:100%;
  596. .el-dialog__body {
  597. padding: 10px 20px;
  598. max-height: 570px;
  599. overflow: hidden;
  600. }
  601. }
  602. </style>