widget.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <template>
  2. <div>
  3. <div class="params-panel">
  4. <div class="head-title">站点设置</div>
  5. <el-form ref="form" :model="form" label-width="auto" size="small">
  6. <el-form-item label="监测站点:">
  7. <el-select
  8. v-model="form.siteId"
  9. filterable
  10. placeholder="选择站点"
  11. style="width:100%"
  12. @change="selectSite"
  13. >
  14. <el-option
  15. v-for="(item,index) in siteOption"
  16. :key="index"
  17. :label="item.siteName"
  18. :value="item.id"
  19. ></el-option>
  20. </el-select>
  21. </el-form-item>
  22. <el-form-item label="时间设置:" style="line-height:78px;">
  23. <el-radio-group v-model="cycle">
  24. <el-radio :label="3">24小时水质变化规律</el-radio>
  25. <el-radio :label="2">7日水质变化规律</el-radio>
  26. <el-radio :label="1">30日水质变化规律</el-radio>
  27. </el-radio-group>
  28. </el-form-item>
  29. <el-form-item label="时段设置:" style="line-height:93px;">
  30. <div class="timeset-btns">
  31. <el-button type="text" icon="el-icon-plus" @click="dialogVisible=true"></el-button>
  32. <el-button type="text" icon="el-icon-minus" @click="removeTime()"></el-button>
  33. <span style="color:#606266">(说明:每个时段代表一条新线)</span>
  34. </div>
  35. <div class="time-container">
  36. <ul>
  37. <li v-for="(item,index) in timeItems" :key="index">
  38. <el-checkbox v-model="item.checked" v-cloak>时段:{{item.beginTime}}-{{item.endTime}}</el-checkbox>
  39. </li>
  40. </ul>
  41. </div>
  42. </el-form-item>
  43. <el-form-item label-width="0" style="text-align:right;">
  44. <el-button type="primary" @click="query()">查询</el-button>
  45. <el-button type="primary" @click="clear()">清空</el-button>
  46. </el-form-item>
  47. </el-form>
  48. </div>
  49. <!-- 结果 -->
  50. <div class="result-panel">
  51. <div class="head-title" style="height:32px;line-height:32px;">
  52. <span>对比结果</span>
  53. <div style="float:right;font-weight:500">
  54. <span>统计方式:</span>
  55. <el-select v-model="granularity" size="small" style="width:120px">
  56. <el-option label="按小时统计" :value="2"></el-option>
  57. <el-option label="按日统计" :value="1"></el-option>
  58. </el-select>
  59. </div>
  60. </div>
  61. <!-- 结果 -->
  62. <div class="result-box">
  63. <div class="empty" v-if="targetVos.length==0"></div>
  64. <div v-for="(item,index) in targetVos" :key="index" :id="'chart'+index" class="chart-box"></div>
  65. </div>
  66. </div>
  67. <!-- 时间选择 -->
  68. <el-dialog title="选择统计时间区段" :visible.sync="dialogVisible" width="500px">
  69. <el-form :inline="true" label-width="80px" size="small">
  70. <el-form-item label="日期范围">
  71. <el-date-picker
  72. v-model="date"
  73. type="daterange"
  74. align="right"
  75. unlink-panels
  76. range-separator="-"
  77. start-placeholder="开始日期"
  78. end-placeholder="结束日期"
  79. :picker-options="pickerOptions"
  80. value-format="yyyy/MM/dd"
  81. format="yyyy/MM/dd"
  82. :clearable="false"
  83. ></el-date-picker>
  84. </el-form-item>
  85. </el-form>
  86. <span slot="footer" class="dialog-footer">
  87. <el-button @click="dialogVisible = false" size="small">取 消</el-button>
  88. <el-button type="primary" size="small" @click="selectTime()">确 定</el-button>
  89. </span>
  90. </el-dialog>
  91. <historyCurve ref="historyCurve"></historyCurve>
  92. </div>
  93. </template>
  94. <script>
  95. import { getSites, getSiteNewData } from '@/views/spectrum/dynamicMonitor/api/api'
  96. import { getSiteManyCurve } from '@/views/spectrum/statisticalAnalysis/api/api'
  97. import { getSiteIcon } from '@/views/spectrum/common/siteIcon/siteIcon' // 站点图标
  98. import { MapPopup } from '@/views/spectrum/common/mapPopup/mapPopup'
  99. import historyCurve from '@/views/spectrum/common/historyCurve/index'
  100. import { creatTipMonitor } from '@/views/spectrum/common/mapPopup/getPopupInfo'
  101. export default {
  102. components: {
  103. historyCurve
  104. },
  105. data() {
  106. return {
  107. pickerOptions: {
  108. shortcuts: [
  109. {
  110. text: '今天',
  111. onClick(picker) {
  112. const start = new Date()
  113. const end = new Date()
  114. picker.$emit('pick', [start, end])
  115. }
  116. },
  117. {
  118. text: '最近一周',
  119. onClick(picker) {
  120. const end = new Date()
  121. const start = new Date()
  122. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
  123. picker.$emit('pick', [start, end])
  124. }
  125. },
  126. {
  127. text: '最近一个月',
  128. onClick(picker) {
  129. const end = new Date()
  130. const start = new Date()
  131. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
  132. picker.$emit('pick', [start, end])
  133. }
  134. },
  135. {
  136. text: '最近一年',
  137. onClick(picker) {
  138. const end = new Date()
  139. const start = new Date()
  140. start.setTime(start.getTime() - 3600 * 1000 * 24 * 365)
  141. picker.$emit('pick', [start, end])
  142. }
  143. }
  144. ]
  145. },
  146. form: {},
  147. cycle: 3,
  148. granularity: 2,
  149. timeItems: [],
  150. date: [],
  151. dialogVisible: false,
  152. siteOption: [],
  153. targetVos: [],
  154. popup: null, // 弹窗
  155. handler: null
  156. }
  157. },
  158. created() {},
  159. mounted() {
  160. this.getSites()
  161. this.initClick()
  162. },
  163. destroyed() {
  164. window.viewer.entities.removeAll()
  165. if (this.popup) this.popup.destroy()
  166. if (this.handler) this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
  167. },
  168. methods: {
  169. /**
  170. * 获取站点
  171. */
  172. getSites() {
  173. getSites({ projectId: this.$store.state.project.project.id, size: 1000 }).then((res) => {
  174. if (res.code && res.code == 1) {
  175. this.siteOption = res.result.records
  176. // if (this.siteOption.length > 0) {
  177. // this.$set(this.form, 'siteId', this.siteOption[0].id)
  178. // }
  179. }
  180. })
  181. },
  182. /**
  183. * 选择站点
  184. */
  185. selectSite(val) {
  186. let site = this.siteOption.find((item) => {
  187. return item.id == val
  188. })
  189. this.showSite(site)
  190. },
  191. /**
  192. * 监听站点点击事件
  193. */
  194. initClick() {
  195. let viewer = window.viewer
  196. this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
  197. this.handler.setInputAction((movement) => {
  198. var pick = viewer.scene.pick(movement.position)
  199. if (Cesium.defined(pick)) {
  200. // 本组件定义弹窗存在先移除
  201. if (this.popup) {
  202. this.popup.destroy()
  203. }
  204. let siteId = pick.id.id
  205. let siteData = this.siteOption.find((item) => {
  206. return item.id == siteId
  207. })
  208. if (siteData) {
  209. // 展示实时数据
  210. this.getSiteNewData([siteData])
  211. }
  212. }
  213. }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  214. },
  215. /**
  216. * 获取站点实时数据
  217. */
  218. getSiteNewData(sites) {
  219. let ids = sites.map((item) => {
  220. return item.id
  221. })
  222. getSiteNewData({ sites: ids.join(',') }).then((res) => {
  223. if (res.code && res.code == 1) {
  224. let result = res.result
  225. creatTipMonitor(sites, result, (data, tipHtml) => {
  226. let viewer = window.viewer
  227. this.popup = new MapPopup({
  228. lon: data.longitude,
  229. lat: data.latitude,
  230. viewer: viewer,
  231. title: data.siteName,
  232. html: tipHtml,
  233. cureBtnClick: () => {
  234. // 查看历史曲线
  235. this.$refs.historyCurve.show(data.id)
  236. }
  237. })
  238. })
  239. }
  240. })
  241. },
  242. /**
  243. * 选择时间区间
  244. */
  245. selectTime() {
  246. if (this.date.length == 2) {
  247. let timeItem = {
  248. checked: false,
  249. beginTime: this.date[0],
  250. endTime: this.date[1]
  251. }
  252. this.timeItems.push(timeItem)
  253. this.dialogVisible = false
  254. this.date = []
  255. }
  256. },
  257. /**
  258. * 移除时间段
  259. */
  260. removeTime() {
  261. let selection = this.timeItems.filter((item) => {
  262. return item.checked == true
  263. })
  264. if (selection.length == 0) {
  265. this.$message.info('请选择要移除的时间段!')
  266. return
  267. }
  268. this.timeItems = this.timeItems.filter((item) => {
  269. return item.checked == false
  270. })
  271. },
  272. /**
  273. * 查询
  274. */
  275. query() {
  276. if (!this.form.siteId) {
  277. this.$message.info('请选择检测站点!')
  278. return
  279. }
  280. if (this.timeItems.length == 0) {
  281. this.$message.info('请选择时间区段!')
  282. return
  283. }
  284. let data = {
  285. cycle: this.cycle,
  286. granularity: this.granularity,
  287. siteId: this.form.siteId,
  288. times: this.timeItems.map((item) => {
  289. return {
  290. beginTime: this.$moment(item.beginTime).format('YYYY-MM-DD'),
  291. endTime: this.$moment(item.endTime).format('YYYY-MM-DD')
  292. }
  293. })
  294. }
  295. getSiteManyCurve(data).then((res) => {
  296. if (res.code && res.code == 1) {
  297. let siteData = res.result
  298. if (siteData) {
  299. this.targetVos = siteData.targetVos // 名称
  300. let collectionDates = siteData.data_x //时间
  301. let datas = siteData.datas[0] //数据
  302. this.targetVos.forEach((item, index) => {
  303. let columnName = `${item.targetCode}s`
  304. let series = []
  305. datas.forEach((item2, index2) => {
  306. let _data = item2[columnName].map((item3) => {
  307. return item3 || 0
  308. })
  309. let seriesdata = {
  310. name: `${item.targetName}${index2 + 1}`,
  311. type: 'line',
  312. data: _data
  313. }
  314. series.push(seriesdata)
  315. })
  316. let chartData = {
  317. seriesdata: series,
  318. collectionDates: collectionDates
  319. }
  320. this.$nextTick(() => {
  321. this.loadChart(chartData, item, index)
  322. })
  323. })
  324. }
  325. }
  326. })
  327. },
  328. loadChart(chartData, target, domIndex) {
  329. let chartDom = document.getElementById('chart' + domIndex)
  330. let myChart = this.$echarts.init(chartDom)
  331. let colorAry = ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc']
  332. let option = {
  333. title: {
  334. show: 'true', //是否显示标题,默认显示,可以不设置
  335. text: `${target.targetName}(${target.targetCode})`, //图表标题文本内容
  336. textStyle: {
  337. color: '#3E84D2',
  338. fontSize: '12px',
  339. fontWeight: 600
  340. }
  341. },
  342. tooltip: {
  343. trigger: 'axis'
  344. },
  345. color: colorAry,
  346. grid: {
  347. top: 35,
  348. bottom: 30,
  349. left: 30,
  350. right: 30
  351. },
  352. xAxis: {
  353. type: 'category',
  354. boundaryGap: false,
  355. data: chartData.collectionDates
  356. },
  357. yAxis: {
  358. type: 'value'
  359. },
  360. series: chartData.seriesdata
  361. }
  362. myChart.clear()
  363. option && myChart.setOption(option)
  364. },
  365. /**
  366. * 清除
  367. */
  368. clear() {
  369. this.timeItems = []
  370. this.targetVos = []
  371. },
  372. /**
  373. * 定位选择的站点
  374. */
  375. showSite(site) {
  376. let icon = getSiteIcon(site)
  377. let viewer = window.viewer
  378. let lon = site.longitude || null
  379. let lat = site.latitude || null
  380. if (!lon || !lat) {
  381. this.$message.warning('无坐标信息,无法定位!')
  382. return
  383. }
  384. let entity = viewer.entities.getById(site.id)
  385. if (!entity) {
  386. const position = Cesium.Cartesian3.fromDegrees(lon, lat, 0)
  387. entity = new Cesium.Entity({
  388. id: site.id,
  389. position: position,
  390. billboard: {
  391. image: icon,
  392. width: 40,
  393. height: 70,
  394. heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
  395. eyeOffset: Cesium.Cartesian3.ZERO
  396. }
  397. })
  398. viewer.entities.removeAll()
  399. viewer.entities.add(entity)
  400. }
  401. // 本组件定义弹窗存在先移除
  402. if (this.popup) {
  403. this.popup.destroy()
  404. }
  405. viewer.flyTo(entity, {
  406. offset: {
  407. heading: Cesium.Math.toRadians(0.0),
  408. pitch: Cesium.Math.toRadians(-25),
  409. range: 3000
  410. }
  411. })
  412. }
  413. }
  414. }
  415. </script>
  416. <style lang="scss" scoped>
  417. @import './css.scss';
  418. </style>