2025-07-04 17:52:10 +08:00
|
|
|
<template>
|
|
|
|
|
<div class="page_container">
|
|
|
|
|
<el-row type="flex" justify="space-between">
|
2025-07-15 13:59:05 +08:00
|
|
|
<el-col :span="10"><button class="button_control" :disabled="disabled" @click="addPoint"><p>打点</p></button></el-col>
|
2025-07-04 17:52:10 +08:00
|
|
|
<el-col :span="14">
|
|
|
|
|
<el-row type="flex" justify="end">
|
|
|
|
|
<el-button type="primary" icon="el-icon-zoom-in" size="mini" @click="zoomIn">放大</el-button>
|
|
|
|
|
<el-button type="primary" icon="el-icon-zoom-out" size="mini" @click="zoomOut">缩小</el-button>
|
|
|
|
|
</el-row>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<div class="canvas-container">
|
|
|
|
|
<canvas id="canvas" ref="canvas" width="1920" height="1080"></canvas>
|
|
|
|
|
</div>
|
2025-07-16 10:49:07 +08:00
|
|
|
<el-row type="flex" justify="end">
|
|
|
|
|
<button class="button_control" @click="$router.push('/index/home')"><p>放弃建图</p></button>
|
|
|
|
|
<button class="button_control" style="margin-left: 10px" :disabled="disabled" @click="_stopMapping"><p>结束建图</p></button>
|
|
|
|
|
</el-row>
|
2025-07-14 09:28:21 +08:00
|
|
|
<el-dialog
|
|
|
|
|
title="设置站点"
|
|
|
|
|
:visible.sync="dialogVisible"
|
|
|
|
|
width="50%">
|
|
|
|
|
<el-form :model="dataForm" ref="dataForm" :label-width="$i18n.locale === 'en-us' ? '' : '1.1rem'" size="mini">
|
|
|
|
|
<el-form-item label="站点名称" prop="point">
|
|
|
|
|
<el-input v-model="dataForm.point" id="point" @focus="show" data-layout="normal"></el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
<el-row type="flex" justify="space-around" style="margin-top: .3rem">
|
|
|
|
|
<el-col :span="7"><button class="button_control button_control_disabled" @click="dialogVisible = false"><p>{{$t('Cancel')}}</p></button></el-col>
|
|
|
|
|
<el-col :span="7"><button class="button_control" @click="_setStation"><p>{{$t('Save')}}</p></button></el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<vue-touch-keyboard id="keyboard" :options="options" v-if="visible" :layout="layout" :cancel="hide" :accept="accept" :input="input" :next="next" />
|
|
|
|
|
</el-dialog>
|
2025-07-16 10:49:07 +08:00
|
|
|
<transition name="custom-message">
|
|
|
|
|
<div v-if="message" class="message">
|
|
|
|
|
<i class="el-icon-success"></i>
|
|
|
|
|
<p>{{ message }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
</transition>
|
2025-07-04 17:52:10 +08:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-07-25 18:43:20 +08:00
|
|
|
import { startMapping, setStation, stopMapping, getLocalMaps, oneClickDeployment, abandonMapping } from '@config/getData.js'
|
2025-07-04 17:52:10 +08:00
|
|
|
export default {
|
2025-07-16 10:49:07 +08:00
|
|
|
beforeRouteLeave (to, from, next) {
|
2025-07-23 20:05:03 +08:00
|
|
|
if (this.needsConfirmation) {
|
|
|
|
|
this.$confirm('是否放弃本次建图?', '提示', {
|
|
|
|
|
confirmButtonText: '确定',
|
|
|
|
|
cancelButtonText: '取消',
|
|
|
|
|
type: 'warning'
|
2025-07-25 18:43:20 +08:00
|
|
|
}).then(async () => {
|
|
|
|
|
try {
|
|
|
|
|
// 显示加载中状态
|
|
|
|
|
this.loading = this.$loading({
|
|
|
|
|
lock: true,
|
|
|
|
|
spinner: 'el-icon-loading',
|
|
|
|
|
background: 'rgba(0, 0, 0, 0.6)'
|
|
|
|
|
})
|
|
|
|
|
// 调用放弃建图接口
|
|
|
|
|
const res = await abandonMapping()
|
|
|
|
|
this.loading.close()
|
|
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
// 接口成功,允许离开页面
|
|
|
|
|
this.needsConfirmation = false // 标记无需再确认
|
|
|
|
|
next()
|
|
|
|
|
} else {
|
|
|
|
|
// 接口返回失败,提示错误并阻止离开
|
|
|
|
|
this.$message.error(res.message || '放弃建图失败,请重试')
|
|
|
|
|
next(false)
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
// 发生异常,提示错误并阻止离开
|
|
|
|
|
this.loading.close()
|
|
|
|
|
this.$message.error('操作失败:' + error.message)
|
|
|
|
|
next(false)
|
|
|
|
|
}
|
2025-07-23 20:05:03 +08:00
|
|
|
}).catch(() => {
|
|
|
|
|
next(false) // 阻止离开
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
next()
|
|
|
|
|
}
|
2025-07-16 10:49:07 +08:00
|
|
|
},
|
2025-07-04 17:52:10 +08:00
|
|
|
data () {
|
|
|
|
|
return {
|
2025-07-23 20:05:03 +08:00
|
|
|
needsConfirmation: true,
|
2025-07-14 17:52:37 +08:00
|
|
|
mapName: '',
|
2025-07-14 09:28:21 +08:00
|
|
|
dialogVisible: false,
|
|
|
|
|
dataForm: {
|
|
|
|
|
point: ''
|
|
|
|
|
},
|
|
|
|
|
keyPoints: [],
|
2025-07-15 13:59:05 +08:00
|
|
|
disabled: false,
|
|
|
|
|
message: '', // 用于显示消息
|
|
|
|
|
intervalId: null, // 用于存储定时器ID
|
|
|
|
|
startTime: null, // 用于记录开始时间
|
2025-07-14 09:28:21 +08:00
|
|
|
visible: false,
|
|
|
|
|
layout: 'normal',
|
|
|
|
|
input: null,
|
|
|
|
|
options: {
|
|
|
|
|
useKbEvents: false,
|
|
|
|
|
preventClickEvent: false
|
2025-07-15 13:59:05 +08:00
|
|
|
}
|
2025-07-04 17:52:10 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
beforeDestroy () {
|
|
|
|
|
if (this.intervalId) {
|
|
|
|
|
clearInterval(this.intervalId)
|
|
|
|
|
}
|
|
|
|
|
},
|
2025-07-16 10:49:07 +08:00
|
|
|
created () {
|
2025-07-14 09:28:21 +08:00
|
|
|
this._startMapping()
|
|
|
|
|
},
|
2025-07-04 17:52:10 +08:00
|
|
|
methods: {
|
2025-07-14 09:28:21 +08:00
|
|
|
show (e) {
|
|
|
|
|
// 关闭中文keyboard
|
|
|
|
|
let arr = document.querySelectorAll('.hg-theme-default')
|
|
|
|
|
arr.forEach((ele) => {
|
|
|
|
|
ele.style.visibility = 'hidden'
|
|
|
|
|
})
|
|
|
|
|
this.input = e.target
|
|
|
|
|
this.layout = e.target.dataset.layout
|
|
|
|
|
if (!this.visible) {
|
|
|
|
|
this.visible = true
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
hide () {
|
|
|
|
|
this.visible = false
|
|
|
|
|
},
|
|
|
|
|
accept () {
|
|
|
|
|
this.hide()
|
|
|
|
|
},
|
|
|
|
|
next () {
|
|
|
|
|
let inputs = document.querySelectorAll('input')
|
|
|
|
|
let found = false;
|
|
|
|
|
[].forEach.call(inputs, (item, i) => {
|
|
|
|
|
if (!found && item === this.input && i < inputs.length - 1 && this.input.dataset.next === '1') {
|
|
|
|
|
found = true
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
inputs[i + 1].focus()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if (!found) {
|
|
|
|
|
this.input.blur()
|
|
|
|
|
this.hide()
|
|
|
|
|
}
|
|
|
|
|
},
|
2025-07-15 13:59:05 +08:00
|
|
|
// 开始建图
|
2025-07-14 09:28:21 +08:00
|
|
|
async _startMapping () {
|
|
|
|
|
try {
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading = this.$loading({
|
|
|
|
|
lock: true,
|
|
|
|
|
spinner: 'el-icon-loading',
|
|
|
|
|
background: 'rgba(0, 0, 0, 0.6)'
|
|
|
|
|
})
|
2025-07-14 17:52:37 +08:00
|
|
|
const getTimestamp = new Date().getTime()
|
|
|
|
|
this.mapName = `apt_map_${getTimestamp}`
|
|
|
|
|
let res = await startMapping(this.mapName)
|
2025-07-16 10:49:07 +08:00
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
this.message = '小车正在建图中'
|
|
|
|
|
} else {
|
|
|
|
|
this.$message.error(res.message)
|
2025-07-14 09:28:21 +08:00
|
|
|
}
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading.close()
|
2025-07-14 09:28:21 +08:00
|
|
|
} catch (e) {
|
|
|
|
|
this.$message.error(e)
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading.close()
|
2025-07-14 09:28:21 +08:00
|
|
|
}
|
|
|
|
|
},
|
2025-07-15 13:59:05 +08:00
|
|
|
// 打点
|
2025-07-04 17:52:10 +08:00
|
|
|
addPoint () {
|
2025-07-14 09:28:21 +08:00
|
|
|
this.dialogVisible = true
|
|
|
|
|
this.dataForm.point = 'B' + (this.keyPoints.length + 1)
|
|
|
|
|
},
|
2025-07-15 13:59:05 +08:00
|
|
|
// 打点->保存
|
2025-07-14 09:28:21 +08:00
|
|
|
async _setStation () {
|
2025-07-15 13:59:05 +08:00
|
|
|
this.disabled = true
|
2025-07-14 09:28:21 +08:00
|
|
|
try {
|
|
|
|
|
let res = await setStation(this.dataForm.point)
|
|
|
|
|
if (res) {
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
this.$message({
|
|
|
|
|
type: 'success',
|
|
|
|
|
message: res.message
|
|
|
|
|
})
|
|
|
|
|
this.keyPoints.push(this.dataForm.point)
|
|
|
|
|
} else {
|
|
|
|
|
this.$message.error(res.message)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-07-14 17:52:37 +08:00
|
|
|
this.dialogVisible = false
|
2025-07-14 09:28:21 +08:00
|
|
|
this.visible = false
|
2025-07-15 13:59:05 +08:00
|
|
|
this.disabled = false
|
2025-07-14 09:28:21 +08:00
|
|
|
} catch (e) {
|
|
|
|
|
this.$message.error(e)
|
2025-07-14 17:52:37 +08:00
|
|
|
this.dialogVisible = false
|
2025-07-14 09:28:21 +08:00
|
|
|
this.visible = false
|
2025-07-15 13:59:05 +08:00
|
|
|
this.disabled = false
|
2025-07-14 09:28:21 +08:00
|
|
|
}
|
|
|
|
|
},
|
2025-07-15 13:59:05 +08:00
|
|
|
// 结束建图
|
2025-07-14 09:28:21 +08:00
|
|
|
async _stopMapping () {
|
2025-07-15 13:59:05 +08:00
|
|
|
this.disabled = true
|
2025-07-14 09:28:21 +08:00
|
|
|
try {
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading = this.$loading({
|
|
|
|
|
lock: true,
|
|
|
|
|
spinner: 'el-icon-loading',
|
|
|
|
|
background: 'rgba(0, 0, 0, 0.6)'
|
|
|
|
|
})
|
2025-07-14 09:28:21 +08:00
|
|
|
let res = await stopMapping()
|
2025-07-16 10:49:07 +08:00
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
this.message = '正在建图,请等待。。。'
|
|
|
|
|
this.startTime = Date.now() // 记录开始时间
|
|
|
|
|
this._getLocalMaps()
|
|
|
|
|
this.intervalId = setInterval(this._getLocalMaps, 3000) // 每5秒检查一次
|
|
|
|
|
} else {
|
|
|
|
|
this.$message.error(res.message)
|
|
|
|
|
this.message = ''
|
|
|
|
|
this.disabled = false
|
|
|
|
|
this.loading.close()
|
2025-07-15 13:59:05 +08:00
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
this.$message.error(e)
|
2025-07-16 10:49:07 +08:00
|
|
|
this.message = ''
|
2025-07-15 13:59:05 +08:00
|
|
|
this.disabled = false
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading.close()
|
2025-07-15 13:59:05 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async _getLocalMaps () {
|
|
|
|
|
try {
|
|
|
|
|
let res = await getLocalMaps()
|
|
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
let flag = false
|
|
|
|
|
res.data.map(el => {
|
|
|
|
|
if (el.id === this.mapName) {
|
|
|
|
|
flag = true
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if (flag) {
|
|
|
|
|
clearInterval(this.intervalId) // 停止定时器
|
|
|
|
|
await this._oneClickDeployment()
|
|
|
|
|
} else {
|
|
|
|
|
const elapsedTime = Date.now() - this.startTime
|
|
|
|
|
if (elapsedTime >= 60000) { // 超过1分钟
|
|
|
|
|
clearInterval(this.intervalId) // 停止定时器
|
|
|
|
|
this.message = ''
|
|
|
|
|
this.$message.error('建图失败,请重新建图')
|
|
|
|
|
this.disabled = false
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading.close()
|
2025-07-15 13:59:05 +08:00
|
|
|
}
|
2025-07-14 17:52:37 +08:00
|
|
|
}
|
2025-07-15 13:59:05 +08:00
|
|
|
} else {
|
|
|
|
|
clearInterval(this.intervalId) // 停止定时器
|
|
|
|
|
this.message = ''
|
|
|
|
|
this.$message.error('建图失败,请重新建图')
|
|
|
|
|
this.disabled = false
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading.close()
|
2025-07-14 17:52:37 +08:00
|
|
|
}
|
|
|
|
|
} catch (e) {
|
2025-07-15 13:59:05 +08:00
|
|
|
clearInterval(this.intervalId) // 出错时停止定时器
|
|
|
|
|
this.message = ''
|
|
|
|
|
this.disabled = false
|
2025-07-14 17:52:37 +08:00
|
|
|
this.$message.error(e)
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading.close()
|
2025-07-14 17:52:37 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
async _oneClickDeployment () {
|
|
|
|
|
try {
|
|
|
|
|
let res = await oneClickDeployment(this.mapName)
|
2025-07-16 10:49:07 +08:00
|
|
|
if (res && res.code === 200) {
|
|
|
|
|
this.$message({
|
|
|
|
|
type: 'success',
|
|
|
|
|
message: res.message
|
|
|
|
|
})
|
2025-07-23 20:05:03 +08:00
|
|
|
this.needsConfirmation = false
|
2025-07-16 10:49:07 +08:00
|
|
|
this.$router.push('/index/home')
|
|
|
|
|
} else {
|
|
|
|
|
this.$message.error(res.message)
|
2025-07-14 09:28:21 +08:00
|
|
|
}
|
2025-07-16 10:49:07 +08:00
|
|
|
this.message = ''
|
|
|
|
|
this.disabled = false
|
|
|
|
|
this.loading.close()
|
2025-07-14 09:28:21 +08:00
|
|
|
} catch (e) {
|
|
|
|
|
this.$message.error(e)
|
2025-07-15 13:59:05 +08:00
|
|
|
this.message = ''
|
|
|
|
|
this.disabled = false
|
2025-07-16 10:49:07 +08:00
|
|
|
this.loading.close()
|
2025-07-04 17:52:10 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 放大
|
|
|
|
|
zoomIn () {
|
2025-07-15 13:59:05 +08:00
|
|
|
// this.scale += 0.1
|
|
|
|
|
// this.redrawCanvas()
|
2025-07-04 17:52:10 +08:00
|
|
|
},
|
|
|
|
|
// 缩小
|
|
|
|
|
zoomOut () {
|
2025-07-15 13:59:05 +08:00
|
|
|
// this.scale -= 0.1
|
|
|
|
|
// if (this.scale < 0.1) this.scale = 0.1 // 防止缩放到 0 或负值
|
|
|
|
|
// this.redrawCanvas()
|
2025-07-04 17:52:10 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="stylus" scoped>
|
|
|
|
|
.canvas-container
|
|
|
|
|
height calc(100% - 1rem)
|
|
|
|
|
margin .14rem 0
|
|
|
|
|
background-color rgba(0, 19, 48, 70%)
|
|
|
|
|
box-shadow inset 1px 1px 7px 2px #4d9bcd
|
|
|
|
|
overflow hidden
|
|
|
|
|
#canvas
|
|
|
|
|
width 100%
|
|
|
|
|
height 100%
|
2025-07-16 10:49:07 +08:00
|
|
|
.message
|
|
|
|
|
min-width 380px
|
|
|
|
|
border 1px solid #e1f3d8
|
|
|
|
|
border-radius 4px
|
2025-07-15 13:59:05 +08:00
|
|
|
position fixed
|
2025-07-16 10:49:07 +08:00
|
|
|
left 50%
|
|
|
|
|
top .87rem
|
|
|
|
|
transform translateX(-50%)
|
|
|
|
|
background-color #f0f9eb
|
|
|
|
|
transition opacity .3s,transform .4s
|
|
|
|
|
overflow hidden
|
|
|
|
|
padding 8px 15px
|
2025-07-15 13:59:05 +08:00
|
|
|
z-index 2025
|
|
|
|
|
display flex
|
|
|
|
|
align-items center
|
2025-07-16 10:49:07 +08:00
|
|
|
font-size .16rem
|
|
|
|
|
list-height 1
|
|
|
|
|
color #67C23A
|
|
|
|
|
p
|
|
|
|
|
margin-left 10px
|
|
|
|
|
.custom-message-enter, .custom-message-leave-to
|
|
|
|
|
opacity 0
|
|
|
|
|
transform translate(-50%,-100%)
|
2025-07-04 17:52:10 +08:00
|
|
|
</style>
|