一键标定、样式修改

This commit is contained in:
2026-01-19 16:49:48 +08:00
parent cf95d10458
commit 9ac5c2052a
9 changed files with 577 additions and 16 deletions

View File

@@ -54,4 +54,20 @@ export const backIoStatus = (type) => post('vehicle/setForkLegsObstacles?backIoS
// 获取当前配置的休息点
export const getReturnStation = () => get('station/getReturnStation', {})
// 配置车辆返回点
export const updateReturnStation = (id) => post('station/updateReturnStation?station_id=' + id, {})
export const updateReturnStation = (id) => post('station/updateReturnStation?station_id=' + id, {})
// 一键标定内容
export const getCalibrationConfigInfo = () => get('calibration/getCalibrationConfigInfo', {})
// 一键标定深度相机
export const calibrationDepthcamera = (id) => post('calibration/calibrationDepthcamera?location=' + id, {})
// 一键标定激光接口
export const calibrationLaser = (id, cmd) => post('calibration/calibrationLaser', {
location: id,
cmd: cmd
})
// 开始标定顶部相机
export const startCalibrationCamera = (id) => post('calibration/startCalibrationCamera?location=' + id, {})
// 结束标定顶部相机接口
export const endCalibrationCamera = (id, params) => post('calibration/endCalibrationCamera?location=' + id + '&params=' + params, {})
// 根据task_id查询对应的标定结果
export const getCalibrationByTaskId = (id) => get('calibration/getCalibrationByTaskId?task_id=' + id, {})

View File

@@ -891,4 +891,89 @@ export const apiLogs = () => {
}
]
return res
}
export const getCalibrationConfigInfo = () => {
let res = {
message: 'ok',
data: {
depthcamera: [
{
zh_name: '顶部前',
en_name: 'Top front',
location: '9'
},
{
zh_name: '右前',
en_name: 'Right front',
location: '9'
}
],
Laser: [
{
zh_name: '顶部前',
en_name: 'Top front',
location: '9'
},
{
zh_name: '右前',
en_name: 'Right front',
location: '9'
}
],
camera: [
{
zh_name: '右前',
en_name: 'Right front',
location: '9'
}
]
}
}
return res
}
export const calibrationDepthcamera = () => {
let res = {
"message": "操作成功!",
"data": {
"task_id": "20260107173429562"
}
}
return res
}
export const calibrationLaser = () => {
let res = {
"message": "操作成功!",
"data": {
"task_id": "20260107173429562"
}
}
return res
}
export const startCalibrationCamera = () => {
let res = {
"message": "操作成功!",
"data": {
"task_id": "20260107173429562"
}
}
return res
}
export const endCalibrationCamera = () => {
let res = {
"message": "操作成功!",
"data": {
"task_id": "20260107173429562"
}
}
return res
}
export const getCalibrationByTaskId = () => {
let res = {
"message": "操作成功!",
"data": "1"
}
return res
}

View File

@@ -143,5 +143,20 @@ module.exports = {
settings: 'Settings',
entertaskchainname: 'Please enter the task chain name',
taskchainnotempty: 'The task chain name cannot be empty',
taskchainname: 'Task Chain Name'
taskchainname: 'Task Chain Name',
depthcamera: 'Depth Camera',
horizontalandheightcalibration: 'Horizontal and Height Calibration',
laser: 'Laser',
calibrationorientation: 'Calibration Orientation',
calibrationposition: 'Calibration Position',
topviewcamera: 'Top - view Camera',
startcalibration: 'Start Calibration',
endcalibration: 'End Calibration',
ceilingheight: 'Ceiling Height',
collectingdata: 'Collecting Data',
calibrationtimeoutpleasereoperate: 'Calibration Timeout. Please Re - operate',
calibrationsuccessful: 'Calibration Successful',
calibrationfailed: 'Calibration Failed',
calibrationresultabnormal: 'Calibration Result Abnormal',
calibrationprogramabnormal: 'Calibration Program Abnormal'
}

View File

@@ -143,5 +143,20 @@ module.exports = {
settings: '设置',
entertaskchainname: '请输入任务链名称',
taskchainnotempty: '任务链名称不能为空',
taskchainname: '任务链名称'
taskchainname: '任务链名称',
depthcamera: '深度相机',
horizontalandheightcalibration: '水平和高度标定',
laser: '激光',
calibrationorientation: '标定朝向',
calibrationposition: '标定位置',
topviewcamera: '顶视相机',
startcalibration: '开始标定',
endcalibration: '结束标定',
ceilingheight: '天花板高度',
collectingdata: '采集数据中',
calibrationtimeoutpleasereoperate: '标定超时,请重新操作',
calibrationsuccessful: '标定成功',
calibrationfailed: '标定失败',
calibrationresultabnormal: '标定结果异常',
calibrationprogramabnormal: '标定程序异常'
}

BIN
src/images/new/RF7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,412 @@
<template>
<div class="page_container" :class="{'enClass': $i18n.locale === 'en-us'}">
<div v-if="depthcamera.length" class="feat-item-wrap">
<div class="feat-title">{{$t('depthcamera')}}</div>
<el-row type="flex" justify="space-between">
<el-col class="feat-item" v-for="(e, i) in depthcamera" :key="i">
<div v-if="$i18n.locale === 'en-us'" class="feat-name">{{ e.en_name }}&nbsp;{{$t('depthcamera')}}</div>
<div v-else class="feat-name">{{ e.zh_name }}{{$t('depthcamera')}}</div>
<el-row type="flex" justify="start">
<el-button type="success" :disabled="disabled1" @click="_calibrationDepthcamera(e.location)">{{ $t('horizontalandheightcalibration') }}</el-button>
</el-row>
</el-col>
</el-row>
</div>
<div v-if="Laser.length" class="feat-item-wrap">
<div class="feat-title">{{ $t('laser') }}</div>
<el-row type="flex" justify="space-between">
<el-col class="feat-item" v-for="(e, i) in Laser" :key="i">
<div v-if="$i18n.locale === 'en-us'" class="feat-name">{{ e.en_name }}&nbsp;{{ $t('laser') }}</div>
<div v-else class="feat-name">{{ e.zh_name }}{{ $t('laser') }}</div>
<el-row type="flex" justify="start">
<el-button type="success" :disabled="disabled2 && cmd === 1802" @click="_calibrationLaser(e.location, 1802)">{{ $t('calibrationorientation') }}</el-button>
<el-button type="success" :disabled="disabled3 && cmd === 1803" @click="_calibrationLaser(e.location, 1803)">{{ $t('calibrationposition') }}</el-button>
</el-row>
</el-col>
</el-row>
</div>
<div v-if="camera.length" class="feat-item-wrap">
<div class="feat-title">{{ $t('topviewcamera') }}</div>
<el-row type="flex" justify="space-between">
<el-col class="relative feat-item" v-for="(e, i) in camera" :key="i">
<div v-if="$i18n.locale === 'en-us'" class="feat-name feat-name1">{{ e.en_name }}&nbsp;{{ $t('topviewcamera') }}</div>
<div v-else class="feat-name">{{ e.zh_name }}{{ $t('topviewcamera') }}</div>
<el-row type="flex" justify="start">
<el-button type="success" :disabled="disabled4" @click="_startCalibrationCamera(e.location)">{{ $t('startcalibration') }}</el-button>
<el-button type="success" :disabled="disabled5" @click="_endCalibrationCamera(e.location, size)">{{$t('endcalibration')}}</el-button>
</el-row>
<div class="absolute size-wrap">
<span class="txt1">{{ $t('ceilingheight') }}</span>
<el-input class="h-input" type="number" size="mini" v-model="size"></el-input>
<span class="txt2">m</span>
</div>
</el-col>
</el-row>
</div>
<div v-if="dialogVisible" class="progress-mask" style="z-index: 2003;">
<div class="progress-container">
<div class="progress_tip">
{{ $t('collectingdata') }}
<span class="dots">
<span class="dot dot1">.</span>
<span class="dot dot2">.</span>
<span class="dot dot3">.</span>
<span class="dot dot4">.</span>
</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { getCalibrationConfigInfo, calibrationDepthcamera, calibrationLaser, startCalibrationCamera, endCalibrationCamera, getCalibrationByTaskId } from '@/config/mork.js'
export default {
name: 'calibration-index',
data () {
return {
depthcamera: [],
Laser: [],
camera: [],
size: 5,
disabled1: false,
disabled2: false,
disabled3: false,
disabled4: false,
disabled5: true,
cmd: null,
taskId: null,
timer: null,
isPolling: false,
dialogVisible: false
}
},
mounted () {
this._getCalibrationConfigInfo()
},
beforeDestroy() {
this._clearTimer()
},
methods: {
_clearTimer() {
this.isPolling = false
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
async _pollTaskStatus(type) {
if (!this.taskId) return
this._clearTimer()
this.isPolling = true
this.timer = setInterval(async () => {
if (!this.isPolling) return
try {
const res = await getCalibrationByTaskId(this.taskId)
if (!this.isPolling) return
if (res && res.data) {
const status = res.data
this._handleTaskStatus(status, type)
}
} catch (e) {
console.error('轮询任务状态失败:', e)
}
}, 1000)
setTimeout(() => {
if (this.isPolling) {
this.isPolling = false
this._clearTimer()
this.dialogVisible = false
this.$message.warning(this.$t('calibrationtimeoutpleasereoperate'))
if (type === 'end') {
this.disabled4 = true
this.disabled5 = false
}
}
}, 60000)
},
_handleTaskStatus(status, type) {
if (!this.isPolling) return
switch(status.toString()) {
case '0': // 标定成功
this.isPolling = false
this._clearTimer()
this.dialogVisible = false
this.$message.success(this.$t('calibrationsuccessful'))
if (type === 'end') {
this.disabled4 = false
this.disabled5 = true
}
break
case '1': // 采集数据中
this.dialogVisible = true
break
case '2': // 标定失败
this.isPolling = false
this._clearTimer()
this.dialogVisible = false
this.$message.error(this.$t('calibrationfailed'))
if (type === 'end') {
this.disabled4 = true
this.disabled5 = false
}
break
case '3': // 结果异常
this.isPolling = false
this._clearTimer()
this.dialogVisible = false
this.$message.error(this.$t('calibrationresultabnormal'))
if (type === 'end') {
this.disabled4 = true
this.disabled5 = false
}
break
case '999': // 标定程序异常
this.isPolling = false
this._clearTimer()
this.dialogVisible = false
this.$message.error(this.$t('calibrationprogramabnormal'))
if (type === 'end') {
this.disabled4 = true
this.disabled5 = false
}
break
default:
console.warn('未知状态码:', status)
}
},
async _getCalibrationConfigInfo () {
try {
let res = await getCalibrationConfigInfo()
if (res && res.data) {
this.depthcamera = [...res.data.depthcamera]
this.Laser = [...res.data.Laser]
this.camera = [...res.data.camera]
}
} catch (e) {
this.depthcamera = []
this.Laser = []
this.camera = []
this.$message.error(e)
}
},
async _calibrationDepthcamera (lock) {
this.disabled1 = true
try {
this.loading = this.$loading({
lock: true,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.6)'
})
let res = await calibrationDepthcamera(lock)
if (res) {
this.taskId = res.data.task_id
this._pollTaskStatus()
}
this.loading.close()
this.disabled1 = false
} catch (e) {
this.$message.error(e)
this.loading.close()
this.disabled1 = false
}
},
async _calibrationLaser (lock, cmd) {
this.disabled2 = true
this.disabled3 = true
this.cmd = cmd
try {
this.loading = this.$loading({
lock: true,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.6)'
})
let res = await calibrationLaser(lock, cmd)
if (res) {
this.taskId = res.data.task_id
this._pollTaskStatus()
}
this.loading.close()
this.disabled2 = false
this.disabled3 = false
} catch (e) {
this.$message.error(e)
this.loading.close()
this.disabled2 = false
this.disabled3 = false
}
},
async _startCalibrationCamera (lock) {
this.disabled4 = true
try {
this.loading = this.$loading({
lock: true,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.6)'
})
let res = await startCalibrationCamera(lock)
if (res) {
this.$message(res.message)
}
this.loading.close()
this.disabled5 = false
} catch (e) {
this.$message.error(e)
this.loading.close()
this.disabled4 = false
}
},
async _endCalibrationCamera (lock, size) {
this.disabled5 = true
try {
this.loading = this.$loading({
lock: true,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.6)'
})
let res = await endCalibrationCamera(lock, size)
if (res) {
this.taskId = res.data.task_id
this._pollTaskStatus('end')
}
this.loading.close()
} catch (e) {
this.$message.error(e)
this.loading.close()
this.disabled5 = false
}
}
}
}
</script>
<style lang="stylus" scoped>
.page_container
padding: 0.1rem;
overflow-y auto
.feat-item-wrap
padding-bottom 0.34rem
border-bottom 1px solid #8a8a8a
+.feat-item-wrap
margin-top .3rem
&:last-child
border-bottom 0
.feat-title
font-size .25rem
color #fff
margin-bottom .2rem
.feat-item
width 48.6%
padding .16rem .2rem
border-radius .15rem
background-color rgba(38,49,76,0.7)
.feat-name
font-size .18rem
line-height .2rem
color #fff
margin-bottom .2rem
.size-wrap
top .1rem
right .1rem
.txt1
font-size .16rem
line-height .4rem
color #fff
.txt2
font-size .16rem
line-height .4rem
color #fff
margin-left .1rem
.h-input
width 1rem
line-height: 0.36rem;
height: 0.36rem;
margin-left .1rem
/deep/ .el-input__inner
line-height: 0.36rem;
height: 0.36rem;
background: rgba(230, 230, 230, 10%);
border-color: #fff;
border-radius: 0.05rem;
.el-button
padding 0.09rem 0.1rem
.progress-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6); /* 半透明黑色遮罩 */
z-index: 9999; /* 确保在最上层 */
display: flex;
justify-content: center;
align-items: center;
}
.progress-container {
background-color: #fff;
padding: 30px 40px;
border-radius: 8px;
text-align: center;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.progress_tip {
font-size: .2rem
line-height: .34rem
color: #000
font-weight: 700
}
.el-button
height .4rem
line-height 1
.el-button--success {
color: #FFF;
background-color: #67C23A;
border-color: #67C23A;
}
.el-button--success.is-disabled, .el-button--success.is-disabled:active, .el-button--success.is-disabled:focus, .el-button--success.is-disabled:hover {
color: #FFF;
background-color: #b3e19d;
border-color: #b3e19d;
}
.dots
display: inline-block;
.dot
opacity: 0;
animation: dotFade 1.5s infinite;
.dot1
animation-delay: 0.1s;
.dot2
animation-delay: 0.2s;
.dot3
animation-delay: 0.3s;
.dot4
animation-delay: 0.4s;
@keyframes dotFade
0%
opacity: 0;
20%
opacity: 1;
40%
opacity: 1;
60%
opacity: 1;
80%
opacity: 1;
100%
opacity: 0;
.enClass
.feat-name1
width 50%
</style>

View File

@@ -2,7 +2,7 @@
<el-row type="flex" class="navs_wraper" justify="start" align="middle">
<el-col class="nav_item" v-for="(e, i) in visibleNav" :key="i" :class="'nav_item_' + (i + 1)">
<div class="nav_item_i" @click="toPage(e)">
<div class="nav_icon"></div>
<div class="nav_icon"><img :src="require('@/images/new/' + e.icon + '.png')" alt=""></div>
<p>{{ e[$langPre.computedProp('title')] }}</p>
</div>
</el-col>
@@ -22,10 +22,11 @@ export default {
...mapGetters(['userRole']),
nav () {
return [
{ title: '操作', zh_title: '操作', en_title: 'Operate', router: '/index/device', isVisible: true },
{ title: '建图', zh_title: '建图', en_title: 'Map - building', router: '/index/building', isVisible: this.userRole === 1 },
{ title: '地图', zh_title: '地图', en_title: 'Map', router: '/index/map', isVisible: true },
{ title: '重定位', zh_title: '重定位', en_title: 'Relocate', router: '/index/relocation', isVisible: true }
{ title: '操作', zh_title: '操作', en_title: 'Operate', router: '/index/device', icon: 'RF1', isVisible: true },
{ title: '建图', zh_title: '建图', en_title: 'Map - building', router: '/index/building', icon: 'RF2', isVisible: this.userRole === 1 },
{ title: '地图', zh_title: '地图', en_title: 'Map', router: '/index/map', icon: 'RF3', isVisible: true },
{ title: '重定位', zh_title: '重定位', en_title: 'Relocate', router: '/index/relocation', icon: 'RF4', isVisible: true },
{ title: '一键标定', zh_title: '一键标定', en_title: 'One - Click Calibration', router: '/index/calibration', icon: 'RF7', isVisible: true }
]
},
visibleNav () {
@@ -92,26 +93,37 @@ export default {
line-height 1
color #F6F9FE
font-family 'YouSheBiaoTiHei'
text-align center
background linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(49,190,255,0.9) 0%, rgba(239,252,254,1) 40%)
-webkit-background-clip: text
-webkit-text-fill-color: transparent
.nav_icon
position relative
width 35%
padding-top 35%
border-radius 50%
margin-bottom 3%
img
position absolute
width 70%
top 50%
left 50%
transform translate(-50%, -50%)
.nav_item_1
.nav_icon
background #217872 center center / 70% auto url(../../images/new/RF1.png) no-repeat
background linear-gradient(90deg, rgba(130, 234, 143, 60%), rgba(0, 185, 81, 80%))
.nav_item_2
.nav_icon
background #80732F center center / 70% auto url(../../images/new/RF2.png) no-repeat
background linear-gradient(90deg, rgba(255, 212, 153, 60%), rgba(255, 144, 25, 80%))
.nav_item_3
.nav_icon
background #00a9ff center center / 70% auto url(../../images/new/RF3.png) no-repeat
background linear-gradient(90deg, rgba(120, 173, 255, 60%), rgba(52, 92, 248, 80%))
.nav_item_4
.nav_icon
background #80372D center center / 70% auto url(../../images/new/RF4.png) no-repeat
background linear-gradient(90deg, rgba(255, 125, 119, 60%), rgba(255, 84, 47, 80%))
.nav_item_5
.nav_icon
background linear-gradient(90deg, rgba(206, 149, 255, 60%), rgba(124, 47, 255, 80%))
.enClass
.nav_item_i
p

View File

@@ -288,10 +288,11 @@ export default {
background linear-gradient(0deg, #E64F29, rgba(230, 79, 41, 0.5))
border-color rgba(230, 79, 41, 0.7)
.state-item
_wh(1rem, .3rem)
height .3rem
_font(.18rem,.3rem,#fff,,center)
font-family 'Adobe Heiti Std'
margin-right .08rem
padding 0 .06rem
background center / 100% 100% url(../../images/new/state-item_bg.png) no-repeat
box-shadow inset 0px 0px 3px 2px rgb(149, 221, 253, 70%)
overflow hidden
@@ -340,11 +341,12 @@ export default {
white-space nowrap
background-color rgba(253, 246, 236, .4)
.scroll-text
display inline-block
text-align center
display flex
align-items center
justify-content center
animation none
.icon-warning
font-size .18rem
font-size .24rem
color #e6bb3c
margin-right .05rem
.error-tips-t

View File

@@ -8,6 +8,7 @@ const Warning = r => require.ensure([], () => r(require('../pages/modules/warn/i
const Building = r => require.ensure([], () => r(require('../pages/modules/build/index.vue')), 'Building')
const Map = r => require.ensure([], () => r(require('../pages/modules/map/index.vue')), 'Map')
const Relocation = r => require.ensure([], () => r(require('../pages/modules/relocation.vue')), 'Relocation')
const Calibration = r => require.ensure([], () => r(require('../pages/modules/calibration/index.vue')), 'Calibration')
const Login = r => require.ensure([], () => r(require('../pages/modules/login/index.vue')), 'login')
const IndexHub = r => require.ensure([], () => r(require('../pages/modules/hub/index.vue')), 'IndexHub')
const Upload = r => require.ensure([], () => r(require('../pages/modules/hub/upload.vue')), 'Upload')
@@ -41,6 +42,9 @@ const router = new VueRouter({
}, {
path: 'relocation',
component: Relocation
}, {
path: 'calibration',
component: Calibration
}]
},
{