lau572 1 year ago
parent
commit
af2a690e2b
  1. 12
      ruoyi-ui/src/api/map/index.js
  2. BIN
      ruoyi-ui/src/assets/screen/xtb/xjbuttom.png
  3. BIN
      ruoyi-ui/src/assets/screen/xtb/xjleft.png
  4. BIN
      ruoyi-ui/src/assets/screen/xtb/xjright.png
  5. BIN
      ruoyi-ui/src/assets/screen/xtb/xjtop.png
  6. 5
      ruoyi-ui/src/views/boardView/editInfo.vue
  7. 167
      ruoyi-ui/src/views/components/videoPlayer/myVideo.vue
  8. 349
      ruoyi-ui/src/views/index.vue
  9. 192
      ruoyi-ui/src/views/map/Thumbnail/data.js
  10. BIN
      ruoyi-ui/src/views/map/Thumbnail/images/bg.png
  11. BIN
      ruoyi-ui/src/views/map/Thumbnail/images/tag0.png
  12. BIN
      ruoyi-ui/src/views/map/Thumbnail/images/tag1.png
  13. BIN
      ruoyi-ui/src/views/map/Thumbnail/images/tag2.png
  14. BIN
      ruoyi-ui/src/views/map/Thumbnail/images/tag3.png
  15. BIN
      ruoyi-ui/src/views/map/Thumbnail/images/tag4.png
  16. 176
      ruoyi-ui/src/views/map/Thumbnail/index.vue
  17. 20
      ruoyi-ui/src/views/map/Thumbnail/utils.js
  18. 43
      ruoyi-ui/src/views/map/index.vue

12
ruoyi-ui/src/api/map/index.js

@ -0,0 +1,12 @@
import request from '@/utils/request'
// 地图 情报板接口
export function getEnergyBoardAPi(params){
return request({
url:'/iot/board/list',
method:'get',
params
})
}

BIN
ruoyi-ui/src/assets/screen/xtb/xjbuttom.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
ruoyi-ui/src/assets/screen/xtb/xjleft.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
ruoyi-ui/src/assets/screen/xtb/xjright.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
ruoyi-ui/src/assets/screen/xtb/xjtop.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

5
ruoyi-ui/src/views/boardView/editInfo.vue

@ -437,13 +437,16 @@ export default {
this.dialogVisible = true
this.itemPropertyMap = new HashMap()
this.alignmentNum = 2
console.log('点击编辑按钮数据回显', this.boardEmitItem)
this.dataForm = JSON.parse(JSON.stringify(this.boardEmitItem))
this.dataForm.formatStyle = this.formatStyle
this.dataForm.COLOR = this.getColorValue(this.boardEmitItem.COLOR)
console.log(this.dataForm, 'this.dataForm')
// this.dataForm.FONT = this.getFont(this.boardEmitItem.FONT)
this.dataForm.CONTENT = JSON.parse(JSON.stringify(this.boardEmitItem.CONTENT.replace('<br>', '\n').replace(/ /g, ' ').replace('<r><n>', '\n')))
this.dataForm.STAY = JSON.parse(JSON.stringify(Number(this.boardEmitItem.STAY) / 100))
// this.dataForm.STAY = JSON.parse(JSON.stringify(Number(this.boardEmitItem.STAY) / 100))
this.dataForm.STAY = Number(this.boardEmitItem.playbackDuration) / 10
console.log('数据回显处理后的参数', this.dataForm)
this.getFontSizeList()
},
getColorValue(color) {

167
ruoyi-ui/src/views/components/videoPlayer/myVideo.vue

@ -0,0 +1,167 @@
<template>
<div class="video-box" v-loading="loading">
<video class="demo-video" ref="player" muted autoplay @dblclick="fullScreen"></video>
</div>
</template>
<script>
import flvjs from 'flv.js'
export default {
props: {
url: {
type: String,
default: ''
}
},
data() {
return {
// id: '1',
player: null,
lastDecodedFrames: 0,
loading: false
}
},
watch: {
url: {
handler() {
if (this.player) {
this.player.unload();
this.player.destroy();
this.player = null;
}
this.playVideo()
},
deep: true
}
},
mounted() {
if (this.player) {
//this.player.stream.close();
this.player.unload();
this.player.destroy();
this.player = null;
}
this.$nextTick(() => {
this.playVideo()
//
/* setInterval(() => {
if (this.player.buffered.length) {
let end = this.player.buffered.end(0);//buffered
let diff = end - this.player.currentTime;//bufferedcurrentTime
console.log('跳帧',diff)
if (diff >= 0.5) {//0.5
this.player.currentTime = this.player.buffered.end(0);//
}
}
}, 2000); //2000*/
})
},
beforeDestroy() {
this.destroyFlv()
},
methods: {
fullScreen() {
if (this.$refs.player.requestFullScreen) {
this.$refs.player.requestFullScreen()
} else if (this.$refs.player.mozRequestFullScreen) {
this.$refs.player.mozRequestFullScreen()
} else if (this.$refs.player.webkitRequestFullScreen) {
this.$refs.player.webkitRequestFullScreen()
}
},
playVideo() {
const time1 = new Date().getTime();
if (flvjs.isSupported()) {
let video = this.$refs.player;
if (video) {
this.loading = true;
//
this.player = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: this.url
},{
enableStashBuffer: false,
autoCleanupSourceBuffer: true,
lazyLoad:false
});
this.player.attachMediaElement(video);
try {
this.player.load();
this.player.play().then(() => {
console.log("首屏打开用时", new Date().getTime() - time1);
this.loading = false
})
this.listenVideo()
} catch (error) {
this.loading = false
console.log("播放失败", error)
}
}
}
},
//
listenVideo() {
const that = this;
this.player.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {
console.log("视频播放出错,错误类型:", errorType,"错误详情:",errorDetail,"错误信息:",errorInfo);
//
that.destroyFlv();
that.playVideo();
}
);
//
this.player.on("statistics_info", function (res) {
if(that.lastDecodedFrames === 0){
that.lastDecodedFrames = res.decodedFrames
return
}
if(that.lastDecodedFrames != res.decodedFrames){
that.lastDecodedFrames = res.decodedFrames
}else{
that.lastDecodedFrames = 0
//that.destroyFlv()
//that.playVideo()
}
});
},
//
destroyFlv() {
if (this.player) {
this.player.pause();
this.player.unload();
this.player.detachMediaElement();
this.player.destroy();
this.player = null;
}
},
},
}
</script>
<style lang="scss">
.video-box {
width: 100%;
height: 100%;
video {
width: 100%;
height: 100%;
object-fit: fill;
}
.demo-video{
background-color: #4b4b4b;
}
//
/*video::-webkit-media-controls-play-button {
display: none;
}
video::-webkit-media-controls-current-time-display {
display: none;
}
video::-webkit-media-controls-timeline {
display: none;
}*/
}
</style>

349
ruoyi-ui/src/views/index.vue

@ -3,10 +3,6 @@
<!-- 地图 -->
<div class="home_page_map">
<GaoDeMap @mapClickEventFn="mapClickEvent" />
</div>
<!-- 地图弹框 -->
<div ref="mapDialog" class="map_dialog" :style="{'top':mapDialogTop,'left':mapDialogLeft}">
</div>
<!-- 情报板弹框 -->
<transition name="el-zoom-in-center">
@ -22,7 +18,10 @@
<div class="dialog_info_left_show_box_item" v-for="i in dialogInfoList" :key="i.id">
<div class="dialog_info_left_show_l">
<div class="dialog_info_left_show_l_xsq" :style="{'width':processString(i.screenSize,'w') / getScrollSz(processString(i.screenSize,'w'))+'px','height':processString(i.screenSize,'h') / getScrollSz(processString(i.screenSize,'w'))+'px','justify-content':getTextAlign(i.tcontents[0].formatStyle)}">
<div class="dialog_info_left_show_l_xsq_txt" :style="{'font-size':i.tcontents[0].fontSize / getScrollSz(processString(i.screenSize,'w'))+'px','color':'#'+i.tcontents[0].fontColor,'font-family':i.tcontents[0].fontType,}" v-html="i.tcontents[0].content"></div>
<div class="dialog_info_left_show_l_xsq_txt" :style="{'font-size':i.tcontents[0].fontSize / getScrollSz(processString(i.screenSize,'w'))+'px','color':'#'+i.tcontents[0].fontColor,'font-family':i.tcontents[0].fontType,}" v-html="i.tcontents[0].content.replace(/\n|\r\n/g, '<br>').replace(
/ /g,
'&nbsp'
)"></div>
</div>
</div>
<div class="dialog_info_left_show_r">
@ -55,31 +54,74 @@
<img class="show_ce_img" src="@/assets/screen/xtb/leftd.png" alt="" :style="{'transform':dialogInfoRight ? 'rotate(0deg)': 'rotate(180deg)'}">
<div class="show_ce_txt">信息模板</div>
</div>
<div class="dialog_info_left_show_ce" style="top:36%;" @click="showCameraInfoFn">
<img class="show_ce_img" src="@/assets/screen/xtb/leftd.png" alt="" :style="{'transform':dialogInfoCamera ? 'rotate(0deg)': 'rotate(180deg)'}">
<div class="show_ce_txt">附近像机</div>
</div>
</div>
</div>
<transition name="el-zoom-in-center">
<div v-if="dialogInfoRight" class="dialog_info_right">
<el-collapse v-model="activeNames" @change="panelChangeFn">
<el-collapse-item v-for="item in moBanList" :key="item.dictCode" :title="item.dictLabel" :name="item.dictCode">
<div class="dialog_info_right_show">
<div class="dialog_info_left_show_box" style="overflow-y: visible;">
<div class="dialog_info_left_show_box_item" v-for="i in item.mbList" :key="i.id">
<div class="dialog_info_left_show_l" style="width:16vw;">
<div class="dialog_info_left_show_l_xsq" :style="{'width':processString(i.screenSize,'w') / getScrollSz(processString(i.screenSize,'w'))+'px','height':processString(i.screenSize,'h') / getScrollSz(processString(i.screenSize,'w'))+'px','justify-content':getTextAlign(i.tcontents[0].formatStyle)}">
<div class="dialog_info_left_show_l_xsq_txt" :style="{'font-size':i.tcontents[0].fontSize / getScrollSz(processString(i.screenSize,'w'))+'px','color':'#'+i.tcontents[0].fontColor,'font-family':i.tcontents[0].fontType}" v-html="i.tcontents[0].content"></div>
</div>
</div>
<div class="dialog_info_left_show_r" style="width: 3.5vw;">
<div @click="putLeftFn(i)" class="show_r_btn dialog_info_left_show_r_btn3"></div>
<!-- 信息模板 -->
<div v-if="dialogInfoRight" class="dialog_info_right">
<el-collapse v-model="activeNames" @change="panelChangeFn">
<el-collapse-item v-for="item in moBanList" :key="item.dictCode" :title="item.dictLabel" :name="item.dictCode">
<div class="dialog_info_right_show">
<div class="dialog_info_left_show_box" style="overflow-y: visible;">
<div class="dialog_info_left_show_box_item" v-for="i in item.mbList" :key="i.id">
<div class="dialog_info_left_show_l" style="width:16vw;">
<div class="dialog_info_left_show_l_xsq" :style="{'width':processString(i.screenSize,'w') / getScrollSz(processString(i.screenSize,'w'))+'px','height':processString(i.screenSize,'h') / getScrollSz(processString(i.screenSize,'w'))+'px','justify-content':getTextAlign(i.tcontents[0].formatStyle)}">
<div class="dialog_info_left_show_l_xsq_txt" :style="{'font-size':i.tcontents[0].fontSize / getScrollSz(processString(i.screenSize,'w'))+'px','color':'#'+i.tcontents[0].fontColor,'font-family':i.tcontents[0].fontType}" v-html="i.tcontents[0].content.replace(/\n|\r\n/g, '<br>').replace(
/ /g,
'&nbsp'
)"></div>
</div>
</div>
<div class="dialog_info_left_show_r" style="width: 3.5vw;">
<div @click="putLeftFn(i)" class="show_r_btn dialog_info_left_show_r_btn3"></div>
</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
</div>
</el-collapse-item>
</el-collapse>
</div>
<!-- 附近相机 -->
<div v-if="dialogInfoCamera" class="dialog_info_right" style="padding:0;">
<div class="dialog_info_left_t" style="height:4vh;">
<div class="dialog_info_left_t_txt">摄像机设备</div>
<img class="dialog_info_left_t_img" src="@/assets/screen/xtb/close.png" alt="" @click="closeCameraBtnFn">
<img class="dialog_info_left_t_ti" src="@/assets/screen/xtb/cltiao.png" alt="">
</div>
<div class="info_right_camera">
<div class="info_right_camera_top">
<!-- 视频组件 -->
</div>
<div class="info_right_camera_bom">
<div class="camera_bom_left">
<div class="camera_bom_left_item">
<div class="camera_bom_left_item_txt">选择相机: </div>
<div class="camera_bom_left_item_val">
<el-select v-model="cameraVal" placeholder="请选择" size="mini" style="width:120px">
<el-option v-for="item in cameraOptList" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
</div>
</div>
<div class="camera_bom_left_item" v-for="item in cameraDataList" :key="item.id">
<div class="camera_bom_left_item_txt">{{ item.txt }}: </div>
<div class="camera_bom_left_item_val">{{ item.val }}</div>
</div>
</div>
<div class="camera_bom_right">
<div class="camera_bom_right_t">
<div class="camera_bom_right_t_box"></div>
<div class="camera_bom_right_t_h_po" v-for="item in cameraBtnList" :key="item.id" :style="{'left':item.le,top:item.to,'transform':'rotate('+item.ro+'deg)'}"></div>
</div>
<div class="camera_bom_right_b"></div>
</div>
</div>
</div>
</transition>
</div>
</div>
</transition>
<!-- 情报板弹框中的弹框 -->
@ -160,8 +202,7 @@
</div>
<!-- -->
<div class="home_page_road">
<div class="home_page_road_t"></div>
<div class="home_page_road_b"></div>
<roadView />
</div>
</div>
</template>
@ -174,10 +215,23 @@ import editBoard from '@/views/boardView/editInfo.vue'
import { invokedFunction, getDeviceRealtimeProperty } from '@/api/device/device.js'
import { getAllVmsTemplate, deleteTemplate } from '@/api//board/template.js'
import { getDicts } from '@/api/system/dict/data.js'
import roadView from '@/views/map/Thumbnail/index.vue'
export default {
name: 'indexView',
data() {
return {
cameraVal: '1',
cameraOptList: [
{
value: '1',
label: '一号相机'
},
{
value: '2',
label: '二号相机'
}
],
editOutlineData: {},
formData: [],
mapIds: '',
screenDataSize: '',
@ -186,8 +240,9 @@ export default {
boardEmitItem: {}, //
activeName: 'first',
dialogTit: '门架式可变信息标志YK16+270',
dialogInfoLeft: false,
dialogInfoLeft: true,
dialogInfoRight: false,
dialogInfoCamera: true,
mapDialogTop: '0px',
mapDialogLeft: '0px',
keyMonitoringList: [
@ -247,13 +302,28 @@ export default {
{ id: 404, tit: '设备桩号', txt: 'K094+079', col: '#fff' },
{ id: 405, tit: '设备厂商', txt: '光电比特', col: '#fff' },
{ id: 406, tit: '设备状态', txt: '离线', col: '#888' }
],
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, dir: 'left', le: '26%', to: '33%', ro: 0 },
{ id: 4002, dir: 'up', le: '46%', to: '4%', ro: 90 },
{ id: 4003, dir: 'right', le: '65%', to: '33%', ro: 180 },
{ id: 4004, dir: 'downward', le: '46%', to: '62%', ro: 267 }
]
}
},
props: [],
//
components: { GaoDeMap, carECharts, addBoard, editBoard },
components: { GaoDeMap, carECharts, addBoard, editBoard, roadView },
//
computed: {},
//
@ -261,7 +331,7 @@ export default {
this.getTemplateHeaderFn()
// this.getTemplateFn()
},
//
// //
// watch: {
// data: {
// // ,使handler
@ -282,9 +352,9 @@ export default {
this.dialogInfoList = []
console.log('父组件地图点位', e)
this.dialogInfoLeft = true
this.mapIds = e.target._opts.extData.ids
this.screenDataSize = e.target._opts.extData.screenSize
this.dialogTit = e.target._opts.extData.tit
this.mapIds = e.target._opts.extData.deviceId
this.screenDataSize = e.target._opts.extData.sceenSize
this.dialogTit = e.target._opts.extData.deviceName
this.getTemplateHeaderFn()
this.onSubmit(this.mapIds)
// this.mapDialogTop = e.pixel.y + 'px'
@ -321,7 +391,7 @@ export default {
let newArr = this.dialogInfoList.map(item => {
let obj = {}
obj.STAY = item.stopTime
obj.STAY = item.STAY
obj.ACTION = item.inScreenMode
obj.SPEED = item.tcontents[0].fontSpacing
obj.COORDINATE = item.screenSize.replace('*', '')
@ -344,33 +414,21 @@ export default {
const param = {
objectData: JSON.stringify(objAll)
}
console.log('newArr11111', newArr)
/* invokedFunction(65,'1B',{fileId:'1'}).then(res =>{
debugger
console.log('发布消息,播放文件-----------------------------')
console.log(res)
}).catch(()=>{
this.$modal.msgError("发布失败,请重试");
})*/
invokedFunction(595, 11, { size: '65535', fileName: 'play099.lst' })
.then(res => {
debugger
console.log('发布消息,校验文件名-------------------------------------')
console.log(res)
// console.log(',-------------')
if (res.data.result == '01') {
invokedFunction(595, 13, { parameters: newArr })
.then(res => {
debugger
console.log('发布消息,发送文件内容-----------------------------')
console.log(res)
// console.log(',-----')
if (res.data.result == '01') {
invokedFunction(595, '1B', { fileId: '99' })
.then(res => {
debugger
console.log('发布消息,播放文件-----------------------------')
console.log(res)
// console.log(',-----')
})
.catch(() => {
this.$modal.msgError('发布失败,请重试')
@ -397,45 +455,15 @@ export default {
},
//
onSubmit(deviceId) {
// this.submitButton = true
// // this.loading = true
// this.contentList = []
// //
// const param = {
// deviceId: deviceId
// }
/* await getBoardContentData(param)
.then(res => {
console.log(res, 'onSubmit')
var contents = res.data.parameters
console.log(contents, 'onSubmit-----contents')
for (let i = 0; i < contents.length; i++) {
let item = contents[i]
item.COLOR = this.getColorStyle(item.COLOR)
item.FONT_SIZE = Number(item.FONT_SIZE.substring(0, 2)) + 'px'
item.ID = i
item.FONT = this.getFont(item.FONT)
this.contentList.push(item)
}
console.log(this.contentList, 'onSubmit-----this.contentList')
this.loading = false
this.submitButton = false
// this.rowDrop();
})
.catch(e => {
this.loading = false
this.submitButton = false
})*/
getDeviceRealtimeProperty(deviceId, '3A', { async: false })
.then(res => {
console.log('回读消息------------------------')
var contentsA = res.data['3A'].content
console.log('回读消息--1111111111---', contentsA)
this.dialogInfoList = contentsA.map(item => {
return {
...item,
stopTime: item.residenceTime,
STAY: item.playbackDuration,
inScreenMode: item.screenEntryMethod,
screenSize: item.displayAreaWidth + '*' + item.displayAreaHeight,
tcontents: [
@ -446,36 +474,13 @@ export default {
fontType: item.font,
fontColor: item.foregroundColor.toUpperCase(),
formatStyle: item.horizontalAlignment,
STAY: item.playbackDuration / 10,
content: item.textContent.replaceAll('\\,', ',').replaceAll('\\=', '=').replaceAll('\\\\n', '\n')
}
]
}
})
console.log('回读处理后的数据', this.dialogInfoList)
// for (let i = 0; i < contents.length; i++) {
// let item = contents[i]
// item.COLOR = item.foregroundColor
// item.FONT_SIZE = item.fontSize + 'px'
// item.ID = i
// item.FONT = item.font
// item.COORDINATE = this.covering(item.xCoordinate) + this.covering(item.yCoordinate)
// ;(item.screenSize = item.displayAreaWidth + '*' + item.displayAreaHeight), (item.CONTENT = item.textContent.replaceAll('\\,', ','))
// item.CONTENT = item.CONTENT.replaceAll('\\=', '=')
// item.CONTENT = item.CONTENT.replaceAll('\\\\n', '\n')
// item.formatStyle = item.verticalAlignment
// this.contentList.push(item)
// this.form.devicePixel = item.screenSize
// }
// console.log(this.contentList, 'onSubmit-----this.contentList')
// this.rowDrop();
// this.loading = false
// this.submitButton = false
})
.catch(e => {
this.$modal.msgError('回读失败,请重试')
@ -522,7 +527,7 @@ export default {
},
//
addInfo(form) {
console.log('待发新增', form)
// console.log('', form)
this.dialogInfoList.push({
id: form.id,
screenSize: form.screenSize,
@ -537,13 +542,6 @@ export default {
...this.processString(form.screenSize),
...this.processStrNum(form.COORDINATE)
})
console.log('新增模板111', this.dialogInfoList)
// this.getTemplateHeaderFn()
// console.log(this.dialogInfoList)
// form.ID = this.contentList.length
// this.contentList.push(deepClone(form))
// this.$message.success('')
// this.$forceUpdate()
},
//
addMoDataInfoFn(type, mode) {
@ -556,6 +554,7 @@ export default {
this.editType = type
console.log('修改弹窗', item)
this.boardEmitItem = {
...item,
FONT_SIZE: item.tcontents[0].fontSize + 'px',
COLOR: item.tcontents[0].fontColor,
CONTENT: item.tcontents[0].content,
@ -572,17 +571,7 @@ export default {
tcontentsId: item.tcontents[0].id
}
},
// // //
// openQbbDrawer(item, index, type) {
// this.index_ = index
// console.log(item)
// this.boardEmitItem = item
// this.boardEmitItem.screenSize = this.form.devicePixel
// this.boardEmitItem.deviceId = this.deviceId
// this.boardEmitItem.type = type
// this.showEmit = true
// },
// form
receiveForm(form) {
console.log('接收子组件form表单 修改111111111', form)
@ -598,29 +587,11 @@ export default {
// this.getTemplateHeaderFn()
this.$forceUpdate()
},
dialogClose() {
this.showEmit = false
this.arrowRightVisible = false
// setTimeout(() => {
// this.allVmsTemplate('no')
// }, 500)
},
delMoFn(item) {
console.log(item)
// deleteTemplate(item.tcontents[0].templateId)
this.removeItemById(this.dialogInfoList, item.id)
// this.$confirm('')
// .then(_ => {
// console.log(item)
// // deleteTemplate(item.tcontents[0].templateId)
// this.removeItemById(this.dialogInfoList, item.id)
// this.$message({
// message: '!',
// type: 'success'
// })
// })
// .catch(_ => {})
},
putLeftFn(item) {
console.log('点击事件', item)
@ -634,11 +605,27 @@ export default {
this.dialogInfoRight = false
},
showCeInfoFn() {
if (this.dialogInfoCamera) {
this.dialogInfoCamera = false
}
this.dialogInfoRight = !this.dialogInfoRight
},
showCameraInfoFn() {
if (this.dialogInfoRight) {
this.dialogInfoRight = false
}
this.dialogInfoCamera = !this.dialogInfoCamera
},
subjectBtnFn(item) {
this.subjectBtn = item.id
},
closeCameraBtnFn() {
this.dialogInfoCamera = false
},
dialogClose() {
this.showEmit = false
this.arrowRightVisible = false
},
removeItemById(arr, id) {
const index = arr.findIndex(item => item.id === id) //
if (index !== -1) {
@ -1091,6 +1078,7 @@ export default {
background-color: #114c66;
padding: 1vh 0.5vw;
overflow-y: scroll;
position: relative;
}
.dialog_info_left_t {
width: 100%;
@ -1283,6 +1271,78 @@ export default {
opacity: 1;
cursor: pointer;
}
.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%;
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: 0.7vh;
}
.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;
}
// background-color: #104b65;
// background-image: url('~@/assets/screen/xtb/qbbtit.png');
// background-size: 100% 100%;
@ -1344,4 +1404,15 @@ export default {
::v-deep .el-collapse-item {
margin-bottom: 1vh;
}
::v-deep .el-input--mini .el-input__icon {
line-height: 20px;
color: #fff;
}
::v-deep .el-input--mini .el-input__inner {
height: 20px;
line-height: 20px;
background-color: #086d8f;
border: none;
color: #fff;
}
</style>

192
ruoyi-ui/src/views/map/Thumbnail/data.js

@ -0,0 +1,192 @@
export const actualLocationList = [
{
code: "K54",
name: "殷家林枢纽",
intervalDistance: 0.0,
lng: 116.865231,
lat: 36.57973,
},
{
code: "K59",
name: "大学城收费站",
intervalDistance: 4.895,
lng: 116.814343,
lat: 36.581052,
},
{
code: "K72",
name: "长清收费站",
lng: 116.865231,
intervalDistance: 13.558,
lat: 36.57973,
},
{
code: "K79",
name: "长清服务区",
intervalDistance: 6.163,
lng: 116.697041,
lat: 36.428953,
},
{
code: "K83",
name: "松林枢纽",
intervalDistance: 4.875,
lng: 116.496503,
lat: 36.292459,
},
{
code: "K86",
name: "孝里收费站",
intervalDistance: 2.614,
lng: 116.638217,
lat: 36.38667,
},
{
code: "K99",
name: "*平阴北收费站",
intervalDistance: 13.251,
lng: 116.447305,
lat: 36.32884,
},
{
code: "K105",
name: "平阴收费站",
intervalDistance: 6.154,
lng: 116.482042,
lat: 36.276899,
},
{
code: "K114",
name: "平阴停车区",
intervalDistance: 8.501,
lng: 116.459654,
lat: 36.204811,
},
{
code: "K117",
name: "孔村枢纽",
intervalDistance: 3.473,
lng: 116.454379,
lat: 36.173621,
},
{
code: "K126",
name: "平阴南收费站",
intervalDistance: 8.345,
lng: 116.445836,
lat: 36.100732,
},
{
code: "K139",
name: "东平服务区",
intervalDistance: 13.594,
lng: 116.417716,
lat: 35.984511,
},
{
code: "K145",
name: "东平收费站",
intervalDistance: 6.116,
lng: 116.414862,
lat: 35.930073,
},
{
code: "K155",
name: "东平湖枢纽",
intervalDistance: 9.719,
lng: 116.381047,
lat: 35.844376,
},
{
code: "K159",
name: "沙河停车区",
lng: 116.366287,
intervalDistance: 3.504,
lat: 35.823098,
},
{
code: "K173",
name: "*梁山东收费站",
intervalDistance: 14.794,
lng: 116.222211,
lat: 35.684336,
},
{
code: "K179",
name: "梁山收费站",
intervalDistance: 5.446,
lng: 116.222163,
lat: 35.684368,
},
{
code: "K186",
name: "梁山服务区",
intervalDistance: 6.665,
lng: 116.177576,
lat: 35.638136,
},
{
code: "K190",
name: "嘉祥西收费站",
intervalDistance: 4.434,
lng: 116.142081,
lat: 35.610556,
},
{
code: "K208",
name: "王官屯枢纽",
intervalDistance: 18.484,
lng: 116.073032,
lat: 35.462815,
},
];
export const canvasList = [
{
name: "殷家林枢纽",
code: "K54+394",
line: "G3京台高速",
isFoot: true,
distance: 171,
},
{ name: "大学城收费站", code: "K59+289", distance: 50.563 },
{ name: "长清收费站", code: "K72+847", distance: 140.05 },
{ name: "长清服务区", code: "K79+010", distance: 63.66 },
{
name: "松竹枢纽",
code: "K83+885",
line: "S0101济南绕城高速二环西环段",
distance: 50.358,
},
{ name: "孝里收费站", code: "K86+499", distance: 27 },
{ name: "平阴北收费站", code: "K99+750", distance: 136.88 },
{ name: "平阴收费站", code: "K105+904", distance: 63.57 },
{ name: "平阴停车区", code: "K114+405", distance: 87.815 },
{
name: "孔村枢纽",
code: "K117+878",
line: "G22青兰高速",
distance: 35.876,
},
{ name: "平阴南收费站", code: "K126+223", distance: 86.2 },
{ name: "东平服务区", code: "K139+817", distance: 140.42 },
{ name: "东平收费站", code: "K145+933", distance: 63 },
{
name: "东平湖枢纽",
code: "K155+652",
line: "S30董梁高速",
distance: 70,
},
{ name: "沙河停车区", code: "K159+156", distance: 70 },
{ name: "梁山东收费站", code: "K173+950", distance: 70 },
{ name: "梁山收费站", code: "K179+396", distance: 70, icon: "tag4" },
{ name: "梁山服务区", code: "K186+061", distance: 70 },
{ name: "嘉祥西收费站", code: "K190+495", distance: 70 },
{
name: "王官屯枢纽",
code: "K208+979",
line: "G1511日兰高速",
distance: 120,
},
];

BIN
ruoyi-ui/src/views/map/Thumbnail/images/bg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
ruoyi-ui/src/views/map/Thumbnail/images/tag0.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
ruoyi-ui/src/views/map/Thumbnail/images/tag1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
ruoyi-ui/src/views/map/Thumbnail/images/tag2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
ruoyi-ui/src/views/map/Thumbnail/images/tag3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
ruoyi-ui/src/views/map/Thumbnail/images/tag4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

176
ruoyi-ui/src/views/map/Thumbnail/index.vue

@ -0,0 +1,176 @@
<template>
<div class="bg" id="content"></div>
</template>
<script>
import { getScaleByActualData } from './utils'
function setFont(size, bold = 'normal', family = '微软雅黑') {
return `${bold} ${size}px ${family}`
}
export default {
data() {
return {
list: getScaleByActualData()
}
},
mounted() {
this.$nextTick(() => {
this.mapInit()
})
},
methods: {
async mapInit() {
var content = document.getElementById('content')
const width = content.clientWidth
const height = content.clientHeight
const zoom = 3
const canvas = document.createElement('canvas')
canvas.style.width = width + 'px'
canvas.style.height = height + 'px'
const w = width * zoom
const h = height * zoom
canvas.width = w
canvas.height = h
content.appendChild(canvas)
const ctx = canvas.getContext('2d')
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
var imgbg = await this.loadImage(require('./images/bg.png'))
ctx.drawImage(imgbg, 0, 0, w, h)
ctx.font = setFont(12 * zoom)
ctx.fillStyle = '#ffffff'
ctx.fillText('G2001济南绕城高速', 66 * zoom, h / 2 - 21 * zoom)
ctx.fillText('G3021德上高速', w - 50 * zoom, h / 2 - 21 * zoom)
ctx.font = setFont(12 * zoom, 'italic 900', 'Arial Black')
ctx.fillStyle = '#ddc85a'
ctx.fillText('项目起点', 210 * zoom, h / 2 - 50 * zoom)
ctx.fillText('K55+378.7', 210 * zoom, h / 2 - 33 * zoom)
ctx.fillText('项目终点', w - 210 * zoom, h / 2 - 50 * zoom)
ctx.fillText('K208+153.4', w - 210 * zoom, h / 2 - 33 * zoom)
ctx.font = setFont(12 * zoom)
ctx.translate(-25 * zoom, 210 * zoom)
this.drawCongestionAreas(ctx, 1404, 80, zoom)
// this.drawCongestionAreas(ctx, 1365, 150, zoom)
for (let i of this.list) {
await this.drawTag(i, zoom, ctx)
}
},
async drayLine(zoom, text, ctx, isFoot = false) {
ctx.setLineDash([4 * zoom, 4 * zoom])
ctx.strokeStyle = '#37B5D4'
ctx.lineWidth = 6
if (isFoot) {
ctx.translate(0, 12 * zoom)
ctx.strokeRect(0, 0, 1, 161 * zoom)
ctx.translate(0, -12 * zoom)
} else {
ctx.strokeRect(0, 0, 1, 135 * zoom)
}
ctx.fillStyle = '#37B5D4'
ctx.translate(0, -16 * zoom)
if (isFoot) {
ctx.fillText(text, 0, 54)
ctx.translate(0, 226 * zoom)
ctx.fillText(text, 0, -90)
} else {
ctx.fillText(text, 0, 18)
}
},
async drawTag(info, zoom, ctx) {
let type = '3'
if (info.name.indexOf('枢纽') !== -1) {
type = '0'
} else if (info.name.indexOf('服务区') !== -1) {
type = '2'
} else if (info.name.indexOf('停车区') !== -1) {
type = '1'
}
if (type === '0') {
ctx.translate(info.distance * zoom, -188 * zoom)
ctx.font = setFont(12 * zoom, '600')
await this.drayLine(zoom, info.line, ctx, info.isFoot)
if (info.isFoot) {
ctx.translate(-10 * zoom, -180 * zoom)
} else {
ctx.translate(-10 * zoom, 35 * zoom)
}
if (info.name === '东平湖枢纽') {
const r = -110
ctx.rotate((r * Math.PI) / 180)
ctx.strokeRect(-15 * zoom, 0, 1, 90 * zoom)
ctx.rotate((r * Math.PI) / -180)
ctx.fillText('S33济徐高速', 124 * zoom, -27 * zoom)
}
} else {
ctx.translate(info.distance * zoom, -169 * zoom)
}
let y = 42 - (info.name.length - 5) * 10
ctx.fillStyle = '#ffffff'
ctx.font = setFont(12 * zoom)
var img = await this.loadImage(require(`./images/${info.icon || `tag${type}`}.png`))
ctx.drawImage(img, 0, 0, 21 * zoom, 117 * zoom)
ctx.translate(11.1 * zoom, y * zoom)
for (var i = 0; i < info.name.length; i++) {
ctx.fillText(info.name[i], 0, i * 15 * zoom)
}
ctx.translate(0, (169 - y) * zoom)
ctx.font = setFont(10.5 * zoom)
ctx.fillText(info.code, 0, -139)
},
loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image()
img.setAttribute('crossOrigin', 'anonymous')
img.src = url
img.onload = () => {
// resolve
resolve(img)
}
img.onerror = () => {
reject(new Error('图像加载失败'))
}
})
},
drawCongestionAreas(ctx, x, y, zoom) {
const { e: translateX, f: translateY } = ctx.getTransform()
x = translateX * -1 + x * zoom
y = translateY * -1 + y * zoom
const rectWidth = 180 * zoom
const rectHeight = 8 * zoom
const grad = ctx.createLinearGradient(x, 0, x + rectWidth, 0)
grad.addColorStop(0, 'rgba(217,50,8,0)')
grad.addColorStop(0.27, '#D73208')
grad.addColorStop(0.42, '#D93208')
grad.addColorStop(0.81, '#F5FF83')
grad.addColorStop(1, 'rgba(215,50,8,0)')
ctx.fillStyle = grad
ctx.fillRect(x, y, rectWidth, rectHeight)
}
}
}
</script>
<style scoped lang="scss">
.bg {
height: 100%;
width: 100%;
}
</style>

20
ruoyi-ui/src/views/map/Thumbnail/utils.js

@ -0,0 +1,20 @@
import { actualLocationList, canvasList } from "./data.js";
export function getScaleByActualData() {
const actualDis = actualLocationList.reduce(
(count, item) => count + item.intervalDistance,
0
);
const idleCanvasWidth = 1440;
const ratio = idleCanvasWidth / actualDis;
return canvasList.map((item, index) => {
if (index) {
item.distance = actualLocationList[index].intervalDistance * ratio;
}
return item;
});
}

43
ruoyi-ui/src/views/map/index.vue

@ -7,6 +7,7 @@ window._AMapSecurityConfig = {
}
import AMapLoader from '@amap/amap-jsapi-loader'
import titImgSrc from '@/assets/screen/ltit.png'
import { getEnergyBoardAPi } from '@/api/map/index.js'
export default {
name: 'mapView',
data() {
@ -14,6 +15,7 @@ export default {
map: null,
infoWindow: '',
addMarkDataList: [],
markBoardDataList: [],
markDataList: [
{
id: 2001,
@ -22,7 +24,6 @@ export default {
longitude: 116.86532,
latitude: 36.57979,
screenSize: '768*64',
imgUrl: require('@/assets/screen/xtb/fwqdot.png')
},
{
@ -46,13 +47,37 @@ export default {
]
}
},
created() {
this.getEnergyBoardFn()
},
mounted() {
this.initAMap()
},
unmounted() {
this.map?.destroy()
},
//
watch: {
markBoardDataList: {
// ,使handler
handler(newVal, oldVal) {
this.initAMap()
// console.log(newVal);
// console.log(oldVal);
},
// true(immediatefalse)
immediate: true
// true
// deep: true
}
},
methods: {
getEnergyBoardFn() {
getEnergyBoardAPi().then(res => {
console.log('地图首页情报板点位', res)
this.markBoardDataList = res
})
},
initAMap() {
AMapLoader.load({
key: '03669f433d77137fe6d048b428b00dd8', // WebKey load
@ -335,23 +360,24 @@ export default {
this.addMarkDataList = []
this.infoWindow = new window.AMap.InfoWindow({ offset: new AMap.Pixel(0, 0), anchor: 'middle-right' })
this.markDataList.forEach((item, index) => {
this.markBoardDataList.forEach((item, index) => {
// Marker
const marker = new AMap.Marker({
position: new AMap.LngLat(item.longitude, item.latitude), // [116.39, 39.9]
offset: new AMap.Pixel(0, 0),
title: item.tit,
let marker = new AMap.Marker({
position: new AMap.LngLat(...item.lnp.split(',')), // [116.39, 39.9]
offset: new AMap.Pixel(-25, -50),
title: item.deviceName,
map: this.map,
extData: item,
icon: new AMap.Icon({
size: new AMap.Size(50, 50), //
image: item.imgUrl, // Icon
// image: item.imgUrl, // Icon
image: require('@/assets/screen/xtb/fwqdot.png'), // Icon
imageOffset: new AMap.Pixel(0, 0), //
imageSize: new AMap.Size(50, 50) //
})
})
marker.setLabel({
offset: new AMap.Pixel(0, 10), //
offset: new AMap.Pixel(0, 0), //
content: '', //
// content: "<div style='padding:1vh 1vw;background-color:rgba(0,0,0,0);border:0;font-size:19px;color:rgba(188, 218, 250, 1);'>" + item.tit + '</div>', //
direction: 'top' //
@ -381,6 +407,7 @@ export default {
// })
})
})
console.log('地图动态获取后台参数', this.addMarkDataList)
//
this.map.add(this.addMarkDataList)
})

Loading…
Cancel
Save