cyy
2025-09-28 fb026e6052b4d843d327312db398cf791ac57ab9
pages/map/index.vue
@@ -10,22 +10,22 @@
                  alt="SVG 图片" @click="clickShowMenu" />
            </view>
            <template v-slot:left>
               <view>
                  <uni-icons type="left" size="24" @click="clickBack"></uni-icons>
               <view @click="clickBack">
                  <uni-icons type="left" size="24"></uni-icons>
               </view>
            </template>
            <template v-slot:right>
            <!-- <template v-slot:right>
               <view v-if="sceneList.length > 0 && !mapOperationType">
                  <a @click="clickMore">
                     <uni-icons class="uni-panel-bar-icon" type="more-filled" size="24"></uni-icons>
                  </a>
               </view>
            </template>
            </template> -->
         </uni-nav-bar>
         <view class="no-content" v-if="unlinked">
            <image class="img" src="/images/image 25.png" alt=" 图片" mode="aspectFit" />
            <image class="img" src="/images/image_25.png" alt=" 图片" mode="aspectFit" />
            <view class="title">车辆连接失败</view>
            <view class="space">请检查你的网络设置或重新加载</view>
         </view>
@@ -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>
@@ -87,7 +89,7 @@
            <view class="tip">请输入场景名称</view>
            <view class="name-input">
               <input ref="refInputName" :focus="true" placeholder="请输入场景名称" :value="sceneInputName"
                  @input="onInputName"></input>
                  @input="onInputName" />
               <uni-icons class="clear" color="#ccc" type="clear" size="20" v-if="sceneInputName"
                  @click="clickClearName"></uni-icons>
            </view>
@@ -106,14 +108,14 @@
                  <view class="coordinate">
                     <text class="name">横坐标:</text>
                     <input ref="refInputX" class="number-input" type="number" :value="stationEdit.x"
                        @input="onInputStationX" :maxlength="4"></input>
                        @input="onInputStationX" :maxlength="4" />
                     <uni-icons class="clear" color="#ccc" type="clear" size="20"
                        v-if="stationEdit.x && stationEdit.x!='0'" @click="clickClearStationX"></uni-icons>
                  </view>
                  <view class="coordinate">
                     <text class="name">竖坐标:</text>
                     <input ref="refInputX" class="number-input" type="number" :value="stationEdit.y"
                        @input="onInputStationY" :maxlength="4"></input>
                        @input="onInputStationY" :maxlength="4" />
                     <uni-icons class="clear" color="#ccc" type="clear" size="20"
                        v-if="stationEdit.y&& stationEdit.y!='0'" @click="clickClearStationY"></uni-icons>
                  </view>
@@ -122,7 +124,7 @@
               <view class="tip">调节朝向</view>
               <view class="angle-group">
                  <image class="img-angle" :src="angleSvg" alt="SVG 图片" />
                  <image class="img-angle-pos" src="/images/Frame 153.svg" alt="SVG 图片"
                  <image class="img-angle-pos" src="/images/Frame_153.svg" alt="SVG 图片"
                     @touchstart="handleAngleTouchStart" @touchmove="handleAngleTouchMove" />
               </view>
            </view>
@@ -130,7 +132,7 @@
               <view class="tip">请输入站点名称</view>
               <view class="name-input">
                  <input ref="refInputName" :focus="true" placeholder="输入站点名称" :value="stationEdit.name"
                     @input="onInputStationName"></input>
                     @input="onInputStationName" />
                  <uni-icons class="clear" color="#ccc" type="clear" size="20" v-if="stationEdit.name"
                     @click="clickClearStationName"></uni-icons>
               </view>
@@ -209,8 +211,8 @@
            <view class="bottom-content" v-if="mapOperationStatus =='teaching'">
               <view class="tip">路径记录中...</view>
               <view v-if="mapOperationType =='public_teaching'">
                  <view>正在记录搬运车行进路径,可随时切换主路/支路示教,完成后点按钮以结束示教。在示教过程中可以添加站点。</view>
                  <view class="switch-type">
                  <view>正在记录搬运车行进路径,完成后点按钮以结束示教。在示教过程中可以添加站点。</view>
                  <!--       <view class="switch-type">可随时切换主路/支路示教,
                     <view class="switch-button-group">
                        <view class="switch-button"
                           :class="teachingModeCur.main_road ==1?'switch-button-checked':''"
@@ -219,7 +221,7 @@
                           :class="teachingModeCur.main_road ==0?'switch-button-checked':''"
                           @click="onTeachingModeMainRoad(0)">支路示教</view>
                     </view>
                  </view>
                  </view> -->
               </view>
               <view v-else>
@@ -345,7 +347,7 @@
                  <view class="img-button-group">
                     <view fill="none" class="button" @click.stop="clickStationDelete">
                        <text class="ico delete-outline"></text>
                        <view class="text"> 删除站点</view>
                        <view class="text"> 批量删除</view>
                     </view>
                     <view type="text" class="button" @click.stop="clickStationPostion">
                        <text class="ico edit-line"></text>
@@ -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: "",
@@ -471,7 +475,8 @@
            wallList: [],
            regionList: [],
            unlinked: false,
            showTeachingPathFlag: false,
            showTeachingPathFlag: true,
            curTeachingPathFlag: false,
            curMapInfo: {
               proportion: 1,
               img_proportion: 1,
@@ -482,7 +487,9 @@
               img_x: 1,
               img_y: 1
            },
            positioningAgv: false
            positioningAgv: false,
            isPageVisible: true,
            destroyFlag: false,
         }
      },
      computed: {
@@ -539,10 +546,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;
@@ -572,6 +598,10 @@
                  this.mapOperationType = ''
                  const scene = this.sceneList[0]
                  this.changeMap(scene)
               } else {
                  uni.navigateBack({
                     delta: 1, //返回层数,2则上上页
                  })
               }
               this.refreshAgvPosition()
            } catch (ex) {
@@ -583,6 +613,10 @@
         },
         clickShowMenu() {
            // const list = [...this.sceneList]
            // for(let i =0; i < 20;i++){
            //    list.push("test" + i)
            // }
            this.menuPopup = {
               type: "scene",
               list: this.sceneList,
@@ -722,19 +756,26 @@
                  showModal("已记录的路径将会被删除。", "是否要退出示教?").then(async (res) => {
                     if (res) {
                        const listDataStr = []
                        if (this.mapOperationStatus == 'end' || this.mapOperationStatus ==
                           'save') {
                           try {
                              await delTeachingMode(this.vehicleIp, [this.teachingModeCur])
                              listDataStr.push({
                                 method: "remove_teaching_path",
                                 param: {
                                    name: this.teachingModeCur.name,
                                    mode: "Public"
                                 },
                              })
                           } catch (ex) {
                              showError(ex)
                           }
                        }
                        this.ctxDataStr = JSON.stringify([{
                        listDataStr.push({
                           method: "teaching_finish",
                        }])
                        })
                        this.ctxDataStr = JSON.stringify(listDataStr)
                        this.mapOperationType = ""
                     }
                  })
@@ -747,11 +788,7 @@
               }
            } else {
               // const eventChannel = this.getOpenerEventChannel();
               // eventChannel.emit('udapte_station', this.unlinked);
               // uni.navigateBack({
               //    delta: 1
               // })
               const eventChannel = this.getOpenerEventChannel();
               eventChannel.emit('check_connect', !this.unlinked);
               uni.navigateBack({
@@ -786,7 +823,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}&opType=create`,
                     events: {
                        // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
                        create_finish: function(data) {
@@ -802,15 +839,13 @@
                  this.clickDelete()
               }
            }
         },
         async loadAgvState() {
            try {
               const info = await getAgvState(this.vehicleIp)
               return info
            } catch (ex) {
               showError(ex)
               showToast(ex)
               return {}
            }
         },
@@ -819,7 +854,7 @@
               const paths = await getCurrentTeachingData(this.vehicleIp) || []
               return paths
            } catch (ex) {
               showError(ex)
               showToast(ex)
               return []
            }
         },
@@ -884,7 +919,6 @@
                  img_x: parseInt(infoMap.img_x) || 1,
                  img_y: parseInt(infoMap.img_y) || 1
               }
               // getApp().globalData.curScene = infoMap
               this.setData({
                  bgProgressPercent: 30,
                  bgLoading: infoMap.filedata ? true : false
@@ -909,13 +943,25 @@
                     param: stationLst
                  },
                  {
                     method: "show_teaching_path",
                     param: {
                        show: this.showTeachingPathFlag
                     }
                  },
                  {
                     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 +985,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,
@@ -975,6 +1028,9 @@
                  width: param.view?.width || 0,
                  height: param.view?.height || 0,
               }
               const angle = this.getStantardAngle(this.stationEdit.angle * 180 / Math.PI)
               this.angleSvg = `/static/images/angle${angle}.svg`
               this.mapOperationType = ""
               this.$refs.refPopupOperateStation.open("bottom")
@@ -1001,6 +1057,9 @@
                     const angle = this.getStantardAngle(this.stationEdit.angle * 180 / Math.PI)
                     this.angleSvg = `/static/images/angle${angle}.svg`
                     if (this.mapOperationType == "teaching_add_station") {
                        this.positioningAgv = true
                     }
                     this.clickStationPositonOk()
                  } else if (param.type == "edit_teaching") {
                     // console.log(param.type,JSON.stringify(param.data))
@@ -1048,7 +1107,7 @@
                     this.stationEdit.stationID = ""
                     this.mapOperationType = "public_teaching"
                     this.mapOperationStatus = "teaching"
                     this.positioningAgv = true
                  } else if (this.mapOperationType == "edit_station") {
                     this.mapOperationType = ""
                     this.mapOperationStatus = ""
@@ -1070,12 +1129,10 @@
                        param: true
                     }])
                  }
               }
            } else if (param.method == "select_teaching_path") {
               console.log("point", param.point)
               if (param.type == "station") {
                  this.selectTeachingMode = {
                     mode: "Stations",
                     name: param.data?.name || "",
@@ -1090,17 +1147,18 @@
                     point: param.point
                  }
               }
               this.$refs.refPopupOperateTeaching.open("bottom")
            } else if (param.method == "cancel_positioning_agv") {
               this.positioningAgv = false
               if (this.mapOperationType == "public_teaching"
               && this.mapOperationStatus == "teaching") {
                  this.positioningAgv = true
               } else
                  this.positioningAgv = false
            } else if (param.method == "show_log") {
               const listLog = session.getValue("request_log") || []
               listLog.unshift(param.data)
               session.setValue("request_log", listLog)
            }
         },
         clickMapStation() {
            this.stationEdit = {
@@ -1129,6 +1187,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,9 +1229,8 @@
         },
         async loadSceneList() {
            try {
               uni.showLoading({
                  title: "加载场景中"
               })
               const _this = this
               const res = await getAllScene(this.vehicleIp) || []
               const list = res?.sceneList || []
@@ -1188,25 +1246,27 @@
                  //    sceneId: "",
                  //    navigationBarTitle: "地图"
                  // })
                  uni.navigateTo({
                     url: `/pages/map/scene?ip=${this.vehicleIp}&opType=create`,
                     events: {
                        // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
                        create_finish: function(data) {
                           _this.onCreateSceneOk(data)
                        },
                     }
                  // uni.navigateTo({
                  //    url: `/pages/map/scene?ip=${this.vehicleIp}`,
                  //    events: {
                  //       // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
                  //       create_finish: function(data) {
                  //          _this.onCreateSceneOk(data)
                  //       },
                  //    }
                  // })
                  uni.navigateBack({
                     delta: 1, //返回层数,2则上上页
                  })
                  return
               }
            } catch (ex) {
               showError(ex)
            } finally {
               uni.hideLoading()
            }
            }
         },
         clickDelete() {
            const _this = this
            showModal(`删除场景[${this.sceneId}]会把场景对应的地图任务信息都会删除,是否确认删除?`, "删除场景").then(async (res) => {
               if (res) {
                  try {
@@ -1218,6 +1278,15 @@
                     await this.loadSceneList()
                     if (this.sceneList.length > 0)
                        this.changeMap(this.sceneList[0])
                     // else {
                     //    _this.mapOperationType = ""
                     //    setTimeout(() => {
                     //       uni.navigateBack({
                     //          delta: 1, //返回层数,2则上上页
                     //       })
                     //    }, 500)
                     // }
                  } catch (ex) {
                     showError(ex)
                  } finally {
@@ -1387,14 +1456,23 @@
                  showToast("场景名称不能为空!")
                  return
               }
               console.log(name, this.sceneId)
               // console.log(name, this.sceneId)
               if (name == this.sceneId) {
                  showToast("场景名称未变化!")
                  return
               }
               const curIndex = this.sceneList.findIndex((param) => param == this.sceneId)
               this.mapOperationType = ""
               await updateScene(this.vehicleIp, this.sceneId, name)
               this.sceneId = name
               if (curIndex > -1) {
                  this.sceneList[curIndex] = name
               }
               this.setData({
                  navigationBarTitle: name
               })
               showToast("场景重命名成功!")
            } catch (ex) {
               this.mapOperationType = "edit_scene_name"
@@ -1427,7 +1505,27 @@
            this.mapOperationType = ""
         },
         clickStationDelete() {
            this.stationDelete(this.stationEdit)
            const _this = this
            uni.navigateTo({
               url: `/pages/station/delete?ip=${ this.vehicleIp}`,
               events: {
                  // 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
                  delete_finish: function(data) {
                     console.log(data)
                     const list = data.map((a) => {
                        return {
                           stationID: a
                        }
                     })
                     _this.ctxDataStr = JSON.stringify([{
                        method: "remove_station",
                        param: list
                     }])
                  }
               }
            })
            //this.stationDelete(this.stationEdit)
            // const _this = this
            // showModal("该站点已绑定任务,删除站点后绑定的任务会停止并删除", "是否确认删除?").then((res) => {
            //    if (res) {
@@ -1726,10 +1824,8 @@
            return resAngle
         },
         touchAngleChange(e) {
            let angle = 0
            const ptX = e.touches[0].clientX
            const offX = ptX // ptX - e.target.offsetLeft
@@ -1846,26 +1942,35 @@
               }
            }
         },
         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
                     }
                  }
               ])
               ]
               if (finish) {
                  list.push({
                     method: "teaching_finish",
                  })
               }
               this.ctxDataStr = JSON.stringify(list)
            } catch (ex) {
               showError(ex)
@@ -1921,40 +2026,110 @@
                     method: "update_agv_state",
                     param: agv
                  }]
                  // if (this.mapOperationType === "public_teaching" && this.mapOperationStatus ===
                  //    "teaching") {
                  const list = await this.loadCurrentTeachingData()
                  if (this.mapOperationType === "public_teaching" && this.mapOperationStatus ===
                     "teaching") {
                     const list = await this.loadCurrentTeachingData()
                     listCtrData.push({
                        method: "update_current_teaching",
                        param: {
                           main_road: this.teachingModeCur.main_road,
                           pos_list: list
                  listCtrData.push({
                     method: "update_current_teaching",
                     param: {
                        main_road: 1, //this.teachingModeCur.main_road,
                        pos_list: list
                     }
                  })
                  if (list.length > 0) {
                     this.curTeachingPathFlag = true
                  } else {
                     if (this.curTeachingPathFlag) {
                        this.curTeachingPathFlag = false
                        const teaching = await this.loadTeachingMode()
                        const publicOld = this.teachingMode.Public || []
                        const stationOld = this.teachingMode.Stations || []
                        const publicNew = teaching.Public || []
                        const stationNew = teaching.Stations || []
                        const publicAdd = []
                        const stationAdd = []
                        for (let i in publicNew) {
                           const item = publicNew[i]
                           const curIndex = publicOld.findIndex((a) => a.name == item.name)
                           console.log(curIndex, item)
                           if (curIndex < 0) {
                              publicAdd.push(item)
                              publicOld.push(item)
                           }
                        }
                     })
                        for (let i in stationNew) {
                           const item = stationNew[i]
                           const curIndex = stationOld.findIndex((a) => a.name == item.name)
                           if (curIndex < 0) {
                              stationAdd.push(item)
                              stationOld.push(item)
                           }
                        }
                        this.teachingMode.Public = publicOld
                        this.teachingMode.Stations = stationOld
                        if (publicAdd.length > 0) {
                           listCtrData.push({
                              method: "public_teaching_path",
                              param: {
                                 list: publicAdd,
                                 show: this.showTeachingPathFlag
                              }
                           })
                        }
                        if (stationAdd.length > 0) {
                           listCtrData.push({
                              method: "station_teaching_path",
                              param: {
                                 list: stationAdd,
                                 show: this.showTeachingPathFlag
                              }
                           })
                        }
                     }
                  }
                  // }
                  if (this.positioningAgv) {
                     listCtrData.push({
                        method: "move_pt_visible",
                        param: {
                           x: agv.x,
                           y: agv.y,
                           width:80,
                           height:80,
                        }
                     })
                     if (this.curTeachingPathFlag) {
                        listCtrData.push({
                           method: "move_pt_center",
                           param: {
                              x: agv.x,
                              y: agv.y,
                           }
                        })
                     } else {
                        listCtrData.push({
                           method: "move_pt_visible",
                           param: {
                              x: agv.x,
                              y: agv.y,
                              width: 80,
                              height: 80,
                           }
                        })
                     }
                  }
                  this.ctxDataStr = JSON.stringify(listCtrData)
               }
               setTimeout(this.refreshAgvPosition, 1000);
               //setTimeout(this.refreshAgvPosition, 1000);
            } catch (ex) {
               showError(ex).then((res) => {
                  setTimeout(this.refreshAgvPosition, 1000);
               })
               // showError(ex).then((res) => {
               // })
               showToast(ex)
            } finally {
               // 无论成功失败,1 秒后再来
               setTimeout(this.refreshAgvPosition, 1000);
            }
         },
@@ -1986,7 +2161,6 @@
               uni.hideLoading()
            }
         },
         async clickTeachingStart() {
            const _this = this
@@ -2024,6 +2198,16 @@
                        this.loading = true
                        await delTeachingMode(_this.vehicleIp, [_this.teachingModeCur])
                        _this.mapOperationStatus = ""
                        const listDataStr = []
                        listDataStr.push({
                           method: "remove_teaching_path",
                           param: {
                              name: _this.teachingModeCur.name,
                              mode: "Public"
                           },
                        })
                        _this.ctxDataStr = JSON.stringify(listDataStr)
                     } catch (ex) {
                        showError(ex)
@@ -2032,8 +2216,7 @@
                     }
                  } else {
                     _this.mapOperationStatus =
                        "save"
                     _this.mapOperationStatus = "save"
                  }
               })
@@ -2049,10 +2232,8 @@
         },
         clickTeachingFinish() {
            this.mapOperationType = ""
            this.ctxDataStr = JSON.stringify([{
               method: "teaching_finish",
            }])
            this.reloadTeachingMode()
            //this.reloadTeachingMode(true)
         },
         async teachingStart(mode) {
@@ -2155,24 +2336,26 @@
                     )
                  if (res?.name)
                     this.teachingModeCur.name = res.name
                     const {
                        data
                     } = await getTeachingMode(this.vehicleIp)
                     const publicList = data.Public || []
                     const curIndex = publicList.findIndex((a)=>a.name == oldName)
                     if(curIndex > -1)
                     {
                        this.ctxDataStr = JSON.stringify([{
                           method: "public_teaching_path",
                           param: [publicList[curIndex]]
                        } ])
                     }
                  const {
                     data
                  } = await getTeachingMode(this.vehicleIp)
                  const publicList = data.Public || []
                  const curIndex = publicList.findIndex((a) => a.name == oldName)
                  if (curIndex > -1) {
                     this.ctxDataStr = JSON.stringify([{
                        method: "public_teaching_path",
                        param: {
                           list: [publicList[curIndex]],
                           show: true
                        }
                     }])
                  }
               } else {
                  this.teachingModeCur
                     .main_road =
@@ -2209,7 +2392,7 @@
         async removeTeachingMode(item) {
            try {
               uni.showLoading({
                  title: "删除场景中"
                  title: "删除示教中"
               })
               await delTeachingMode(this.vehicleIp, [item])
               this.ctxDataStr =
@@ -2228,7 +2411,7 @@
         async removeTeachingModeData(data) {
            try {
               uni.showLoading({
                  title: "删除场景数据中"
                  title: "删除示教数据中"
               })
               await delTeachingModeData(this.vehicleIp, data)
               this.reloadTeachingMode()
@@ -2705,6 +2888,8 @@
         margin-top: 140rpx;
         margin-left: 225rpx;
         width: 300rpx;
         max-height: 50vh;
         overflow: auto;
         align-items: center;
         justify-content: center;
         flex-direction: column;