spaceGraph.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <template>
  2. <div id="graphContainer" ref="graphContainer">
  3. <el-row class="buttons-box">
  4. <div>
  5. <el-autocomplete popper-class="my-autocomplete" v-model="search" :fetch-suggestions="querySearch" placeholder="输入平面图中已有的业务空间名称进行查找"
  6. width="180px" @select="handleSelect">
  7. <i class="el-icon-search el-input__icon" slot="suffix"></i>
  8. <template slot-scope="{ item }">
  9. <div class="name" style="position: relative;padding-right:40px;overflow: hidden;text-overflow:ellipsis;white-space: nowrap;"
  10. :title="item.data.RoomLocalName">
  11. {{ item.data.RoomLocalName }}
  12. <span class="addr" style="position: absolute;right:0;color:#409EFF;">定位</span>
  13. </div>
  14. </template>
  15. </el-autocomplete>
  16. </div>
  17. <div class="button-group">
  18. <!-- 默认操作模式 -->
  19. <div v-show="type==1">
  20. <el-dropdown split-button type="primary" @click="editGraphy" @command="handleCommand">
  21. 创建业务空间
  22. <el-dropdown-menu slot="dropdown">
  23. <el-dropdown-item command="groupCreateBSpace">批量创建业务空间</el-dropdown-item>
  24. </el-dropdown-menu>
  25. </el-dropdown>
  26. <!-- 点击已经关联的业务空间 -->
  27. <el-button plain @click="refactorBSP" :disabled="zoneDisable" style="margin-left:10px;">重新划分业务空间</el-button>
  28. <el-button plain :disabled="zoneDisable" style="margin-left:10px;">维护空间信息</el-button>
  29. <el-button plain @click="cancelGraphy" v-show="!zoneDisable">取 消</el-button>
  30. </div>
  31. <!-- 点击未关联的业务空间 -->
  32. <div v-show="type==3">
  33. <el-button plain @click="createNewZone">创建单个全新的业务空间</el-button>
  34. <el-button plain @click="cancelGraphy">取 消</el-button>
  35. </div>
  36. <!-- 重新划分业务空间 -->
  37. <div v-show="type==4">
  38. <el-button plain @click="cancelGraphy">取 消</el-button>
  39. <el-button type="primary" @click="saveRefactorBSP">保存</el-button>
  40. </div>
  41. <!-- 批量创建所选业务空间 -->
  42. <div v-show="type==5">
  43. <el-button type="primary" @click="groupCreateZone">批量创建所选业务空间</el-button>
  44. <el-button plain @click="cancelGraphy">取 消</el-button>
  45. </div>
  46. </div>
  47. </el-row>
  48. <canvas id="spaceCanvas" :width="canvasWidth" :height="canvasHeight" tabindex="0"></canvas>
  49. <el-row class="canvas-actions-box">
  50. <canvas-fun :config="config" @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @divide="divide" @clearDivide="clearDivide" ref="canvasFun"
  51. @saveJson="saveJson" @changeAbsorb="changeAbsorb" @scale="scale" @groupSelect="groupSelect" />
  52. </el-row>
  53. </div>
  54. </template>
  55. <script lang="ts">
  56. import { Vue, Component, Watch } from "vue-property-decorator";
  57. import { FloorView } from "@/utils/graph/FloorView";
  58. import { FloorScene } from "@/utils/graph/FloorScene";
  59. import canvasFun from "./canvasFun.vue";
  60. @Component({
  61. components: { canvasFun },
  62. })
  63. export default class spaceGraph extends Vue {
  64. canvasWidth = 800;
  65. canvasHeight = 800;
  66. view: FloorView | null = null;
  67. scene: FloorScene | null = null;
  68. floorMap =
  69. "/image-service/common/file_get?systemId=revit&key=base/76233a3214dd11eb94d469663ce1649a.jsonz";
  70. canvasLoading = false;
  71. type = 1;
  72. config = {
  73. isEdit: false,
  74. divide: true,
  75. groupSelect: false,
  76. };
  77. search = ""; //搜索
  78. zoneDisable = true;
  79. curZoneItem = {};
  80. zoneList = [];
  81. buildFloor: string[] = [];
  82. // 挂载
  83. mounted(): void {
  84. this.canvasWidth = this.$refs.graphContainer.offsetWidth;
  85. this.canvasHeight = this.$refs.graphContainer.offsetHeight;
  86. this.getGraph();
  87. }
  88. // 初始化
  89. init(initType: number): void {
  90. this.type = 1;
  91. if (this.scene) {
  92. // this.scene.clearSpaceSelection();
  93. // this.scene.clearZoneSelection();
  94. // this.scene.clearLikeSpaces();
  95. // this.zoneDisable = true;
  96. // this.scene.isZoneSelectable = true;
  97. // this.scene.isSpaceSelectable = false;
  98. }
  99. if (
  100. this.buildFloor.indexOf("all") > -1 ||
  101. this.buildFloor.indexOf("noKnow") > -1
  102. ) {
  103. return;
  104. }
  105. if (initType == 1) {
  106. // 底图
  107. // this.getGraphy();
  108. } else {
  109. // 业务空间
  110. // this.getBusinessSpace();
  111. }
  112. this.config = {
  113. isEdit: false,
  114. divide: true,
  115. groupSelect: true,
  116. };
  117. // 获取当前楼层的元空间
  118. // this.getFloorISpace();
  119. // 查询未关联业务空间的元空间
  120. // this.getISPSPUnrelaBSP();
  121. // 查询未关联平面图的业务空间
  122. // this.getBSPunrelaISP();
  123. }
  124. // 获取底图
  125. getGraph(): void {
  126. const scene = new FloorScene();
  127. this.canvasLoading = true;
  128. this.clearGraphy();
  129. this.scene = null;
  130. scene.loadUrl(this.floorMap).then((res) => {
  131. if (this.view) {
  132. this.view.scene = scene;
  133. }
  134. this.scene = scene;
  135. this.getGraphSuc(res);
  136. });
  137. }
  138. // 获取底图成功
  139. getGraphSuc(res: any): void {
  140. this.canvasLoading = false;
  141. if (res == "error") {
  142. this.floorMap = "";
  143. this.$message.warning("数据解析异常");
  144. return;
  145. }
  146. this.view?.fitSceneToView();
  147. this.view!.minScale = this.view!.scale;
  148. if (this.$refs.canvasFun) {
  149. // @ts-ignore
  150. this.$refs.canvasFun.everyScale = this.view.scale;
  151. }
  152. }
  153. // 清除canvas
  154. clearGraphy() {
  155. if (this.view) {
  156. this.view.scene = null;
  157. return;
  158. }
  159. this.view = new FloorView("spaceCanvas");
  160. }
  161. // 搜索
  162. querySearch(queryString: string, cb: Function) {
  163. let restaurants = this.zoneList;
  164. let results = queryString
  165. ? restaurants.filter(this.createFilter(queryString))
  166. : restaurants;
  167. // 调用 callback 返回建议列表的数据
  168. cb(results);
  169. }
  170. // 过滤器
  171. createFilter(queryString: any) {
  172. return (restaurant: any) => {
  173. return restaurant.data.RoomLocalName.indexOf(queryString) > -1;
  174. };
  175. }
  176. // 查询选中,定位
  177. handleSelect(zone) {
  178. // // 清空选中
  179. // this.scene.clearSpaceSelection();
  180. // this.scene.clearZoneSelection();
  181. // // 选中当前
  182. // zone.selected = true;
  183. // this.curZoneItem = zone;
  184. // this.zoneDisable = false;
  185. // this.view.fitSelectedToView();
  186. }
  187. // 点击创建业务空间
  188. editGraphy() {
  189. this.type = 3;
  190. this.config.isEdit = true;
  191. this.config.groupSelect = false;
  192. this.config.divide = true;
  193. this.scene!.isSpaceSelectable = true;
  194. this.scene!.isZoneSelectable = false;
  195. this.view?.update();
  196. }
  197. // 创建新的业务空间
  198. createNewZone() {
  199. // let arr = this.scene.getSelectedSpaces();
  200. // if (arr.length) {
  201. // let tempArr = [];
  202. // arr.map(t => {
  203. // tempArr.push(this.BIMIDToSIName[t.data.SourceId]);
  204. // })
  205. // this.$refs.createBSP.showDialog(tempArr.toString());
  206. // } else {
  207. // this.$message.warning('请至少选择一个空间');
  208. // }
  209. }
  210. handleCommand() {}
  211. refactorBSP() {}
  212. editeSpaceDetail() {}
  213. // 取消(所有取消公用)
  214. cancelGraphy() {
  215. this.init(2);
  216. }
  217. saveRefactorBSP() {}
  218. groupCreateZone() {}
  219. // 适配底图到窗口
  220. fit() {
  221. this.view?.fitSceneToView();
  222. }
  223. // 保存为png
  224. savePng() {
  225. this.view?.saveImage(`1.png`, "png");
  226. }
  227. // 保存为svg
  228. saveSvg() {
  229. this.view?.saveSceneSvg(`1.svg`, 6400, 4800);
  230. }
  231. // 保存json
  232. saveJson() {
  233. this.view?.saveFloorJson(`1.json`);
  234. }
  235. // 切割划分
  236. divide() {
  237. this.scene.isCutting = true;
  238. }
  239. // 清除切割划分
  240. clearDivide() {
  241. // @ts-ignore
  242. this.view!.scene.clearCut();
  243. }
  244. // 缩放
  245. scale(val: number) {
  246. if (!this.view) {
  247. return;
  248. }
  249. let scale = this.view.scale;
  250. this.view.scaleByPoint(
  251. val / scale,
  252. this.canvasWidth / 2,
  253. this.canvasHeight / 2
  254. );
  255. }
  256. groupSelect() {
  257. console.log("groupSelect");
  258. }
  259. changeAbsorb() {
  260. console.log("changeAbsorb");
  261. }
  262. @Watch("view.scale", { immediate: true, deep: true })
  263. onScaleChange(n: number) {
  264. if (this.$refs.canvasFun) {
  265. // @ts-ignore
  266. let s = (n * 10) / this.view.minScale;
  267. // @ts-ignore
  268. this.$refs.canvasFun.sliderVal = s > 1000 ? 1000 : s;
  269. }
  270. }
  271. }
  272. </script>
  273. <style lang="scss">
  274. #graphContainer {
  275. position: relative;
  276. width: 100%;
  277. height: 100%;
  278. .canvas-actions-box {
  279. position: absolute;
  280. bottom: 60px;
  281. left: 50%;
  282. transform: translateX(-50%);
  283. z-index: 99;
  284. }
  285. .buttons-box {
  286. position: absolute;
  287. top: 16px;
  288. left: 0;
  289. padding: 0 16px;
  290. width: 100%;
  291. z-index: 999;
  292. & > div {
  293. float: left;
  294. }
  295. .el-autocomplete {
  296. display: inline-block;
  297. width: 320px;
  298. margin-right: 10px;
  299. }
  300. .button-group button,
  301. .button-group .el-dropdown {
  302. display: block;
  303. float: left;
  304. }
  305. .my-autocomplete {
  306. li {
  307. line-height: normal;
  308. padding: 7px;
  309. .name {
  310. text-overflow: ellipsis;
  311. overflow: hidden;
  312. }
  313. .addr {
  314. font-size: 12px;
  315. color: #b4b4b4;
  316. }
  317. .highlighted .addr {
  318. color: #ddd;
  319. }
  320. }
  321. }
  322. }
  323. }
  324. </style>