Commit 406bc995 authored by 高晓帆's avatar 高晓帆

需求

parent b83028c8
<template>
<div class="basic-message">
<div class="basic-title">
<p>
<span>基础信息</span>
<Icon class="basic-close" type="ios-close-circle-outline" @click="handleClose" />
</p>
<i class="basic-title-line"></i>
</div>
<div class="basic">
<div class="basic-top">
<i :class="['vehicle-state', vehicleState]" @click="showStates"></i>
<span class="vehicle-msg">
<span>{{pattern == 0 ? '司机' : '安全员'}}{{name}}</span>
<span>工号:{{number}}</span>
</span>
</div>
<ul class="basic-middle">
<li v-for="item in list" :key="item.index">
<span class="middle-img" :style="`background-image: url('/image/ic_${item.name}.png')`">
{{basicMid[item.title] || 0}}{{item.unit}}
</span>
<span>{{item.label}}</span>
</li>
</ul>
</div>
<ul class="basic-info">
<li v-for="item in infos" :key="item.index">
<p v-for="list in item" :key="list.name">
<span class="label">{{list.label}}</span>
<span v-if="list.fixed">{{ debug[list.name] ? debug[list.name].toFixed(list.fixed) : list.default }}</span>
<span v-else>{{debug[list.name] || list.default}}</span>
</p>
</li>
</ul>
</div>
</template>
<script setup>
import { reactive, markRaw, ref, watch, computed } from 'vue';
import { useVehicleStore } from '@/store/VehicleStore.js'
import { useStateStore } from '@/store/StateStore.js'
import { storeToRefs } from 'pinia'
const BASIC_MESSAGE_INFO = [
[
{
name: 'target_velocity',
label: '速度(线控)',
default: 0,
fixed: 1,
},
{
name: 'steerangle',
label: '转向',
default: '——',
},
],
[
{
name: 'dump_bed',
label: '举升',
default: '——',
},
{
name: 'throttlecmd',
label: '油门',
default: '——',
},
],
[
{
name: 'Retarder_cmd',
label: '制动',
default: '——',
},
],
[
{
name: 'lateralDeviation',
label: '横向偏差',
default: 0.00,
},
],
[
{
name: 'courseDeviation',
label: '航向偏差',
default: 0.00,
},
],
[
{
name: 'obstacleFrontDistance',
label: '前向障碍物距离',
fixed: 2,
default: 0.00,
},
],
[
{
name: 'obstacleBackDistance',
label: '后向障碍物距离',
fixed: 2,
default: 0.00,
},
],
[
{
name: 'obstacleBackBarriDistance',
label: '后向挡墙距离',
fixed: 2,
default: 0.00,
},
],
]
const VEHICLE_TIRES = [
{
name: 'front_right',
icon: 'ic_tireLeft',
tire: 'tire0'
},
{
name: 'back_right_inside',
icon: 'ic_tireMiddle',
tire: 'tire1'
},
{
name: 'back_right_outside',
icon: 'ic_tireRight',
tire: 'tire2'
},
{
name: 'front_left',
icon: 'ic_tireLeft',
tire: 'tire3'
},
{
name: 'back_left_inside',
icon: 'ic_tireMiddle',
tire: 'tire4'
},
{
name: 'back_left_outside',
icon: 'ic_tireRight',
tire: 'tire5'
}
]
const BASIC_MESSAGE = [
{
label: '载重量',
name: 'weight',
title: 'vehicleLoad',
unit: 'T'
},
{
label: '时速(rosbeacon)',
name: 'speed',
title: 'vehicleSpeed',
unit: 'Km/h'
},
{
label: '油量',
name: 'oil',
title: 'oil',
unit: '%'
},
]
const list = markRaw(BASIC_MESSAGE)
const infos = markRaw(BASIC_MESSAGE_INFO)
const debug = ref({})
const name = ref('')
const number = ref('')
let basicMid = reactive({})
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { getVehicleDebug, getVehicleBasic, getCurrentBasic} = vehicleStoreToRefs
const stateStore = useStateStore()
const stateStoreToRefs = storeToRefs(stateStore)
const { getLoginAck } = stateStoreToRefs
const emits = defineEmits(['handleClose', 'showModal'])
const vehicleState = computed(() => {
const {isError} = vehicleStoreToRefs
return isError.value
})
const pattern = computed(() => {
const {softDrivingPattern} = vehicleStoreToRefs
return softDrivingPattern.value
})
function handleClose() {
emits('handleClose')
}
function showStates() {
if (vehicleState.value === 'normal') return
emits('showModal', {name: 'states'})
}
watch([getVehicleDebug, getLoginAck, getVehicleBasic, getCurrentBasic], ([debugValue, loginAckValue, vehicleBasic, currentBasic]) => {
if (debugValue) {
debug.value = debugValue
}
if (loginAckValue) {
name.value = loginAckValue.name
number.value = loginAckValue.number
}
if (vehicleBasic) {
const {oil} = vehicleBasic
basicMid['oil'] = oil ? oil.toFixed(2) : 0
}
if (currentBasic) {
const {vehicleLoad, vehicleSpeed} = currentBasic
let result = {
vehicleLoad: vehicleLoad ? vehicleLoad.toFixed(2) : 0,
vehicleSpeed: vehicleSpeed ? vehicleSpeed.toFixed(2) : 0,
oil: basicMid.oil
}
basicMid = Object.assign(basicMid, result)
}
}, {
immediate: true
})
</script>
<style lang="less" scoped>
.basic-message {
.basic-title {
padding: 5px 20px 10px;
color: #fff;
position: relative;
p {
display: flex;
align-items: center;
justify-content: space-between;
span:nth-child(1) {
margin-left: 10px;
}
}
.basic-close {
color: #63A9FB;
cursor: pointer;
}
.basic-title-line {
display: inline-block;
background: url('/image/basic-title.png') no-repeat;
background-size: cover;
width: 100%;
height: 10px;
position: absolute;
}
}
.basic {
color: #fff;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
.basic-top {
display: flex;
align-items: center;
width: 100%;
padding-left: 10px;
margin-bottom: 10px;
.vehicle-state {
display: inline-block;
width: 6vw;
height: 6vw;
background-size: contain;
background-repeat: no-repeat;
margin-right: 10px;
cursor: pointer;
}
@media screen and (min-width: 1400px) {
.vehicle-state {
width: 5vw;
height: 5vw;
}
}
.normal {
background-image: url('/image/heal_normal.png');
}
.fault {
background-image: url('/image/heal_fault.png');
}
.warning {
background-image: url('/image/heal_warning.png');
}
.vehicle-msg {
display: flex;
flex-direction: column;
span {
line-height: 5vh;
display: inline-block;
}
}
}
.basic-middle {
display: flex;
width: 100%;
justify-content: space-between;
li {
text-align: center;
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
.middle-img {
display: block;
width: 6vw;
height: 6vw;
min-width: 50px;
min-height: 50px;
background-size: cover;
line-height: 7vw;
text-align: center;
}
@media screen and (min-width: 1400px) {
.middle-img {
width: 5vw;
height: 5vw;
line-height: 5vw;
}
}
@media screen and (max-width: 631px) {
.middle-img {
line-height: 9vw;
}
}
}
}
}
.basic-info {
color: #fff;
padding: 10px 20px;
margin-top: 10px;
li {
display: flex;
p {
min-width: 50%;
white-space: nowrap;
}
.label {
color: #63A9FB;
}
}
}
}
</style>
\ No newline at end of file
<template>
<div class="basic-message">
<div class="basic-title">
<p>
<span>基础信息</span>
<Icon class="basic-close" type="ios-close-circle-outline" @click="handleClose" />
</p>
<i class="basic-title-line"></i>
</div>
<div class="basic">
<div class="basic-top">
<i :class="['vehicle-state', vehicleState]" @click="showStates"></i>
<span class="vehicle-msg">
<span>{{pattern == 0 ? '司机' : '安全员'}}{{name}}</span>
<span>工号:{{number}}</span>
</span>
</div>
<ul class="basic-middle">
<li v-for="item in list" :key="item.index">
<span class="middle-img" :style="`background-image: url('/image/ic_${item.name}.png')`">
{{basicMid[item.title] || 0}}{{item.unit}}
</span>
<span>{{item.label}}</span>
</li>
</ul>
</div>
<ul class="basic-info">
<li v-for="item in infos" :key="item.index">
<p v-for="list in item" :key="list.name">
<span class="label">{{list.label}}</span>
<span v-if="list.fixed">{{ debug[list.name] ? debug[list.name].toFixed(list.fixed) : list.default }}</span>
<span v-else>{{debug[list.name] || list.default}}</span>
</p>
</li>
</ul>
</div>
</template>
<script setup>
import { reactive, markRaw, ref, watch, computed } from 'vue';
import { useVehicleStore } from '@/store/VehicleStore.js'
import { useStateStore } from '@/store/StateStore.js'
import { storeToRefs } from 'pinia'
const BASIC_MESSAGE_INFO = [
[
{
name: 'target_velocity',
label: '速度(线控)',
default: 0,
fixed: 1,
},
{
name: 'steerangle',
label: '转向',
default: '——',
},
],
[
{
name: 'dump_bed',
label: '举升',
default: '——',
},
{
name: 'throttlecmd',
label: '油门',
default: '——',
},
],
[
{
name: 'Retarder_cmd',
label: '制动',
default: '——',
},
],
[
{
name: 'lateralDeviation',
label: '横向偏差',
default: 0.00,
},
],
[
{
name: 'courseDeviation',
label: '航向偏差',
default: 0.00,
},
],
[
{
name: 'obstacleFrontDistance',
label: '前向障碍物距离',
fixed: 2,
default: 0.00,
},
],
[
{
name: 'obstacleBackDistance',
label: '后向障碍物距离',
fixed: 2,
default: 0.00,
},
],
[
{
name: 'obstacleBackBarriDistance',
label: '后向挡墙距离',
fixed: 2,
default: 0.00,
},
],
]
const VEHICLE_TIRES = [
{
name: 'front_right',
icon: 'ic_tireLeft',
tire: 'tire0'
},
{
name: 'back_right_inside',
icon: 'ic_tireMiddle',
tire: 'tire1'
},
{
name: 'back_right_outside',
icon: 'ic_tireRight',
tire: 'tire2'
},
{
name: 'front_left',
icon: 'ic_tireLeft',
tire: 'tire3'
},
{
name: 'back_left_inside',
icon: 'ic_tireMiddle',
tire: 'tire4'
},
{
name: 'back_left_outside',
icon: 'ic_tireRight',
tire: 'tire5'
}
]
const BASIC_MESSAGE = [
{
label: '载重量',
name: 'weight',
title: 'vehicleLoad',
unit: 'T'
},
{
label: '时速(rosbeacon)',
name: 'speed',
title: 'vehicleSpeed',
unit: 'Km/h'
},
{
label: '油量',
name: 'oil',
title: 'oil',
unit: '%'
},
]
const list = markRaw(BASIC_MESSAGE)
const infos = markRaw(BASIC_MESSAGE_INFO)
const debug = ref({})
const name = ref('')
const number = ref('')
let basicMid = reactive({})
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { getVehicleDebug, getVehicleBasic, getCurrentBasic} = vehicleStoreToRefs
const stateStore = useStateStore()
const stateStoreToRefs = storeToRefs(stateStore)
const { getLoginAck } = stateStoreToRefs
const emits = defineEmits(['handleClose', 'showModal'])
const vehicleState = computed(() => {
const {isError} = vehicleStoreToRefs
return isError.value
})
const pattern = computed(() => {
const {softDrivingPattern} = vehicleStoreToRefs
return softDrivingPattern.value
})
function handleClose() {
emits('handleClose')
}
function showStates() {
if (vehicleState.value === 'normal') return
emits('showModal', {name: 'states'})
}
watch([getVehicleDebug, getLoginAck, getVehicleBasic, getCurrentBasic], ([debugValue, loginAckValue, vehicleBasic, currentBasic]) => {
if (debugValue) {
debug.value = debugValue
}
if (loginAckValue) {
name.value = loginAckValue.name
number.value = loginAckValue.number
}
if (vehicleBasic) {
const {oil} = vehicleBasic
basicMid['oil'] = oil ? oil.toFixed(2) : 0
}
if (currentBasic) {
const {vehicleLoad, vehicleSpeed} = currentBasic
let result = {
vehicleLoad: vehicleLoad ? vehicleLoad.toFixed(2) : 0,
vehicleSpeed: vehicleSpeed ? vehicleSpeed.toFixed(2) : 0,
oil: basicMid.oil
}
basicMid = Object.assign(basicMid, result)
}
}, {
immediate: true
})
</script>
<style lang="less" scoped>
.basic-message {
.basic-title {
padding: 5px 20px 10px;
color: #fff;
position: relative;
p {
display: flex;
align-items: center;
justify-content: space-between;
span:nth-child(1) {
margin-left: 10px;
}
}
.basic-close {
color: #63A9FB;
cursor: pointer;
}
.basic-title-line {
display: inline-block;
background: url('/image/basic-title.png') no-repeat;
background-size: cover;
width: 100%;
height: 10px;
position: absolute;
}
}
.basic {
color: #fff;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
.basic-top {
display: flex;
align-items: center;
width: 100%;
padding-left: 10px;
margin-bottom: 10px;
.vehicle-state {
display: inline-block;
width: 6vw;
height: 6vw;
background-size: contain;
background-repeat: no-repeat;
margin-right: 10px;
cursor: pointer;
}
@media screen and (min-width: 1400px) {
.vehicle-state {
width: 5vw;
height: 5vw;
}
}
.normal {
background-image: url('/image/heal_normal.png');
}
.fault {
background-image: url('/image/heal_fault.png');
}
.warning {
background-image: url('/image/heal_warning.png');
}
.vehicle-msg {
display: flex;
flex-direction: column;
span {
line-height: 5vh;
display: inline-block;
}
}
}
.basic-middle {
display: flex;
width: 100%;
justify-content: space-between;
li {
text-align: center;
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
.middle-img {
display: block;
width: 6vw;
height: 6vw;
min-width: 50px;
min-height: 50px;
background-size: cover;
line-height: 7vw;
text-align: center;
}
@media screen and (min-width: 1400px) {
.middle-img {
width: 5vw;
height: 5vw;
line-height: 5vw;
}
}
@media screen and (max-width: 631px) {
.middle-img {
line-height: 9vw;
}
}
}
}
}
.basic-info {
color: #fff;
padding: 10px 20px;
margin-top: 10px;
li {
display: flex;
p {
min-width: 50%;
white-space: nowrap;
}
.label {
color: #63A9FB;
}
}
}
}
</style>
\ No newline at end of file
<template>
<div class="main">
<page-header class="page-header"></page-header>
<div class="page-main">
<side-bar class="side-bar" ref="sideBarDom" @changeTab="changeTab"></side-bar>
<div class="container">
<div class="container-message" v-show="isShowBasic">
<basic-message v-if="basciName === 'basic_message'" @handleClose="handleClose" @showModal="showModal"></basic-message>
<basic-information v-else @handleClose="handleClose"></basic-information>
<information-msg class="information-msg"></information-msg>
</div>
<div v-show="!isShowBasic" class="container-message-icon" @click="handleShowBasic">
<img src="/image/basic-message-icon.png" alt="" />
</div>
<map-container class="map" :reloadData="reloadData" :isShowBasic="isShowBasic" @handleSend="handleSend"></map-container>
</div>
</div>
<Modal v-model="isShow"
:mask-closable="false"
:footer-hide="true"
:title="title"
:closable="isCloseable"
:width="modalWidth"
@on-visible-change="modeChange">
<component :is="currentTag" :is-show="isShow" @handleSend="handleSend" @closeModal="closeModal"></component>
</Modal>
<Modal v-model="isShowTip"
:mask-closable="false"
:mask="false"
:footer-hide="isFooterHide">
<p>{{ vehicleTip }}</p>
<p>{{ remaintime }}</p>
<template #footer>
<Button type="info" class="footer" @click="doClose">确定</Button>
</template>
</Modal>
<Modal v-model="isShowBoxCheck"
title="确认信息"
class="box-check"
:closable="false"
:mask-closable="false"
@on-ok="handleBoxCheck(1)"
@on-cancel="handleBoxCheck(0)">
<span>{{ checkMsg.msg }}</span>
</Modal>
</div>
</template>
<script setup>
import { onBeforeMount, ref, getCurrentInstance, computed, watch, toRefs, reactive, onBeforeUnmount, shallowRef } from 'vue'
import { useVehicleStore } from '../store/VehicleStore';
import { storeToRefs } from 'pinia';
import { Message } from 'view-ui-plus';
import PageHeader from './PageHeader.vue'
import SideBar from './SideBar.vue';
import BasicMessage from './BasicMessage.vue';
import BasicInformation from './BasicInformation.vue';
import InformationMsg from './InformationMsg.vue';
import AlarmModal from './AlarmModal.vue'
import ModeSwitch from './ModeSwitch.vue'
import LogModal from './LogModal.vue'
import SetView from './SetView.vue'
import Logout from './Logout.vue'
import MapContainer from './MapContainer.vue'
let tipTimer = null
const isShowBasic = ref(true)
const currentName = ref('basic_message')
const basciName = ref('basic_message')
const isShow = ref(false)
const isShowTip = ref(false)
const isShowBoxCheck = ref(false)
const title = ref('')
const isCloseable = ref(true)
const currentTag = shallowRef('')
const sideBarDom = ref(null)
const vehicleTip = ref('')
const remaintime = ref('')
const isFooterHide = ref(true)
const reloadData = ref(false)
const boxCheckMsg = reactive({
checkMsg: {}
})
const { checkMsg } = toRefs(boxCheckMsg)
const instance = getCurrentInstance()
const { appContext } = instance
const { $indexRoot } = appContext.config.globalProperties
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { tipInfo, infoPop } = vehicleStoreToRefs
onBeforeMount(() => {
window.addEventListener('beforeunload', () => {
handleSubscribe()
})
// // 发送同步地图版本号信息
// if (!$indexRoot.sock) {
// $indexRoot.init()
// }
})
function handleSubscribe() {
reloadData.value = true
$indexRoot.destroyData()
}
const modalWidth = computed(() => {
if (currentName.value === 'log' || currentName.value === 'set') return '70%'
return '520px'
})
function handleSend(msg) {
if ($indexRoot.sock) {
console.log('发送信息', msg)
$indexRoot.sock.send(JSON.stringify(msg))
} else {
$indexRoot.init().then(socket => {
console.log('发送信息', msg)
socket.send(JSON.stringify(msg))
})
}
}
function doModeSwitch() {
isCloseable.value = false
title.value = '确认信息'
isShow.value = true
currentTag.value = ModeSwitch
}
function handleModal(name) {
title.value = name === 'log' ? '日志获取' : '设置'
currentTag.value = name === 'log' ? LogModal : SetView
isCloseable.value = true
isShow.value = true
}
function handleLogout() {
title.value = ''
currentTag.value = Logout
isCloseable.value = true
isShow.value = true
}
function changeTab(name) {
console.log(name)
currentName.value = name
switch(name) {
case 'mode_switch':
doModeSwitch()
break
case 'mode_information':
case 'basic_message':
basciName.value = name
break
case 'log':
case 'set':
handleModal(name)
break
case 'logout':
handleLogout()
break
}
}
function handleClose() {
isShowBasic.value = false
}
function handleShowBasic() {
isShowBasic.value = true
}
function closeModal() {
isShow.value = false
}
function modeChange(visible) {
if (!visible) {
let sideBar = sideBarDom.value
sideBar.changeMode()
}
}
function showModal() {
isShow.value = true
currentTag.value = AlarmModal
title.value = '车辆故障码'
isCloseable.value = true
}
function doClose() {
isShowTip.value = false
if (tipTimer) {
clearTimeout(tipTimer)
tipTimer = null
}
}
function handleShowBoxCheck(list) {
let data = list[0]
if (!data) return
boxCheckMsg.checkMsg = data
isShowBoxCheck.value = true
}
function handleBoxCheck(accept) {
let {type, value} = boxCheckMsg.checkMsg
handleSend({
type: '/info/popupack',
msg: {
type,
value,
accept
}
})
vehicleStore.splitInfoPop()
}
watch(tipInfo, (msg) => {
if (!msg) return
const {type, value, remaintime: vehicleRemainTime, isFirst} = msg
if (type === 1) {
isShowTip.value = true
vehicleTip.value = value
isFooterHide.value = false
tipTimer = setTimeout(() => {
doClose()
}, 5 * 1000)
} else if (type === 2) {
Message.info({
content: value,
duration: 10,
closable: true
})
} else {
isFooterHide.value = true
if (isFirst === 1) {
isShowTip.value = true
}
vehicleTip.value = value
remaintime.value = vehicleRemainTime
if (vehicleRemainTime < 1) {
isShowTip.value = false
}
}
vehicleStore.setData('tipInfo', null)
}, {
deep: true
})
watch(infoPop, (list) => {
if (list.length) {
handleShowBoxCheck(list)
} else {
isShowBoxCheck.value = false
}
}, {
deep: true
})
onBeforeUnmount(() => {
$indexRoot.destroyData()
window.removeEventListener('beforeunload', handleSubscribe())
})
</script>
<style lang="less" scoped>
.main {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.page-header {
flex: 0 0 10vh;
min-height: 46px;
// align-items: flex-end;
}
.page-main {
background: url('/image/background.png') no-repeat;
background-size: cover;
flex: auto;
display: flex;
height: calc(100% - 10vh);
.side-bar {
flex: 0 0 7vw;
min-width: 70px;
}
.container {
flex: auto;
display: flex;
position: relative;
.container-message {
flex: 0 0 22vw;
min-width: 240px;
display: flex;
flex-direction: column;
overflow-y: auto;
overflow-x: hidden;
.container-basic {
flex: auto;
height: calc(100% - 150px);
overflow-y: auto;
overflow-x: hidden;
}
}
.container-message-icon {
position: absolute;
z-index: 9999;
top: 5vh;
left: 1vw;
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.25);
border-radius: 10px;
opacity: 1;
display: flex;
cursor: pointer;
}
.map {
flex: auto;
display: flex;
flex-direction: column;
}
}
}
}
</style>
\ No newline at end of file
<template>
<div class="main">
<page-header class="page-header"></page-header>
<div class="page-main">
<side-bar
class="side-bar"
ref="sideBarDom"
@changeTab="changeTab"
></side-bar>
<div class="container">
<div class="container-message" v-show="isShowBasic">
<basic-message
v-if="basciName === 'basic_message'"
@handleClose="handleClose"
@showModal="showModal"
></basic-message>
<basic-information
v-else
@handleClose="handleClose"
></basic-information>
<information-msg class="information-msg"></information-msg>
</div>
<div
v-show="!isShowBasic"
class="container-message-icon"
@click="handleShowBasic"
>
<img src="/image/basic-message-icon.png" alt="" />
</div>
<map-container
class="map"
:reloadData="reloadData"
:isShowBasic="isShowBasic"
@handleSend="handleSend"
></map-container>
</div>
</div>
<Modal
v-model="isShow"
:mask-closable="false"
:footer-hide="true"
:title="title"
:closable="isCloseable"
:width="modalWidth"
@on-visible-change="modeChange"
>
<component
:is="currentTag"
:is-show="isShow"
@handleSend="handleSend"
@closeModal="closeModal"
></component>
</Modal>
<Modal
v-model="isShowTip"
:mask-closable="false"
:mask="false"
:footer-hide="isFooterHide"
>
<p>{{ vehicleTip }}</p>
<p>{{ remaintime }}</p>
<template #footer>
<Button type="info" class="footer" @click="doClose">确定</Button>
</template>
</Modal>
<Modal
v-model="isShowBoxCheck"
title="确认信息"
class="box-check"
:closable="false"
:mask-closable="false"
>
<div style="display: flex; flex-direction: column">
<span>{{ checkMsg.msg }}</span>
<!-- 增加option选项,默认选择第一个,提交时要把accept替换为option -->
<Radio-group v-if="checkMsg.option" vertical v-model="optionModel">
<Radio
:key="key.value"
v-for="key in checkMsg.option"
:label="key.value"
>{{ key.desc }}</Radio
>
</Radio-group>
</div>
<template #footer>
<Button
v-if="!checkMsg.option"
type="info"
class="footer"
@click="handleBoxCheck(1)"
>确定</Button
>
<Button
v-if="!checkMsg.option"
type="info"
class="footer"
@click="handleBoxCheck(0)"
>取消</Button
>
<!-- 增加option选项,该状态只有确定 -->
<Button
v-if="checkMsg.option"
type="info"
class="footer"
@click="handleBoxCheck()"
>确定</Button
>
</template>
</Modal>
</div>
</template>
<script setup>
import {
onBeforeMount,
ref,
getCurrentInstance,
computed,
watch,
toRefs,
reactive,
onBeforeUnmount,
shallowRef,
} from "vue";
import { useVehicleStore } from "../store/VehicleStore";
import { storeToRefs } from "pinia";
import { Message } from "view-ui-plus";
import PageHeader from "./PageHeader.vue";
import SideBar from "./SideBar.vue";
import BasicMessage from "./BasicMessage.vue";
import BasicInformation from "./BasicInformation.vue";
import InformationMsg from "./InformationMsg.vue";
import AlarmModal from "./AlarmModal.vue";
import ModeSwitch from "./ModeSwitch.vue";
import LogModal from "./LogModal.vue";
import SetView from "./SetView.vue";
import Logout from "./Logout.vue";
import MapContainer from "./MapContainer.vue";
let tipTimer = null;
const isShowBasic = ref(true);
const currentName = ref("basic_message");
const basciName = ref("basic_message");
const isShow = ref(false);
const isShowTip = ref(false);
const isShowBoxCheck = ref(false);
const title = ref("");
const isCloseable = ref(true);
const currentTag = shallowRef("");
const sideBarDom = ref(null);
const vehicleTip = ref("");
const remaintime = ref("");
const isFooterHide = ref(true);
const reloadData = ref(false);
const boxCheckMsg = reactive({
checkMsg: {},
optionModel: "",
});
const { checkMsg, optionModel } = toRefs(boxCheckMsg);
const instance = getCurrentInstance();
const { appContext } = instance;
const { $indexRoot } = appContext.config.globalProperties;
const vehicleStore = useVehicleStore();
const vehicleStoreToRefs = storeToRefs(vehicleStore);
const { tipInfo, infoPop } = vehicleStoreToRefs;
onBeforeMount(() => {
window.addEventListener("beforeunload", () => {
handleSubscribe();
});
// // 发送同步地图版本号信息
// if (!$indexRoot.sock) {
// $indexRoot.init()
// }
});
function handleSubscribe() {
reloadData.value = true;
$indexRoot.destroyData();
}
const modalWidth = computed(() => {
if (currentName.value === "log" || currentName.value === "set") return "70%";
return "520px";
});
function handleSend(msg) {
if ($indexRoot.sock) {
console.log("发送信息", msg);
$indexRoot.sock.send(JSON.stringify(msg));
} else {
$indexRoot.init().then((socket) => {
console.log("发送信息", msg);
socket.send(JSON.stringify(msg));
});
}
}
function doModeSwitch() {
isCloseable.value = false;
title.value = "确认信息";
isShow.value = true;
currentTag.value = ModeSwitch;
}
function handleModal(name) {
title.value = name === "log" ? "日志获取" : "设置";
currentTag.value = name === "log" ? LogModal : SetView;
isCloseable.value = true;
isShow.value = true;
}
function handleLogout() {
title.value = "";
currentTag.value = Logout;
isCloseable.value = true;
isShow.value = true;
}
function changeTab(name) {
console.log(name);
currentName.value = name;
switch (name) {
case "mode_switch":
doModeSwitch();
break;
case "mode_information":
case "basic_message":
basciName.value = name;
break;
case "log":
case "set":
handleModal(name);
break;
case "logout":
handleLogout();
break;
}
}
function handleClose() {
isShowBasic.value = false;
}
function handleShowBasic() {
isShowBasic.value = true;
}
function closeModal() {
isShow.value = false;
}
function modeChange(visible) {
if (!visible) {
let sideBar = sideBarDom.value;
sideBar.changeMode();
}
}
function showModal() {
isShow.value = true;
currentTag.value = AlarmModal;
title.value = "车辆故障码";
isCloseable.value = true;
}
function doClose() {
isShowTip.value = false;
if (tipTimer) {
clearTimeout(tipTimer);
tipTimer = null;
}
}
function handleShowBoxCheck(list) {
let data = list[0];
if (!data) return;
if (data.option&&data.option.length > 0) {
optionModel.value = data.option[0].value;
}
boxCheckMsg.checkMsg = data;
isShowBoxCheck.value = true;
}
function handleBoxCheck(accept) {
let msg = null;
let { type, value, option } = boxCheckMsg.checkMsg;
handleSend({
type: "/info/popupack",
msg: {
type,
value,
accept: option&&option.length > 0 ? optionModel.value : accept,
},
});
vehicleStore.splitInfoPop();
}
watch(
tipInfo,
(msg) => {
if (!msg) return;
const { type, value, remaintime: vehicleRemainTime, isFirst } = msg;
if (type === 1) {
isShowTip.value = true;
vehicleTip.value = value;
isFooterHide.value = false;
tipTimer = setTimeout(() => {
doClose();
}, 5 * 1000);
} else if (type === 2) {
Message.info({
content: value,
duration: 10,
closable: true,
});
} else {
isFooterHide.value = true;
if (isFirst === 1) {
isShowTip.value = true;
}
vehicleTip.value = value;
remaintime.value = vehicleRemainTime;
if (vehicleRemainTime < 1) {
isShowTip.value = false;
}
}
vehicleStore.setData("tipInfo", null);
},
{
deep: true,
}
);
watch(
infoPop,
(list) => {
if (list.length) {
handleShowBoxCheck(list);
} else {
isShowBoxCheck.value = false;
}
},
{
deep: true,
}
);
onBeforeUnmount(() => {
$indexRoot.destroyData();
window.removeEventListener("beforeunload", handleSubscribe());
});
</script>
<style lang="less" scoped>
.main {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
.page-header {
flex: 0 0 10vh;
min-height: 46px;
// align-items: flex-end;
}
.page-main {
background: url("/image/background.png") no-repeat;
background-size: cover;
flex: auto;
display: flex;
height: calc(100% - 10vh);
.side-bar {
flex: 0 0 7vw;
min-width: 70px;
}
.container {
flex: auto;
display: flex;
position: relative;
.container-message {
flex: 0 0 22vw;
min-width: 240px;
display: flex;
flex-direction: column;
overflow-y: auto;
overflow-x: hidden;
.container-basic {
flex: auto;
height: calc(100% - 150px);
overflow-y: auto;
overflow-x: hidden;
}
}
.container-message-icon {
position: absolute;
z-index: 9999;
top: 5vh;
left: 1vw;
background: #4a75a9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
cursor: pointer;
}
.map {
flex: auto;
display: flex;
flex-direction: column;
}
}
}
}
</style>
\ No newline at end of file
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<div class="basic-top"> <div class="basic-top">
<i :class="['vehicle-state', vehicleState]" @click="showStates"></i> <i :class="['vehicle-state', vehicleState]" @click="showStates"></i>
<span class="vehicle-msg"> <span class="vehicle-msg">
<span>{{softDrivingPattern == 0 ? '司机' : '安全员'}}{{name}}</span> <span>{{pattern == 0 ? '司机' : '安全员'}}{{name}}</span>
<span>工号:{{number}}</span> <span>工号:{{number}}</span>
</span> </span>
</div> </div>
......
<template> <template>
<div class="main"> <div class="main">
<page-header class="page-header"></page-header> <page-header class="page-header"></page-header>
<div class="page-main"> <div class="page-main">
<side-bar class="side-bar" ref="sideBarDom" @changeTab="changeTab"></side-bar> <side-bar
<div class="container"> class="side-bar"
<div class="container-message" v-show="isShowBasic"> ref="sideBarDom"
<basic-message v-if="basciName === 'basic_message'" @handleClose="handleClose" @showModal="showModal"></basic-message> @changeTab="changeTab"
<basic-information v-else @handleClose="handleClose"></basic-information> ></side-bar>
<information-msg class="information-msg"></information-msg> <div class="container">
</div> <div class="container-message" v-show="isShowBasic">
<div v-show="!isShowBasic" class="container-message-icon" @click="handleShowBasic"> <basic-message
<img src="/image/basic-message-icon.png" alt="" /> v-if="basciName === 'basic_message'"
</div> @handleClose="handleClose"
<map-container class="map" :reloadData="reloadData" :isShowBasic="isShowBasic" @handleSend="handleSend"></map-container> @showModal="showModal"
</div> ></basic-message>
<basic-information
v-else
@handleClose="handleClose"
></basic-information>
<information-msg class="information-msg"></information-msg>
</div> </div>
<Modal v-model="isShow" <div
:mask-closable="false" v-show="!isShowBasic"
:footer-hide="true" class="container-message-icon"
:title="title" @click="handleShowBasic"
:closable="isCloseable" >
:width="modalWidth" <img src="/image/basic-message-icon.png" alt="" />
@on-visible-change="modeChange"> </div>
<component :is="currentTag" :is-show="isShow" @handleSend="handleSend" @closeModal="closeModal"></component> <map-container
</Modal> class="map"
<Modal v-model="isShowTip" :reloadData="reloadData"
:mask-closable="false" :isShowBasic="isShowBasic"
:mask="false" @handleSend="handleSend"
:footer-hide="isFooterHide"> ></map-container>
<p>{{ vehicleTip }}</p> </div>
<p>{{ remaintime }}</p>
<template #footer>
<Button type="info" class="footer" @click="doClose">确定</Button>
</template>
</Modal>
<Modal v-model="isShowBoxCheck"
title="确认信息"
class="box-check"
:closable="false"
:mask-closable="false"
@on-ok="handleBoxCheck(1)"
@on-cancel="handleBoxCheck(0)">
<span>{{ checkMsg.msg }}</span>
</Modal>
</div> </div>
<Modal
v-model="isShow"
:mask-closable="false"
:footer-hide="true"
:title="title"
:closable="isCloseable"
:width="modalWidth"
@on-visible-change="modeChange"
>
<component
:is="currentTag"
:is-show="isShow"
@handleSend="handleSend"
@closeModal="closeModal"
></component>
</Modal>
<Modal
v-model="isShowTip"
:mask-closable="false"
:mask="false"
:footer-hide="isFooterHide"
>
<p>{{ vehicleTip }}</p>
<p>{{ remaintime }}</p>
<template #footer>
<Button type="info" class="footer" @click="doClose">确定</Button>
</template>
</Modal>
<Modal
v-model="isShowBoxCheck"
title="确认信息"
class="box-check"
:closable="false"
:mask-closable="false"
>
<div style="display: flex; flex-direction: column">
<span>{{ checkMsg.msg }}</span>
<!-- 增加option选项,默认选择第一个,提交时要把accept替换为option -->
<Radio-group v-if="checkMsg.option" vertical v-model="optionModel">
<Radio
:key="key.value"
v-for="key in checkMsg.option"
:label="key.value"
>{{ key.desc }}</Radio
>
</Radio-group>
</div>
<template #footer>
<Button
v-if="!checkMsg.option"
type="info"
class="footer"
@click="handleBoxCheck(1)"
>确定</Button
>
<Button
v-if="!checkMsg.option"
type="info"
class="footer"
@click="handleBoxCheck(0)"
>取消</Button
>
<!-- 增加option选项,该状态只有确定 -->
<Button
v-if="checkMsg.option"
type="info"
class="footer"
@click="handleBoxCheck()"
>确定</Button
>
</template>
</Modal>
</div>
</template> </template>
<script setup> <script setup>
import { onBeforeMount, ref, getCurrentInstance, computed, watch, toRefs, reactive, onBeforeUnmount, shallowRef } from 'vue' import {
import { useVehicleStore } from '../store/VehicleStore'; onBeforeMount,
import { storeToRefs } from 'pinia'; ref,
import { Message } from 'view-ui-plus'; getCurrentInstance,
import PageHeader from './PageHeader.vue' computed,
import SideBar from './SideBar.vue'; watch,
import BasicMessage from './BasicMessage.vue'; toRefs,
import BasicInformation from './BasicInformation.vue'; reactive,
import InformationMsg from './InformationMsg.vue'; onBeforeUnmount,
import AlarmModal from './AlarmModal.vue' shallowRef,
import ModeSwitch from './ModeSwitch.vue' } from "vue";
import LogModal from './LogModal.vue' import { useVehicleStore } from "../store/VehicleStore";
import SetView from './SetView.vue' import { storeToRefs } from "pinia";
import Logout from './Logout.vue' import { Message } from "view-ui-plus";
import MapContainer from './MapContainer.vue' import PageHeader from "./PageHeader.vue";
import SideBar from "./SideBar.vue";
import BasicMessage from "./BasicMessage.vue";
import BasicInformation from "./BasicInformation.vue";
import InformationMsg from "./InformationMsg.vue";
import AlarmModal from "./AlarmModal.vue";
import ModeSwitch from "./ModeSwitch.vue";
import LogModal from "./LogModal.vue";
import SetView from "./SetView.vue";
import Logout from "./Logout.vue";
import MapContainer from "./MapContainer.vue";
let tipTimer = null let tipTimer = null;
const isShowBasic = ref(true) const isShowBasic = ref(true);
const currentName = ref('basic_message') const currentName = ref("basic_message");
const basciName = ref('basic_message') const basciName = ref("basic_message");
const isShow = ref(false) const isShow = ref(false);
const isShowTip = ref(false) const isShowTip = ref(false);
const isShowBoxCheck = ref(false) const isShowBoxCheck = ref(false);
const title = ref('') const title = ref("");
const isCloseable = ref(true) const isCloseable = ref(true);
const currentTag = shallowRef('') const currentTag = shallowRef("");
const sideBarDom = ref(null) const sideBarDom = ref(null);
const vehicleTip = ref('') const vehicleTip = ref("");
const remaintime = ref('') const remaintime = ref("");
const isFooterHide = ref(true) const isFooterHide = ref(true);
const reloadData = ref(false) const reloadData = ref(false);
const boxCheckMsg = reactive({ const boxCheckMsg = reactive({
checkMsg: {} checkMsg: {},
}) optionModel: "",
const { checkMsg } = toRefs(boxCheckMsg) });
const instance = getCurrentInstance() const { checkMsg, optionModel } = toRefs(boxCheckMsg);
const { appContext } = instance const instance = getCurrentInstance();
const { $indexRoot } = appContext.config.globalProperties const { appContext } = instance;
const vehicleStore = useVehicleStore() const { $indexRoot } = appContext.config.globalProperties;
const vehicleStoreToRefs = storeToRefs(vehicleStore) const vehicleStore = useVehicleStore();
const { tipInfo, infoPop } = vehicleStoreToRefs const vehicleStoreToRefs = storeToRefs(vehicleStore);
const { tipInfo, infoPop } = vehicleStoreToRefs;
onBeforeMount(() => { onBeforeMount(() => {
window.addEventListener('beforeunload', () => { window.addEventListener("beforeunload", () => {
handleSubscribe() handleSubscribe();
}) });
// // 发送同步地图版本号信息 // // 发送同步地图版本号信息
// if (!$indexRoot.sock) { // if (!$indexRoot.sock) {
// $indexRoot.init() // $indexRoot.init()
// } // }
}) });
function handleSubscribe() { function handleSubscribe() {
reloadData.value = true reloadData.value = true;
$indexRoot.destroyData() $indexRoot.destroyData();
} }
const modalWidth = computed(() => { const modalWidth = computed(() => {
if (currentName.value === 'log' || currentName.value === 'set') return '70%' if (currentName.value === "log" || currentName.value === "set") return "70%";
return '520px' return "520px";
}) });
function handleSend(msg) { function handleSend(msg) {
if ($indexRoot.sock) { if ($indexRoot.sock) {
console.log('发送信息', msg) console.log("发送信息", msg);
$indexRoot.sock.send(JSON.stringify(msg)) $indexRoot.sock.send(JSON.stringify(msg));
} else { } else {
$indexRoot.init().then(socket => { $indexRoot.init().then((socket) => {
console.log('发送信息', msg) console.log("发送信息", msg);
socket.send(JSON.stringify(msg)) socket.send(JSON.stringify(msg));
}) });
} }
} }
function doModeSwitch() { function doModeSwitch() {
isCloseable.value = false isCloseable.value = false;
title.value = '确认信息' title.value = "确认信息";
isShow.value = true isShow.value = true;
currentTag.value = ModeSwitch currentTag.value = ModeSwitch;
} }
function handleModal(name) { function handleModal(name) {
title.value = name === 'log' ? '日志获取' : '设置' title.value = name === "log" ? "日志获取" : "设置";
currentTag.value = name === 'log' ? LogModal : SetView currentTag.value = name === "log" ? LogModal : SetView;
isCloseable.value = true isCloseable.value = true;
isShow.value = true isShow.value = true;
} }
function handleLogout() { function handleLogout() {
title.value = '' title.value = "";
currentTag.value = Logout currentTag.value = Logout;
isCloseable.value = true isCloseable.value = true;
isShow.value = true isShow.value = true;
} }
function changeTab(name) { function changeTab(name) {
console.log(name) console.log(name);
currentName.value = name currentName.value = name;
switch(name) { switch (name) {
case 'mode_switch': case "mode_switch":
doModeSwitch() doModeSwitch();
break break;
case 'mode_information': case "mode_information":
case 'basic_message': case "basic_message":
basciName.value = name basciName.value = name;
break break;
case 'log': case "log":
case 'set': case "set":
handleModal(name) handleModal(name);
break break;
case 'logout': case "logout":
handleLogout() handleLogout();
break break;
} }
} }
function handleClose() { function handleClose() {
isShowBasic.value = false isShowBasic.value = false;
} }
function handleShowBasic() { function handleShowBasic() {
isShowBasic.value = true isShowBasic.value = true;
} }
function closeModal() { function closeModal() {
isShow.value = false isShow.value = false;
} }
function modeChange(visible) { function modeChange(visible) {
if (!visible) { if (!visible) {
let sideBar = sideBarDom.value let sideBar = sideBarDom.value;
sideBar.changeMode() sideBar.changeMode();
} }
} }
function showModal() { function showModal() {
isShow.value = true isShow.value = true;
currentTag.value = AlarmModal currentTag.value = AlarmModal;
title.value = '车辆故障码' title.value = "车辆故障码";
isCloseable.value = true isCloseable.value = true;
} }
function doClose() { function doClose() {
isShowTip.value = false isShowTip.value = false;
if (tipTimer) { if (tipTimer) {
clearTimeout(tipTimer) clearTimeout(tipTimer);
tipTimer = null tipTimer = null;
} }
} }
function handleShowBoxCheck(list) { function handleShowBoxCheck(list) {
let data = list[0] let data = list[0];
if (!data) return if (!data) return;
boxCheckMsg.checkMsg = data if (data.option&&data.option.length > 0) {
isShowBoxCheck.value = true optionModel.value = data.option[0].value;
} }
boxCheckMsg.checkMsg = data;
isShowBoxCheck.value = true;
}
function handleBoxCheck(accept) { function handleBoxCheck(accept) {
let {type, value} = boxCheckMsg.checkMsg let msg = null;
handleSend({ let { type, value, option } = boxCheckMsg.checkMsg;
type: '/info/popupack',
msg: {
type,
value,
accept
}
})
vehicleStore.splitInfoPop()
}
watch(tipInfo, (msg) => { handleSend({
if (!msg) return type: "/info/popupack",
msg: {
type,
value,
accept: option&&option.length > 0 ? optionModel.value : accept,
},
});
vehicleStore.splitInfoPop();
}
const {type, value, remaintime: vehicleRemainTime, isFirst} = msg watch(
if (type === 1) { tipInfo,
isShowTip.value = true (msg) => {
vehicleTip.value = value if (!msg) return;
isFooterHide.value = false
tipTimer = setTimeout(() => {
doClose()
}, 5 * 1000)
} else if (type === 2) {
Message.info({
content: value,
duration: 10,
closable: true
})
} else {
isFooterHide.value = true
if (isFirst === 1) {
isShowTip.value = true
}
vehicleTip.value = value
remaintime.value = vehicleRemainTime
if (vehicleRemainTime < 1) {
isShowTip.value = false
}
}
vehicleStore.setData('tipInfo', null)
}, {
deep: true
})
watch(infoPop, (list) => { const { type, value, remaintime: vehicleRemainTime, isFirst } = msg;
if (list.length) { if (type === 1) {
handleShowBoxCheck(list) isShowTip.value = true;
} else { vehicleTip.value = value;
isShowBoxCheck.value = false isFooterHide.value = false;
} tipTimer = setTimeout(() => {
}, { doClose();
deep: true }, 5 * 1000);
}) } else if (type === 2) {
Message.info({
content: value,
duration: 10,
closable: true,
});
} else {
isFooterHide.value = true;
if (isFirst === 1) {
isShowTip.value = true;
}
vehicleTip.value = value;
remaintime.value = vehicleRemainTime;
if (vehicleRemainTime < 1) {
isShowTip.value = false;
}
}
vehicleStore.setData("tipInfo", null);
},
{
deep: true,
}
);
watch(
infoPop,
(list) => {
if (list.length) {
handleShowBoxCheck(list);
} else {
isShowBoxCheck.value = false;
}
},
{
deep: true,
}
);
onBeforeUnmount(() => { onBeforeUnmount(() => {
$indexRoot.destroyData() $indexRoot.destroyData();
window.removeEventListener('beforeunload', handleSubscribe()) window.removeEventListener("beforeunload", handleSubscribe());
}) });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.main { .main {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex;
flex-direction: column;
.page-header {
flex: 0 0 10vh;
min-height: 46px;
// align-items: flex-end;
}
.page-main {
background: url("/image/background.png") no-repeat;
background-size: cover;
flex: auto;
display: flex; display: flex;
flex-direction: column; height: calc(100% - 10vh);
.page-header { .side-bar {
flex: 0 0 10vh; flex: 0 0 7vw;
min-height: 46px; min-width: 70px;
// align-items: flex-end;
} }
.page-main { .container {
background: url('/image/background.png') no-repeat; flex: auto;
background-size: cover; display: flex;
flex: auto; position: relative;
.container-message {
flex: 0 0 22vw;
min-width: 240px;
display: flex; display: flex;
height: calc(100% - 10vh); flex-direction: column;
.side-bar { overflow-y: auto;
flex: 0 0 7vw; overflow-x: hidden;
min-width: 70px; .container-basic {
} flex: auto;
.container { height: calc(100% - 150px);
flex: auto; overflow-y: auto;
display: flex; overflow-x: hidden;
position: relative;
.container-message {
flex: 0 0 22vw;
min-width: 240px;
display: flex;
flex-direction: column;
overflow-y: auto;
overflow-x: hidden;
.container-basic {
flex: auto;
height: calc(100% - 150px);
overflow-y: auto;
overflow-x: hidden;
}
}
.container-message-icon {
position: absolute;
z-index: 9999;
top: 5vh;
left: 1vw;
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.25);
border-radius: 10px;
opacity: 1;
display: flex;
cursor: pointer;
}
.map {
flex: auto;
display: flex;
flex-direction: column;
}
} }
}
.container-message-icon {
position: absolute;
z-index: 9999;
top: 5vh;
left: 1vw;
background: #4a75a9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
cursor: pointer;
}
.map {
flex: auto;
display: flex;
flex-direction: column;
}
} }
}
} }
</style> </style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment