Files
school-developer/src/views/recruit/recruitstudentsignup/dormFW.vue
zhoutianchi 7640282a93 1
2026-01-26 14:27:04 +08:00

278 lines
8.5 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>
<el-dialog
title="请设置住宿范围"
append-to-body
:close-on-click-modal="false"
v-model="visible"
width="90%">
<div>
<el-form :model="form" :rules="rules" ref="formRef" class="demo-ruleForm">
<el-form-item label="住宿半径(米)" prop="raidus">
<el-input-number v-model="form.raidus" :min="0" style="width: 100%"></el-input-number>
</el-form-item>
</el-form>
<div id="container"></div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataFormSubmit">确定</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive, watch, nextTick } from 'vue'
import { useMessage, useMessageBox } from '/@/hooks/message'
import { loadTiandituMap } from "/@/api/recruit/recruitstudentsignup"
import { editDormrange } from "/@/api/admin/dict"
import { getDicts } from "/@/api/admin/dict"
import { TIANDITU_TOKEN } from '/@/config/map'
// 消息提示 hooks
const message = useMessage()
const messageBox = useMessageBox()
// 表单引用
const formRef = ref()
// 响应式数据
const tk = TIANDITU_TOKEN // 天地图的token在 src/config/map.ts 中配置)
const visible = ref(false)
const canSubmit = ref(false)
const circleShow = ref(false)
const circle = ref<any>(null)
const map = ref<any>(null)
// 地址信息
const center = reactive({ lng: 0, lat: 0 })
const dictId = ref("")
const form = reactive({
raidus: 0,
})
const rules = {
raidus: [
{ required: true, message: '住宿半径不能为空', trigger: ["blur", "change"] }
],
}
// 监听半径变化
watch(() => form.raidus, (newVal) => {
if (newVal !== 0 && newVal !== undefined && circle.value && map.value) {
// 移除旧圆形
map.value.removeOverLay(circle.value)
// 创建新圆形(确保数据类型正确)
// @ts-ignore
const newCircle = new window.T.Circle(
// @ts-ignore
new window.T.LngLat(
// @ts-ignore
parseFloat(center.lng),
// @ts-ignore
parseFloat(center.lat)
),
// @ts-ignore
parseFloat(newVal), // 确保半径是数字类型
{
color: '#FF0000', // 边框颜色:鲜红色
weight: 4, // 边框粗细4像素
opacity: 0.9, // 边框不透明度90%
fillColor: '#FF4444', // 填充颜色:亮红色
fillOpacity: 0.12 // 填充透明度12%
}
)
map.value.addOverLay(newCircle)
circle.value = newCircle
// 让新圆形也不拦截鼠标事件
setTimeout(() => {
const circleElements = document.querySelectorAll('.tdt-circle, [class*="circle"]')
circleElements.forEach((el: any) => {
el.style.pointerEvents = 'none'
})
}, 100)
}
})
// 初始化
const init = () => {
visible.value = true
canSubmit.value = true
circleShow.value = true
nextTick(() => {
getDicts("dorm_jw").then((data: any) => {
const arr = data.data
arr.forEach((e: any) => {
if (e.label == 'bj') {
form.raidus = e.value
dictId.value = e.id
} else if (e.label == 'lng') {
center.lng = e.value
} else if (e.label == 'lat') {
center.lat = e.value
}
})
// 等待对话框渲染完成后再加载地图
setTimeout(() => {
// 调试信息:打印配置数据
// eslint-disable-next-line no-console
console.log('地图配置:', { lng: center.lng, lat: center.lat, radius: form.raidus, token: tk })
loadTiandituMap(tk).then((T: any) => {
// eslint-disable-next-line no-console
console.log('天地图API加载成功', T)
// 清除之前的地图实例(如果存在)
if (map.value) {
map.value.clearOverLays()
}
// 创建地图实例
map.value = new T.Map("container")
// 创建点坐标(确保经纬度是数字类型)
// @ts-ignore
const point = new T.LngLat(
// @ts-ignore
parseFloat(center.lng),
// @ts-ignore
parseFloat(center.lat)
)
// 根据半径自动计算合适的缩放级别
// @ts-ignore
const radius = parseFloat(form.raidus)
let zoomLevel = 12 // 默认缩放级别
// 根据半径动态调整缩放级别
if (radius <= 1000) {
zoomLevel = 15 // 1公里以内 - 非常近
} else if (radius <= 3000) {
zoomLevel = 14 // 3公里以内 - 近距离
} else if (radius <= 5000) {
zoomLevel = 13 // 5公里以内 - 中等距离
} else if (radius <= 10000) {
zoomLevel = 12 // 10公里以内 - 较远
} else if (radius <= 20000) {
zoomLevel = 11 // 20公里以内 - 远距离
} else {
zoomLevel = 10 // 20公里以上 - 超远距离
}
// 初始化地图,设置中心点坐标和地图级别
map.value.centerAndZoom(point, zoomLevel)
// eslint-disable-next-line no-console
console.log('地图缩放级别:', zoomLevel, '(半径:', radius, '米)')
// 添加地图类型切换控件(让用户可以切换卫星图/普通图)
const ctrl = new T.Control.MapType()
map.value.addControl(ctrl)
// 默认使用矢量地图(普通地图),用户可通过右上角控件切换到卫星图
// 绘制圆形覆盖物(使用前面已计算好的 radius 变量)
// eslint-disable-next-line no-console
console.log('绘制圆形:', { center: point, radius: radius, radiusType: typeof radius })
circle.value = new T.Circle(point, radius, {
color: '#FF0000', // 边框颜色:鲜红色,更醒目
weight: 4, // 边框粗细4像素更明显
opacity: 0.9, // 边框不透明度90%,清晰可见
fillColor: '#FF4444', // 填充颜色:亮红色
fillOpacity: 0.12 // 填充透明度12%,轻盈不遮挡地图
})
map.value.addOverLay(circle.value)
// 让圆形不拦截鼠标事件,使地图可以在圆圈内拖拽
// 通过 CSS 设置 pointer-events 为 none
setTimeout(() => {
const circleElements = document.querySelectorAll('.tdt-circle, [class*="circle"]')
circleElements.forEach((el: any) => {
el.style.pointerEvents = 'none'
})
}, 100)
// 添加中心点标记(更明显地标识中心位置)
const marker = new T.Marker(point)
map.value.addOverLay(marker)
// eslint-disable-next-line no-console
console.log('地图初始化完成 - 圆形已添加')
}).catch((error: any) => {
// eslint-disable-next-line no-console
console.error('天地图加载失败:', error)
message.error('地图加载失败请检查网络连接或Token配置')
})
}, 200)
}).catch(() => {
message.error('获取地图配置失败')
})
})
}
// 表单提交
const dataFormSubmit = async () => {
try {
await messageBox.confirm('是否确认保存住宿半径')
formRef.value?.validate((valid: boolean) => {
if (valid) {
canSubmit.value = false
editDormrange({ id: dictId.value, value: form.raidus }).then(() => {
message.success('修改成功')
visible.value = false
canSubmit.value = true
}).catch(() => {
canSubmit.value = true
})
}
})
} catch {
// 用户取消
}
}
// 暴露方法给父组件
defineExpose({
init
})
</script>
<style scoped>
#container {
overflow: hidden;
width: 100%;
height: 700px;
margin: 0;
font-family: "微软雅黑";
margin-top: 15px;
}
ul li {
list-style: none;
}
.dialog-footer {
text-align: right;
}
</style>
<style>
/* 让地图上的圆形覆盖物不拦截鼠标事件,使地图可以拖拽 */
#container svg path[fill*="#FF"],
#container svg path[stroke*="#FF"],
#container svg circle,
#container canvas {
pointer-events: none !important;
}
/* 但保持标记点可点击 */
#container .tdt-marker,
#container img {
pointer-events: auto !important;
}
</style>