MapView.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. <template>
  2. <div class='map-view'>
  3. <van-nav-bar :title="`${floorName}平面图`" @click-left='backPage'>
  4. <template #left>
  5. <van-icon name="arrow-left" size="18" color="#333333" />
  6. </template>
  7. </van-nav-bar>
  8. <div id="bind-map-content">
  9. <canvas id="bind-canvas" ref="bind-canvas" tabindex="0"></canvas>
  10. <!-- 地图底部操作按钮 -->
  11. <div class='strip-bottom'>
  12. <canvasFun @fit='fit' @showText='showText' ref='canvasFun'></canvasFun>
  13. </div>
  14. <floor-list ref="fList" class="bind-floor-list" v-if='floorsArr.length>0' :floorsArr='floorsArr'
  15. @emitFloor='emitFloor'></floor-list>
  16. <div class="change-direction" @click='changeOri'>
  17. <i class="iconfont wanda-hengshuping"></i>
  18. </div>
  19. </div>
  20. </div>
  21. </template>
  22. <script>
  23. /**
  24. * 平面图展示
  25. */
  26. import Vue from 'vue'
  27. import { mapGetters } from 'vuex'
  28. import { NavBar, Toast } from 'vant'
  29. import floorList from "@/components/floorMap/floorList.vue"
  30. import canvasFun from '@/components/floorMap/canvasFun'
  31. import { readGroup, queryStatis, graphQuery } from '@/api/public'
  32. import { queryShops } from '@/api/equipmentList.js'
  33. import { FloorView } from '@/lib/FloorView'
  34. import { FloorScene } from '@/lib/FloorScene'
  35. import { STopologyParser } from '@/lib/parsers/STopologyParser'
  36. import { TipelineItem } from '@/lib/items/TipelineItem'
  37. import { SImageLegendItem } from '@/lib/items/SImageLegendItem'
  38. import { SImageItem, SImageShowType, SGraphItem } from '@saga-web/graph/lib'
  39. import { ProjectRf } from '@saga-web/feng-map'
  40. import { SFloorParser, ItemOrder, ItemColor, SPolygonItem, SBoardItem } from '@saga-web/big'
  41. import { SColor } from '@saga-web/draw/lib'
  42. Vue.use(NavBar).use(Toast)
  43. export default {
  44. name: 'MapView',
  45. props: {},
  46. components: { floorList, canvasFun },
  47. computed: {
  48. ...mapGetters(['plazaId', 'fmapID', 'haveFengMap', 'bunkObj', 'floorsArr', 'categoryId']),
  49. },
  50. data() {
  51. return {
  52. view: '',
  53. scene: '',
  54. mapServerURL: "http://map.wanda.cn/editor",
  55. canvasLoading: false,
  56. floorid: '', //楼层id
  57. floorName: '', //楼层名
  58. count: 0, // 顶楼为多张图时计数器
  59. topologyParser: null, // 解析器数据
  60. fParser: null, // 底图解析器
  61. direction: '竖屏',
  62. }
  63. },
  64. props: {},
  65. beforeMount() { },
  66. mounted() {
  67. window.addEventListener("onorientationchange" in window ? "orientationchange" : "resize", () => {
  68. this.clearGraphy();
  69. setTimeout(() => {
  70. if (window.orientation === 0 || window.orientation === 180) {
  71. console.log("竖屏");
  72. }
  73. if (window.orientation === 90 || window.orientation === -90) {
  74. console.log("横屏");
  75. }
  76. document.getElementById("bind-canvas").width = document.getElementById("bind-map-content").offsetWidth;
  77. document.getElementById("bind-canvas").height = document.getElementById("bind-map-content").offsetHeight;
  78. this.init(this.floorid)
  79. }, 500)
  80. }, false);
  81. this.$nextTick(() => {
  82. document.getElementById("bind-canvas").width = document.getElementById("bind-map-content").offsetWidth;
  83. document.getElementById("bind-canvas").height = document.getElementById("bind-map-content").offsetHeight;
  84. })
  85. },
  86. methods: {
  87. backPage() {
  88. if (this.direction === '横屏') {
  89. this.roateY()
  90. this.direction = '竖屏'
  91. }
  92. this.$router.go(-1);
  93. },
  94. // 切换楼层
  95. emitFloor(floorObj) {
  96. if (floorObj) {
  97. this.$nextTick(() => {
  98. this.floorid = floorObj.gcname;
  99. this.floorName = floorObj.code;
  100. this.init(floorObj.gcname);
  101. })
  102. }
  103. },
  104. init(floorid) {
  105. // this.canvasLoading = true
  106. Toast.loading({
  107. duration: 0, // 持续展示 toast
  108. message: '加载中...',
  109. forbidClick: true,
  110. });
  111. // this.floorid = floorid
  112. // this.$refs.canvasFun.isShow = false
  113. setTimeout(() => {
  114. this.clearGraphy()
  115. this.scene = new FloorScene()
  116. if (this.haveFengMap == 1) {
  117. this.scene.selectContainer.connect('listChange', this, this.listChange)
  118. this.getGraphDetail().then((res) => {
  119. if (res.Content.length == 1) {
  120. const data = res.Content[0]
  121. if (data.MaxY && data.MinX) {
  122. window.fengmapData.maxY = data.MaxY
  123. window.fengmapData.minX = data.MinX
  124. }
  125. }
  126. this.parserData(floorid)
  127. })
  128. // this.parserData(floorid);
  129. } else if (this.haveFengMap == 0) {
  130. this.view.scene = this.scene
  131. this.readGraph()
  132. } else {
  133. this.canvasLoading = false
  134. Toast.clear();
  135. }
  136. }, 100)
  137. },
  138. // 解析底图
  139. parserData(floor) {
  140. if (floor == 'g80') {
  141. // 屋顶
  142. if (window.fengmapData.frImg) {
  143. const pj = this.fmapID.split('_')[0]
  144. // 单张图片
  145. if (!ProjectRf[pj]) {
  146. let imgItem = new SImageItem(null, `${this.mapServerURL}/webtheme/${this.fmapID}/${window.fengmapData.frImg}`)
  147. imgItem.showType = SImageShowType.AutoFit
  148. imgItem.connect('imgLoadOver', this, () => {
  149. this.readGraph()
  150. })
  151. this.scene.addItem(imgItem)
  152. this.view.scene = this.scene
  153. // this.view.fitSceneToView()
  154. } else {
  155. // 多张图
  156. try {
  157. // 初始化0
  158. this.count = 0
  159. ProjectRf[pj].forEach((t) => {
  160. const item = new SImageItem(null, `${this.mapServerURL}/webtheme/${this.fmapID}/${t.name}`)
  161. item.width = t.width
  162. item.height = t.height
  163. item.moveTo(t.x, t.y)
  164. item.connect('imgLoadOver', this, () => {
  165. this.countRf(ProjectRf[pj].length)
  166. })
  167. this.scene.addItem(item)
  168. })
  169. this.view.scene = this.scene
  170. } catch (e) {
  171. console.log(e)
  172. }
  173. }
  174. } else {
  175. // 屋顶图不为图片
  176. this.readBaseMap(floor)
  177. }
  178. } else {
  179. if (window.fengmapData.gnameToGid[floor]) {
  180. this.readBaseMap(floor)
  181. } else {
  182. console.log('楼层不正确')
  183. }
  184. }
  185. },
  186. // 解析楼地板
  187. loadBoard(floor) {
  188. window.fengmapData.loadFloor(floor, (res) => {
  189. const zone = new SBoardItem(null, res)
  190. this.scene.addItem(zone)
  191. })
  192. },
  193. readBaseMap(floor) {
  194. this.loadBoard(window.fengmapData.gnameToGid[floor])
  195. window.fengmapData.parseData(window.fengmapData.gnameToGid[floor], (res) => {
  196. if (res.err) {
  197. console.log('errr', res.err)
  198. return
  199. }
  200. this.fParser = new SFloorParser(null)
  201. this.fParser.parseData(res)
  202. this.fParser.spaceList.forEach((t) => {
  203. this.scene.addItem(t)
  204. t.nameSize = 12
  205. t.nameColor = '#2a2a2a'
  206. if (t.data.Name && this.bunkObj[t.data.Name]) {
  207. t.name = this.bunkObj[t.data.Name].brandname
  208. } else {
  209. // t.name = t.data.Name
  210. t.name = ''
  211. }
  212. })
  213. this.fParser.wallList.forEach((t) => this.scene.addItem(t))
  214. this.fParser.virtualWallList.forEach((t) => this.scene.addItem(t))
  215. this.fParser.doorList.forEach((t) => this.scene.addItem(t))
  216. this.fParser.columnList.forEach((t) => this.scene.addItem(t))
  217. this.fParser.casementList.forEach((t) => this.scene.addItem(t))
  218. this.view.scene = this.scene
  219. // this.view.fitSceneToView()
  220. this.readGraph()
  221. })
  222. },
  223. readGraph() {
  224. this.readGroup()
  225. .then((data) => {
  226. if (data.Result == 'failure') {
  227. this.$store.commit('SETISMESSAGE', false)
  228. this.view.fitSceneToView()
  229. this.view.minScale = this.view.scale
  230. if (this.$refs.canvasFun) {
  231. this.$refs.canvasFun.everyScale = this.view.scale
  232. }
  233. Toast.clear();
  234. return
  235. } else {
  236. if (
  237. data.Data[0].Elements.Nodes.length === 0 &&
  238. data.Data[0].Elements.Markers.length === 0 &&
  239. data.Data[0].Elements.Relations.length === 0
  240. ) {
  241. this.$store.commit('SETISMESSAGE', false)
  242. } else {
  243. this.$store.commit('SETISMESSAGE', true)
  244. }
  245. }
  246. // 无返回Data处理
  247. if (!(data.Data && data.Data.length)) {
  248. this.view.fitSceneToView()
  249. this.view.minScale = this.view.scale
  250. if (this.$refs.canvasFun) {
  251. this.$refs.canvasFun.everyScale = this.view.scale
  252. }
  253. return false
  254. }
  255. // // 请求回来的备注
  256. // if (data.Data && data.Data[0].Note) {
  257. // let note = data.Data[0].Note
  258. // bus.$emit('queryRemarksMethods', note)
  259. // } else {
  260. // bus.$emit('queryRemarksMethods', '')
  261. // }
  262. // //土建装饰的图例展示
  263. // if (this.$cookie.get('categoryId') == 'SCPZ') {
  264. // let scpzTable = [],
  265. // arr = []
  266. // scpzTable = data.Data[0].Elements.Nodes || []
  267. // console.log(scpzTable)
  268. // if (scpzTable.length > 0) {
  269. // scpzTable.forEach((e) => {
  270. // if (e.Properties.ItemExplain) {
  271. // let obj = e
  272. // arr.push(obj)
  273. // }
  274. // })
  275. // }
  276. // console.log(arr)
  277. // this.$store.commit('SETSCPZTABLE', arr)
  278. // }
  279. // if (data.Data[0].Elements.Nodes.length > 0) {
  280. // this.$store.commit('SETTYPENUM', '')
  281. // let Lengd = data.Data[0].Elements.Nodes
  282. // Lengd.forEach((el) => {
  283. // if (el.Type == 'Image' && el.Num > 1) {
  284. // console.log(el.Num)
  285. // this.$store.commit('SETTYPENUM', el.Num)
  286. // }
  287. // })
  288. // }
  289. // 放到后边 $cookie graphId
  290. // this.$cookie.set('graphId', data.Data[0].ID, 3)
  291. // if (this.$cookie.get('graphId')) {
  292. // // 得到graphId 就请求图例
  293. // // 除土建装饰之外的图例展示 包括楼层功能
  294. // bus.$emit('queryViewMethods')
  295. // }
  296. this.topologyParser = new STopologyParser(null)
  297. this.topologyParser.parseData(data.Data[0].Elements)
  298. // 多边形
  299. this.topologyParser.zoneLegendList.forEach((t) => {
  300. this.scene.addItem(t)
  301. // t.connect('legendItemClick', t, this.handleClickLegendItem)
  302. })
  303. // 增加文字
  304. this.topologyParser.textMarkerList.forEach((t) => {
  305. this.scene.addItem(t)
  306. })
  307. // 增加图片
  308. this.topologyParser.imageMarkerList.forEach((t) => {
  309. this.scene.addItem(t)
  310. })
  311. // 增加直线
  312. this.topologyParser.lineMarkerList.forEach((t) => {
  313. this.scene.addItem(t)
  314. })
  315. // 增加图标类图例
  316. this.topologyParser.imageLegendList.forEach((t) => {
  317. this.scene.addItem(t)
  318. // t.connect('legendItemClick', t, this.handleClickLegendItem)
  319. })
  320. // 增加管线类
  321. // 增加图标类图例
  322. this.topologyParser.relationList.forEach((t) => {
  323. t.selectable = true
  324. this.scene.addItem(t)
  325. // t.connect('legendItemClick', t, this.handleClickLegendItem)
  326. })
  327. // this.view.fitSceneToView()
  328. // this.view.minScale = this.view.scale
  329. if (this.$refs.canvasFun) {
  330. this.$refs.canvasFun.everyScale = this.view.scale
  331. }
  332. this.view.fitSceneToView()
  333. this.view.minScale = this.view.scale
  334. this.canvasLoading = false
  335. Toast.clear();
  336. })
  337. .catch(() => {
  338. this.canvasLoading = false
  339. Toast.clear();
  340. })
  341. },
  342. // 顶楼为多张图时计数器
  343. countRf(len) {
  344. this.count++
  345. if (len == this.count) {
  346. this.readGraph()
  347. } else {
  348. console.log('所有图片未加载完成')
  349. }
  350. },
  351. clearGraphy() {
  352. if (this.view) {
  353. this.view.scene = null
  354. return
  355. }
  356. this.view = new FloorView("bind-canvas");
  357. },
  358. listChange(item, ev) {
  359. if (ev[0].length) {
  360. // 选中电井设置电井关联的商铺高亮
  361. this.setHightLight(ev[0])
  362. } else {
  363. this.clearHightLight()
  364. }
  365. },
  366. // 选中电井关联的商铺高亮
  367. setHightLight(arr) {
  368. this.clearHightLight()
  369. arr.forEach((item) => {
  370. let location = item.data.AttachObjectIds[0] ? item.data.AttachObjectIds[0].id : ''
  371. // 添加了位置类型并且选中的类型为电井类型
  372. if (
  373. (item.data.GraphElementId == '100050' ||
  374. item.data.GraphElementId == '100055' ||
  375. item.data.GraphElementId == '100056' ||
  376. item.data.GraphElementId == '100057') &&
  377. location
  378. ) {
  379. let getParams = {
  380. plazaId: this.plazaId,
  381. floor: this.floorid,
  382. keyword: `${location}:wellnum;`,
  383. }
  384. queryShops({ getParams }).then((res) => {
  385. let shopsnumList = []
  386. if (res.data && res.data.length) {
  387. for (let floor in res.data[0]) {
  388. if (res.data[0][floor].length) {
  389. res.data[0][floor].forEach((v) => {
  390. shopsnumList = shopsnumList.concat(v.shopsnumList.split(','))
  391. })
  392. }
  393. }
  394. }
  395. if (shopsnumList.length) {
  396. this.fParser.spaceList.forEach((item) => {
  397. if (shopsnumList.findIndex((name) => name == item.data.Name) != -1) {
  398. item.highLightFlag = true
  399. item.zOrder = 30
  400. }
  401. })
  402. }
  403. })
  404. }
  405. })
  406. },
  407. // 清除电井关联商铺的高亮状态
  408. clearHightLight() {
  409. ItemColor.spaceHighColor = new SColor('#FBF2CC')
  410. this.fParser.spaceList.forEach((item) => {
  411. item.highLightFlag = false
  412. item.zOrder = ItemOrder.spaceOrder
  413. })
  414. },
  415. // 适配底图到窗口
  416. fit() {
  417. this.view.fitSceneToView()
  418. },
  419. // 小眼睛控制显示铺位名称
  420. showText(val) {
  421. this.fParser.spaceList.forEach((t) => {
  422. t.showBaseName = val
  423. })
  424. },
  425. // 读取数据
  426. readGroup() {
  427. const data = {
  428. BuildingID: '1',
  429. FloorID: this.floorid,
  430. categoryId: this.categoryId,
  431. projectId: this.plazaId,
  432. Pub: true,
  433. }
  434. return readGroup(data)
  435. },
  436. // 获取图最大最小值
  437. getGraphDetail() {
  438. const categoryId = this.categoryId
  439. const data = {
  440. Filters: `categoryId='${categoryId}';projectId='${this.plazaId}';BuildingID='1';FloorID='${this.floorid}';isPub=true`,
  441. }
  442. return graphQuery(data)
  443. },
  444. changeOri() {
  445. if (this.direction === '竖屏') {
  446. this.roateX()
  447. this.direction = '横屏'
  448. } else if (this.direction === '横屏') {
  449. this.roateY()
  450. this.direction = '竖屏'
  451. }
  452. },
  453. roateX() {
  454. console.log('横屏')
  455. window.webkit &&
  456. webkit.messageHandlers.cordova_iab.postMessage(
  457. JSON.stringify({
  458. method: 'roateX',
  459. })
  460. )
  461. },
  462. // 竖屏
  463. roateY() {
  464. console.log('竖屏')
  465. window.webkit &&
  466. webkit.messageHandlers.cordova_iab.postMessage(
  467. JSON.stringify({
  468. method: 'roateY',
  469. })
  470. )
  471. },
  472. },
  473. watch: {
  474. '$route.params.floor': {
  475. handler(floor) {
  476. this.$nextTick(() => {
  477. this.floorid = floor.FloorId;
  478. this.floorName = floor.FloorName;
  479. let index = this.floorsArr.findIndex(item => {
  480. return item.gcname === floor.FloorId
  481. })
  482. let item = {
  483. gcname: floor.FloorId,
  484. code: floor.FloorName
  485. }
  486. this.$refs.fList.tabFloor(item ,index);
  487. // this.$refs.fList.currentFloorId = floor.FloorId;
  488. // this.init(floor.FloorId);
  489. })
  490. },
  491. immediate: true,
  492. deep: true
  493. }
  494. },
  495. }
  496. </script>
  497. <style lang='less' scoped>
  498. .map-view {
  499. width: 100%;
  500. height: 100%;
  501. overflow: hidden;
  502. display: flex;
  503. flex-direction: column;
  504. #bind-map-content {
  505. width: 100%;
  506. height: calc(100% - 50px);
  507. position: relative;
  508. overflow: hidden;
  509. .bind-floor-list {
  510. position: fixed;
  511. top: 65px;
  512. right: 16px;
  513. }
  514. .strip-bottom {
  515. position: fixed;
  516. bottom: 60px;
  517. right: 16px;
  518. }
  519. .change-direction {
  520. position: fixed;
  521. bottom: 60px;
  522. left: 16px;
  523. .wanda-hengshuping {
  524. font-size: 26px;
  525. }
  526. }
  527. }
  528. }
  529. // 横屏
  530. @media screen and (orientation: landscape) {
  531. .map-view {
  532. /deep/ .van-nav-bar {
  533. height: 40px;
  534. }
  535. #bind-map-content {
  536. .bind-floor-list {
  537. position: fixed;
  538. top: 47px;
  539. right: 16px;
  540. }
  541. .strip-bottom {
  542. position: fixed;
  543. bottom: 15px;
  544. right: 60px;
  545. }
  546. .change-direction {
  547. position: fixed;
  548. bottom: 15px;
  549. left: 15px;
  550. .wanda-hengshuping {
  551. font-size: 26px;
  552. }
  553. }
  554. }
  555. }
  556. }
  557. </style>