diff --git a/src/api/recruit/recruitstudentsignup.ts b/src/api/recruit/recruitstudentsignup.ts index 42e99e5..545a4a6 100644 --- a/src/api/recruit/recruitstudentsignup.ts +++ b/src/api/recruit/recruitstudentsignup.ts @@ -392,6 +392,14 @@ export const setFw = (obj: any) => { }); }; +export const updateInfo = (obj: any) => { + return request({ + url: '/recruit/recruitstudentsignup/updateInfo', + method: 'post', + data: obj + }) +} + /** * 更新信息 * @param obj diff --git a/src/components/ClickableTag/README.md b/src/components/ClickableTag/README.md new file mode 100644 index 0000000..f447730 --- /dev/null +++ b/src/components/ClickableTag/README.md @@ -0,0 +1,225 @@ +# ClickableTag 可点击标签组件 + +一个可点击、带图标的标签组件,支持悬停动画效果。 + +## 功能特性 + +- ✅ 支持所有 Element Plus Tag 类型 +- ✅ 可自定义左侧图标 +- ✅ 可选显示右侧箭头(默认不显示) +- ✅ 可选显示警告图标(默认不显示) +- ✅ 悬停动画效果 +- ✅ 点击事件支持 + +## Props + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +|-----|------|------|-------|--------| +| type | 标签类型 | string | success/info/warning/danger/primary | primary | +| size | 标签大小 | string | large/default/small | default | +| leftIcon | 左侧图标组件 | Component | - | undefined | +| middleIcon | 中间图标组件(如警告图标) | Component | - | undefined | +| rightIcon | 右侧图标组件 | Component | - | DArrowRight(默认双箭头,传 null 不显示) | + +## Events + +| 事件名 | 说明 | 回调参数 | +|--------|------|---------| +| click | 点击标签时触发 | - | + +## 使用示例 + +### 基础用法(默认带右侧双箭头) + +```vue + + + +``` + +### 不显示右侧箭头 + +```vue + + + +``` + +### 带左侧图标 + +```vue + + + +``` + +### 自定义右侧图标 + +```vue + + + +``` + +### 带中间警告图标 + +```vue + + + +``` + +### 自定义所有图标 + +```vue + + + +``` + +### 监听点击事件 + +```vue + + + +``` + +### 配合 Popover 使用 + +```vue + + + +``` + +## 样式说明 + +组件自带以下交互效果: + +- **悬停效果**:添加阴影 +- **右图标动画**:悬停时向右移动 2px,透明度 70% +- **中间图标动画**:带有脉冲动画效果 +- **图标大小**:自动跟随 size 属性(small/default/large) +- **响应式**:所有图标垂直居中对齐 +- **默认箭头**:右侧默认显示双箭头图标 `DArrowRight` + +## 实际应用 + +在 `src/views/recruit/recruitstudentsignup/index.vue` 中的使用: + +```vue + + + 待审核 + +``` + +## 图标位置说明 + +``` +[ 左图标 文本内容 中间图标 ⇉ ] + ↑ ↑ ↑ +leftIcon middleIcon rightIcon(默认双箭头) +``` + +- **leftIcon**: 主要图标,表示状态类型 +- **middleIcon**: 辅助图标,如警告提示(带脉冲动画) +- **rightIcon**: 交互提示图标,默认为双箭头 `DArrowRight`(悬停时右移,透明度70%),传 `null` 则不显示 diff --git a/src/components/ClickableTag/index.vue b/src/components/ClickableTag/index.vue new file mode 100644 index 0000000..8fe6817 --- /dev/null +++ b/src/components/ClickableTag/index.vue @@ -0,0 +1,119 @@ + + + + + + + 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 @@ - +