"axios": "^0.26.1", | "axios": "^0.26.1", | ||||
"dayjs": "^1.11.2", | "dayjs": "^1.11.2", | ||||
"mockjs": "^1.1.0", | "mockjs": "^1.1.0", | ||||
"ol": "^6.15.1", | |||||
"pinia": "^2.0.13", | "pinia": "^2.0.13", | ||||
"pinia-plugin-persist": "^1.0.0", | "pinia-plugin-persist": "^1.0.0", | ||||
"tinymce": "^5.10.2", | "tinymce": "^5.10.2", |
<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> |
<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> |
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 | |||||
} | |||||
}, | }, | ||||
children: [ | children: [ | ||||
{ | { | ||||
path: 'allTask', | |||||
path: 'all', | |||||
component: () => import('@/views/task-manage/all-task/index.vue'), | component: () => import('@/views/task-manage/all-task/index.vue'), | ||||
name: 'TaskAll', | name: 'TaskAll', | ||||
title: '所有任务', | title: '所有任务', |
try { | try { | ||||
const res = await getMenu() | const res = await getMenu() | ||||
if (res.code === 0) { | 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 { | } else { | ||||
return Promise.reject(res.message) | return Promise.reject(res.message) | ||||
} | } |
if (props.row.pid === 0) { | if (props.row.pid === 0) { | ||||
row.pid = null | row.pid = null | ||||
} | } | ||||
console.log('====部门计算属性触发了====', row) | |||||
return { | return { | ||||
title: props.row.name ? '修改部门' : '添加部门', | title: props.row.name ? '修改部门' : '添加部门', | ||||
show: props.visible, | show: props.visible, |
<template> | <template> | ||||
<n-drawer v-bind="getDrawerOptions" @update:show="handleDrawerColse"> | <n-drawer v-bind="getDrawerOptions" @update:show="handleDrawerColse"> | ||||
<n-drawer-content closable title="问题核实"> | <n-drawer-content closable title="问题核实"> | ||||
问题核实 | |||||
<position-msg /> | |||||
</n-drawer-content> | </n-drawer-content> | ||||
</n-drawer> | </n-drawer> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import { h, defineComponent, computed, reactive, toRefs } from 'vue' | import { h, defineComponent, computed, reactive, toRefs } from 'vue' | ||||
import PositionMsg from '@/components/PositionMsg/index.vue' | |||||
export default defineComponent({ | export default defineComponent({ | ||||
name: 'LiveDrawer', | name: 'LiveDrawer', | ||||
components: { PositionMsg }, | |||||
props: { | props: { | ||||
/* 可见 */ | /* 可见 */ | ||||
visible: { | visible: { |