@@ -16,6 +16,7 @@ | |||
"axios": "^0.26.1", | |||
"dayjs": "^1.11.2", | |||
"mockjs": "^1.1.0", | |||
"ol": "^6.15.1", | |||
"pinia": "^2.0.13", | |||
"pinia-plugin-persist": "^1.0.0", | |||
"tinymce": "^5.10.2", |
@@ -0,0 +1,90 @@ | |||
<template> | |||
<div class="overlay_container"> | |||
<div class="overlay_head"> | |||
<img class="close_img" src="@/assets/point/close.png" alt="" @click="close"> | |||
</div> | |||
<div class="overlay_main"> | |||
<n-form | |||
ref="formRef" | |||
:model="form" | |||
:label-width="80" | |||
label-placement="left" | |||
require-mark-placement="left" | |||
> | |||
<n-form-item label="问题类型:"> | |||
<n-select | |||
v-model:value="form.name" | |||
:options="typeList" | |||
placeholder="请选择问题类型" | |||
/> | |||
</n-form-item> | |||
<n-form-item label="问题描述:"> | |||
<span>{{ form.content }}</span> | |||
</n-form-item> | |||
<n-form-item label="经纬度:"> | |||
<span>{{ form.longitude }},{{ form.latitude }}</span> | |||
</n-form-item> | |||
<n-form-item label="问题图片:"> | |||
<img class="image_size" :src="form.fileImage" alt="" style="width: 108px; height: auto; margin: 0 5px 5px 0"> | |||
</n-form-item> | |||
</n-form> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { toRefs, reactive } from 'vue' | |||
export default { | |||
name: 'OverLay', | |||
props: { | |||
data: { | |||
type: Object, | |||
default: () => null | |||
} | |||
}, | |||
emits: { 'close': null }, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
form: Object.assign({}, props.data), | |||
typeList: [ | |||
{ value: 0, label: '林班' } | |||
] | |||
}) | |||
function close() { | |||
emit('close') | |||
} | |||
return { | |||
...toRefs(data), | |||
close | |||
} | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.overlay_container { | |||
width: 100%; | |||
height: 436px; | |||
padding: 0; | |||
overflow-y: scroll; | |||
background-color: #fff; | |||
} | |||
.overlay_head { | |||
width: 100%; | |||
display: flex; | |||
justify-content: flex-end; | |||
align-items: center; | |||
} | |||
.close_img { | |||
width: 40px; | |||
height: 40px; | |||
cursor: pointer; | |||
} | |||
.overlay_main { | |||
width: 100%; | |||
margin-top: 10px; | |||
padding: 0 30px 0 40px; | |||
} | |||
</style> |
@@ -0,0 +1,82 @@ | |||
<template> | |||
<div class="main_container"> | |||
<div id="track" ref="map" /> | |||
<div id="pointOverlay" class="point_overlay"> | |||
<over-lay :data="problemData" @close="closeOverlay" /> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import { reactive, toRefs, onMounted } from 'vue' | |||
import OverLay from './OverLay.vue' | |||
import { initMap, setOverlay } from './util.js' | |||
export default { | |||
name: 'PositionMsg', | |||
components: { OverLay }, | |||
props: {}, | |||
emits: {}, | |||
setup(props, { emit }) { | |||
const data = reactive({ | |||
mapdata: null, // 地图 | |||
view: null, // 视图 | |||
source: null, | |||
layer: null, // 底图 | |||
problemLayer: null, // 问题矢量图 | |||
select: null, | |||
TDimageMap: null, // 影像底图 | |||
problemList: [ | |||
{ content: '河道内存在水生植被', | |||
fileImage: 'https://image.t-aaron.com/XJRW20220725103839/2022-07-25-10-41-46_frame-1500-1680_type-水生植被_VMgRwh05s4clHXCu_s-live-XJRW20220725103839-b73c470768f74422b287981fc75c31c3_AI.jpg', | |||
handlerImage: 'https://image.t-aaron.com/imagedir/kw6vv4m1yw_1658717157035.png', | |||
handlerResult: '', | |||
handlerTime: '2022-07-25 10:45:56', | |||
latitude: '31.829037194418085', | |||
location: '江苏省南京市江宁区秣陵街道东吉大道', | |||
longitude: '118.770222690945', | |||
name: 1, | |||
status: 1, | |||
type: 1, | |||
userName: '运管单位' } | |||
], // 问题矢量点列表 | |||
overlay: null, // overlay弹出框 | |||
problemData: {} // 问题点数据 | |||
}) | |||
onMounted(() => { | |||
initMap('track', data.problemList, 'pointOverlay').then(({ mapdata, select, view, overlay, dataObj, problemLayer }) => { | |||
data.mapdata = mapdata | |||
data.select = select | |||
data.view = view | |||
data.overlay = overlay | |||
data.problemData = dataObj | |||
data.problemLayer = problemLayer | |||
}) | |||
}) | |||
const closeOverlay = () => { | |||
data.select.getFeatures().clear() | |||
data.mapdata.removeOverlay(data.overlay) | |||
} | |||
return { | |||
...toRefs(data), | |||
closeOverlay | |||
} | |||
} | |||
} | |||
</script> | |||
<style scoped> | |||
.main_container { | |||
width: 100%; | |||
height: 100%; | |||
position: relative; | |||
overflow: hidden; | |||
} | |||
#track { | |||
width: 100%; | |||
height: 100%; | |||
} | |||
.point_overlay { | |||
width: 400px; | |||
} | |||
</style> |
@@ -0,0 +1,215 @@ | |||
import { Map, View, Feature, Overlay } from 'ol' | |||
import 'ol/ol.css' | |||
import Projection from 'ol/proj/Projection' | |||
import { Tile, Vector as VectorLayer } from 'ol/layer' | |||
import LineString from 'ol/geom/LineString' | |||
import { ImageStatic, TileWMS, XYZ, Vector as VectorSource } from 'ol/source' | |||
import { transform, fromLonLat } from 'ol/proj' | |||
import * as control from 'ol/control' | |||
import { Select } from 'ol/interaction' | |||
import { Stroke, Style, Icon } from 'ol/style' | |||
import Point from 'ol/geom/Point' | |||
import imgAll from '../../assets/point/all.png' | |||
import imgChecked from '../../assets/point/checked.png' | |||
/** | |||
* 初始化地图 | |||
* @param {*} ids dom的id | |||
* @param {*} mapdata 地图对象 | |||
* @param {*} blanklayerList 显示图层列表 | |||
* @param {*} datalayerList 待添加图层列表 | |||
* @param {*} zoom 层级 | |||
* @param {*} interactions 控制 | |||
*/ | |||
export function initMap(ids, data, overlayId) { | |||
const layers = [ | |||
new Tile({ | |||
visible: true, | |||
source: new XYZ({ | |||
url: 'https://tianditu.t-aaron.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=f82bb2fd8115c7fb576a8b2fcf738523' | |||
}) | |||
}) | |||
] | |||
const view = new View({ | |||
maxZoom: 18, | |||
zoom: 4, | |||
center: transform([108.94043, 31.008173], 'EPSG:4326', 'EPSG:3857') | |||
}) | |||
const mapdata = new Map({ | |||
layers: layers, | |||
target: ids, | |||
view: view, | |||
controls: control.defaults({ | |||
attribution: false, | |||
rotate: false, | |||
zoom: false | |||
}) | |||
}) | |||
mapdata.render() | |||
const problemLayer = null | |||
getLayers(data, problemLayer, view, mapdata) | |||
const select = new Select({ | |||
style: (feature) => { | |||
const properties = feature.getProperties() | |||
if (feature.getGeometry() instanceof Point) { | |||
return styleList[properties.item.status] | |||
} | |||
} | |||
}) | |||
mapdata.addInteraction(select) | |||
// 新建overlay弹出框 | |||
const overlay = new Overlay({ | |||
element: document.getElementById(overlayId), | |||
autoPan: true | |||
}) | |||
let dataObj | |||
select.on('select', (e) => { | |||
if (e.selected.length > 0) { | |||
const properties = e.selected[0].getProperties() | |||
const geom = properties.geometry | |||
if (geom instanceof Point) { | |||
dataObj = properties.item | |||
const coordinate = e.mapBrowserEvent.coordinate | |||
overlay.setPosition(coordinate) | |||
overlay.setOffset([30, -400]) | |||
mapdata.addOverlay(overlay) | |||
} else { | |||
mapdata.removeOverlay(overlay) | |||
} | |||
} else { | |||
mapdata.removeOverlay(overlay) | |||
} | |||
}) | |||
return Promise.resolve({ | |||
mapdata, | |||
view, | |||
select, | |||
overlay, | |||
dataObj | |||
}) | |||
} | |||
/** | |||
* 选择矢量图层并添加overlay | |||
* @param {*} overlay | |||
* @param {*} select 选择 | |||
* @param {*} mapdata 地图 | |||
* @param {*} problemData 问题数据 | |||
*/ | |||
export function setOverlay(overlay, select, mapdata, problemData) { | |||
console.log(select) | |||
select.on('select', (e) => { | |||
if (e.selected.length > 0) { | |||
const properties = e.selected[0].getProperties() | |||
const geom = properties.geometry | |||
if (geom instanceof Point) { | |||
problemData = properties.item | |||
const coordinate = e.mapBrowserEvent.coordinate | |||
overlay.setPosition(coordinate) | |||
overlay.setOffset([30, -400]) | |||
mapdata.addOverlay(overlay) | |||
} else { | |||
mapdata.removeOverlay(overlay) | |||
} | |||
} else { | |||
mapdata.removeOverlay(overlay) | |||
} | |||
}) | |||
return Promise.resolve({ | |||
overlay, | |||
select, | |||
mapdata, | |||
problemData | |||
}) | |||
} | |||
// 矢量图标样式 | |||
const styleList = [ | |||
new Style({ | |||
image: new Icon({ | |||
anchor: [0.5, 0.5], | |||
src: imgAll, | |||
crossOrigin: '', | |||
scale: [1, 1], | |||
rotateWithView: true | |||
}) | |||
}), | |||
new Style({ | |||
image: new Icon({ | |||
anchor: [0.5, 0.5], | |||
src: imgChecked, | |||
crossOrigin: '', | |||
scale: [1, 1], | |||
rotateWithView: true | |||
}) | |||
}) | |||
] | |||
/** | |||
* 生成矢量图层 | |||
* @param {*} datalayerList 图层数据列表 | |||
* [{paramlayer: '图层名',type: 'wms' 类型}] | |||
* @returns | |||
*/ | |||
function getLayers(data, layer, view, map) { | |||
const pointFeatures = [] | |||
const points = [] | |||
if (data.length) { | |||
data.forEach((item) => { | |||
const pointItem = [] | |||
pointItem.push(parseFloat(item.longitude)) | |||
pointItem.push(parseFloat(item.latitude)) | |||
const featureItem = new Feature(new Point(fromLonLat(pointItem))) | |||
points.push(fromLonLat(pointItem)) | |||
featureItem.setProperties({ item: item, type: 'problem' }, false) | |||
featureItem.setStyle(styleList[item.status]) | |||
pointFeatures.push(featureItem) | |||
}) | |||
const pointSource = new VectorSource({ | |||
wrapX: false, | |||
features: pointFeatures | |||
}) | |||
layer = new VectorLayer({ | |||
source: pointSource, | |||
zIndex: 12 | |||
}) | |||
let geom | |||
if (points.length > 1) { | |||
geom = new LineString(points) | |||
} else if (points.length > 0) { | |||
geom = new Point(points[0]) | |||
} | |||
if (geom) { | |||
view.fit(geom, { padding: [100, 100, 100, 100] }) | |||
} | |||
map.addLayer(layer) | |||
} | |||
} | |||
/** | |||
* 引入静态图标创建图标对象 | |||
**/ | |||
const imgstyle = new Style({ | |||
image: new Icon({ | |||
anchor: [0.5, 1], | |||
src: import.meta.env.BASE_URL + `img/icon-biaozhu.png`, | |||
scale: 0.5 | |||
}) | |||
}) | |||
/** | |||
* 使用feature | |||
* coordinate 坐标 | |||
**/ | |||
export function setTrmFeature(coordinate) { | |||
const feature = new Feature({ | |||
type: 'icon', | |||
geometry: new Point(coordinate) | |||
}) | |||
feature.setStyle(imgstyle) | |||
return feature | |||
} | |||
@@ -11,7 +11,7 @@ export default [ | |||
}, | |||
children: [ | |||
{ | |||
path: 'allTask', | |||
path: 'all', | |||
component: () => import('@/views/task-manage/all-task/index.vue'), | |||
name: 'TaskAll', | |||
title: '所有任务', |
@@ -114,11 +114,11 @@ export const usePermissionStore = defineStore('permission', { | |||
try { | |||
const res = await getMenu() | |||
if (res.code === 0) { | |||
// const result = dataArrayToRoutes(res.data) | |||
// this.accessRoutes = result | |||
// return Promise.resolve(result) | |||
this.accessRoutes = router | |||
return Promise.resolve(router) | |||
const result = dataArrayToRoutes(res.data) | |||
this.accessRoutes = result | |||
return Promise.resolve(result) | |||
// this.accessRoutes = router | |||
// return Promise.resolve(router) | |||
} else { | |||
return Promise.reject(res.message) | |||
} |
@@ -126,7 +126,6 @@ export default defineComponent({ | |||
if (props.row.pid === 0) { | |||
row.pid = null | |||
} | |||
console.log('====部门计算属性触发了====', row) | |||
return { | |||
title: props.row.name ? '修改部门' : '添加部门', | |||
show: props.visible, |
@@ -1,16 +1,18 @@ | |||
<template> | |||
<n-drawer v-bind="getDrawerOptions" @update:show="handleDrawerColse"> | |||
<n-drawer-content closable title="问题核实"> | |||
问题核实 | |||
<position-msg /> | |||
</n-drawer-content> | |||
</n-drawer> | |||
</template> | |||
<script> | |||
import { h, defineComponent, computed, reactive, toRefs } from 'vue' | |||
import PositionMsg from '@/components/PositionMsg/index.vue' | |||
export default defineComponent({ | |||
name: 'LiveDrawer', | |||
components: { PositionMsg }, | |||
props: { | |||
/* 可见 */ | |||
visible: { |