From 0063894c8e09a8588ce285a5d76e014dedb91f15 Mon Sep 17 00:00:00 2001 From: guochunsi <1595020186@qq.com> Date: Mon, 19 Jan 2026 18:01:21 +0800 Subject: [PATCH 01/13] a --- src/api/recruit/recruitstudentsignup.ts | 40 ++++ src/config/map.ts | 40 ++++ .../recruitstudentsignup/detaiform.vue | 7 +- .../recruit/recruitstudentsignup/dormFW.vue | 189 ++++++++++++++---- .../recruit/recruitstudentsignup/index.vue | 6 +- .../recruit/recruitstudentsignup/list.vue | 8 +- .../recruitstudentsignup/majorChange.vue | 36 ++-- .../recruit/recruitstudentsignup/showMap.vue | 143 +++++++++---- 8 files changed, 373 insertions(+), 96 deletions(-) create mode 100644 src/config/map.ts diff --git a/src/api/recruit/recruitstudentsignup.ts b/src/api/recruit/recruitstudentsignup.ts index 010ad66..aa6f520 100644 --- a/src/api/recruit/recruitstudentsignup.ts +++ b/src/api/recruit/recruitstudentsignup.ts @@ -458,6 +458,7 @@ export const batchPushAll = (obj: any) => { */ export const BMPGL = (ak: string) => { return new Promise(function (resolve, reject) { + // @ts-ignore window.init = function () { // eslint-disable-next-line // 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 diff --git a/src/config/map.ts b/src/config/map.ts new file mode 100644 index 0000000..92c9ac7 --- /dev/null +++ b/src/config/map.ts @@ -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 diff --git a/src/views/recruit/recruitstudentsignup/detaiform.vue b/src/views/recruit/recruitstudentsignup/detaiform.vue index db296f9..29a5e0d 100644 --- a/src/views/recruit/recruitstudentsignup/detaiform.vue +++ b/src/views/recruit/recruitstudentsignup/detaiform.vue @@ -590,7 +590,7 @@ @@ -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 = [] diff --git a/src/views/recruit/recruitstudentsignup/dormFW.vue b/src/views/recruit/recruitstudentsignup/dormFW.vue index 9cb4199..413d7fd 100644 --- a/src/views/recruit/recruitstudentsignup/dormFW.vue +++ b/src/views/recruit/recruitstudentsignup/dormFW.vue @@ -4,22 +4,19 @@ append-to-body :close-on-click-modal="false" v-model="visible" - width="800"> + width="90%">
- - + -
@@ -28,9 +25,10 @@ - diff --git a/src/config/global.ts b/src/config/global.ts index 80c4684..8022246 100644 --- a/src/config/global.ts +++ b/src/config/global.ts @@ -51,3 +51,36 @@ export const BXSTATUS = { * 前端URL */ export const FRONT_URL = "https://zhxy.czjsy.com"; + +/** + * 招生相关常量 + */ + +// 缴费状态 使用字典recruit_pay_status + +// 推送状态 +export const PUSHED_STATUS_LIST = [ + { label: "未推送", value: "0" }, + { label: "已推送", value: "1" } +]; + +// 数据来源 +export const DATA_SOURCE_LIST = [ + { label: "学校", value: "0" }, + { label: "市平台", value: "1" } +]; + +// 录取通知书发放状态 +export const NOTICE_SEND_STATUS_LIST = [ + { label: "未发放", value: "0" }, + { label: "已发放", value: "1" } +]; + +// 审核状态 使用字典recruit_audit_status + + +// 市平台考试类型审核状态 使用字典recruit_city_exzm_type + + +// 宿舍范围状态 使用字典recruit_dorm_range_status + diff --git a/src/directive/customDirective.ts b/src/directive/customDirective.ts index abad5d8..bbb562f 100644 --- a/src/directive/customDirective.ts +++ b/src/directive/customDirective.ts @@ -1,5 +1,54 @@ import type { App } from 'vue'; +/** + * 输入过滤指令 + * @directive v-input-filter,如 `` + * @param number - 纯数字 + * @param alphanumeric - 数字+字母 + * @param idcard - 数字+字母+括号(支持大陆、港澳台身份证) + * @param tel - 固话格式(数字+横杠+括号+空格) + */ +export function inputFilterDirective(app: App) { + app.directive('input-filter', { + mounted(el, binding) { + const input = el.querySelector('input') || el; + const filterType = binding.value || 'number'; + + const filters: { [key: string]: RegExp } = { + number: /[^\d]/g, // 纯数字 + alphanumeric: /[^0-9A-Za-z]/g, // 数字+字母 + idcard: /[^0-9A-Za-z()]/g, // 数字+字母+括号(支持港澳台) + tel: /[^\d\-() ]/g, // 固话:数字+横杠+括号+空格 + }; + + const handleInput = (e: Event) => { + const target = e.target as HTMLInputElement; + const regex = filters[filterType]; + if (regex && target.value) { + const newValue = target.value.replace(regex, ''); + if (newValue !== target.value) { + target.value = newValue; + // 触发 input 事件,确保 v-model 更新 + target.dispatchEvent(new Event('input')); + } + } + }; + + input.addEventListener('input', handleInput); + // 保存 handler,用于 unmounted 时清理 + (el as any)._inputFilterHandler = handleInput; + (el as any)._inputFilterElement = input; + }, + unmounted(el) { + const handler = (el as any)._inputFilterHandler; + const input = (el as any)._inputFilterElement; + if (handler && input) { + input.removeEventListener('input', handler); + } + }, + }); +} + /** * 按钮波浪指令 * @directive 默认方式:v-waves,如 `
` diff --git a/src/directive/index.ts b/src/directive/index.ts index 3e04a79..3fff6df 100644 --- a/src/directive/index.ts +++ b/src/directive/index.ts @@ -1,17 +1,20 @@ import type { App } from 'vue'; import { authDirective } from '/@/directive/authDirective'; -import { wavesDirective } from '/@/directive/customDirective'; +import { wavesDirective, inputFilterDirective } from '/@/directive/customDirective'; /** * 导出指令方法:v-xxx * @methods authDirective 用户权限指令,用法:v-auth * @methods wavesDirective 按钮波浪指令,用法:v-waves + * @methods inputFilterDirective 输入过滤指令,用法:v-input-filter */ export function directive(app: App) { // 用户权限指令 authDirective(app); // 按钮波浪指令 wavesDirective(app); + // 输入过滤指令 + inputFilterDirective(app); // focus app.directive('focus', { mounted(el) { diff --git a/src/theme/element.scss b/src/theme/element.scss index 7b0c4e9..d443684 100644 --- a/src/theme/element.scss +++ b/src/theme/element.scss @@ -545,14 +545,8 @@ svg { border-color: #d3d4d6 !important; } - // 主要类型 - 浅蓝背景 + 深蓝文字 - &.el-tag--primary { - --el-tag-bg-color: #ecf5ff !important; - --el-tag-text-color: #409eff !important; - background-color: #ecf5ff !important; - color: #409eff !important; - border-color: #b3d8ff !important; - } + // 主要类型 - 保持 Element Plus 默认样式,不覆盖 + // primary 类型使用默认的主题色系统,无需手动覆盖 // 确保文字颜色应用到所有子元素 .el-tag__content, diff --git a/src/utils/toolsValidate.ts b/src/utils/toolsValidate.ts index c3b80d3..d472c99 100644 --- a/src/utils/toolsValidate.ts +++ b/src/utils/toolsValidate.ts @@ -300,7 +300,7 @@ export function verifyEmail(val: string) { } /** - * 身份证 + * 身份证(大陆18位) * @param val 当前值字符串 * @returns 返回 true: 身份证正确 */ @@ -311,6 +311,28 @@ export function verifyIdCard(val: string) { else return true; } +/** + * 身份证/港澳台证件(支持大陆、香港、澳门、台湾) + * @param val 当前值字符串 + * @returns 返回 true: 证件号正确 + */ +export function verifyIdCardAll(val: string) { + // 大陆身份证:18位 + const mainlandIdCard = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; + // 香港身份证:字母+6位数字+(校验码),如 A123456(7) + const hkIdCard = /^[A-Z]{1,2}\d{6}\([0-9A]\)$/; + // 澳门身份证:1位或7位数字 + const macaoIdCard = /^[1-9]\d{0,6}$/; + // 台湾身份证:1个字母+9位数字 + const taiwanIdCard = /^[A-Z]\d{9}$/; + + // 只要匹配其中一种即可 + if (mainlandIdCard.test(val) || hkIdCard.test(val) || macaoIdCard.test(val) || taiwanIdCard.test(val)) { + return true; + } + return false; +} + /** * 姓名 * @param val 当前值字符串 @@ -368,3 +390,15 @@ export function verifyCarNum(val: string) { // true:车牌号正确 else return true; } + +/** + * 准考证号 + * @param val 当前值字符串 + * @returns 返回 true:准考证号正确 + */ +export function verifyAdmissionNumber(val: string) { + // false: 准考证号不正确(6-20位数字或字母) + if (!/^[0-9A-Za-z]{6,20}$/.test(val)) return false; + // true:准考证号正确 + else return true; +} diff --git a/src/views/recruit/recruitImitateAdjustBatch/detaiform.vue b/src/views/recruit/recruitImitateAdjustBatch/detaiform.vue index bad8a31..923a553 100644 --- a/src/views/recruit/recruitImitateAdjustBatch/detaiform.vue +++ b/src/views/recruit/recruitImitateAdjustBatch/detaiform.vue @@ -4,7 +4,7 @@ :close-on-click-modal="false" width="600px" v-model="visible"> - + diff --git a/src/views/recruit/recruitImitateAdjustBatch/index.vue b/src/views/recruit/recruitImitateAdjustBatch/index.vue index f7e31ff..6be36f9 100644 --- a/src/views/recruit/recruitImitateAdjustBatch/index.vue +++ b/src/views/recruit/recruitImitateAdjustBatch/index.vue @@ -99,7 +99,7 @@ - + @@ -127,7 +127,7 @@ import { useMessage, useMessageBox } from '/@/hooks/message' import { Edit, Delete } from '@element-plus/icons-vue' import { getMNStuList, delMNObj } from '/@/api/recruit/recruitImitateAdjustBatch' import { listPlanByCondition as planMajor } from '/@/api/recruit/recruitstudentplan' -import { getTypeValue } from '/@/api/admin/dict' +import { getDicts } from '/@/api/admin/dict' import { getLabelValueByProps } from '/@/utils/dictLabel' const AddMNStu = defineAsyncComponent(() => import('./addMNStu.vue')) @@ -149,7 +149,6 @@ const addMnStuRef = ref() const visible = ref(false) const canSubmit = ref(false) const dataListLoading = ref(false) -const addMnStuVisible = ref(false) const dataForm = reactive({ batchNo: "", @@ -171,7 +170,6 @@ const init = (batchNo: string, groupId: string) => { // 新增 / 修改 const addOrUpdateHandle = (id?: string) => { - addMnStuVisible.value = true nextTick(() => { addMnStuRef.value?.init(id || null, dataForm.groupId, dataForm.batchNo) }) @@ -205,7 +203,7 @@ const getDataList = () => { // 初始化数据 const initData = () => { eduList.value = [] - getTypeValue('finance_student_source').then((res: any) => { + getDicts('finance_student_source').then((res: any) => { eduList.value = res.data }) planMajorList.value = [] diff --git a/src/views/recruit/recruitexampeople/index.vue b/src/views/recruit/recruitexampeople/index.vue index 17ec062..23f072d 100644 --- a/src/views/recruit/recruitexampeople/index.vue +++ b/src/views/recruit/recruitexampeople/index.vue @@ -71,11 +71,11 @@ - +