|
@@ -0,0 +1,215 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <a-modal title="初始化打点 - 地图选点" :width="1300" :visible="visible" :footer="null" @cancel="handleCancel">
|
|
|
|
|
+ <div class="point-toolbar">
|
|
|
|
|
+ <span>底图:</span>
|
|
|
|
|
+ <a-select v-model="mapName" style="width: 140px" @change="handleMapChange">
|
|
|
|
|
+ <a-select-option v-for="item in mapList" :key="item.targetId" :value="item.targetId">
|
|
|
|
|
+ {{ item.targetId }}
|
|
|
|
|
+ </a-select-option>
|
|
|
|
|
+ </a-select>
|
|
|
|
|
+ <span class="ml">左上角 - 经度(%):</span>
|
|
|
|
|
+ <a-input-number v-model="x1Pct" :min="0" :max="100" :step="0.0001" style="width: 110px" placeholder="经度" />
|
|
|
|
|
+ <span class="ml">纬度(%):</span>
|
|
|
|
|
+ <a-input-number v-model="y1Pct" :min="0" :max="100" :step="0.0001" style="width: 110px" placeholder="纬度" />
|
|
|
|
|
+ <span class="ml">右下角 - 经度(%):</span>
|
|
|
|
|
+ <a-input-number v-model="x2Pct" :min="0" :max="100" :step="0.0001" style="width: 110px" placeholder="经度" />
|
|
|
|
|
+ <span class="ml">纬度(%):</span>
|
|
|
|
|
+ <a-input-number v-model="y2Pct" :min="0" :max="100" :step="0.0001" style="width: 110px" placeholder="纬度" />
|
|
|
|
|
+ <a-button class="ml" type="primary" @click="resetPoints">重置</a-button>
|
|
|
|
|
+ <a-button class="ml" type="primary" :loading="saving" @click="save">确认选点</a-button>
|
|
|
|
|
+ <span class="tip ml">第1次点击=左上角,第2次点击=右下角</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="point-map" ref="mapBox" @click="handleMapClick">
|
|
|
|
|
+ <img v-if="mapUrl" class="map-bg" :src="mapUrl" alt="">
|
|
|
|
|
+ <div v-if="hasPoint1" class="point-marker marker-1" :style="{ left: x1Pct + '%', top: y1Pct + '%' }">
|
|
|
|
|
+ <span class="marker-label">左上</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-if="hasPoint2" class="point-marker marker-2" :style="{ left: x2Pct + '%', top: y2Pct + '%' }">
|
|
|
|
|
+ <span class="marker-label">右下</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </a-modal>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+import { axios } from '@/utils/request'
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'InitPointMapSelect',
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ visible: false,
|
|
|
|
|
+ saving: false,
|
|
|
|
|
+ mapList: [],
|
|
|
|
|
+ mapName: null,
|
|
|
|
|
+ clickCount: 0,
|
|
|
|
|
+ x1Pct: null,
|
|
|
|
|
+ y1Pct: null,
|
|
|
|
|
+ x2Pct: null,
|
|
|
|
|
+ y2Pct: null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ computed: {
|
|
|
|
|
+ mapUrl() {
|
|
|
|
|
+ const current = (this.mapList || []).find(item => item.targetId === this.mapName)
|
|
|
|
|
+ return current ? current.url : ''
|
|
|
|
|
+ },
|
|
|
|
|
+ hasPoint1() {
|
|
|
|
|
+ return this.x1Pct != null && this.y1Pct != null
|
|
|
|
|
+ },
|
|
|
|
|
+ hasPoint2() {
|
|
|
|
|
+ return this.x2Pct != null && this.y2Pct != null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ base(mapName) {
|
|
|
|
|
+ this.visible = true
|
|
|
|
|
+ this.mapName = mapName || null
|
|
|
|
|
+ this.clickCount = 0
|
|
|
|
|
+ this.x1Pct = null
|
|
|
|
|
+ this.y1Pct = null
|
|
|
|
|
+ this.x2Pct = null
|
|
|
|
|
+ this.y2Pct = null
|
|
|
|
|
+ this.getMapList()
|
|
|
|
|
+ },
|
|
|
|
|
+ getMapList() {
|
|
|
|
|
+ axios.get('/upms/files', { params: { type: 56 } }).then(res => {
|
|
|
|
|
+ this.mapList = res.data || []
|
|
|
|
|
+ if (!this.mapName && this.mapList.length > 0) {
|
|
|
|
|
+ this.mapName = this.mapList[0].targetId
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ handleMapChange() {
|
|
|
|
|
+ // 切换底图时重置选点
|
|
|
|
|
+ this.resetPoints()
|
|
|
|
|
+ },
|
|
|
|
|
+ handleMapClick(e) {
|
|
|
|
|
+ const rect = this.$refs.mapBox.getBoundingClientRect()
|
|
|
|
|
+ if (!rect.width || !rect.height) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const x = ((e.clientX - rect.left) / rect.width) * 100
|
|
|
|
|
+ const y = ((e.clientY - rect.top) / rect.height) * 100
|
|
|
|
|
+ const xPct = Math.round(x * 10000) / 10000
|
|
|
|
|
+ const yPct = Math.round(y * 10000) / 10000
|
|
|
|
|
+
|
|
|
|
|
+ this.clickCount++
|
|
|
|
|
+ if (this.clickCount === 1) {
|
|
|
|
|
+ // 第1次点击 = 左上角
|
|
|
|
|
+ this.x1Pct = xPct
|
|
|
|
|
+ this.y1Pct = yPct
|
|
|
|
|
+ this.x2Pct = null
|
|
|
|
|
+ this.y2Pct = null
|
|
|
|
|
+ } else if (this.clickCount === 2) {
|
|
|
|
|
+ // 第2次点击 = 右下角
|
|
|
|
|
+ this.x2Pct = xPct
|
|
|
|
|
+ this.y2Pct = yPct
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 第3次点击重新开始
|
|
|
|
|
+ this.clickCount = 1
|
|
|
|
|
+ this.x1Pct = xPct
|
|
|
|
|
+ this.y1Pct = yPct
|
|
|
|
|
+ this.x2Pct = null
|
|
|
|
|
+ this.y2Pct = null
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ resetPoints() {
|
|
|
|
|
+ this.clickCount = 0
|
|
|
|
|
+ this.x1Pct = null
|
|
|
|
|
+ this.y1Pct = null
|
|
|
|
|
+ this.x2Pct = null
|
|
|
|
|
+ this.y2Pct = null
|
|
|
|
|
+ },
|
|
|
|
|
+ save() {
|
|
|
|
|
+ if (!this.hasPoint1 || !this.hasPoint2) {
|
|
|
|
|
+ this.$message.error('请点击地图选取左上角和右下角两个点')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.saving = true
|
|
|
|
|
+ // 百分比转小数(0-1),保留6位小数
|
|
|
|
|
+ const data = {
|
|
|
|
|
+ x1: Math.round((this.x1Pct / 100) * 1000000) / 1000000,
|
|
|
|
|
+ y1: Math.round((this.y1Pct / 100) * 1000000) / 1000000,
|
|
|
|
|
+ x2: Math.round((this.x2Pct / 100) * 1000000) / 1000000,
|
|
|
|
|
+ y2: Math.round((this.y2Pct / 100) * 1000000) / 1000000
|
|
|
|
|
+ }
|
|
|
|
|
+ this.saving = false
|
|
|
|
|
+ this.$emit('ok', data)
|
|
|
|
|
+ this.visible = false
|
|
|
|
|
+ },
|
|
|
|
|
+ handleCancel() {
|
|
|
|
|
+ this.visible = false
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
|
+.point-toolbar {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+
|
|
|
|
|
+ .ml {
|
|
|
|
|
+ margin-left: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .tip {
|
|
|
|
|
+ color: #999;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.point-map {
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ height: 620px;
|
|
|
|
|
+ border: 1px solid #e8e8e8;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ cursor: crosshair;
|
|
|
|
|
+
|
|
|
|
|
+ .map-bg {
|
|
|
|
|
+ display: block;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .point-marker {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ width: 16px;
|
|
|
|
|
+ height: 16px;
|
|
|
|
|
+ margin: -8px 0 0 -8px;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ z-index: 10;
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+
|
|
|
|
|
+ .marker-label {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ top: -20px;
|
|
|
|
|
+ left: 50%;
|
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.7);
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ padding: 2px 6px;
|
|
|
|
|
+ border-radius: 3px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.marker-1 {
|
|
|
|
|
+ background: #ff4d4f;
|
|
|
|
|
+ box-shadow: 0 0 8px #ff4d4f;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &.marker-2 {
|
|
|
|
|
+ background: #52c41a;
|
|
|
|
|
+ box-shadow: 0 0 8px #52c41a;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|