济菏高速业务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1002 lines
25 KiB

<template>
<Teleport>
<div class="mask">
<transition>
<div v-if="visible" class="content">
<div class="mainDialog">
<div class="dialog_head">
<div class="tit">{{ device.deviceName }}</div>
<img class="btnCls" src="@/assets/jihe/images/dialog/ibCls.png" alt="" @click="____onClose">
<img class="deco" src="@/assets/jihe/images/dialog/ibHeadDeco.png" alt="">
</div>
<div class="dialogContent">
<div v-if="selectedBdMsg.length > 0" class="dialogContent_box" style="height: 100%;">
<vuescroll :ops="scrollOptions" class="listBox">
<div v-for="(itm, indx) in selectedBdMsg" :key="indx" class="tplItem">
<!-- 模板内容 -->
<BoardPreview class="boardPreview" :boardWH="selectedSize" :tpl="itm"></BoardPreview>
<!-- 操作按钮 -->
<div class="infoBtnBox">
<el-tooltip content="编辑" placement="top">
<p @click="____onEditBoardItem(itm, indx)" class="btn btnEdit"></p>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<p @click="____onDeleteBoardItem(indx)" class="btn btnDelete"></p>
</el-tooltip>
</div>
</div>
</vuescroll>
</div>
<div v-else class="dialogContent_box" style="height: 100%;">
<div class="dialogContent_box_empty">暂无数据</div>
</div>
<div class="dialogContent_bottom">
<el-tabs v-model="activeTab" @tab-click="tabClickFn">
<el-tab-pane label="详情信息" name="first">
<div class="show_bottom_tab_box">
<div class="deviceInfo">
<div class="deviceInfo_l">设备名称</div>
<div class="deviceInfo_r">{{ device.deviceName }}</div>
</div>
<div class="deviceInfo">
<div class="deviceInfo_l">设备桩号</div>
<div class="deviceInfo_r">{{ device.stakeMarkId }}</div>
</div>
<div class="deviceInfo">
<div class="deviceInfo_l">屏幕像素</div>
<div class="deviceInfo_r">{{ JSON.parse(device.otherConfig).screenSize }} px</div>
</div>
<!-- <div class="deviceInfo" v-for="item in tabDataInfoList" :key="item.id">
<div class="deviceInfo_l">{{ item.tit }}: </div>
<div class="deviceInfo_r" :style="{ 'color': item.col }"> {{ item.txt }}</div>
</div> -->
</div>
</el-tab-pane>
<el-tab-pane label="设备参数" name="second">设备参数</el-tab-pane>
</el-tabs>
</div>
<div class="dialogContent_bottom_btn">
<el-button class="btnInfoBoard" type="add" @click.native="____onAddDeviceItem()">添加信息</el-button>
<el-button class="btnInfoBoard" type="publish" @click="____publishInfo" :disabled="selectedBdMsg.length <= 0">发布信息</el-button>
</div>
<div class="sideSwitch" @click="____onShowTemplate">
<img class="img" src="@/assets/screen/xtb/leftd.png" alt=""
:style="{ 'transform': isShowTemplate ? 'rotate(0deg)' : 'rotate(180deg)' }">
<div class="txt">信息模板</div>
</div>
<!-- 附近的摄像机 -->
<div class="sideSwitch" style="top:36%;" @click="____onShowCameraShower">
<img class="img" src="@/assets/screen/xtb/leftd.png" alt=""
:style="{ 'transform': dialogInfoCamera ? 'rotate(0deg)' : 'rotate(180deg)' }">
<div class="txt">附近相机</div>
</div>
</div>
</div>
<!-- 信息模板 -->
<div v-if="isShowTemplate" class="sideContent template">
<vuescroll :ops="scrollOptions" class="listBox">
<div v-for="(item, index) in templateAvailable" :key="item.dictValue">
<!-- 原来是<el-collapse v-model="activeNames"> -->
<h3>{{ item.dictLabel }}</h3>
<div v-for="(itm, indx) in item.list" :key="indx" class="tplItem">
<!-- 模板内容 -->
<BoardTplPreview class="boardPreview" :boardWH="selectedSize" :tpl="itm"></BoardTplPreview>
<!-- <div class="infoPreview">
<div class="infoBox" :style="____boardBgStyle">
<span class="infoTxt" :style="____boardTxtStyle(itm)" v-html="itm.content.replace(/\n|\r\n/g, '<br>').replace(/ /g, '&nbsp')"></span>
</div>
</div> -->
<!-- 操作按钮 -->
<div class="infoBtnBox infoBtnBoxSm">
<el-tooltip content="加入待下发信息" placement="top">
<p @click="____onAddToDevice(itm)" class="btn btnApply"></p>
</el-tooltip>
</div>
</div>
</div>
</vuescroll>
</div>
<!-- 附近相机 -->
<CameraShower class="sideContent camera" :visible.sync="dialogInfoCamera" :list="nearbyCameraList"></CameraShower>
</div>
</transition>
<BoardInfoEditor @afterSubmit="____onEditSubmit" :mode="editDialog.mode" :type="editDialog.type"
:visible.sync="editDialog.visible" :screenSize="selectedSize" :tpl="editDialog.tpl"></BoardInfoEditor>
</div>
</Teleport>
</template>
<script>
import { listDevice, invokedFunction, getDeviceRealtimeProperty } from '@/api/device/device.js'
// import infoBoardTestData from "@/common/infoBoardTestData.js"
import { getBoardDeviceInfo } from '@/api/board/board'
import { getNearbyCameraByPileNum } from '@/api/camera/camera'
import BoardPreview from "@screen/components/infoBoard/BoardPreview.vue"
import BoardTplPreview from "@screen/components/infoBoard/BoardTplPreview.vue"
import BoardInfoEditor from '@screen/components/infoBoard/BoardInfoEditor'
import vuescroll from 'vuescroll'
import scrollOptions from '@/common/scrollbar.js'
import Teleport from '@screen/components/Teleport.vue'
import { publishToBoard } from '@/api/board/board'
import { getTemplateList } from '@/api/board/template'
import testDeviceInfo from "@screen/testData/infoBoard.js"
import CameraShower from '@screen/components/CameraShower'
export default {
name: 'InfoBoard',
data() {
return {
isShowTemplate: false,
dialogInfoCamera: false,
dialogInfoList: [],
moBanList: [],
activeNames: [1001, 1002],
activeTab: "first",
tabDataInfoList: [],
cameraDataVideoList: [],
cameraDataList: [
{ id: 3001, txt: '设备名称', val: '疲劳唤醒设备1' },
{ id: 3002, txt: '设备编号', val: 'G00030497B0180001' },
{ id: 3003, txt: '设备桩号', val: 'K097+900' },
{ id: 3004, txt: '经/纬度', val: '117.071152/35.910659' },
{ id: 3005, txt: '道路名称', val: 'G35济菏高速' },
{ id: 3006, txt: '道路状况', val: '正常' },
{ id: 3007, txt: '方向', val: '菏泽' }
],
cameraBtnList: [
{ id: 4001, cmd: 23, dir: 'left', le: '26%', to: '33%', ro: 0 },
{ id: 4002, cmd: 21, dir: 'up', le: '46%', to: '4%', ro: 90 },
{ id: 4003, cmd: 24, dir: 'right', le: '65%', to: '33%', ro: 180 },
{ id: 4004, cmd: 22, dir: 'downward', le: '46%', to: '62%', ro: 267 }
],
cameraControlList: [
{ id: 5001, txt: '变倍', numL: 11, numR: 12 },
{ id: 5002, txt: '光圈', numL: 16, numR: 15 },
{ id: 5003, txt: '聚焦', numL: 14, numR: 13 }
],
selectedBdMsg: [],
selectedSize: "",
editDialog: {
mode: "",
type: "",
visible: false,
tpl: {}
},
scrollOptions,
templateAvailable: null,
tplCategory: [], //模板
templateAll: [],
nearbyCameraList:[]
}
},
props: {
visible: {
type: Boolean,
default: false
},
device: {
type: Object,
default: null
}
},
watch: {
device: {
handler(newV) {
this.____initData();
},
immediate: true
}
},
components: { BoardPreview, BoardTplPreview, BoardInfoEditor, vuescroll, Teleport,
CameraShower
},
created() {
// this.____getTemplateCategory();
// this.____getAllTemplate();
},
computed: {
},
mounted() {
},
methods: {
// 获取信息模板分类
____getTemplateCategory() {
return this.getDicts('iot_template_category').then(res => {
this.tplCategory = res.data;
})
},
//获取全部模版
____getAllTemplate() {
return getTemplateList().then((res) => {
this.templateAll = res.data;
});
},
//初始化数据
____initData() {
this.selectedSize = JSON.parse(this.device.otherConfig).screenSize;
if(this.tplCategory.length && this.templateAll.length){
this.____setAvailableTemplate();
}else{
Promise.all([this.____getTemplateCategory(), this.____getAllTemplate()]).then(res=>{
this.____setAvailableTemplate();
})
}
this.____getDeviceInfo();
},
// 获取已选中设备的展示内容
____getDeviceInfo(){
if (IS_TESTING) {
this.selectedBdMsg = _.cloneDeep(testDeviceInfo.data["3A"].content);
}else{
getBoardDeviceInfo(this.device.iotDeviceId).then(res => {
this.selectedBdMsg = res.data["3A"].content;
}).catch(err => {
})
}
},
// 设置当前设备可用的模板
____setAvailableTemplate() {
this.templateAvailable = [];
this.tplCategory.forEach((item, index) => {
let arr = this.templateAll['' + index];
if (arr.length > 0) {
let temp = [];
arr.forEach(tpl => {
if (tpl.screenSize == this.selectedSize) {
temp.push(tpl);
}
})
if (temp.length > 0) {
this.templateAvailable.push({
...item,
list: temp
});
}
}
})
},
//调用编辑器编辑设备展示项
____onEditBoardItem(tpl, index) {
// type : board template
// mode : edit add toDevice toTemplate
this.boardItemEdtingIndex = index;
this.editDialog = {
visible: true,
mode: "edit",
type: "device",
tpl
}
},
//删除设备展示项
____onDeleteBoardItem(index) {
if (index > -1) {
this.selectedBdMsg.splice(index, 1)
this.$message.success('删除成功,发布后才效。')
}
},
//编辑机编辑后的回调
____onEditSubmit(para) {
this.editDialog.tpl = {};
this.editDialog.visible = false;
if (para.type == "device") {
if (para.mode == "edit") {
this.selectedBdMsg[this.boardItemEdtingIndex] = para.data;
} else {
this.selectedBdMsg.push(para.data);
}
} else if (para.mode == "toDevice") {
this.selectedBdMsg.push(para.data);
} else {
this.____refreshPageData(para);
}
},
____refreshPageData(para) { },
// 从模板新增待下发
____onAddToDevice(item) {
let arr = this.selectedSize.split("*");
item.origin = {
displayAreaWidth: +arr[0],
displayAreaHeight: +arr[1]
}
console.log(item);
this.editDialog = {
visible: true,
mode: "toDevice",
type: "template",
tpl: item,
}
},
// 新增待下发
____onAddDeviceItem() {
let arr = this.selectedSize.split("*");
this.editDialog = {
visible: true,
mode: "add",
type: "device",
tpl: {
"textContent": "",
origin: {
displayAreaWidth: +arr[0],
displayAreaHeight: +arr[1]
}
}
}
},
____getNearbyCams() {
if(!this.device.stakeMarkId){
this.$message.warning("设备缺少stakeMarkId字段...");
}
let stakeMarkId = this.device.stakeMarkId;
// stakeMarkId = "K64+300";
getNearbyCameraByPileNum(stakeMarkId).then(res=>{
this.nearbyCameraList = res.data;
})
},
cameraControlBtnFn(item) {
this.getEnergyCameraControlFn(item.cmd, 5)
},
cameraControlLeFn(item) {
// console.log('按钮点击事件', item)
this.getEnergyCameraControlFn(item, 5)
},
getEnergyCameraControlFn(cmd, spe) {
getEnergyCameraControlAPi({ camId: this.cameraVal, cmdType: cmd, speed: spe }).then(res => {
// console.log('控制返回结果', res)
// this.videoUrl = res.data.liveUrl
})
},
cameraValChangeFn() {
console.log('点击切换按钮', this.cameraVal)
this.cameraValCha(this.cameraOptList, this.cameraVal)
},
// cameraDataVideoList
cameraValCha(date, num) {
let str = {
0: '正常',
1: '网络中断',
2: '网络正常无图像',
3: '有图像图可能存在问题'
}
date.forEach(i => {
if (i.camId === num) {
this.cameraDataVideoList = [
{ id: 3001, txt: '设备名称', val: i.camName },
{ id: 3002, txt: '设备编号', val: i.camId },
{ id: 3003, txt: '设备桩号', val: i.pileNum },
{ id: 3005, txt: '道路名称', val: i.deptName },
{ id: 3006, txt: '道路状况', val: i.status == '-1' ? '未启用' : str[Number(i.status)] }
]
}
})
},
// 发布信息
____publishInfo() {
this.$confirm('是否确定发布情报板?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
let content = [];
this.selectedBdMsg.forEach(item => {
content.push({
STAY: item.playbackDuration,
ACTION: item.screenEntryMethod,
SPEED: item.fontSpacing,
COLOR: item.foregroundColor,
FONT: item.font,
FONT_SIZE: item.fontSize,
CONTENT: item.textContent.replaceAll(',', '\\,').replaceAll('=', '\\=').replaceAll('\n', '\\\\n'),
width: item.displayAreaWidth,
height: item.displayAreaHeight,
formatStyle: item.verticalAlignment
})
})
let data = { content: content, deviceId: this.device.iotDeviceId }
console.log(data, "发布内容");
if (IS_TESTING) {
console.log("测试模式")
this.____getDeviceInfo();
loading.close()
}else{
publishToBoard(data).then(res=>{
loading.close()
this.____getDeviceInfo();
});
}
}).catch(() => {
this.$message({
type: 'info',
message: '取消发布'
})
})
},
tabClickFn(tab, event) {
console.log(tab, event)
},
____onClose() {
this.$emit("update:visible", false);
this.isShowTemplate = false
},
____onShowTemplate() {
if (this.dialogInfoCamera) {
this.dialogInfoCamera = false
}
this.isShowTemplate = !this.isShowTemplate
},
____onShowCameraShower() {
if (this.isShowTemplate) {
this.isShowTemplate = false
}
this.dialogInfoCamera = !this.dialogInfoCamera
this.____getNearbyCams();
},
subjectBtnFn(item) {
this.subjectBtn = item.id
}
}
}
</script>
<style lang='scss' scoped>
.listBox {
padding: 20px;
.tplItem {
margin-right: 14px;
display: flex;
align-items: stretch;
padding-bottom: 10px;
.boardPreview {
border: 1px solid rgba(61, 232, 255, 0.5);
// width: 560px;
// height:80px;
flex: 1;
}
.infoBtnBox {
&.infoBtnBoxSm{
width: 60px;
}
width: 110px;
height: 80px;
display: flex;
margin-left: 10px;
/* // border: solid 1px #05afe3; */
border: 1px solid rgba(61, 232, 255, 0.5);
display: flex;
justify-content: space-around;
align-items: center;
.btn {
background-repeat: no-repeat;
background-size: 100% 100%;
width: 30px;
height: 30px;
&.btnApply {
background-image: url(~@/assets/jihe/images/button/toLeft.svg);
}
&.btnEdit {
background-image: url(~@/assets/jihe/images/button/edit.svg);
}
&.btnDelete {
background-image: url(~@/assets/jihe/images/button/delete.svg);
}
}
i {
font-size: 24px;
color: #666;
padding-left: 4px;
cursor: pointer;
caret-color: rgba(0, 0, 0, 0);
user-select: none;
}
i:hover {
color: #05afe3;
}
.disabledClass {
pointer-events: none;
cursor: auto !important;
color: #ccc;
}
}
}
.controlBox {
margin-top: 10px;
margin-bottom: 10px;
display: flex;
justify-content: center;
}
.el-collapse {
max-height: 100% !important;
overflow: auto;
border-bottom: none;
border-top: none;
padding: 0 0.5vw;
}
}
.mask {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(0, 0, 0, .36);
z-index: 1100;
display: flex;
justify-content: center;
align-items: center;
.content {
display: flex;
flex-direction: row;
}
}
.mainDialog {
width: 510px;
height: 620px;
background-color: #114c66;
margin-right: 3px;
}
.sideContent {
border: 2px solid #196980;
background-color: #114c66;
position: relative;
margin-top: 50px;
&.camera{
width: 540px;
height: 556px;
}
&.template{
width: 430px;
height: 556px;
padding:20px 0 20px 10px;
}
}
.dialog_head {
width: 100%;
height: 48px;
padding: 0 10px;
background-image: url('~@/assets/screen/xtb/qbbtit.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
.tit {
color: #3de8ff;
font-size: 18px;
}
.btnCls {
width: 13px;
height: 13px;
cursor: pointer;
}
.deco {
width: 55%;
height: 5px;
position: absolute;
left: 0;
top: 0;
}
}
.dialogContent {
width: 100%;
height: 300px;
padding: 10px 24px 10px 10px;
position: relative;
}
.dialogContent_box {
width: 100%;
// height: 100%;
overflow-y: scroll;
}
.dialogContent_l {
width: 355px;
// height: 4.91vh;
border: 2px solid #1d7890;
padding: 1px 0;
display: flex;
justify-content: center;
align-items: center;
}
.dialogContent_r {
width: 96px;
// height: 4.91vh;
border: 2px solid #1d7890;
display: flex;
justify-content: space-around;
align-items: center;
}
.dialogContent_l_xsq {
width: 256px;
height: 100%;
font-size: 18px;
color: #ff0000;
background-color: #000;
line-height: 1;
// text-align: center;
display: flex;
// justify-content: center;
align-items: center;
}
.show_r_btn {
width: 1.67vw;
height: 2.96vh;
cursor: pointer;
}
.dialogContent_r_btn1 {
background-image: url('~@/assets/screen/xtb/gg.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.dialogContent_r_btn2 {
background-image: url('~@/assets/screen/xtb/xx.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.dialogContent_r_btn3 {
background-image: url('~@/assets/screen/xtb/zz.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.dialogContent_box_item {
margin-bottom: 0.5vh;
display: flex;
justify-content: space-between;
}
.dialogContent_bottom {
width: 105%;
height: 16.52vh;
}
.deviceInfo {
width: 50%;
padding: 10px 0;
display: flex;
// flex-wrap: wrap;
align-items: stretch;
}
.show_bottom_tab_box {
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.deviceInfo_l {
color: #3de8ff;
font-size: 14px;
width: 70px;
display: flex;
flex-direction: row;
align-items: center;
}
.deviceInfo_r {
width: 0;
flex: 1;
color: #fff;
font-size: 14px;
margin-left: 0.5vw;
}
.sideSwitch {
position: absolute;
right: 0%;
top: 0%;
width: 24px;
line-height: 1.2;
padding: 0.5vh 0;
background: linear-gradient(180deg, #005c79 0%, #009bcc 100%);
border-radius: 0px 0px 0px 0px;
opacity: 1;
text-align: center;
cursor: pointer;
.img {
width: 15px;
height: 10px;
border: none;
transition: transform 0.3s ease;
/* 过渡效果 */
}
.txt {
color: #fff;
font-size: 13px;
}
}
.dialogContent_box_empty {
font-size: 14px;
text-align: center;
color: #fff;
}
.dialog_info_right_tit {
color: #fff;
font-size: 14px;
margin-bottom: 0.5vh;
}
.dialog_info_right_show {
width: 100%;
// height: 28vh;
}
.dialogContent_bottom_btn {
height: 28px;
display: flex;
justify-content: flex-end;
align-items: center;
text-align: center;
}
.info_right_camera {
width: 100%;
height: calc(100% - 4vh);
padding: 1vh 0.5vw;
}
.info_right_camera_top {
width: 100%;
height: 20vh;
}
.info_right_camera_bom {
width: 100%;
padding: 1vh 0;
height: calc(100% - 20vh);
display: flex;
}
.camera_bom_left {
width: 50%;
height: 100%;
padding: 2vh 0;
border-right: 1px dashed #285a71;
}
.camera_bom_right {
width: 50%;
height: 100%;
}
.camera_bom_left_item {
width: 100%;
color: #fff;
display: flex;
font-size: 14px;
padding-bottom: 1.5vh;
}
.camera_bom_left_item_txt {
width: 31%;
color: #3de8ff;
}
.camera_bom_left_item_val {
color: #fff;
font-size: 13px;
}
.camera_bom_right_t {
width: 100%;
height: 60%;
position: relative;
}
.camera_bom_right_b {
width: 100%;
height: 40%;
// background-color: deeppink;
}
.camera_bom_right_t_box {
width: 2vw;
height: 4vh;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #005f87;
border-radius: 50%;
border: 1px solid #2191b1;
}
.camera_bom_right_t_h_po {
width: 1vw;
height: 5vh;
position: absolute;
left: 27%;
top: 33%;
cursor: pointer;
background-image: url('~@/assets/screen/xtb/xjleft.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
.camera_bom_right_b_btn {
width: 100%;
padding: 0vh 2vw 1vh 2vw;
display: flex;
justify-content: space-between;
}
.camera_bom_right_b_btn_l {
width: 1.2vw;
height: 2.4vh;
border-radius: 50%;
background-image: url('~@/assets/screen/xtb/jhbtn.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
}
.camera_bom_right_b_btn_c {
color: #fff;
}
.camera_bom_right_b_btn_r {
width: 1.2vw;
height: 2.4vh;
border-radius: 50%;
background-image: url('~@/assets/screen/xtb/addbtn.png');
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
}
// background-color: #104b65;
// background-image: url('~@/assets/screen/xtb/qbbtit.png');
// background-size: 100% 100%;
// background-repeat: no-repeat;
// background-position: center;
/* 通用滚动条样式 */
::-webkit-scrollbar {
width: 3px;
/* 设置滚动条宽度 */
height: 3px;
/* 设置滚动条高度 */
}
::-webkit-scrollbar-track {
background-color: #114c66;
/* 设置滚动条轨道颜色 */
}
::-webkit-scrollbar-thumb {
background-color: #9abce0;
/* 设置滚动条滑块颜色 */
border-radius: 4px;
/* 设置滚动条滑块圆角 */
}
::v-deep .el-tabs__nav-wrap::after {
background-color: #316076;
}
::v-deep .el-tabs__item.is-active {
color: #3de8ff !important;
}
::v-deep .el-tabs__item {
color: #fff !important;
}
::v-deep .el-tabs__active-bar {
background-color: #3de8ff !important;
}
::v-deep .el-collapse-item__header {
color: #fff;
height: 28px;
background-color: #053b4f;
border: none;
padding-left: 0.5vw;
}
::v-deep .el-collapse {
color: #fff;
border: none;
}
::v-deep .el-collapse-item__wrap {
color: #fff;
will-change: height;
background-color: #053b4f;
overflow: hidden;
-webkit-box-sizing: border-box;
box-sizing: border-box;
margin-top: 0.5vh;
border: none;
}
::v-deep .el-collapse-item__content {
margin-bottom: 0;
padding: 0.5vh 0.5vw;
}
::v-deep .el-collapse-item {
margin-bottom: 1vh;
}
::v-deep .el-input--mini .el-input__icon {
line-height: 20px;
color: #fff;
}
</style>