cuiqian2004
2025-09-25 9efd4a80aae58cf36266e774d3c820cc8e115028
test
13个文件已修改
1181 ■■■■■ 已修改文件
App.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/request.js 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
api/vehicle.js 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manifest.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/index/index.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/login/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/map/index.vue 106 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/map/infos/scene-create.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/map/js/ctx.js 606 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/map/scene.vue 259 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/map/task.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/my/help-feedback.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/my/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
App.vue
@@ -15,7 +15,8 @@
                min_y: 0,
                img_x: 1,
                img_y: 1,
            }
            },
            withLog:false
        },
        onLaunch: function() {
            console.log('App Launch')
api/request.js
@@ -11,24 +11,71 @@
        dataType: "json",
        
    },
    apiCount: {
        agv_state: 0,
        laser_data: 0,
    },
    addLog(item) {
        const list = session.getValue("request_log") || []
        if (!getApp().globalData.withLog) {
            return
        }
        if (item.statusCode == 200) {
            const ret = JSON.parse(item.data)
            if (ret.code == 0) {
                if (item.url.indexOf("get_agv_state") > 0) {
        const res = typeof item.data == 'string' ? item.data : JSON.stringify(item.data)
        if (res.length > 64 * 1024) {
                    if (this.apiCount.agv_state % 20 != 0) {
                        this.apiCount.agv_state++;
                        return
                    }
                    this.apiCount.agv_state = 1;
                }
                if (item.url.indexOf("laser_data") > 0) {
                    if (ret.data?.base_map?.image_base64) {
                        this.apiCount.laser_data++;
                    } else {
                        if (this.apiCount.laser_data % 20 != 0) {
                            this.apiCount.laser_data++;
                            return
                        }
                        this.apiCount.laser_data = 1;
                    }
                }
                const res = ret.data
                if (res) {
                    if (item.url.indexOf("getMapUrl") > 0) {
                        if (res.filedata) {
                            res.data_length = res.filedata.length
                            res.filedata = "..."
                            item.data = JSON.stringify(ret)
                        }
                    } else if (item.url.indexOf("laser_data") > 0) {
                        if (res?.base_map?.image_base64) {
                            res.base_map.image_length = res.base_map.image_base64.length
                            res.base_map.image_base64 = "..."
                            item.data = JSON.stringify(ret)
                        }
                    }
                    if (JSON.stringify(res).length > 100 * 1024) {
            // const maxData = session.getValue("request_log_max_data") || {}
            // const key = `data${new Date().getTime()}`
            // maxData[key] = item.data
            // item.data_key = key
            // delete item.data
            // session.setValue("request_log_max_data", maxData)
             item.data  = res.length
                        ret.data = "..."
                        ret.data_length = JSON.stringify(res).length
                        item.data = JSON.stringify(ret)
        }
        if(item.url.indexOf("get_agv_state") > 0)
        {
            return
        }
            }
        }
        const list = session.getValue("request_log") || []
        list.unshift(item)
        if (list.length > 512) {
            const oldItem = list.pop()
            if (oldItem.data_key) {
@@ -48,8 +95,8 @@
        options.method = options.method || this.common.method;
        options.dataType = options.dataType || this.common.dataType;
        
        if(options.url.indexOf("get_agv_state") < 0 && options.url.indexOf("laser_data") < 0)
        {
        if (options.url.indexOf("get_agv_state") < 0 && options.url.indexOf("laser_data") < 0 && options.url.indexOf(
                "taskGroupStatus") < 0) {
            console.log("url", options.url, options.data)
        }
        return new Promise((resolve, reject) => {
@@ -61,8 +108,8 @@
                method: options.method,
                dataType: options.dataType,
                success: (result) => {
                    if(options.url.indexOf("get_agv_state") < 0 && options.url.indexOf("laser_data") < 0)
                    {
                    if (options.url.indexOf("get_agv_state") < 0 && options.url.indexOf(
                            "laser_data") < 0) { //
                        console.log("result", result)
                    }
                    
@@ -87,14 +134,7 @@
                            msg: "访问失败,状态码:" + result.statusCode
                        })
                    }
                    this.addLog({
                        date,
                        method: `${options.method || ""}`,
                        url: options.url,
                        param: options.data,
                        statusCode: result.statusCode,
                        data: result.data
                    })
                    var ret = result.data
                    if (typeof ret == 'string') {
                        try {
@@ -116,6 +156,14 @@
                            })
                        }
                    }
                    this.addLog({
                        date,
                        method: `${options.method || ""}`,
                        url: options.url,
                        param: options.data,
                        statusCode: result.statusCode,
                        data: JSON.stringify(ret)
                    })
                    if (ret.code == 0) {
                        resolve(ret.data);
api/vehicle.js
@@ -894,3 +894,84 @@
    })
}
/**
 * GET 5000/api/check_mapserver_is_start
 * 判断构图程序是否启动
 * @param
 * @returns
 */
export const checkMapServerIsStart = (ip) => {
    var header = {
        "Content-Type": "application/json;charset=UTF-8"
    };
    var url = `http://${ip}:5000/api/check_mapserver_is_start/`;
    return http.request({
        method: "GET",
        url,
        header,
    })
}
/**
 * POST 5000/api/start_or_stop_mapserver
 * 开启或者关闭构图程序: 1开启2关闭
 * @param  status 1开启2关闭
 * @returns
 */
export const startOrStopMapServer = (ip, status) => {
    var header = {
        "Content-Type": "application/json;charset=UTF-8"
    };
    var url = `http://${ip}:5000/api/start_or_stop_mapserver/`;
    return http.request({
        method: "POST",
        url,
        header,
        data: {status}
    })
}
 /**
  * GET 5000/api/check_mapserver_is_ok
  * 构图程序是否准备到位
  * @param
  * @returns
  */
 export const checkMapServerIsOk = (ip) => {
     var header = {
         "Content-Type": "application/json;charset=UTF-8"
     };
     var url = `http://${ip}:5000/api/check_mapserver_is_ok/`;
     return http.request({
         method: "GET",
         url,
         header,
     })
 }
 /**
  * GET 5000/api/check_save_map_is_ok
  * 结束构图是否保存完成
  * @param
  * @returns
  */
 export const checkSaveMapIsOk = (ip) => {
     var header = {
         "Content-Type": "application/json;charset=UTF-8"
     };
     var url = `http://${ip}:5000/api/check_save_map_is_ok/`;
     return http.request({
         method: "GET",
         url,
         header,
     })
 }
manifest.json
@@ -2,8 +2,8 @@
    "name" : "ES-GO",
    "appid" : "__UNI__C988375",
    "description" : "",
    "versionName" : "1.2.9",
    "versionCode" : 129,
    "versionName" : "1.3.2",
    "versionCode" : 132,
    "transformPx" : false,
    /* 5+App特有相关 */
    "app-plus" : {
pages/index/index.vue
@@ -877,6 +877,8 @@
            margin-top: 150rpx;
            margin-left: calc(750rpx - 330rpx);
            width: 320rpx;
            max-height: 50vh;
            overflow: auto;
            align-items: center;
            justify-content: center;
            flex-direction: column;
pages/login/index.vue
@@ -188,7 +188,7 @@
                        password: ""
                    })
                }
                getApp().globalData.withLog  =     session.getValue("write_log") ? true:false
                uni.reLaunch({
                    url: "/pages/index/index"
                })
pages/map/index.vue
@@ -33,7 +33,9 @@
                v-model:opSceneType="opSceneType" @create-ok="onCreateSceneOk"></SceneCreateInfo> -->
            <view class="map-content" v-show="mapOperationType !='scene_create'">
                <view class="content">
                    <view class="fabric" :message="ctxDataStr" :change:message="ctx.receiveMsg" id="canvasMap"></view>
                    <view ref="canvasCtx" class="fabric" id="canvasMap" :message="ctxDataStr"
                        :change:message="ctx.receiveMsg">
                    </view>
                    <view class="loading-overlay" v-if="bgLoading">
                        <view class="loading-content">
                            <view class="loading-spinner"></view>
@@ -386,9 +388,10 @@
    </view>
</template>
<script src="./js/ctx.js" module="ctx" lang="renderjs"></script>
<script>
    import {
        ref
    } from "vue";
    import {
        showToast,
        showModal,
@@ -440,6 +443,7 @@
                    list: []
                },
                sceneList: [],
                ctxDataStr: "[]",
                mapOperationType: "",
                mapOperationStatus: "",
@@ -482,7 +486,9 @@
                    img_x: 1,
                    img_y: 1
                },
                positioningAgv: false
                positioningAgv: false,
                isPageVisible: true,
                destroyFlag: false,
            }
        },
        computed: {
@@ -539,10 +545,29 @@
        },
        onHide() {
            this.isPageVisible = false
        },
        onUnload() {
        async onUnload() {
            this.isPageVisible = false
            console.log("onUnload")
        },
        onBackPress() {
                this.isPageVisible = false
            if (this.destroyFlag)
                return false
            else {
                this.ctxDataStr = JSON.stringify([{
                    method: "destroy",
                }])
                return true
            }
        },
        methods: {
            setData(obj) {
                let that = this;
@@ -583,6 +608,10 @@
            },
            clickShowMenu() {
                // const list = [...this.sceneList]
                // for(let i =0; i < 20;i++){
                //     list.push("test" + i)
                // }
                this.menuPopup = {
                    type: "scene",
                    list: this.sceneList,
@@ -786,7 +815,7 @@
                        // this.mapOperationType = 'scene_create'
                        // this.opSceneType = 'add_name'
                        uni.navigateTo({
                            url: `/pages/map/scene?ip=${this.vehicleIp}`,
                            url: `/pages/map/scene?ip=${_this.vehicleIp}`,
                            events: {
                                // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
                                create_finish: function(data) {
@@ -910,12 +939,18 @@
                        },
                        {
                            method: "public_teaching_path",
                            param: this.teachingMode.Public || []
                            param: {
                                list: this.teachingMode.Public || [],
                                show: this.showTeachingPathFlag
                            }
                        },
                        {
                            method: "station_teaching_path",
                            param: this.teachingMode.Stations || []
                            param: {
                                list: this.teachingMode.Stations || [],
                                show: this.showTeachingPathFlag
                            }
                        },
                        {
@@ -939,7 +974,14 @@
            receiveRenderData(param) {
                console.log('接收到视图层的数据:', param);
                if (param.method == "set_backgroud_progress") {
                if (param.method === "destroy_complete") {
                    if (param.param) {
                        this.destroyFlag = true
                        uni.navigateBack({
                            delta: 1
                        })
                    }
                } else if (param.method == "set_backgroud_progress") {
                    if (param.type == "start") {
                        this.setData({
                            bgProgressPercent: 50,
@@ -1129,6 +1171,7 @@
                this.mapOperationType = "edit_map"
            },
            clickExtendMap() {
                const _this = this
                uni.navigateTo({
                    url: `/pages/map/scene?ip=${this.vehicleIp}&opType=extend&sceneId=${this.sceneId}`,
                    events: {
@@ -1170,6 +1213,7 @@
            },
            async loadSceneList() {
                try {
                    uni.showLoading({
                        title: "加载场景中"
                    })
@@ -1846,26 +1890,40 @@
                    }
                }
            },
            async reloadTeachingMode() {
            async reloadTeachingMode(finish) {
                try {
                    this.teachingMode = await this.loadTeachingMode()
                    this.ctxDataStr = JSON.stringify([{
                    const list = [{
                            method: "clear_teaching_path",
                        },
                        {
                            method: "public_teaching_path",
                            param: this.teachingMode.Public || []
                            param: {
                                list: this.teachingMode.Public || [],
                                show: this.showTeachingPathFlag
                            }
                        },
                        {
                            method: "station_teaching_path",
                            param: this.teachingMode.Stations || []
                        }, {
                            method: "show_teaching_path",
                            param: {
                                list: this.teachingMode.Stations || [],
                                show: this.showTeachingPathFlag
                            }
                        }
                    ])
                        // , {
                        //     method: "show_teaching_path",
                        //     param: {
                        //         show: this.showTeachingPathFlag
                        //     }
                        // }
                    ]
                    if (finish) {
                        list.push({
                            method: "teaching_finish",
                        })
                    }
                    this.ctxDataStr = JSON.stringify(list)
                } catch (ex) {
                    showError(ex)
@@ -2049,10 +2107,8 @@
            },
            clickTeachingFinish() {
                this.mapOperationType = ""
                this.ctxDataStr = JSON.stringify([{
                    method: "teaching_finish",
                }])
                this.reloadTeachingMode()
                this.reloadTeachingMode(true)
            },
            async teachingStart(mode) {
@@ -2163,11 +2219,13 @@
                            const publicList = data.Public || []
                            const curIndex = publicList.findIndex((a)=>a.name == oldName)
                            
                            if(curIndex > -1)
                            {
                        if (curIndex > -1) {
                                this.ctxDataStr = JSON.stringify([{
                                    method: "public_teaching_path",
                                    param: [publicList[curIndex]]
                                param: {
                                    list: [publicList[curIndex]],
                                    show: true
                                }
                                } ])
                                
                            }
@@ -2705,6 +2763,8 @@
            margin-top: 140rpx;
            margin-left: 225rpx;
            width: 300rpx;
            max-height: 50vh;
            overflow: auto;
            align-items: center;
            justify-content: center;
            flex-direction: column;
pages/map/infos/scene-create.vue
@@ -102,6 +102,7 @@
        computed: {
        },
        mounted() {
            const _this = this
            uni.getSystemInfo({
pages/map/js/ctx.js
@@ -31,7 +31,6 @@
export default {
    data() {
        return {
            vehicleIp: "",
            canvasId: "",
            canvas: null,
            eleWidth: 0,
@@ -64,16 +63,17 @@
                img_y: 1
            },
            pressObjTimer: 0,
            selectable: true,
        }
    },
    mounted() {
        console.log("ctx mounted")
        this.init()
    },
    methods: {
        async init(ip) {
            try {
                this.agvObj = null
                const _this = this
                fabric.Object.prototype.setControlsVisibility({
                    mt: false, // 中间上
@@ -107,6 +107,7 @@
                canvas.setAttribute("id", this.canvasId)
                canvas.setAttribute("type", "2d")
                cantainerEl.appendChild(canvas)
                this.canvas = new fabric.Canvas(this.canvasId, {
                    allowTouchScrolling: true, // 允许触摸滚动
                    selection: true,
@@ -120,6 +121,8 @@
                    renderOnAddRemove: false,
                    imageSmoothingEnabled: true
                })
                this.canvas.clear()
                this.eleWidth = cantainerEl.clientWidth
                this.eleHeight = cantainerEl.clientHeight
@@ -144,6 +147,28 @@
            } catch (ex) {
                this.showError(ex)
            }
        },
        destroyCanvas() {
            console.log("destroyCanvas")
            if (this.canvas) {
                // 2. 移除所有事件监听器
                this.removeAllEventListeners();
                // 3. 清空所有对象(分批处理避免阻塞)
                this.clearObjects();
                // 4. 销毁Fabric.js实例
                this.canvas.dispose();
                // 6. 清除所有变量引用
                this.cleanupReferences();
                this.canvas = null
                // 通知Vue层销毁完成
                this.$ownerInstance.callMethod('receiveRenderData', {
                    method: "destroy_complete",
                    param: true
                });
            }
        },
        patchFabricForUniApp(canvas) {
@@ -425,10 +450,61 @@
            cantainerEl.addEventListener('touchstart', function(e) {
                //        console.log('touchstart:', e.touches.length);
                e.preventDefault(); // 阻止默认行为
                _this.canvas.fire('touch:start', {
                    e: e
                });
                _this.canvasTouchStart(e)
                //    _this.canvas._onMouseDown(e);
            });
            cantainerEl.addEventListener('touchmove', function(e) {
                //    _this.canvas._onMouseMove(e);
                //    console.log('touchmove:', e.touches.length);
                e.preventDefault(); // 阻止默认行为
                // 处理移动
                _this.canvasTouchMove(e)
            });
            cantainerEl.addEventListener('touchend', function(e) {
                //    _this.canvas._onMouseUp(e);
                //    console.log('touchend:');
                e.preventDefault(); // 阻止默认行为
                _this.touchPoint = {
                    x: 0,
                    y: 0
                };
                const activeObj = _this.canvas.getActiveObject()
                if (!activeObj) {
                    // 处理结束事件
                    if (e.touches.length === 0) {
                        _this.handleTouchEnd();
                    }
                    // if (_this.editObject) {
                    //     _this.canvas.setActiveObject(_this.editObject)
                    // }
                } else {
                    // if (activeObj.lockMovementX) {
                    //     _this.canvas.discardActiveObject();
                    // }
                }
                if (this.pressObjTimer) {
                    clearTimeout(this.pressObjTimer);
                    this.pressObjTimer = null
                }
            });
            cantainerEl.addEventListener('touchcancel', function(e) {
                //    console.log('touchcancel:');
                if (this.pressObjTimer) {
                    clearTimeout(this.pressObjTimer);
                    this.pressObjTimer = null
                }
            })
        },
        canvasTouchStart(e) {
            const _this = this
                _this.pointerSelectObject(e)
                if (!_this.canvas.getActiveObject()) {
                    // 根据触摸点数量判断交互类型
@@ -596,13 +672,10 @@
                        _this.handleMultiTouch(e.touches);
                    }
                }
            });
            cantainerEl.addEventListener('touchmove', function(e) {
                //    _this.canvas._onMouseMove(e);
                //    console.log('touchmove:', e.touches.length);
                e.preventDefault(); // 阻止默认行为
                // 处理移动
        },
        canvasTouchMove(e) {
            const _this = this
                const list = _this.canvas.getActiveObjects()
                if (list.length == 0) {
                    if (e.touches.length === 1) {
@@ -630,48 +703,6 @@
                        _this.handleMultiTouchMove(e.touches);
                    }
                }
            });
            cantainerEl.addEventListener('touchend', function(e) {
                //    _this.canvas._onMouseUp(e);
                //    console.log('touchend:');
                e.preventDefault(); // 阻止默认行为
                _this.touchPoint = {
                    x: 0,
                    y: 0
                };
                const activeObj = _this.canvas.getActiveObject()
                if (!activeObj) {
                    // 处理结束事件
                    if (e.touches.length === 0) {
                        _this.handleTouchEnd();
                    }
                    // if (_this.editObject) {
                    //     _this.canvas.setActiveObject(_this.editObject)
                    // }
                } else {
                    // if (activeObj.lockMovementX) {
                    //     _this.canvas.discardActiveObject();
                    // }
                }
                if (this.pressObjTimer) {
                    clearTimeout(this.pressObjTimer);
                    this.pressObjTimer = null
                }
            });
            cantainerEl.addEventListener('touchcancel', function(e) {
                //    console.log('touchcancel:');
                if (this.pressObjTimer) {
                    clearTimeout(this.pressObjTimer);
                    this.pressObjTimer = null
                }
                // const activeObj = _this.canvas.getActiveObject()
                // if (activeObj) {
                //     if (activeObj.lockMovementX) {
                //         _this.canvas.discardActiveObject();
                //     }
                // }
            })
        },
        // 计算点到线段的距离
@@ -753,7 +784,6 @@
            objects.splice(0, 1);
            const objActive = this.canvas.getActiveObject()
            let pointerList = []
            let pointerList2 = []
            for (let i = objects.length - 1; i >= 0; i--) {
@@ -893,44 +923,6 @@
                }
                return
            }
            // objects.forEach(obj => {
            //     if (obj instanceof fabric.Path || obj instanceof fabric.Line) {
            //         // 设置一个“点击容忍度”,比如 5 像素
            //         const tolerance = 5;
            //         // 临时扩大路径的点击区域
            //         const originalStrokeWidth = obj.strokeWidth;
            //         obj.strokeWidth = originalStrokeWidth + tolerance * 2;
            //         const isHit = obj.intersectsWithPointer(pointer);
            //         // 恢复原始宽度
            //         obj.strokeWidth = originalStrokeWidth;
            //         if (isHit) {
            //             pointerList.push(obj)
            //         }
            //     } else if (obj instanceof fabric.Rect || obj instanceof fabric.Ellipse) {
            //         const isHit = obj.containsPoint(pointer);
            //         if (isHit) {
            //             pointerList.push(obj)
            //         }
            //     }
            //     // else if (obj instanceof fabric.Group )
            //     // {
            //     //     const objects2 = obj.getObjects();
            //     //     const isHit = obj.containsPoint(pointer);
            //     //     if (isHit) {
            //     //         pointerList.push(obj)
            //     //     }
            //     // }
            // });
            // if (pointerList.length === 0) {
            //     return
            // }
            // const obj = pointerList.pop()
            // this.canvas.discardActiveObject()
            // this.canvas.setActiveObject(obj)
        },
        objectMoving(target) {
            const _this = this
@@ -955,7 +947,7 @@
                });
                _this.createOkCancelControl(obj)
                _this.canvas.renderAll()
                _this.canvas.requestRenderAll()
            } else if (target?.eleType == "edit_teaching") {
                _this.updateEditTeachingPath(target)
@@ -977,7 +969,7 @@
                else
                    _this.updateRegion(target, data)
                _this.canvas.renderAll()
                _this.canvas.requestRenderAll()
            } else if (target?.eleType == "wall_pt") {
                const data = target.mainObj?.data
@@ -1007,7 +999,7 @@
                _this.updateVirtualWall(target.mainObj, data)
                _this.canvas.renderAll()
                _this.canvas.requestRenderAll()
            } else if (target?.eleType == "region_pt") {
                const data = target.mainObj?.data
                if (!data)
@@ -1039,10 +1031,8 @@
                        }
                        _this.updateRegion(target.mainObj, data)
                    }
                    _this.canvas.renderAll()
                    _this.canvas.requestRenderAll()
                }
            } else if (target?.eleType == "edit_teaching_pt") {
@@ -1126,28 +1116,6 @@
        onSelectionChanage() {
        },
        safeLoadImage(url, maxSize = 2048) {
            console.log(url)
            return new Promise((resolve) => {
                const img = new Image();
                img.onload = () => {
                    // 检查尺寸是否超出限制
                    const scale = Math.min(
                        maxSize / Math.max(img.width, img.height),
                        1
                    );
                    resolve(new fabric.Image(img, {
                        scaleX: scale,
                        scaleY: scale
                    }));
                };
                img.onerror = () => {
                    console.error('图片加载失败');
                    resolve(null);
                };
                img.src = url;
            });
        },
        // 将 Base64 转为 Blob,再生成 URL
        base64ToBlob(base64, mime) {
@@ -1234,6 +1202,7 @@
                    _this.$ownerInstance.callMethod('receiveRenderData', {
                        method: "set_backgroud_progress",
                        type: "error",
                        msg:err
                    });
                    console.error("图片加载失败", err)
                    reject(new Error('图片加载失败'));
@@ -1253,14 +1222,66 @@
            }
            return null;
        },
        clearObjects() {
            const list = this.canvas.getObjects()
            list.splice(0, 1)
            for (let i in list) {
                const obj = list[i]
                this.canvas.remove(obj)
        // 移除所有事件监听器
        removeAllEventListeners() {
            if (!this.canvas) return;
            // 移除Fabric.js内置事件
            this.canvas.off();
            // 移除自定义事件监听器
            const cantainerEl = document.getElementById("canvasMap");
            if (cantainerEl) {
                cantainerEl.replaceWith(cantainerEl.cloneNode(true));
            }
        },
        clearObjects() {
            if (!this.canvas) return;
            this.canvas.discardActiveObject()
            const objects = this.canvas.getObjects()
            const batchSize = 50; // 每批删除50个对象
            for (let i = 0; i < objects.length; i += batchSize) {
                const batch = objects.slice(i, i + batchSize);
                this.canvas.remove(...batch);
            }
            this.canvas.clear();
            this.workSpace = null;
            this.agvObj = null;
            this.curTeachingObj = null;
            this.objEditing = null;
            this.editObject = null;
            this.drawingObj = null;
            if (this.pressObjTimer) {
                clearTimeout(this.pressObjTimer);
                this.pressObjTimer = null;
            }
        },
        // 清理所有引用
        cleanupReferences() {
            this.canvas = null;
            this.workSpace = null;
            this.agvObj = null;
            this.curTeachingObj = null;
            this.objEditing = null;
            this.editObject = null;
            this.drawingObj = null;
            this.mapInfo = {
                proportion: 1,
                img_proportion: 1,
                max_x: 1,
                max_y: 1,
                min_x: 0,
                min_y: 0,
                img_x: 1,
                img_y: 1
            };
            // 清除所有定时器
            if (this.pressObjTimer) {
                clearTimeout(this.pressObjTimer);
                this.pressObjTimer = null;
            }
        },
        setBackground(info) {
            const _this = this
@@ -1277,7 +1298,7 @@
            // this.canvas.selectionColor = 'rgba(100, 200, 255, 0.3)'; // 选中背景色
            // this.canvas.selectionBorderColor = '#1890ff'; // 边框颜色
            // this.canvas.selectionLineWidth = 3; // 边框宽度
            this.agvObj = null
            const cantainerEl = document.getElementById("canvasMap")
            this.eleWidth = cantainerEl.clientWidth
            this.eleHeight = cantainerEl.clientHeight
@@ -1314,25 +1335,8 @@
                                left: 0,
                                top: 0,
                            });
                            // if (_this.workSpace instanceof fabric.Group) {
                            //     const objs = _this.workSpace.getObjects()
                            //     const rect = objs[1]
                            //     _this.workSpace.remove(objs[0])
                            //     _this.workSpace.insertAt(0,img)
                            //     rect.set({
                            //         width: _this.mapInfo.img_x,
                            //         height: _this.mapInfo.img_y,
                            //     })
                            //     _this.workSpace.set({
                            //         width: _this.mapInfo.img_x,
                            //         height: _this.mapInfo.img_y,
                            //     })
                            //     resolve()
                            //     return
                            // }
                            _this.clearObjects()
                            //
                            const rect = new fabric.Rect({
                                left: 0,
                                top: 0,
@@ -1359,21 +1363,48 @@
                                height: _this.mapInfo.img_y,
                            });
                            _this.canvas.add(wsGroup)
                            if (_this.workSpace) {
                                _this.canvas.remove(_this.workSpace)
                            }
                            _this.workSpace = wsGroup
                            _this.clearObjects()
                            _this.canvas.add(wsGroup)
                            // _this.canvas.renderAll()
                            _this.workSpace = wsGroup
                        }
                        //_this.checkMemoryUsage()
                        resolve()
                    }).catch((err) => {
                        _this.$ownerInstance.callMethod('receiveRenderData', {
                            method: "set_backgroud_progress",
                            type: "error",
                        // _this.$ownerInstance.callMethod('receiveRenderData', {
                        //     method: "set_backgroud_progress",
                        //     type: "error",
                        //     msg:err
                        // });
                        const rect = new fabric.Rect({
                            left: 0,
                            top: 0,
                            width: _this.mapInfo.img_x,
                            height: _this.mapInfo.img_y,
                            stroke: "#333",
                            strokeWidth: 1,
                            strokeDashArray: [5, 5],
                            strokeLineCap: 'butt',
                            fill: "rgba(255,255,255,0)",
                        })
                        let wsGroup = new fabric.Group([ rect], {
                            id: "workspace",
                            eleType: "workspace",
                            selectable: false,
                            hasControls: false,
                            left: 0,
                            top: 0,
                            width: _this.mapInfo.img_x,
                            height: _this.mapInfo.img_y,
                        });
                        _this.clearObjects()
                        _this.canvas.add(wsGroup)
                        _this.workSpace = wsGroup
                        resolve()
                    })
@@ -1425,12 +1456,7 @@
                scale: scale
            });
            if (!this.workSpace) return;
            // this.setCenterFromObject(this.workSpace);
            // 超出画布不展示
            // _this.workSpace.clone().then((cloned) => {
            //     _this.canvas.clipPath = cloned;
            //     _this.canvas.requestRenderAll();
            // });
        },
        setDrawingType(type, svg) {
            if (svg) {
@@ -1474,7 +1500,6 @@
                y: touch.clientY
            };
            //    console.log('单点触摸开始');
            let activeObj = this.canvas.getActiveObject();
            if (!activeObj) {
                if (!this.drawType) {
@@ -1520,7 +1545,6 @@
                }
                // 移动视口
                //    console.log('relativePan', deltaX, deltaY);
                const vpt = this.canvas.viewportTransform;
                this.canvas.relativePan(new fabric.Point(deltaX, deltaY));
                if (this.objEditing) {
@@ -1543,7 +1567,7 @@
                this.lastPosX = touch.clientX;
                this.lastPosY = touch.clientY;
                this.canvas.renderAll()
                this.canvas.requestRenderAll()
            } else if (this.isDrawing) {
                const vpt = this.canvas.viewportTransform;
                //    console.log("viewportTransform", vpt[4], vpt[5])
@@ -1849,7 +1873,7 @@
            if (this.objEditing) {
                this.createOkCancelControl(this.objEditing)
            }
            this.canvas.renderAll()
            this.canvas.requestRenderAll()
        },
@@ -2222,8 +2246,7 @@
                    lockScalingY: true,
                    lockMovementX: true,
                    lockMovementY: true,
                    selectable: false,
                    opacity: 1,
                    mainRoad: main_road,
                    data: teachingData
                })
@@ -2271,8 +2294,8 @@
                const obj = list[i2]
                obj.set({
                    opacity: show ? 1 : 0,
                    strokeDashArray: [],
                    strokeLineCap: '',
                    // strokeDashArray: [],
                    // strokeLineCap: '',
                    hasControls: show,
                    selectable: show,
                })
@@ -2432,23 +2455,23 @@
            this.createOkCancelControl(obj)
            this.canvas.requestRenderAll();
        },
        updateAgv(info) {
        updateAgv(info, obj) {
            const _this = this
            return new Promise((resolve) => {
                //    const scale = this.getAutoScale()
                const left = _this.getXOnImg(info.x) // * scale
                const top = _this.getYOnImg(info.y) //* scale
                const angle = info.angle * 180 / Math.PI
                if (this.agvObj) {
                    this.agvObj.set({
                if (obj) {
                    obj.set({
                        left,
                        top,
                        angle,
                        data: info
                    });
                    this.agvObj.setCoords()
                    _this.canvas.requestRenderAll();
                    resolve()
                    obj.setCoords()
                    this.canvas.requestRenderAll();
                    resolve(obj)
                } else {
                    const zoom = _this.canvas.getZoom();
                    fabric.loadSVGFromURL("static/images/van.svg").then(
@@ -2489,16 +2512,13 @@
                            console.log("agv", JSON.stringify(info))
                            _this.canvas.add(obj)
                            //    _this.canvas.bringObjectToFront(obj);
                            _this.agvObj = obj
                            resolve()
                            resolve(obj)
                        }
                    )
                }
            })
        },
        addVirtualWallShow(info) {
            const path = info.path || []
            if (path.length != 2)
@@ -2526,7 +2546,6 @@
            });
            return line
        },
        addVirtualWall(info) {
            const path = info.path || []
            if (path.length != 2)
@@ -2705,18 +2724,7 @@
                    y: this.getYOnImg(pt.y)
                }
                // if (pt.x < 10) {
                //     pt.x = 10
                // }
                // if (pt.y < 10) {
                //     pt.y = 10
                // }
                // if (pt.x > this.workSpace.width - 10) {
                //     pt.x = 10
                // }
                // if (pt.y > this.workSpace.height - 10) {
                //     pt.y = 10
                // }
                if (index > 0) {
                    path2 += ` L${pt2} ${pt2.y}`
                } else {
@@ -2754,18 +2762,6 @@
            const path = info.path || []
            let path2 = ""
            path.forEach((pt, index) => {
                // if (pt.x < 10) {
                //     pt.x = 10
                // }
                // if (pt.y < 10) {
                //     pt.y = 10
                // }
                // if (pt.x > this.workSpace.width - 10) {
                //     pt.x = this.workSpace.width - 10
                // }
                // if (pt.y > this.workSpace.height - 10) {
                //     pt.y = this.workSpace.height - 10
                // }
                let pt2 = {
                    x: this.getXOnImg(pt.x),
                    y: this.getYOnImg(pt.y)
@@ -3083,14 +3079,30 @@
        updateLaserPoint(param) {
            let list2 = this.canvas.getObjects() || []
            list2 = list2.filter((a) => a.eleType == "laser_point")
            list2 = list2.filter((a) => a.eleType == "laser_point_cur_group")
            for (let i in list2) {
                const obj = list2[i]
                const objGroup = list2[i]
                objGroup.set({
                    eleType: "laser_point_group",
                })
                const list3 = objGroup.getObjects()
                for (let i3 in list3) {
                    const obj = list3[i3]
                obj.set({
                    fill: "#000",
                        fill: "#0000FF",
                })
            }
            const list = param.xy || []
            }
            const list = param?.xy || []
            const objs = []
            let right = 0
            let bottom = 0
            let left = this.mapInfo.img_x
            let top = this.mapInfo.img_y
            for (let i in list) {
                const pt = list[i]
                const pt2 = {
@@ -3098,35 +3110,15 @@
                    y: this.getYOnImg(pt[1])
                }
                const point = new fabric.Rect({
                    id: "laser_point",
                    eleType: "laser_point",
                    // id: "laser_point",
                    // eleType: "laser_point",
                    left: pt2.x,
                    top: pt2.y,
                    width: 1,
                    height: 1,
                    fill: "#F5222D",
                    originX: "center",
                    originY: "center",
                    selectable: false,
                    hasControls: true,
                    lockRotation: true,
                    lockScalingX: true,
                    lockScalingY: true,
                    lockMovementX: true,
                    lockMovementY: true,
                });
                // let point = new fabric.Ellipse({
                //    id: "laser_point",
                //     eleType: "laser_point",
                //     left: pt[0],
                //     top: pt[1],
                //     rx: 2,
                //     ry: 1,
                //     strokeWidth: 1,
                //     stroke: "#F5222D",
                //     fill: "#F5222D",
                //     originX: "center",
                //     originY: "center",
                    originX: "left",
                    originY: "top",
                //     selectable: false,
                //     hasControls: true,
                //     lockRotation: true,
@@ -3134,9 +3126,36 @@
                //     lockScalingY: true,
                //     lockMovementX: true,
                //     lockMovementY: true,
                // });
                this.canvas.add(point)
                });
                objs.push(point)
                if (left > pt2.x) {
                    left = pt2.x
            }
                if (top > pt2.y) {
                    top = pt2.y
                }
                if (right < pt2.x + 1) {
                    right = pt2.x + 1
                }
                if (bottom < pt2.y + 1) {
                    bottom = pt2.y + 1
                }
            }
            //console.log("updateLaserPoint", list.length, left, right,top,bottom)
            const groupObj = new fabric.Group(objs, {
                id: `laser_point_group`,
                eleType: "laser_point_cur_group",
                left,
                top,
                width: right - left,
                height: bottom - top,
                // originX: "left",
                // originY: "top",
                selectable: false,
                hasControls: true,
            })
            this.canvas.add(groupObj)
        },
@@ -3152,28 +3171,19 @@
            if (pt.x * zoom < -vpt[4] + offWidth || pt.x * zoom > -vpt[4] + this.eleWidth - offWidth) {
                if (pt.x * zoom - this.eleWidth / 2 <offWidth) {
                    newPanX = -offWidth
                }
                // else if (pt.x * zoom > this.mapInfo.img_x * zoom - 20) {
                //     newPanX = this.mapInfo.img_x * zoom - this.eleWidth + 20
                // }
                else {
                } else {
                    newPanX = pt.x * zoom - this.eleWidth / 2
                }
            }
            if (pt.y * zoom < -vpt[5] +offHeight || pt.y * zoom > -vpt[5] + this.eleHeight - (120+offHeight)) {
            if (pt.y * zoom < -vpt[5] + offHeight || pt.y * zoom > -vpt[5] + this.eleHeight - (120 +
                    offHeight)) {
                if (pt.y * zoom - this.eleHeight / 2 <offHeight) {
                    newPanY = -offHeight
                }
                // else if (pt.y * zoom > this.mapInfo.img_y * zoom - 180) {
                //     newPanY = this.mapInfo.img_y * zoom - this.eleHeight + 180
                // }
                 else {
                } else {
                    newPanY = pt.y * zoom -(this.eleHeight - 120) / 2
                }
            }
        //    console.log("ensurePointVisible2",newPanX,newPanY)
            // 只有在需要时才平移
            if (newPanX !== -vpt[4] || newPanY !== -vpt[5]) {
                this.canvas.absolutePan({
@@ -3193,44 +3203,58 @@
        },
        setAllObjectSelectable(selectable) {
            let flag = false
            this.canvas.forEachObject(function(obj) {
                if (obj.canSelect) {
                    if (!obj.flag) {
                    if (obj.selectable != selectable) {
                        flag = true
                    }
                    obj.set({
                        selectable: selectable,
                        lockEdit: true
                    })
                }
                }
            });
            if (flag) {
            if (flag)
                this.canvas.requestRenderAll()
            }
        },
        receiveMsg(newValue, oldValue) {
            if (typeof newValue == "undefined")
                return;
            const _this = this
            //console.log("receiveMsg",_this.initFlag)
            setTimeout(() => {
            if (!this.canvas) {
                return
            }
                if (_this.initFlag) {
                    _this.handleMsg(newValue, oldValue)
                } else {
                setTimeout(() => {
                    _this.receiveMsg(newValue, oldValue)
                }
            }, 100)
            }
        },
        async handleMsg(newValue, oldValue) {
            const _this = this
            if (!this.canvas) {
                return
            }
            try {
                //console.log("handleMsg", newValue)
                var data = JSON.parse(newValue);
                // console.log("handleMsg", data.length)
                const destroyCommand = data.find(item => item.method === "destroy");
                if (destroyCommand) {
                    this.destroyCanvas();
                    return;
                }
                for (var i = 0; i < data.length; i++) {
                    const item = data[i]
                    if (item.method == "init") {
                        if (item.param?.editMode) {
@@ -3243,7 +3267,20 @@
                        await _this.setBackground(item.param)
                    } else if (item.method == "update_agv_state") {
                        const info = item.param || {}
                        await _this.updateAgv(info)
                        const obj = _this.agvObj
                        const obj2 = await _this.updateAgv(info, obj)
                        let obj3 = _this.agvObj
                        _this.agvObj = obj2
                        if (obj && obj2 != obj) {
                            _this.canvas.remove(obj)
                            if (obj3 == obj)
                                obj3 = undefined
                        }
                        if (obj3 && obj2 != obj3) {
                            _this.canvas.remove(obj3)
                        }
                    } else if (item.method == "update_current_teaching") {
                        const info = item.param || []
                        await _this.updateCurrentTeaching(info)
@@ -3257,17 +3294,14 @@
                            height: 20
                        }
                        this.ensurePointVisible(pt)
                    }
                    else if (item.method == "move_pt_center") {
                    } else if (item.method == "move_pt_center") {
                        const info2 = item.param || {}
                        const pt = {
                            x: this.getXOnImg(info2.x),
                            y: this.getYOnImg(info2.y)
                        }
                        this.ensurePointCenter(pt)
                    }
                    else if (item.method == "add_station") {
                    } else if (item.method == "add_station") {
                        const stationList = item.param || []
                        let list = _this.canvas.getObjects() || []
                        for (let i2 in stationList) {
@@ -3322,7 +3356,6 @@
                                }
                            }
                        }
                    } else if (item.method == "remove_station") {
@@ -3341,9 +3374,7 @@
                                _this.canvas.remove(list[curIndex])
                                if (tipObj) {
                                    _this.canvas.remove(tipObj)
                                }
                            }
                        }
@@ -3475,14 +3506,11 @@
                        _this.setAllObjectSelectable(false)
                        let list = _this.canvas.getObjects() || []
                        list.forEach((obj) => {
                            if (obj.eleType == "public_teaching" || obj.eleType == "station_teaching") {
                            if (obj.eleType == "public_teaching" || obj.eleType ==
                                "station_teaching") {
                                obj.set({
                                    opacity: 1
                                })
                                // obj.set({
                                //     hasControls: false,
                                //     selectable: false,
                                // })
                            } else if (obj.eleType == "agv")
                                obj.set({
                                    opacity: 1
@@ -3507,32 +3535,40 @@
                        }
                        _this.showTeachingPath(_this.showTeachPathFlag ? true : false)
                    }
                    else if (item.method == "clear_teaching_path") {
                    } else if (item.method == "clear_teaching_path") {
                        let list = _this.canvas.getObjects() || []
                        list = list.filter((a) => a.eleType == "public_teaching" || a.eleType == "station_teaching")
                        list = list.filter((a) => a.eleType == "public_teaching" || a.eleType ==
                            "station_teaching")
                        for (let i2 in list) {
                            this.canvas.remove(list[i2])
                        }
                    }
                    else if (item.method == "public_teaching_path") {
                    } else if (item.method == "public_teaching_path") {
                    
                        const teachingPathList = item.param || []
                        const teachingPathList = item.param?.list || []
                        const show = item.param?.show || false
                        for (let i2 in teachingPathList) {
                            const teachingPath = teachingPathList[i2]
                            const id = `public_teaching_${teachingPath.name}`
                            await this.addTeachingPath(teachingPath, id, "public_teaching")
                            const obj = await this.addTeachingPath(teachingPath, id, "public_teaching",
                                show)
                            obj.set({
                                selectable: show ? true : false,
                                opacity: show ? 1 : 0,
                            })
                        }
                    } else if (item.method == "station_teaching_path") {
                        const teachingPathList = item.param || []
                        const show = item.param?.show || false
                        const teachingPathList = item.param?.list || []
                        for (let i2 in teachingPathList) {
                            const teachingPath = teachingPathList[i2]
                            const id = `station_teaching_${teachingPath.src_dst}`
                            await this.addTeachingPath(teachingPath, id, "station_teaching")
                            const obj = await this.addTeachingPath(teachingPath, id, "station_teaching",
                                show)
                            obj.set({
                                selectable: show ? true : false,
                                opacity: show ? 1 : 0,
                            })
                        }
                    } else if (item.method == "show_teaching_path") {
                        _this.showTeachPathFlag = item.param.show
@@ -3559,9 +3595,7 @@
                                const obj = list[curIndex]
                                this.canvas.remove(obj)
                            }
                        }
                    } else if (item.method == "edit_teaching") {
                        const teachingMode = item.param
                        _this.showEditTeachingPath(teachingMode)
@@ -3583,7 +3617,6 @@
                        for (let i2 in wallList) {
                            const wall = wallList[i2]
                            const obj = await _this.addVirtualWall(wall)
                        }
                    } else if (item.method == "wall_list") {
                        const wallList = item.param || []
@@ -3601,8 +3634,6 @@
                        for (let i2 in regionList) {
                            const region = regionList[i2]
                            const obj = await _this.addRegion(region)
                        }
                    } else if (item.method == "region_list") {
                        const regionList = item.param || []
@@ -3615,7 +3646,6 @@
                                await _this.addRegionShow(region)
                            }
                        }
                    } else if (item.method == "remove_wall") {
                        const wallList = item.param || []
                        let list = _this.canvas.getObjects() || []
@@ -3644,6 +3674,7 @@
                        this.updateLaserPoint(item.param || {})
                    }
                }
                if (_this.canvas)
                _this.canvas.renderAll()
            } catch (ex) {
                console.log(ex)
@@ -3685,6 +3716,5 @@
                verticalAlign: "center"
            }); // undefined, "错误"
        },
    },
    }
}
pages/map/scene.vue
@@ -1,15 +1,18 @@
<template>
    <view class="pages-scene">
        <view class="map-content" v-if="opSceneType =='' ">
            <image class="img" src="/images/image 25.png" alt=" 图片" mode="aspectFit" />
            <view class="space">没有找到符合条件的地图</view>
            <image v-if="opType != 'extend'" class="img" src="/images/image 25.png" alt=" 图片" mode="aspectFit" />
            <image v-else class="img" :src="extendBase64Img" alt=" 图片" mode="aspectFit" />
            <view v-if="opType != 'extend'" class="space">没有找到符合条件的地图</view>
            <!-- <view class="loading-view">{{mapserverIsOk?"构图程序准备就绪":"等待构图程序就绪..."}}
                <view v-if="!mapserverIsOk" class="auto-circle"></view>:disabled="!mapserverIsOk"
            </view> -->
            <view class="text-button-group">
                <a-button type="primary" class="button" @click="clickStartConstructScene">
                    开始构建
                    {{opType == 'extend'?"开始扩展":'开始构建'}}
                </a-button>
                <a-button type="primary" class="button" :disabled="loading && localSceneList.length == 0"
                    @click="clickDownloadScene" disabled>
                <a-button v-if="opType != 'extend'" type="primary" class="button"
                    :disabled="loading && localSceneList.length == 0" @click="clickDownloadScene" disabled>
                    下载场景
                </a-button>
            </view>
@@ -49,10 +52,10 @@
            </view>
            <view class="bottom-content" v-else-if="opSceneType =='finish'">
                <view class="tip">场景构建完成</view>
                <view>
                    已成功构建“{{sceneName}}”
                </view>
                <view>已成功构建“{{sceneName}}”</view>
                <!-- <view class="loading-view">{{saveMapIsOk?"构图保存完成":"等待构图保存完成..."}}
                    <view v-if="!saveMapIsOk" class="auto-circle"></view>
                </view> !saveMapIsOk ||-->
                <view class="text-button-group">
                    <a-button type="primary" class="button" :disabled="loading" @click="clickFinish">构建完成</a-button>
                </view>
@@ -81,6 +84,11 @@
        //getAgvState,
        getMapLaserData,
        saveDBData,
        checkMapServerIsStart,
        startOrStopMapServer,
        checkMapServerIsOk,
        checkSaveMapIsOk,
        getMapUrl
    } from "@/api/vehicle.js"
    export default {
@@ -101,7 +109,11 @@
                ctxDataStr: "[]",
                localSceneList: [],
                positioningAgv: true,
                robotPos: {}
                robotPos: {},
                mapserverIsOk: false,
                extendBase64Img: "",
                saveMapIsOk: false,
                destroyFlag: false,
            }
        },
@@ -137,6 +149,7 @@
                    if (res) {
                        this.opSceneType = ""
                        if (this.opType != "") {
                            uni.navigateBack({
                                delta: 1, //返回层数,2则上上页
                            })
@@ -147,11 +160,27 @@
                return true
            } else if (this.opSceneType == "finish") {
                if (this.destroyFlag) {
                const eventChannel = this.getOpenerEventChannel();
                eventChannel.emit('create_finish', this.sceneName);
                return false
            } else {
                    this.ctxDataStr = JSON.stringify([{
                        method: "destroy",
                    }])
                    return true
                }
            } else {
                if (this.destroyFlag)
                return false
                else {
                    this.ctxDataStr = JSON.stringify([{
                        method: "destroy",
                    }])
                    return true
                }
            }
        },
@@ -180,6 +209,7 @@
            async loadData() {
                try {
                    // this.loadMapServerState()
                    if (this.opType == "") {
                        this.localSceneList = await this.loadLocalScene()
                    } else {
@@ -190,8 +220,19 @@
                            await addMap(this.ip, this.sceneName, "extend")
                            this.opSceneType = 'scan'
                        }
                    }
                        // if (this.opType == "extend") {
                        //     // const infoMap = await this.loadMapInfo(this.sceneName)
                        //     // if (infoMap.filedata) {
                        //     //     var base64Image = infoMap.filedata
                        //     //     if (base64Image.indexOf("data:image/png;base64,") < 0) {
                        //     //         base64Image = "data:image/png;base64," + infoMap.filedata
                        //     //     }
                        //     //     this.extendBase64Img = base64Image
                        //     // }
                        // }
                    }
                    this.refreshMapLaserData()
@@ -200,9 +241,81 @@
                    showError(ex)
                }
            },
            async loadMapInfo(id) {
                try {
                    const info = await getMapUrl(this.ip, id)
                    return info
                } catch (ex) {
                    return {}
                }
            },
            async loadMapServerState() {
                try {
                    this.mapserverIsOk = false
                    const res = await checkMapServerIsStart(this.ip)
                    if (res) {
                        this.mapserverIsOk = true
                    } else {
                        this.mapserverIsOk = false
                        const res = await startOrStopMapServer(this.ip, 1)
                        if (res) {
                            this.checkMapServerState()
                        }
                    }
                } catch (ex) {
                    showError(ex)
                }
            },
            async checkMapServerState() {
                try {
                    const res = await checkMapServerIsOk(this.ip)
                    if (res) {
                        this.mapserverIsOk = true
                    } else {
                        this.mapserverIsOk = false
                        setTimeout(this.checkMapServerState, 1000);
                    }
                } catch (ex) {
                    showError(ex).then((res) => {
                        setTimeout(this.checkMapServerState, 1000);
                    })
                }
            },
            async checkSaveMapState() {
                try {
                    const res = await checkSaveMapIsOk(this.ip)
                    if (res) {
                        this.saveMapIsOk = true
                    } else {
                        this.saveMapIsOk = false
                        setTimeout(this.checkSaveMapState, 1000);
                    }
                } catch (ex) {
                    showError(ex).then((res) => {
                        setTimeout(this.checkSaveMapState, 1000);
                    })
                }
            },
            receiveRenderData(param) {
                console.log('接收到视图层的数据:', param);
                if (param.method == "set_backgroud_progress") {
                if (param.method === "destroy_complete") {
                    if (param.param) {
                        this.destroyFlag = true
                        uni.navigateBack({
                            delta: 1
                        })
                    }
                } else if (param.method == "set_backgroud_progress") {
                    if (param.type == "start") {
                        this.setData({
                            bgProgressPercent: 50,
@@ -224,14 +337,34 @@
                        }, 500)
                    } else if (param.type == "error") {
                        console.log("set_backgroud_progress error")
                        this.setData({
                            bgProgressPercent: 0,
                            bgLoading: false
                        })
                        const now = new Date()
                        const date = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`
                        showToast("加载底图失败")
                        const log = {
                            date,
                            method: `POST`,
                            url: "app/log/load_img",
                            param: param.msg,
                            statusCode: 100,
                            data: "加载底图失败"
                        }
                        const listLog = session.getValue("request_log") || []
                        listLog.unshift(log)
                        session.setValue("request_log", listLog)
                    }
                } else if (param.method == "cancel_positioning_agv") {
                    this.positioningAgv = false
                } else if (param.method == "show_log") {
                    const listLog = session.getValue("request_log") || []
                    listLog.unshift(param.data)
                    session.setValue("request_log", listLog)
                }
            },
@@ -244,8 +377,17 @@
                    return []
                }
            },
            clickStartConstructScene() {
            async clickStartConstructScene() {
                try {
                    if (this.opType == "extend") {
                        await addMap(this.ip, this.sceneName, "extend")
                        this.opSceneType = 'scan'
                    } else {
                this.opSceneType = "add_name"
                    }
                } catch (ex) {
                    showError(ex)
                }
            },
            async clickDownloadScene() {
                try {
@@ -328,7 +470,10 @@
                    uni.setNavigationBarTitle({
                        title: this.sceneName
                    })
                    this.saveMapIsOk = false
                    await stopMap(this.ip, this.sceneName)
                    // await startOrStopMapServer(this.ip, 2)
                    // this.checkSaveMapState();
                    if (this.opType == "extend") {
                        this.opSceneType = ""
                        const eventChannel = this.getOpenerEventChannel();
@@ -339,14 +484,10 @@
                    }
                } catch (ex) {
                    console.log(ex)
                    showModal("请检查车辆连接,并重新开始构建场景", "场景构建失败", false, "确定").then((res) => {
                        this.opSceneType = ''
                        if (this.opType != "") {
                            uni.navigateBack({
                                delta: 1, //返回层数,2则上上页
                            })
                        }
                        // this.loadMapServerState()
                    })
                } finally {
                    this.loading = false
@@ -368,14 +509,7 @@
                        delta: 1, //返回层数,2则上上页
                    })
                } catch (ex) {
                    showModal("请检查车辆连接,并重新开始构建场景", "场景构建失败", false, "确定").then((res) => {
                        this.opSceneType = ''
                        if (this.opType != "") {
                            uni.navigateBack({
                                delta: 1, //返回层数,2则上上页
                            })
                        }
                    })
                    console.log(ex)
                } finally {
                    this.loading = false
                    uni.hideLoading()
@@ -399,34 +533,49 @@
                        const data = await this.loadMapLaserData()
                        const listCtrData = []
                        let newMap = false
                        if (data.base_map?.image_base64) {
                            this.robotPos = {}
                            newMap = true
                            const mapData = data.base_map.image_base64  //this.mapId ?"terdy":
                            this.mapId = data.base_map.map_id
                            listCtrData.push({
                                method: "background",
                                param: {
                                    proportion: 1,
                                    img_proportion: 1,
                                    max_x: data.base_map.width,
                                    max_y: data.base_map.height,
                                    max_x: data.base_map.width || 100,
                                    max_y: data.base_map.height || 100,
                                    min_x: 0,
                                    min_y: 0,
                                    img_x: data.base_map.width,
                                    img_y: data.base_map.height,
                                    filedata: data.base_map.image_base64
                                    img_x: data.base_map.width || 100,
                                    img_y: data.base_map.height || 100,
                                    filedata: mapData
                                }
                            })
                        }
                        listCtrData.push({
                            method: "agv_laser",
                            param: data.robot_pose
                        })
                        listCtrData.push({
                            method: "point_cloud",
                            param: data.point_cloud
                        })
                        if (data.robot_pose) {
                            listCtrData.push({
                                method: "agv_laser",
                                param: data.robot_pose
                            })
                            if (newMap) {
                                listCtrData.push({
                                    method: "move_pt_center",
                                    param: {
                                        x: data.robot_pose.x,
                                        y: data.robot_pose.y,
                                    }
                                })
                            } else {
                        if (this.positioningAgv) {
                            listCtrData.push({
                                method: "move_pt_visible",
@@ -438,18 +587,21 @@
                                }
                            })
                        }
                            }
                        }
                        // console.log("ctxDataStr",listCtrData.length)
                        this.ctxDataStr = JSON.stringify(listCtrData)
                        if (data.robot_pose) {
                        this.robotPos = {
                            x: data.robot_pose.x,
                            y: data.robot_pose.y
                        }
                    }
                    }
                    setTimeout(this.refreshMapLaserData, 1000);
                } catch (ex) {
                    showError(ex).then((res) => {
                    showToast(ex)
                        setTimeout(this.refreshMapLaserData, 1000);
                    })
                }
            },
            async clickVehiclePosition() {
@@ -517,6 +669,7 @@
            justify-content: center;
            .text-button-group {
                display: flex;
                width: 100%;
@@ -533,6 +686,32 @@
        }
        .loading-view {
            display: flex;
            flex-direction: row;
            .auto-circle {
                margin-left: 20rpx;
                width: 50rpx;
                height: 50rpx;
                border-radius: 50%;
                border: 10rpx solid #1890FF;
                border-top-color: transparent;
                animation: drawCircle 1s infinite linear;
            }
            @keyframes drawCircle {
                0% {
                    transform: rotate(0deg);
                }
                100% {
                    transform: rotate(360deg);
                }
            }
        }
        .bottom {
            position: fixed;
pages/map/task.vue
@@ -320,6 +320,8 @@
            margin-top: 75px;
            margin-left: 120px;
            width: 150px;
            max-height: 50vh;
            overflow: auto;
            align-items: center;
            justify-content: center;
            flex-direction: column;
pages/my/help-feedback.vue
@@ -1,31 +1,33 @@
<template>
    <view class="pages-my">
        <view class="group">
            <view class="item line" @click="clickRemoteAssistance">
            <view class="item line">
                <view>远程协助:</view>
                <view class="right"></view>
                <a>
                <a @click="clickRemoteAssistance">
                    <uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
                </a>
            </view>
            <view class="item line" @click="clickUploadLog">
            <view class="item line">
                <view>日志上传:</view>
                <view class="right"></view>
                <a>
                <a @click="clickUploadLog">
                    <uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
                </a>
            </view>
            <view class="item line" @click="clickViewInstruction">
            <view class="item line">
                <view>查看说明书:</view>
                <view class="right"></view>
                <a>
                <a @click="clickViewInstruction">
                    <uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
                </a>
            </view>
            <view class="item line" @click="clickApiLog">
            <view class="item line">
                <view>接口日志:</view>
                <switch :checked="withLog" style="transform:scale(0.7)" @change="switchChangeLog"/>{{withLog?"记录接口日志":"不记录接口日志"}}
                <view class="right"></view>
                <a>
                <a @click="clickApiLog">
                    <uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
                </a>
            </view>
@@ -48,7 +50,7 @@
        },
        data() {
            return {
                withLog: getApp().globalData.withLog || false
            }
        },
        onLoad() {
@@ -58,6 +60,11 @@
        },
        methods: {
            switchChangeLog(e) {
                this.withLog = e.detail.value
                getApp().globalData.withLog =this.withLog
                session.setValue("write_log",this.withLog ? 1:0)
            },
            clickRemoteAssistance() {
                showToast("暂未实现")
pages/my/index.vue
@@ -32,7 +32,7 @@
            </view>
         -->
            <view class="item line" @click="clickClearCache">
                <view>清楚缓存:</view>
                <view>清除缓存:</view>
                <view class="right">{{cacheSizeStr}}</view>
                <a >
                    <uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>