添加定位与展示功能
This commit is contained in:
parent
8d0babadd9
commit
cee790c4fc
BIN
src/assets/poi.png
Normal file
BIN
src/assets/poi.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
src/assets/water.png
Normal file
BIN
src/assets/water.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
@ -78,7 +78,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
import { login, logout } from "@/utils/http";
|
||||
import { getData, login, logout, URL_MAP } from "@/utils/http";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -121,6 +121,17 @@ export default {
|
||||
// }
|
||||
let data = await login(this.form.utel, this.form.upass, 'tt', 'tt');
|
||||
this.$store.commit("login", data);
|
||||
/**
|
||||
* 初始化设备数据、传感器数据
|
||||
*/
|
||||
let results = [
|
||||
getData(URL_MAP.DEVICE_LIST),
|
||||
getData(URL_MAP.SENSOR_LIST)
|
||||
]
|
||||
data = await Promise.all(results)
|
||||
this.$store.commit('deviceList', data[0].data)
|
||||
this.$store.commit('sensorList', data[1].data)
|
||||
|
||||
let path = decodeURIComponent(this.$route.query.redirect || "/");
|
||||
this.$router.push({ path: path });
|
||||
} catch (e) {
|
||||
|
@ -11,6 +11,9 @@
|
||||
<p v-if="!isAnyone" style="cursor: pointer;" @click="changePasswd">
|
||||
更改密码
|
||||
</p>
|
||||
<p style="cursor: pointer;" @click="logout">
|
||||
登出
|
||||
</p>
|
||||
</template>
|
||||
<a-avatar :size="48" icon="user" />
|
||||
</a-popover>
|
||||
@ -39,7 +42,7 @@
|
||||
</a-row>
|
||||
</a-layout-header>
|
||||
<a-layout-content>
|
||||
<keep-alive>
|
||||
<keep-alive exclude="map-layout">
|
||||
<component :is="currentComp"/>
|
||||
</keep-alive>
|
||||
</a-layout-content>
|
||||
@ -53,6 +56,7 @@
|
||||
@ok="logout"
|
||||
@cancle="passwd_visible = false"
|
||||
/>
|
||||
|
||||
</a-modal>
|
||||
</a-layout>
|
||||
</template>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form-model :model="form">
|
||||
<a-form-model :model="form" :label-col="{span:4}" :wrapper-col="{span:14}">
|
||||
<a-form-model-item label="设备ID">
|
||||
<a-input :disabled="isCreate" v-model="form._id" />
|
||||
</a-form-model-item>
|
||||
@ -41,6 +41,9 @@
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="位置">
|
||||
<p>{{position.detail}}<a-button @click="visible=true" >点击选择</a-button></p>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item :wrapper-col="{ span: 14, offset: 4 }">
|
||||
<a-button type="primary" @click="onSubmit"> 确认 </a-button>
|
||||
<a-button style="margin-left: 10px" @click="$emit('cancle')">
|
||||
@ -48,14 +51,28 @@
|
||||
</a-button>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
<a-modal
|
||||
v-model="visible"
|
||||
:title="'选择位置'"
|
||||
:destroyOnClose="true"
|
||||
:footer="null"
|
||||
>
|
||||
<position-select style="height:520px;"
|
||||
:detail="position"
|
||||
@ok="handlePosOk"
|
||||
@cancle="visible=false"
|
||||
/>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mergeList } from "@/utils/utils";
|
||||
import { getData, URL_MAP } from "@/utils/http";
|
||||
import PositionSelect from './PositionSelect.vue';
|
||||
|
||||
export default {
|
||||
components: { PositionSelect },
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
@ -70,8 +87,10 @@ export default {
|
||||
},
|
||||
sensors: [],
|
||||
projects: [],
|
||||
position: {},
|
||||
fetching: false,
|
||||
isCreate: true,
|
||||
visible: false
|
||||
};
|
||||
},
|
||||
props: {
|
||||
@ -107,6 +126,11 @@ export default {
|
||||
this.fetching = false;
|
||||
}
|
||||
},
|
||||
handlePosOk(pos) {
|
||||
this.form.position = pos._id
|
||||
this.position = pos
|
||||
this.visible = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
for (let key in this.form) {
|
||||
@ -128,6 +152,18 @@ export default {
|
||||
this.form.project = null
|
||||
this.projects = []
|
||||
}
|
||||
if(this.detail.position) {
|
||||
this.form.position = this.detail.position._id
|
||||
this.position = this.detail.position
|
||||
}
|
||||
else{
|
||||
this.form.position = ''
|
||||
this.position = {
|
||||
detail:'',
|
||||
position:'',
|
||||
_id:''
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<a-form-model :model="form">
|
||||
<a-form-model :model="form" :label-col="{span:4}" :wrapper-col="{span:14}">
|
||||
<a-form-model-item label="旧密码">
|
||||
<a-input type="password" v-model="form.old" />
|
||||
</a-form-model-item>
|
||||
|
135
src/components/admin/forms/PositionSelect.vue
Normal file
135
src/components/admin/forms/PositionSelect.vue
Normal file
@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-spin :spinning="loading">
|
||||
<div id="map-pos-select" style="height: 460px; width: 100%"></div>
|
||||
<a-row style="margin-top: 20px">
|
||||
<a-col :span="4" :offset="8">
|
||||
<a-button @click="handleOk" type="primary">确认</a-button>
|
||||
</a-col>
|
||||
<a-col :span="4">
|
||||
<a-button @click="$emit('cancle')">取消</a-button>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-modal
|
||||
v-model="visible"
|
||||
title="输入名称"
|
||||
@ok="handleDetailOk"
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
>
|
||||
<a-input v-model="posDetail" />
|
||||
</a-modal>
|
||||
</a-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import "ol/ol.css";
|
||||
import Feature from "ol/Feature";
|
||||
import Map from "ol/Map";
|
||||
import View from "ol/View";
|
||||
import OSM from "ol/source/OSM";
|
||||
import Projection from "ol/proj/Projection";
|
||||
import { fromLonLat, toLonLat } from "ol/proj.js";
|
||||
import { Fill, Icon, Stroke, Style } from "ol/style";
|
||||
import { LineString, Point, Polygon } from "ol/geom";
|
||||
import GeoJSON from "ol/format/GeoJSON";
|
||||
import {
|
||||
Pointer as PointerInteraction,
|
||||
defaults as defaultInteractions,
|
||||
} from "ol/interaction";
|
||||
import { TileJSON, Vector as VectorSource } from "ol/source";
|
||||
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
|
||||
import { Drag } from "@/components/utils/olInteraction";
|
||||
import { deleteJSON, postJSON, URL_MAP } from "@/utils/http";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pointFeature: "",
|
||||
posDetail: "",
|
||||
visible: false,
|
||||
projection: null,
|
||||
loading: false,
|
||||
posId: "",
|
||||
};
|
||||
},
|
||||
props: {
|
||||
detail: Object,
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
var osm = new OSM();
|
||||
var layer = new TileLayer({
|
||||
source: osm,
|
||||
wrapX: false,
|
||||
});
|
||||
this.projection = osm.getProjection();
|
||||
var map = new Map({
|
||||
interactions: defaultInteractions().extend([new Drag()]),
|
||||
layers: [
|
||||
layer,
|
||||
new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [this.pointFeature],
|
||||
}),
|
||||
style: new Style({
|
||||
image: new Icon({
|
||||
anchor: [0.5, 0.5],
|
||||
anchorXUnits: "fraction",
|
||||
anchorYUnits: "fraction",
|
||||
opacity: 0.95,
|
||||
scale: 0.6,
|
||||
src: require("@/assets/poi.png"),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
],
|
||||
target: "map-pos-select",
|
||||
view: new View({
|
||||
center: fromLonLat([114.3, 30.6]),
|
||||
zoom: 10,
|
||||
}),
|
||||
});
|
||||
},
|
||||
handleOk() {
|
||||
this.visible = true;
|
||||
},
|
||||
async handleDetailOk() {
|
||||
this.visible = false;
|
||||
this.loading = true;
|
||||
try {
|
||||
let f = new GeoJSON().writeFeatureObject(this.pointFeature, {
|
||||
dataProjection: this.projection,
|
||||
});
|
||||
|
||||
let coors = f.geometry.coordinates;
|
||||
f.geometry.coordinates = toLonLat(coors, this.projection);
|
||||
let data = await postJSON(URL_MAP.POSITION_LIST, {
|
||||
detail: this.posDetail,
|
||||
position: JSON.stringify(f.geometry),
|
||||
});
|
||||
this.$emit("ok", data);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.posId = this.detail._id;
|
||||
this.posDetail = this.detail.detail;
|
||||
if (this.detail.position) {
|
||||
let g = JSON.parse(this.detail.position.replace(/'/g, '"'));
|
||||
g.coordinates = fromLonLat(g.coordinates);
|
||||
this.pointFeature = new Feature(new GeoJSON().readGeometry(g));
|
||||
} else {
|
||||
this.pointFeature = new Feature(new Point(fromLonLat([114.3, 30.6])));
|
||||
}
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form-model :model="form">
|
||||
<a-form-model :model="form" :label-col="{span:4}" :wrapper-col="{span:14}">
|
||||
<a-form-model-item label="项目名">
|
||||
<a-input v-model="form.name" />
|
||||
</a-form-model-item>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form-model :model="form">
|
||||
<a-form-model :model="form" :label-col="{span:4}" :wrapper-col="{span:14}">
|
||||
<a-form-model-item label="名称">
|
||||
<a-input v-model="form.name" />
|
||||
</a-form-model-item>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<a-form-model :model="form">
|
||||
<a-form-model :model="form" :label-col="{span:4}" :wrapper-col="{span:14}">
|
||||
<a-form-model-item label="用户名">
|
||||
<a-input v-model="form.username" />
|
||||
</a-form-model-item>
|
||||
|
@ -1,41 +1,114 @@
|
||||
<template>
|
||||
<div>
|
||||
<div id="map" ref="map" style="height:calc(100vh - 110px);"></div>
|
||||
<div id="map" ref="map" style="height: calc(100vh - 110px)"></div>
|
||||
<a-button
|
||||
style="position: absolute; top: 120px; right: 10px"
|
||||
shape="circle"
|
||||
icon="sync"
|
||||
type="primary"
|
||||
@click="loadBaseData"
|
||||
></a-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Map, Tile, View } from "ol";
|
||||
import { Map, View } from "ol";
|
||||
import OSM from "ol/source/OSM";
|
||||
import { fromLonLat, toLonLat } from "ol/proj.js";
|
||||
import TileLayer from "ol/layer/Tile";
|
||||
import { Fill, Icon, Stroke, Style } from "ol/style";
|
||||
import { TileJSON, Vector as VectorSource } from "ol/source";
|
||||
import { LineString, Point, Polygon } from "ol/geom";
|
||||
import GeoJSON from "ol/format/GeoJSON";
|
||||
import Feature from "ol/Feature";
|
||||
import "ol/ol.css";
|
||||
import { getData, login, logout, URL_MAP } from "@/utils/http";
|
||||
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
|
||||
|
||||
let map = null;
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
return {
|
||||
view: new View({
|
||||
center: fromLonLat([114.3, 30.6]),
|
||||
zoom: 10,
|
||||
}),
|
||||
waterLayer: '',
|
||||
projection: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
deviceList() {
|
||||
return this.$store.getters.deviceList;
|
||||
},
|
||||
sensorList() {
|
||||
return this.$store.getters.sensorList;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
mapinit() {
|
||||
var map = this.$refs.map;
|
||||
|
||||
var osm = new OSM();
|
||||
var layer = new TileLayer({
|
||||
source: new OSM(),
|
||||
source: osm,
|
||||
wrapX: false,
|
||||
});
|
||||
new Map({
|
||||
this.projection = osm.getProjection();
|
||||
this.waterLayer = this.getDeviceVectorLayer();
|
||||
map = new Map({
|
||||
target: "map",
|
||||
layers: [layer],
|
||||
view: new View({
|
||||
view: this.view,
|
||||
});
|
||||
map.addLayer(this.waterLayer);
|
||||
},
|
||||
getDeviceVectorLayer() {
|
||||
let devices = this.deviceList.filter((d) => !!d.position);
|
||||
let features = []
|
||||
devices.forEach((d) => {
|
||||
let g = JSON.parse(d.position.position.replace(/'/g, '"'));
|
||||
g.coordinates = fromLonLat(g.coordinates, this.projection);
|
||||
features.push(new Feature(new GeoJSON().readGeometry(g)));
|
||||
});
|
||||
console.log(features);
|
||||
let style = new Style({
|
||||
image: new Icon({
|
||||
anchor: [0.5, 0.5],
|
||||
anchorXUnits: "fraction",
|
||||
anchorYUnits: "fraction",
|
||||
opacity: 0.95,
|
||||
scale: 0.6,
|
||||
src: require("@/assets/water.png"),
|
||||
}),
|
||||
});
|
||||
return new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: features,
|
||||
}),
|
||||
style: style,
|
||||
});
|
||||
},
|
||||
async loadBaseData() {
|
||||
let results = [
|
||||
getData(URL_MAP.DEVICE_LIST),
|
||||
getData(URL_MAP.SENSOR_LIST),
|
||||
];
|
||||
let data = await Promise.all(results);
|
||||
this.$store.commit("deviceList", data[0].data);
|
||||
this.$store.commit("sensorList", data[1].data);
|
||||
map.setView(
|
||||
new View({
|
||||
center: fromLonLat([114.3, 30.6]),
|
||||
zoom: 10,
|
||||
}),
|
||||
});
|
||||
})
|
||||
);
|
||||
map.removeLayer(this.waterLayer)
|
||||
this.waterLayer = this.getDeviceVectorLayer()
|
||||
map.addLayer(this.waterLayer)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.mapinit()
|
||||
}
|
||||
this.mapinit();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
109
src/components/utils/olInteraction.js
Normal file
109
src/components/utils/olInteraction.js
Normal file
@ -0,0 +1,109 @@
|
||||
import {
|
||||
Pointer as PointerInteraction,
|
||||
defaults as defaultInteractions,
|
||||
} from 'ol/interaction';
|
||||
|
||||
export const Drag = /*@__PURE__*/(function (PointerInteraction) {
|
||||
function Drag() {
|
||||
PointerInteraction.call(this, {
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleMoveEvent: handleMoveEvent,
|
||||
handleUpEvent: handleUpEvent,
|
||||
});
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
if ( PointerInteraction ) Drag.__proto__ = PointerInteraction;
|
||||
Drag.prototype = Object.create( PointerInteraction && PointerInteraction.prototype );
|
||||
Drag.prototype.constructor = Drag;
|
||||
|
||||
return Drag;
|
||||
}(PointerInteraction));
|
||||
|
||||
/**
|
||||
* @param {import("../src/ol/MapBrowserEvent.js").default} evt Map browser event.
|
||||
* @return {boolean} `true` to start the drag sequence.
|
||||
*/
|
||||
function handleDownEvent(evt) {
|
||||
var map = evt.map;
|
||||
|
||||
var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
|
||||
return feature;
|
||||
});
|
||||
|
||||
if (feature) {
|
||||
this.coordinate_ = evt.coordinate;
|
||||
this.feature_ = feature;
|
||||
}
|
||||
|
||||
return !!feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../src/ol/MapBrowserEvent.js").default} evt Map browser event.
|
||||
*/
|
||||
function handleDragEvent(evt) {
|
||||
var deltaX = evt.coordinate[0] - this.coordinate_[0];
|
||||
var deltaY = evt.coordinate[1] - this.coordinate_[1];
|
||||
|
||||
var geometry = this.feature_.getGeometry();
|
||||
geometry.translate(deltaX, deltaY);
|
||||
|
||||
this.coordinate_[0] = evt.coordinate[0];
|
||||
this.coordinate_[1] = evt.coordinate[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../src/ol/MapBrowserEvent.js").default} evt Event.
|
||||
*/
|
||||
function handleMoveEvent(evt) {
|
||||
if (this.cursor_) {
|
||||
var map = evt.map;
|
||||
var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature) {
|
||||
return feature;
|
||||
});
|
||||
var 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {boolean} `false` to stop the drag sequence.
|
||||
*/
|
||||
function handleUpEvent() {
|
||||
this.coordinate_ = null;
|
||||
this.feature_ = null;
|
||||
return false;
|
||||
}
|
@ -18,7 +18,9 @@ export const URL_MAP = {
|
||||
USER_LIST: 'user/',
|
||||
USER_DETAIL: 'user/detail/',
|
||||
CHANGE_PASSWD: 'current/chpass/',
|
||||
RESET_PASSWD: 'passwd/reset/'
|
||||
RESET_PASSWD: 'passwd/reset/',
|
||||
POSITION_LIST: 'position/',
|
||||
POSITION_DETAIL: 'position/detail/'
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user