支持通用通道云台控制,支持地图位置编辑
This commit is contained in:
@@ -19,7 +19,9 @@
|
||||
ref="regionTree"
|
||||
:edit="false"
|
||||
:show-header="false"
|
||||
:show-position="showPosition"
|
||||
:has-channel="true"
|
||||
:contextmenu="contextmenu"
|
||||
@clickEvent="treeNodeClickEvent"
|
||||
:default-expanded-keys="[]"
|
||||
/>
|
||||
@@ -28,7 +30,9 @@
|
||||
ref="groupTree"
|
||||
:edit="false"
|
||||
:show-header="false"
|
||||
:show-position="showPosition"
|
||||
:has-channel="true"
|
||||
:contextmenu="contextmenu"
|
||||
@clickEvent="treeNodeClickEvent"
|
||||
:default-expanded-keys="[]"
|
||||
/>
|
||||
@@ -56,6 +60,14 @@ export default {
|
||||
contextMenuEvent: {
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
showPosition: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
contextmenu: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -135,6 +147,14 @@ export default {
|
||||
if (data.leaf) {
|
||||
this.$emit('clickEvent', data.id)
|
||||
}
|
||||
},
|
||||
refresh: function(id) {
|
||||
console.log(id)
|
||||
if (this.showRegion) {
|
||||
this.$refs.regionTree.refresh(id)
|
||||
}else {
|
||||
this.$refs.groupTree.refresh(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
style=" padding-left: 1px"
|
||||
:title="node.data.deviceId"
|
||||
>{{ node.label }}</span>
|
||||
<span v-if="node.data.longitude && showPosition" class="iconfont icon-gps"></span>
|
||||
</span>
|
||||
</template>
|
||||
</vue-easy-tree>
|
||||
@@ -130,7 +131,7 @@ export default {
|
||||
GbChannelSelect,
|
||||
VueEasyTree, groupEdit, gbDeviceSelect
|
||||
},
|
||||
props: ['edit', 'enableAddChannel', 'showHeader', 'hasChannel', 'addChannelToGroup', 'treeHeight'],
|
||||
props: ['edit', 'enableAddChannel', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToGroup', 'treeHeight', 'showPosition', 'contextmenu'],
|
||||
data() {
|
||||
return {
|
||||
props: {
|
||||
@@ -231,90 +232,111 @@ export default {
|
||||
this.$forceUpdate()
|
||||
},
|
||||
contextmenuEventHandler: function(event, data, node, element) {
|
||||
if (!this.edit) {
|
||||
if (!this.edit && !this.contextmenu) {
|
||||
return
|
||||
}
|
||||
const allMenuItem = []
|
||||
if (node.data.type === 0) {
|
||||
const menuItem = [
|
||||
{
|
||||
label: '刷新节点',
|
||||
icon: 'el-icon-refresh',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '新建节点',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addGroup(data.id, node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '编辑节点',
|
||||
icon: 'el-icon-edit',
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.editGroup(data, node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '删除节点',
|
||||
icon: 'el-icon-delete',
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeGroup(data.id, node)
|
||||
}).catch(() => {
|
||||
if (this.edit) {
|
||||
const menuItem = [
|
||||
{
|
||||
label: '刷新节点',
|
||||
icon: 'el-icon-refresh',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '新建节点',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addGroup(data.id, node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '编辑节点',
|
||||
icon: 'el-icon-edit',
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.editGroup(data, node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '删除节点',
|
||||
icon: 'el-icon-delete',
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeGroup(data.id, node)
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
if (this.enableAddChannel) {
|
||||
menuItem.push(
|
||||
{
|
||||
label: '添加设备',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: node.level <= 2,
|
||||
onClick: () => {
|
||||
this.addChannelFormDevice(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: '移除设备',
|
||||
icon: 'el-icon-delete',
|
||||
disabled: node.level <= 2,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.removeChannelFormDevice(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: '添加通道',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: node.level <= 2,
|
||||
onClick: () => {
|
||||
this.addChannel(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
allMenuItem.push(...menuItem)
|
||||
}
|
||||
if (this.contextmenu) {
|
||||
for (let i = 0; i < this.contextmenu.length; i++) {
|
||||
let item = this.contextmenu[i]
|
||||
if (item.type === node.data.type) {
|
||||
allMenuItem.push({
|
||||
label: item.label,
|
||||
icon: item.icon,
|
||||
onClick: () => {
|
||||
item.onClick(event, data, node)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
if (this.enableAddChannel) {
|
||||
menuItem.push(
|
||||
{
|
||||
label: '添加设备',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: node.level <= 2,
|
||||
onClick: () => {
|
||||
this.addChannelFormDevice(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: '移除设备',
|
||||
icon: 'el-icon-delete',
|
||||
disabled: node.level <= 2,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.removeChannelFormDevice(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: '添加通道',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: node.level <= 2,
|
||||
onClick: () => {
|
||||
this.addChannel(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
if (allMenuItem.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
this.$contextmenu({
|
||||
items: menuItem,
|
||||
items: allMenuItem,
|
||||
event, // 鼠标事件信息
|
||||
customClass: 'custom-class', // 自定义菜单 class
|
||||
zIndex: 3000 // 菜单样式 z-index
|
||||
|
||||
@@ -17,11 +17,16 @@ import View from 'ol/View'
|
||||
import Feature from 'ol/Feature'
|
||||
import Overlay from 'ol/Overlay'
|
||||
import { Point, LineString } from 'ol/geom'
|
||||
import { get as getProj, fromLonLat } from 'ol/proj'
|
||||
import { ZoomSlider, Zoom } from 'ol/control'
|
||||
import { get as getProj } from 'ol/proj'
|
||||
import { containsCoordinate } from 'ol/extent'
|
||||
import {
|
||||
defaults as defaultInteractions
|
||||
} from 'ol/interaction'
|
||||
import DragInteraction from './map/DragInteraction'
|
||||
import { fromLonLat, toLonLat } from './map/TransformLonLat'
|
||||
|
||||
import { v4 } from 'uuid'
|
||||
import { getUid } from 'ol'
|
||||
|
||||
let olMap = null
|
||||
|
||||
@@ -30,7 +35,8 @@ export default {
|
||||
props: [],
|
||||
data() {
|
||||
return {
|
||||
|
||||
overlayId: null,
|
||||
dragInteraction: new DragInteraction()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -44,34 +50,28 @@ export default {
|
||||
|
||||
},
|
||||
destroyed() {
|
||||
// if (this.jessibuca) {
|
||||
// this.jessibuca.destroy();
|
||||
// }
|
||||
// this.playing = false;
|
||||
// this.loaded = false;
|
||||
// this.performance = "";
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
let center = fromLonLat([116.41020, 39.915119])
|
||||
if (mapParam.center) {
|
||||
center = fromLonLat(mapParam.center)
|
||||
if (window.mapParam.center) {
|
||||
center = fromLonLat(window.mapParam.center)
|
||||
}
|
||||
const view = new View({
|
||||
center: center,
|
||||
zoom: mapParam.zoom || 10,
|
||||
zoom: window.mapParam.zoom || 10,
|
||||
projection: this.projection,
|
||||
maxZoom: mapParam.maxZoom || 19,
|
||||
minZoom: mapParam.minZoom || 1
|
||||
maxZoom: window.mapParam.maxZoom || 19,
|
||||
minZoom: window.mapParam.minZoom || 1
|
||||
})
|
||||
let tileLayer = null
|
||||
if (mapParam.tilesUrl) {
|
||||
if (window.mapParam.tilesUrl) {
|
||||
tileLayer = new Tile({
|
||||
source: new XYZ({
|
||||
projection: getProj('EPSG:3857'),
|
||||
wrapX: false,
|
||||
tileSize: 256 || mapParam.tileSize,
|
||||
url: mapParam.tilesUrl
|
||||
tileSize: 256 || window.mapParam.tileSize,
|
||||
url: window.mapParam.tilesUrl
|
||||
})
|
||||
})
|
||||
} else {
|
||||
@@ -81,18 +81,48 @@ export default {
|
||||
})
|
||||
}
|
||||
olMap = new Map({
|
||||
interactions: defaultInteractions().extend([this.dragInteraction]),
|
||||
target: this.$refs.mapContainer, // 容器ID
|
||||
layers: [tileLayer], // 默认图层
|
||||
view: view, // 视图
|
||||
controls: [ // 控件
|
||||
// new ZoomSlider(),
|
||||
new Zoom()
|
||||
]
|
||||
})
|
||||
console.log(3222)
|
||||
olMap.once('loadend', event => {
|
||||
this.$emit('loaded')
|
||||
})
|
||||
olMap.on('click', event => {
|
||||
let features = {}
|
||||
let layers = {}
|
||||
// 单个元素事件传递
|
||||
olMap.forEachFeatureAtPixel(event.pixel, (featureAtPixel, layerAtPixel) => {
|
||||
|
||||
if (layerAtPixel) {
|
||||
let ol_uid = 'key' + getUid(layerAtPixel)
|
||||
layers[ol_uid] = layerAtPixel
|
||||
if (Object.hasOwn(features, ol_uid)) {
|
||||
features[ol_uid].push(featureAtPixel)
|
||||
} else {
|
||||
features[ol_uid] = new Array(featureAtPixel)
|
||||
}
|
||||
}
|
||||
})
|
||||
// 遍历图层,传递事件
|
||||
for (const key in layers) {
|
||||
if (Object.hasOwn(layers, key)) {
|
||||
var layer = layers[key]
|
||||
layer.dispatchEvent({ type: 'click', event: event, features: features[key], outParam: { layersCount: Object.keys(layers).length } });
|
||||
}
|
||||
}
|
||||
features = {}
|
||||
layer = {}
|
||||
})
|
||||
},
|
||||
setCenter(point) {
|
||||
|
||||
},
|
||||
getCenter() {
|
||||
return toLonLat(olMap.getView().getCenter())
|
||||
},
|
||||
zoomIn(zoom) {
|
||||
|
||||
@@ -110,23 +140,33 @@ export default {
|
||||
duration: duration
|
||||
})
|
||||
},
|
||||
panTo(point, zoom) {
|
||||
const duration = 800
|
||||
coordinateInView: function(point) {
|
||||
return containsCoordinate(olMap.getView().calculateExtent(), fromLonLat(point))
|
||||
},
|
||||
panTo(point, zoom, endCallback) {
|
||||
const duration = 1500
|
||||
var coordinate = fromLonLat(point)
|
||||
if (containsCoordinate(olMap.getView().calculateExtent(), coordinate)) {
|
||||
olMap.getView().setCenter(coordinate)
|
||||
if (endCallback) {
|
||||
endCallback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
olMap.getView().cancelAnimations()
|
||||
olMap.getView().animate({
|
||||
center: fromLonLat(point),
|
||||
center: coordinate,
|
||||
duration: duration
|
||||
})
|
||||
if (!containsCoordinate(olMap.getView().calculateExtent(), fromLonLat(point))) {
|
||||
olMap.getView().animate({
|
||||
zoom: olMap.getView().getZoom() - 1,
|
||||
duration: duration / 2
|
||||
}, {
|
||||
zoom: zoom || olMap.getView().getZoom(),
|
||||
duration: duration / 2
|
||||
})
|
||||
}
|
||||
olMap.getView().animate({
|
||||
zoom: 12,
|
||||
duration: duration / 2
|
||||
}, {
|
||||
zoom: zoom || olMap.getView().getZoom(),
|
||||
duration: duration / 2
|
||||
})
|
||||
setTimeout(endCallback, duration + 100)
|
||||
},
|
||||
fit(layer) {
|
||||
const extent = layer.getSource().getExtent()
|
||||
@@ -138,10 +178,15 @@ export default {
|
||||
}
|
||||
},
|
||||
openInfoBox(position, content, offset) {
|
||||
if (this.overlayId !== null) {
|
||||
console.log(this.overlayId)
|
||||
this.closeInfoBox(this.overlayId)
|
||||
this.overlayId = null
|
||||
}
|
||||
const id = v4()
|
||||
// let infoBox = document.createElement("div");
|
||||
// infoBox.innerHTML = content ;
|
||||
// infoBox.setAttribute("infoBoxId", id)
|
||||
// let infoBox = document.createElement('div')
|
||||
// infoBox.setAttribute('id', id)
|
||||
// infoBox.innerHTML = content
|
||||
const overlay = new Overlay({
|
||||
id: id,
|
||||
autoPan: true,
|
||||
@@ -150,16 +195,23 @@ export default {
|
||||
},
|
||||
element: content,
|
||||
positioning: 'bottom-center',
|
||||
offset: offset
|
||||
offset: offset,
|
||||
position: fromLonLat(position)
|
||||
// className:overlayStyle.className
|
||||
})
|
||||
olMap.addOverlay(overlay)
|
||||
overlay.setPosition(fromLonLat(position))
|
||||
this.overlayId = id
|
||||
return id
|
||||
},
|
||||
closeInfoBox(id) {
|
||||
olMap.getOverlayById(id).setPosition(undefined)
|
||||
// olMap.removeOverlay(olMap.getOverlayById(id))
|
||||
let overlay = olMap.getOverlayById(id)
|
||||
if (overlay) {
|
||||
olMap.removeOverlay(overlay)
|
||||
}
|
||||
var element = document.getElementById(id)
|
||||
if (element) {
|
||||
element.remove()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 添加图层
|
||||
@@ -178,13 +230,13 @@ export default {
|
||||
* ]
|
||||
*/
|
||||
addLayer(data, clickEvent) {
|
||||
const style = new Style()
|
||||
if (data.length > 0) {
|
||||
const features = []
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const feature = new Feature(new Point(fromLonLat(data[i].position)))
|
||||
feature.setId(data[i].id)
|
||||
feature.customData = data[i].data
|
||||
const cloneStyle = style.clone()
|
||||
const cloneStyle = new Style()
|
||||
cloneStyle.setImage(new Icon({
|
||||
anchor: data[i].image.anchor,
|
||||
crossOrigin: 'Anonymous',
|
||||
@@ -197,31 +249,88 @@ export default {
|
||||
source.addFeatures(features)
|
||||
const vectorLayer = new VectorLayer({
|
||||
source: source,
|
||||
style: style,
|
||||
renderMode: 'image',
|
||||
declutter: false
|
||||
})
|
||||
olMap.addLayer(vectorLayer)
|
||||
if (typeof clickEvent === 'function') {
|
||||
olMap.on('click', (event) => {
|
||||
vectorLayer.getFeatures(event.pixel).then((features) => {
|
||||
if (features.length > 0) {
|
||||
const items = []
|
||||
for (let i = 0; i < features.length; i++) {
|
||||
items.push(features[i].customData)
|
||||
}
|
||||
clickEvent(items)
|
||||
vectorLayer.on('click', (event) => {
|
||||
|
||||
if (event.features.length > 0) {
|
||||
const items = []
|
||||
for (let i = 0; i < event.features.length; i++) {
|
||||
items.push(event.features[i].customData)
|
||||
}
|
||||
})
|
||||
clickEvent(items)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return vectorLayer
|
||||
}
|
||||
},
|
||||
updateLayer(layer, data, postponement) {
|
||||
console.log(layer)
|
||||
layer.getSource().clear(true)
|
||||
const features = []
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const feature = new Feature(new Point(fromLonLat(data[i].position)))
|
||||
feature.setId(data[i].id)
|
||||
feature.customData = data[i].data
|
||||
const cloneStyle = new Style()
|
||||
cloneStyle.setImage(new Icon({
|
||||
anchor: data[i].image.anchor,
|
||||
crossOrigin: 'Anonymous',
|
||||
src: data[i].image.src
|
||||
}))
|
||||
feature.setStyle(cloneStyle)
|
||||
features.push(feature)
|
||||
}
|
||||
layer.getSource().addFeatures(features)
|
||||
if (postponement) {
|
||||
olMap.removeLayer(layer)
|
||||
setTimeout(() => {
|
||||
olMap.addLayer(layer)
|
||||
}, 100)
|
||||
}
|
||||
return layer
|
||||
},
|
||||
removeLayer(layer) {
|
||||
olMap.removeLayer(layer)
|
||||
},
|
||||
setFeatureImageById(layer, featureId, image) {
|
||||
let feature = layer.getSource().getFeatureById(featureId)
|
||||
if (!feature) {
|
||||
console.error('更改feature的图标时未找到图标')
|
||||
return
|
||||
}
|
||||
let style = feature.getStyle()
|
||||
style.setImage(new Icon({
|
||||
anchor: image.anchor,
|
||||
crossOrigin: 'Anonymous',
|
||||
src: image.src
|
||||
}))
|
||||
feature.setStyle(style)
|
||||
olMap.render()
|
||||
},
|
||||
setFeaturePositionById(layer, featureId, data) {
|
||||
let featureOld = layer.getSource().getFeatureById(featureId)
|
||||
if (featureOld) {
|
||||
layer.getSource().removeFeature(featureOld)
|
||||
}
|
||||
|
||||
const feature = new Feature(new Point(fromLonLat(data.position)))
|
||||
feature.setId(data.id)
|
||||
feature.customData = data.data
|
||||
const style = new Style()
|
||||
style.setImage(new Icon({
|
||||
anchor: data.image.anchor,
|
||||
crossOrigin: 'Anonymous',
|
||||
src: data.image.src
|
||||
}))
|
||||
feature.setStyle(style)
|
||||
layer.getSource().addFeature(feature)
|
||||
},
|
||||
|
||||
addLineLayer(positions) {
|
||||
if (positions.length > 0) {
|
||||
|
||||
@@ -56,15 +56,11 @@
|
||||
class="iconfont icon-shexiangtou2"
|
||||
/>
|
||||
<span
|
||||
v-if="node.data.deviceId !=='' && showCode"
|
||||
style=" padding-left: 1px"
|
||||
:title="node.data.deviceId"
|
||||
>{{ node.label }}(编号:{{ node.data.deviceId }})</span>
|
||||
<span
|
||||
v-if="node.data.deviceId ==='' || !showCode"
|
||||
style=" padding-left: 1px"
|
||||
:title="node.data.deviceId"
|
||||
>{{ node.label }}</span>
|
||||
<span v-if="node.data.deviceId !=='' && showCode">(编号:{{ node.data.deviceId }})</span>
|
||||
<span v-if="node.data.longitude && showPosition" class="iconfont icon-gps"></span>
|
||||
</span>
|
||||
</template>
|
||||
</vue-easy-tree>
|
||||
@@ -131,7 +127,7 @@ export default {
|
||||
GbChannelSelect,
|
||||
VueEasyTree, regionEdit, gbDeviceSelect
|
||||
},
|
||||
props: ['edit', 'enableAddChannel', 'showHeader', 'hasChannel', 'addChannelToCivilCode', 'treeHeight'],
|
||||
props: ['edit', 'enableAddChannel', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToCivilCode', 'treeHeight', 'showPosition', 'contextmenu'],
|
||||
data() {
|
||||
return {
|
||||
props: {
|
||||
@@ -236,95 +232,115 @@ export default {
|
||||
this.$forceUpdate()
|
||||
},
|
||||
contextmenuEventHandler: function(event, data, node, element) {
|
||||
if (!this.edit) {
|
||||
if (!this.edit && !this.contextmenu) {
|
||||
return
|
||||
}
|
||||
const allMenuItem = []
|
||||
if (node.data.type === 0) {
|
||||
const menuItem = [
|
||||
{
|
||||
label: '刷新节点',
|
||||
icon: 'el-icon-refresh',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '新建节点',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addRegion(data.id, node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '编辑节点',
|
||||
icon: 'el-icon-edit',
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.editCatalog(data, node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '删除节点',
|
||||
icon: 'el-icon-delete',
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeRegion(data.id, node)
|
||||
}).catch(() => {
|
||||
if (this.edit) {
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
if (this.enableAddChannel) {
|
||||
menuItem.push(
|
||||
const menuItem = [
|
||||
{
|
||||
label: '添加设备',
|
||||
label: '刷新节点',
|
||||
icon: 'el-icon-refresh',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '新建节点',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addRegion(data.id, node)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '编辑节点',
|
||||
icon: 'el-icon-edit',
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.addChannelFormDevice(data.id, node)
|
||||
this.editCatalog(data, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
},
|
||||
{
|
||||
label: '移除设备',
|
||||
label: '删除节点',
|
||||
icon: 'el-icon-delete',
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.removeChannelFormDevice(data.id, node)
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeRegion(data.id, node)
|
||||
}).catch(() => {
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: '添加通道',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.addChannel(data.id, node)
|
||||
]
|
||||
if (this.enableAddChannel) {
|
||||
menuItem.push(
|
||||
{
|
||||
label: '添加设备',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.addChannelFormDevice(data.id, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: '移除设备',
|
||||
icon: 'el-icon-delete',
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.removeChannelFormDevice(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: '添加通道',
|
||||
icon: 'el-icon-plus',
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.addChannel(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
allMenuItem.push(...menuItem)
|
||||
}
|
||||
|
||||
this.$contextmenu({
|
||||
items: menuItem,
|
||||
event, // 鼠标事件信息
|
||||
customClass: 'custom-class', // 自定义菜单 class
|
||||
zIndex: 3000 // 菜单样式 z-index
|
||||
})
|
||||
}
|
||||
|
||||
if (this.contextmenu) {
|
||||
for (let i = 0; i < this.contextmenu.length; i++) {
|
||||
let item = this.contextmenu[i]
|
||||
if (item.type === node.data.type) {
|
||||
allMenuItem.push({
|
||||
label: item.label,
|
||||
icon: item.icon,
|
||||
onClick: () => {
|
||||
item.onClick(event, data, node)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allMenuItem.length === 0) {
|
||||
return
|
||||
}
|
||||
this.$contextmenu({
|
||||
items: allMenuItem,
|
||||
event, // 鼠标事件信息
|
||||
customClass: 'custom-class', // 自定义菜单 class
|
||||
zIndex: 3000 // 菜单样式 z-index
|
||||
})
|
||||
return false
|
||||
},
|
||||
removeRegion: function(id, node) {
|
||||
@@ -396,12 +412,16 @@ export default {
|
||||
node.expand()
|
||||
},
|
||||
refresh: function(id) {
|
||||
console.log(id)
|
||||
// 查询node
|
||||
const node = this.$refs.veTree.getNode(id)
|
||||
if (node) {
|
||||
node.loaded = false
|
||||
node.expand()
|
||||
if (id.includes('channel') >= 0) {
|
||||
node.parent.loaded = false
|
||||
node.parent.expand()
|
||||
}else {
|
||||
node.loaded = false
|
||||
node.expand()
|
||||
}
|
||||
}
|
||||
},
|
||||
addRegion: function(id, node) {
|
||||
|
||||
116
web/src/views/common/map/DragInteraction.js
Normal file
116
web/src/views/common/map/DragInteraction.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import PointerInteraction from 'ol/interaction/Pointer'
|
||||
import { toLonLat } from './TransformLonLat'
|
||||
|
||||
class DragInteraction extends PointerInteraction {
|
||||
constructor() {
|
||||
super({
|
||||
handleDownEvent: (evt) => {
|
||||
const map = evt.map
|
||||
|
||||
const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => {
|
||||
if (this.featureIdMap_.has(feature.getId())) {
|
||||
return feature
|
||||
}else {
|
||||
return null
|
||||
}
|
||||
})
|
||||
if (feature) {
|
||||
this.coordinate_ = evt.coordinate
|
||||
this.feature_ = feature
|
||||
let eventCallback = this.featureIdMap_.get(this.feature_.getId())
|
||||
if (eventCallback && eventCallback.startEvent) {
|
||||
eventCallback.startEvent(evt)
|
||||
}
|
||||
return !!feature
|
||||
}
|
||||
},
|
||||
handleDragEvent: (evt) => {
|
||||
const deltaX = evt.coordinate[0] - this.coordinate_[0]
|
||||
const deltaY = evt.coordinate[1] - this.coordinate_[1]
|
||||
|
||||
const geometry = this.feature_.getGeometry()
|
||||
geometry.translate(deltaX, deltaY)
|
||||
|
||||
this.coordinate_[0] = evt.coordinate[0]
|
||||
this.coordinate_[1] = evt.coordinate[1]
|
||||
|
||||
let eventCallback = this.featureIdMap_.get(this.feature_.getId())
|
||||
if (eventCallback && eventCallback.moveEvent) {
|
||||
eventCallback.moveEvent(evt)
|
||||
}
|
||||
|
||||
},
|
||||
handleMoveEvent: (evt) => {
|
||||
if (this.cursor_) {
|
||||
const map = evt.map
|
||||
const feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) {
|
||||
return feature
|
||||
})
|
||||
const element = evt.map.getTargetElement()
|
||||
if (feature) {
|
||||
if (element.style.cursor != this.cursor_) {
|
||||
this.previousCursor_ = element.style.cursor
|
||||
element.style.cursor = this.cursor_
|
||||
}
|
||||
} else if (this.previousCursor_ !== undefined) {
|
||||
element.style.cursor = this.previousCursor_
|
||||
this.previousCursor_ = undefined
|
||||
}
|
||||
}
|
||||
},
|
||||
handleUpEvent: (evt) => {
|
||||
let eventCallback = this.featureIdMap_.get(this.feature_.getId())
|
||||
if (eventCallback && eventCallback.endEvent) {
|
||||
evt.lonLat = toLonLat(this.feature_.getGeometry().getCoordinates())
|
||||
eventCallback.endEvent(evt)
|
||||
}
|
||||
this.coordinate_ = null
|
||||
this.feature_ = null
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* @type {import('../src/ol/coordinate.js').Coordinate}
|
||||
* @private
|
||||
*/
|
||||
this.coordinate_ = null
|
||||
|
||||
/**
|
||||
* @type {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.cursor_ = 'pointer'
|
||||
|
||||
/**
|
||||
* @type {Feature}
|
||||
* @private
|
||||
*/
|
||||
this.feature_ = null
|
||||
|
||||
/**
|
||||
* @type {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
this.previousCursor_ = undefined
|
||||
|
||||
this.featureIdMap_ = new Map()
|
||||
|
||||
this.addFeatureId = (id, moveEndEvent) => {
|
||||
if (this.featureIdMap_.has(id)) {
|
||||
return
|
||||
}
|
||||
this.featureIdMap_.set(id, moveEndEvent)
|
||||
}
|
||||
|
||||
this.removeFeatureId= (id) => {
|
||||
this.featureIdMap_.delete(id)
|
||||
}
|
||||
|
||||
this.hasFeatureId= (id) => {
|
||||
this.featureIdMap_.has(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default DragInteraction
|
||||
9
web/src/views/common/map/TransformLonLat.js
Normal file
9
web/src/views/common/map/TransformLonLat.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { fromLonLat as projFromLonLat, toLonLat as projToLonLat } from 'ol/proj'
|
||||
import gcoord from 'gcoord'
|
||||
|
||||
export function fromLonLat(coordinate) {
|
||||
return projFromLonLat(gcoord.transform(coordinate, gcoord.WGS84, gcoord.GCJ02))
|
||||
}
|
||||
export function toLonLat(coordinate) {
|
||||
return gcoord.transform(projToLonLat(coordinate), gcoord.GCJ02, gcoord.WGS84)
|
||||
}
|
||||
Reference in New Issue
Block a user