feat: 优化地区管理地图操作
This commit is contained in:
parent
d5fe1702d2
commit
dda03a03f4
|
@ -25,7 +25,7 @@
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"global": "^4.4.0",
|
"global": "^4.4.0",
|
||||||
"jetlinks-store": "^0.0.3",
|
"jetlinks-store": "^0.0.3",
|
||||||
"jetlinks-ui-components": "^1.0.34-2",
|
"jetlinks-ui-components": "^1.0.34-3",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
|
|
|
@ -22,6 +22,8 @@ import '@vuemap/vue-amap/dist/style.css';
|
||||||
import { getAMapUiPromise } from './utils';
|
import { getAMapUiPromise } from './utils';
|
||||||
import { useSystem } from '@/store/system';
|
import { useSystem } from '@/store/system';
|
||||||
|
|
||||||
|
const emit = defineEmits('init')
|
||||||
|
|
||||||
const system = useSystem();
|
const system = useSystem();
|
||||||
interface AMapProps {
|
interface AMapProps {
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
|
@ -65,6 +67,7 @@ const initMap = (e: any) => {
|
||||||
if (isOpenUi.value) {
|
if (isOpenUi.value) {
|
||||||
getAMapUI();
|
getAMapUI();
|
||||||
}
|
}
|
||||||
|
emit('init', e)
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -4132,7 +4132,7 @@ export default [
|
||||||
sortIndex: 12,
|
sortIndex: 12,
|
||||||
url: '/system/region',
|
url: '/system/region',
|
||||||
icon: 'FormOutlined',
|
icon: 'FormOutlined',
|
||||||
showPage: ['region'],
|
showPage: ['area'],
|
||||||
permissions: [],
|
permissions: [],
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
|
@ -4140,7 +4140,7 @@ export default [
|
||||||
name: "新增",
|
name: "新增",
|
||||||
permissions: [
|
permissions: [
|
||||||
{
|
{
|
||||||
permission: "region",
|
permission: "area",
|
||||||
actions: [
|
actions: [
|
||||||
"save"
|
"save"
|
||||||
]
|
]
|
||||||
|
@ -4152,7 +4152,7 @@ export default [
|
||||||
name: "删除",
|
name: "删除",
|
||||||
permissions: [
|
permissions: [
|
||||||
{
|
{
|
||||||
permission: "region",
|
permission: "area",
|
||||||
actions: [
|
actions: [
|
||||||
"delete"
|
"delete"
|
||||||
]
|
]
|
||||||
|
@ -4164,7 +4164,7 @@ export default [
|
||||||
name: "编辑",
|
name: "编辑",
|
||||||
permissions: [
|
permissions: [
|
||||||
{
|
{
|
||||||
permission: "region",
|
permission: "area",
|
||||||
actions: [
|
actions: [
|
||||||
"save"
|
"save"
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,99 @@
|
||||||
<template>
|
<template>
|
||||||
<AMapComponent>
|
<div class="region-map">
|
||||||
|
<AMapComponent
|
||||||
|
@init="initMap"
|
||||||
|
>
|
||||||
|
<el-amap-polygon
|
||||||
|
v-if="overlay.type === 'polygon'"
|
||||||
|
:key="JSON.stringify(overlay.path || [])"
|
||||||
|
:editable="overlay.editable"
|
||||||
|
:path="overlay.path"
|
||||||
|
:visible="visible"
|
||||||
|
@addnode="polygonDraw"
|
||||||
|
@adjust="polygonDraw"
|
||||||
|
@init="overlaysInit"
|
||||||
|
@removenode="polygonDraw"
|
||||||
|
/>
|
||||||
|
<el-amap-circle
|
||||||
|
v-else-if="overlay.type === 'circle'"
|
||||||
|
:key="`${overlay.radius}_${JSON.stringify(overlay.path || [])}`"
|
||||||
|
:center="overlay.path"
|
||||||
|
:editable="overlay.editable"
|
||||||
|
:radius="overlay.radius"
|
||||||
|
:visible="visible"
|
||||||
|
@adjust="circleDraw"
|
||||||
|
@init="overlaysInit"
|
||||||
|
/>
|
||||||
|
<el-amap-rectangle
|
||||||
|
v-else-if="overlay.type === 'rectangle'"
|
||||||
|
:key="JSON.stringify(overlay.path || [])"
|
||||||
|
:bounds="overlay.path"
|
||||||
|
:editable="overlay.editable"
|
||||||
|
:visible="visible"
|
||||||
|
@adjust="rectangleDraw"
|
||||||
|
@init="overlaysInit"
|
||||||
|
/>
|
||||||
|
<el-amap-mouse-tool
|
||||||
|
v-else-if="overlay.type === 'create' && toolType"
|
||||||
|
:type="toolType"
|
||||||
|
@draw="toolDraw"
|
||||||
|
/>
|
||||||
</AMapComponent>
|
</AMapComponent>
|
||||||
|
<div v-show="overlay.editable || overlay.type === 'create'" class="map-tool">
|
||||||
|
<div class="map-tool-content">
|
||||||
|
<div class="tool-item-group">
|
||||||
|
<div class="tool-item">
|
||||||
|
<j-tooltip title="双击保存描点" >
|
||||||
|
<AIcon type="QuestionCircleOutlined" />
|
||||||
|
</j-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-item-group">
|
||||||
|
<div :class="{'tool-item': true, 'active': toolType === 'rectangle'}" @click="() => { drawOverlays('rectangle') }">
|
||||||
|
<j-tooltip title="矩形" >
|
||||||
|
<AIcon type="icon-huajuxing" />
|
||||||
|
</j-tooltip>
|
||||||
|
</div>
|
||||||
|
<div :class="{'tool-item': true, 'active': toolType === 'circle'}" @click="() => { drawOverlays('circle') }">
|
||||||
|
<j-tooltip title="圆" >
|
||||||
|
<AIcon type="icon-draw-circle" />
|
||||||
|
</j-tooltip>
|
||||||
|
</div>
|
||||||
|
<div :class="{'tool-item': true, 'active': toolType === 'polygon'}" @click="() => { drawOverlays('polygon') }">
|
||||||
|
<j-tooltip title="多边形" >
|
||||||
|
<AIcon type="icon-huaduobianxing" />
|
||||||
|
</j-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="tool-item-group">-->
|
||||||
|
<!-- <div class="tool-item">-->
|
||||||
|
<!-- <j-tooltip title="缩放" >-->
|
||||||
|
<!-- <AIcon type="GetwayOutlined" />-->
|
||||||
|
<!-- </j-tooltip>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- <div class="tool-item">-->
|
||||||
|
<!-- <j-tooltip title="旋转" >-->
|
||||||
|
<!-- <AIcon type="GetwayOutlined" />-->
|
||||||
|
<!-- </j-tooltip>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<div class="tool-item-group">
|
||||||
|
<div :class="{'tool-item': true, 'disabled': historyList.length <= 1 }" @click="cancel">
|
||||||
|
<j-tooltip title="撤销" >
|
||||||
|
<AIcon type="RollbackOutlined" />
|
||||||
|
</j-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="tool-item">
|
||||||
|
<j-tooltip title="删除" @click="deleteOverlays">
|
||||||
|
<AIcon type="DeleteOutlined" />
|
||||||
|
</j-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script name="RegionMap" setup>
|
<script name="RegionMap" setup>
|
||||||
|
@ -9,13 +101,204 @@ const props = defineProps({
|
||||||
path: {
|
path: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
}
|
},
|
||||||
|
radius: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'polygon'
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits('')
|
const emit = defineEmits('dragend')
|
||||||
|
const MapRef = ref()
|
||||||
|
const toolType = ref('')
|
||||||
|
const historyList = ref([])
|
||||||
|
|
||||||
|
const overlay = reactive({
|
||||||
|
type: props.type,
|
||||||
|
path: props.path,
|
||||||
|
center: [],
|
||||||
|
editable: false,
|
||||||
|
status: 0 // 0 预览;1 编辑
|
||||||
|
})
|
||||||
|
|
||||||
|
const visible = computed(() => {
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
const setHistory = (data) => {
|
||||||
|
if (historyList.value.length > 10) {
|
||||||
|
historyList.value.shift()
|
||||||
|
}
|
||||||
|
historyList.value.push(data)
|
||||||
|
}
|
||||||
|
const initMap = (e) => {
|
||||||
|
MapRef.value = e
|
||||||
|
}
|
||||||
|
|
||||||
|
const polygonDraw = (e) => {
|
||||||
|
|
||||||
|
const target = e.target
|
||||||
|
const path = target.getPath()
|
||||||
|
setHistory({
|
||||||
|
type: 'polygon',
|
||||||
|
toolType: toolType.value,
|
||||||
|
editable: true,
|
||||||
|
path: path.map(item => [item.lng, item.lat]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const circleDraw = (e) => {
|
||||||
|
setHistory({
|
||||||
|
type: 'circle',
|
||||||
|
toolType: toolType.value,
|
||||||
|
editable: true,
|
||||||
|
path: [e.lnglat.lng, e.lnglat.lat],
|
||||||
|
radius: e.radius
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const rectangleDraw = (e) => {
|
||||||
|
const northEast = e.bounds.getNorthEast()
|
||||||
|
const southWest = e.bounds.getSouthWest()
|
||||||
|
const path = [
|
||||||
|
[southWest.lng, southWest.lat],
|
||||||
|
[northEast.lng, northEast.lat]
|
||||||
|
]
|
||||||
|
|
||||||
|
setHistory({
|
||||||
|
type: 'rectangle',
|
||||||
|
toolType: toolType.value,
|
||||||
|
editable: true,
|
||||||
|
path: path,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const overlaysInit = (e) => {
|
||||||
|
if (MapRef.value) {
|
||||||
|
MapRef.value.setFitView(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const drawOverlays = (e) => {
|
||||||
|
overlay.type = 'create'
|
||||||
|
toolType.value = e
|
||||||
|
}
|
||||||
|
|
||||||
|
const toolDraw = (e) => {
|
||||||
|
if (toolType.value === 'circle') {
|
||||||
|
overlay.path = e.center
|
||||||
|
overlay.radius = e.radius
|
||||||
|
} else {
|
||||||
|
overlay.path = e
|
||||||
|
}
|
||||||
|
overlay.editable = true
|
||||||
|
overlay.type = toolType.value
|
||||||
|
setHistory({
|
||||||
|
type: toolType.value,
|
||||||
|
toolType: toolType.value,
|
||||||
|
editable: overlay.editable,
|
||||||
|
path: overlay.path,
|
||||||
|
radius: overlay.radius
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteOverlays = () => {
|
||||||
|
overlay.type = 'create'
|
||||||
|
overlay.editable = false
|
||||||
|
toolType.value = ''
|
||||||
|
|
||||||
|
setHistory({
|
||||||
|
type: 'create',
|
||||||
|
toolType: '',
|
||||||
|
editable: false,
|
||||||
|
path: [],
|
||||||
|
radius: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancel = () => {
|
||||||
|
if (historyList.value.length > 1) {
|
||||||
|
historyList.value.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldData = historyList.value[historyList.value.length - 1]
|
||||||
|
|
||||||
|
if (oldData) {
|
||||||
|
overlay.type = oldData.type
|
||||||
|
overlay.editable = oldData.editable
|
||||||
|
overlay.path = oldData.path
|
||||||
|
overlay.radius = oldData.radius
|
||||||
|
toolType.value = oldData.toolType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="less" scoped>
|
||||||
|
.region-map {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.map-tool{
|
||||||
|
position: absolute;
|
||||||
|
top: 20%;
|
||||||
|
right: 20px;
|
||||||
|
|
||||||
|
|
||||||
|
.map-tool-content {
|
||||||
|
display: flex;
|
||||||
|
gap: 24px;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.tool-item-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid #e3e3e3;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 0 16px rgba(#000, .15);
|
||||||
|
|
||||||
|
.tool-item {
|
||||||
|
padding: 4px 6px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:first-child) {
|
||||||
|
border-top: 1px solid #e3e3e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: var(--ant-primary-color);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
background-color: #efefef;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<LeftTree />
|
<LeftTree />
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<Map />
|
<Map :path="path" type="create" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</full-page>
|
</full-page>
|
||||||
|
@ -29,6 +29,7 @@ import FullPage from "components/Layout/FullPage.vue";
|
||||||
const searchValue = ref()
|
const searchValue = ref()
|
||||||
const visible = ref<boolean>(false)
|
const visible = ref<boolean>(false)
|
||||||
const current = ref<any>({})
|
const current = ref<any>({})
|
||||||
|
const path = ref([[121.5273285, 31.21515044], [121.5293285, 31.21515044], [121.5293285, 31.21915044], [121.5273285, 31.21515044]])
|
||||||
|
|
||||||
const onSearch = () => {
|
const onSearch = () => {
|
||||||
|
|
||||||
|
|
|
@ -3738,10 +3738,10 @@ jetlinks-store@^0.0.3:
|
||||||
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
||||||
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
||||||
|
|
||||||
jetlinks-ui-components@^1.0.34-2:
|
jetlinks-ui-components@^1.0.34-3:
|
||||||
version "1.0.34-2"
|
version "1.0.34-3"
|
||||||
resolved "https://registry.npmjs.org/jetlinks-ui-components/-/jetlinks-ui-components-1.0.34-2.tgz#8acd9f5dd4e5baa89703391620c80545c60ea98d"
|
resolved "https://registry.npmjs.org/jetlinks-ui-components/-/jetlinks-ui-components-1.0.34-3.tgz#c4f8182ce7419db40ed6d937ab0a7040bfb1549a"
|
||||||
integrity sha512-Z8/TRoJut1CuGsXXkzUYwvmKdQ1FhvXc46uK308M76Ezv4iJIGphwt1ancqVst0+WRBWoG6ps2ZsBbqCSQB7Rg==
|
integrity sha512-9jzzGOIR5ICCBdCVYfQoWyZCIFcauLuvIF+WN/djR1glC4lsBdegN06HpzxcGMfsJlWODxzjRXEq+UDNqiL4zg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/core" "^9.12.0"
|
"@vueuse/core" "^9.12.0"
|
||||||
"@vueuse/router" "^9.13.0"
|
"@vueuse/router" "^9.13.0"
|
||||||
|
|
Loading…
Reference in New Issue