This commit is contained in:
guochunsi
2026-01-19 18:01:21 +08:00
parent 083d9d5c13
commit 0063894c8e
8 changed files with 373 additions and 96 deletions

View File

@@ -458,6 +458,7 @@ export const batchPushAll = (obj: any) => {
*/ */
export const BMPGL = (ak: string) => { export const BMPGL = (ak: string) => {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
// @ts-ignore
window.init = function () { window.init = function () {
// eslint-disable-next-line // eslint-disable-next-line
// resolve(BMapGL); // resolve(BMapGL);
@@ -470,6 +471,45 @@ export const BMPGL = (ak: string) => {
}); });
}; };
/**
* 天地图
* @param tk 天地图token
*/
export const loadTiandituMap = (tk: string) => {
return new Promise(function (resolve, reject) {
// @ts-ignore
// 如果天地图API已经加载直接返回
if (window.T) {
// @ts-ignore
resolve(window.T);
return;
}
// 检查是否已经有加载中的脚本
const existingScript = document.querySelector('script[src*="api.tianditu.gov.cn"]');
if (existingScript) {
// 如果脚本正在加载中,等待加载完成
existingScript.addEventListener('load', () => {
// @ts-ignore
resolve(window.T);
});
existingScript.addEventListener('error', reject);
return;
}
// 加载天地图主库
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = `https://api.tianditu.gov.cn/api?v=4.0&tk=${tk}`;
script.onload = () => {
// @ts-ignore
resolve(window.T);
};
script.onerror = reject;
document.head.appendChild(script);
});
};
/** /**
* 宿舍申请分析 * 宿舍申请分析
* @param obj * @param obj

40
src/config/map.ts Normal file
View File

@@ -0,0 +1,40 @@
/**
* 地图配置文件
* 统一管理地图相关的配置信息
*/
/**
* 天地图Token
* 请到天地图开放平台申请https://console.tianditu.gov.cn/
* 申请后请将下方的token替换为您自己的token
*/
export const TIANDITU_TOKEN = 'd584b11f3c0d801105df2f415a2d3530'
/**
* 地理编码服务配置
* 使用OpenStreetMap Nominatim服务完全免费
*/
export const GEOCODING_SERVICE = 'nominatim' // 使用Nominatim服务
/**
* 天地图API版本
*/
export const TIANDITU_API_VERSION = '4.0'
/**
* 天地图地理编码服务地址
*/
export const TIANDITU_GEOCODE_URL = 'https://api.tianditu.gov.cn/geocoder'
/**
* 默认地图中心点(可根据实际情况修改)
*/
export const DEFAULT_MAP_CENTER = {
lng: 116.397428,
lat: 39.90923
}
/**
* 默认地图缩放级别
*/
export const DEFAULT_MAP_ZOOM = 13

View File

@@ -590,7 +590,7 @@
<template #footer v-if="type==1"> <template #footer v-if="type==1">
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="visible = false">取消</el-button> <el-button @click="visible = false">取消</el-button>
<el-button type="success" @click="dataFormSubmit(20)" v-if="canSubmit">确认录取</el-button> <el-button type="primary" @click="dataFormSubmit(20)" v-if="canSubmit">确认录取</el-button>
<el-button type="danger" plain @click="dataFormSubmit(-20)" v-if="canSubmit">驳回录取</el-button> <el-button type="danger" plain @click="dataFormSubmit(-20)" v-if="canSubmit">驳回录取</el-button>
</div> </div>
</template> </template>
@@ -612,7 +612,7 @@ import { list as listByGroupId } from '/@/api/recruit/recruitstudentschool'
import { getDeptList } from "/@/api/basic/basicclass" import { getDeptList } from "/@/api/basic/basicclass"
import { getList } from "/@/api/recruit/recruitstudentplangroup" import { getList } from "/@/api/recruit/recruitstudentplangroup"
import { listByEdu } from "/@/api/recruit/recruitstudentplan" import { listByEdu } from "/@/api/recruit/recruitstudentplan"
import { getDictsByTypes } from "/@/api/admin/dict" import { getDicts, getDictsByTypes } from "/@/api/admin/dict"
import { useDict } from '/@/hooks/dict' import { useDict } from '/@/hooks/dict'
import { areaList, areaSonList } from "/@/api/recruit/recruitstudentschool" import { areaList, areaSonList } from "/@/api/recruit/recruitstudentschool"
import { list as scoreList } from "/@/api/recruit/recruitstudentplancorrectscoreconfig" import { list as scoreList } from "/@/api/recruit/recruitstudentplancorrectscoreconfig"
@@ -832,6 +832,9 @@ const init = (id: string | null, typeParam: number) => {
isShow.value = true isShow.value = true
nextTick(() => { nextTick(() => {
dataFormRef.value?.resetFields() dataFormRef.value?.resetFields()
getDicts('finance_student_source').then((res: any) => {
eduList.value = res.data || []
})
if (dataForm.id) { if (dataForm.id) {
areaPList.value = [] areaPList.value = []
areaCList.value = [] areaCList.value = []

View File

@@ -4,22 +4,19 @@
append-to-body append-to-body
:close-on-click-modal="false" :close-on-click-modal="false"
v-model="visible" v-model="visible"
width="800"> width="90%">
<div> <div>
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" <el-form :model="form" :rules="rules" ref="formRef" class="demo-ruleForm">
class="demo-ruleForm">
<el-form-item label="住宿半径(米)" prop="raidus"> <el-form-item label="住宿半径(米)" prop="raidus">
<el-input-number v-model="form.raidus" :min="0" style="width: 100%"></el-input-number> <el-input-number v-model="form.raidus" :min="0" style="width: 100%"></el-input-number>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div id="container"></div> <div id="container"></div>
</div> </div>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button type="primary" @click="dataFormSubmit">确定</el-button>
<el-button @click="visible = false">取消</el-button> <el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataFormSubmit">确定</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@@ -28,9 +25,10 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, watch, nextTick } from 'vue' import { ref, reactive, watch, nextTick } from 'vue'
import { useMessage, useMessageBox } from '/@/hooks/message' import { useMessage, useMessageBox } from '/@/hooks/message'
import { BMPGL } from "@/api/recruit/recruitstudentsignup" import { loadTiandituMap } from "/@/api/recruit/recruitstudentsignup"
import { putItemObj } from "@/api/admin/dict" import { putItemObj } from "/@/api/admin/dict"
import { getTypeValue } from "@/api/admin/dict" import { getDicts } from "/@/api/admin/dict"
import { TIANDITU_TOKEN } from '/@/config/map'
// 消息提示 hooks // 消息提示 hooks
const message = useMessage() const message = useMessage()
@@ -40,17 +38,16 @@ const messageBox = useMessageBox()
const formRef = ref() const formRef = ref()
// 响应式数据 // 响应式数据
const ak = "V0ooaf2RZyEGOkD8UzZB3gvw7pCb0Kx7" // 百度的地图密钥 const tk = TIANDITU_TOKEN // 天地图的token在 src/config/map.ts 中配置)
const visible = ref(false) const visible = ref(false)
const canSubmit = ref(false) const canSubmit = ref(false)
const circleShow = ref(false) const circleShow = ref(false)
const circle = ref<any>(null) const circle = ref<any>(null)
const map = ref<any>(null)
// 地址信息 // 地址信息
const address = ref(null)
const center = reactive({ lng: 0, lat: 0 }) const center = reactive({ lng: 0, lat: 0 })
const dictId = ref("") const dictId = ref("")
const circleArr = ref<any[]>([])
const form = reactive({ const form = reactive({
raidus: 0, raidus: 0,
@@ -64,8 +61,39 @@ const rules = {
// 监听半径变化 // 监听半径变化
watch(() => form.raidus, (newVal) => { watch(() => form.raidus, (newVal) => {
if (newVal != '' && newVal != undefined && circle.value) { if (newVal !== 0 && newVal !== undefined && circle.value && map.value) {
circle.value.setRadius(newVal) // 设置圆形覆盖物的半径 // 移除旧圆形
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)
} }
}) })
@@ -75,7 +103,7 @@ const init = () => {
canSubmit.value = true canSubmit.value = true
circleShow.value = true circleShow.value = true
nextTick(() => { nextTick(() => {
getTypeValue("dorm_jw").then((data: any) => { getDicts("dorm_jw").then((data: any) => {
const arr = data.data const arr = data.data
arr.forEach((e: any) => { arr.forEach((e: any) => {
if (e.label == 'bj') { if (e.label == 'bj') {
@@ -87,25 +115,101 @@ const init = () => {
center.lat = e.value center.lat = e.value
} }
}) })
BMPGL(ak).then((BMapGL: any) => {
// 创建地图实例 // 等待对话框渲染完成后再加载地图
const map = new BMapGL.Map("container") setTimeout(() => {
// 创建点坐标 // 调试信息:打印配置数据
const point = new BMapGL.Point(center.lng, center.lat) // eslint-disable-next-line no-console
// 初始化地图,设置中心点坐标和地图级别 console.log('地图配置:', { lng: center.lng, lat: center.lat, radius: form.raidus, token: tk })
map.centerAndZoom(point, 13)
// 开启鼠标滚轮缩放 loadTiandituMap(tk).then((T: any) => {
map.enableScrollWheelZoom(true) // eslint-disable-next-line no-console
console.log('天地图API加载成功', T)
// 绘制圆
circle.value = new BMapGL.Circle(new BMapGL.Point(center.lng, center.lat), form.raidus, { // 清除之前的地图实例(如果存在)
strokeColor: 'blue', if (map.value) {
strokeWeight: 2, map.value.clearOverLays()
strokeOpacity: 0.5, }
enableEditing: false
// 创建地图实例
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配置')
}) })
map.addOverlay(circle.value) }, 200)
}) }).catch(() => {
message.error('获取地图配置失败')
}) })
}) })
} }
@@ -141,9 +245,10 @@ defineExpose({
#container { #container {
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
height: 500px; height: 700px;
margin: 0; margin: 0;
font-family: "微软雅黑"; font-family: "微软雅黑";
margin-top: 15px;
} }
ul li { ul li {
@@ -154,3 +259,19 @@ ul li {
text-align: right; text-align: right;
} }
</style> </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>

View File

@@ -290,14 +290,14 @@
icon="Download" icon="Download"
@click="handleExport()">名单导出 @click="handleExport()">名单导出
</el-button> </el-button>
<el-button <!-- <el-button
class="ml10" class="ml10"
type="primary" type="primary"
plain plain
icon="UploadFilled" icon="UploadFilled"
v-auth="'recruit_send_img'" v-auth="'recruit_send_img'"
@click="handleSendImg()">图片同步 @click="handleSendImg()">图片同步
</el-button> </el-button> -->
</div> </div>
</el-row> </el-row>
@@ -347,7 +347,7 @@
prop="name" prop="name"
header-align="center" header-align="center"
align="left" align="left"
min-width="250" width="290"
label="资料检测"> label="资料检测">
<template #default="scope"> <template #default="scope">
<div v-if="scope.row.isOut=='0'" class="material-check-cell"> <div v-if="scope.row.isOut=='0'" class="material-check-cell">

View File

@@ -126,7 +126,7 @@
<el-table-column prop="name" label="姓名" width="100" align="center" show-overflow-tooltip /> <el-table-column prop="name" label="姓名" width="100" align="center" show-overflow-tooltip />
<el-table-column prop="gender" label="性别" width="80" align="center" show-overflow-tooltip> <el-table-column prop="gender" label="性别" width="80" align="center" show-overflow-tooltip>
<template #default="scope"> <template #default="scope">
{{ getLabelValue(sexy, scope.row.gender) }} <GenderTag :sex="scope.row.gender" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="idNumber" label="身份证号" width="180" align="center" show-overflow-tooltip /> <el-table-column prop="idNumber" label="身份证号" width="180" align="center" show-overflow-tooltip />
@@ -159,7 +159,7 @@
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '1'" v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '1'"
type="success" type="primary"
link link
icon="CircleCheck" icon="CircleCheck"
@click="setFw(scope.row, 1)" @click="setFw(scope.row, 1)"
@@ -168,7 +168,7 @@
</el-button> </el-button>
<el-button <el-button
v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '2'" v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '2'"
type="warning" type="primary"
link link
icon="Close" icon="Close"
@click="setFw(scope.row, 2)" @click="setFw(scope.row, 2)"
@@ -220,6 +220,8 @@ import { getList } from '/@/api/recruit/recruitstudentplangroup'
import { fetchListStuDorm, yjOut as yjOutApi, setFw as setFwApi, delFw, yjSend as yjSendApi } from '/@/api/recruit/recruitstudentsignup' import { fetchListStuDorm, yjOut as yjOutApi, setFw as setFwApi, delFw, yjSend as yjSendApi } from '/@/api/recruit/recruitstudentsignup'
import { getDeptList } from '/@/api/basic/basicclass' import { getDeptList } from '/@/api/basic/basicclass'
const GenderTag = defineAsyncComponent(() => import('/@/components/GenderTag/index.vue'))
const DormFW = defineAsyncComponent(() => import('./dormFW.vue')) const DormFW = defineAsyncComponent(() => import('./dormFW.vue'))
const ShowMap = defineAsyncComponent(() => import('./showMap.vue')) const ShowMap = defineAsyncComponent(() => import('./showMap.vue'))

View File

@@ -4,14 +4,14 @@
:close-on-click-modal="false" :close-on-click-modal="false"
v-model="visible" v-model="visible"
append-to-body append-to-body
width="90%"> width="600">
<el-form :model="dataForm" :rules="dataRule" ref="dataFormRef" @keyup.enter="dataFormSubmit" <el-form :model="dataForm" :rules="dataRule" ref="dataFormRef" @keyup.enter="dataFormSubmit"
label-width="170px" size="small"> label-width="120px">
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="招生计划" prop="groupId"> <el-form-item label="招生计划" prop="groupId">
<el-select v-model="dataForm.groupId" filterable :disabled="!!dataForm.id" <el-select v-model="dataForm.groupId" filterable :disabled="!!dataForm.id"
placeholder="请选择招生计划" size="small" style="width: 100%"> placeholder="请选择招生计划">
<el-option <el-option
v-for="item in planList" v-for="item in planList"
:key="item.id" :key="item.id"
@@ -39,14 +39,14 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="成绩折算分" prop="correctedScore"> <el-form-item label="成绩折算分" prop="correctedScore">
<el-input-number v-model="dataForm.correctedScore" controls-position="right" :min="0" :max="999" :step-strictly="true" style="width: 100%;"></el-input-number> <el-input-number v-model="dataForm.correctedScore" controls-position="right" :min="0" :max="999" :step-strictly="true"></el-input-number>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="原录取专业" prop="confirmedMajor"> <el-form-item label="原录取专业" prop="confirmedMajor">
<el-select v-model="dataForm.confirmedMajor" filterable clearable placeholder="" size="small" style="width: 100%" :disabled="type != 1" @change="changeM(dataForm.confirmedMajor)"> <el-select v-model="dataForm.confirmedMajor" filterable clearable placeholder="" :disabled="type != 1" @change="changeM(dataForm.confirmedMajor)">
<el-option <el-option
v-for="item in planMajorList" v-for="item in planMajorList"
:key="item.majorCode" :key="item.majorCode"
@@ -60,7 +60,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="新录取专业" prop="newConfirmedMajor"> <el-form-item label="新录取专业" prop="newConfirmedMajor">
<el-select v-model="dataForm.newConfirmedMajor" filterable placeholder="" size="small" style="width: 100%" @change="changeCM(dataForm.newConfirmedMajor)"> <el-select v-model="dataForm.newConfirmedMajor" filterable placeholder="" @change="changeCM(dataForm.newConfirmedMajor)">
<el-option <el-option
v-for="item in planMajorList" v-for="item in planMajorList"
:key="item.majorCode" :key="item.majorCode"
@@ -73,23 +73,24 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="6"> <el-col :span="12">
<el-form-item label="学费" prop="feeTuition"> <el-form-item label="学费" prop="feeTuition">
<el-input-number v-model="dataForm.feeTuition" controls-position="right" :min="0" :max="999999" :step-strictly="true" style="width:100%;" :disabled="type == 2"></el-input-number> <el-input-number v-model="dataForm.feeTuition" controls-position="right" :min="0" :max="999999" :step-strictly="true" :disabled="type == 2"></el-input-number>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="12">
<el-form-item label="代办费" prop="feeAgency"> <el-form-item label="代办费" prop="feeAgency">
<el-input-number v-model="dataForm.feeAgency" controls-position="right" :min="0" :max="999999" :step-strictly="true" style="width:100%;" :disabled="type == 2"></el-input-number> <el-input-number v-model="dataForm.feeAgency" controls-position="right" :min="0" :max="999999" :step-strictly="true" :disabled="type == 2"></el-input-number>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="6"> </el-row>
<el-row>
<el-col :span="24">
<el-form-item label="总费用" prop="allMoney"> <el-form-item label="总费用" prop="allMoney">
<span style="color: red">{{ dataForm.feeTuition + dataForm.feeAgency }}</span> <span style="color: red">{{ dataForm.feeTuition + dataForm.feeAgency }}</span>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-form-item label="审核备注" prop="auditRemarks"> <el-form-item label="审核备注" prop="auditRemarks">
@@ -101,7 +102,7 @@
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="visible = false">取消</el-button> <el-button @click="visible = false">取消</el-button>
<el-button type="success" @click="dataFormSubmit" v-if="canSubmit">确认修改</el-button> <el-button type="primary" @click="dataFormSubmit" v-if="canSubmit">确认修改</el-button>
</div> </div>
</template> </template>
</el-dialog> </el-dialog>
@@ -380,7 +381,12 @@ defineExpose({
}) })
</script> </script>
<style scoped> <style lang="scss" scoped>
.el-form {
.el-row:not(:last-of-type) {
margin-bottom: 18px !important;
}
}
.dialog-footer { .dialog-footer {
text-align: right; text-align: right;
} }

View File

@@ -1,19 +1,14 @@
<template> <template>
<el-dialog <el-dialog
title="家庭地址地图选点" title="家庭地址地图查看"
append-to-body append-to-body
:close-on-click-modal="false" :close-on-click-modal="false"
v-model="visible" v-model="visible"
width="90%"> width="90%">
<div style="height: 100%;width:100%"> <div style="height: 100%;width:100%">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" <el-descriptions :column="1" border>
class="demo-ruleForm"> <el-descriptions-item label="家庭地址">{{ form.homeAddressDetail }}</el-descriptions-item>
</el-descriptions>
<el-form-item label="家庭地址" prop="homeAddressDetail">
<el-input v-model="form.homeAddressDetail" style="width: 100%"></el-input>
</el-form-item>
</el-form>
<div id="container2"></div> <div id="container2"></div>
</div> </div>
</el-dialog> </el-dialog>
@@ -21,36 +16,34 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, nextTick } from 'vue' import { ref, reactive, nextTick } from 'vue'
import { BMPGL } from "@/api/recruit/recruitstudentsignup" import { loadTiandituMap } from "/@/api/recruit/recruitstudentsignup"
import { getTypeValue } from "@/api/admin/dict" import { getDicts } from "/@/api/admin/dict"
import { ElMessage } from 'element-plus'
import { TIANDITU_TOKEN } from '/@/config/map'
// 表单引用 // 表单引用
const formRef = ref() const formRef = ref()
// 响应式数据 // 响应式数据
const ak = "V0ooaf2RZyEGOkD8UzZB3gvw7pCb0Kx7" // 百度的地图密钥 const tk = TIANDITU_TOKEN // 天地图的token在 src/config/map.ts 中配置)
const visible = ref(false) const visible = ref(false)
const canSubmit = ref(false) const canSubmit = ref(false)
const circleShow = ref(false) const circleShow = ref(false)
const circle = ref<any>(null) const circle = ref<any>(null)
const map = ref<any>(null)
// 地址信息 // 地址信息
const address = ref(null)
const center = reactive({ lng: 0, lat: 0 }) const center = reactive({ lng: 0, lat: 0 })
const dictId = ref("") const dictId = ref("")
const circleArr = ref<any[]>([])
const form = reactive({ const form = reactive({
id: "", id: "",
homeAddressDetail: "", homeAddressDetail: "",
homeLng: 0, // 家庭地址经度
homeLat: 0, // 家庭地址纬度
raidus: 0 raidus: 0
}) })
const rules = {
homeAddressDetail: [
{ required: true, message: '家庭地址不能为空', trigger: ["blur", "change"] }
],
}
// 初始化 // 初始化
const init = (row: any) => { const init = (row: any) => {
@@ -59,8 +52,11 @@ const init = (row: any) => {
circleShow.value = true circleShow.value = true
form.id = row.id form.id = row.id
form.homeAddressDetail = row.homeAddressDetail form.homeAddressDetail = row.homeAddressDetail
// 获取家庭地址的经纬度(如果有的话)
form.homeLng = row.homeLng || row.homeLongitude || 0
form.homeLat = row.homeLat || row.homeLatitude || 0
nextTick(() => { nextTick(() => {
getTypeValue("dorm_jw").then((data: any) => { getDicts("dorm_jw").then((data: any) => {
const arr = data.data const arr = data.data
arr.forEach((e: any) => { arr.forEach((e: any) => {
if (e.label == 'bj') { if (e.label == 'bj') {
@@ -72,26 +68,94 @@ const init = (row: any) => {
center.lat = e.value center.lat = e.value
} }
}) })
BMPGL(ak).then((BMapGL: any) => {
// 创建地图实例 // 等待对话框渲染完成后再加载地图
const map = new BMapGL.Map("container2") setTimeout(() => {
// 创建点坐标 loadTiandituMap(tk).then((T: any) => {
const point = new BMapGL.Point(center.lng, center.lat) // 清除之前的地图实例(如果存在)
// 初始化地图,设置中心点坐标和地图级别 if (map.value) {
map.centerAndZoom(point, 13) map.value.clearOverLays()
// 开启鼠标滚轮缩放
map.enableScrollWheelZoom(true)
// 创建地址解析器实例
const myGeo = new BMapGL.Geocoder()
myGeo.getPoint(form.homeAddressDetail, function (point: any) {
if (point) {
map.centerAndZoom(point, 16)
map.addOverlay(new BMapGL.Marker(point, { title: form.homeAddressDetail }))
} else {
alert('您选择的地址没有解析到结果!')
} }
}, '北京市')
}) // 创建地图实例
map.value = new T.Map("container2")
// 创建点坐标
const point = new T.LngLat(center.lng, center.lat)
// 初始化地图,设置中心点坐标和地图级别(使用默认矢量地图)
map.value.centerAndZoom(point, 13)
// 启用地图交互功能
map.value.enableDrag() // 启用拖拽
map.value.enableScrollWheelZoom() // 启用滚轮缩放
map.value.enableDoubleClickZoom() // 启用双击放大
map.value.enableKeyboard() // 启用键盘操作
// 使用天地图JavaScript API的Geocoder进行地址解析
if (form.homeAddressDetail) {
// eslint-disable-next-line no-console
console.log('开始地理编码,地址:', form.homeAddressDetail)
// 创建地理编码对象
const geocoder = new T.Geocoder()
// 进行地址解析
geocoder.getPoint(form.homeAddressDetail, (result: any) => {
if (result && result.getStatus() === 0) {
// 解析成功
const location = result.getLocationPoint()
// eslint-disable-next-line no-console
console.log('地理编码成功:', { lng: location.lng, lat: location.lat })
// 将地图中心移动到该位置
map.value.centerAndZoom(location, 15)
// 添加标记
const marker = new T.Marker(location)
map.value.addOverLay(marker)
// 添加信息窗口
const infoWin = new T.InfoWindow()
infoWin.setContent(`<div style="padding:12px;max-width:300px;">
<div style="font-size:14px;font-weight:bold;margin-bottom:8px;">📍 家庭地址</div>
<div style="color:#666;margin-bottom:6px;">${form.homeAddressDetail}</div>
<div style="font-size:12px;color:#999;padding-top:6px;border-top:1px solid #eee;">
坐标: ${location.lng.toFixed(6)}, ${location.lat.toFixed(6)}
</div>
</div>`)
marker.addEventListener('click', function () {
marker.openInfoWindow(infoWin)
})
// 自动打开信息窗口
marker.openInfoWindow(infoWin)
} else {
// 解析失败,显示学校中心位置
// eslint-disable-next-line no-console
console.log('地理编码失败,显示学校中心位置')
ElMessage.warning('地址解析失败')
}
})
} else {
// 没有地址信息
const marker = new T.Marker(point)
map.value.addOverLay(marker)
const infoWin = new T.InfoWindow()
infoWin.setContent(`<div style="padding:12px;max-width:300px;">
<div style="font-size:14px;font-weight:bold;margin-bottom:8px;">📍 学校位置</div>
<div style="font-size:12px;color:#999;">暂无家庭地址信息</div>
</div>`)
marker.addEventListener('click', function () {
marker.openInfoWindow(infoWin)
})
}
}).catch(() => {
ElMessage.error('地图加载失败请检查网络连接或Token配置')
})
}, 200)
}).catch(() => {
ElMessage.error('获取地图配置失败')
}) })
}) })
} }
@@ -109,6 +173,7 @@ defineExpose({
height: 700px; height: 700px;
margin: 0; margin: 0;
font-family: "微软雅黑"; font-family: "微软雅黑";
margin-top: 15px;
} }
ul li { ul li {