Browse Source

业务空间修改,字体图标引入

haojianlong 4 years ago
parent
commit
61c13e8d23

+ 2 - 1
.eslintrc.js

@@ -14,6 +14,7 @@ module.exports = {
   },
   rules: {
     "@typescript-eslint/ban-types": "off",
+    "@typescript-eslint/ban-ts-comment": "off",
     "@typescript-eslint/explicit-module-boundary-types": "off",
     "@typescript-eslint/member-delimiter-style": [
       "error",
@@ -41,7 +42,7 @@ module.exports = {
     "vue/camelcase": "error",
     "vue/comma-dangle": "error",
     "vue/component-name-in-template-casing": ["error", "kebab-case"],
-    "vue/eqeqeq": "error",
+    "vue/eqeqeq": ["off"],
     "vue/key-spacing": "error",
     "vue/match-component-file-name": "error",
     "vue/object-curly-spacing": ["error", "always"]

File diff suppressed because it is too large
+ 489 - 0
src/assets/iconfont/iconfont.css


BIN
src/assets/iconfont/iconfont.eot


File diff suppressed because it is too large
+ 380 - 0
src/assets/iconfont/iconfont.svg


BIN
src/assets/iconfont/iconfont.ttf


BIN
src/assets/iconfont/iconfont.woff


+ 1 - 0
src/main.ts

@@ -13,6 +13,7 @@ import App from "@/App.vue";
 import store from "@/store";
 import router from "@/router/index";
 import "@/icons/components";
+import '@/assets/iconfont/iconfont.css'
 import "@/permission";
 
 Vue.use(uploader);

+ 21 - 0
src/utils/graph/FloorScene.ts

@@ -5,6 +5,7 @@ import { SSpaceItem } from "@persagy-web/big/lib/items/floor/SSpaceItem";
 import { SVirtualWallItem } from "@persagy-web/big/lib/items/floor/SVirtualWallItem";
 import { SWallItem } from "@persagy-web/big/lib/items/floor/SWallItem";
 import { SWindowItem } from "@persagy-web/big/lib/items/floor/SWindowItem";
+import { SZoneItem } from "@persagy-web/big/lib/items/floor/ZoneItem";
 import { Casement } from "@persagy-web/big/lib/types/floor/Casement";
 import { Column } from "@persagy-web/big/lib/types/floor/Column";
 import { Door } from "@persagy-web/big/lib/types/floor/Door";
@@ -32,6 +33,8 @@ export class FloorScene extends SGraphScene {
     virtualWallList: SVirtualWallItem[] = [];
     /** 空间list   */
     spaceList: SSpaceItem[] = [];
+    /** 业务空间list */
+    zoneList: SZoneItem[] = [];
 
     /** 空间是否可选  */
     _isSpaceSelectable: boolean = true;
@@ -51,6 +54,24 @@ export class FloorScene extends SGraphScene {
         );
     } // Set isSpaceSelectable
 
+    /** 空间是否可选  */
+    _isZoneSelectable: boolean = true;
+    get isZoneSelectable(): boolean {
+        return this._isZoneSelectable;
+    } // Get isZoneSelectable
+    set isZoneSelectable(v: boolean) {
+        if (this._isZoneSelectable === v) {
+            return;
+        }
+        this._isZoneSelectable = v;
+        this.zoneList.map(
+            (t: SZoneItem): SZoneItem => {
+                t.selectable = this._isZoneSelectable;
+                return t;
+            }
+        );
+    } // Set isZoneSelectable
+
     constructor() {
         super()
         // 设置始终不出现选择器

+ 170 - 0
src/views/maintain/space/components/canvasFun.vue

@@ -0,0 +1,170 @@
+<template>
+    <el-row id="canvas-actions-box" :class="{ 'isEdit': config.isEdit }">
+        <div v-if="config.isEdit&&config.groupSelect" :class="{ 'active': active === 'groupSelect' }" @click="groupSelect">
+            <i class="iconfont icon-shuxingxuanze"></i>
+        </div>
+        <div @click="fitToWindow">
+            <i class="iconfont icon-maximize"></i>
+        </div>
+        <div v-if="!config.isEdit">
+            <el-dropdown size="mini" placement="top-start" @command="handleCommand">
+                <i class="el-icon-download" style="font-size:20px;color:#fff;"></i>
+                <el-dropdown-menu slot='dropdown'>
+                    <el-dropdown-item command="savePng">保存为png</el-dropdown-item>
+                    <el-dropdown-item command="saveSvg">保存为svg</el-dropdown-item>
+                    <el-dropdown-item command="saveJson">保存为Json</el-dropdown-item>
+                </el-dropdown-menu>
+            </el-dropdown>
+        </div>
+        <div v-if="config.isEdit&&config.divide" :class="{ 'active': active === 'divide' }" @click="divide">
+            <el-dropdown size="mini" placement="top-start" @command="handleDivideCommand" :hide-on-click="false">
+                <i class="iconfont icon-edit1"></i>
+                <!-- <el-dropdown-menu slot='dropdown'>
+                    <el-dropdown-item command="savePng">
+                        吸附 <el-switch v-model="isSwitch"></el-switch>
+                    </el-dropdown-item>
+                </el-dropdown-menu> -->
+            </el-dropdown>
+        </div>
+        <div v-if="config.isEdit&&config.divide" @click="clearDivide">
+            <i class="iconfont icon-Erase"></i>
+        </div>
+        <div @click="reduce">
+            <i class="iconfont icon-narrow"></i>
+        </div>
+        <div class="line">
+            <el-slider tooltip-class="tooltip-class" :min="min" v-model="sliderVal" :show-tooltip="false" @input="scale" :max="max"></el-slider>
+        </div>
+        <div @click="plus">
+            <i class="iconfont icon-zoom"></i>
+        </div>
+    </el-row>
+</template>
+<script lang="ts">
+interface configFace {
+    isEdit: boolean;
+    divide: boolean;
+    groupSelect: boolean;
+}
+import { Vue, Component, Prop } from "vue-property-decorator";
+@Component
+export default class canvasFun extends Vue {
+    @Prop({
+        type: Object,
+        default: {
+            isEdit: false,
+            divide: true,
+            groupSelect: false,
+        },
+    })
+    config!: configFace;
+
+    sliderVal = 1; // 滑块值
+    active = "";
+    min = 1;
+    max = 1000;
+    everyScale = 1; // 每份的放大倍数
+    isSwitch = false; // 是否开启吸附
+
+    groupSelect() {
+        this.active = "groupSelect";
+        this.$emit("groupSelect");
+    }
+    // 适配大小
+    fitToWindow() {
+        this.$emit("fit");
+    }
+    // 下拉菜单
+    handleCommand(command: string) {
+        this.$emit(command);
+    }
+    // 是否开启吸附
+    handleDivideCommand() {
+        this.$emit("changeAbsorb", this.isSwitch);
+    }
+    // 切割编辑
+    divide() {
+        this.active = "divide";
+        this.$emit("divide");
+    }
+    // 清除编辑
+    clearDivide() {
+        this.active = "";
+        this.$emit("clearDivide");
+    }
+    // 撤销
+    undo() {
+        this.$emit("undo");
+    }
+    // 反撤销
+    redo() {
+        this.$emit("redo");
+    }
+    // 减
+    reduce() {
+        this.sliderVal /= 1.1;
+        if (this.sliderVal < this.min) {
+            this.sliderVal = this.min;
+        }
+        this.scale(this.sliderVal);
+    }
+    // 缩放
+    scale(val: number) {
+        // 换算
+        let scale = (val * this.everyScale) / 10;
+        this.$emit("scale", scale);
+    }
+    // 加
+    plus() {
+        this.sliderVal *= 1.1;
+        if (this.sliderVal > this.max) {
+            this.sliderVal = this.max;
+        }
+        this.scale(this.sliderVal);
+    }
+}
+</script>
+<style lang="scss" scoped>
+#canvas-actions-box {
+    & > div {
+        float: left;
+        font-size: 20px;
+        padding: 0 10px;
+        color: #fff;
+        background-color: #6da60f;
+        line-height: 2;
+        i {
+            cursor: pointer;
+            color: #fff;
+        }
+    }
+    & > div:active {
+        background-color: #4b7902;
+    }
+    & > div.active {
+        background-color: #4b7902;
+    }
+    &.isEdit > div {
+        background-color: #02a7f0;
+    }
+    &.isEdit > div:active {
+        background-color: #027db4;
+    }
+    &.isEdit > div.active {
+        background-color: #027db4;
+    }
+    & > div.line {
+        width: 200px;
+        height: 40px;
+        padding: 0;
+        ::v-deep .el-slider__runway {
+            margin: 18px 0;
+            height: 4px;
+            .el-slider__bar {
+                background-color: #fff;
+                height: 4px;
+            }
+        }
+    }
+}
+</style>

+ 290 - 16
src/views/maintain/space/components/spaceGraph.vue

@@ -1,44 +1,145 @@
 <template>
     <div id="graphContainer" ref="graphContainer">
+        <el-row class="buttons-box">
+            <div>
+                <el-autocomplete popper-class="my-autocomplete" v-model="search" :fetch-suggestions="querySearch" placeholder="输入平面图中已有的业务空间名称进行查找"
+                    width="180px" @select="handleSelect">
+                    <i class="el-icon-search el-input__icon" slot="suffix"></i>
+                    <template slot-scope="{ item }">
+                        <div class="name" style="position: relative;padding-right:40px;overflow: hidden;text-overflow:ellipsis;white-space: nowrap;"
+                            :title="item.data.RoomLocalName">
+                            {{ item.data.RoomLocalName }}
+                            <span class="addr" style="position: absolute;right:0;color:#409EFF;">定位</span>
+                        </div>
+                    </template>
+                </el-autocomplete>
+            </div>
+            <div class="button-group">
+                <!-- 默认操作模式 -->
+                <div v-show="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-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-show="type==3">
+                    <el-button plain @click="createNewZone">创建单个全新的业务空间</el-button>
+                    <el-button plain @click="cancelGraphy">取 消</el-button>
+                </div>
+                <!-- 重新划分业务空间 -->
+                <div v-show="type==4">
+                    <el-button plain @click="cancelGraphy">取 消</el-button>
+                    <el-button type="primary" @click="saveRefactorBSP">保存</el-button>
+                </div>
+                <!-- 批量创建所选业务空间 -->
+                <div v-show="type==5">
+                    <el-button type="primary" @click="groupCreateZone">批量创建所选业务空间</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" />
+        </el-row>
     </div>
 </template>
 <script lang="ts">
-import { Vue, Component } from "vue-property-decorator";
+import { Vue, Component, Watch } from "vue-property-decorator";
 import { FloorView } from "@/utils/graph/FloorView";
 import { FloorScene } from "@/utils/graph/FloorScene";
+import canvasFun from "./canvasFun";
 
-@Component
+@Component({
+    components: { canvasFun },
+})
 export default class spaceGraph extends Vue {
     canvasWidth = 800;
     canvasHeight = 800;
-    view: FloorView | undefined = undefined;
+    view: FloorView | null = null;
+    scene: FloorScene | null = null;
     floorMap =
         "/image-service/common/file_get?systemId=revit&key=base/76233a3214dd11eb94d469663ce1649a.jsonz";
     canvasLoading = false;
-
+    type = 1;
+    config = {
+        isEdit: false,
+        divide: true,
+        groupSelect: false,
+    };
+    search = ""; //搜索
+    zoneDisable = true;
+    curZoneItem = {};
+    zoneList = [];
+    buildFloor: string[] = [];
+    // 挂载
     mounted(): void {
         this.canvasWidth = this.$refs.graphContainer.offsetWidth;
         this.canvasHeight = this.$refs.graphContainer.offsetHeight;
         this.getGraph();
     }
+    // 初始化
+    init(initType: number): void {
+        this.type = 1;
+        if (this.scene) {
+            // this.scene.clearSpaceSelection();
+            // this.scene.clearZoneSelection();
+            // this.scene.clearLikeSpaces();
+            // this.zoneDisable = true;
+            // this.scene.isZoneSelectable = true;
+            // this.scene.isSpaceSelectable = false;
+        }
+        if (
+            this.buildFloor.indexOf("all") > -1 ||
+            this.buildFloor.indexOf("noKnow") > -1
+        ) {
+            return;
+        }
 
-    init(): void {
-        console.log('init');
+        if (initType == 1) {
+            // 底图
+            // this.getGraphy();
+        } else {
+            // 业务空间
+            // this.getBusinessSpace();
+        }
+        this.config = {
+            isEdit: false,
+            divide: true,
+            groupSelect: true,
+        };
+        // 获取当前楼层的元空间
+        // this.getFloorISpace();
+        // 查询未关联业务空间的元空间
+        // this.getISPSPUnrelaBSP();
+        // 查询未关联平面图的业务空间
+        // this.getBSPunrelaISP();
     }
-
+    // 获取底图
     getGraph(): void {
         const scene = new FloorScene();
         this.canvasLoading = true;
-        this.clearGraphy()
+        this.clearGraphy();
+        this.scene = null;
         scene.loadUrl(this.floorMap).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") {
@@ -46,16 +147,144 @@ export default class spaceGraph extends Vue {
             this.$message.warning("数据解析异常");
             return;
         }
-        this.view?.fitSceneToView()
+        this.view?.fitSceneToView();
+        this.view!.minScale = this.view!.scale;
+        if (this.$refs.canvasFun) {
+            // @ts-ignore
+            this.$refs.canvasFun.everyScale = this.view.scale;
+        }
     }
-
     // 清除canvas
     clearGraphy() {
-      if (this.view) {
-        this.view.scene = null;
-        return
-      }
-      this.view = new FloorView('spaceCanvas')
+        if (this.view) {
+            this.view.scene = null;
+            return;
+        }
+        this.view = new FloorView("spaceCanvas");
+    }
+
+    // 搜索
+    querySearch(queryString: string, cb: Function) {
+        let restaurants = this.zoneList;
+        let results = queryString
+            ? restaurants.filter(this.createFilter(queryString))
+            : restaurants;
+        // 调用 callback 返回建议列表的数据
+        cb(results);
+    }
+
+    // 过滤器
+    createFilter(queryString: any) {
+        return (restaurant: any) => {
+            return restaurant.data.RoomLocalName.indexOf(queryString) > -1;
+        };
+    }
+
+    // 查询选中,定位
+    handleSelect(zone) {
+        //   // 清空选中
+        //   this.scene.clearSpaceSelection();
+        //   this.scene.clearZoneSelection();
+        //   // 选中当前
+        //   zone.selected = true;
+        //   this.curZoneItem = zone;
+        //   this.zoneDisable = false;
+        //   this.view.fitSelectedToView();
+    }
+
+    // 点击创建业务空间
+    editGraphy() {
+        this.type = 3;
+        this.config.isEdit = true;
+        this.config.groupSelect = false;
+        this.config.divide = true;
+        this.scene!.isSpaceSelectable = true;
+        this.scene!.isZoneSelectable = false;
+        this.view?.update();
+    }
+    // 创建新的业务空间
+    createNewZone() {
+        //   let arr = this.scene.getSelectedSpaces();
+        //   if (arr.length) {
+        //     let tempArr = [];
+        //     arr.map(t => {
+        //       tempArr.push(this.BIMIDToSIName[t.data.SourceId]);
+        //     })
+        //     this.$refs.createBSP.showDialog(tempArr.toString());
+        //   } else {
+        //     this.$message.warning('请至少选择一个空间');
+        //   }
+    }
+
+    handleCommand() {}
+
+    refactorBSP() {}
+
+    editeSpaceDetail() {}
+
+    // 取消(所有取消公用)
+    cancelGraphy() {
+        this.init(2);
+    }
+
+    saveRefactorBSP() {}
+
+    groupCreateZone() {}
+
+    // 适配底图到窗口
+    fit() {
+        this.view?.fitSceneToView();
+    }
+    // 保存为png
+    savePng() {
+        this.view?.saveImage(`1.png`, "png");
+    }
+    // 保存为svg
+    saveSvg() {
+        this.view?.saveSceneSvg(`1.svg`, 6400, 4800);
+    }
+    // 保存json
+    saveJson() {
+        this.view?.saveFloorJson(`1.json`);
+    }
+    // 切割划分
+    divide() {
+        this.scene.isCutting = true;
+    }
+    // 清除切割划分
+    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");
+    }
+
+    @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;
+        }
     }
 }
 </script>
@@ -64,5 +293,50 @@ export default class spaceGraph extends Vue {
     position: relative;
     width: 100%;
     height: 100%;
+    .canvas-actions-box {
+        position: absolute;
+        bottom: 60px;
+        left: 50%;
+        transform: translateX(-50%);
+        z-index: 99;
+    }
+    .buttons-box {
+        position: absolute;
+        top: 16px;
+        left: 0;
+        padding: 0 16px;
+        width: 100%;
+        z-index: 999;
+        & > div {
+            float: left;
+        }
+        .el-autocomplete {
+            display: inline-block;
+            width: 320px;
+            margin-right: 10px;
+        }
+        .button-group button,
+        .button-group .el-dropdown {
+            display: block;
+            float: left;
+        }
+        .my-autocomplete {
+            li {
+                line-height: normal;
+                padding: 7px;
+                .name {
+                    text-overflow: ellipsis;
+                    overflow: hidden;
+                }
+                .addr {
+                    font-size: 12px;
+                    color: #b4b4b4;
+                }
+                .highlighted .addr {
+                    color: #ddd;
+                }
+            }
+        }
+    }
 }
 </style>

+ 2 - 1
src/views/maintain/space/index.vue

@@ -64,7 +64,7 @@ export default class spaceIndex extends Vue {
         },
     ];
     // 建筑楼层更改
-    handleChange(v) {
+    handleChange(v: string) {
         console.log(v);
     }
     // 搜索
@@ -94,6 +94,7 @@ export default class spaceIndex extends Vue {
             border-top: none;
             .search {
                 padding: 16px;
+                border-bottom: 1px solid #e1e7ea;
                 & > .item + .item {
                     margin-left: 16px;
                 }

+ 1 - 1
tsconfig.json

@@ -45,4 +45,4 @@
         "node_modules",
         "src/@types/**/*"
     ]
-}
+}