添加定位与展示功能

This commit is contained in:
王铜 2020-11-29 21:30:37 +08:00
parent 8d0babadd9
commit cee790c4fc
13 changed files with 391 additions and 21 deletions

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -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) {

View File

@ -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>

View File

@ -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>

View File

@ -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>

View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View 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;
}

View File

@ -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/'
}