Files
school-developer/src/views/recruit/recruitstudentsignup/index.vue

1449 lines
44 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>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<!-- 搜索表单 -->
<search-form
v-show="showSearch"
:model="dataForm"
ref="searchFormRef"
@keyup-enter="handleFilter"
>
<template #default="{ visible }">
<template v-if="visible">
<el-form-item label="招生计划" prop="groupId">
<el-select v-model="dataForm.groupId" filterable clearable placeholder="请选择招生计划" @change="chanMajor">
<el-option
v-for="item in planList"
:key="item.id"
:label="item.groupName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="学院" prop="deptCode">
<el-select v-model="dataForm.deptCode" filterable clearable placeholder="请选择学院">
<el-option
v-for="item in deptList"
:key="item.deptCode"
:label="item.deptName"
:value="item.deptCode">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="报名时段" prop="startDate">
<el-date-picker
v-model="dataForm.startDate"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
clearable
:disabled-date="startDateDisabledDate"
type="date"
/>
<span style="margin: 0 8px;">-</span>
<el-date-picker
v-model="dataForm.endDate"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
clearable
:disabled-date="endDateDisabledDate"
type="date"
/>
</el-form-item>
<el-form-item label="录取时段" prop="lqStartDate">
<el-date-picker
v-model="dataForm.lqStartDate"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
clearable
type="date"
/>
<span style="margin: 0 8px;">-</span>
<el-date-picker
v-model="dataForm.lqEndDate"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
clearable
type="date"
/>
</el-form-item>
</template>
<!-- 可折叠的高级筛选条件 -->
<template v-if="!visible">
<el-form-item label="录取专业" prop="confirmedMajor">
<el-select v-model="dataForm.confirmedMajor" filterable clearable placeholder="请选择录取专业">
<el-option
v-for="item in planMajorList"
:key="item.majorCode"
:label="item.majorName+'('+item.learnYear+'年制)'"
:value="item.majorCode">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="拟报专业" prop="wishMajorOne">
<el-select v-model="dataForm.wishMajorOne" filterable clearable placeholder="请选择录取专业">
<el-option
v-for="item in planMajorList"
:key="item.majorCode"
:label="item.majorName+'('+item.learnYear+'年制)'"
:value="item.majorCode">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="录取状态" prop="auditStatus">
<el-select v-model="dataForm.auditStatus" filterable clearable placeholder="请选择录取状态">
<el-option
v-for="item in auditStatusList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="唯一号/姓名/身份证号/学校名称" prop="search">
<el-input v-model="dataForm.search" clearable placeholder="唯一号/姓名/身份证号/学校名称"></el-input>
</el-form-item>
<el-form-item label="文化程度" prop="degreeOfEducation">
<el-select v-model="dataForm.degreeOfEducation" filterable clearable placeholder="请选择文化程度">
<el-option
v-for="item in eduList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="是否住宿" prop="isAccommodation">
<el-select v-model="dataForm.isAccommodation" filterable clearable placeholder="请选择是否住宿">
<el-option
v-for="item in yes_no_type"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="是否低保" prop="isMinimumLivingSecurity">
<el-select v-model="dataForm.isMinimumLivingSecurity" filterable clearable placeholder="请选择是否低保">
<el-option
v-for="item in yes_no_type"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="经办人" prop="auditor">
<el-select
v-model="dataForm.auditor"
filterable
remote
clearable
reserve-keyword
placeholder="请选择经办人"
:remote-method="remoteTeacherByQuery">
<el-option
v-for="item in teacherList"
:key="item.teacherNo"
:label="item.realName"
:value="item.teacherNo">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="缴费状态" prop="paystatus">
<el-select v-model="dataForm.paystatus" filterable clearable placeholder="请选择缴费状态">
<el-option
v-for="item in paystatusList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="新市民材料已上传" prop="isNewCity">
<el-select v-model="dataForm.isNewCity" filterable clearable placeholder="请选择新市民材料已上传">
<el-option
v-for="item in yes_no_type"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="毕业证已上传" prop="graPic">
<el-select v-model="dataForm.graPic" filterable clearable placeholder="请选择毕业证已上传">
<el-option
v-for="item in yes_no_type"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="推送状态" prop="pushed">
<el-select v-model="dataForm.pushed" filterable clearable placeholder="请选择推送状态">
<el-option
v-for="item in pushedList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="来源" prop="isOut">
<el-select v-model="dataForm.isOut" filterable clearable placeholder="请选择来源">
<el-option
v-for="item in isOutList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="证书发放" prop="isBackTz">
<el-select v-model="dataForm.isBackTz" filterable clearable placeholder="请选择是否发放">
<el-option
v-for="item in isBackTzList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="是否同步学工" prop="isTb">
<el-select v-model="dataForm.isTb" filterable clearable placeholder="请选择是否同步学工">
<el-option
v-for="item in yes_no_type"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="市局审核" prop="cityExamType">
<el-select v-model="dataForm.cityExamType" filterable clearable placeholder="请选择市局审核状态">
<el-option
v-for="item in cityExamTypeList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="面试结果" prop="interview">
<el-select v-model="dataForm.interview" filterable clearable placeholder="请选择面试结果">
<el-option
v-for="item in interviewDicList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="资料审核状态" prop="zlsh">
<el-select v-model="dataForm.zlsh" filterable clearable placeholder="请选择资料审核状态">
<el-option
v-for="item in zlshList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</template>
</template>
<!-- 操作按钮 -->
<template #actions>
<el-form-item>
<el-button type="primary" @click="handleFilter" icon="Search">查询</el-button>
<el-button @click="resetForm('searchForm')" icon="Refresh" class="ml10">重置</el-button>
</el-form-item>
</template>
</search-form>
<!-- 操作按钮 -->
<el-row>
<div class="mb15" style="width: 100%;">
<el-button
type="primary"
icon="FolderAdd"
v-auth="'recruit_send_img'"
@click="handleAddData">新增
</el-button>
<el-button
type="warning"
plain
v-auth="'zipExport'"
icon="Download"
@click="downZip()">招生名单打包导出
</el-button>
<el-button
class="ml10"
type="warning"
plain
icon="Download"
@click="handleExport()">名单导出
</el-button>
<!-- <el-button
class="ml10"
type="primary"
plain
icon="UploadFilled"
v-auth="'recruit_send_img'"
@click="handleSendImg()">图片同步
</el-button> -->
</div>
</el-row>
<!-- 表格 -->
<el-table
ref="tableRef"
:data="state.dataList"
v-loading="state.loading"
border
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle">
<el-table-column
header-align="center"
align="center"
width="140"
label="操作">
<template #default="scope">
<div style="display: flex; align-items: center;">
<el-button type="primary" link icon="Document" @click="addOrUpdateHandle(scope.row.id,0)">
查看
</el-button>
<ActionDropdown
:items="getActionMenuItems(scope.row)"
@command="(command) => handleMoreCommand(command, scope.row)"
/>
</div>
</template>
</el-table-column>
<el-table-column
prop="serialNumber"
header-align="center"
align="center"
width="110"
label="唯一号">
</el-table-column>
<el-table-column
prop="name"
header-align="center"
align="center"
width="120"
label="姓名">
</el-table-column>
<el-table-column
prop="name"
header-align="center"
align="left"
width="290"
label="资料检测">
<template #default="scope">
<div v-if="scope.row.isOut=='0'" class="material-check-cell">
<!-- 资料审核状态 -->
<div class="check-item">
<span class="check-label">审核状态</span>
<el-tag v-if="scope.row.zlsh=='0'" type="info" size="small">未填写</el-tag>
<el-tag v-else-if="scope.row.zlsh=='2'" type="success" size="small">
<el-icon class="tag-icon"><CircleCheck /></el-icon>
审核通过
</el-tag>
<el-tag v-else-if="scope.row.zlsh=='1'" type="warning" size="small">待审核</el-tag>
<el-tag v-else-if="scope.row.zlsh=='3'" type="danger" size="small">
<el-icon class="tag-icon"><CircleClose /></el-icon>
审核驳回
</el-tag>
</div>
<!-- 材料状态 -->
<div v-if="scope.row.zlsh !='2'" class="check-item">
<span class="check-label">材料状态</span>
<div class="material-status">
<el-tag v-if="!scope.row.graPic" type="warning" size="small" class="material-tag">
<el-icon class="tag-icon"><Warning /></el-icon>
缺少毕业证
</el-tag>
<el-tag v-if="scope.row.degreeOfEducation == '1' && scope.row.zlsh !='2' && !scope.row.yyPic && !scope.row.housePic && !scope.row.sbPic" type="warning" size="small" class="material-tag">
<el-icon class="tag-icon"><Warning /></el-icon>
缺新市民材料
</el-tag>
<span v-if="scope.row.degreeOfEducation == '1' && scope.row.isOut == '1'" class="no-upload-text">无需上传</span>
</div>
</div>
<!-- 审核意见 -->
<div v-if="scope.row.zlsh=='3' && scope.row.zlshRemark" class="check-item check-remark">
<span class="check-label">审核意见</span>
<div class="remark-content">
<el-icon class="remark-icon"><Warning /></el-icon>
<el-tooltip :content="scope.row.zlshRemark" placement="top" :show-after="300">
<span class="remark-text">{{ scope.row.zlshRemark }}</span>
</el-tooltip>
</div>
</div>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
header-align="center"
align="center"
label="录取专业">
<el-table-column
prop="auditStatus"
header-align="center"
align="center"
width="110"
label="录取状态">
<template #default="scope">
<el-tag
v-if="getAuditStatusTagType(scope.row.auditStatus)"
:type="getAuditStatusTagType(scope.row.auditStatus)"
>
{{ getLabelValue(auditStatusList, scope.row.auditStatus) }}
</el-tag>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
prop="confirmedMajor"
header-align="center"
align="left"
min-width="180"
label="专业名称">
<template #default="scope">
<div v-if="scope.row.auditStatus==20" class="major-name">
<el-icon class="major-icon"><Document /></el-icon>
<span class="major-text">{{ getMajorLabelWithYears(planMajorList, scope.row.confirmedMajor, { key: 'majorCode', value: 'majorName' }) }}</span>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
prop="auditTime"
header-align="center"
align="center"
width="110"
label="录取时间">
<template #default="scope">
<span v-if="scope.row.auditStatus==20" class="time-text">{{ dateFormat(scope.row.auditTime) }}</span>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
prop="interview"
header-align="center"
align="center"
width="110"
label="面试结果">
<template #default="scope">
<div v-if="scope.row.degreeOfEducation == '3'" class="interview-cell">
<!-- <IconText
v-if="scope.row.interview == '1'"
:icon="CircleCheck"
:text="getLabelValue(interviewDicList, scope.row.interview)"
type="success"
size="small"
align="center"
/>
<IconText
v-else-if="scope.row.interview == '-1'"
:icon="CircleClose"
:text="getLabelValue(interviewDicList, scope.row.interview)"
type="danger"
size="small"
align="center"
/>
<IconText
v-else
:text="getLabelValue(interviewDicList, scope.row.interview)"
type="info"
size="small"
align="center"
/> -->
<span>{{ getLabelValue(interviewDicList, scope.row.interview) }}</span>
<div v-if="scope.row.interview == '-1' && scope.row.interviewReason" class="interview-reason">
<el-icon class="reason-icon"><Warning /></el-icon>
<el-tooltip :content="scope.row.interviewReason" placement="top" :show-after="300">
<span class="reason-text">{{ scope.row.interviewReason }}</span>
</el-tooltip>
</div>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
<el-table-column
prop="isBackTz"
header-align="center"
align="center"
min-width="150"
label="证书发放/发放人">
<template #default="scope">
<div v-if="scope.row.confirmedMajor" class="certificate-sender-cell">
<!-- <div class="certificate-status">
<IconText
v-if="scope.row.isBackTz=='0'"
:icon="CircleClose"
text="未发放"
type="danger"
align="center"
/>
<IconText
v-else-if="scope.row.isBackTz=='1'"
:icon="CircleCheck"
text="已发放"
type="success"
align="center"
/>
</div> -->
<span>{{ scope.row.isBackTz=='0' ? '未发放' : scope.row.isBackTz=='1' ? '已发放' : '-' }}</span>
<div v-if="scope.row.isBackTz=='1' && scope.row.sendUserName" class="sender-info">
<span class="sender-separator">/</span>
<IconText
:icon="User"
:text="scope.row.sendUserName"
align="center"
/>
</div>
</div>
<span v-else class="empty-text">-</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column
prop="deptCode"
header-align="center"
align="center"
width="120"
label="学院(经办人)">
<template #default="scope">
<span v-if="scope.row.auditStatus==20">
{{ getLabelValueByProps(deptList, scope.row.deptCode, { key: 'deptCode', value: 'deptName' }) }}
</span> <br/>
<span v-if="scope.row.auditStatus==20">
<span v-if="scope.row.auditorName">({{scope.row.auditorName}})</span>
<span v-else>-</span>
</span>
</template>
</el-table-column>
<el-table-column
prop="paiedOffline"
header-align="center"
align="center"
width="90"
label="缴费状态">
<template #default="scope">
<el-tag
v-if="getPaymentStatusTagType(scope.row.paiedOffline)"
:type="getPaymentStatusTagType(scope.row.paiedOffline)"
>
{{ getStatus(scope.row.paiedOffline) }}
</el-tag>
<span v-else class="empty-text">{{ getStatus(scope.row.paiedOffline) || '-' }}</span>
</template>
</el-table-column>
<el-table-column
prop="pushed"
header-align="center"
align="center"
width="90"
label="推送状态">
<template #default="scope">
<el-tag
:type="scope.row.pushed == '0' ? 'danger' : 'success'"
>
{{ getPushed(scope.row.pushed) }}
</el-tag>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-bind="state.pagination"
@current-change="currentChangeHandle"
@size-change="sizeChangeHandle"
/>
<!-- 弹窗, 新增 / 修改 -->
<TableForm ref="addOrUpdateRef" @refreshDataList="getDataList"></TableForm>
<MajorChange ref="majorChangeRef" @refreshDataList="getDataList"></MajorChange>
<Update ref="updateRef" @refreshDataList="getDataList"></Update>
<!-- 支付二维码弹窗 -->
<PayQrcodeDialog ref="payQrcodeDialogRef" @refresh="getDataList"></PayQrcodeDialog>
<!-- 延迟缴费弹窗 -->
<DelayPayTimeDialog ref="delayPayTimeDialogRef" @refresh="getDataList"></DelayPayTimeDialog>
<!-- 录取通知书弹窗 -->
<AdmissionNoticeDialog ref="admissionNoticeDialogRef" @refresh="getDataList"></AdmissionNoticeDialog>
<DormFW ref="dormFWRef"></DormFW>
<ShowMap ref="baiduMapRef"></ShowMap>
<InterviewForm ref="interviewFormRef" @refresh="getDataList"></InterviewForm>
</div>
</div>
</template>
<script setup lang="ts" name="recruitstudentsignup">
import { ref, reactive, onMounted, nextTick, defineAsyncComponent, watch } from 'vue'
import { Edit, Check, DocumentChecked, Close, Switch, Tickets, Document, Upload, Warning, User, CircleCheck, CircleClose } from '@element-plus/icons-vue'
import { useMessage, useMessageBox } from '/@/hooks/message'
import { BasicTableProps, useTable } from '/@/hooks/table'
import { auth } from '/@/utils/authFunction'
import axios from 'axios'
import { getList } from '/@/api/recruit/recruitstudentplangroup'
import {
delObj,
exportZip,
fetchList,
leaveSchool,
rePush as rePushApi,
yjOut,
oneClass,
oneStuNo,
tbStuWork,
sendImg,
pushCity as pushCityApi
} from '/@/api/recruit/recruitstudentsignup'
import { getLabelValue, getLabelValueByProps, getMajorLabelWithYears } from '/@/utils/dictLabel'
import { getDeptList } from "/@/api/basic/basicclass";
import { listPlanByCondition as planMajor } from "/@/api/recruit/recruitstudentplan";
import { getDictsByTypes } from "/@/api/admin/dict";
import { getUserListByRole } from "/@/api/admin/user";
import { queryTeacherBaseByNo } from "/@/api/professional/professionaluser/teacherbase";
import { useDict } from '/@/hooks/dict'
import { ROLE_CODE } from '/@/config/global'
import { showLoading, hideLoading } from '/@/api/asset/loading'
// 定义组件
const TableForm = defineAsyncComponent(() => import('./detaiform.vue'))
const MajorChange = defineAsyncComponent(() => import('./majorChange.vue'))
const Update = defineAsyncComponent(() => import('./update.vue'))
const DormFW = defineAsyncComponent(() => import('./dormFW.vue'))
const ShowMap = defineAsyncComponent(() => import('./showMap.vue'))
const InterviewForm = defineAsyncComponent(() => import('/@/views/recruit/recruitstudentsignup/interviewForm.vue'))
const PayQrcodeDialog = defineAsyncComponent(() => import('./PayQrcodeDialog.vue'))
const DelayPayTimeDialog = defineAsyncComponent(() => import('./DelayPayTimeDialog.vue'))
const AdmissionNoticeDialog = defineAsyncComponent(() => import('./AdmissionNoticeDialog.vue'))
const ActionDropdown = defineAsyncComponent(() => import('/@/components/tools/action-dropdown.vue'))
// 消息提示 hooks
const message = useMessage()
const messageBox = useMessageBox()
// 表格引用
const tableRef = ref()
const searchFormRef = ref()
const addOrUpdateRef = ref()
const majorChangeRef = ref()
const updateRef = ref()
const dormFWRef = ref()
const baiduMapRef = ref()
const interviewFormRef = ref()
const payQrcodeDialogRef = ref()
const delayPayTimeDialogRef = ref()
const admissionNoticeDialogRef = ref()
// 搜索表单显示状态
const showSearch = ref(true)
// 表单数据
const dataForm = reactive({
zlsh: '',
groupId: '',
deptCode: '',
confirmedMajor: '',
degreeOfEducation: '',
isAccommodation: '',
isMinimumLivingSecurity: '',
search: '',
auditor: '',
isNewCity: '',
startDate: '',
endDate: '',
lqStartDate: '',
lqEndDate: '',
paystatus: '',
graPic: '',
pushed: '',
wishMajorOne: '',
isTb: '',
cityExamType: '',
interview: '',
type: '',
auditStatus: '',
isOut: '',
isBackTz: ''
})
// 表格状态
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: dataForm,
pageList: async (params: any) => {
const response = await fetchList(params)
return {
data: {
records: response.data.records || [],
total: response.data.total || 0
}
}
},
createdIsNeed: false
})
// 使用 table hook
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle } = useTable(state)
// 弹窗状态(已移除,组件内部通过 v-model="visible" 控制)
// 列表数据
const auditorList = ref<any[]>([])
const planList = ref<any[]>([])
const eduList = ref<any[]>([])
const planMajorList = ref<any[]>([])
const deptList = ref<any[]>([])
const teacherList = ref<any[]>([])
const interviewDicList = ref<any[]>([])
const zlshList = ref<any[]>([])
const paystatusList = ref<any[]>([])
// 字典数据
const { yes_no_type } = useDict('yes_no_type')
// 静态数据
const isBackTzList = [{ label: '未发放', value: '0' }, { label: '已发放', value: '1' }]
const auditStatusList = [{ label: '未录取', value: '-20' }, { label: '待审核', value: '0' }, { label: '已录取', value: '20' }]
const cityExamTypeList = [{ label: '待审核', value: '0' }, { label: '通过', value: '1' }, { label: '驳回', value: '2' }]
const pushedList = [{ label: '未推送', value: '0' }, { label: '已推送', value: '1' }]
const isOutFwList = [{ label: '待确认', value: '0' }, { label: '范围内', value: '1' }, { label: '范围外', value: '2' }]
const isOutList = [{ label: '学校', value: '0' }, { label: '市平台', value: '1' }]
// 日期格式化
const dateFormat = (date: string | null | undefined) => {
if (!date) return ''
// return formatDate(date, format)
return date
}
// 日期选择器禁用日期
const startDateDisabledDate = (time: Date) => {
if (dataForm.endDate) {
return new Date(dataForm.endDate).getTime() < time.getTime()
}
return false
}
const endDateDisabledDate = (time: Date) => {
if (dataForm.startDate) {
return new Date(dataForm.startDate).getTime() > time.getTime()
}
return false
}
// 检索教师
const remoteTeacherByQuery = (query: string) => {
teacherList.value = []
if (query !== '') {
setTimeout(() => {
queryTeacherBaseByNo(query).then((response: any) => {
teacherList.value = response.data || []
}).catch(() => {
teacherList.value = []
})
}, 200)
}
}
// 发送图片
const handleSendImg = () => {
messageBox.confirm('是否确认同步招生图片到市平台?请谨慎操作').then(() => {
return sendImg()
}).then(() => {
message.success('同步图片请求已发起,请耐心等待')
}).catch(() => {
hideLoading()
})
}
// 同步学工
const handleTbStuWork = () => {
if (dataForm.groupId == '') {
message.warning('招生计划不能为空')
return
}
messageBox.confirm('是否确认同步学工?请谨慎操作').then(() => {
showLoading()
return tbStuWork(dataForm)
}).then(() => {
hideLoading()
message.success('同步完成')
}).catch(() => {
hideLoading()
})
}
// 一键分配班级和学号
const handleOneClassAndStuNo = () => {
if (dataForm.groupId == '') {
message.warning('招生计划不能为空')
return
}
messageBox.confirm('是否确认一键分配班级和学号?请谨慎操作').then(() => {
showLoading()
return Promise.all([oneClass(dataForm), oneStuNo(dataForm)])
}).then(() => {
hideLoading()
message.success('分配完成')
}).catch(() => {
hideLoading()
})
}
// 下载zip
const downZip = () => {
if (dataForm.groupId == '') {
message.warning('招生计划不能为空')
return
}
showLoading()
exportZip(dataForm).then(res => {
hideLoading()
const blob = new Blob([res.data])
const elink = document.createElement('a')
elink.download = '招生名单.zip'
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href)
document.body.removeChild(elink)
}).catch(() => {
hideLoading()
})
}
// 百度地图
const baiduMap = (row: any) => {
// 组件内部通过 v-model="visible" 控制显示
nextTick(() => {
baiduMapRef.value?.init(row)
})
}
// 设置宿舍
const setDormFW = () => {
// 组件内部通过 v-model="visible" 控制显示
nextTick(() => {
dormFWRef.value?.init()
})
}
// 一键判断是否超出住宿范围
const handleYjOut = () => {
if (dataForm.groupId == '') {
message.warning('招生计划不能为空')
return
}
messageBox.confirm('是否确认一键判断是否超出住宿范围?请谨慎操作').then(() => {
return yjOut({ groupId: dataForm.groupId })
}).then(() => {
message.success('操作成功')
getDataList()
})
}
// 导出审核
const handleExportAudit = (type: number) => {
if (dataForm.groupId == '') {
message.warning('招生计划不能为空')
return
}
downFile(type)
}
// 导出Excel
const exportExcel = (form: any, url: string) => {
return axios({
method: 'post',
url: url,
data: form,
responseType: 'blob',
headers: {
'Content-Type': 'application/json'
}
})
}
// 导出文件
const downFile = (type: number) => {
dataForm.type = String(type)
exportExcel(dataForm, '/recruit/recruitstudentsignup/exportExcel').then(res => {
const blob = new Blob([res.data])
const fileName = type == 1 ? '延迟缴费名单导出.xlsx' : '超时缴费名单导出.xlsx'
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href)
document.body.removeChild(elink)
}).catch(() => {})
}
// 导出
const handleExport = () => {
if (dataForm.groupId == '') {
message.warning('招生计划不能为空')
return
}
exportExcel(dataForm, '/recruit/recruitstudentsignup/exportData').then(res => {
const blob = new Blob([res.data])
const elink = document.createElement('a')
elink.download = '招生名单导出.xls'
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href)
document.body.removeChild(elink)
}).catch(() => {})
}
// 去重
const unique = (arr: any[]) => {
const rese = new Map()
return arr.filter((item) => !rese.has(item.username) && rese.set(item.username, 1))
}
// 切换专业
const chanMajor = () => {
planMajorList.value = []
if (dataForm.groupId) {
planMajor({ groupId: dataForm.groupId }).then(data => {
planMajorList.value = data.data
})
}
}
// 查询
const handleFilter = () => {
getDataList()
}
// 获取数据列表
const handleAddData=()=>{
addOrUpdateRef.value?.init(null, '1')
}
// 新增 / 修改
const addOrUpdateHandle = (id?: string, type?: number) => {
nextTick(() => {
// 新增时默认 type=1可编辑查看时 type=0只读审核时 type=1可编辑
const finalType = type !== undefined ? type : (id ? 0 : 1)
addOrUpdateRef.value?.init(id || null, finalType)
})
}
// 编辑
const edit = (id: string) => {
nextTick(() => {
updateRef.value?.init(id)
})
}
// 专业调整
const majorChange = (id: string) => {
nextTick(() => {
majorChangeRef.value?.init(id)
})
}
// 退学
const handleUpdate = (id: string, groupId: string, feeAgency: string) => {
messageBox.confirm('是否确认办理退学操作?请谨慎操作').then(() => {
return leaveSchool({ id, groupId, feeAgency })
}).then(() => {
message.success('操作成功')
getDataList()
})
}
// 删除
const deleteHandle = (id: string) => {
messageBox.confirm('是否确认删除本条数据?请谨慎操作').then(() => {
return delObj(id)
}).then(() => {
message.success('删除成功')
getDataList()
})
}
// 重置表单
const resetForm = (formName: string) => {
if (formName === 'searchForm') {
searchFormRef.value?.formRef?.resetFields()
}
}
// 获取录取状态标签类型
const getAuditStatusTagType = (status: string | number) => {
const statusMap: Record<string, string> = {
'0': 'warning',
'20': 'success',
'-20': 'danger'
}
return statusMap[String(status)] || ''
}
// 获取缴费状态标签类型
const getPaymentStatusTagType = (status: string | number) => {
const statusMap: Record<string, string> = {
'0': 'danger', // 未缴费
'5': 'warning', // 部分缴费
'10': 'success' // 已缴费
}
return statusMap[String(status)] || ''
}
// 缴费状态
const getStatus = (type: string) => {
return getLabelValue(paystatusList.value, type)
}
// 推送状态
const getPushed = (type: string) => {
if (type == '0') return '未推送'
if (type == '1') return '已推送'
return ''
}
// 专业状态
const getMajor = (type: string) => {
if (type == '0') return '未申请'
if (type == '1') return '待审核'
if (type == '2') return '驳回'
if (type == '3') return '已通过'
return ''
}
// 录取通知书
const lqtz = (row: any) => {
nextTick(() => {
admissionNoticeDialogRef.value?.init(row)
})
}
// 信息表
const infoTable = (row: any) => {
window.open('printRecruitedStu.html?appId=' + row.id)
}
// 推送市局
const handlePushCity = (id: string) => {
messageBox.confirm('是否确认推送该数据到市局审核?请谨慎操作').then(() => {
return pushCityApi({ id })
}).then(() => {
message.success('推送成功')
getDataList()
})
}
// 重新推送
const handleRePush = (row: any) => {
messageBox.confirm('是否确认重新推送本条数据?请谨慎操作').then(() => {
return rePushApi({ id: row.id })
}).then(() => {
message.success('推送成功')
getDataList()
})
}
// 延迟缴费
const delayPayTimeSet = (row: any) => {
nextTick(() => {
delayPayTimeDialogRef.value?.init(row)
})
}
// 支付二维码
const showPayCode = (row: any) => {
nextTick(() => {
payQrcodeDialogRef.value?.init(row)
})
}
// 面试
const interviewForm = (row: any) => {
nextTick(() => {
interviewFormRef.value?.init(row)
})
}
// 获取操作菜单项
const getActionMenuItems = (row: any) => {
return [
{
command: 'edit',
label: '补材料',
icon: Edit,
visible: () => auth('recruit_recruitstudentsignup_edit')
},
{
command: 'interview',
label: '面试',
icon: Check,
visible: () => auth('recruit_recruitstudentsignup_interview') && row.degreeOfEducation == '3'
},
{
command: 'audit',
label: '审核',
icon: DocumentChecked,
visible: () => auth('recruit_recruitstudentsignup_edit') && row.auditStatus == '0'
},
{
command: 'leaveSchool',
label: '退学',
icon: Close,
visible: () => auth('recruit_recruitstudentsignup_leaveSchool') && row.auditStatus == '20' && row.isMajorChange != '1'
},
{
command: 'majorChange',
label: '调整专业',
icon: Switch,
visible: () => auth('recruit_recruitstudentsignup_change') && row.auditStatus == '20'
},
{
command: 'payQrcode',
label: '支付二维码',
icon: Tickets,
visible: () => auth('recruit_recruitstudentsignup_show') && row.pushed == '1' && row.paiedOffline != '10'
},
{
command: 'rePush',
label: '重新推送',
icon: Check,
visible: () => auth('recruit_recruitstudentsignup_rePush') && row.pushed == '0' && row.auditStatus == '20'
},
{
command: 'admissionNotice',
label: '录取通知书',
icon: Document,
visible: () => {
if (!auth('recruit_recruitstudentsignup_show')) return false
return (
(row.degreeOfEducation == '1' && row.isOut == '1' && row.auditStatus == '20') ||
(row.degreeOfEducation == '1' && row.isOut == '0' && row.paiedOffline != '0' && row.auditStatus == '20') ||
(row.degreeOfEducation == '2' && row.isGradePic == '1' && row.paiedOffline != '0' && row.auditStatus == '20') ||
(row.degreeOfEducation == '3' && row.isGradePic == '1' && row.paiedOffline != '0' && row.auditStatus == '20')
)
}
},
{
command: 'infoTable',
label: '信息表',
icon: Document,
visible: () => auth('recruit_recruitstudentsignup_show') && row.paiedOffline != '0' && row.auditStatus == '20'
},
// {
// command: 'pushCity',
// label: '推送市局',
// icon: Upload,
// visible: () => auth('recruit_recruitstudentsignup_push') && row.auditStatus == '20'
// }
]
}
// 处理更多操作命令
const handleMoreCommand = (command: string, row: any) => {
switch (command) {
case 'edit':
edit(row.id)
break
case 'interview':
interviewForm(row)
break
case 'audit':
addOrUpdateHandle(row.id, 1)
break
case 'leaveSchool':
handleUpdate(row.id, row.groupId, row.feeAgency)
break
case 'majorChange':
majorChange(row.id)
break
case 'payQrcode':
showPayCode(row)
break
case 'admissionNotice':
lqtz(row)
break
case 'infoTable':
infoTable(row)
break
case 'rePush':
handleRePush(row)
break
case 'pushCity':
handlePushCity(row.id)
break
}
}
// 初始化
const init = async () => {
// 查询二级学院信息
getDeptList().then(data => {
deptList.value = data.data
})
// 获取招生计划列表
getList().then(data => {
planList.value = data.data
if (planList.value.length > 0) {
dataForm.groupId = planList.value[0].id
getDataList()
chanMajor()
}
})
// 批量获取字典数据:文化程度、面试结果、资料审核状态、缴费状态
getDictsByTypes(['finance_student_source','interview_dic', 'recruit_zlsh', 'recruit_pay_status']).then((res) => {
eduList.value = res.data.finance_student_source || []
interviewDicList.value = res.data.interview_dic || []
zlshList.value = res.data.recruit_zlsh || []
paystatusList.value = res.data.recruit_pay_status || []
})
// 所有经办人
getUserListByRole(ROLE_CODE.ROLE_RECRUIT_SECOND).then((res: any) => {
auditorList.value = res.data || []
getUserListByRole(ROLE_CODE.ROLE_RECRUIT).then((re: any) => {
if (re.data) {
re.data.forEach((r: any) => {
auditorList.value.push(r)
})
}
auditorList.value = unique(auditorList.value)
})
})
}
// 监听招生计划变化
watch(() => dataForm.groupId, () => {
if (dataForm.groupId) {
chanMajor()
}
})
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
// 空值文本样式
.empty-text {
color: #909399;
font-size: 13px;
}
// 专业名称样式
.major-name {
display: flex;
align-items: center;
gap: 6px;
.major-icon {
color: var(--el-color-primary);
font-size: 14px;
flex-shrink: 0;
}
.major-text {
color: #303133;
font-weight: 500;
font-size: 13px;
}
}
// 时间样式
.time-text {
font-size: 13px;
}
// 面试结果样式
.interview-cell {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
.interview-reason {
display: flex;
align-items: center;
gap: 4px;
margin-top: 4px;
.reason-icon {
color: #ff9900;
font-size: 12px;
flex-shrink: 0;
}
.reason-text {
color: #ff9900;
font-size: 12px;
max-width: 85px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
}
}
// 证书发放/发放人样式
.certificate-sender-cell {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 6px;
flex-wrap: wrap;
.certificate-status {
display: flex;
align-items: center;
justify-content: center;
}
.sender-info {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
.sender-separator {
color: #c0c4cc;
font-size: 12px;
margin: 0 2px;
}
.sender-icon {
font-size: 13px;
flex-shrink: 0;
}
.sender-text {
font-size: 12px;
}
}
}
// 资料检测样式
.material-check-cell {
display: flex;
flex-direction: column;
gap: 8px;
padding: 4px 0;
.check-item {
display: flex;
align-items: flex-start;
gap: 6px;
line-height: 1.5;
.check-label {
color: #606266;
font-size: 12px;
font-weight: 500;
white-space: nowrap;
flex-shrink: 0;
}
:deep(.el-tag) {
display: inline-flex;
align-items: center;
vertical-align: middle;
gap: 4px;
line-height: 1;
.tag-icon {
font-size: 12px;
vertical-align: middle;
}
}
}
.material-status {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
gap: 6px;
align-items: center;
.material-tag {
margin: 0;
flex-shrink: 0;
}
.no-upload-text {
color: #67c23a;
font-size: 12px;
white-space: nowrap;
}
}
.check-remark {
margin-top: 4px;
.remark-content {
display: flex;
align-items: flex-start;
gap: 4px;
flex: 1;
.remark-icon {
color: #f56c6c;
font-size: 14px;
flex-shrink: 0;
margin-top: 2px;
}
.remark-text {
color: #f56c6c;
font-size: 12px;
line-height: 1.5;
display: inline-block;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: top;
}
}
}
}
</style>