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

@@ -590,7 +590,7 @@
<template #footer v-if="type==1">
<div class="dialog-footer">
<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>
</div>
</template>
@@ -612,7 +612,7 @@ import { list as listByGroupId } from '/@/api/recruit/recruitstudentschool'
import { getDeptList } from "/@/api/basic/basicclass"
import { getList } from "/@/api/recruit/recruitstudentplangroup"
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 { areaList, areaSonList } from "/@/api/recruit/recruitstudentschool"
import { list as scoreList } from "/@/api/recruit/recruitstudentplancorrectscoreconfig"
@@ -832,6 +832,9 @@ const init = (id: string | null, typeParam: number) => {
isShow.value = true
nextTick(() => {
dataFormRef.value?.resetFields()
getDicts('finance_student_source').then((res: any) => {
eduList.value = res.data || []
})
if (dataForm.id) {
areaPList.value = []
areaCList.value = []

View File

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

View File

@@ -290,14 +290,14 @@
icon="Download"
@click="handleExport()">名单导出
</el-button>
<el-button
<!-- <el-button
class="ml10"
type="primary"
plain
icon="UploadFilled"
v-auth="'recruit_send_img'"
@click="handleSendImg()">图片同步
</el-button>
</el-button> -->
</div>
</el-row>
@@ -347,7 +347,7 @@
prop="name"
header-align="center"
align="left"
min-width="250"
width="290"
label="资料检测">
<template #default="scope">
<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="gender" label="性别" width="80" align="center" show-overflow-tooltip>
<template #default="scope">
{{ getLabelValue(sexy, scope.row.gender) }}
<GenderTag :sex="scope.row.gender" />
</template>
</el-table-column>
<el-table-column prop="idNumber" label="身份证号" width="180" align="center" show-overflow-tooltip />
@@ -159,7 +159,7 @@
<template #default="scope">
<el-button
v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '1'"
type="success"
type="primary"
link
icon="CircleCheck"
@click="setFw(scope.row, 1)"
@@ -168,7 +168,7 @@
</el-button>
<el-button
v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '2'"
type="warning"
type="primary"
link
icon="Close"
@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 { getDeptList } from '/@/api/basic/basicclass'
const GenderTag = defineAsyncComponent(() => import('/@/components/GenderTag/index.vue'))
const DormFW = defineAsyncComponent(() => import('./dormFW.vue'))
const ShowMap = defineAsyncComponent(() => import('./showMap.vue'))

View File

@@ -4,14 +4,14 @@
:close-on-click-modal="false"
v-model="visible"
append-to-body
width="90%">
width="600">
<el-form :model="dataForm" :rules="dataRule" ref="dataFormRef" @keyup.enter="dataFormSubmit"
label-width="170px" size="small">
label-width="120px">
<el-row>
<el-col :span="24">
<el-form-item label="招生计划" prop="groupId">
<el-select v-model="dataForm.groupId" filterable :disabled="!!dataForm.id"
placeholder="请选择招生计划" size="small" style="width: 100%">
placeholder="请选择招生计划">
<el-option
v-for="item in planList"
:key="item.id"
@@ -39,14 +39,14 @@
<el-row>
<el-col :span="24">
<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-col>
</el-row>
<el-row>
<el-col :span="24">
<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
v-for="item in planMajorList"
:key="item.majorCode"
@@ -60,7 +60,7 @@
<el-row>
<el-col :span="24">
<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
v-for="item in planMajorList"
:key="item.majorCode"
@@ -73,23 +73,24 @@
</el-row>
<el-row>
<el-col :span="6">
<el-col :span="12">
<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-col>
<el-col :span="6">
<el-col :span="12">
<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-col>
<el-col :span="6">
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="总费用" prop="allMoney">
<span style="color: red">{{ dataForm.feeTuition + dataForm.feeAgency }}</span>
</el-form-item>
</el-col>
</el-row>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="审核备注" prop="auditRemarks">
@@ -101,7 +102,7 @@
<template #footer>
<div class="dialog-footer">
<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>
</template>
</el-dialog>
@@ -380,7 +381,12 @@ defineExpose({
})
</script>
<style scoped>
<style lang="scss" scoped>
.el-form {
.el-row:not(:last-of-type) {
margin-bottom: 18px !important;
}
}
.dialog-footer {
text-align: right;
}

View File

@@ -1,19 +1,14 @@
<template>
<el-dialog
title="家庭地址地图选点"
title="家庭地址地图查看"
append-to-body
:close-on-click-modal="false"
v-model="visible"
width="90%">
<div style="height: 100%;width:100%">
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px"
class="demo-ruleForm">
<el-form-item label="家庭地址" prop="homeAddressDetail">
<el-input v-model="form.homeAddressDetail" style="width: 100%"></el-input>
</el-form-item>
</el-form>
<el-descriptions :column="1" border>
<el-descriptions-item label="家庭地址">{{ form.homeAddressDetail }}</el-descriptions-item>
</el-descriptions>
<div id="container2"></div>
</div>
</el-dialog>
@@ -21,36 +16,34 @@
<script setup lang="ts">
import { ref, reactive, nextTick } from 'vue'
import { BMPGL } from "@/api/recruit/recruitstudentsignup"
import { getTypeValue } from "@/api/admin/dict"
import { loadTiandituMap } from "/@/api/recruit/recruitstudentsignup"
import { getDicts } from "/@/api/admin/dict"
import { ElMessage } from 'element-plus'
import { TIANDITU_TOKEN } from '/@/config/map'
// 表单引用
const formRef = ref()
// 响应式数据
const ak = "V0ooaf2RZyEGOkD8UzZB3gvw7pCb0Kx7" // 百度的地图密钥
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 address = ref(null)
const center = reactive({ lng: 0, lat: 0 })
const dictId = ref("")
const circleArr = ref<any[]>([])
const form = reactive({
id: "",
homeAddressDetail: "",
homeLng: 0, // 家庭地址经度
homeLat: 0, // 家庭地址纬度
raidus: 0
})
const rules = {
homeAddressDetail: [
{ required: true, message: '家庭地址不能为空', trigger: ["blur", "change"] }
],
}
// 初始化
const init = (row: any) => {
@@ -59,8 +52,11 @@ const init = (row: any) => {
circleShow.value = true
form.id = row.id
form.homeAddressDetail = row.homeAddressDetail
// 获取家庭地址的经纬度(如果有的话)
form.homeLng = row.homeLng || row.homeLongitude || 0
form.homeLat = row.homeLat || row.homeLatitude || 0
nextTick(() => {
getTypeValue("dorm_jw").then((data: any) => {
getDicts("dorm_jw").then((data: any) => {
const arr = data.data
arr.forEach((e: any) => {
if (e.label == 'bj') {
@@ -72,26 +68,94 @@ const init = (row: any) => {
center.lat = e.value
}
})
BMPGL(ak).then((BMapGL: any) => {
// 创建地图实例
const map = new BMapGL.Map("container2")
// 创建点坐标
const point = new BMapGL.Point(center.lng, center.lat)
// 初始化地图,设置中心点坐标和地图级别
map.centerAndZoom(point, 13)
// 开启鼠标滚轮缩放
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('您选择的地址没有解析到结果!')
// 等待对话框渲染完成后再加载地图
setTimeout(() => {
loadTiandituMap(tk).then((T: any) => {
// 清除之前的地图实例(如果存在)
if (map.value) {
map.value.clearOverLays()
}
}, '北京市')
})
// 创建地图实例
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;
margin: 0;
font-family: "微软雅黑";
margin-top: 15px;
}
ul li {