feat: 应急救援指挥地图扎点及其他展示框绘制
parent
06f842b97f
commit
8c689b6b29
|
@ -27,7 +27,7 @@ module.exports = {
|
|||
},
|
||||
|
||||
// Various Dev Server settings
|
||||
host: 'localhost', // can be overwritten by process.env.HOST
|
||||
host: '192.168.0.37', // can be overwritten by process.env.HOST 目前设置为本地主机的IP地址,目的是为了让同网络中的其他主机可通过该IP地址访问本脚手架项目
|
||||
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||
autoOpenBrowser: false, // 是否自动开启浏览器预览能力
|
||||
errorOverlay: true,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"dependencies": {
|
||||
"@jiaminghi/data-view": "^2.10.0",
|
||||
"@riophae/vue-treeselect": "^0.4.0",
|
||||
"autofit.js": "^3.1.1",
|
||||
"axios": "^0.21.1",
|
||||
"dayjs": "^1.11.10",
|
||||
"echarts": "^5.3.1",
|
||||
|
@ -1747,6 +1748,11 @@
|
|||
"node": ">= 4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/autofit.js": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmmirror.com/autofit.js/-/autofit.js-3.1.1.tgz",
|
||||
"integrity": "sha512-ECW7wNUW1e6F+c0lRc9X+xyCrbqY3FsSnCObNDhQAo77E4/45tWx0YeLuiqA7qxrnxl2Plh3lF/pC+vzXC+8ZA=="
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "7.2.6",
|
||||
"resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-7.2.6.tgz",
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -26,6 +26,7 @@ Vue.component('Treeselect', Treeselect)
|
|||
|
||||
import Viewer from 'v-viewer'
|
||||
import 'viewerjs/dist/viewer.css'
|
||||
|
||||
Vue.use(Viewer, {
|
||||
defaultOptions: {
|
||||
zIndex: 9999// 解决图片放大的层级问题
|
||||
|
@ -119,4 +120,3 @@ new Vue({
|
|||
components: { App },
|
||||
template: '<App/>'
|
||||
})
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ service.interceptors.request.use(
|
|||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
}
|
||||
config.headers['Authorization'] = JSON.parse(sessionStorage.getItem('user')).sessionId || ''
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
import axios from 'axios'
|
||||
import { Message, MessageBox, Loading } from 'element-ui'
|
||||
|
||||
// create an axios instance
|
||||
axios.defaults.withCredentials = true
|
||||
let loadingService = null
|
||||
|
||||
const service = axios.create({
|
||||
// baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
|
||||
// eslint-disable-next-line no-undef
|
||||
baseURL: config.httpurl,
|
||||
// withCredentials: true, // send cookies when cross-domain requests
|
||||
timeout: 300000, // request timeout
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
||||
})
|
||||
|
||||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
// do something before request is sent
|
||||
if (
|
||||
(
|
||||
!config.url.includes('getLevels') &&
|
||||
!config.url.includes('hasMenu') &&
|
||||
!config.url.includes('hasButton') &&
|
||||
!config.url.includes('getInfo')
|
||||
) &&
|
||||
!loadingService
|
||||
) {
|
||||
loadingService = Loading.service({
|
||||
lock: true,
|
||||
text: '加载中......',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
}
|
||||
if (config.url === '/admin/check') {
|
||||
delete config.headers.Authorization
|
||||
}
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
// do something with request error
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// response interceptor
|
||||
service.interceptors.response.use(
|
||||
/**
|
||||
* If you want to get http information such as headers or status
|
||||
* Please return response => response
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determine the request status by custom code
|
||||
* Here is just an example
|
||||
* You can also judge the status by HTTP Status Code
|
||||
*/
|
||||
response => {
|
||||
// console.info('response:' + response)
|
||||
loadingService && loadingService.close()
|
||||
loadingService = null
|
||||
const res = response.data
|
||||
// if the custom code is not 20000, it is judged as an error.
|
||||
if (res.result !== 'success' && res.result !== 'fail') {
|
||||
if (res.response == '302') {
|
||||
MessageBox.alert('登录失效,请重新登录', {
|
||||
confirmButtonText: '确定',
|
||||
callback: action => {
|
||||
sessionStorage.clear()
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
if (res.result !== 'exception') {
|
||||
Message({
|
||||
message: res.msg || '没有此页面的访问权限,请联系管理员',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
}
|
||||
Message({
|
||||
message: res.msg || '系统开小差了,请联系管理员',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
return Promise.reject(new Error(res.message || '系统开小差了,请联系管理员'))
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
},
|
||||
error => {
|
||||
if (!error.response || error.response.status == '404' || error.response.status == '302') {
|
||||
MessageBox.alert('登录失效,请重新登录', {
|
||||
confirmButtonText: '确定',
|
||||
callback: action => {
|
||||
sessionStorage.clear()
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
MessageBox.alert('登录失效,请重新登录', {
|
||||
confirmButtonText: '确定',
|
||||
callback: action => {
|
||||
sessionStorage.clear()
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export function requestFN2(url, data) {
|
||||
// 基础请求方法
|
||||
const Qs = require('qs')
|
||||
const method = 'post'
|
||||
const obj = {
|
||||
method, // 请求的类型
|
||||
url // 请求地址
|
||||
}
|
||||
obj.data = Qs.stringify(data) // data 带参数
|
||||
// 返回axios的基础方法
|
||||
return service(obj).then(r => {
|
||||
return r // 方法请求的数据
|
||||
})
|
||||
}
|
||||
export default service
|
||||
|
|
@ -0,0 +1,286 @@
|
|||
<template>
|
||||
<div class="chat">
|
||||
<div class="chat-title">
|
||||
欢迎您,在这里可查看城市的重点隐患信息!
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="item item-right">
|
||||
<div class="bubble bubble-right">
|
||||
刚刚不在,不好意思
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<img src="https://tse1-mm.cn.bing.net/th/id/OIP-C.4XP3SrYigaDrlkbG_uFkzQAAAA?rs=1&pid=ImgDetMain">
|
||||
</div>
|
||||
</div>
|
||||
<div class="item item-left">
|
||||
<div class="avatar">
|
||||
<img src="https://tse4-mm.cn.bing.net/th/id/OIP-C.-byzt1F3AA9UcVgO_DOIwQAAAA?rs=1&pid=ImgDetMain">
|
||||
</div>
|
||||
<div class="bubble bubble-left">
|
||||
没事
|
||||
<br>
|
||||
你继续!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 服务端向客户端推送的消息队列 -->
|
||||
<div v-for="(item, index) in receiveMessageList" :key="index" :class="item.className">
|
||||
<div style="display: flex;" v-html="item.content" />
|
||||
</div>
|
||||
|
||||
<!-- 客户端向服务端主动发送的消息队列 -->
|
||||
<div v-for="(item, index) in sendMessageList" :key="index" :class="item.className">
|
||||
<div style="display: flex;" v-html="item.content" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-area">
|
||||
<textarea id="textarea" v-model="inputTextValue" class="input-text-area" name="text" />
|
||||
<div class="button-area">
|
||||
<button class="btnSend" @click="handleSendMessage"> 发送(S) </button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
let socketIOInstance
|
||||
|
||||
export default {
|
||||
name: 'Chat',
|
||||
data() {
|
||||
return {
|
||||
websocketonline: '',
|
||||
inputTextValue: '',
|
||||
/** 发送消息列表 */
|
||||
sendMessageList: [],
|
||||
/** 接收消息列表 */
|
||||
receiveMessageList: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getWebsocketController()
|
||||
},
|
||||
beforeDestroy() {
|
||||
socketIOInstance.close()
|
||||
},
|
||||
methods: {
|
||||
// 启动 websocket 连接控制器
|
||||
getWebsocketController() {
|
||||
if (window.WebSocket) {
|
||||
socketIOInstance = new WebSocket(encodeURI('ws://192.168.0.35:8089/getMapData/1'))
|
||||
socketIOInstance.onopen = () => {
|
||||
console.log('socket 连接成功!')
|
||||
}
|
||||
socketIOInstance.onerror = () => {
|
||||
console.log('socket 连接失败!')
|
||||
}
|
||||
socketIOInstance.onclose = () => {
|
||||
console.log('socket 连接断开!')
|
||||
}
|
||||
socketIOInstance.onmessage = (message) => {
|
||||
this.handleReceiveMessage(message)
|
||||
}
|
||||
}
|
||||
},
|
||||
/** 处理服务端向客户端推送的消息并展示到消息列表内 */
|
||||
handleReceiveMessage(val) {
|
||||
this.sendMessageList.push({
|
||||
className: 'item item-left',
|
||||
content: `<div class="avatar"><img src="https://tse4-mm.cn.bing.net/th/id/OIP-C.-byzt1F3AA9UcVgO_DOIwQAAAA?rs=1&pid=ImgDetMain"></div><div class="bubble bubble-left">${val.data}</div>`
|
||||
})
|
||||
},
|
||||
// 处理客户端向服务端发送消息
|
||||
handleSendMessage() {
|
||||
if (this.inputTextValue === '') {
|
||||
this.$message('消息不能为空!')
|
||||
return
|
||||
}
|
||||
socketIOInstance.send(this.inputTextValue) // 向 websocket 服务发送消息
|
||||
|
||||
this.sendMessageList.push({
|
||||
className: 'item item-right',
|
||||
content: `<div class="bubble bubble-left">${this.inputTextValue}</div><div class="avatar"><img src="https://tse1-mm.cn.bing.net/th/id/OIP-C.4XP3SrYigaDrlkbG_uFkzQAAAA?rs=1&pid=ImgDetMain" /></div>`
|
||||
})
|
||||
|
||||
this.inputTextValue = ''
|
||||
this.$nextTick(() => {
|
||||
// 滚动条置底
|
||||
const height = document.querySelector('.content').scrollHeight
|
||||
document.querySelector('.content').scrollTop = height
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
font-family: '微软雅黑', "宋体", "Arial Narrow", Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.chat {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.chat-title {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
height: 35px;
|
||||
border-bottom: 1px solid white
|
||||
}
|
||||
|
||||
.content {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
height: 648px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
}
|
||||
|
||||
// 滚动条的滚动区域(轨道)
|
||||
&::-webkit-scrollbar-track {
|
||||
width: 8px;
|
||||
border-radius: 18px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
// 滚动条的可拖拽部分(滑块)
|
||||
&::-webkit-scrollbar-thumb {
|
||||
width: 8px;
|
||||
border-radius: 18px;
|
||||
background: rgba(20, 31, 168, .8);
|
||||
}
|
||||
|
||||
.bubble {
|
||||
max-width: 300px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
color: #000;
|
||||
word-wrap: break-word;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.item-left .bubble {
|
||||
margin-left: 15px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.item-left .bubble:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10px solid transparent;
|
||||
border-top: 10px solid transparent;
|
||||
border-right: 10px solid #fff;
|
||||
border-bottom: 10px solid transparent;
|
||||
left: -20px;
|
||||
}
|
||||
|
||||
.item-right .bubble {
|
||||
margin-right: 15px;
|
||||
background-color: #9eea6a;
|
||||
}
|
||||
|
||||
.item-right .bubble:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10px solid #9eea6a;
|
||||
border-top: 10px solid transparent;
|
||||
border-right: 10px solid transparent;
|
||||
border-bottom: 10px solid transparent;
|
||||
right: -20px;
|
||||
}
|
||||
|
||||
.item {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.item.item-right {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.avatar img {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.input-area {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
|
||||
.input-text-area {
|
||||
// 去除选中后的边框
|
||||
outline: none;
|
||||
resize: none;
|
||||
background: none;
|
||||
caret-color: #fff;
|
||||
border: 1px solid #fff;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
overflow: auto;
|
||||
line-height: 20px;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
}
|
||||
|
||||
// 滚动条的滚动区域(轨道)
|
||||
&::-webkit-scrollbar-track {
|
||||
width: 8px;
|
||||
border-radius: 18px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
// 滚动条的可拖拽部分(滑块)
|
||||
&::-webkit-scrollbar-thumb {
|
||||
width: 8px;
|
||||
border-radius: 18px;
|
||||
background: rgba(20, 31, 168, .8);
|
||||
}
|
||||
}
|
||||
|
||||
.button-area {
|
||||
margin-top: 5px;
|
||||
text-align: right;
|
||||
|
||||
.btnSend {
|
||||
width: 85px;
|
||||
height: 37px;
|
||||
background: none;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-weight: 800;
|
||||
transition: transform ease-in-out .2s;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,24 +1,12 @@
|
|||
<template>
|
||||
<div class="mapAssembly-container">
|
||||
<div id="mapAssembly_container" class="mapAssembly-container">
|
||||
<!-- 地图 -->
|
||||
<div id="map" />
|
||||
<!-- 展示左侧的盒子元素 -->
|
||||
<div class="left-display-box">
|
||||
<!-- 应急机构 -->
|
||||
<div class="emergency-department">
|
||||
<el-descriptions :column="2" :colon="true" title="应急机构" class="department-list" content-style="huc">
|
||||
<template>
|
||||
<el-descriptions-item label="专家组名称">看板</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">18100000000</el-descriptions-item>
|
||||
</template>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<!-- 联系人方式 -->
|
||||
<div class="contact-information">
|
||||
联系人方式
|
||||
</div>
|
||||
</div>
|
||||
<!-- 展示中间的盒子元素 -->
|
||||
<div class="center-display-box">
|
||||
|
||||
<!-- 悬浮框主体 -->
|
||||
<div class="mainer">
|
||||
|
||||
<div v-if="currentSelectPointAccident" class="center">
|
||||
<div v-for="(item, index) in pointsList" :key="index" class="point" @click="handlePoint(item, index)">
|
||||
<div class="rescue-box">
|
||||
<img :src="item.check ? item.check_img : item.img" class="rescue-img" alt="">
|
||||
|
@ -26,39 +14,92 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 展示右侧的盒子元素 -->
|
||||
<div class="right-display-box">
|
||||
展示右侧的盒子元素
|
||||
|
||||
<div class="left">
|
||||
<!-- 应急机构 -->
|
||||
<div class="emergency-department">
|
||||
<h2 class="department-title">应急机构</h2>
|
||||
<div class="department-body">
|
||||
<ul
|
||||
v-for="(item, index) in expertGroupInfo"
|
||||
:key="index"
|
||||
class="department-ul"
|
||||
@click="expertInfoItemClick(item, index)">
|
||||
<li class="department-li">专家组名称: {{ item.EXPERT_GROUP_NAME }}</li>
|
||||
<li class="department-li">联系电话: {{ item.CONTACT_TELEPHONE }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line" />
|
||||
<!-- 联系人方式 -->
|
||||
<div class="contact-information">
|
||||
<h2 class="contact-title">联系人方式</h2>
|
||||
<div v-if="varList.length > 0">
|
||||
<ul v-for="(item, index) in varList" :key="index" class="contact-ul">
|
||||
<li class="contact-li">专家姓名: {{ item.GENDER }}</li>
|
||||
<li class="contact-li">性别: {{ item.EXPERT_NAME }}</li>
|
||||
<li class="contact-li">专家类型: {{ item.EXPERT_TYPE }}</li>
|
||||
<li class="contact-li">专家姓名: {{ item.EXPERT_NAME }}</li>
|
||||
<li class="contact-li">办公电话: {{ item.OFFICE_TELEPHONE }}</li>
|
||||
<li class="contact-li">移动电话: {{ item.MOBILE_TELEPHONE }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-else class="contact-empty">
|
||||
<span>暂无数据</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 对话框 -->
|
||||
<div class="right">
|
||||
<!-- 对话框组件渲染 -->
|
||||
<chat />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { requestFN } from '@/utils/request'
|
||||
import autofit from 'autofit.js'
|
||||
import chat from './chat.vue'
|
||||
|
||||
let mapInstance
|
||||
|
||||
export default {
|
||||
components: { chat },
|
||||
data() {
|
||||
return {
|
||||
config: config,
|
||||
pointsList: [
|
||||
{
|
||||
img: require('@/assets/map/emergency_rescue/ico1.png'),
|
||||
check_img: require('@/assets/map/emergency_rescue/ico1_on.png'),
|
||||
label: '物资',
|
||||
check: true
|
||||
label: '分类一',
|
||||
check: true,
|
||||
type: 1
|
||||
},
|
||||
{
|
||||
img: require('@/assets/map/emergency_rescue/ico2.png'),
|
||||
check_img: require('@/assets/map/emergency_rescue/ico2_on.png'),
|
||||
label: '消防',
|
||||
check: false
|
||||
label: '分类二',
|
||||
check: false,
|
||||
type: 2
|
||||
},
|
||||
{
|
||||
img: require('@/assets/map/emergency_rescue/ico3.png'),
|
||||
check_img: require('@/assets/map/emergency_rescue/ico3_on.png'),
|
||||
label: '更多',
|
||||
check: false
|
||||
check: false,
|
||||
type: 3
|
||||
},
|
||||
{
|
||||
img: require('@/assets/map/emergency_rescue/reset_point.png'),
|
||||
check_img: null,
|
||||
label: '重置',
|
||||
check: false,
|
||||
type: 4
|
||||
}
|
||||
],
|
||||
// 列表查询参数
|
||||
|
@ -66,18 +107,27 @@ export default {
|
|||
page: 1,
|
||||
limit: 10
|
||||
},
|
||||
KEYWORDS: ''
|
||||
KEYWORDS: '',
|
||||
/** 应急救援专家组状态变量 */
|
||||
expertGroupInfo: [],
|
||||
/** 存储某个专家组的所在成员 */
|
||||
varList: [],
|
||||
/** 当前选择的事故信息 */
|
||||
currentSelectPointAccident: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.mapInit() // 调用地图初始化方法
|
||||
this.initPoints() // 调用初始化点位绘制方法
|
||||
// 使用 autofit 第三方库实现PC自适应屏幕
|
||||
autofit.init({
|
||||
el: '#mapAssembly_container',
|
||||
resize: true
|
||||
})
|
||||
/** 调用地图初始化方法 */
|
||||
this.mapInit()
|
||||
/** 调用初始化点位绘制方法 */
|
||||
this.initPoints()
|
||||
this.getYjExpertGroupInfo()
|
||||
},
|
||||
// 实例销毁之前调用
|
||||
beforeDestroy() {
|
||||
mapInstance = null
|
||||
},
|
||||
methods: {
|
||||
/** 地图初始化 */
|
||||
mapInit() {
|
||||
|
@ -85,43 +135,108 @@ export default {
|
|||
mapInstance.centerAndZoom(new window.BMapGL.Point('119.645516', '39.934547'), 15) // 创建点坐标
|
||||
mapInstance.enableScrollWheelZoom(true) // 开启鼠标滚轮缩放能力
|
||||
},
|
||||
// 扎点
|
||||
// addPoint(anchor) {
|
||||
// if (!anchor.iconImg) throw new Error('请传入图标')
|
||||
/** 扎点方法 */
|
||||
addPoint(anchor) {
|
||||
if (!anchor.iconUrl) throw new Error('请传入图标')
|
||||
// if (!anchor.imageSize) throw new Error('请传入图片大小')
|
||||
// if (!anchor.lng) throw new Error('请传入经度')
|
||||
// if (!anchor.lat) throw new Error('请传入纬度')
|
||||
// const imageSize = new window.BMapGL.Size(23, 30)
|
||||
// const icon = new window.BMapGL.Icon(anchor.iconImg, imageSize, { imageSize })
|
||||
// const point = new window.BMapGL.Point(anchor.lng, anchor.lat)
|
||||
// const marker = new window.BMapGL.Marker(point, { icon }) // 创建标注
|
||||
// mapInstance.addOverlay(marker) // 将标注添加到地图中
|
||||
// },
|
||||
// 给地图扎点标记事件事故
|
||||
if (!anchor.longitude) throw new Error('请传入经度')
|
||||
if (!anchor.latitude) throw new Error('请传入纬度')
|
||||
const imageSize = new window.BMapGL.Size(23, 30)
|
||||
const icon = new window.BMapGL.Icon(config.fileUrl + anchor.iconUrl, imageSize, { imageSize })
|
||||
const point = new window.BMapGL.Point(anchor.longitude, anchor.latitude)
|
||||
const marker = new window.BMapGL.Marker(point, { icon }) // 创建标注
|
||||
const anchorOpts = {
|
||||
width: 90,
|
||||
height: 70,
|
||||
title: '资源信息'
|
||||
}
|
||||
const infoWindow = new window.BMapGL.InfoWindow(`<p">资源名称: ${anchor.name || '无'}</p>`, anchorOpts)
|
||||
marker.addEventListener('mouseover', () => {
|
||||
mapInstance.openInfoWindow(infoWindow, point)
|
||||
})
|
||||
mapInstance.addOverlay(marker) // 将标注添加到地图中
|
||||
},
|
||||
handleClickInfo() {
|
||||
console.log('你惦记了')
|
||||
},
|
||||
/** 标点的信息窗口控制器 */
|
||||
infoWindowPointerController(config) {
|
||||
const { point, marker, info } = config
|
||||
var opts = {
|
||||
width: 300,
|
||||
height: 200,
|
||||
title: '事故点位信息'
|
||||
}
|
||||
const sContent = `
|
||||
<div>
|
||||
<ul>
|
||||
<li>机主姓名: ${info.accident.OWNER_NAME || '无'}</li>
|
||||
<li>访问模式: ${info.accident.ACCESS_MODE || '无'}</li>
|
||||
<li>呼入电话: ${info.accident.INCOMING_PHONE || '无'}</li>
|
||||
<li>事件类型: ${info.accident.EVENT_TYPE || '无'}</li>
|
||||
<li>接报时间: ${info.accident.REPORT_TIME || '无'}</li>
|
||||
<li>发生时间: ${info.accident.OCCURRENCE_TIME || '无'}</li>
|
||||
<li>救援情况: ${info.accident.RESCUE_SITUATION || '无'}</li>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
const infoWindow = new window.BMapGL.InfoWindow(sContent, opts)
|
||||
marker.addEventListener('mouseover', () => {
|
||||
mapInstance.openInfoWindow(infoWindow, point)
|
||||
})
|
||||
},
|
||||
/** 给地图扎点标记事件事故 */
|
||||
addPointCallback(anchor) {
|
||||
// if (!anchor.iconImg) throw new Error('请传入图标')
|
||||
// if (!anchor.imageSize) throw new Error('请传入图片大小')
|
||||
if (!anchor.iconUrl) throw new Error('请传入图标')
|
||||
if (!anchor.LONGITUDE) throw new Error('请传入经度')
|
||||
if (!anchor.LATITUDE) throw new Error('请传入纬度')
|
||||
const { LONGITUDE, LATITUDE } = anchor
|
||||
const imageSize = new window.BMapGL.Size(33, 40)
|
||||
const icon = new window.BMapGL.Icon(config.fileUrl + anchor.iconUrl, imageSize, { imageSize }) // 创建 icon 图标
|
||||
var point = new window.BMapGL.Point(LONGITUDE, LATITUDE)
|
||||
var marker = new window.BMapGL.Marker(point) // 创建标注
|
||||
const marker = new window.BMapGL.Marker(point, { icon }) // 创建标注
|
||||
mapInstance.addOverlay(marker) // 将标注添加到地图中
|
||||
// 处理标注事件点击行为
|
||||
marker.addEventListener('click', function() {
|
||||
marker.addEventListener('click', async() => {
|
||||
let accidentParams = {}
|
||||
let nearbyResourcesList = []
|
||||
// 获取指定点位所对应的范围等详细信息
|
||||
requestFN('major/comprehensive/scope', {
|
||||
accidentId: anchor.id
|
||||
})
|
||||
.then((data) => {
|
||||
const { LONGITUDE, LATITUDE } = anchor
|
||||
var point = new window.BMapGL.Point(LONGITUDE, LATITUDE)
|
||||
var marker = new window.BMapGL.Marker(point) // 创建标注
|
||||
this.currentSelectPointAccident = anchor
|
||||
|
||||
const result = await this.getQueryScopeAsync(anchor)
|
||||
|
||||
if (result.code === 200) {
|
||||
mapInstance.clearOverlays() // 清除地图上所有覆盖物
|
||||
const { accident, nearbyResources } = result.data
|
||||
accidentParams = accident
|
||||
nearbyResourcesList = nearbyResources
|
||||
const point = new window.BMapGL.Point(accidentParams.LONGITUDE, accidentParams.LATITUDE)
|
||||
const marker = new window.BMapGL.Marker(point, { icon })
|
||||
mapInstance.addOverlay(marker)
|
||||
}).catch((e) => { })
|
||||
this.infoWindowPointerController({ point, marker, info: result.data })
|
||||
|
||||
if (nearbyResourcesList.length === 0) return
|
||||
nearbyResourcesList.forEach(item => {
|
||||
this.addPoint(item)
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 初始化定位点
|
||||
/** 获取指定点位所在周围范围等详细信息 */
|
||||
getQueryScopeAsync(enterParams) {
|
||||
return new Promise((resolve, reject) => {
|
||||
requestFN('major/comprehensive/scope', {
|
||||
accidentId: enterParams.id,
|
||||
type: enterParams.type ? enterParams.type : ''
|
||||
}).then((data) => {
|
||||
resolve(data)
|
||||
return data
|
||||
}).catch((error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
/** 初始化定位点 */
|
||||
getInfo(id) {
|
||||
requestFN('/dictionaries/listTree').then((data) => {
|
||||
this.treeData = JSON.parse(data.zTreeNodes)
|
||||
|
@ -129,6 +244,7 @@ export default {
|
|||
console.error('获取树形数据失败', e)
|
||||
})
|
||||
},
|
||||
/** 初始化点位绘制方法 */
|
||||
async initPoints() {
|
||||
const result = await this.getAccidentList()
|
||||
result.data.forEach((item) => {
|
||||
|
@ -152,17 +268,71 @@ export default {
|
|||
name: this.KEYWORDS
|
||||
}
|
||||
).then((data) => {
|
||||
console.log('data HHHHHHHh红红火火恍恍惚惚 :>> ', data)
|
||||
this.expertGroupInfo = data.varList
|
||||
})
|
||||
.catch((e) => {
|
||||
this.listISLOADing = false
|
||||
})
|
||||
},
|
||||
/** 点击某一项专家组的处理事件 */
|
||||
async expertInfoItemClick(item, index) {
|
||||
requestFN(
|
||||
'/yjExpertGroup/groupExpertlist?showCount=' + this.listQuery.limit + '¤tPage=' + this.listQuery.page,
|
||||
{
|
||||
name: null,
|
||||
id: item.EXPERT_GROUP_ID
|
||||
}
|
||||
).then((data) => {
|
||||
this.varList = data.varList
|
||||
})
|
||||
.catch((e) => { })
|
||||
},
|
||||
/** 处理分类下的扎点坐标渲染任务 */
|
||||
async baseClassifyPointer(type) {
|
||||
mapInstance.clearOverlays() // 清除地图上所有覆盖物
|
||||
let accidentParams = {}
|
||||
let nearbyResourcesList = []
|
||||
const response = await this.getQueryScopeAsync({
|
||||
id: this.currentSelectPointAccident.id,
|
||||
type
|
||||
})
|
||||
const { accident, nearbyResources } = response.data
|
||||
accidentParams = accident
|
||||
nearbyResourcesList = nearbyResources
|
||||
const imageSize = new window.BMapGL.Size(33, 40)
|
||||
const icon = new window.BMapGL.Icon(config.fileUrl + this.currentSelectPointAccident.iconUrl, imageSize, { imageSize }) // 创建 icon 图标
|
||||
const point = new window.BMapGL.Point(accidentParams.LONGITUDE, accidentParams.LATITUDE)
|
||||
const marker = new window.BMapGL.Marker(point, { icon })
|
||||
mapInstance.addOverlay(marker)
|
||||
|
||||
if (nearbyResourcesList.length === 0) return
|
||||
nearbyResourcesList.forEach(item => {
|
||||
this.addPoint(item)
|
||||
})
|
||||
},
|
||||
/** 处理点坐标 */
|
||||
handlePoint(item, index) {
|
||||
console.log('当前点击的点坐标信息 :>> ', item)
|
||||
console.log('当前点击的点坐标索引值 :>>', index)
|
||||
async handlePoint(item, index) {
|
||||
switch (index) {
|
||||
case 0: {
|
||||
this.pointsList[index].check = !this.pointsList[index].check
|
||||
this.baseClassifyPointer(item.type)
|
||||
break
|
||||
}
|
||||
case 1: {
|
||||
this.pointsList[index].check = !this.pointsList[index].check
|
||||
this.baseClassifyPointer(item.type)
|
||||
break
|
||||
}
|
||||
case 2: {
|
||||
this.pointsList[index].check = !this.pointsList[index].check
|
||||
this.baseClassifyPointer(item.type)
|
||||
break
|
||||
}
|
||||
case 3: {
|
||||
mapInstance.clearOverlays()
|
||||
this.initPoints()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,108 +340,188 @@ export default {
|
|||
|
||||
<style scoped lang="scss">
|
||||
.mapAssembly-container {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
font-family: '微软雅黑', "宋体", "Arial Narrow", Helvetica, sans-serif;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
|
||||
// 地图的宽高样式限制
|
||||
#map {
|
||||
width: calc(100vw - 44px);
|
||||
height: calc(100vh - 84px);
|
||||
width: 100%;
|
||||
height: 91%;
|
||||
}
|
||||
|
||||
.el-descriptions {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.el-descriptions__body {
|
||||
background-color: red !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.left-display-box {
|
||||
z-index: 99;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
width: 26vw;
|
||||
height: 83vh;
|
||||
background: rgba(20, 31, 168, .7);
|
||||
border: 1px solid #0060d7;
|
||||
border-top: none;
|
||||
padding: 8px;
|
||||
color: #fff;
|
||||
border-radius: 8px;
|
||||
.mainer {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
// 应急部门样式
|
||||
.emergency-department {
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
height: 100%;
|
||||
|
||||
.department-list {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
// 联系人方式样式
|
||||
.contact-information {
|
||||
border-radius: 8px;
|
||||
border: 1px solid greenyellow;
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// 展示中间的盒子元素
|
||||
.center-display-box {
|
||||
z-index: 99;
|
||||
color: #fff;
|
||||
.center {
|
||||
width: 340px;
|
||||
position: absolute;
|
||||
top: 72vh;
|
||||
left: 50%;
|
||||
transform: translateX(-20vw);
|
||||
width: 40vw;
|
||||
height: 13vh;
|
||||
border-radius: 8px;
|
||||
top: 765px;
|
||||
transform: translateX(-170px);
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.point {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
width: 50px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.rescue-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
width: 4vw;
|
||||
height: 4vw;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
|
||||
.rescue-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rescue-text {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: rgb(255, 255, 255);
|
||||
color: rgb(0, 52, 221);
|
||||
font-weight: 800;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 展示右侧的盒子元素
|
||||
.right-display-box {
|
||||
z-index: 99;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
width: 25vw;
|
||||
height: 83vh;
|
||||
.left {
|
||||
width: 477px;
|
||||
height: 850px;
|
||||
max-height: 850px;
|
||||
background: rgba(20, 31, 168, .7);
|
||||
border: 1px solid #0060d7;
|
||||
z-index: 99;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 18px;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
padding: 12px;
|
||||
|
||||
// 应急机构样式
|
||||
.emergency-department {
|
||||
max-height: 420px;
|
||||
overflow: auto;
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
|
||||
.department-title {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
padding: 5px 0 5px 6px;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.department-body {
|
||||
height: 85%;
|
||||
overflow: auto;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.department-ul {
|
||||
width: 100%;
|
||||
margin-bottom: 9px;
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
box-shadow:
|
||||
inset -1px -3px 4px rgba(255, 255, 255, .9), inset 8px 6px 12px rgba(0, 0, 0, .4);
|
||||
}
|
||||
|
||||
.department-li {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分割线条
|
||||
.line {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
border-bottom: 1px solid #fff;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
// 联系人方式样式
|
||||
.contact-information {
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
|
||||
.contact-title {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
padding: 5px 0 5px 6px;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
.contact-ul {
|
||||
max-height: 420px;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
margin-bottom: 9px;
|
||||
border-radius: 8px;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
|
||||
.contact-li {
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
}
|
||||
|
||||
.contact-empty {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
box-sizing: border-box;
|
||||
z-index: 99;
|
||||
background: rgba(20, 31, 168, .7);
|
||||
border: 1px solid #0060d7;
|
||||
width: 477px;
|
||||
height: 850px;
|
||||
max-height: 850px;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 265px;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -100,7 +100,6 @@
|
|||
|
||||
<script>
|
||||
import { requestFN } from '@/utils/request'
|
||||
import { requestFN2 } from '@/utils/request2'
|
||||
import SIdentify from './components/sidentify'
|
||||
import JSEncrypt from '../../../static/js/jsencrypt.min.js'
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
@ -270,7 +269,7 @@ export default {
|
|||
jsencrypt.setPublicKey(config.publicKey)
|
||||
const loginData = jsencrypt.encrypt('qdkjchina' + this.loginForm.username + ',qd,' + this.loginForm.password)
|
||||
this.loading = true
|
||||
requestFN2(
|
||||
requestFN(
|
||||
'/admin/check',
|
||||
{
|
||||
KEYDATA: loginData
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
const config = {
|
||||
weburl: 'http://192.168.0.37:8080/', // 前台地址
|
||||
// httpurl: 'http://192.168.0.29:8091/', // 后台地址
|
||||
httpurl: 'http://192.168.0.35:8089/', // 后台地址
|
||||
httpurl: '/api', // 后台地址
|
||||
qyurl: 'https://qgqy.qhdsafety.com/', // 企业前台
|
||||
adminurl: 'https://www.qdkjchina.com/qa-prevention-admin/',
|
||||
// 正式
|
||||
|
|
Loading…
Reference in New Issue