Selaa lähdekoodia

Merge branch 'master' of http://39.106.8.246:3003/web/wanda-adm

YaolongHan 4 vuotta sitten
vanhempi
commit
e8692e5eb5

+ 1 - 1
package.json

@@ -15,7 +15,7 @@
   "dependencies": {
     "@babel/runtime": "^7.12.5",
     "@persagy-web/base": "2.2.1",
-    "@persagy-web/big": "2.2.49",
+    "@persagy-web/big": "2.2.50",
     "@persagy-web/draw": "2.2.13",
     "@persagy-web/graph": "2.2.45",
     "axios": "^0.21.1",

+ 248 - 27
src/utils/graph/DivideFloorScene.ts

@@ -4,15 +4,22 @@ import { SPoint, SRect } from "@persagy-web/draw/lib";
 import { FloorScene } from "./FloorScene";
 import { HighlightItem } from "./HighlightItem";
 import { ShadeItem } from "./ShadeItem";
+// @ts-ignore
+import { intersect, polygon, segments, combine, selectIntersect, selectUnion, selectDifference, selectDifferenceRev, difference } from "polybooljs";
+import { DrawZoneItem } from "./DrawZoneItem";
+import { SItemStatus } from "@persagy-web/big/lib";
 
 export class DivideFloorScene extends FloorScene {
     /** 划分item  */
     cutItem: ShadeItem | null = null;
-    /** 是否开启切分  */
-    isCutting: boolean = false;
+
+    /** 绘制的分区item */
+    drawItem: DrawZoneItem | null = null;
+    /** 当前绘制命令 cut-交集区域绘制 zoneDraw-绘制业务空间 */
+    drawCmd: string = '';
 
     /** 是否开启吸附  */
-    private _isAbsorbing: boolean = true;
+    private _isAbsorbing: boolean = false;
     get isAbsorbing(): boolean {
         return this._isAbsorbing;
     } // Get isAbsorbing
@@ -27,13 +34,19 @@ export class DivideFloorScene extends FloorScene {
      * 清除划分区域
      */
     clearCut(): void {
-        if (this.cutItem) {
+        if (this.cutItem && this.drawCmd == 'cut') {
             this.grabItem = null;
             this.removeItem(this.cutItem);
             this.cutItem = null;
-            this.isCutting = false;
             this.view && this.view.update();
         }
+        if (this.drawItem && this.drawCmd == 'zoneDraw') {
+            this.grabItem = null;
+            this.removeItem(this.drawItem);
+            this.drawItem = null;
+            this.view && this.view.update();
+        }
+        this.drawCmd = '';
     } // Function clearCut()
 
     /**
@@ -44,24 +57,32 @@ export class DivideFloorScene extends FloorScene {
     */
     onMouseDown(event: SMouseEvent): boolean {
         if (event.buttons == 1) {
-            if (this.isCutting) {
-                // 判断是否开启吸附,并且有吸附的点
-                if (
-                    this.isAbsorbing &&
-                    this.highLight &&
-                    this.highLight.visible
-                ) {
-                    event.x = this.highLight.point.x;
-                    event.y = this.highLight.point.y;
+            // 判断是否开启吸附,并且有吸附的点
+            if (
+                this.isAbsorbing &&
+                this.highLight &&
+                this.highLight.visible
+            ) {
+                event.x = this.highLight.point.x;
+                event.y = this.highLight.point.y;
+            }
+            if (this.drawCmd == 'cut') {
+                if (!this.cutItem) {
+                    let point = new SPoint(event.x, event.y);
+                    let item = new ShadeItem(null, point);
+                    this.addItem(item);
+                    this.cutItem = item;
+                    this.grabItem = item;
+                    return true;
                 }
-                if (this.cutItem) {
-                    return this.cutItem.onMouseDown(event);
-                } else {
+            } else if (this.drawCmd == 'zoneDraw') {
+                if (!this.drawItem) {
                     let point = new SPoint(event.x, event.y);
-                    let cut = new ShadeItem(null, point);
-                    this.addItem(cut);
-                    this.cutItem = cut;
-                    this.grabItem = cut;
+                    let item = new DrawZoneItem(null, point);
+                    item.status = SItemStatus.Create;
+                    this.addItem(item);
+                    this.drawItem = item;
+                    this.grabItem = item;
                     return true;
                 }
             }
@@ -190,12 +211,12 @@ export class DivideFloorScene extends FloorScene {
     } // Function isPointInAbsorbArea()
 
     /**
-         *  吸附空间线
-         *
-         *  @param  event       鼠标事件对象
-         *  @param  absorbLen   吸附距离
-         *  @return PointToLine 吸附的线
-         */
+     *  吸附空间线
+     *
+     *  @param  event       鼠标事件对象
+     *  @param  absorbLen   吸附距离
+     *  @return PointToLine 吸附的线
+     */
     absorbSpaceLine(event: SMouseEvent, absorbLen: number): any {
         let minPointDis = Number.MAX_SAFE_INTEGER;
         let Point, Line;
@@ -232,4 +253,204 @@ export class DivideFloorScene extends FloorScene {
             Line: Line
         };
     } // Function absorbSpaceLine()
+
+    /**
+     * 计算选中的空间与业务空间的差集
+    */
+    getSpaceZoneIntersect(): SPoint[][] | undefined {
+        // 未选中空间- 不计算
+        if (!this.selectContainer.itemList.length) {
+            return
+        }
+        // 没有业务空间不计算
+        if (!this.zoneList.length) {
+            return
+        }
+        // 生成选中的空间计算时用的格式
+        const space = {
+            regions: [],
+            inverted: false
+        }
+        const sourceIdToDiff = {};
+        try {
+            let poly1, poly2;
+            const start = +new Date();
+            let rect1: SRect, list = [];
+            // 计算外接矩阵与选中空间相交的业务空间的所有轮廓
+            this.selectContainer.itemList.forEach(item => {
+                rect1 = item.boundingRect();
+                this.zoneList.forEach(t => {
+                    if (t.visible) {
+                        let rect2 = t.boundingRect();
+                        // 外接矩阵是否相交,缩小计算范围
+                        if (SMathUtil.rectIntersection(rect1, rect2)) {
+                            t.pointList.forEach((zoneLine): void => {
+                                let polygons = {
+                                    regions: [],
+                                    inverted: false
+                                };
+                                zoneLine.forEach((po): void => {
+                                    let point = SMathUtil.transferToArray(po);
+                                    polygons.regions.push(point);
+                                });
+                                list.push(polygons);
+                            })
+                        }
+                    }
+                })
+            })
+            // 
+            if (list.length) {
+                let seg1 = segments(list[0]),
+                    seg2,
+                    comb;
+                for (let i = 1; i < list.length; i++) {
+                    seg2 = segments(list[i]);
+                    comb = combine(seg1, seg2);
+                    seg1 = selectUnion(comb);
+                }
+                poly1 = seg1;
+                this.selectContainer.itemList.forEach(t => {
+                    let key = t.data.SourceId;
+                    poly2 = {
+                        regions: [],
+                        inverted: false
+                    }
+                    poly2.regions = t.pointList[0].map((item): number[][] => {
+                        return SMathUtil.transferToArray(item);
+                    });
+                    const comb = combine(segments(poly2), poly1)
+                    const diffObj = selectDifference(comb);
+                    const diffPoly = polygon(diffObj)
+                    // 理论上只要选择了空间 length就不会为0
+                    if (diffPoly.regions.length) {
+                        let outlineList = SMathUtil.getIntersectInArray(
+                            diffPoly.regions
+                        );
+                        console.log(outlineList);
+                        // @ts-ignore
+                        sourceIdToDiff[key] = outlineList.map(t => {
+                            let arr = [t.Outer];
+                            t.Inner.forEach((inner): void => {
+                                arr.push(inner);
+                            });
+                            return arr;
+                        });
+                    }
+                });
+                const end = +new Date()
+                console.log(sourceIdToDiff);
+                console.log(end - start, 'comb-diff');
+                return sourceIdToDiff
+            }
+        } catch (err) {
+            console.log(err);
+        }
+    }
+
+    /**
+     * 计算选中的空间与绘制的区域交集
+    */
+    getSpaceCutIntersect(seg?: any): SPoint[][] | undefined {
+        // 未选中空间- 不计算
+        if (!this.selectContainer.itemList.length) {
+            return
+        }
+        // 没有绘制不计算
+        if (!this.cutItem) {
+            return
+        }
+        const sourceIdToIntersect = {};
+        try {
+            const start = +new Date();
+            let cutPoly;
+            if (seg) {
+                cutPoly = seg
+            } else {
+                const poly = {
+                    regions: [SMathUtil.transferToArray(this.cutItem.pointList)],
+                    inverted: false
+                }
+                cutPoly = segments(poly)
+            }
+            this.selectContainer.itemList.forEach(item => {
+                const arr = item.pointList[0].map(t => {
+                    return SMathUtil.transferToArray(t);
+                })
+                const poly2 = {
+                    regions: arr,
+                    inverted: false
+                }
+                const seg = segments(poly2)
+                const comb = combine(cutPoly, seg)
+                if (item.data.SourceId) {
+                    const spoly = polygon(selectIntersect(comb));
+                    // 绘制切割区域可能与空间没有交集
+                    if (spoly.regions.length) {
+                        let outlineList = SMathUtil.getIntersectInArray(
+                            spoly.regions
+                        );
+                        console.log(outlineList);
+                        // @ts-ignore
+                        sourceIdToIntersect[item.data.SourceId] = outlineList.map(t => {
+                            let arr = [t.Outer];
+                            t.Inner.forEach((inner): void => {
+                                arr.push(inner);
+                            });
+                            return arr;
+                        });
+                        // 得到的结果
+                        // sourceIdToIntersect[item.data.SourceId] = polygon(selectIntersect(comb))
+                    } else {
+                        // 没有交集
+                    }
+                }
+            })
+            const end = +new Date()
+            console.log(end - start, 'comb-intersect', sourceIdToIntersect);
+            return sourceIdToIntersect
+        } catch (err) {
+            console.log(err);
+        }
+        return
+    }
+
+    /**
+     * 如果场景中既有绘制的区域也有创建好的业务空间,则在区域中将已创建的业务空间减去
+    */
+    getCurInZone() {
+        if (!this.cutItem) {
+            return
+        }
+        // 绘制区域外接矩阵
+        const rect2 = this.cutItem.boundingRect()
+        // 绘制区域的多边形 - 也是每次减去业务空间后剩下的多边形
+        let poly = segments({
+            regions: [SMathUtil.transferToArray(this.cutItem.pointList)],
+            inverted: false
+        })
+        this.zoneList.forEach(item => {
+            if (item.visible) {
+                const rect1 = item.boundingRect();
+                if (SMathUtil.rectIntersection(rect1, rect2)) {
+                    item.pointList.forEach((zoneLine): void => {
+                        let polygons = {
+                            regions: [],
+                            inverted: false
+                        }
+                        zoneLine.forEach((po): void => {
+                            let point = SMathUtil.transferToArray(po);
+                            polygons.regions.push(point);
+                        });
+                        const segZone = segments(polygons);
+                        const comb = combine(poly, segZone);
+                        poly = selectDifference(comb)
+                    })
+                }
+            }
+        })
+        console.log(poly);
+        // poly为segments类型
+        return poly;
+    }
 }

+ 680 - 0
src/utils/graph/DrawZoneItem.ts

@@ -0,0 +1,680 @@
+import { SKeyCode, SMouseEvent, SUndoStack } from "@persagy-web/base/lib";
+import { ItemOrder, SItemStatus } from "@persagy-web/big/lib";
+import { SMathUtil } from "@persagy-web/big/lib/utils/SMathUtil";
+import { SColor, SLine, SLineCapStyle, SPainter, SPoint, SPolygonUtil, SRect, SSize } from "@persagy-web/draw/lib";
+import { SGraphItem, SGraphPointListDelete, SGraphPointListInsert, SGraphPointListUpdate, SGraphStyleItem, SLineStyle } from "@persagy-web/graph/lib";
+
+export class DrawZoneItem extends SGraphStyleItem {
+    /** X 坐标最小值 */
+    private minX = Number.MAX_SAFE_INTEGER;
+    /** X 坐标最大值 */
+    private maxX = Number.MIN_SAFE_INTEGER;
+    /** Y 坐标最小值 */
+    private minY = Number.MAX_SAFE_INTEGER;
+    /** Y 坐标最大值 */
+    private maxY = Number.MIN_SAFE_INTEGER;
+    /** 轮廓线坐标 */
+    private pointList: SPoint[] = [];
+
+    /** 当前状态 */
+    protected _status: number = SItemStatus.Normal;
+    get status(): SItemStatus {
+        return this._status;
+    }
+    set status(value: SItemStatus) {
+        this._status = value;
+        this.undoStack.clear();
+        this.update();
+    }
+
+    /** 是否闭合 */
+    closeFlag: boolean = false;
+    /** 鼠标移动点 */
+    private lastPoint: SPoint | null = null;
+    /** 当前鼠标获取顶点对应索引 */
+    private curIndex: number = -1;
+    /** 当前鼠标获取顶点对应坐标 */
+    private curPoint: null | SPoint = null;
+    /** 灵敏像素 */
+    private len: number = 10;
+    /** 场景像素内部将灵敏像素换算为场景实际距离 */
+    private scenceLen: number = 15;
+    /** 场景像素 */
+    private isShift: boolean = false;
+    /** undo/redo 堆栈 */
+    protected undoStack: SUndoStack = new SUndoStack();
+
+    /**
+     * 构造函数
+     *
+     * @param parent    指向父对象
+     * @param data      图例节点对象数据
+     */
+    constructor(parent: SGraphItem | null, data: any) {
+        super(parent);
+        this.zOrder = ItemOrder.polygonOrder;
+        this.data = data;
+        if (data instanceof Array) {
+            this.pointList = data;
+        } else {
+            this.pointList.push(data);
+            this.lastPoint = data;
+        }
+        this.showSelect = false;
+        this.fillColor = new SColor('#2cd1f780')
+    }
+
+    //////////////////
+    //  以下为对pointList 数组的操作方法
+
+    /**
+     * 储存新的多边形顶点
+     *
+     * @param x   点位得 x 坐标
+     * @param y   点位得 y 坐标
+     * @param i   储存所在索引
+     * @return 添加的顶点
+     */
+    insertPoint(x: number, y: number, i: number | null = null): SPoint {
+        const point = new SPoint(x, y);
+        if (i == null) {
+            this.pointList.push(point);
+        } else {
+            this.pointList.splice(i, 0, point);
+        }
+
+        this.update();
+        return point;
+    }
+
+    /**
+     * 删除点位
+     *
+     * @param i   删除点所在的索引
+     * @return   索引不在数组范围则返回 null
+     */
+    deletePoint(i: number | null = null): SPoint | null {
+        let point;
+        if (i != null) {
+            if (i >= this.pointList.length || i < 0) {
+                point = null;
+            } else {
+                point = new SPoint(this.pointList[i].x, this.pointList[i].y);
+                this.pointList.splice(i, 1);
+            }
+        } else {
+            if (this.pointList.length) {
+                point = this.pointList[this.pointList.length - 1];
+                this.pointList.pop();
+            } else {
+                point = null;
+            }
+        }
+
+        this.curIndex = -1;
+        this.curPoint = null;
+        this.update();
+        return point;
+    }
+
+    /**
+     * 多边形顶点的移动位置
+     *
+     * @param x   点位得 x 坐标
+     * @param y   点位得 y 坐标
+     * @param i   点位得 i 坐标
+     * @return    移动对应得点。如果索引无法找到移动顶点,则返回 null
+     */
+    movePoint(x: number, y: number, i: number): SPoint | null {
+        let point
+        if (i >= this.pointList.length || i < 0) {
+            return null;
+        }
+
+        if (this.pointList.length) {
+            this.pointList[i].x = x;
+            this.pointList[i].y = y;
+        }
+
+        point = this.pointList[i];
+        return point;
+    }
+
+    /**
+     * 展示状态 -- 绘制多边形数组
+     *
+     * @param painter      绘制类
+     * @param pointList    绘制多边形数组
+     */
+    protected drawShowPolygon(painter: SPainter, pointList: SPoint[]): void {
+        painter.save();
+        const eachPx = painter.toPx(1)
+        painter.pen.lineCapStyle = SLineCapStyle.Square;
+        painter.pen.color = this.strokeColor;
+        painter.brush.color = this.fillColor;
+        painter.pen.lineWidth = eachPx * this.lineWidth;
+        if (this.lineStyle == SLineStyle.Dashed) {
+            painter.pen.lineDash = [3 * eachPx, 7 * eachPx];
+        } else if (this.lineStyle == SLineStyle.Dotted) {
+            painter.pen.lineDash = [eachPx * this.lineWidth, eachPx * this.lineWidth];
+        }
+        painter.drawPolygon([...pointList]);
+        painter.restore();
+    }
+
+    /**
+     * 创建状态 -- 绘制多边形数组
+     *
+     * @param painter      绘制类
+     * @param pointList    绘制多边形数组
+     */
+    protected drawCreatePolygon(painter: SPainter, pointList: SPoint[]): void {
+        painter.pen.lineCapStyle = SLineCapStyle.Square;
+        painter.pen.color = this.strokeColor;
+        painter.pen.lineWidth = painter.toPx(this.lineWidth);
+        if (this.lastPoint && pointList.length) {
+            painter.drawLine(
+                pointList[pointList.length - 1].x,
+                pointList[pointList.length - 1].y,
+                this.lastPoint.x,
+                this.lastPoint.y
+            );
+        }
+
+        painter.drawPolyline(pointList);
+        painter.pen.color = SColor.Transparent;
+        painter.brush.color = new SColor(this.fillColor.value);
+        painter.pen.lineWidth = painter.toPx(this.lineWidth);
+        if (this.lastPoint) {
+            painter.drawPolygon([...pointList, this.lastPoint]);
+            // 绘制顶点块
+            painter.pen.color = SColor.Black;
+            painter.brush.color = SColor.White;
+            pointList.forEach(item => {
+                painter.drawCircle(item.x, item.y, painter.toPx(this.len / 2));
+            });
+            // 如果最后一个点在第一个点的灵敏度范围内,第一个点填充变红
+            if (this.pointList.length) {
+                if (
+                    SMathUtil.pointDistance(
+                        this.lastPoint.x,
+                        this.lastPoint.y,
+                        this.pointList[0].x,
+                        this.pointList[0].y
+                    ) < this.scenceLen
+                ) {
+                    // 绘制第一个点的顶点块
+                    painter.pen.color = SColor.Black;
+                    painter.brush.color = SColor.Red;
+                    painter.drawCircle(
+                        this.pointList[0].x,
+                        this.pointList[0].y,
+                        painter.toPx(this.len / 2)
+                    );
+                }
+            }
+        } else {
+            painter.drawPolygon(pointList);
+        }
+    }
+
+    /**
+     *
+     * 编辑状态 -- 绘制多边形数组
+     *
+     * @param painter      绘制类
+     * @param pointList    绘制多边形数组
+     */
+    protected drawEditPolygon(painter: SPainter, pointList: SPoint[]): void {
+        // 展示多边形
+        painter.pen.lineCapStyle = SLineCapStyle.Square;
+        painter.pen.color = this.strokeColor;
+        painter.pen.lineWidth = painter.toPx(this.lineWidth);
+        painter.brush.color = new SColor(this.fillColor.value);
+        painter.drawPolygon([...pointList]);
+        // 绘制顶点块
+        painter.pen.color = SColor.Black;
+        painter.brush.color = SColor.White;
+        pointList.forEach((item, index) => {
+            painter.brush.color = SColor.White;
+            if (index == this.curIndex) {
+                painter.brush.color = new SColor("#2196f3");
+            }
+
+            painter.drawCircle(item.x, item.y, painter.toPx(this.len / 2));
+        });
+    }
+
+    /**
+     * 编辑状态操作多边形数组
+     *
+     * @param event    鼠标事件
+     */
+    protected editPolygonPoint(event: SMouseEvent): void {
+        //  判断是否为删除状态 isShift = true为删除状态
+        if (this.isShift) {
+            // 1 判断是否点击在多边形顶点
+            let lenIndex = -1; // 当前点击到的点位索引;
+            let curenLen = this.scenceLen; // 当前的灵敏度
+            this.pointList.forEach((item, index) => {
+                let dis = SMathUtil.pointDistance(
+                    event.x,
+                    event.y,
+                    item.x,
+                    item.y
+                );
+                if (dis < curenLen) {
+                    curenLen = dis;
+                    lenIndex = index;
+                }
+            });
+
+            // 若点击到,对该索引对应的点做删除
+            if (lenIndex != -1) {
+                if (this.pointList.length <= 3) {
+                    return;
+                }
+
+                const delePoint = new SPoint(
+                    this.pointList[lenIndex].x,
+                    this.pointList[lenIndex].y
+                );
+                this.deletePoint(lenIndex);
+                // 记录顶点操作记录压入堆栈
+                this.recordAction(SGraphPointListDelete, [
+                    this.pointList,
+                    delePoint,
+                    lenIndex
+                ]);
+            }
+        } else {
+            // 1 判断是否点击在多边形顶点
+            this.curIndex = -1;
+            this.curPoint = null;
+            let lenIndex = -1; // 当前点击到的点位索引;
+            let curenLen = this.scenceLen; // 当前的灵敏度
+            this.pointList.forEach((item, index) => {
+                let dis = SMathUtil.pointDistance(
+                    event.x,
+                    event.y,
+                    item.x,
+                    item.y
+                );
+                if (dis < curenLen) {
+                    curenLen = dis;
+                    lenIndex = index;
+                }
+            });
+            this.curIndex = lenIndex;
+            // 2判断是否点击在多边形得边上
+            if (-1 == lenIndex) {
+                let len = SMathUtil.pointToLine(
+                    new SPoint(event.x, event.y),
+                    new SLine(this.pointList[0], this.pointList[1])
+                ),
+                    index = 0;
+                if (this.pointList.length > 2) {
+                    for (let i = 1; i < this.pointList.length; i++) {
+                        let dis = SMathUtil.pointToLine(
+                            new SPoint(event.x, event.y),
+                            new SLine(this.pointList[i], this.pointList[i + 1])
+                        );
+                        if (i + 1 == this.pointList.length) {
+                            dis = SMathUtil.pointToLine(
+                                new SPoint(event.x, event.y),
+                                new SLine(this.pointList[i], this.pointList[0])
+                            );
+                        }
+                        if (dis.MinDis < len.MinDis) {
+                            len = dis;
+                            index = i;
+                        }
+                    }
+                }
+
+                // 判断是否有点
+                if (len.Point) {
+                    // 点在了多边形的边上
+                    if (len.MinDis <= this.scenceLen) {
+                        this.pointList.splice(index + 1, 0, len.Point);
+                        // 记录新增顶点操作记录压入堆栈
+                        this.recordAction(SGraphPointListInsert, [
+                            this.pointList,
+                            len.Point,
+                            index + 1
+                        ]);
+                    } else {
+                        //没点在多边形边上也没点在多边形顶点上
+                        super.onMouseDown(event);
+                    }
+                }
+            } else {
+                // 当捕捉到顶点后 ,记录当前点的xy坐标,用于undo、redo操作
+                this.curPoint = new SPoint(
+                    this.pointList[this.curIndex].x,
+                    this.pointList[this.curIndex].y
+                );
+            }
+
+            // 刷新视图
+            this.update();
+        }
+    }
+
+    /**
+     * 记录相关动作并推入栈中
+     *
+     * @param SGraphCommand      相关命令类
+     * @param any                对应传入参数
+     */
+    protected recordAction(SGraphCommand: any, any: any[]): void {
+        // 记录相关命令并推入堆栈中
+        const sgraphcommand = new SGraphCommand(this.scene, this, ...any);
+        this.undoStack.push(sgraphcommand);
+    }
+
+    /**
+     * 执行取消操作执行
+     */
+    undo(): void {
+        if (this.status == SItemStatus.Normal) {
+            return;
+        }
+        this.undoStack.undo();
+    }
+
+    /**
+     * 执行重做操作执行
+     */
+    redo(): void {
+        if (this.status == SItemStatus.Normal) {
+            return;
+        }
+
+        this.undoStack.redo();
+    }
+
+    /**
+     * 键盘事件
+     *
+     * @param event    事件参数
+     * @return  是否处理该事件
+     */
+    onKeyUp(event: KeyboardEvent): boolean {
+        if (this.status == SItemStatus.Normal) {
+            return false;
+        } else if (this.status == SItemStatus.Create) {
+            if (event.code == "Enter") {
+                // 当顶点大于二个时才又条件执行闭合操作并清空堆栈
+                if (this.pointList.length > 2) {
+                    this.status = SItemStatus.Normal;
+                    //3 传递完成事件状态
+                    this.$emit("finishCreated");
+                    //1 grabItem 置为null
+                    this.releaseItem();
+                }
+            }
+        } else if (this.status == SItemStatus.Edit) {
+            if (event.keyCode == SKeyCode.Delete) {
+                // 当多边形的顶点大于三个允许删除点
+                if (this.pointList.length > 3) {
+                    this.deletePoint(this.curIndex);
+                }
+            }
+        }
+        this.update();
+        return true;
+    }
+
+    /**
+     * 鼠标按下事件
+     *
+     * @param	event      事件参数
+     * @return	 是否处理该事件
+     */
+    onMouseDown(event: SMouseEvent): boolean {
+        if (event.shiftKey) {
+            event = this.compare(event);
+        }
+        // 如果状态为编辑状态则添加点
+        if (this.status == SItemStatus.Create) {
+            // 新增顶点
+            let len = -1;
+            if (this.pointList.length) {
+                len = SMathUtil.pointDistance(
+                    event.x,
+                    event.y,
+                    this.pointList[0].x,
+                    this.pointList[0].y
+                );
+            }
+            if (this.pointList.length > 2 && len > 0 && len < this.scenceLen) {
+                this.$emit("finishCreated");
+                this.status = SItemStatus.Normal;
+                this.releaseItem();
+            } else {
+                this.insertPoint(event.x, event.y);
+                // 记录新增顶点操作记录压入堆栈
+                let pos = new SPoint(event.x, event.y);
+                this.recordAction(SGraphPointListInsert, [this.pointList, pos]);
+            }
+        } else if (this.status == SItemStatus.Edit) {
+            // 对多边形数组做编辑操作
+            this.editPolygonPoint(event);
+        } else {
+            super.onMouseDown(event);
+        }
+        return true;
+    }
+
+    /**
+     * 鼠标移入事件
+     *
+     * @param event   事件参数
+     * @return 是否处理该事件
+     */
+    onMouseEnter(event: SMouseEvent): boolean {
+        return true;
+    }
+
+    /**
+     * 鼠标移出事件
+     *
+     * @param event    事件参数
+     * @return 是否处理该事件
+     */
+    onMouseLeave(event: SMouseEvent): boolean {
+        return true;
+    }
+
+    /**
+     * 鼠标移动事件
+     *
+     * @param event    事件参数
+     * @return 是否处理该事件
+     */
+    onMouseMove(event: SMouseEvent): boolean {
+        if (event.shiftKey) {
+            event = this.compare(event);
+        }
+        if (this.status == SItemStatus.Create) {
+            this.lastPoint = new SPoint();
+            this.lastPoint.x = event.x;
+            this.lastPoint.y = event.y;
+            this.update();
+        } else if (this.status == SItemStatus.Edit) {
+            if (event.buttons == 1) {
+                if (-1 != this.curIndex) {
+                    this.pointList[this.curIndex].x = event.x;
+                    this.pointList[this.curIndex].y = event.y;
+                }
+            }
+            this.update();
+        } else {
+            return super.onMouseMove(event);
+        }
+        return true;
+    }
+
+    /**
+     * shift 垂直水平创建或编辑
+     *
+     * @param event   事件
+     */
+    compare(event: SMouseEvent): SMouseEvent {
+        if (this.pointList.length) {
+            let last = new SPoint(event.x, event.y);
+            if (this.status == SItemStatus.Create) {
+                last = this.pointList[this.pointList.length - 1];
+            } else if (this.status == SItemStatus.Edit) {
+                if (this.curIndex > 0) {
+                    last = this.pointList[this.curIndex - 1];
+                }
+            }
+            const dx = Math.abs(event.x - last.x);
+            const dy = Math.abs(event.y - last.y);
+            if (dy > dx) {
+                event.x = last.x;
+            } else {
+                event.y = last.y;
+            }
+        }
+        return event;
+    }
+
+    /**
+     * 鼠标抬起事件
+     *
+     * @param event    事件参数
+     * @return 是否处理该事件
+     */
+    onMouseUp(event: SMouseEvent): boolean {
+        if (this.status == SItemStatus.Edit) {
+            if (-1 != this.curIndex) {
+                const pos = new SPoint(
+                    this.pointList[this.curIndex].x,
+                    this.pointList[this.curIndex].y
+                );
+                this.recordAction(SGraphPointListUpdate, [
+                    this.pointList,
+                    this.curPoint,
+                    pos,
+                    this.curIndex
+                ]);
+            }
+        } else if (this.status == SItemStatus.Normal) {
+            return super.onMouseUp(event);
+        } else if (this.status == SItemStatus.Create) {
+
+        }
+        return true;
+    }
+
+    /**
+     * 取消操作
+     */
+    cancelOperate(): void {
+        // 当状态为展示状态
+        if (this.status == SItemStatus.Create) {
+            // 闭合多边形
+            this.parent = null;
+        } else if (this.status == SItemStatus.Edit) {
+            // 编辑状态
+            this.status = SItemStatus.Normal;
+        }
+        this.update();
+    }
+
+    /**
+     * Item 对象边界区域
+     *
+     * @return 边界区域
+     */
+    boundingRect(): SRect {
+        if (this.pointList.length) {
+            this.minX = this.pointList[0].x;
+            this.maxX = this.pointList[0].x;
+            this.minY = this.pointList[0].y;
+            this.maxY = this.pointList[0].y;
+            this.pointList.forEach(it => {
+                let x = it.x,
+                    y = it.y;
+                if (x < this.minX) {
+                    this.minX = x;
+                }
+
+                if (y < this.minY) {
+                    this.minY = y;
+                }
+
+                if (x > this.maxX) {
+                    this.maxX = x;
+                }
+
+                if (y > this.maxY) {
+                    this.maxY = y;
+                }
+
+            });
+        }
+
+        return new SRect(
+            this.minX,
+            this.minY,
+            this.maxX - this.minX,
+            this.maxY - this.minY
+        );
+    }
+
+    /**
+     * 判断点是否在区域内
+     *
+     * @param x     x 坐标
+     * @param y     y 坐标
+     * @return 是否在该区域内
+     */
+    contains(x: number, y: number): boolean {
+        let arr = this.pointList;
+        if (arr.length < 3 || !SPolygonUtil.pointIn(x, y, arr)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * 选择器放缩控制大小变化'
+     * 
+     * @param old    旧的大小
+     * @param newS   新的大小
+    */
+    resize(old: SSize, newS: SSize): void {
+        const xs = newS.width / old.width;
+        const ys = newS.height / old.height;
+        this.pointList = this.pointList.map(item => {
+            item.x = item.x * xs;
+            item.y = item.y * ys;
+            return item
+        });
+    }
+
+    /**
+     * Item 绘制操作
+     *
+     * @param painter    绘制对象
+     */
+    onDraw(painter: SPainter): void {
+        this.scenceLen = painter.toPx(this.len);
+        // 当状态为展示状态
+        if (this.status == SItemStatus.Normal) {
+            // 闭合多边形
+            this.drawShowPolygon(painter, this.pointList);
+        } else if (this.status == SItemStatus.Create) {
+            // 创建状态
+            this.drawCreatePolygon(painter, this.pointList);
+        } else {
+            // 编辑状态
+            this.drawEditPolygon(painter, this.pointList);
+        }
+    }
+}

+ 5 - 1
src/utils/graph/FloorScene.ts

@@ -260,7 +260,11 @@ export class FloorScene extends SGraphScene {
     initZoneColor(): void {
         this.zoneList.forEach(
             (t: SZoneItem, i: number) => {
-                t.fillColor = new SColor(zoneColor[i % zoneColor.length]);
+                if (t.selectable) {
+                    t.fillColor = new SColor(zoneColor[i % zoneColor.length]);
+                } else {
+                    t.fillColor = ItemColor.zoneUnselectColor;
+                }
             }
         );
     }

+ 74 - 18
src/utils/graph/ShadeItem.ts

@@ -1,7 +1,7 @@
 import { SMouseEvent } from "@persagy-web/base/lib";
 import { ItemOrder } from "@persagy-web/big/lib";
 import { SMathUtil } from "@persagy-web/big/lib/utils/SMathUtil";
-import { SColor, SLineCapStyle, SPainter, SPoint, SPolygonUtil } from "@persagy-web/draw/lib";
+import { SColor, SLineCapStyle, SPainter, SPoint, SPolygonUtil, SRect } from "@persagy-web/draw/lib";
 import { SGraphItem, SGraphStyleItem } from "@persagy-web/graph/lib";
 
 /**
@@ -10,8 +10,16 @@ import { SGraphItem, SGraphStyleItem } from "@persagy-web/graph/lib";
  * @author  郝建龙
  */
 export class ShadeItem extends SGraphStyleItem {
+    /** X 坐标最小值 */
+    private minX = Number.MAX_SAFE_INTEGER;
+    /** X 坐标最大值 */
+    private maxX = Number.MIN_SAFE_INTEGER;
+    /** Y 坐标最小值 */
+    private minY = Number.MAX_SAFE_INTEGER;
+    /** Y 坐标最大值 */
+    private maxY = Number.MIN_SAFE_INTEGER;
     /** 轮廓线坐标  */
-    outLine: SPoint[] = [];
+    pointList: SPoint[] = [];
     /** 是否闭合    */
     closeFlag = false;
     /** 鼠标移动点  */
@@ -42,10 +50,10 @@ export class ShadeItem extends SGraphStyleItem {
     constructor(parent: SGraphItem | null, data: SPoint[] | SPoint) {
         super(parent);
         if (data instanceof Array) {
-            this.outLine = data;
+            this.pointList = data;
             this.createMask();
         } else {
-            this.outLine.push(data);
+            this.pointList.push(data);
             this.lastPoint = data;
         }
         this.zOrder = ItemOrder.shadeOrder;
@@ -61,9 +69,9 @@ export class ShadeItem extends SGraphStyleItem {
     onMouseDown(event: SMouseEvent): boolean {
         if (!this.closeFlag && event.buttons == 1) {
             if (
-                this.lastPoint.x == this.outLine[0].x &&
-                this.lastPoint.y == this.outLine[0].y &&
-                this.outLine.length >= 3
+                this.lastPoint.x == this.pointList[0].x &&
+                this.lastPoint.y == this.pointList[0].y &&
+                this.pointList.length >= 3
             ) {
                 this.createMask();
                 return true;
@@ -71,7 +79,7 @@ export class ShadeItem extends SGraphStyleItem {
             let p = new SPoint(event.x, event.y);
             this.lastPoint.x = p.x;
             this.lastPoint.y = p.y;
-            this.outLine.push(p);
+            this.pointList.push(p);
         }
         this.update();
         return true;
@@ -86,18 +94,18 @@ export class ShadeItem extends SGraphStyleItem {
     onMouseMove(event: SMouseEvent): boolean {
         if (!this.closeFlag) {
             this.lastPoint = new SPoint(event.x, event.y);
-            if (this.outLine.length >= 3) {
+            if (this.pointList.length >= 3) {
                 let le = SMathUtil.pointDistance(
                     this.lastPoint.x,
                     this.lastPoint.y,
-                    this.outLine[0].x,
-                    this.outLine[0].y
+                    this.pointList[0].x,
+                    this.pointList[0].y
                 );
                 // @ts-ignore
                 let scale = this.parent.scene.view.scale;
                 if (le * scale < 30) {
-                    this.lastPoint.x = this.outLine[0].x;
-                    this.lastPoint.y = this.outLine[0].y;
+                    this.lastPoint.x = this.pointList[0].x;
+                    this.lastPoint.y = this.pointList[0].y;
                 }
             }
         }
@@ -121,7 +129,7 @@ export class ShadeItem extends SGraphStyleItem {
      * @param	event         事件参数
      */
     onKeyUp(event: KeyboardEvent): void {
-        if (event.keyCode == 13 && this.outLine.length >= 3) {
+        if (event.keyCode == 13 && this.pointList.length >= 3) {
             this.createMask();
         }
     } // Function onKeyUp()
@@ -133,18 +141,66 @@ export class ShadeItem extends SGraphStyleItem {
     createMask(): void {
         this.closeFlag = true;
         this.releaseItem();
+        this.calRect();
         this.$emit('createSuc')
         this.update();
     } // Function createMask()
 
     /**
+     * 计算最大最小值
+    */
+    calRect() {
+        // 点集存在
+        if (this.pointList.length) {
+            this.minX = this.pointList[0].x;
+            this.maxX = this.pointList[0].x;
+            this.minY = this.pointList[0].y;
+            this.maxY = this.pointList[0].y;
+            // 遍历点集并计算最大最小值
+            this.pointList.forEach((it): void => {
+                let x = it.x,
+                    y = it.y;
+                if (x < this.minX) {
+                    this.minX = x;
+                }
+
+                if (y < this.minY) {
+                    this.minY = y;
+                }
+
+                if (x > this.maxX) {
+                    this.maxX = x;
+                }
+
+                if (y > this.maxY) {
+                    this.maxY = y;
+                }
+            });
+        }
+    }
+
+    /**
+     * Item 对象边界区域
+     *
+     * @return 边界区域
+     */
+    boundingRect(): SRect {
+        return new SRect(
+            this.minX,
+            this.minY,
+            this.maxX - this.minX,
+            this.maxY - this.minY
+        );
+    }
+
+    /**
      * 判断点是否在区域内
      *
      * @param x
      * @param y
      */
     contains(x: number, y: number): boolean {
-        let arr = this.outLine;
+        let arr = this.pointList;
         return SPolygonUtil.pointIn(x, y, arr);
     } // Function contains()
 
@@ -158,13 +214,13 @@ export class ShadeItem extends SGraphStyleItem {
         if (this.closeFlag) {
             painter.pen.color = SColor.Transparent;
             painter.brush.color = this.fillColor;
-            painter.drawPolygon(this.outLine);
+            painter.drawPolygon(this.pointList);
         } else {
             painter.pen.color = new SColor("#ff0000");
             painter.pen.lineWidth = painter.toPx(3);
-            painter.drawPolyline(this.outLine);
+            painter.drawPolyline(this.pointList);
             painter.drawLine(
-                this.outLine[this.outLine.length - 1],
+                this.pointList[this.pointList.length - 1],
                 this.lastPoint
             );
         }

+ 39 - 1
src/utils/maintain.ts

@@ -80,8 +80,46 @@ export const tools = {
             }
         }
         return newData
-    }
+    },
 
+    /**
+     * 解析模型文件名称信息
+     * @param name 模型文件名称
+     * @returns 模型文件名包含的楼层信息
+     */
+    getMoldeFileInfo: (name: string) => {
+        const regList = name.match(/(-[FB]\d+M?[.-])|(-RF[.-])/g);
+        const floorInfo: any = {}
+        if (regList && regList.length === 1) {
+            const floorName = regList[0].slice(1, -1);
+            floorInfo.floorName = floorName;
+            if (floorName === 'RF') { //顶层
+                floorInfo.floorSequenceId = 9999;
+                return floorInfo;
+            } else { //非顶层
+                const strList = floorName.split("");
+                if (strList[0] && strList[0] === 'F') { //地上
+                    if (strList[strList.length - 1] === 'M') { //有夹层
+                        floorInfo.floorSequenceId = Number(floorName.slice(1, -1)) * 10 + 5;
+                    } else { //无夹层
+                        floorInfo.floorSequenceId = Number(floorName.slice(1)) * 10;
+                    }
+                    return floorInfo;
+                } else if (strList[0] && strList[0] === 'B') { //地下
+                    if (strList[strList.length - 1] === 'M') { //有夹层
+                        floorInfo.floorSequenceId = -(Number(floorName.slice(1, -1)) * 10 + 5);
+                    } else { //无夹层
+                        floorInfo.floorSequenceId = -(Number(floorName.slice(1)) * 10);
+                    }
+                    return floorInfo;
+                } else { //其他
+                    return false;
+                }
+            }
+        } else {
+            return false;
+        }
+    }
 
 }
 export default tools

+ 110 - 27
src/views/maintain/space/components/spaceGraph.vue

@@ -122,7 +122,7 @@ export default class spaceGraph extends Vue {
     mounted(): void {
         this.canvasWidth = this.$refs.graphContainer.offsetWidth;
         this.canvasHeight = this.$refs.graphContainer.offsetHeight;
-        this.getGraph();
+        // this.getGraph();
     }
     // 父组件调用查询楼层底图
     getData(floor: any, zoneType: any) {
@@ -189,6 +189,7 @@ export default class spaceGraph extends Vue {
         this.canvasLoading = true;
         this.clearGraphy();
         this.scene = null;
+        console.log(this.floorKey);
         scene.loadUrl(this.floorKey).then((res) => {
             if (this.view) {
                 this.view.scene = scene;
@@ -258,8 +259,11 @@ export default class spaceGraph extends Vue {
         this.config.isEdit = true;
         this.config.groupSelect = false;
         this.config.divide = true;
-        this.scene!.isSpaceSelectable = true;
-        this.scene!.isZoneSelectable = false;
+        if (this.scene) {
+            this.scene.isSpaceSelectable = true;
+            this.scene.isZoneSelectable = false;
+            this.scene.selectContainer.clear()
+        }
         this.view?.update();
     }
     // 创建新的业务空间
@@ -278,8 +282,14 @@ export default class spaceGraph extends Vue {
     handleCommand() {}
     // 编辑业务空间
     refactorBSP() {
-        this.scene!.isZoneSelectable = false;
-        this.scene!.isSpaceSelectable = true;
+        this.config.isEdit = true;
+        this.config.groupSelect = false;
+        this.config.divide = true;
+        if (this.scene) {
+            this.scene.isZoneSelectable = false;
+            this.scene.isSpaceSelectable = true;
+            this.scene.selectContainer.clear();
+        }
         this.type = 4;
         this.curZoneItem.visible = false;
     }
@@ -347,27 +357,15 @@ export default class spaceGraph extends Vue {
     }
     // 重新划分业务空间保存
     saveRefactorBSP() {
-        const arr = this.scene?.selectContainer.itemList;
-        const zoneObj = {
+        let zoneObj = {
             id: this.curZoneItem.data.RoomID,
             classCode: this.curZoneType,
             outline: [],
         };
-        if (arr.length) {
-            arr?.forEach((t) => {
-                if (t instanceof SSpaceItem) {
-                    zoneObj.outline.push(t.data.OutLine);
-                }
-            });
+        if (this.scene) {
+            zoneObj = this.calIntersect(zoneObj);
+            this.handleUpdateZone(zoneObj);
         }
-        const pa = {
-            content: [zoneObj],
-        };
-        this.canvasLoading = true;
-        updateZone(pa).then((res) => {
-            this.$message.success("更新成功");
-            this.init(2);
-        });
     }
 
     groupCreateZone() {}
@@ -405,20 +403,86 @@ export default class spaceGraph extends Vue {
 
     // 根据图创建新的业务空间-弹窗返回确认创建
     createRoom(val) {
-        const zoneObj = {
+        let zoneObj = {
             outline: [],
             localName: val,
             buildingId: this.floor.buildingId,
             floorId: this.floor.id,
             classCode: this.curZoneType,
         };
-        let arr = this.scene?.selectContainer.itemList;
-        arr?.forEach((t) => {
-            zoneObj.outline.push(t.data.OutLine);
-        });
+        if (this.scene) {
+            zoneObj = this.calIntersect(zoneObj);
+            this.handleCreateZone(zoneObj);
+        }
+    }
+
+    /**
+     * 单个计算交集
+     */
+    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;
+    }
+
+    /**
+     * 创建业务空间接口
+     */
+    handleCreateZone(zoneObj: any) {
         const pa = {
             content: [zoneObj],
         };
+        if (Array.isArray(zoneObj)) {
+            pa.content = zoneObj;
+        }
         this.canvasLoading = true;
         createZone(pa).then((res) => {
             this.$message.success("创建成功");
@@ -426,6 +490,23 @@ export default class spaceGraph extends Vue {
         });
     }
 
+    /**
+     * 更新业务空间接口
+     */
+    handleUpdateZone(zoneObj: any) {
+        const pa = {
+            content: [zoneObj],
+        };
+        if (Array.isArray(zoneObj)) {
+            pa.content = zoneObj;
+        }
+        this.canvasLoading = true;
+        updateZone(pa).then((res) => {
+            this.$message.success("更新成功");
+            this.init(2);
+        });
+    }
+
     // 适配底图到窗口
     fit() {
         this.view?.fitSceneToView();
@@ -444,7 +525,9 @@ export default class spaceGraph extends Vue {
     }
     // 切割划分
     divide() {
-        this.scene.isCutting = true;
+        if (this.scene) {
+            this.scene.drawCmd = 'cut';
+        }
     }
     // 清除切割划分
     clearDivide() {

+ 101 - 53
src/views/manage/build/components/AddFloorDialog/index.vue

@@ -22,22 +22,19 @@
                     <el-select v-model="form.revitVersion" placeholder="请选择">
                         <el-option v-for="item in revitVersionList" :key="`revit-${item.value}`" :label="item.label" :value="item.value"></el-option>
                     </el-select>
-                </el-form-item> -->
+                </el-form-item>
                 <el-form-item label="模型所属楼层:">
                     <div class="floorModle">
                         <el-select v-model="form.floorTypeVal" placeholder="请选择">
                             <el-option v-for="item in floorType" :key="item.value" :label="item.label" :value="item.value"></el-option>
                         </el-select>
-                        <!-- 计数 -->
                         <el-input-number
                             style="margin-left: 10px"
                             v-model="form.floorNum"
                             :min="1"
                             :disabled="form.floorTypeVal === 'RF'"
                         ></el-input-number>
-                        <!-- 是否夹层 -->
                         <el-checkbox style="margin: 0 10px" v-model="form.haveInterlayer">是否夹层</el-checkbox>
-                        <!-- 夹层选择 -->
                         <el-select v-model="form.interlayerTypeVal" :disabled="!form.haveInterlayer" placeholder="请选择">
                             <el-option v-for="item in interlayerType" :key="item.value" :label="item.label" :value="item.value"></el-option>
                         </el-select>
@@ -48,7 +45,7 @@
                         :controls="false"
                         v-model="form.floorSequenceID"
                     ></el-input-number>
-                </el-form-item>
+                </el-form-item> -->
                 <el-form-item label="备注信息:">
                     <el-input type="textarea" v-model="form.desc"></el-input>
                 </el-form-item>
@@ -66,6 +63,7 @@ import { Vue, Component, Prop, Emit, Ref, Watch } from "vue-property-decorator";
 import { UserModule } from "@/store/modules/user";
 import { modelFileUpload } from "@/api/modelapi";
 import { ElUpload } from "element-ui/types/upload";
+import tools from "@/utils/maintain";
 
 @Component({
     name: "AddFloorDialog",
@@ -167,61 +165,111 @@ export default class extends Vue {
      * 提交表单创建楼层并发出上传指令
      */
     private async onSubmit() {
+        // if (this.form.file == null) {
+        //     this.$message.error("模型文件不能为空!");
+        // } else if (!this.form.revitVersion) {
+        //     this.$message.error("revit版本不能为空!");
+        // } else if (this.form.floorSequenceID === undefined || this.form.floorSequenceID === null) {
+        //     this.$message.error("楼层顺序码不能为空!");
+        // } else {
+        //     let FloorName: string | null = null;
+        //     // 根据是否有夹层拼接楼层名
+        //     if (this.form.haveInterlayer) {
+        //         if (this.form.floorTypeVal === "RF") {
+        //             FloorName = this.form.floorTypeVal + this.form.interlayerTypeVal;
+        //         } else {
+        //             FloorName = this.form.floorTypeVal + this.form.floorNum + this.form.interlayerTypeVal;
+        //         }
+        //     } else {
+        //         if (this.form.floorTypeVal === "RF") {
+        //             FloorName = this.form.floorTypeVal;
+        //         } else {
+        //             FloorName = this.form.floorTypeVal + this.form.floorNum;
+        //         }
+        //     }
+        //     let FloorObj = this.floorList.find((item) => {
+        //         return item.FloorName == FloorName;
+        //     });
+        //     if (FloorObj && FloorObj.Status !== 0) {
+        //         this.$message.error("该楼层名称已存在,请勿重复创建!");
+        //     } else {
+        //         let data = {
+        //             FileName: this.form.file.name,
+        //             FloorName: FloorName,
+        //             LocalName: FloorName,
+        //             LocalId: FloorName,
+        //             FloorSequenceId: this.form.floorSequenceID,
+        //             FolderId: this.FolderId,
+        //             RevitVersion: this.form.revitVersion,
+        //             Note: this.form.desc,
+        //             ProjectId: this.projectId,
+        //             ReplaceReason: null,
+        //             Size: this.form.file.size,
+        //             UserName: this.username,
+        //             UserId: this.userId,
+        //         };
+        //         const res = await modelFileUpload(data);
+        //         //  创建成功
+        //         if (res.Result === "success" && res.ModelId && res.UploadId) {
+        //             this.$emit("uploadModelFile", {
+        //                 modelId: res.ModelId,
+        //                 uploadId: res.UploadId,
+        //                 file: this.form.file,
+        //             });
+        //             this.handleClose();
+        //         } else {
+        //             this.$message.info(`准备分片上传模型文件接口失败!失败原因:${res.Message}`);
+        //         }
+        //     }
+        // }
+
+        /**
+         * TODO:通过解析文件名称获取楼层信息上传
+         */
         if (this.form.file == null) {
             this.$message.error("模型文件不能为空!");
         } else if (!this.form.revitVersion) {
             this.$message.error("revit版本不能为空!");
-        } else if (this.form.floorSequenceID === undefined || this.form.floorSequenceID === null) {
-            this.$message.error("楼层顺序码不能为空!");
         } else {
-            let FloorName: string | null = null;
-            // 根据是否有夹层拼接楼层名
-            if (this.form.haveInterlayer) {
-                if (this.form.floorTypeVal === "RF") {
-                    FloorName = this.form.floorTypeVal + this.form.interlayerTypeVal;
-                } else {
-                    FloorName = this.form.floorTypeVal + this.form.floorNum + this.form.interlayerTypeVal;
-                }
-            } else {
-                if (this.form.floorTypeVal === "RF") {
-                    FloorName = this.form.floorTypeVal;
-                } else {
-                    FloorName = this.form.floorTypeVal + this.form.floorNum;
-                }
-            }
-            let FloorObj = this.floorList.find((item) => {
-                return item.FloorName == FloorName;
-            });
-            if (FloorObj && FloorObj.Status !== 0) {
-                this.$message.error("该楼层名称已存在,请勿重复创建!");
-            } else {
-                let data = {
-                    FileName: this.form.file.name,
-                    FloorName: FloorName,
-                    LocalName: FloorName,
-                    LocalId: FloorName,
-                    FloorSequenceId: this.form.floorSequenceID,
-                    FolderId: this.FolderId,
-                    RevitVersion: this.form.revitVersion,
-                    Note: this.form.desc,
-                    ProjectId: this.projectId,
-                    ReplaceReason: null,
-                    Size: this.form.file.size,
-                    UserName: this.username,
-                    UserId: this.userId,
-                };
-                const res = await modelFileUpload(data);
-                //  创建成功
-                if (res.Result === "success" && res.ModelId && res.UploadId) {
-                    this.$emit("uploadModelFile", {
-                        modelId: res.ModelId,
-                        uploadId: res.UploadId,
-                        file: this.form.file,
-                    });
-                    this.handleClose();
+            const fileNameInfo = tools.getMoldeFileInfo(this.form.file.name);
+            if (fileNameInfo) { //模型文件名解析成功
+                const {floorName, floorSequenceId} = fileNameInfo;
+                let floorObj = this.floorList.find((item) => {
+                    return item.FloorName == floorName;
+                });
+                if (floorObj && floorObj.Status !== 0) {
+                    this.$message.error("该楼层名称已存在,请勿重复创建!");
                 } else {
-                    this.$message.info(`准备分片上传模型文件接口失败!失败原因:${res.Message}`);
+                    let data = {
+                        FileName: this.form.file.name,
+                        FloorName: floorName,
+                        LocalName: floorName,
+                        LocalId: floorName,
+                        FloorSequenceId: floorSequenceId,
+                        FolderId: this.FolderId,
+                        RevitVersion: this.form.revitVersion,
+                        Note: this.form.desc,
+                        ProjectId: this.projectId,
+                        ReplaceReason: null,
+                        Size: this.form.file.size,
+                        UserName: this.username,
+                        UserId: this.userId,
+                    };
+                    const res = await modelFileUpload(data);
+                    //  创建成功
+                    if (res.Result === "success" && res.ModelId && res.UploadId) {
+                        this.$emit("uploadModelFile", {
+                            modelId: res.ModelId,
+                            uploadId: res.UploadId,
+                            file: this.form.file,
+                        });
+                        this.handleClose();
+                    } else {
+                        this.$message.info(`准备分片上传模型文件接口失败!失败原因:${res.Message}`);
+                    }
                 }
+            } else { //模型文件名解析失败
+                this.$message.error("模型文件命名错误,请检查!");
             }
         }
     }

+ 33 - 22
src/views/manage/build/components/RepliceModel/index.vue

@@ -42,6 +42,7 @@ import { Vue, Component, Prop, Emit, Watch } from "vue-property-decorator";
 import { AppModule } from "@/store/modules/app";
 import { UserModule } from "@/store/modules/user";
 import { modelFileUpload } from "@/api/modelapi";
+import tools from "@/utils/maintain";
 
 @Component({
     name: "RepliceModel",
@@ -108,28 +109,38 @@ export default class extends Vue {
         } else if (!this.form.revitVersion) {
             this.$message.error("revit版本不能为空!");
         } else {
-            let data = {
-                FileName: this.form.file.name,
-                FloorName: this.replaceModelItem.FloorName,
-                FolderId: this.replaceModelItem.FolderId,
-                RevitVersion: this.form.revitVersion,
-                Note: this.form.Note,
-                ProjectId: this.projectId,
-                ReplaceReason: 0,
-                Size: this.form.file.size,
-                UserName: this.username,
-                UserId: this.userId,
-            };
-            const res = await modelFileUpload(data);
-            if (res.Result === "success" && res.UploadId && res.ModelId) {
-                this.$emit("uploadModelFile", {
-                    modelId: res.ModelId,
-                    uploadId: res.UploadId,
-                    file: this.form.file,
-                });
-                this.handleClose();
-            } else {
-                this.$message.info(`准备分片上传模型文件接口失败!失败原因:${res.Message}`);
+            const fileNameInfo = tools.getMoldeFileInfo(this.form.file.name);
+            if (fileNameInfo) { //模型文件名解析成功
+                const {floorName} = fileNameInfo;
+                if (floorName === this.replaceModelItem.FloorName) { //模型楼层信息正确
+                    let data = {
+                        FileName: this.form.file.name,
+                        FloorName: this.replaceModelItem.FloorName,
+                        FolderId: this.replaceModelItem.FolderId,
+                        RevitVersion: this.form.revitVersion,
+                        Note: this.form.Note,
+                        ProjectId: this.projectId,
+                        ReplaceReason: 0,
+                        Size: this.form.file.size,
+                        UserName: this.username,
+                        UserId: this.userId,
+                    };
+                    const res = await modelFileUpload(data);
+                    if (res.Result === "success" && res.UploadId && res.ModelId) {
+                        this.$emit("uploadModelFile", {
+                            modelId: res.ModelId,
+                            uploadId: res.UploadId,
+                            file: this.form.file,
+                        });
+                        this.handleClose();
+                    } else {
+                        this.$message.info(`准备分片上传模型文件接口失败!失败原因:${res.Message}`);
+                    }
+                } else {
+                    this.$message.error("模型文件楼层信息有误,请检查后再上传!");
+                }
+            } else { //模型文件名解析失败
+                this.$message.error("模型文件命名错误,请检查后再上传!");
             }
         }
     }