index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. <template>
  2. <div class="sy-content">
  3. <el-row>
  4. <el-col>
  5. <!-- 搜索信息 -->
  6. <el-form ref="chartForm" :model="chartForm" :rules="chartFormRules" size="small" :inline="true">
  7. <el-row>
  8. <el-col :span="4" :xs="8" :sm="6" :md="4" :lg="3" :xl="4">
  9. <el-form-item prop="trendType">
  10. <el-radio-group v-model="chartForm.trendType">
  11. <el-radio :label="0">实时趋势</el-radio>
  12. <el-radio :label="1">历史趋势</el-radio>
  13. </el-radio-group>
  14. </el-form-item>
  15. </el-col>
  16. <el-col v-if="chartForm.trendType == 0" :span="4">
  17. <el-form-item label="更新频率" prop="frequencyValue">
  18. <el-input v-model="chartForm.frequencyValue"></el-input>
  19. </el-form-item>
  20. </el-col>
  21. <el-col v-if="chartForm.trendType == 0" :span="1" :xl="2">
  22. <el-form-item prop="frequencyType">
  23. <el-select v-model="chartForm.frequencyType">
  24. <el-option v-for="timeType in timeTypeList" :key="timeType.value"
  25. :label="timeType.label" :value="timeType.value">
  26. </el-option>
  27. </el-select>
  28. </el-form-item>
  29. </el-col>
  30. <el-col v-if="chartForm.trendType == 0" :span="4">
  31. <el-form-item label="时间长度" prop="timeValue">
  32. <el-input v-model="chartForm.timeValue"></el-input>
  33. </el-form-item>
  34. </el-col>
  35. <el-col v-if="chartForm.trendType == 0" :span="2">
  36. <el-form-item prop="timeType">
  37. <el-select v-model="chartForm.timeType">
  38. <el-option v-for="timeType in timeTypeList" :key="timeType.value"
  39. :label="timeType.label" :value="timeType.value">
  40. </el-option>
  41. </el-select>
  42. </el-form-item>
  43. </el-col>
  44. <el-col v-if="chartForm.trendType == 1" :span="6">
  45. <el-form-item label="开始时间" prop="startTime">
  46. <el-date-picker value-format="yyyy-MM-dd HH:mm:ss" v-model="chartForm.startTime"
  47. type="datetime" placeholder="选择日期">
  48. </el-date-picker>
  49. </el-form-item>
  50. </el-col>
  51. <el-col v-if="chartForm.trendType == 1" :span="6">
  52. <el-form-item label="结束时间" prop="endTime">
  53. <el-date-picker value-format="yyyy-MM-dd HH:mm:ss" v-model="chartForm.endTime"
  54. type="datetime" placeholder="选择日期">
  55. </el-date-picker>
  56. </el-form-item>
  57. </el-col>
  58. </el-row>
  59. <el-row>
  60. <el-form-item label="数据项" prop="itemListTitile">
  61. <el-input :title="chartForm.itemListTitile" v-model="chartForm.itemListTitile" disabled
  62. placeholder="请选择数据项" maxlength="10">
  63. <el-button type="primary" slot="append" icon="el-icon-search"
  64. @click="chooseItemEvent">选择</el-button>
  65. </el-input>
  66. </el-form-item>
  67. <el-form-item label="小数位" prop="decimalPlaces">
  68. <el-input v-model="chartForm.decimalPlaces"></el-input>
  69. </el-form-item>
  70. <el-form-item label="量程" prop="range">
  71. <el-input v-model="chartForm.range"></el-input>
  72. </el-form-item>
  73. <el-form-item>
  74. <el-button type="primary" plain icon="el-icon-search" size="mini"
  75. @click="queryData">查询</el-button>
  76. <el-button type="primary" plain icon="el-icon-folder-opened" size="mini"
  77. @click="exportData">导出</el-button>
  78. </el-form-item>
  79. </el-row>
  80. </el-form>
  81. </el-col>
  82. </el-row>
  83. <!-- 添加数据项 -->
  84. <ChooseItem ref="chooseItem" @receiveCheckedData="receiveCheckedData"></ChooseItem>
  85. <!-- 统计图 -->
  86. <div class="lineChartContant" v-on:mouseover="mouseOver()" v-on:mouseout="mouseOut()">
  87. <div ref="chart" class="lineChart" />
  88. </div>
  89. </div>
  90. </template>
  91. <script>
  92. import { showLoading } from '@/utils/cqcy'
  93. import { parseTime } from "@/utils/index";
  94. import ChooseItem from './chooseItem.vue'
  95. import { getItemListValue } from '@/api/source/itemGroup'
  96. import qs from 'qs'
  97. import echarts from 'echarts'
  98. export default {
  99. created() {
  100. },
  101. components: {
  102. ChooseItem
  103. },
  104. data() {
  105. return {
  106. timer: null,
  107. //如果state为true,则是动态统计图。反之
  108. state: null,
  109. count: 0,
  110. itemGroupList: [],
  111. trendTypeList: [
  112. { label: '实时趋势', value: 0 },
  113. { label: '历史趋势', value: 1 }
  114. ],
  115. timeTypeList: [
  116. { label: '秒', value: 0 },
  117. { label: '分', value: 1 },
  118. { label: '时', value: 2 },
  119. { label: '天', value: 3 }
  120. ],
  121. itemList: [],
  122. chartForm: {
  123. itemListTitile: '',
  124. idList: [],
  125. decimalPlaces: 0,
  126. trendType: 0,
  127. range: null,
  128. frequencyValue: 1,
  129. frequencyType: 0,
  130. timeValue: 60,
  131. timeType: 0,
  132. startTime: null,
  133. endTime: null
  134. },
  135. chooseStartTime: null,
  136. chooseEndTime: null,
  137. chartFormRules: {
  138. frequencyValue: [
  139. { required: true, message: '更新频率值不能为空', trigger: 'blur' }
  140. ],
  141. frequencyType: [
  142. { required: true, message: '更新频率类型不能为空', trigger: 'blur' }
  143. ],
  144. timeValue: [
  145. { required: true, message: '时间值不能为空', trigger: 'blur' }
  146. ],
  147. timeType: [
  148. { required: true, message: '时间类型不能为空', trigger: 'blur' }
  149. ],
  150. startTime: [
  151. { required: true, message: '开始时间不能为空', trigger: 'blur' }
  152. ],
  153. endTime: [
  154. { required: true, message: '结束时间不能为空', trigger: 'blur' }
  155. ],
  156. decimalPlaces: [
  157. ],
  158. range: [
  159. ],
  160. },
  161. //charts
  162. chart: null,
  163. //背景颜色
  164. backgroundColor: '#394056',
  165. //统计图标题
  166. title: {
  167. top: 20,
  168. text: '数据查询',
  169. textStyle: {
  170. fontWeight: 'normal',
  171. fontSize: 16,
  172. color: '#F1F1F3'
  173. },
  174. left: '1%'
  175. },
  176. //工具提示
  177. tooltip: {
  178. show: true,
  179. trigger: 'axis',
  180. backgroundColor: 'rgba(255, 255, 255, 0.8)',
  181. axisPointer: {
  182. type: 'cross',
  183. label: {
  184. backgroundColor: '#777'
  185. },
  186. }
  187. },
  188. //列标题
  189. legend: {
  190. top: 20,
  191. icon: 'rect',
  192. itemWidth: 14,
  193. itemHeight: 5,
  194. itemGap: 13,
  195. data: [],
  196. right: '4%',
  197. textStyle: {
  198. fontSize: 12,
  199. color: '#FFFFFF'
  200. }
  201. },
  202. //布局
  203. grid: {
  204. top: 100,
  205. left: '2%',
  206. right: '2%',
  207. bottom: '2%',
  208. containLabel: true
  209. },
  210. //缩放组件
  211. dataZoom: [{
  212. type: 'inside', // 放大和缩小
  213. orient: 'vertical',
  214. }, {
  215. type: 'inside',
  216. }],
  217. //x轴
  218. xAxis: {
  219. type: 'category',
  220. boundaryGap: false,
  221. axisLine: {
  222. lineStyle: {
  223. color: '#FFFFFF'
  224. }
  225. },
  226. data: []
  227. },
  228. //y轴
  229. yAxis: [{
  230. type: 'value',
  231. //是否显示坐标轴刻度。
  232. axisTick: {
  233. show: true
  234. },
  235. axisLine: {
  236. lineStyle: {
  237. color: '#FFFFFF'
  238. }
  239. },
  240. axisLabel: {
  241. margin: 10,
  242. textStyle: {
  243. fontSize: 14
  244. }
  245. },
  246. splitLine: {
  247. lineStyle: {
  248. color: '#57617B'
  249. }
  250. }
  251. }],
  252. //数据列
  253. series: []
  254. }
  255. },
  256. methods: {
  257. /** 接受传过来的数据 */
  258. receiveCheckedData(data) {
  259. this.itemList = data
  260. let arr = []
  261. let b = ''
  262. for (let i in data) {
  263. const a = data[i]
  264. arr.push(a.id)
  265. if (i == data.length - 1) {
  266. b += a.itemGroupId + "." + a.itemReadName
  267. } else {
  268. b += a.itemGroupId + "." + a.itemReadName + ","
  269. }
  270. }
  271. this.chartForm.idList = arr
  272. this.chartForm.itemListTitile = b
  273. },
  274. /** 选择数据项事件 */
  275. chooseItemEvent() {
  276. this.$refs.chooseItem.selectedItemList = this.itemList
  277. this.$refs.chooseItem.visible = true
  278. },
  279. /** 查询数据 */
  280. queryData() {
  281. //每次查询的时候,将统计图初清空,定时器清空
  282. this.stopTimer()
  283. this.destroyChart()
  284. if (this.chartForm.idList.length == 0) {
  285. this.$message({
  286. message: '请选择数据项',
  287. type: 'warning'
  288. })
  289. return
  290. }
  291. //如果为实时趋势
  292. if (this.chartForm.trendType == 0) {
  293. if (!this.chartForm.frequencyValue) {
  294. this.$message({
  295. message: '频率不能为空',
  296. type: 'warning'
  297. })
  298. return
  299. }
  300. if (!this.chartForm.timeValue) {
  301. this.$message({
  302. message: '时间长度不能为空',
  303. type: 'warning'
  304. })
  305. return
  306. }
  307. let currentTime = new Date().getTime()
  308. this.count = this.timeCalculation(this.chartForm.timeValue, this.chartForm.timeType)
  309. this.chooseStartTime = parseTime(new Date(currentTime - this.count))
  310. this.chooseEndTime = parseTime(currentTime)
  311. //添加监听事件
  312. this.state = true
  313. //初始化统计图
  314. this.initChart()
  315. //如果为历史趋势
  316. } else if (this.chartForm.trendType == 1) {
  317. if (!this.chartForm.startTime) {
  318. this.$message({
  319. message: '请选择开始时间',
  320. type: 'warning'
  321. })
  322. return
  323. }
  324. if (!this.chartForm.endTime) {
  325. this.$message({
  326. message: '请选择结束时间',
  327. type: 'warning'
  328. })
  329. return
  330. }
  331. this.chooseStartTime = this.chartForm.startTime
  332. this.chooseEndTime = this.chartForm.endTime
  333. //展示死统计图,且不添加监听事件
  334. this.state = false
  335. this.initChart()
  336. }
  337. },
  338. /** 通过数据项id,开始结束时间获取相应的数据 */
  339. getItemListValue(callback) {
  340. if (this.chooseStartTime == this.chooseEndTime) {
  341. return
  342. }
  343. let param = {
  344. itemGroupId: this.chartForm.itemGroupId,
  345. idList: this.chartForm.idList,
  346. startTime: this.chooseStartTime,
  347. endTime: this.chooseEndTime
  348. }
  349. let params = qs.stringify(param, { arrayFormat: 'repeat' })
  350. getItemListValue(params).then(res => {
  351. callback(res);
  352. })
  353. },
  354. /** 初始化统计图,如果state为true,则是动态,否则是静态 */
  355. initChart() {
  356. const loading = showLoading(this, "加载中,请稍候···")
  357. this.getItemListValue((res) => {
  358. let data = res.data
  359. this.chart = echarts.init(this.$refs.chart)
  360. let legendData = []
  361. let seriesData = []
  362. for (let a of data) {
  363. legendData.push(a.describe ? a.describe : a.itemReadName)
  364. let b = {
  365. name: a.unit ? ((a.describe ? a.describe : a.itemReadName) + '(' + a.unit + ')') :
  366. (a.describe ? a.describe : a.itemReadName),
  367. type: 'line',
  368. smooth: true,
  369. symbol: 'circle',
  370. symbolSize: 5,
  371. showSymbol: false,
  372. itemStyle: {
  373. color: this.getColor()
  374. },
  375. lineStyle: {
  376. normal: {
  377. width: 1
  378. }
  379. },
  380. data: a.dataValueList
  381. }
  382. seriesData.push(b)
  383. }
  384. // let decimalPlaces = this.chartForm.decimalPlaces
  385. this.tooltip.formatter = function (params, ticket, callback) {
  386. let b = '<div style="display:inline;">'
  387. for (let a of params) {
  388. b += '<div><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:' + a.color + ';"></span><span style="color:' + a.color + '">'
  389. + a.name + ' ' + a.seriesName + ': ' + a.data + '</span></div>'
  390. }
  391. b += '</div>'
  392. return b
  393. }
  394. this.legend.data = legendData
  395. this.xAxis.data = data[0].dataTimeList
  396. this.series = seriesData
  397. this.chart.setOption({
  398. backgroundColor: this.backgroundColor,
  399. title: this.title,
  400. tooltip: this.tooltip,
  401. legend: this.legend,
  402. grid: this.grid,
  403. dataZoom: this.dataZoom,
  404. xAxis: this.xAxis,
  405. yAxis: this.yAxis,
  406. series: this.series
  407. })
  408. if (this.state) {
  409. //启动定时器,轮训更新统计图
  410. this.startTimer()
  411. }
  412. loading.close()
  413. })
  414. },
  415. /** 生成颜色方法 */
  416. getColor() {
  417. const r = this.colorRandom(128, 255)
  418. const g = this.colorRandom(0, 63)
  419. const b = this.colorRandom(128, 255)
  420. return "rgb(" + r + ", " + g + ", " + b + ")"
  421. },
  422. /** 颜色数字随机方法 */
  423. colorRandom(minValue, maxValue) {
  424. return Math.floor((Math.random() * (maxValue - minValue)) + minValue)
  425. },
  426. /** 鼠标移入事件 */
  427. mouseOver() {
  428. if (this.state) {
  429. this.stopTimer()
  430. }
  431. },
  432. /** 鼠标移出事件 */
  433. mouseOut() {
  434. if (this.state) {
  435. this.startTimer()
  436. }
  437. },
  438. /** 清除统计图 */
  439. destroyChart() {
  440. if (!this.chart) {
  441. return
  442. }
  443. this.chart.dispose()
  444. this.chart = null
  445. },
  446. /** 清除定时器 */
  447. stopTimer() {
  448. clearInterval(this.timer)
  449. this.timer = null
  450. },
  451. /** 设置定时器,继续轮训数据 */
  452. startTimer() {
  453. this.timer = setInterval(() => {
  454. this.chooseStartTime = this.chooseEndTime
  455. this.chooseEndTime = parseTime(new Date())
  456. this.updateChartData()
  457. }, this.timeCalculation(this.chartForm.frequencyValue, this.chartForm.frequencyType))
  458. },
  459. /** 选择时间类型之后得到时间搓 */
  460. timeCalculation(value, type) {
  461. if (type == 0) {
  462. return value * 1000
  463. } else if (type == 1) {
  464. return value * 60 * 1000
  465. } else if (type == 2) {
  466. return value * 60 * 60 * 1000
  467. } else if (type == 3) {
  468. return value * 60 * 60 * 24 * 1000
  469. }
  470. },
  471. /** 更新统计图数据 */
  472. updateChartData() {
  473. this.getItemListValue((res) => {
  474. let data = res.data
  475. if (data && data[0].dataTimeList) {
  476. let arrX = this.xAxis.data
  477. arrX = arrX.concat(data[0].dataTimeList)
  478. //删除掉多余时间
  479. let count = new Date(arrX[arrX.length - 1]).getTime() - this.count
  480. let num = 0
  481. for (let i in arrX) {
  482. if (new Date(arrX[i]).getTime() >= count) {
  483. num = i
  484. break
  485. }
  486. }
  487. this.xAxis.data = arrX.splice(num)
  488. //删除多余数据
  489. for (let i in data) {
  490. let a = data[i]
  491. let arr = this.series[i].data
  492. arr = arr.concat(a.dataValueList)
  493. this.series[i].data = arr.splice(num)
  494. }
  495. //更新统计图
  496. this.chart.setOption({ xAxis: this.xAxis, series: this.series });
  497. }
  498. })
  499. },
  500. /** 导出统计图数据 */
  501. exportData() {
  502. console.log("---导出统计图-----")
  503. }
  504. },
  505. destroyed: function () {
  506. // 每次离开当前界面时,清除定时器
  507. clearInterval(this.timer)
  508. this.timer = null
  509. }
  510. }
  511. </script>
  512. <style rel="stylesheet/scss" lang="scss" scoped>
  513. .lineChartContant {
  514. width: 180vh;
  515. height: 75vh;
  516. .lineChart {
  517. width: 100%;
  518. height: 100%;
  519. }
  520. }
  521. </style>