feat: 拦截跳转
This commit is contained in:
parent
ab98000ab1
commit
2d12fc3f89
3
components.d.ts
vendored
3
components.d.ts
vendored
@ -17,6 +17,8 @@ declare module 'vue' {
|
||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||
ElForm: typeof import('element-plus/es')['ElForm']
|
||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
@ -34,6 +36,7 @@ declare module 'vue' {
|
||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||
ElTag: typeof import('element-plus/es')['ElTag']
|
||||
HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
|
||||
IPlayer: typeof import('./src/components/IPlayer/index.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
"@element-plus/icons-vue": "^2.3.2",
|
||||
"@grpc/grpc-js": "^1.14.4",
|
||||
"@grpc/proto-loader": "^0.8.1",
|
||||
"autofit.js": "^3.2.8",
|
||||
"concurrently": "^10.0.3",
|
||||
"cors": "^2.8.6",
|
||||
"dotenv": "^17.4.2",
|
||||
@ -27,7 +28,8 @@
|
||||
"urdf-loader": "^0.12.6",
|
||||
"vue": "^3.5.38",
|
||||
"vue-router": "^5.1.0",
|
||||
"xacro-parser": "^0.3.11"
|
||||
"xacro-parser": "^0.3.11",
|
||||
"xgplayer": "^3.0.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.7",
|
||||
|
||||
130
pnpm-lock.yaml
generated
130
pnpm-lock.yaml
generated
@ -17,6 +17,9 @@ importers:
|
||||
'@grpc/proto-loader':
|
||||
specifier: ^0.8.1
|
||||
version: 0.8.1
|
||||
autofit.js:
|
||||
specifier: ^3.2.8
|
||||
version: 3.2.8
|
||||
concurrently:
|
||||
specifier: ^10.0.3
|
||||
version: 10.0.3
|
||||
@ -56,6 +59,9 @@ importers:
|
||||
xacro-parser:
|
||||
specifier: ^0.3.11
|
||||
version: 0.3.11
|
||||
xgplayer:
|
||||
specifier: ^3.0.24
|
||||
version: 3.0.24(core-js@3.49.0)
|
||||
devDependencies:
|
||||
'@vitejs/plugin-vue':
|
||||
specifier: ^6.0.7
|
||||
@ -586,6 +592,9 @@ packages:
|
||||
engines: {node: '>= 4.5.0'}
|
||||
hasBin: true
|
||||
|
||||
autofit.js@3.2.8:
|
||||
resolution: {integrity: sha512-albZNwDIXvcRneEDyZLW3uAIOH0cUQG/TnCGQ7jpfnL0gPn/+1ZNVRuEz3ZuzZvVkQ4HQRplGHjUeMRtPNxjLQ==}
|
||||
|
||||
available-typed-arrays@1.0.7:
|
||||
resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -723,6 +732,9 @@ packages:
|
||||
resolution: {integrity: sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
core-js@3.49.0:
|
||||
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
|
||||
|
||||
cors@2.8.6:
|
||||
resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@ -769,6 +781,13 @@ packages:
|
||||
csstype@3.2.3:
|
||||
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
||||
|
||||
d@1.0.2:
|
||||
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
danmu.js@1.2.1:
|
||||
resolution: {integrity: sha512-evDEImUBo94c846fC92K//Dzll8jXnZ3zKmYlQHwMzmvw6IW2IyjWL3Ew2SqEAzuqauFnDkwJEgZauu3uW/p1Q==}
|
||||
|
||||
data-view-buffer@1.0.2:
|
||||
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -828,6 +847,9 @@ packages:
|
||||
defu@6.1.7:
|
||||
resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
|
||||
|
||||
delegate@3.2.0:
|
||||
resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==}
|
||||
|
||||
depd@2.0.0:
|
||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -943,6 +965,17 @@ packages:
|
||||
resolution: {integrity: sha512-CxN9N56HYfd2m/acc/NOFrZQsN9kU4eh+2kk6A707Kz1krH8tKmfrs5RnftB8WNX80T0NS7vSQsDOlg23diR2g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
es5-ext@0.10.64:
|
||||
resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==}
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==}
|
||||
engines: {node: '>=0.12'}
|
||||
|
||||
escalade@3.2.0:
|
||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||
engines: {node: '>=6'}
|
||||
@ -958,6 +991,10 @@ packages:
|
||||
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
esniff@2.0.1:
|
||||
resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==}
|
||||
engines: {node: '>=0.10'}
|
||||
|
||||
estree-walker@2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
|
||||
@ -968,6 +1005,12 @@ packages:
|
||||
resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
event-emitter@0.3.5:
|
||||
resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
|
||||
|
||||
eventemitter3@4.0.7:
|
||||
resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
|
||||
|
||||
expand-brackets@2.1.4:
|
||||
resolution: {integrity: sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -983,6 +1026,9 @@ packages:
|
||||
exsolve@1.1.0:
|
||||
resolution: {integrity: sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw==}
|
||||
|
||||
ext@1.7.0:
|
||||
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
|
||||
|
||||
extend-shallow@2.0.1:
|
||||
resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -1594,6 +1640,9 @@ packages:
|
||||
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
next-tick@1.1.0:
|
||||
resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
@ -2100,6 +2149,9 @@ packages:
|
||||
resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
type@2.7.3:
|
||||
resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==}
|
||||
|
||||
typed-array-buffer@1.0.3:
|
||||
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2324,6 +2376,16 @@ packages:
|
||||
xacro-parser@0.3.11:
|
||||
resolution: {integrity: sha512-zyRzHmf6/BySLZQP77zp6iEtdryq1g7tWtfwj/28GOPyf9ijtPvouivOAeaA/yAu0/Bwh20DtA4x+BrYiV6qKQ==}
|
||||
|
||||
xgplayer-subtitles@3.0.24:
|
||||
resolution: {integrity: sha512-yrHROepD9kTGWiTSxBjh+TGaK9orQOHQ1GUxWFOkQzO8BLl/pcIAqqJkHiAoP0j+eU8VdIhpb55oJRIkTTWPsA==}
|
||||
peerDependencies:
|
||||
core-js: '>=3.12.1'
|
||||
|
||||
xgplayer@3.0.24:
|
||||
resolution: {integrity: sha512-rK3hoJ+1Pbl9PUCHgeJv1GnOQF28BKLQFTBxdvi0pHsibJeXaDUf51SLFcgNVAPN15aDYcjJgaSf7LQ0RfEFPQ==}
|
||||
peerDependencies:
|
||||
core-js: '>=3.12.1'
|
||||
|
||||
y18n@5.0.8:
|
||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -2811,6 +2873,8 @@ snapshots:
|
||||
|
||||
atob@2.1.2: {}
|
||||
|
||||
autofit.js@3.2.8: {}
|
||||
|
||||
available-typed-arrays@1.0.7:
|
||||
dependencies:
|
||||
possible-typed-array-names: 1.1.0
|
||||
@ -2976,6 +3040,8 @@ snapshots:
|
||||
|
||||
copy-descriptor@0.1.1: {}
|
||||
|
||||
core-js@3.49.0: {}
|
||||
|
||||
cors@2.8.6:
|
||||
dependencies:
|
||||
object-assign: 4.1.1
|
||||
@ -3035,6 +3101,15 @@ snapshots:
|
||||
|
||||
csstype@3.2.3: {}
|
||||
|
||||
d@1.0.2:
|
||||
dependencies:
|
||||
es5-ext: 0.10.64
|
||||
type: 2.7.3
|
||||
|
||||
danmu.js@1.2.1:
|
||||
dependencies:
|
||||
event-emitter: 0.3.5
|
||||
|
||||
data-view-buffer@1.0.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.4
|
||||
@ -3092,6 +3167,8 @@ snapshots:
|
||||
|
||||
defu@6.1.7: {}
|
||||
|
||||
delegate@3.2.0: {}
|
||||
|
||||
depd@2.0.0: {}
|
||||
|
||||
detect-libc@2.1.2: {}
|
||||
@ -3278,6 +3355,24 @@ snapshots:
|
||||
is-date-object: 1.1.0
|
||||
is-symbol: 1.1.1
|
||||
|
||||
es5-ext@0.10.64:
|
||||
dependencies:
|
||||
es6-iterator: 2.0.3
|
||||
es6-symbol: 3.1.4
|
||||
esniff: 2.0.1
|
||||
next-tick: 1.1.0
|
||||
|
||||
es6-iterator@2.0.3:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
es6-symbol: 3.1.4
|
||||
|
||||
es6-symbol@3.1.4:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
ext: 1.7.0
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
escape-html@1.0.3: {}
|
||||
@ -3286,6 +3381,13 @@ snapshots:
|
||||
|
||||
escape-string-regexp@5.0.0: {}
|
||||
|
||||
esniff@2.0.1:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
event-emitter: 0.3.5
|
||||
type: 2.7.3
|
||||
|
||||
estree-walker@2.0.2: {}
|
||||
|
||||
estree-walker@3.0.3:
|
||||
@ -3294,6 +3396,13 @@ snapshots:
|
||||
|
||||
etag@1.8.1: {}
|
||||
|
||||
event-emitter@0.3.5:
|
||||
dependencies:
|
||||
d: 1.0.2
|
||||
es5-ext: 0.10.64
|
||||
|
||||
eventemitter3@4.0.7: {}
|
||||
|
||||
expand-brackets@2.1.4:
|
||||
dependencies:
|
||||
debug: 2.6.9
|
||||
@ -3343,6 +3452,10 @@ snapshots:
|
||||
|
||||
exsolve@1.1.0: {}
|
||||
|
||||
ext@1.7.0:
|
||||
dependencies:
|
||||
type: 2.7.3
|
||||
|
||||
extend-shallow@2.0.1:
|
||||
dependencies:
|
||||
is-extendable: 0.1.1
|
||||
@ -3945,6 +4058,8 @@ snapshots:
|
||||
|
||||
negotiator@1.0.0: {}
|
||||
|
||||
next-tick@1.1.0: {}
|
||||
|
||||
node-addon-api@7.1.1:
|
||||
optional: true
|
||||
|
||||
@ -4558,6 +4673,8 @@ snapshots:
|
||||
media-typer: 1.1.0
|
||||
mime-types: 3.0.2
|
||||
|
||||
type@2.7.3: {}
|
||||
|
||||
typed-array-buffer@1.0.3:
|
||||
dependencies:
|
||||
call-bound: 1.0.4
|
||||
@ -4837,6 +4954,19 @@ snapshots:
|
||||
yaml: 2.9.0
|
||||
yargs: 17.7.3
|
||||
|
||||
xgplayer-subtitles@3.0.24(core-js@3.49.0):
|
||||
dependencies:
|
||||
core-js: 3.49.0
|
||||
eventemitter3: 4.0.7
|
||||
|
||||
xgplayer@3.0.24(core-js@3.49.0):
|
||||
dependencies:
|
||||
core-js: 3.49.0
|
||||
danmu.js: 1.2.1
|
||||
delegate: 3.2.0
|
||||
eventemitter3: 4.0.7
|
||||
xgplayer-subtitles: 3.0.24(core-js@3.49.0)
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
||||
yaml@2.9.0: {}
|
||||
|
||||
@ -56,6 +56,7 @@ const init = () => {
|
||||
|
||||
.xgplayer {
|
||||
height: 100% !important;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
// 页面组件
|
||||
import Home from '@/views/Home.vue'
|
||||
import Address from '@/views/Address.vue'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/home'
|
||||
path: '/',e: 'Address',
|
||||
component: Address
|
||||
},
|
||||
{
|
||||
path: '/home',
|
||||
|
||||
82
src/views/Address.vue
Normal file
82
src/views/Address.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="title">设备连接登录</div>
|
||||
<div class="secondaryTitle">请输入IP和端口连接后进入上位机页面</div>
|
||||
<div class="form">
|
||||
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto">
|
||||
<el-form-item label="" prop="ip">
|
||||
<el-input v-model="ruleForm.ip" style="width: 240px" placeholder="请输入IP" >
|
||||
<template #append>
|
||||
<el-button @click="testConnect">➡</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<!-- <el-button @click="testConnect">➡</el-button> -->
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getCurrentMapName } from '@/api/agv.js'
|
||||
import { useRobotStore } from '@/stores/robot'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const robotStore = useRobotStore()
|
||||
|
||||
const ruleFormRef = ref()
|
||||
const ruleForm = ref({
|
||||
ip: '',
|
||||
port: 80
|
||||
})
|
||||
|
||||
const rules = ref({
|
||||
ip: [
|
||||
{ required: true, message: '请输入机器人IP和端口', trigger: 'blur' }
|
||||
],
|
||||
})
|
||||
|
||||
const testConnect = async () => {
|
||||
const valid = await ruleFormRef.value.validate();
|
||||
if (valid) {
|
||||
const result = await getCurrentMapName({
|
||||
ip: robotStore.ip,
|
||||
deviceId: VITE_DEVICE_ID,
|
||||
})
|
||||
if (result.code === 200) {
|
||||
router.push({
|
||||
path: '/home',
|
||||
query: {
|
||||
mapName: result.data.current_map
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
|
||||
.title {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.secondaryTitle {
|
||||
font-size: 14px;
|
||||
color: #8f8f8f;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,8 +1,9 @@
|
||||
<template>
|
||||
<div class="common-layout">
|
||||
<el-container>
|
||||
<el-header>
|
||||
<div class="header-container">
|
||||
<el-header>
|
||||
<div class="header-container">
|
||||
<div class="back" @click="back">< 返回</div>
|
||||
<div class="left">
|
||||
<div class="date">
|
||||
<div>{{ currentTime }}</div>
|
||||
@ -16,14 +17,15 @@
|
||||
<div class="btn-container">
|
||||
<button class="nav-btn" :class="{ active: activePage === 'chassis' }" @click="handleBtn('chassis')">底盘控制</button>
|
||||
<button class="nav-btn" :class="{ active: activePage === 'mechanicalArm' }" @click="handleBtn('mechanicalArm')">机械臂控制</button>
|
||||
<button class="nav-btn" :class="{ active: activePage === 'manualTakeover' }" @click="handleBtn('manualTakeover')">相机</button>
|
||||
<button class="nav-btn" :class="{ active: activePage === 'camera' }" @click="handleBtn('camera')">相机</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<Chassis v-if="activePage === 'chassis'" />
|
||||
<Chassis :mapName="mapName" v-if="activePage === 'chassis'" />
|
||||
<MechanicalArm v-if="activePage === 'mechanicalArm'" />
|
||||
<Camera v-if="activePage === 'camera'" />
|
||||
</el-main>
|
||||
</el-container>
|
||||
</div>
|
||||
@ -31,6 +33,14 @@
|
||||
<script setup>
|
||||
import Chassis from './chassis/Chassis.vue';
|
||||
import MechanicalArm from './arm/MechanicalArm.vue';
|
||||
import Camera from './camera/index.vue'
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import autofit from 'autofit.js'
|
||||
autofit.init()
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const currentTime = ref('')
|
||||
const weekText = ref('')
|
||||
@ -63,15 +73,21 @@ const animateBinary = () => {
|
||||
const activePage = ref('chassis')
|
||||
const handleBtn = (page) => {
|
||||
activePage.value = page
|
||||
// emits("activePage", page);
|
||||
}
|
||||
|
||||
const back = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
const mapName = ref('')
|
||||
|
||||
let clockTimer, binaryTimer;
|
||||
onMounted(() => {
|
||||
updateClock();
|
||||
clockTimer = setInterval(updateClock, 1000);
|
||||
animateBinary()
|
||||
binaryTimer = setInterval(animateBinary, 400);
|
||||
mapName.value = route.query.mapName
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@ -100,6 +116,13 @@ onUnmounted(() => {
|
||||
gap: 20px;
|
||||
margin: 0 20px;
|
||||
|
||||
.back {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #00c2ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.left {
|
||||
flex: 1;
|
||||
@ -172,7 +195,7 @@ onUnmounted(() => {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'Orbitron', monospace;
|
||||
font-size: 10px;
|
||||
font-size: 14px;
|
||||
color: #00c2ff4d;
|
||||
letter-spacing: 2px;
|
||||
white-space: nowrap;
|
||||
|
||||
@ -268,6 +268,11 @@ onMounted(() => {
|
||||
border-radius: 5px;
|
||||
background: #0a0b10;
|
||||
|
||||
&:hover {
|
||||
border-color: #2a3f7a;
|
||||
background: rgba(59, 130, 246, 0.031372549);
|
||||
}
|
||||
|
||||
label {
|
||||
width: 120px;
|
||||
font-size: 16px;
|
||||
|
||||
@ -13,6 +13,18 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
||||
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
|
||||
|
||||
import { XacroAdapter } from '@/adapters/XacroAdapter.js'
|
||||
import { fileNameMap } from './config'
|
||||
|
||||
const props = defineProps({
|
||||
filePath: {
|
||||
type: String,
|
||||
default: '/inspection/elfin10/'
|
||||
},
|
||||
fileName: {
|
||||
type: String,
|
||||
default: 'elfin10.urdf.xacro'
|
||||
}
|
||||
})
|
||||
|
||||
const viewerContainer = ref(null);
|
||||
|
||||
@ -26,41 +38,32 @@ const initScene = () => {
|
||||
const container = viewerContainer.value;
|
||||
const width = container.clientWidth || 800;
|
||||
const height = container.clientHeight || 600;
|
||||
|
||||
scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color('#060a12');
|
||||
camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
|
||||
camera.position.set(2, 2, 3);
|
||||
|
||||
camera = new THREE.PerspectiveCamera(35, width / height, 0.1, 1000);
|
||||
camera.position.set(0, 0, 4);
|
||||
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
|
||||
renderer.setSize(width, height);
|
||||
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
|
||||
renderer.shadowMap.enabled = true;
|
||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
renderer.toneMappingExposure = 1.2;
|
||||
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true;
|
||||
controls.dampingFactor = 0.1;
|
||||
controls.target.set(0, 0.5, 0);
|
||||
controls.update();
|
||||
|
||||
const ambient = new THREE.AmbientLight(0x404060, 0.6);
|
||||
const ambient = new THREE.AmbientLight(0xffffff, 0.6)
|
||||
scene.add(ambient);
|
||||
const main = new THREE.DirectionalLight(0xffffff, 1.0);
|
||||
main.position.set(5, 10, 7);
|
||||
main.castShadow = true;
|
||||
scene.add(main);
|
||||
const fill = new THREE.DirectionalLight(0x8888ff, 0.4);
|
||||
fill.position.set(-5, 0, 5);
|
||||
scene.add(fill);
|
||||
const rim = new THREE.DirectionalLight(0xffffff, 0.3);
|
||||
rim.position.set(0, -5, 5);
|
||||
scene.add(rim);
|
||||
// const grid = new THREE.GridHelper(3, 20, 0x444466, 0x333355);
|
||||
// grid.position.y = -0.5;
|
||||
// scene.add(grid);
|
||||
};
|
||||
|
||||
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
|
||||
directionalLight.position.set(5, 10, 7);
|
||||
directionalLight.castShadow = true;
|
||||
scene.add(directionalLight);
|
||||
};
|
||||
|
||||
// ============ 关节控制(无需修改) ============
|
||||
const updateJoint = (jointName, angle) => {
|
||||
@ -94,28 +97,16 @@ const resetJoints = () => {
|
||||
|
||||
const fileMap = new Map()
|
||||
const loadFiles = async () => {
|
||||
const fileNames = [
|
||||
'elfin10.urdf.xacro',
|
||||
'elfin10_gazebo.xacro',
|
||||
'elfin10_transmission.xacro',
|
||||
'meshes/elfin10/elfin_base.STL',
|
||||
'meshes/elfin10/elfin_end_link.STL',
|
||||
'meshes/elfin10/elfin_link1.STL',
|
||||
'meshes/elfin10/elfin_link2.STL',
|
||||
'meshes/elfin10/elfin_link3.STL',
|
||||
'meshes/elfin10/elfin_link4.STL',
|
||||
'meshes/elfin10/elfin_link5.STL',
|
||||
'meshes/elfin10/elfin_link6.STL'
|
||||
]
|
||||
const fileNames = fileNameMap[props.filePath]
|
||||
const fetchPromises = fileNames.map(async (name) => {
|
||||
const url = `/inspection/elfin10/${name}`
|
||||
const url = `${props.filePath}${name}`
|
||||
const response = await fetch(url)
|
||||
const blob = await response.blob()
|
||||
return new File([blob], name, { type: blob.type })
|
||||
})
|
||||
const fileList = await Promise.all(fetchPromises)
|
||||
fileList.forEach(item => {
|
||||
fileMap.set('elfin10/' + item.name, item);
|
||||
fileMap.set(props.filePath + item.name, item);
|
||||
})
|
||||
}
|
||||
|
||||
@ -123,19 +114,21 @@ const currentModel = ref()
|
||||
let robotInstance = null; // 保存 URDFRobot 对象
|
||||
|
||||
const loadRobot = async () => {
|
||||
const xacroUrl = `/inspection/elfin10/elfin10.urdf.xacro`;
|
||||
const xacroUrl = `${props.filePath}${props.fileName}`;
|
||||
|
||||
const response = await fetch(xacroUrl);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
const xacroContent = await response.text();
|
||||
const file = fileMap.get('elfin10/elfin10.urdf.xacro')
|
||||
const model = await XacroAdapter.parse(xacroContent, file.name, fileMap, file);
|
||||
|
||||
const robot = model.threeObject; // 这就是 URDFRobot
|
||||
const file = fileMap.get(xacroUrl)
|
||||
let model
|
||||
if (props.fileName.split('.').pop() === 'xacro') {
|
||||
model = await XacroAdapter.parse(xacroContent, file.name, fileMap, file);
|
||||
}
|
||||
|
||||
const robot = model.threeObject;
|
||||
|
||||
// 将机器人添加到场景
|
||||
scene.add(robot); // ⚠️ 注意:是 robot.scene,不是 robot
|
||||
scene.add(robot);
|
||||
robot.rotation.x = -Math.PI / 2;
|
||||
currentModel.value = model
|
||||
|
||||
|
||||
15
src/views/arm/config.js
Normal file
15
src/views/arm/config.js
Normal file
@ -0,0 +1,15 @@
|
||||
export const fileNameMap = {
|
||||
'/inspection/elfin10/': [
|
||||
'elfin10.urdf.xacro',
|
||||
'elfin10_gazebo.xacro',
|
||||
'elfin10_transmission.xacro',
|
||||
'meshes/elfin10/elfin_base.STL',
|
||||
'meshes/elfin10/elfin_end_link.STL',
|
||||
'meshes/elfin10/elfin_link1.STL',
|
||||
'meshes/elfin10/elfin_link2.STL',
|
||||
'meshes/elfin10/elfin_link3.STL',
|
||||
'meshes/elfin10/elfin_link4.STL',
|
||||
'meshes/elfin10/elfin_link5.STL',
|
||||
'meshes/elfin10/elfin_link6.STL'
|
||||
]
|
||||
}
|
||||
14
src/views/camera/index.vue
Normal file
14
src/views/camera/index.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<IPlayer />
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import IPlayer from '@/components/IPlayer/index.vue'
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -131,9 +131,16 @@
|
||||
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { ZoomIn, ZoomOut, Location } from '@element-plus/icons-vue'
|
||||
import { useRobotStore } from '@/stores/robot'
|
||||
import { getCurrentMapName, moveRobot, stopRobot } from '@/api/agv.js'
|
||||
import { moveRobot, stopRobot } from '@/api/agv.js'
|
||||
import MapCanvas from './MapCanvas.vue'
|
||||
|
||||
const props = defineProps({
|
||||
mapName: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const VITE_DEVICE_ID = import.meta.env.VITE_DEVICE_ID
|
||||
|
||||
const robotStore = useRobotStore()
|
||||
@ -193,22 +200,6 @@ function onRelease() {
|
||||
})
|
||||
}
|
||||
|
||||
const mapName = ref('')
|
||||
|
||||
const getRobotCurrentMapName = async () => {
|
||||
const result = await getCurrentMapName({
|
||||
ip: robotStore.ip,
|
||||
deviceId: VITE_DEVICE_ID,
|
||||
})
|
||||
if (result.code === 200) {
|
||||
mapName.value = result.data.current_map
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getRobotCurrentMapName()
|
||||
})
|
||||
onBeforeUnmount(() => { })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user