Files
Lydc_frontend/src/components/DataManagement/DataManagement.vue
2025-12-05 10:46:19 +08:00

1990 lines
61 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div id="mapDiv">
<Map @mapView="getMap"></Map>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
>
<div v-show="collapsed" id="leftPanel">
<div>
<!--展开折叠开关-->
<div @click.prevent="collapse" id="toLeft">
<i
v-if="collapsed"
class="el-icon-arrow-left"
title="收起"
style="margin-top: 13px; color: #264672"
></i>
<i
v-else
class="el-icon-arrow-right"
title="展开"
style="margin-top: 13px; color: #264672"
></i>
</div>
</div>
<div id="leftPanelScroll">
<el-tabs v-model="activeName">
<el-tab-pane label="数据查看" name="second">
<div>
<p class="mylabel">
<span class="label-text">任务</span>
<el-select
v-model="task"
size="small"
style="width: 60%"
placeholder="请选择任务"
filterable
clearable
@focus="getTasks()"
@change="table = ''; userId = ''"
>
<el-option
v-for="item in taskoptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</p>
<p class="mylabel">
<span class="label-text"></span>
<el-select
id="sTable"
v-model="table"
size="small"
style="width: 60%"
placeholder="请选择表"
filterable
clearable
@focus="getTables()"
>
<el-option
v-for="item in tableoptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</p>
<p class="mylabel">
<span class="label-text">人员</span>
<el-select
id="sUser"
v-model="userId"
size="small"
style="width: 60%"
placeholder="请选择人员"
filterable
clearable
@focus="getUser()"
@blur="handleUserSelectBlur"
>
<el-option
v-for="item in useroptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</p>
<el-button
size="small"
icon="el-icon-search"
class="dateBtn"
style="background-color: #304156; color: #fff"
@click="handleConfirmClick()"
>确定
</el-button
>
<!-- 显示要素信息属性照片和视频
<div v-if="Info && Object.keys(Info).length > 0" style="margin-top: 20px">
<featureInfo :data="Info" style="margin: 0 auto"/>
</div>-->
</div>
</el-tab-pane>
</el-tabs>
<div id="editionContainer">
<el-tabs v-model="activeName1">
<el-tab-pane label="版本回退" name="first1">
<p>
重叠数据查看
<el-tooltip
class="item"
effect="dark"
content="在地图上选择要素后,切换查看与已选要素重叠的要素"
placement="top-end"
><i class="el-icon-info"></i></el-tooltip
>
<el-select
v-model="currentFeatureId"
style="width: 55%; margin-bottom: 10px"
placeholder="请选择数据id"
filterable
clearable
>
<el-option
v-for="item in FeaturesId"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</p>
<featureInfo :data="Info" style="margin: 0 auto"/>
<div class="button-group" v-if="currentFeatureId && Object.keys(Info).length > 0">
<el-button
size="small"
class="dateBtn"
@click="ifsub ? getGeoJson() : getSubGeoJson()"
>{{ ifsub ? '返回父表' : '进入子表' }}
</el-button>
<el-button
size="small"
class="dateBtn"
@click="clearAll()"
>清除
</el-button>
<el-button
size="small"
class="dateBtn"
icon="el-icon-info"
@click="getEdition()"
>查看历史版本
</el-button>
</div>
</el-tab-pane>
<el-tab-pane label="数据审核" name="second1">
<el-radio-group v-model="datastatus">
<el-radio :label="0">未审核</el-radio>
<el-radio :label="2">审核已通过</el-radio>
<el-radio :label="-1">审核未通过</el-radio>
</el-radio-group>
<div v-show="getList === true">
<div
:key="i"
v-for="(item, i) in examData"
style="border: 1px solid #cfcece; text-align: left"
>
{{ i + 1 + (pageNumber - 1) * pageSize }}.
<el-row
v-for="(val, key) in examData[i]"
:key="key"
@click.native="getExamInfo(i)"
>
<el-col>
{{ key }}:
<span style="color: #409eff">{{ val }}</span>
</el-col>
</el-row>
</div>
<el-pagination
small
layout="prev, pager, next, jumper,sizes"
:page-count="dataPageNum"
@current-change="pageChange"
@size-change="pageSizeChange"
style="height: 80px; white-space: break-spaces;"
></el-pagination>
</div>
<div v-show="getList === false">
<el-button
type="text"
@click="getList = true"
style="color: #409eff !important; margin-left: -250px"
>返回列表
</el-button
>
<featureInfo :data="examInfo" style="margin: 0 auto"/>
<el-button
v-show="datastatus === 0"
size="small"
icon="el-icon-success"
style="
background-color: #304156;
color: #fff;
margin-top: 20px;
margin-bottom: 20px;
"
@click="passData()"
>审核通过
</el-button
>
<el-button
v-show="datastatus === 0"
size="small"
icon="el-icon-error"
style="
background-color: #304156;
color: #fff;
margin-top: 20px;
margin-bottom: 20px;
"
@click="deleteData()"
>审核未通过
</el-button
>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</transition>
<div style="height: 100%">
<el-dialog
v-dialogDrag
class="infoDialog1"
title="历史版本信息"
:visible.sync="dialogVisible"
>
<p>
数据历史版本
<el-select
size="small"
v-model="edition"
style="width: 71%"
placeholder="请选择历史版本"
filterable
clearable
@change="getEditionData()"
>
<el-option
v-for="item in editionoptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</p>
<featureInfo :data="EditionInfo" style="margin: 0 auto"/>
<el-button
size="small"
icon="el-icon-sort"
style="background-color: #304156; color: #fff; margin-top: 10px"
@click="Rollback()"
>回退到当前历史版本
</el-button
>
</el-dialog>
</div>
</div>
</template>
<script>
import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import GeoJSON from 'ol/format/GeoJSON'
import Select from 'ol/interaction/Select'
import {ajax as request} from '@/request.js'
import 'ol/ol.css'
import Feature from 'ol/Feature'
import Point from 'ol/geom/Point'
import {Cluster} from 'ol/source'
import {Circle as CircleStyle, Fill, Stroke, Style, Text} from 'ol/style'
const Map = () => import('../Mapview/Map')
const featureInfo = () => import('../DataManagement/featureInfo')
export default {
name: 'ViewTask',
data () {
return {
isExtend: false,
datastatus: 0,
dataPageNum: 1,
pageNumber: 1,
pageSize: 10,
dataInfo: [],
dataCoordinates: [],
getList: true,
examData: [],
FeaturesId: [],
clusters: null,
isClusters: false,
vectorLayer: null,
isVectorLayer: false,
distribute: false,
minSize: '',
maxSize: '',
cellLayer: null,
dialogVisible: false,
selectclick: null,
activeName: 'second',
activeName1: 'first1',
collapsed: true,
drawer: false,
task: '',
table: '',
userId: '',
edition: '',
Info: {},
examInfo: {},
EditionInfo: {},
taskoptions: [],
tableoptions: [],
useroptions: [],
editionoptions: [],
currentFeatureId: '',
feature: null,
vectorSource: null,
pageLayer: null,
pageSource: null,
selectclick1: null,
sontablename: '',
fathertablename: '',
ifsub: false,
iffather: false,
fathergeom: null,
fatherFeatureLayer: null,
isFatherFeatureLayer: false,
isSwitchingToSubTable: false,
selectId: null
}
},
components: {
Map,
featureInfo
},
created () {
},
mounted () {
},
methods: {
getTasks () {
this.taskoptions = []
let that = this
// 从 store 获取数据
const taskData = that.$store.state.taskData.selectTaskHasCreated || []
for (var i = 0; i < taskData.length; i++) {
that.taskoptions.push({
value: taskData[i].id,
label: taskData[i].taskName
})
}
},
getTables () {
if (this.task === '') {
this.$alert('请先选择任务!', '提示', {
confirmButtonText: '确定'
})
document.getElementById('sTable').blur()
} else {
var taskname = ''
for (var i = 0; i < this.taskoptions.length; i++) {
if (this.task === this.taskoptions[i].value) {
taskname = this.taskoptions[i].label
break
}
}
this.tableoptions = []
let that = this
request({
url: '/statistic/getTables',
method: 'post',
params: {
tskName: taskname
}
}).then(function (response) {
// 获取数据存入config
if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
} else if (response.status === 200) {
var json = response.data
for (var key in json) {
that.tableoptions.push({
value: key,
label: json[key]
})
}
}
})
}
},
getUser () {
if (this.task === '') {
this.$alert('请先选择任务!', '提示', {
confirmButtonText: '确定'
})
document.getElementById('sUser').blur()
} else {
this.useroptions = []
let that = this
request({
// url: '/report/workloadByUser',
url: 'statistic/getWorkers',
method: 'get',
params: {
taskId: that.task
}
}).then(function (response) {
// 登录成功获取数据存入usersData
if (response.data.success) {
response.data.data.forEach(user => {
that.useroptions.push({
value: user.id,
label: user.realName
})
})
}
})
}
},
getMap (val) {
this.map = val
let that = this
this.map.on('moveend', function (e) {
// 20250729
if (that.ifsub) {
return
}
// ---------------
// 移除所有
if (that.clusters) {
if (that.isClusters) {
that.map.removeLayer(that.clusters)
}
that.clusters = null
}
if (that.vectorLayer) {
if (that.isVectorLayer) {
that.map.removeLayer(that.vectorLayer)
that.map.removeInteraction(that.selectclick)
}
that.vectorLayer = null
that.selectclick = null
}
if (that.distribute && that.activeName1 === 'first1' && that.cellLayer) {
that.debounce(that.getClusters(), 500)
}
})
},
debounce (fn, delay) {
let timer = null // 借助闭包
return function () {
if (timer) {
clearTimeout(timer)
timer = setTimeout(fn, delay)
} else {
timer = setTimeout(fn, delay)
}
}
},
// 左侧面板收缩动画
collapse () {
this.collapsed = !this.collapsed
},
beforeEnter: function (el) {
el.style.transform = 'translate(410px,0px)'
},
enter: function (el, done) {
el.style.transform = 'translate(0px,0px)'
el.style.transition = 'all 0.6s ease'
done()
},
beforeLeave: function (el) {
el.style.transform = 'translate(0px,0px)'
},
leave: function (el, done) {
el.style.transform = 'translate(-425px,0px)'
el.style.transition = 'all 0.6s ease'
// done();
},
getRange (addToMap) {
let that = this
request({
url: '/allocation/info/cell/all',
method: 'post',
params: {
taskId: that.task
}
}).then(function (response) {
// 获取数据存入config
if (response.data.status === 200) {
var result = response.data.data
if (result.features.length !== 0) {
that.drawCellLayer(result)
that.map.getView().fit(that.cellLayer.getSource().getExtent())
// if (that.ifsub === false && that.iffather === false) {
// that.map.getView().fit(that.cellLayer.getSource().getExtent())
// }
that.getClusters()
} else {
that.$message.info('获取任务范围失败,未上传数据!')
}
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
},
getClusters () {
var zoom = 0
zoom = this.map.getView().getZoom()
// 获取地图范围
var coordinates = this.map.getView().calculateExtent(this.map.getSize())
var geoHashLength = ''
switch (zoom) {
case 8:
case 9:
geoHashLength = 4
break
case 10:
case 11:
case 12:
geoHashLength = 5
break
case 13:
case 14:
case 15:
case 16:
geoHashLength = 6
break
case 17:
case 18:
case 19:
case 20:
geoHashLength = 7
break
default:
geoHashLength = 3
}
if (this.distribute) {
if (this.ifsub) {
let that = this
request({
url: '/get/getSubDataByRangeIntersection',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
parentId: that.selectId,
longitudeMin: coordinates[0],
latitudeMin: coordinates[1],
longitudeMax: coordinates[2],
latitudeMax: coordinates[3]
}
}).then(function (response) {
if (response.data.success) {
if (response.data.data) {
var geojson = response.data.data
var geojsonObject = {
type: 'FeatureCollection',
features: geojson,
crs: {type: 'EPSG', properties: {code: '4326'}}
}
that.drawVectorLayer(geojsonObject)
} else {
that.$message.info('获取范围内数据为空!')
}
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
} else {
if (zoom < 15) {
// 请求聚类图层
let that = this
that.minSize = 0
that.maxSize = 0
request({
url: '/base/getCountByGeoHash',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
accuracy: geoHashLength,
longitudeMin: coordinates[0],
latitudeMin: coordinates[1],
longitudeMax: coordinates[2],
latitudeMax: coordinates[3]
}
}).then(function (response) {
if (response.data.success) {
if (response.data.data) {
var result = response.data.data
var geojson = []
for (var i = 0; i < result.length; i++) {
var count = result[i].count
if (i === 0) {
that.minSize = count
that.maxSize = count
} else {
if (count < that.minSize) {
that.minSize = count
}
if (count > that.maxSize) {
that.maxSize = count
}
}
// 存入count
var geojson1 = result[i].feature
geojson1.properties = {}
geojson1.properties.count = count
geojson.push(result[i].feature)
}
var geojsonObject = {
type: 'FeatureCollection',
features: geojson,
crs: {type: 'EPSG', properties: {code: '4326'}}
}
that.drawClusterLayer(geojsonObject)
} else {
that.$message.info('获取范围内数据为空!')
}
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
} else {
let that = this
request({
url: '/get/getDataByRangeIntersection',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
longitudeMin: coordinates[0],
latitudeMin: coordinates[1],
longitudeMax: coordinates[2],
latitudeMax: coordinates[3]
}
}).then(function (response) {
if (response.data.success) {
if (response.data.data) {
var geojson = response.data.data
var geojsonObject = {
type: 'FeatureCollection',
features: geojson,
crs: {type: 'EPSG', properties: {code: '4326'}}
}
that.drawVectorLayer(geojsonObject)
} else {
that.$message.info('获取范围内数据为空!')
}
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
}
}
}
},
drawCellLayer (geojsonObject) {
if (this.cellLayer) {
this.map.removeLayer(this.cellLayer)
}
var vectorSource = new VectorSource({
features: new GeoJSON().readFeatures(geojsonObject)
})
this.cellLayer = new VectorLayer({
source: vectorSource
})
this.cellLayer.setZIndex(5)
},
drawClusterLayer (geojsonObject) {
if (this.clusters) {
if (this.isClusters) {
this.map.removeLayer(this.clusters)
this.isClusters = false
}
this.clusters = null
}
if (this.vectorLayer) {
if (this.isVectorLayer) {
this.map.removeLayer(this.vectorLayer)
this.map.removeInteraction(this.selectclick)
}
this.vectorLayer = null
this.selectclick = null
}
var vectorSource = new VectorSource({
features: new GeoJSON().readFeatures(geojsonObject)
})
// let that = this
this.clusters = new VectorLayer({
source: vectorSource,
style: function (feature) {
// let count = feature.get('count').toString()
let style = new Style({
stroke: new Stroke({
lineDash: [1, 2, 3, 4, 5, 6],
color: 'rgba(70,130,180, 0.9)',
width: 2
}),
fill: new Fill({
color: [255, 153, 0, 0.8]
}),
text: new Text({
text: feature.get('count').toString(),
font: '16px Microsoft YaHei',
fill: new Fill({
color: '#fff'
}),
stroke: new Stroke({
color: 'rgba(0, 0, 0, 0.6)',
width: 3
})
})
})
return [style]
}
})
this.clusters.setZIndex(4)
this.map.addLayer(this.clusters)
this.isClusters = true
},
drawVectorLayer (geojsonObject) {
this.drawFatherFeature()
if (this.clusters) {
if (this.isClusters) {
this.map.removeLayer(this.clusters)
}
this.clusters = null
}
if (this.vectorLayer) {
if (this.isVectorLayer) {
this.map.removeLayer(this.vectorLayer)
this.map.removeInteraction(this.selectclick)
}
this.vectorLayer = null
this.selectclick = null
}
this.vectorSource = new VectorSource({
features: new GeoJSON().readFeatures(geojsonObject)
})
var styles = {
Point: new Style({
image: new CircleStyle({
radius: 7,
fill: new Fill({
color: 'rgba(173,216,230)'
}),
stroke: new Stroke({
lineDash: [1, 2, 3, 4, 5, 6],
color: 'rgba(70,130,180)',
width: 2
})
}),
stroke: new Stroke({
lineDash: [1, 2, 3, 4, 5, 6],
color: 'rgba(70,130,180)',
width: 2
}),
fill: new Fill({
color: 'rgba(173,216,230)'
})
}),
LineString: new Style({
stroke: new Stroke({
color: 'green',
width: 3
})
}),
Polygon: new Style({
stroke: new Stroke({
color: 'blue',
lineDash: [4],
width: 3
}),
fill: new Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
})
}
var styleFunction = function (feature) {
return styles[feature.getGeometry().getType()]
}
var allfearures = this.vectorSource.getFeatures()
for (var i = 0; i < allfearures.length; i++) {
allfearures[i].setId(allfearures[i].get('id'))
}
this.vectorLayer = new VectorLayer({
id: 'vectorlayer',
source: this.vectorSource,
style: styleFunction
})
this.vectorLayer.setZIndex(4)
this.map.addLayer(this.vectorLayer)
this.isVectorLayer = true
let this1 = this
this.selectclick = new Select({
layers: [this.vectorLayer]
})
this.selectclick.on('select', function (e) {
this1.edition = ''
this1.editionoptions = []
this1.EditionInfo = {}
this1.FeaturesId = []
var features = e.selected
if (features.length > 0) {
let that = this1
var feature = features[0]
var type = feature.getGeometry().getType()
if (that.ifsub === false) {
that.fathergeom = feature.getGeometry()
}
console.log(that.fathergeom)
var tmp = 1
if (type === 'LineString' || type === 'Point') {
that.FeaturesId.push({
value: feature.get('id'),
label: feature.get('id')
})
that.currentFeatureId = feature.get('id')
tmp = 0
}
this.getFeatures().clear()
var coordinate = e.mapBrowserEvent.coordinate
var Features = that.vectorSource.getFeaturesAtCoordinate(coordinate)
for (var i = 0; i < Features.length; i++) {
that.FeaturesId.push({
value: Features[i].get('id'),
label: Features[i].get('id')
})
if (i === 0 && tmp === 1) {
that.currentFeatureId = Features[i].get('id')
}
}
// 获取并显示要素属性(无论哪个标签页都获取)
that.getFeatureData()
}
})
this.map.addInteraction(this.selectclick)
},
drawFatherFeature () {
// 如果已存在父几何图层,先移除它
if (this.fatherFeatureLayer) {
if (this.isFatherFeatureLayer) {
this.map.removeLayer(this.fatherFeatureLayer)
}
this.fatherFeatureLayer = null
}
// 如果 fathergeom 存在,则绘制它
if (this.fathergeom) {
// 创建一个 feature 来容纳 fathergeom
const fatherFeature = new Feature({
geometry: this.fathergeom
})
// 为父几何图形创建特殊样式(红色高亮)
const fatherStyle = new Style({
image: new CircleStyle({
radius: 8,
fill: new Fill({
color: 'rgba(255, 0, 0, 0.7)'
}),
stroke: new Stroke({
color: 'rgba(255, 0, 0, 1)',
width: 3
})
}),
stroke: new Stroke({
color: 'rgba(255, 0, 0, 1)',
width: 4
}),
fill: new Fill({
color: 'rgba(255, 0, 0, 0.3)'
})
})
// 创建父几何图形的 source 和 layer
const fatherSource = new VectorSource({
features: [fatherFeature]
})
this.fatherFeatureLayer = new VectorLayer({
source: fatherSource,
style: fatherStyle
})
this.fatherFeatureLayer.setZIndex(2)
this.map.addLayer(this.fatherFeatureLayer)
this.isFatherFeatureLayer = true
}
},
handleConfirmClick () {
// 主动移除所有可能的焦点,防止下拉菜单意外弹出
if (document.activeElement) {
document.activeElement.blur()
}
// 使用 nextTick 确保 DOM 更新完成后再执行
this.$nextTick(() => {
this.getGeoJson()
})
},
handleUserSelectBlur () {
// 处理人员选择组件失焦事件,确保下拉菜单正确关闭
this.$nextTick(() => {
// 确保下拉菜单完全关闭
const userSelect = document.getElementById('sUser')
if (userSelect) {
const selectElement = userSelect.querySelector('.el-select')
if (selectElement) {
selectElement.blur()
}
}
})
},
getGeoJson () {
if (this.pageLayer) {
this.map.removeLayer(this.pageLayer)
this.map.removeInteraction(this.selectclick1)
this.pageLayer = null
this.selectclick1 = null
}
this.examInfo = {}
this.examData = []
this.dataPageNum = 1
this.activeName1 = 'first1'
this.getList = true
this.currentFeatureId = ''
this.edition = ''
this.editionoptions = []
this.EditionInfo = {}
this.fathergeom = null
if (this.task === '') {
this.$alert('请选择任务!', '提示', {
confirmButtonText: '确定'
})
return
}
if (this.table === '') {
this.$alert('请选择表!', '提示', {
confirmButtonText: '确定'
})
return
}
/*if (this.userId === '') {
this.$alert('请选择人员!', '提示', {
confirmButtonText: '确定'
})
return
}*/
if (this.ifsub === true) {
this.table = this.fathertablename
this.ifsub = false
this.iffather = true
}
this.distribute = true
this.getRange(0)
this.getList = true
this.updataList()
},
initPageLayer () {
if (this.pageLayer) {
this.map.removeLayer(this.pageLayer)
this.pageLayer = null
this.map.removeInteraction(this.selectclick1)
}
var geojsonObject = {
type: 'FeatureCollection',
features: this.dataCoordinates,
crs: {type: 'EPSG', properties: {code: '4326'}}
}
this.pageSource = new VectorSource({
features: new GeoJSON().readFeatures(geojsonObject)
})
var styles = {
Point: new Style({
image: new CircleStyle({
radius: 7,
fill: new Fill({
color: 'rgba(173,216,230)'
}),
stroke: new Stroke({
lineDash: [1, 2, 3, 4, 5, 6],
color: 'rgba(70,130,180)',
width: 2
})
}),
stroke: new Stroke({
lineDash: [1, 2, 3, 4, 5, 6],
color: 'rgba(70,130,180)',
width: 2
}),
fill: new Fill({
color: 'rgba(173,216,230)'
})
}),
LineString: new Style({
stroke: new Stroke({
color: 'green',
width: 3
})
}),
Polygon: new Style({
stroke: new Stroke({
color: 'blue',
lineDash: [4],
width: 3
}),
fill: new Fill({
color: 'rgba(0, 0, 255, 0.1)'
})
})
}
var styleFunction = function (feature) {
return styles[feature.getGeometry().getType()]
}
var allfearures = this.pageSource.getFeatures()
for (var i = 0; i < allfearures.length; i++) {
allfearures[i].setId(allfearures[i].get('id'))
}
this.pageLayer = new VectorLayer({
source: this.pageSource,
style: styleFunction
})
this.pageLayer.setZIndex(5)
this.map.addLayer(this.pageLayer)
if (this.activeName1 === 'first1') {
this.pageLayer.setVisible(false)
}
this.selectclick1 = new Select({
layers: [this.pageLayer]
})
let that = this
this.selectclick1.on('select', function (e) {
var features = e.selected
if (features.length > 0) {
var feature = features[0]
that.isExtend = false
that.currentFeatureId = feature.get('id')
this.getFeatures().clear()
}
})
this.map.addInteraction(this.selectclick1)
},
initPage () {
this.examData = []
for (var i = 0; i < this.dataInfo.length; i++) {
// var maxcount = 0;
var dataInfo1 = {}
for (var key in this.dataInfo[i]) {
if (
key !== 'mediaFileURLs' &&
key !== 'id' &&
this.dataInfo[i][key].toString().substring(0, 15) !== '/get/getPicture'
// && maxcount < 3
) {
// maxcount = maxcount + 1;
dataInfo1[key] = this.dataInfo[i][key]
}
}
this.examData.push(dataInfo1)
}
},
getEdition () {
if (this.currentFeatureId === '') {
this.$alert('请先选择数据!', '提示', {confirmButtonText: '确定'})
} else {
let that = this
that.editionoptions = []
request({
url: '/get/getDataVersion',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
polygonId: that.currentFeatureId
}
}).then(function (response) {
// 获取数据存入config
if (response.data.success === true) {
var options = response.data.data
that.edition = options[0]
that.getEditionData()
for (var i = 0; i < options.length; i++) {
that.editionoptions.push({
value: options[i],
label: options[i]
})
}
that.dialogVisible = true
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
} else if (response.data.success === false) {
that.$alert('当前数据无历史版本!')
}
})
}
},
getFeatureData () {
if (this.currentFeatureId !== '') {
let that = this
// 获取数据
request({
url: '/get/getDataById',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
polygonId: that.currentFeatureId,
requestor: 'browser'
}
}).then(function (response) {
if (response.data.success === true) {
var jsondata = response.data.data
var imagedata = []
var videodata = []
// 处理媒体文件URL
if (jsondata.mediaFileURLs && Array.isArray(jsondata.mediaFileURLs)) {
for (var i = 0; i < jsondata.mediaFileURLs.length; i++) {
var url = jsondata.mediaFileURLs[i]
if (!url) continue
// 获取文件扩展名(支持多种格式)
var urlLower = url.toLowerCase()
var ext = ''
var lastDot = urlLower.lastIndexOf('.')
if (lastDot > 0) {
ext = urlLower.substring(lastDot + 1)
}
// 图片格式jpg, jpeg, png, gif, bmp, webp
if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(ext)) {
imagedata.push(url)
}
// 视频格式avi, mp4, mov, wmv, flv, mkv, webm
else if (['avi', 'mp4', 'mov', 'wmv', 'flv', 'mkv', 'webm'].includes(ext)) {
videodata.push(url)
}
}
}
jsondata.imagedata = imagedata
jsondata.videodata = videodata
// 处理字典数组:将属性值为字典数组的字段转换为 value 值
for (var key in jsondata) {
// 排除特殊字段
if (key === 'imagedata' || key === 'videodata' || key === 'mediaFileURLs' || key === 'id') {
continue
}
var value = jsondata[key]
// 检查是否为字符串且可能是JSON格式
if (typeof value === 'string' && value.trim().startsWith('[') && value.trim().endsWith(']')) {
try {
var parsed = JSON.parse(value)
// 检查是否为数组且数组元素是对象
if (Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0] === 'object' && parsed[0] !== null) {
// 提取所有 value 值,用逗号连接
var values = parsed.map(function(item) {
// 如果 value 存在且不为空,返回 value否则返回空字符串
if (item.value !== undefined && item.value !== null && item.value !== '') {
return item.value
}
return ''
}).filter(function(v) {
return v !== ''
})
// 如果所有值都为空,设置为空字符串;否则用逗号连接
jsondata[key] = values.length > 0 ? values.join(', ') : ''
}
} catch (e) {
// 如果解析失败,保持原值
console.warn('Failed to parse dictionary array for key:', key, e)
}
}
}
that.Info = jsondata
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
}
},
getEditionData () {
if (this.edition !== '') {
let that = this
request({
url: '/get/getDataByIdAndVersion',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
polygonId: that.currentFeatureId,
version: that.edition
}
}).then(function (response) {
if (response.data.success === true) {
var jsondata = response.data.data
var imagedata = []
var videodata = []
for (var i = 0; i < jsondata.mediaFileURLs.length; i++) {
if (
jsondata.mediaFileURLs[i].substring(
jsondata.mediaFileURLs[i].length - 3
) === 'jpg'
) {
imagedata.push(jsondata.mediaFileURLs[i])
} else if (
jsondata.mediaFileURLs[i].substring(
jsondata.mediaFileURLs[i].length - 3
) === 'avi'
) {
videodata.push(jsondata.mediaFileURLs[i])
}
}
jsondata.imagedata = imagedata
jsondata.videodata = videodata
// 处理字典数组:将属性值为字典数组的字段转换为 value 值
for (var key in jsondata) {
// 排除特殊字段
if (key === 'imagedata' || key === 'videodata' || key === 'mediaFileURLs' || key === 'id') {
continue
}
var value = jsondata[key]
// 检查是否为字符串且可能是JSON格式
if (typeof value === 'string' && value.trim().startsWith('[') && value.trim().endsWith(']')) {
try {
var parsed = JSON.parse(value)
// 检查是否为数组且数组元素是对象
if (Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0] === 'object' && parsed[0] !== null) {
// 提取所有 value 值,用逗号连接
var values = parsed.map(function(item) {
// 如果 value 存在且不为空,返回 value否则返回空字符串
if (item.value !== undefined && item.value !== null && item.value !== '') {
return item.value
}
return ''
}).filter(function(v) {
return v !== ''
})
// 如果所有值都为空,设置为空字符串;否则用逗号连接
jsondata[key] = values.length > 0 ? values.join(', ') : ''
}
} catch (e) {
// 如果解析失败,保持原值
console.warn('Failed to parse dictionary array for key:', key, e)
}
}
}
that.EditionInfo = jsondata
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
}
},
Rollback () {
if (this.edition === '') {
this.$alert('请先选择历史版本!', '提示', {
confirmButtonText: '确定'
})
} else {
let that = this
request({
url: '/base/rollBackDataForVersion',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
polygonId: that.currentFeatureId,
version: that.edition
}
}).then(function (response) {
if (response.data.success === true) {
that.$alert('版本回退成功!', '提示', {
confirmButtonText: '确定'
})
that.edition = ''
that.Info = {}
that.currentFeatureId = ''
that.editionoptions = []
that.EditionInfo = {}
that.getClusters()
that.dialogVisible = false
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
}
},
passData () {
if (this.currentFeatureId === '') {
this.$alert('请先选择数据!', '提示', {confirmButtonText: '确定'})
} else {
this.$confirm('确认该数据审核通过吗?', '提示', {}).then(() => {
let that = this
// 审核通过请求
request({
url: '/base/setDataStatus',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
polygonId: that.currentFeatureId,
pass: true
}
}).then(function (response) {
if (response.data.success === true) {
that.$alert('操作成功!', '提示', {confirmButtonText: '确定'})
that.changeCurrentInfo(that.pageNumber, that.currentFeatureId)
that.updataList()
that.getList = true
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
}
})
})
}
},
deleteData () {
if (this.currentFeatureId === '') {
this.$alert('请先选择数据!', '提示', {confirmButtonText: '确定'})
} else {
this.$prompt('请输入审核未通过原因', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /\S/,
inputErrorMessage: '输入原因不可为空'
})
.then(({value}) => {
let that = this
// 审核未通过请求
request({
url: '/base/setDataStatus',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
polygonId: that.currentFeatureId,
pass: false,
reason: value
}
}).then(function (response) {
if (response.data.success === true) {
that.$message({
type: 'success',
message: '操作成功'
})
that.changeCurrentInfo(that.pageNumber, that.currentFeatureId)
that.updataList()
that.getList = true
/* that.pageChange(that.pageNumber)
that.getExamInfoById(that.currentFeatureId); */
} else if (response.data.status === '401') {
that.$alert(response.data.message)
that.$router.push({path: '/login'})
} else {
that.$message({
type: 'error',
message: '操作失败'
})
}
})
})
.catch(() => {
this.$message({
type: 'info',
message: '取消操作'
})
})
}
},
getClusterData (geojsonObject) {
var Features = new GeoJSON().readFeatures(geojsonObject)
var features = new Array(Features.length)
for (var i = 0; i < Features.length; i++) {
var geometry = Features[i].getGeometry()
var coordinates = geometry.getCoordinates()
var coordinate = []
if (coordinates[0][0]) {
if (coordinates[0][0][0]) {
coordinate = coordinates[0][0]
} else {
coordinate = coordinates[0]
}
} else {
coordinate = coordinates
}
features[i] = new Feature(new Point(coordinate))
}
var clusterSource = new VectorSource({
features: features
})
var cluster = new Cluster({
distance: 40,
source: clusterSource
})
var styleCache = {}
this.clusters = new VectorLayer({
id: 'clusterlayer',
source: cluster,
style: function (feature) {
if (feature.get('features')) {
var size = feature.get('features').length
var style = styleCache[size]
if (!style) {
style = new Style({
image: new CircleStyle({
radius: 10,
stroke: new Stroke({
color: '#fff'
}),
fill: new Fill({
color: '#3399CC'
})
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: '#fff'
})
})
})
styleCache[size] = style
}
return style
}
}
})
// 聚类图层
this.clusters.setZIndex(4)
this.map.addLayer(this.clusters)
this.isClusters = true
},
setCurrentStyle1 () {
if (this.currentFeatureId !== '') {
this.getList = false
this.getExamInfoById(this.currentFeatureId)
// 改变样式
if (this.feature) {
this.feature.setStyle(undefined)
}
this.feature = this.pageSource.getFeatureById(this.currentFeatureId)
var type = this.feature.getGeometry().getType()
if (this.isExtend) {
if (type === 'Point') {
this.map
.getView()
.setCenter(this.feature.getGeometry().getExtent())
this.map.getView().setZoom(15)
} else {
var extent = this.feature.getGeometry().getExtent()
var center = [
(extent[0] + extent[2]) / 2,
(extent[1] + extent[3]) / 2
] // 获取边界区域的中心位置
this.map.getView().setCenter(center) // 设置当前地图的显示中心位置
this.map.getView().setZoom(14)
}
}
var style = new Style({
image: new CircleStyle({
radius: 7,
fill: new Fill({
color: 'yellow'
}),
stroke: new Stroke({
color: '#37eed0',
width: 3
})
}),
fill: new Fill({
color: 'yellow'
}),
stroke: new Stroke({
color: '#37eed0',
width: 3
})
})
this.feature.setStyle(style)
} else {
if (this.feature) {
this.feature.setStyle(undefined)
this.feature = null
}
}
},
setCurrentStyle () {
if (this.currentFeatureId !== '') {
this.getFeatureData()
// 改变样式
if (this.feature) {
this.feature.setStyle(undefined)
}
this.feature = this.vectorSource.getFeatureById(this.currentFeatureId)
if (this.feature) { // 添加检查确保要素存在
var style = new Style({
image: new CircleStyle({
radius: 7,
fill: new Fill({
color: 'yellow'
}),
stroke: new Stroke({
color: '#37eed0',
width: 3
})
}),
fill: new Fill({
color: 'yellow'
}),
stroke: new Stroke({
color: '#37eed0',
width: 3
})
})
this.feature.setStyle(style)
}
} else {
if (this.feature) {
this.feature.setStyle(undefined)
this.feature = null
}
}
},
clearAll () {
this.currentFeatureId = ''
this.Info = {}
this.edition = ''
this.editionoptions = []
this.EditionInfo = {}
this.FeaturesId = []
this.fathergeom = null
// 清除父几何图形显示
if (this.fatherFeatureLayer) {
if (this.isFatherFeatureLayer) {
this.map.removeLayer(this.fatherFeatureLayer)
}
this.fatherFeatureLayer = null
this.isFatherFeatureLayer = false
}
},
getExamInfoById (id) {
var jsondata = {}
for (var k = 0; k < this.dataInfo.length; k++) {
if (this.dataInfo[k].id.toString() === id) {
jsondata = JSON.parse(JSON.stringify(this.dataInfo[k]))
break
}
}
this.examInfo = {}
var imagedata = []
var videodata = []
for (var i = 0; i < jsondata.mediaFileURLs.length; i++) {
if (
jsondata.mediaFileURLs[i].substring(
jsondata.mediaFileURLs[i].length - 3
) === 'jpg'
) {
imagedata.push(jsondata.mediaFileURLs[i])
} else if (
jsondata.mediaFileURLs[i].substring(
jsondata.mediaFileURLs[i].length - 3
) === 'avi'
) {
videodata.push(jsondata.mediaFileURLs[i])
}
}
jsondata.imagedata = imagedata
jsondata.videodata = videodata
delete jsondata.mediaFileURLs
delete jsondata.id
this.examInfo = jsondata
},
getExamInfo (i) {
this.getList = false
var jsondata = this.dataInfo[i]
this.examInfo = {}
if (this.currentFeatureId === jsondata.id.toString()) {
this.getExamInfoById(this.currentFeatureId)
} else {
this.isExtend = true
this.currentFeatureId = jsondata.id.toString()
}
},
changeCurrentInfo (num, id) {
let that = this
if (this.table !== '') {
request({
url: '/get/getDataByPageNum',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
pageNum: num,
pageSize: that.pageSize,
status: that.datastatus,
workerId: that.userId
}
}).then(function (response) {
if (response.data.data) {
that.dataInfo = response.data.data.dataInfo
that.dataCoordinates = response.data.data.dataCoordinates
that.getExamInfoById(id)
that.initPage()
that.initPageLayer()
}
})
}
},
updataList () {
this.pageNumber = 1
if (this.table !== '') {
let that = this
request({
url: '/get/getDataByPageNum',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
pageNum: 1,
pageSize: that.pageSize,
status: that.datastatus,
workerId: that.userId
}
}).then(function (response) {
if (response.data.data) {
that.dataInfo = response.data.data.dataInfo
that.dataCoordinates = response.data.data.dataCoordinates
that.dataPageNum = response.data.data.dataPageNum
that.initPage()
that.initPageLayer()
} else {
that.examData = []
that.dataInfo = []
that.dataCoordinates = null
that.dataPageNum = 0
that.map.removeLayer(that.pageLayer)
}
})
}
},
pageChange (val) {
let that = this
this.pageNumber = val
if (this.table !== '') {
request({
url: '/get/getDataByPageNum',
method: 'post',
params: {
taskId: that.task,
tableName: that.table,
pageNum: val,
pageSize: that.pageSize,
status: that.datastatus,
workerId: that.userId
}
}).then(function (response) {
if (response.data.data) {
that.dataInfo = response.data.data.dataInfo
that.dataCoordinates = response.data.data.dataCoordinates
that.initPage()
that.initPageLayer()
}
})
}
},
pageSizeChange (pageSize) {
this.pageSize = pageSize
this.pageNumber = 1
},
getSubGeoJson () {
if (!this.currentFeatureId) {
this.$alert('请先在地图上选择一个要素!', '提示', {
confirmButtonText: '确定'
})
return
}
this.selectId = this.currentFeatureId
// 保存当前状态
this.fathertablename = this.table
// 设置新的表名
if (this.table === 'roottable1') {
this.table = 't1sub1'
} else if (this.table === 'roottable3') {
this.table = 't3sub'
} else if (this.table === 'roottable4') {
this.table = 't4sub'
}
this.ifsub = true
// 清理现有图层和交互
this.clearAllLayersAndInteractions()
// 重置相关状态
this.FeaturesId = []
this.Info = {}
this.currentFeatureId = ''
// 获取子区域范围并更新数据列表
this.distribute = true
this.getRange(0)
this.updataList()
},
clearAllLayersAndInteractions () {
// 清除聚类图层
if (this.clusters) {
if (this.isClusters) {
this.map.removeLayer(this.clusters)
}
this.clusters = null
this.isClusters = false
}
// 清除矢量图层和交互
if (this.vectorLayer) {
if (this.isVectorLayer) {
this.map.removeLayer(this.vectorLayer)
this.map.removeInteraction(this.selectclick)
}
this.vectorLayer = null
this.selectclick = null
this.isVectorLayer = false
}
// 清除分页图层和交互
if (this.pageLayer) {
this.map.removeLayer(this.pageLayer)
this.map.removeInteraction(this.selectclick1)
this.pageLayer = null
this.selectclick1 = null
}
// 清除cellLayer
this.cellLayer = null
// 清除父几何图层
if (this.fatherFeatureLayer) {
if (this.isFatherFeatureLayer) {
this.map.removeLayer(this.fatherFeatureLayer)
}
this.fatherFeatureLayer = null
this.isFatherFeatureLayer = false
}
// 重置相关数据
this.FeaturesId = []
this.Info = {}
this.EditionInfo = {}
this.editionoptions = []
this.edition = ''
}
},
watch: {
currentFeatureId: {
handler () {
if (this.vectorLayer && this.activeName1 === 'first1') {
this.setCurrentStyle()
}
if (this.pageLayer && this.activeName1 === 'second1') {
this.setCurrentStyle1(1)
}
// 在"数据查看"标签页中,当选择要素时获取要素数据
if (this.activeName === 'second' && this.currentFeatureId && this.task && this.table) {
this.getFeatureData()
}
}
},
vectorSource: {
handler () {
if (this.vectorLayer) {
this.setCurrentStyle()
}
}
},
activeName1: {
handler () {
if (this.activeName1 === 'first1') {
this.clearAll()
this.getClusters()
if (this.pageLayer) {
this.pageLayer.setVisible(false)
}
} else {
this.clearAll()
if (this.clusters) {
if (this.isClusters) {
this.map.removeLayer(this.clusters)
}
this.clusters = null
}
if (this.vectorLayer) {
if (this.isVectorLayer) {
this.map.removeLayer(this.vectorLayer)
this.map.removeInteraction(this.selectclick)
}
this.vectorLayer = null
this.selectclick = null
}
this.cellLayer = null
if (this.pageLayer) {
this.pageLayer.setVisible(true)
this.map.getView().fit(this.pageLayer.getSource().getExtent())
}
}
}
},
datastatus: {
handler () {
this.updataList()
this.getList = true
}
},
table: {
handler () {
if (this.clusters) {
if (this.isClusters) {
this.map.removeLayer(this.clusters)
}
this.clusters = null
}
if (this.vectorLayer) {
if (this.isVectorLayer) {
this.map.removeLayer(this.vectorLayer)
this.map.removeInteraction(this.selectclick)
}
this.vectorLayer = null
this.selectclick = null
}
this.cellLayer = null
if (this.pageLayer) {
this.map.removeLayer(this.pageLayer)
this.map.removeInteraction(this.selectclick1)
this.pageLayer = null
this.selectclick1 = null
}
this.currentFeatureId = ''
this.Info = {}
this.edition = ''
this.editionoptions = []
this.EditionInfo = {}
this.FeaturesId = []
this.examInfo = {}
this.examData = []
this.dataPageNum = 1
this.activeName1 = 'first1'
this.getList = true
}
}
}
}
</script>
<style scoped lang='scss'>
.el-input__inner {
&::placeholder {
font-family: PingFangSC-Regular;
font-size: 14px;
color: #c0c4cc;
}
}
.ol-popup {
position: absolute;
background-color: white;
-webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
padding: 15px;
border-radius: 10px;
border: 1px solid #cccccc;
bottom: 12px;
left: -50px;
min-width: 280px;
}
.ol-popup:after,
.ol-popup:before {
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ol-popup:after {
border-top-color: white;
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before {
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
.ol-popup-closer {
text-decoration: none;
position: absolute;
top: 2px;
right: 8px;
}
.ol-popup-closer:after {
content: "✖";
}
.taskChoser {
margin: 5px 0px 5px 0px;
}
.mylabel {
display: flex;
align-items: center;
flex-wrap: wrap;
margin: 0 0 8px 0;
padding: 4px 14px;
font-family: "Microsoft YaHei", "PingFang SC", "Helvetica Neue", Arial, sans-serif;
font-size: 14px;
font-weight: 600;
color: #1B5E20;
background: rgba(232, 245, 233, 0.85);
border: 1px solid rgba(129, 199, 132, 0.4);
border-radius: 12px;
letter-spacing: 0.5px;
line-height: 1.4;
}
.mylabel .label-text {
display: inline-block;
min-width: 60px;
flex-shrink: 0;
text-align: right;
}
.mylabel ::v-deep .el-select,
.mylabel ::v-deep .el-input {
flex: 1;
min-width: 220px;
}
.el-icon-circle-close {
color: white;
}
</style>