index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <template>
  2. <div
  3. class="bs-design-wrap bs-bar"
  4. style="width: 100%; height: 100%"
  5. >
  6. <el-button v-if="currentDeep > 0" class="button" type='text' @click="jumpTo(config)"> 返回上一级</el-button>
  7. <div
  8. :id="`chart${config.code}`"
  9. style="width: 100%; height: 100%"
  10. />
  11. </div>
  12. </template>
  13. <script>
  14. import 'insert-css'
  15. import * as echarts from 'echarts'
  16. import {nameMap} from './json/mapData.js'
  17. import commonMixins from 'data-room-ui/js/mixins/commonMixins.js'
  18. import paramsMixins from 'data-room-ui/js/mixins/paramsMixins'
  19. import linkageMixins from 'data-room-ui/js/mixins/linkageMixins'
  20. export default {
  21. name: 'MapCharts',
  22. mixins: [paramsMixins, commonMixins, linkageMixins],
  23. props: {
  24. id: {
  25. type: String,
  26. default: ''
  27. },
  28. config: {
  29. type: Object,
  30. default: () => ({})
  31. }
  32. },
  33. data() {
  34. return {
  35. charts: null,
  36. hasData: false,
  37. level: '',
  38. option: {},
  39. mapList: [],
  40. currentDeep: 0,
  41. }
  42. },
  43. computed: {
  44. Data() {
  45. return JSON.parse(JSON.stringify(this.config))
  46. }
  47. },
  48. watch: {
  49. Data: {
  50. handler(newVal, oldVal) {
  51. if (newVal.w !== oldVal.w || newVal.h !== oldVal.h) {
  52. this.$nextTick(() => {
  53. this.charts.resize()
  54. })
  55. }
  56. },
  57. deep: true
  58. }
  59. },
  60. mounted() {
  61. this.chartInit()
  62. },
  63. beforeDestroy() {
  64. this.charts?.clear()
  65. },
  66. methods: {
  67. chartInit() {
  68. const config = this.config
  69. // key和code相等,说明是一进来刷新,调用list接口
  70. if (this.config.code === this.config.key || this.isPreview) {
  71. // 改变数据
  72. this.changeDataByCode(config).then((res) => {
  73. // 改变样式
  74. // config = this.changeStyle(res)
  75. this.newChart(config)
  76. }).catch(() => {
  77. })
  78. } else {
  79. // 否则说明是更新,这里的更新只指更新数据(改变样式时是直接调取changeStyle方法),因为更新数据会改变key,调用chart接口
  80. this.changeData(config).then((res) => {
  81. // 初始化图表
  82. this.newChart(res)
  83. })
  84. }
  85. },
  86. dataFormatting(config, data) {
  87. config.option = {
  88. ...config.option,
  89. data: data?.data
  90. }
  91. return config
  92. },
  93. async jumpTo(config) {
  94. this.currentDeep--
  95. let map = this.mapList[this.currentDeep]
  96. // 移除mapList中的最后一个元素
  97. this.mapList.pop()
  98. let mapData = JSON.parse(map.geoJson)
  99. this.option.geo.map = map.name;
  100. this.changeData({...config, customize: {...config.customize, level: map.level, scope: map.name}})
  101. echarts.registerMap(map.name, mapData);
  102. this.charts.setOption(this.option, true);
  103. },
  104. async newChart(config) {
  105. this.charts = echarts.init(
  106. document.getElementById(`chart${this.config.code}`)
  107. )
  108. this.level = config.customize.level
  109. const lines_coord = []
  110. let fromCoord = []
  111. let coord = []
  112. let hasMapId = !!config.customize.mapId
  113. // 根据mapId获取地图数据
  114. let mapInfoUrl = `${window.BS_CONFIG?.httpConfigs?.baseURL}/bigScreen/map/info/${config.customize.mapId}`
  115. // 如果设置了地图id,就用地图id获取地图数据,否则用默认的世界地图
  116. if (!hasMapId) {
  117. mapInfoUrl = `${window.BS_CONFIG?.httpConfigs?.baseURL}/static/worldMap/world.json`
  118. }
  119. this.$dataRoomAxios.get(mapInfoUrl, {}, true).then(res => {
  120. if (this.config.option.data) {
  121. this.config.option.data.forEach(val => {
  122. lines_coord.push({value: val.value, msg: {...val}, coords: [[val.lat1, val.lng1], [val.lat2, val.lng2]]})
  123. if (val.type === 'move_in') {
  124. coord.push({name: val.from, value: [val.lat1, val.lng1, val.value], msg: {...val}})
  125. fromCoord.push({name: val.to, value: [val.lat2, val.lng2, val.value], msg: {...val}})
  126. } else {
  127. coord.push({name: val.to, value: [val.lat2, val.lng2, val.value], msg: {...val}})
  128. fromCoord.push({name: val.from, value: [val.lat1, val.lng1, val.value], msg: {...val}})
  129. }
  130. })
  131. }
  132. let mapData = hasMapId ? JSON.parse(res.data.geoJson) : res
  133. if (hasMapId && res.data.uploadedGeoJson !== 1) {
  134. // 没有上传过geoJson
  135. this.$message({
  136. message: '请先上传地图数据',
  137. type: 'warning'
  138. })
  139. return
  140. }
  141. this.mapList.push(res.data)
  142. echarts.registerMap(config.customize.scope, mapData)
  143. this.option = {
  144. nameMap: config.customize.level == '0' ? nameMap : '',
  145. // graphic: [
  146. // ],
  147. geo: {
  148. map: config.customize.scope,
  149. zlevel: 10,
  150. show: true,
  151. layoutCenter: ['50%', '50%'],
  152. roam: true,
  153. layoutSize: "100%",
  154. zoom: 1,
  155. label: {
  156. // 通常状态下的样式
  157. normal: {
  158. show: config.customize.mapName,
  159. textStyle: {
  160. color: '#fff'
  161. }
  162. },
  163. // 鼠标放上去的样式
  164. emphasis: {
  165. textStyle: {
  166. color: '#fff'
  167. }
  168. }
  169. },
  170. // 地图区域的样式设置
  171. itemStyle: {
  172. normal: {
  173. borderColor: config.customize.mapLineColor,
  174. borderWidth: 1,
  175. areaColor: config.customize.areaColor,
  176. shadowColor: 'fffff',
  177. shadowOffsetX: -2,
  178. shadowOffsetY: 2,
  179. shadowBlur: 10
  180. },
  181. // 鼠标放上去高亮的样式
  182. emphasis: {
  183. areaColor: '#389BB7',
  184. borderWidth: 0
  185. }
  186. }
  187. },
  188. tooltip: {
  189. backgroundColor: config.customize.tooltipBackgroundColor,
  190. borderColor: config.customize.borderColor,
  191. show: true,
  192. textStyle: {
  193. color: config.customize.fontColor,
  194. },
  195. },
  196. series: [
  197. {
  198. type: 'effectScatter',
  199. coordinateSystem: 'geo',
  200. zlevel: 15,
  201. symbolSize: 8,
  202. rippleEffect: {
  203. period: 4, brushType: 'stroke', scale: 4
  204. },
  205. tooltip: {
  206. trigger: 'item',
  207. formatter(params) {
  208. const a = eval(config.customize.scatterFormatter)
  209. return a
  210. },
  211. },
  212. itemStyle: {
  213. color: config.customize.scatterColor,
  214. opacity: 1
  215. },
  216. data: coord
  217. },
  218. {
  219. type: 'effectScatter',
  220. coordinateSystem: 'geo',
  221. zlevel: 15,
  222. symbolSize: 12,
  223. tooltip: {
  224. trigger: 'item',
  225. formatter(params) {
  226. const a = eval(config.customize.scatterFormatter)
  227. return a
  228. },
  229. },
  230. rippleEffect: {
  231. period: 6, brushType: 'stroke', scale: 8
  232. },
  233. itemStyle: {
  234. color: config.customize.scatterCenterColor,
  235. opacity: 1
  236. },
  237. data: fromCoord
  238. },
  239. {
  240. type: 'lines',
  241. coordinateSystem: 'geo',
  242. zlevel: 15,
  243. tooltip: {
  244. trigger: 'item',
  245. formatter(params) {
  246. const a = eval(config.customize.lineFormatter)
  247. return a
  248. },
  249. },
  250. effect: {
  251. show: true,
  252. period: 5,
  253. trailLength: 0,
  254. symbol: config.customize.symbol,
  255. color: config.customize.symbolColor,
  256. symbolSize: config.customize.symbolSize,
  257. },
  258. lineStyle: {
  259. normal: {
  260. color: function (value) {
  261. return '#ffffff'
  262. }, width: 2, opacity: 0.6, curveness: 0.2
  263. }
  264. },
  265. data: lines_coord
  266. }
  267. ]
  268. }
  269. if (config.customize.visual) {
  270. this.option.visualMap = {
  271. show: false,
  272. min: config.customize.range[0],
  273. max: config.customize.range[1],
  274. seriesIndex: [0, 2],
  275. inRange: {
  276. color: config.customize.rangeColor
  277. }
  278. }
  279. }
  280. this.charts.setOption(this.option)
  281. // 点击下钻
  282. this.charts.on('click', async (params) => {
  283. if (params.name == '') return
  284. if (!config.customize.down) {
  285. this.$message({
  286. message: '该地图未开启下钻',
  287. type: 'warning'
  288. })
  289. return
  290. }
  291. // 到达允许下钻的层数,则不再下钻
  292. if (this.currentDeep >= config.customize.downLevel) return
  293. const mapUrl = `${window.BS_CONFIG?.httpConfigs?.baseURL}/bigScreen/map/data/${this.mapList[this.currentDeep].id}/${params.name}`
  294. const map = await this.$dataRoomAxios.get(decodeURI(mapUrl), {}, false)
  295. // 地图不可用
  296. if (map.available !== 1) {
  297. this.$message({
  298. message: '未找到该地图配置',
  299. type: 'warning'
  300. })
  301. return
  302. }
  303. this.currentDeep++
  304. this.mapList.push(map)
  305. this.changeData({...config, customize: {...config.customize, scope: params.name}})
  306. this.option.geo.map = params.name
  307. echarts.registerMap(params.name, JSON.parse(map.geoJson));
  308. this.charts.setOption(this.option, true);
  309. });
  310. })
  311. }
  312. }
  313. }
  314. </script>
  315. <style lang="scss" scoped>
  316. @import '../../assets/style/echartStyle';
  317. .light-theme {
  318. background-color: #ffffff;
  319. color: #000000;
  320. }
  321. .auto-theme {
  322. background-color: rgba(0, 0, 0, 0);
  323. }
  324. .bs-design-wrap {
  325. padding: 0 16px;
  326. position: relative;
  327. .button {
  328. position: absolute;
  329. z-index: 999;
  330. }
  331. }
  332. </style>