cenoteGraphy.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <template>
  2. <div id="cenoteGraphy" style="height:100%;width:100%;" ref="graphy">
  3. <div v-show="!floorMap">
  4. <div class="center" style="height: 400px;padding-top:182px;box-sizing:border-box;">
  5. <i class="icon-wushuju iconfont"></i>
  6. 暂无数据
  7. </div>
  8. </div>
  9. <div class="canvas-box" v-show="floorMap" v-loading="canvasLoading">
  10. <canvas id="floorCanvas" :width="canvasWidth" :height="canvasHeight" ref="canvas" tabindex="0"></canvas>
  11. <el-row class="canvas-actions-box">
  12. <canvasFun @scale="scale" @groupSelect="groupSelect" @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @saveJson="saveJson" :config="config"
  13. ref="canvasFun"></canvasFun>
  14. </el-row>
  15. </div>
  16. </div>
  17. </template>
  18. <script>
  19. import canvasFun from "@/components/business_space/newGraphy/canvasFun";
  20. import { SColor, SPoint } from "@saga-web/draw/lib";
  21. import { DivideFloorScene, SpaceItem, ZoneItem, Opt } from "@saga-web/cad-engine/lib";
  22. import { FloorView } from "@saga-web/cad-engine/lib/FloorView";
  23. import { colorArr } from '@/utils/spaceColor';
  24. import { getFloorMsgByFloorID, shaftSpaceQuery, shaftZoneLinkReplace, zoneQuery } from '@/api/scan/request';
  25. import { resolve, reject } from 'q';
  26. export default {
  27. data() {
  28. return {
  29. canvasLoading: false,//加载canvas
  30. floorMap: '',//地图
  31. canvasWidth: 800,
  32. canvasHeight: 600,
  33. view: null,
  34. scene: null,
  35. buildingData: [],//建筑,楼层
  36. space: '',//当前空间类型
  37. businessSpaceList: [],//所有业务空间
  38. BSPRelaISPList: [],//已关联元空间的业务空间
  39. zoneList: [], // 业务空间-canvas图中
  40. selectAble: false,
  41. relatedSpaceIdList: [],//已关联的业务空间id
  42. config: {
  43. isEdit: false,
  44. groupSelect: true
  45. },
  46. sceneMarkList: []
  47. }
  48. },
  49. mounted() {
  50. this.canvasWidth = this.$refs.graphy.offsetWidth;
  51. this.canvasHeight = this.$refs.graphy.offsetHeight;
  52. },
  53. components: {
  54. canvasFun
  55. },
  56. created() {
  57. Opt.sceneMarkColor = new SColor('#ffffff');
  58. },
  59. methods: {
  60. //获取楼层map
  61. getFloorMap(buildfloor, space) {
  62. if (buildfloor.length == 2 && space && buildfloor[1] && buildfloor[0]) {
  63. this.buildingData = buildfloor
  64. let pa = {
  65. Filters: `FloorID='${this.buildingData[1]}'`
  66. }
  67. getFloorMsgByFloorID(pa, res => {
  68. this.floorMap = res.Content[0].StructureInfo ? res.Content[0].StructureInfo.FloorMap : '';
  69. this.space = space;
  70. // 蒙版
  71. if (res.Content[0].Outline) {
  72. this.sceneMarkList = res.Content[0].Outline.map(t => {
  73. return new SPoint(t.X, t.Y);
  74. })
  75. }
  76. this.getGraphy();
  77. })
  78. }
  79. else {
  80. this.floorMap = '';
  81. }
  82. },
  83. //加载
  84. load() {
  85. if (this.scene) {
  86. this.scene.clearSpaceSelection();
  87. this.scene.clearZoneSelection();
  88. }
  89. //加载底板
  90. this.getGraphy()
  91. },
  92. //获取底图
  93. getGraphy() {
  94. let that = this;
  95. that.clearGraphy()
  96. if (!this.floorMap) return
  97. that.scene = new DivideFloorScene();
  98. that.canvasLoading = true;
  99. that.scene.loadUrl(`/image-service/common/file_get?systemId=revit&key=${this.floorMap}`).then(res => {
  100. that.canvasLoading = false;
  101. if (res == 'error') {
  102. this.floorMap = '';
  103. this.$message.warning('数据解析异常');
  104. return;
  105. }
  106. that.view.scene = that.scene;
  107. if (that.sceneMarkList.length) {
  108. that.scene.addSceneMark(that.sceneMarkList)
  109. }
  110. that.scene.isSpaceSelectable = false;
  111. // 绘制业务空间
  112. that.getBusinessSpace();
  113. that.fit();
  114. that.view.minScale = that.view.scale;
  115. if (that.$refs.canvasFun) {
  116. that.$refs.canvasFun.everyScale = that.view.scale;
  117. }
  118. })
  119. },
  120. // 获取当前分区下的业务空间
  121. getBusinessSpace() {
  122. this.canvasLoading = true
  123. let promise1 = new Promise((resolve, reject) => {
  124. let params = {
  125. data: {
  126. Filters: `not RoomID isNull;ObjectType = '${this.space}';buildingId = '${this.buildingData[0]}';floorId = '${this.buildingData[1]}'`,
  127. Orders: "RoomLocalName desc"
  128. },
  129. ShaftId: this.$route.query.ShaftId
  130. };
  131. shaftSpaceQuery(params, res => {
  132. resolve(res)
  133. })
  134. });
  135. let promise2 = new Promise((resolve, reject) => {
  136. let pa = {
  137. Filters: `not RoomID isNull`,
  138. Orders: "createTime desc, RoomID asc",
  139. PageSize: 1000,
  140. ZoneType: this.space
  141. }
  142. if (this.buildingData.length && this.buildingData.length > 1) {
  143. pa.BuildingId = this.buildingData[0];
  144. pa.FloorId = this.buildingData[1];
  145. }
  146. zoneQuery(pa, res => {
  147. resolve(res);
  148. })
  149. })
  150. Promise.all([promise1, promise2]).then(values => {
  151. let relatedZone = values[0].Content;
  152. let zoneData = values[1].Content;
  153. this.relatedSpaceIdList = [];
  154. relatedZone.map(item => {
  155. this.relatedSpaceIdList.push(item.RoomID);
  156. })
  157. // 所有业务空间
  158. this.businessSpaceList = zoneData;
  159. // 已关联元空间的业务空间
  160. this.BSPRelaISPList = [];
  161. zoneData.map(t => {
  162. if (t.Outline && t.Outline.length) {
  163. this.BSPRelaISPList.push(t)
  164. }
  165. })
  166. // 绘制业务空间
  167. let tempArr = this.BSPRelaISPList.map((t, i) => {
  168. if (t.FloorId == this.buildingData[1] && t.ObjectType == this.space) {
  169. return {
  170. RoomLocalName: t.RoomLocalName,
  171. OutLine: t.Outline,
  172. RoomID: t.RoomID,
  173. Color: colorArr[i % colorArr.length],
  174. HighLightFlag: relatedZone.findIndex((item) => (item.RoomID == t.RoomID)) > -1,
  175. Transparency: relatedZone.findIndex((item) => (item.RoomID == t.RoomID)) > -1 ? 20 : 1
  176. }
  177. } else {
  178. return undefined
  179. }
  180. }).filter(item => item)
  181. this.scene.removeAllZone();
  182. this.scene.addZoneList(tempArr);
  183. this.scene.click(this, this.canvasClick);
  184. this.canvasLoading = false;
  185. })
  186. },
  187. // canvas点击事件
  188. canvasClick(item, event) {
  189. if (!this.config.isEdit) {
  190. item.selected = false;
  191. }
  192. },
  193. // 立面图选中空间对应平面图选中
  194. canvasChecked(RoomID) {
  195. this.scene.zoneList.map(zoneItem => {
  196. if (zoneItem.data.RoomID == RoomID) {
  197. zoneItem.selected = true;
  198. }
  199. })
  200. },
  201. // 立面图取消选中对应平面图取消选中
  202. canvasUncheck(RoomID) {
  203. this.scene.zoneList.map(zoneItem => {
  204. if (zoneItem.data.RoomID == RoomID) {
  205. zoneItem.selected = false;
  206. }
  207. })
  208. },
  209. //取消编辑
  210. cancelEdit() {
  211. this.config.isEdit = false;
  212. this.scene.clearZoneSelection();
  213. this.getBusinessSpace();
  214. },
  215. //编辑
  216. edit() {
  217. this.config.isEdit = true;
  218. this.scene.zoneList.map(t => {
  219. t.selected = t.highLightFlag;
  220. t.transparency = 20;
  221. t.highLightFlag = false;
  222. })
  223. },
  224. //保存编辑
  225. saveEdit() {
  226. let arr = this.scene.getSelectedZone();
  227. let param = {
  228. BuildingId: this.buildingData[0],
  229. FloorId: this.buildingData[1],
  230. Type: this.space,
  231. data: {
  232. ShaftId: this.$route.query.ShaftId,
  233. SpaceIdList: []
  234. }
  235. }
  236. param.data.SpaceIdList = arr.map(t => {
  237. return t.data.RoomID;
  238. })
  239. shaftZoneLinkReplace(param, res => {
  240. this.config.isEdit = false;
  241. this.$message.success("保存成功");
  242. this.getBusinessSpace();
  243. })
  244. },
  245. // 清除canvas
  246. clearGraphy() {
  247. // debugger
  248. this.scene = null;
  249. if (this.view) {
  250. this.view.scene = null;
  251. return
  252. }
  253. this.view = new FloorView('floorCanvas')
  254. },
  255. // 适配底图到窗口
  256. fit() {
  257. if (this.scene.sceneMark) {
  258. this.view.fitItemToView([this.scene.sceneMark])
  259. return
  260. }
  261. this.view.fitSceneToView()
  262. },
  263. // 缩放
  264. scale(val) {
  265. if (!this.view) {
  266. return;
  267. }
  268. let scale = this.view.scale;
  269. this.view.scaleByPoint(val / scale, this.canvasWidth / 2, this.canvasHeight / 2);
  270. },
  271. // 保存为png
  272. savePng() {
  273. this.view.saveImage(`${this.buildingData[1]}.png`, 'png');
  274. },
  275. // 保存为svg
  276. saveSvg() {
  277. this.view.saveSceneSvg(`${this.buildingData[1]}.svg`, 6400, 4800);
  278. },
  279. // 框选
  280. groupSelect() {
  281. this.scene.isRectSelection = 2;
  282. },
  283. // 保存json
  284. saveJson() {
  285. this.view.saveFloorJson(`${this.buildingData[1]}.json`)
  286. },
  287. },
  288. watch: {
  289. "view.scale": {
  290. handler(n) {
  291. if (this.$refs.canvasFun) {
  292. let s = n * 10 / this.view.minScale
  293. this.$refs.canvasFun.sliderVal = s > 1000 ? 1000 : s;
  294. }
  295. }
  296. },
  297. "scene.isRectSelection": {
  298. handler(n) {
  299. if (!n) {
  300. this.$refs.canvasFun.active = '';
  301. }
  302. }
  303. },
  304. }
  305. }
  306. </script>
  307. <style lang="less" scoped>
  308. .canvas-actions-box {
  309. position: absolute;
  310. bottom: 20px;
  311. left: 50%;
  312. width: 352px;
  313. transform: translateX(-50%);
  314. z-index: 999;
  315. }
  316. .canvas-box {
  317. width: 100%;
  318. height: 100%;
  319. }
  320. </style>