123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759 |
- <template>
- <div id="graphContainer" ref="graphContainer">
- <div v-show="floorKey" v-loading="canvasLoading">
- <el-row class="buttons-box">
- <div class="button-group">
- <!-- 默认操作模式 -->
- <div v-if="type==1">
- <el-dropdown split-button type="primary" @click="editGraphy" @command="handleCommand">
- 创建空间
- <el-dropdown-menu slot="dropdown">
- <!-- <el-dropdown-item command="groupCreateBSpace">批量创建业务空间</el-dropdown-item> -->
- <el-dropdown-item command="createWall">创建墙体</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- <!-- 点击已经关联的业务空间 -->
- <!-- <el-button plain @click="refactorBSP" :disabled="zoneDisable" style="margin-left:10px;">编辑业务空间</el-button> -->
- <!-- <el-button plain :disabled="zoneDisable" style="margin-left:10px;">维护空间信息</el-button> -->
- <!-- <el-button plain @click="cancelGraphy" v-show="!zoneDisable">取 消</el-button> -->
- </div>
- <!-- 点击未关联的业务空间 -->
- <div v-if="type==3">
- <el-button plain @click="createNewZone">创 建</el-button>
- <el-button plain @click="cancelGraphy">取 消</el-button>
- </div>
- <!-- 重新划分业务空间 -->
- <div v-if="type==4">
- <el-button type="primary" @click="saveRefactorBSP">保 存</el-button>
- <el-button plain @click="cancelGraphy">取 消</el-button>
- </div>
- <!-- 批量创建所选业务空间 -->
- <div v-if="type==5">
- <el-button type="primary" @click="groupCreateZone">批量创建所选业务空间</el-button>
- <el-button plain @click="cancelGraphy">取 消</el-button>
- </div>
- <!-- 保存墙 -->
- <div v-if="type==6">
- <el-button type="primary" @click="saveMap">保 存</el-button>
- <el-button plain @click="cancelGraphy">取 消</el-button>
- </div>
- <!-- 删除业务空间 -->
- <div v-if="type==7">
- <el-button type="primary" @click="deleteRoom">删 除</el-button>
- <el-button plain @click="cancelGraphy">取 消</el-button>
- </div>
- </div>
- </el-row>
- <canvas id="spaceCanvas" :width="canvasWidth" :height="canvasHeight" tabindex="0"></canvas>
- <el-row class="canvas-actions-box">
- <canvas-fun :config="config" @fit="fit" @savePng="savePng" @saveSvg="saveSvg" @divide="divide" @clearDivide="clearDivide"
- ref="canvasFun" @saveJson="saveJson" @changeAbsorb="changeAbsorb" @scale="scale" @groupSelect="groupSelect" @drawWall="drawWall"
- @clearWall="clearWall" />
- </el-row>
- </div>
- <div v-show="!floorKey">
- <p style="text-align:center;margin-top:199px;">
- 暂无数据
- </p>
- </div>
- <!-- 创建新的业务空间 -->
- <createBSP ref="createBSP" @createRoom="createRoom"></createBSP>
- </div>
- </template>
- <script lang="ts">
- import { Vue, Component, Watch } from "vue-property-decorator";
- import { FloorView } from "@/utils/graph/FloorView";
- import { DivideFloorScene } from "@/utils/graph/DivideFloorScene";
- import canvasFun from "./canvasFun.vue";
- import {
- queryZone,
- queryIspace,
- createZone,
- updateZone,
- deleteZone,
- } from "@/api/datacenter";
- import createBSP from "./createBSP";
- import colorArr from "@/utils/graph/config/zoneColor";
- import { SObject } from "@persagy-web/base/lib";
- import { ItemColor } from "@persagy-web/big/lib";
- import { SSpaceItem } from "@persagy-web/big/lib/items/floor/SSpaceItem";
- import { SZoneItem } from "@persagy-web/big/lib/items/floor/ZoneItem";
- import { AppModule } from "@/store/modules/app";
- import { watch } from "fs";
- import { SWallItem } from "@persagy-web/big/lib/items/floor/SWallItem";
- import { CustomWall } from "@/utils/graph/CustomWall";
- @Component({
- components: { canvasFun, createBSP },
- })
- export default class spaceGraph extends Vue {
- canvasWidth = 800;
- canvasHeight = 800;
- view: FloorView | null = null;
- scene: DivideFloorScene | null = null;
- canvasLoading = false;
- type = -1;
- config = {
- isEdit: false,
- divide: true,
- groupSelect: false,
- drawWall: false,
- };
- // zoneDisable = true;
- curZoneItem = {};
- zoneList = [];
- buildFloor: string[] = [];
- floor = {}; // 当前楼层对象
- floorKey = ""; // 当前楼层底图请求完整url
- curZoneType = "";
- allzone = [];
- BSPRelaISPList = [];
- businessSpaceList = [];
- BIMIDToSID = {};
- BIMIDToSIName = {};
- sourceIdToISP = {};
- localFun = [];
- get mapBaseUrl() {
- return AppModule.mapBaseUrl;
- }
- // 挂载
- mounted(): void {
- this.canvasWidth = this.$refs.graphContainer.offsetWidth;
- this.canvasHeight = this.$refs.graphContainer.offsetHeight;
- // this.getGraph();
- }
- // 父组件调用查询楼层底图
- getData(floor: any, zoneType: any) {
- this.curZoneType = zoneType[zoneType.length - 1];
- this.canvasLoading = true;
- if (floor.infos && floor.infos.floorMap) {
- this.floor = floor;
- if (floor.infos.floorMap == this.floorKey) {
- this.init(2);
- } else {
- this.floorKey = floor.infos.floorMap;
- this.init(1);
- }
- } else {
- this.noMap();
- }
- }
- // 无底图时操作
- noMap() {
- this.floorKey = "";
- this.canvasLoading = false;
- this.$emit('initCreatBtn', true)
- }
- // 初始化
- init(initType: number): void {
- this.type = -1;
- if (this.scene) {
- this.scene.selectContainer.clear();
- this.scene.initSpaceColor();
- this.scene.initWallColor();
- this.scene.clearCut();
- this.scene.clearWalls();
- // this.zoneDisable = true;
- this.scene.isZoneSelectable = true;
- this.scene.isSpaceSelectable = false;
- this.scene.isWallSelectable = false
- }
- if (
- this.buildFloor.indexOf("all") > -1 ||
- this.buildFloor.indexOf("noKnow") > -1
- ) {
- return;
- }
- this.$emit('initCreatBtn', false)
- if (initType == 1) {
- // 底图
- this.getGraph();
- } else {
- // 业务空间
- this.getBussiness();
- }
- this.config = {
- isEdit: false,
- divide: true,
- groupSelect: true,
- drawWall: false,
- };
- if (this.$refs.canvasFun) {
- // @ts-ignore
- this.$refs.canvasFun.active = "";
- }
- // 获取当前楼层的元空间
- this.getFloorISpace();
- }
- // 获取底图
- getGraph(): void {
- const scene = new DivideFloorScene();
- this.canvasLoading = true;
- this.clearGraphy();
- this.scene = null;
- scene.loadUrl(this.mapBaseUrl + this.floorKey).then((res) => {
- if (this.view) {
- this.view.scene = scene;
- }
- this.scene = scene;
- this.getGraphSuc(res);
- });
- }
- // 获取底图成功
- getGraphSuc(res: any): void {
- this.canvasLoading = false;
- if (res == "error") {
- this.noMap();
- this.$message.warning("数据解析异常");
- return;
- }
- if (this.view) {
- this.view.fitSceneToView();
- this.view.minScale = this.view.scale;
- }
- if (this.$refs.canvasFun) {
- // @ts-ignore
- this.$refs.canvasFun.everyScale = this.view.scale;
- }
- if (this.scene) {
- this.scene.changeSelect = this.changeSelect;
- this.scene.isSpaceSelectable = false;
- }
- this.getBussiness();
- }
- // 清除canvas
- clearGraphy() {
- if (this.view) {
- this.view.scene = null;
- return;
- }
- this.view = new FloorView("spaceCanvas");
- }
- // 查询选中,定位
- handleSelect(zone: SZoneItem) {
- // 清空选中
- this.scene?.selectContainer.clear();
- this.curZoneItem = zone;
- this.scene?.selectContainer.setItem(zone);
- // this.zoneDisable = false;
- this.view?.fitSelectedToView();
- }
- // 点击创建业务空间
- editGraphy() {
- this.type = 3;
- this.config.isEdit = true;
- this.config.groupSelect = false;
- this.config.divide = true;
- this.config.drawWall = false;
- if (this.scene) {
- this.scene.isSpaceSelectable = true;
- this.scene.isZoneSelectable = false;
- this.scene.isWallSelectable = false
- this.scene.selectContainer.clear();
- }
- this.view?.update();
- }
- // 创建新的业务空间
- createNewZone() {
- if (this.scene) {
- let arr = this.scene.selectContainer.itemList;
- if (arr.length || this.scene.drawItem) {
- // 手绘的空间只有轮廓线可用
- let tempArr = [];
- this.localFun = [];
- arr.map((t) => {
- tempArr.push(this.BIMIDToSIName[t.data.SourceId]);
- if (
- this.sourceIdToISP[t.data.SourceId] &&
- this.sourceIdToISP[t.data.SourceId].infos
- ) {
- this.localFun.push(
- this.sourceIdToISP[t.data.SourceId].infos
- );
- }
- });
- this.$refs.createBSP.showDialog(tempArr.toString());
- } else {
- this.$message.warning("请至少选择一个空间");
- }
- }
- }
- // 下拉菜单
- handleCommand(command: string) {
- if (command == "createWall") {
- // 绘制墙
- this.config.isEdit = true;
- this.config.groupSelect = false;
- this.config.divide = false;
- this.config.drawWall = true;
- this.type = 6;
- if (this.scene) {
- this.scene.isSpaceSelectable = false;
- this.scene.isZoneSelectable = false;
- this.scene.isWallSelectable = true
- }
- }
- }
- // 编辑业务空间
- refactorBSP() {
- this.config.isEdit = true;
- this.config.groupSelect = false;
- this.config.divide = true;
- this.config.drawWall = false;
- if (this.scene) {
- this.scene.isZoneSelectable = false;
- this.scene.isSpaceSelectable = true;
- this.scene.isWallSelectable = false
- this.scene.selectContainer.clear();
- }
- this.type = 4;
- this.curZoneItem.visible = false;
- }
- editeSpaceDetail() {}
- // 获取元空间
- getFloorISpace() {
- const pa = {
- floorId: this.floor.id,
- buildingId: this.floor.buildingId,
- pageSize: 2000,
- };
- queryIspace(pa).then((res) => {
- if (res.message == this.floor.id) {
- this.BIMIDToSID = {};
- this.BIMIDToSIName = {};
- this.sourceIdToISP = {};
- res.content.map((t) => {
- let key = t.bimId.split(":")[1];
- this.BIMIDToSID[key] = t.id;
- this.BIMIDToSIName[key] = t.localName || t.name;
- this.sourceIdToISP[key] = t;
- });
- }
- });
- }
- // 获取业务空间
- getBussiness() {
- const pa = {
- filters: `classCode='${this.curZoneType}';floorId='${this.floor.id}';buildingId='${this.floor.buildingId}'`,
- pageSize: 2000,
- };
- this.canvasLoading = true;
- queryZone(pa).then((res) => {
- // if (res.FloorId == this.buildFloor[1] && res.ZoneType == tempType) {
- // 所有业务空间
- this.businessSpaceList = res.content;
- // 已关联元空间的业务空间
- this.BSPRelaISPList = [];
- res.content.map((t) => {
- if (t.outline && t.outline.length) {
- this.BSPRelaISPList.push(t);
- }
- });
- // 绘制业务空间
- let tempArr = this.BSPRelaISPList.map((t, i) => {
- return {
- RoomLocalName: t.localName || t.name,
- OutLine: t.outline,
- RoomID: t.id,
- Color: colorArr[i % colorArr.length],
- };
- }).filter((item) => item);
- this.scene?.removeAllZone();
- this.scene?.addZoneList(tempArr);
- this.$emit("getZoneSuc", this.scene?.zoneList);
- this.view?.update();
- this.canvasLoading = false;
- // }
- });
- }
- // 取消(所有取消公用)
- cancelGraphy() {
- this.init(2);
- }
- // 重新划分业务空间保存
- saveRefactorBSP() {
- let zoneObj = {
- id: this.curZoneItem.data.RoomID,
- classCode: this.curZoneType,
- outline: [],
- };
- // 没有业务空间,也没有绘制切割区域
- let arr = this.scene?.selectContainer.itemList;
- let temp = arr
- ?.map((t) => {
- return this.sourceIdToISP[t.data.SourceId]
- ? this.sourceIdToISP[t.data.SourceId].infos
- : undefined;
- })
- .filter((item) => item);
- if (temp?.length) {
- zoneObj.infos = temp[0];
- }
- if (this.scene) {
- zoneObj = this.setZoneOutline(zoneObj);
- this.handleUpdateZone(zoneObj);
- }
- }
- groupCreateZone() {}
- // 点击平面图事件
- changeSelect(selectContainer: SObject, data: any[]) {
- if (data.length) {
- console.log(data[0]);
- if (data[0].length) {
- if (data[0][0] instanceof SSpaceItem) {
- this.scene?.initSpaceColor();
- } else if (data[0][0] instanceof SZoneItem) {
- this.scene?.initZoneColor();
- // this.zoneDisable = false;
- this.type = 7;
- this.curZoneItem = data[0][0];
- }
- } else {
- this.scene?.initSpaceColor();
- if (this.type == 3) {
- console.log(3);
- } else if (this.type == 6) {
- console.log(6)
- } else {
- this.scene?.initZoneColor();
- this.type = -1;
- // this.zoneDisable = true;
- }
- }
- data[0].forEach((t) => {
- t.fillColor = ItemColor.selectColor;
- });
- } else {
- this.scene?.initSpaceColor();
- this.scene?.initZoneColor();
- this.type = -1;
- // this.zoneDisable = true;
- }
- }
- // 根据图创建新的业务空间-弹窗返回确认创建
- createRoom(val) {
- let zoneObj = {
- outline: [],
- localName: val,
- buildingId: this.floor.buildingId,
- floorId: this.floor.id,
- classCode: this.curZoneType,
- };
- if (this.localFun.length) {
- zoneObj.infos = this.localFun[0];
- }
- if (this.scene) {
- // 旧逻辑--计算区域交集--
- // zoneObj = this.calIntersect(zoneObj);
- // 设置业务空间轮廓线
- zoneObj = this.setZoneOutline(zoneObj);
- this.handleCreateZone(zoneObj);
- }
- }
- /**
- * 删除业务空间
- */
- deleteRoom() {
- let arr = this.scene?.selectContainer.itemList || [];
- if (arr.length) {
- let temp = arr
- .map((t) => {
- if (t instanceof SZoneItem) {
- return { id: t.data.RoomID };
- }
- })
- .filter((item) => item);
- if (temp.length) {
- this.handleDeleteZone(temp);
- }
- }
- }
- /**
- * 生成底图json
- */
- saveMap() {
- if (this.scene) {
- this.scene.generateFile(this.floorKey, () => {
- this.$message.success('修改模型成功');
- this.init(1)
- });
- }
- }
- /**
- * 画墙
- */
- drawWall() {
- if (this.scene) {
- this.scene.drawCmd = "wallDraw";
- }
- }
- /**
- * 单个计算交集
- */
- calIntersect(zoneObj: any) {
- // 画了切割区域
- if (this.scene.cutItem && this.scene.cutItem.closeFlag) {
- const seg = this.scene.getCurInZone();
- const poly = this.scene.getSpaceCutIntersect(seg);
- for (let key in poly) {
- for (let i = 0; i < poly[key].length; i++) {
- const arr = poly[key][i].map((t) => {
- return t.map((it) => {
- return {
- X: Number(it.x.toFixed(2)),
- Y: -Number(it.y.toFixed(2)),
- Z: 0,
- };
- });
- });
- zoneObj.outline.push(arr);
- }
- }
- } else if (this.scene.zoneList.length) {
- // 没画切割区域,但是有业务空间
- const poly = this.scene.getSpaceZoneIntersect();
- // 与已有业务空间的外接矩阵有交集
- if (poly) {
- for (let key in poly) {
- for (let i = 0; i < poly[key].length; i++) {
- const arr = poly[key][i].map((t) => {
- return t.map((it) => {
- return {
- X: Number(it.x.toFixed(2)),
- Y: -Number(it.y.toFixed(2)),
- Z: 0,
- };
- });
- });
- zoneObj.outline.push(arr);
- }
- }
- } else {
- let arr = this.scene?.selectContainer.itemList;
- arr?.forEach((t) => {
- zoneObj.outline.push(t.data.OutLine);
- });
- }
- } else {
- // 没有业务空间,也没有绘制切割区域
- let arr = this.scene?.selectContainer.itemList;
- arr?.forEach((t) => {
- zoneObj.outline.push(t.data.OutLine);
- });
- }
- return zoneObj;
- }
- /**
- * 新逻辑添加业务空间轮廓线
- */
- setZoneOutline(zoneObj: any) {
- if (this.scene) {
- if (this.scene.drawItem) {
- if (
- this.scene.drawItem.pointList.length &&
- this.scene.drawItem.pointList.length > 2
- ) {
- const temp = this.scene.drawItem.pointList.map((t) => {
- return {
- X: t.x,
- Y: -t.y,
- Z: 0,
- };
- });
- zoneObj.outline.push([temp]);
- }
- }
- let arr = this.scene.selectContainer.itemList;
- if (arr.length) {
- arr.forEach((t) => {
- if (t instanceof SSpaceItem)
- zoneObj.outline.push(t.data.OutLine);
- });
- }
- }
- return zoneObj;
- }
- /**
- * 创建业务空间接口
- */
- handleCreateZone(zoneObj: any) {
- const pa = {
- content: [zoneObj],
- };
- if (Array.isArray(zoneObj)) {
- pa.content = zoneObj;
- }
- this.canvasLoading = true;
- createZone(pa).then(() => {
- this.$message.success("创建成功");
- this.init(2);
- });
- }
- /**
- * 更新业务空间接口
- */
- handleUpdateZone(zoneObj: any) {
- const pa = {
- content: [zoneObj],
- };
- if (Array.isArray(zoneObj)) {
- pa.content = zoneObj;
- }
- this.canvasLoading = true;
- updateZone(pa).then(() => {
- this.$message.success("更新成功");
- this.init(2);
- });
- }
- /**
- * 删除业务空间接口
- */
- handleDeleteZone(zone: any) {
- let pa = [zone]
- if (Array.isArray(zone)) {
- pa = zone;
- }
- this.canvasLoading = true;
- deleteZone(pa).then(() => {
- this.$message.success("删除成功");
- this.init(2);
- });
- }
- // 适配底图到窗口
- fit() {
- this.view?.fitSceneToView();
- }
- // 保存为png
- savePng() {
- this.view?.saveImage(`1.png`, "png");
- }
- // 保存为svg
- saveSvg() {
- this.view?.saveSceneSvg(`1.svg`, 6400, 4800);
- }
- // 保存json
- saveJson() {
- try {
- this.view?.saveFloorJson(
- `${this.floor.build}-${this.floor.localName}.json`
- );
- } catch (err) {
- console.log(err);
- this.view?.saveFloorJson(`1.json`);
- }
- }
- // 切割划分
- divide() {
- if (this.scene) {
- this.scene.drawCmd = "zoneDraw";
- }
- }
- // 清除切割划分
- clearDivide() {
- // @ts-ignore
- this.view!.scene.clearCut();
- }
- // 缩放
- scale(val: number) {
- if (!this.view) {
- return;
- }
- let scale = this.view.scale;
- this.view.scaleByPoint(
- val / scale,
- this.canvasWidth / 2,
- this.canvasHeight / 2
- );
- }
- groupSelect() {
- console.log("groupSelect");
- }
- changeAbsorb() {
- console.log("changeAbsorb");
- }
- /**
- * 删除墙
- */
- clearWall() {
- if (this.scene) {
- if (this.scene.selectContainer.itemList.length) {
- const item = this.scene.selectContainer.itemList[0];
- if (item instanceof SWallItem || item instanceof CustomWall) {
- this.scene.deleteItem(item);
- }
- }
- }
- }
- @Watch("view.scale", { immediate: true, deep: true })
- onScaleChange(n: number) {
- if (this.$refs.canvasFun) {
- // @ts-ignore
- let s = (n * 10) / this.view.minScale;
- // @ts-ignore
- this.$refs.canvasFun.sliderVal = s > 1000 ? 1000 : s;
- }
- }
- @Watch("scene.drawCmd", { immediate: true, deep: true })
- onCmdChange(n: string) {
- if (!n) {
- if (this.$refs.canvasFun) {
- this.$refs.canvasFun.active = "";
- this.$refs.canvasFun.isSwitch = false;
- }
- }
- }
- }
- </script>
- <style lang="scss">
- #graphContainer {
- position: relative;
- width: 100%;
- height: 100%;
- .canvas-actions-box {
- position: absolute;
- bottom: 14px;
- left: 50%;
- transform: translateX(-50%);
- z-index: 99;
- }
- .buttons-box {
- position: absolute;
- bottom: 68px;
- left: 0;
- padding: 0 16px;
- width: 100%;
- z-index: 999;
- & > div {
- margin: 0 auto;
- }
- .button-group {
- width: 300px;
- height: 35px;
- margin: 0 auto;
- text-align: center;
- }
- }
- }
- </style>
|