<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>
|
|
<view class="text-button-group">
|
<a-button type="primary" class="button" @click="clickStartConstructScene">
|
开始构建
|
</a-button>
|
<a-button type="primary" class="button" :disabled="loading && localSceneList.length == 0"
|
@click="clickDownloadScene" disabled>
|
下载场景
|
</a-button>
|
</view>
|
|
</view>
|
<view class="content" v-show="opSceneType =='scan'">
|
<view class="fabric" :message="ctxDataStr" :change:message="ctx.receiveMsg" id="canvasMap"></view>
|
</view>
|
<view class="bottom">
|
<view class="bottom-content" v-if="opSceneType =='add_name' ">
|
<view class="tip">请输入场景名称</view>
|
<view class="name-input">
|
<input ref="refInputName" :focus="true" placeholder="请输入场景名称" :value="sceneName"
|
@input="onInputName"></input>
|
<uni-icons class="clear" color="#ccc" type="clear" size="20" v-if="showClearName"
|
@click="clickClearName"></uni-icons>
|
</view>
|
<view class="text-button-group">
|
<a-button type="primary" class="button" :disabled="loading || sceneName.trim() == ''"
|
@click="clickNameOK">确认</a-button>
|
<a-button type="ghost" class="button" :disabled="loading" @click="clickNameCancel">取消</a-button>
|
|
</view>
|
</view>
|
<view class="bottom-content" v-else-if="opSceneType =='scan'">
|
<view class="tip">场景构建中</view>
|
<view>
|
请操作搬运车扫描地图覆盖的区域
|
</view>
|
|
<view class="text-button-group">
|
<a-button type="primary" class="button" :disabled="loading" @click="clickScanFinish">扫描完成</a-button>
|
</view>
|
</view>
|
<view class="bottom-content" v-else-if="opSceneType =='finish'">
|
<view class="tip">场景构建完成</view>
|
<view>
|
已成功构建“{{sceneName}}”
|
</view>
|
|
<view class="text-button-group">
|
<a-button type="primary" class="button" :disabled="loading" @click="clickFinish">构建完成</a-button>
|
</view>
|
</view>
|
</view>
|
</view>
|
</template>
|
<script src="./js/ctx.js" module="ctx" lang="renderjs"></script>
|
|
<script>
|
import {
|
showToast,
|
showModal,
|
session,
|
} from "@/comm/utils.js"
|
import {
|
Button
|
} from 'antd-mobile-vue-next'
|
|
import {
|
createScene,
|
addMap,
|
stopMap,
|
//getAgvState,
|
getMapLaserData,
|
saveDBData,
|
|
} from "@/api/vehicle.js"
|
export default {
|
name: "PagesScene",
|
components: {
|
'a-button': Button
|
},
|
data() {
|
return {
|
opType: "",
|
loading: false,
|
ip: "",
|
opSceneType: "",
|
windowWidth: 375,
|
sceneName: "",
|
showClearName: false,
|
mapId: "",
|
ctxDataStr: "[]",
|
localSceneList: []
|
|
}
|
},
|
computed: {
|
|
},
|
watch: {
|
|
},
|
onLoad(option) {
|
const _this = this
|
this.ip = option.ip || ""
|
uni.getSystemInfo({
|
success(e) {
|
_this.windowWidth = e.windowWidth
|
},
|
|
})
|
this.sceneName = option.sceneId || ""
|
this.opType = option.opType || ""
|
this.opSceneType = ""
|
this.loadData()
|
|
},
|
onUnload() {
|
|
},
|
onBackPress() {
|
|
if (this.opSceneType == "scan") {
|
|
showModal("已构建场景将会被删除", "是否中断场景构建?").then((res) => {
|
if (res) {
|
this.opSceneType = ""
|
if (this.opType != "") {
|
uni.navigateBack({
|
delta: 1, //返回层数,2则上上页
|
})
|
}
|
|
}
|
})
|
return true
|
|
} else {
|
return false
|
}
|
|
},
|
methods: {
|
setData(obj) {
|
let that = this;
|
let keys = [];
|
let val, data;
|
|
Object.keys(obj).forEach(function(key) {
|
keys = key.split(".");
|
val = obj[key];
|
data = that.$data;
|
keys.forEach(function(key2, index) {
|
if (index + 1 == keys.length) {
|
that.$set(data, key2, val);
|
} else {
|
if (!data[key2]) {
|
that.$set(data, key2, {});
|
}
|
}
|
data = data[key2];
|
});
|
});
|
},
|
async loadData() {
|
try {
|
|
if (this.opType == "") {
|
this.localSceneList = await this.loadLocalScene()
|
} else {
|
if (this.opType == "create") {
|
this.opSceneType = "add_name"
|
}
|
if (this.opType == "extend") {
|
await addMap(this.ip, this.sceneName, "extend")
|
this.opSceneType = 'scan'
|
}
|
}
|
|
this.refreshMapLaserData()
|
|
|
} catch (ex) {
|
|
this.showError(ex)
|
}
|
},
|
receiveRenderData(param) {
|
console.log('接收到视图层的数据:', param);
|
if (param.method == "set_backgroud_progress") {
|
if (param.type == "start") {
|
this.setData({
|
bgProgressPercent: 50,
|
bgLoading: true
|
})
|
} else if (param.type == "progress") {
|
this.setData({
|
bgProgressPercent: 50 + (param.percent || 0) / 2
|
})
|
} else if (param.type == "end") {
|
this.setData({
|
bgProgressPercent: 100,
|
bgLoading: true
|
})
|
setTimeout(() => {
|
this.setData({
|
bgLoading: false
|
})
|
}, 500)
|
|
} else if (param.type == "error") {
|
this.setData({
|
bgProgressPercent: 0,
|
bgLoading: false
|
})
|
}
|
|
}
|
},
|
|
async loadLocalScene() {
|
try {
|
const list = session.getValue("scene_db") || []
|
return list
|
} catch (ex) {
|
this.showError(ex)
|
return []
|
}
|
},
|
clickStartConstructScene() {
|
this.opSceneType = "add_name"
|
},
|
async clickDownloadScene() {
|
try {
|
this.loading = true
|
uni.showLoading({
|
title: "下载场景中"
|
})
|
const data = this.localSceneList[0].data
|
await saveDBData(this.ip, data)
|
showToast("下载场景成功")
|
this.opSceneType = ""
|
const eventChannel = this.getOpenerEventChannel();
|
eventChannel.emit('create_finish', this.sceneName);
|
uni.navigateBack({
|
delta: 1, //返回层数,2则上上页
|
})
|
} catch (ex) {
|
this.showError(ex)
|
} finally {
|
this.loading = false
|
uni.hideLoading()
|
}
|
|
|
},
|
|
clickNameCancel() {
|
uni.navigateBack({
|
delta: 1, //返回层数,2则上上页
|
})
|
},
|
async clickNameOK() {
|
try {
|
this.loading = true
|
uni.showLoading({
|
title: "开始构建场景"
|
})
|
const name = this.sceneName.trim()
|
if (!name) {
|
showToast("站点名称还未输入")
|
return
|
}
|
|
this.sceneName = name
|
await createScene(this.ip, name, 1)
|
await addMap(this.ip, name)
|
uni.showLoading({
|
title: "开始扫描地图"
|
})
|
this.opSceneType = 'scan'
|
|
|
} catch (ex) {
|
this.showError(ex)
|
this.opSceneType = 'add_name'
|
} finally {
|
this.loading = false
|
uni.hideLoading()
|
}
|
|
},
|
clickClearName() {
|
this.sceneName = ""
|
this.showClearName = false
|
},
|
onInputName(event) {
|
this.sceneName = event.detail.value;
|
if (this.sceneName)
|
this.showClearName = true
|
else
|
this.showClearName = false
|
},
|
async clickScanFinish() {
|
try {
|
this.loading = true
|
uni.showLoading({
|
title: "地图扫描结束"
|
})
|
this.opSceneType = "finish"
|
uni.setNavigationBarTitle({
|
title: this.sceneName
|
})
|
await stopMap(this.ip, this.sceneName)
|
if (this.opType == "extend") {
|
this.opSceneType = ""
|
const eventChannel = this.getOpenerEventChannel();
|
eventChannel.emit('create_finish', this.sceneName);
|
uni.navigateBack({
|
delta: 1, //返回层数,2则上上页
|
})
|
}
|
|
} catch (ex) {
|
|
showModal("请检查车辆连接,并重新开始构建场景", "场景构建失败", false, "确定").then((res) => {
|
this.opSceneType = ''
|
if (this.opType != "") {
|
uni.navigateBack({
|
delta: 1, //返回层数,2则上上页
|
})
|
}
|
})
|
} finally {
|
this.loading = false
|
uni.hideLoading()
|
}
|
|
},
|
async clickFinish() {
|
try {
|
|
this.loading = true
|
uni.showLoading({
|
title: "结束场景构建"
|
})
|
this.opSceneType = ""
|
await createScene(this.ip, this.sceneName, 0)
|
const eventChannel = this.getOpenerEventChannel();
|
eventChannel.emit('create_finish', this.sceneName);
|
uni.navigateBack({
|
delta: 1, //返回层数,2则上上页
|
})
|
} catch (ex) {
|
showModal("请检查车辆连接,并重新开始构建场景", "场景构建失败", false, "确定").then((res) => {
|
this.opSceneType = ''
|
if (this.opType != "") {
|
uni.navigateBack({
|
delta: 1, //返回层数,2则上上页
|
})
|
}
|
})
|
} finally {
|
this.loading = false
|
uni.hideLoading()
|
}
|
|
|
},
|
async loadMapLaserData() {
|
try {
|
const info = await getMapLaserData(this.ip, this.mapId)
|
return info
|
} catch (ex) {
|
this.showError(ex)
|
return {}
|
}
|
},
|
async refreshMapLaserData() {
|
try {
|
if (this.opSceneType === "scan") {
|
|
const data = await this.loadMapLaserData()
|
|
const listCtrData = []
|
if (data.base_map?.image_base64) {
|
|
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,
|
min_x: 0,
|
min_y: 0,
|
img_x: data.base_map.width,
|
img_y: data.base_map.height,
|
filedata: data.base_map.image_base64
|
}
|
})
|
listCtrData.push({
|
method: "agv_laser",
|
param: data.robot_pose
|
})
|
listCtrData.push({
|
method: "point_cloud",
|
param: data.point_cloud
|
})
|
listCtrData.push({
|
method: "move_canvas",
|
param: {
|
x: data.robot_pose.x,
|
y: data.robot_pose.y
|
}
|
})
|
|
} else {
|
listCtrData.push({
|
method: "agv_laser",
|
param: data.robot_pose
|
})
|
listCtrData.push({
|
method: "point_cloud",
|
param: data.point_cloud
|
})
|
}
|
this.ctxDataStr = JSON.stringify(listCtrData)
|
}
|
} catch (ex) {
|
this.showError(ex)
|
} finally {
|
// 无论成功失败,1 秒后再来
|
setTimeout(this.refreshMapLaserData, 1000);
|
}
|
},
|
|
showError(ex) {
|
console.log(ex)
|
let exStr = JSON.stringify(ex)
|
if (exStr == "{}")
|
exStr = ex
|
let tip = typeof ex.msg == "string" ? ex.msg : exStr
|
showModal(tip, "错误", false, "确定")
|
},
|
|
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
.pages-scene {
|
display: flex;
|
width: 750rpx;
|
height: 100vh;
|
position: relative;
|
|
.content {
|
overflow: auto;
|
position: absolute;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
top: 0;
|
|
.fabric {
|
width: 100%;
|
height: 100%;
|
background-color: #fff;
|
}
|
|
|
}
|
|
.map-content {
|
width: 100%;
|
display: flex;
|
flex: 1;
|
flex-direction: column;
|
margin: auto;
|
align-items: center;
|
justify-content: center;
|
|
|
.text-button-group {
|
display: flex;
|
width: 100%;
|
justify-content: center;
|
align-items: center;
|
flex-direction: column;
|
font-size: 30rpx !important;
|
|
.button {
|
margin-top: 20rpx;
|
width: 375rpx;
|
}
|
}
|
|
}
|
|
|
.bottom {
|
position: fixed;
|
left: 50rpx;
|
right: 50rpx;
|
bottom: 20rpx;
|
display: flex;
|
|
.bottom-content {
|
display: flex;
|
flex-direction: column;
|
width: 100%;
|
// justify-content: center;
|
// align-items: center;
|
padding: 0 10rpx;
|
padding-bottom: 10rpx;
|
background-color: #fff;
|
border-radius: 10rpx;
|
//background-color: #eee;
|
|
.title {
|
font-size: 40rpx;
|
margin-bottom: 10rpx;
|
}
|
|
.tip {
|
color: #888;
|
margin: 10rpx;
|
text-align: left;
|
}
|
|
|
.disabled {
|
color: #ccc !important;
|
}
|
|
.name-input {
|
width: calc(100% - 20rpx);
|
margin-bottom: 10rpx;
|
background-color: #fff;
|
padding: 10rpx;
|
border-radius: 8rpx;
|
display: flex;
|
flex-direction: row;
|
color: #1890FF;
|
|
input {
|
flex: 1;
|
}
|
}
|
}
|
|
|
.text-button-group {
|
display: flex;
|
width: 100%;
|
justify-content: center;
|
align-items: center;
|
flex-direction: column;
|
font-size: 30rpx !important;
|
|
.button {
|
margin: auto;
|
margin-top: 20rpx;
|
width: calc(100% - 10rpx);
|
}
|
|
.am-button {
|
border-radius: 30px;
|
}
|
|
.am-button-ghost {
|
border: 1px solid #1677ff !important;
|
|
}
|
}
|
|
|
}
|
|
|
}
|
</style>
|