Files
school-developer/src/views/recruit/recruitstudentsignup/index.vue
zhoutianchi 96d2d9b6e1 1
2026-02-27 15:07:35 +08:00

1435 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"
:label-width="100"
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="请选择招生计划" >
<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="search">
<el-input v-model="dataForm.search" clearable placeholder="唯一号/姓名/身份证号/学校名称"></el-input>
</el-form-item>
<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="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>
</template>
<!-- 可折叠的高级筛选条件 -->
<template v-if="!visible">
<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="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 newCityMaterialList"
: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>
<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>
<!-- 操作按钮 -->
<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
v-if="hasAuth('recruit_send_img')"
type="primary"
icon="FolderAdd"
@click="handleAddData">新增
</el-button>
<el-button
v-auth="'recruit_zzpt_import'"
type="primary"
plain
icon="UploadFilled"
:loading="exportLoading"
@click="handleImportDialog"
>导入中招平台数据
</el-button>
<el-button
v-auth="'recruit_sign_sync'"
type="warning"
plain
icon="Refresh"
:loading="exportLoading"
@click="handleSyncData"
>一键同步省人社
</el-button>
<!-- <el-button-->
<!-- v-if="hasAuth('zipExport')"-->
<!-- type="warning"-->
<!-- plain-->
<!-- icon="Download"-->
<!-- @click="downZip()">招生名单打包导出-->
<!-- </el-button>-->
<!-- <el-button -->
<!-- class="ml10"-->
<!-- type="warning"-->
<!-- plain-->
<!-- icon="Download"-->
<!-- @click="handleExport()">名单导出-->
<!-- </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
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="center"
width="130"
label="资料检测">
<template #default="scope">
<div v-if="scope.row.isOut=='0'" class="material-check-compact">
<!-- 审核通过zlsh=='2'不需要弹窗直接显示 -->
<ClickableTag
v-if="scope.row.zlsh=='2'"
:type="getStatusConfig(zlshList, '2')?.type"
:left-icon="CircleCheck"
:right-icon="null">
{{ getStatusConfig(zlshList, '2')?.label }}
</ClickableTag>
<!-- 其他状态需要弹窗查看详情 -->
<el-popover
v-else
placement="right"
:width="320"
trigger="click">
<template #reference>
<div class="status-wrapper">
<!-- 审核状态标签基于配置 -->
<ClickableTag
v-if="getStatusConfig(zlshList, scope.row.zlsh)"
:type="getStatusConfig(zlshList, scope.row.zlsh)?.type"
:left-icon="getStatusConfig(zlshList, scope.row.zlsh)?.icon">
{{ getStatusConfig(zlshList, scope.row.zlsh)?.label }}
</ClickableTag>
</div>
</template>
<!-- 弹出内容 -->
<div class="material-detail-popover">
<div class="detail-title">资料检测详情</div>
<!-- 审核状态 -->
<div class="detail-section horizontal">
<div class="section-label">审核状态</div>
<div class="section-content">
<el-tag
v-if="getStatusConfig(zlshList, scope.row.zlsh)"
:type="getStatusConfig(zlshList, scope.row.zlsh)?.type"
size="small">
<el-icon v-if="getStatusConfig(zlshList, scope.row.zlsh)?.icon" class="tag-icon">
<component :is="getStatusConfig(zlshList, scope.row.zlsh)?.icon" />
</el-icon>
{{ getStatusConfig(zlshList, scope.row.zlsh)?.label }}
</el-tag>
</div>
</div>
<!-- 材料状态 审核通过不需要弹窗直接显示 -->
<div v-if="scope.row.zlsh !='2'" class="detail-section">
<div class="section-label">材料状态</div>
<div class="material-list">
<div v-if="!scope.row.graPic" class="material-item warning">
<el-icon><Warning /></el-icon>
<span>缺少毕业证</span>
</div>
<div v-if="scope.row.degreeOfEducation == '1' && scope.row.zlsh !='2' && !scope.row.yyPic && !scope.row.housePic && !scope.row.sbPic" class="material-item warning">
<el-icon><Warning /></el-icon>
<span>缺新市民材料</span>
</div>
<div v-if="scope.row.degreeOfEducation == '1' && scope.row.isOut == '1'" class="material-item success">
<el-icon><CircleCheck /></el-icon>
<span>无需上传</span>
</div>
<div v-if="scope.row.graPic && (scope.row.degreeOfEducation != '1' || scope.row.yyPic || scope.row.housePic || scope.row.sbPic)" class="material-item success">
<el-icon><CircleCheck /></el-icon>
<span>材料齐全</span>
</div>
</div>
</div>
<!-- 驳回zlsh=='3' 审核意见 -->
<div v-if="scope.row.zlsh=='3' && scope.row.zlshRemark" class="detail-section">
<div class="section-label">审核意见</div>
<div class="remark-box">
<el-icon class="remark-icon"><Warning /></el-icon>
<div class="remark-text">{{ scope.row.zlshRemark }}</div>
</div>
</div>
</div>
</el-popover>
</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="getStatusConfig(auditStatusList, scope.row.auditStatus)"
:type="getStatusConfig(auditStatusList, scope.row.auditStatus)?.type"
>
{{ getStatusConfig(auditStatusList, scope.row.auditStatus)?.label }}
</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="160"
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="140"
label="面试结果">
<template #default="scope">
<div v-if="scope.row.degreeOfEducation == '3'" class="interview-cell">
<!-- 面试驳回点击查看驳回原因 -->
<el-popover
v-if="scope.row.interview == '-1'"
placement="right"
:width="300"
trigger="click">
<template #reference>
<ClickableTag
:type="getStatusConfig(interviewDicList, scope.row.interview)?.type"
:left-icon="getStatusConfig(interviewDicList, scope.row.interview)?.icon">
{{ getStatusConfig(interviewDicList, scope.row.interview)?.label }}
</ClickableTag>
</template>
<!-- 弹出内容 -->
<div class="interview-detail-popover">
<div class="detail-title">面试详情</div>
<!-- 面试结果 -->
<div class="detail-section horizontal">
<div class="section-label">面试结果</div>
<div class="section-content">
<ClickableTag
:type="getStatusConfig(interviewDicList, scope.row.interview)?.type"
:left-icon="getStatusConfig(interviewDicList, scope.row.interview)?.icon"
:right-icon="null">
{{ getStatusConfig(interviewDicList, scope.row.interview)?.label }}
</ClickableTag>
</div>
</div>
<!-- 驳回原因 -->
<div v-if="scope.row.interviewReason" class="detail-section">
<div class="section-label">驳回原因</div>
<div class="section-content reason-content">
<el-icon class="reason-icon"><Warning /></el-icon>
<span>{{ scope.row.interviewReason }}</span>
</div>
</div>
</div>
</el-popover>
<!-- 其他状态包括面试通过直接显示不需要弹窗 -->
<ClickableTag
v-else-if="scope.row.interview"
:type="getStatusConfig(interviewDicList, scope.row.interview)?.type"
:left-icon="getStatusConfig(interviewDicList, scope.row.interview)?.icon"
:right-icon="null">
{{ getStatusConfig(interviewDicList, scope.row.interview)?.label }}
</ClickableTag>
<!-- 未填写 -->
<span v-else class="empty-text">-</span>
</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">
<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="180"
label="学院(经办人)"
show-overflow-tooltip>
<template #default="scope">
<span v-if="scope.row.auditStatus==20">
{{ getLabelValueByProps(deptList, scope.row.deptCode, { key: 'deptCode', value: 'deptName' }) }}
<span v-if="scope.row.auditorName">({{ scope.row.auditorName }})</span>
</span>
<span v-else class="empty-text">-</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="getStatusConfig(paystatusList, scope.row.paiedOffline)"
:type="getStatusConfig(paystatusList, scope.row.paiedOffline)?.type"
>
{{ getStatusConfig(paystatusList, scope.row.paiedOffline)?.label }}
</el-tag>
<span v-else class="empty-text">{{ getStatusConfig(paystatusList, scope.row.paiedOffline)?.label || '-' }}</span>
</template>
</el-table-column>
<el-table-column
prop="pushed"
header-align="center"
align="center"
width="90"
label="推送状态">
<template #default="scope">
<el-tag
:type="getStatusConfig(pushedList, scope.row.pushed)?.type"
>
{{ getStatusConfig(pushedList, scope.row.pushed)?.label }}
</el-tag>
</template>
</el-table-column>
<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>
<!-- 分页 -->
<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>
<!-- 录取通知书弹窗 -->
<AdmissionNoticeDialog ref="admissionNoticeDialogRef" @refresh="getDataList"></AdmissionNoticeDialog>
<InterviewForm ref="interviewFormRef" @refresh="getDataList"></InterviewForm>
<import-recruit-info ref="ImportRecruitInfoRef" @refreshDataList="getDataList"></import-recruit-info>
</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, Warning, User, CircleCheck } from '@element-plus/icons-vue'
import ClickableTag from '/@/components/ClickableTag/index.vue'
import { useAuth } from '/@/hooks/auth'
import { useMessage, useMessageBox } from '/@/hooks/message'
import { BasicTableProps, useTable } from '/@/hooks/table'
import axios from 'axios'
import { getList } from '/@/api/recruit/recruitstudentplangroup'
import {
exportZip,
fetchList,
leaveSchool,
rePush as rePushApi,
pushCity as pushCityApi,
resetSign as resetSignApi
} from '/@/api/recruit/recruitstudentsignup'
import { 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 { queryTeacherBaseByNo } from "/@/api/professional/professionaluser/teacherbase";
import { useDict } from '/@/hooks/dict'
import {
PUSHED_STATUS_LIST,
NOTICE_SEND_STATUS_LIST,
RECRUIT_MATERIAL_STATUS_LIST,
AUDIT_STATUS_LIST,
PAY_STATUS_LIST,
INTERVIEW_DIC_LIST,
NEW_CITY_MATERIAL_STATUS_LIST,
getStatusConfig
} 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 InterviewForm = defineAsyncComponent(() => import('/@/views/recruit/recruitstudentsignup/interviewForm.vue'))
const PayQrcodeDialog = defineAsyncComponent(() => import('./PayQrcodeDialog.vue'))
const AdmissionNoticeDialog = defineAsyncComponent(() => import('./AdmissionNoticeDialog.vue'))
const ActionDropdown = defineAsyncComponent(() => import('/@/components/tools/action-dropdown.vue'))
const ImportRecruitInfo = defineAsyncComponent(() => import('/@/views/recruit/common/import-recruit-info.vue'));
const ImportRecruitInfoRef=ref<any>();
const { hasAuth } = useAuth()
// 消息提示 hooks
const message = useMessage()
const messageBox = useMessageBox()
// 表格引用
const tableRef = ref()
const searchFormRef = ref()
const addOrUpdateRef = ref()
const majorChangeRef = ref()
const updateRef = ref()
const interviewFormRef = ref()
const payQrcodeDialogRef = 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 planList = ref<any[]>([])
const eduList = ref<any[]>([])
const planMajorList = ref<any[]>([])
const deptList = ref<any[]>([])
const teacherList = ref<any[]>([])
const cityExamTypeList = ref<any[]>([]) // 市平台考试类型
// 字典数据
const { yes_no_type } = useDict('yes_no_type')
// 静态数据
const paystatusList = PAY_STATUS_LIST
// 面试结果
const interviewDicList = INTERVIEW_DIC_LIST
// 录取状态
const auditStatusList = AUDIT_STATUS_LIST
// 资料审核状态
const zlshList = RECRUIT_MATERIAL_STATUS_LIST
// 证书发放状态
const isBackTzList = NOTICE_SEND_STATUS_LIST
// 推送状态
const pushedList = PUSHED_STATUS_LIST
// 新市民材料上传状态
const newCityMaterialList = NEW_CITY_MATERIAL_STATUS_LIST
// 来源
const isOutList = ref<any[]>([])
// 日期格式化
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)
}
}
// 下载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()
})
}
// 导出Excel
const exportExcel = (form: any, url: string) => {
return axios({
method: 'post',
url: url,
data: form,
responseType: 'blob',
headers: {
'Content-Type': 'application/json'
}
})
}
// 导出
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 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, dataForm.groupId)
}
// 新增 / 修改
const addOrUpdateHandle = (id?: string, type?: number) => {
nextTick(() => {
// 新增时默认 type=1可编辑查看时 type=0只读审核时 type=1可编辑
addOrUpdateRef.value?.init(id || null, type)
})
}
// 编辑
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,force:booleam) => {
var str=force?"强制":"";
messageBox.confirm('是否确认'+str+'办理退档操作?请谨慎操作').then(() => {
return leaveSchool({ id, groupId, feeAgency ,force})
}).then(() => {
message.success('操作成功')
getDataList()
})
}
// 复学
const reEntry = (id: string) => {
messageBox.confirm('是否确认复学操作?请谨慎操作').then(() => {
return resetSignApi({ id })
}).then(() => {
message.success('操作成功')
getDataList()
})
}
// 重置表单
const resetForm = (formName: string) => {
if (formName === 'searchForm') {
searchFormRef.value?.formRef?.resetFields()
}
}
// 录取通知书
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 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: () => hasAuth('recruit_recruitstudentsignup_edit')
},
{
command: 'interview',
label: '面试',
icon: Check,
visible: () => hasAuth('recruit_recruitstudentsignup_interview') && row.canInterview
},
{
command: 'audit',
label: '审核',
icon: DocumentChecked,
visible: () => hasAuth('recruit_recruitstudentsignup_edit') && row.canExam
},
{
command: 'leaveSchool',
label: '退档',
icon: Close,
visible: () => hasAuth('recruit_recruitstudentsignup_leaveSchool') && row.canQuit
},
{
command: 'forceLeaveSchool',
label: '强制退档',
icon: Close,
visible: () => hasAuth('recruit_leaveSchool_force') && row.canQuit
},
// 复学
{
command: 'reEntry',
label: '复学',
icon: Check,
visible: () => hasAuth('recruit_resetsign') && row.canReset
},
{
command: 'majorChange',
label: '调整专业',
icon: Switch,
visible: () => hasAuth('recruit_recruitstudentsignup_change') && row.canChangeMajor
},
{
command: 'payQrcode',
label: '支付二维码',
icon: Tickets,
visible: () => hasAuth('recruit_recruitstudentsignup_show') && row.canPayQrcode
},
{
command: 'rePush',
label: '重新推送',
icon: Check,
visible: () => hasAuth('recruit_recruitstudentsignup_rePush') && row.rePush
},
{
command: 'admissionNotice',
label: '录取通知书',
icon: Document,
visible: () => hasAuth('recruit_recruitstudentsignup_show') && row.canPrintReport
},
{
command: 'infoTable',
label: '信息表',
icon: Document,
visible: () => hasAuth('recruit_recruitstudentsignup_show') && row.canShowInfo
},
// {
// command: 'pushCity',
// label: '推送市局',
// icon: Upload,
// visible: () => hasAuth('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,false)
break
case 'forceLeaveSchool':
handleUpdate(row.id, row.groupId, row.feeAgency, true)
break
case 'reEntry':
reEntry(row.id)
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()
}
})
// 批量获取字典数据
getDictsByTypes([
'finance_student_source', // 文化程度
'recruit_city_exam_type', // 市平台考试类型
'recruit_data_source' // 数据来源
]).then((res) => {
eduList.value = res.data.finance_student_source || []
cityExamTypeList.value = res.data.recruit_city_exam_type || []
isOutList.value = res.data.recruit_data_source || []
})
}
// 监听招生计划变化
watch(() => dataForm.groupId, () => {
if (dataForm.groupId) {
chanMajor()
}
})
const handleImportDialog = () => {
ImportRecruitInfoRef.value?.init("R10003");
};
const exportLoading=ref(false);
const handleSyncData=()=>{
exportLoading.value=true;
setTimeout(() => {
exportLoading.value=false;
message.success('同步成功');
}, 3000);
}
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);
}
}
// 时间样式
.time-text {
font-size: 13px;
}
// 面试详情弹窗样式
.interview-detail-popover {
.detail-title {
font-size: 14px;
font-weight: 600;
color: #303133;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #EBEEF5;
}
.detail-section {
margin-bottom: 16px;
&:last-child {
margin-bottom: 0;
}
&.horizontal {
display: flex;
align-items: center;
gap: 12px;
}
.section-label {
font-size: 13px;
color: #606266;
font-weight: 500;
margin-bottom: 8px;
flex-shrink: 0;
.horizontal & {
margin-bottom: 0;
}
}
.section-content {
font-size: 13px;
color: #303133;
&.reason-content {
display: flex;
align-items: flex-start;
gap: 6px;
padding: 8px 12px;
background-color: #fff7e6;
border-radius: 4px;
border-left: 3px solid #ff9900;
.reason-icon {
color: #ff9900;
font-size: 14px;
margin-top: 2px;
flex-shrink: 0;
}
span {
color: #ff9900;
line-height: 1.6;
word-break: break-all;
}
}
}
.tag-icon {
margin-right: 4px;
}
}
}
// 证书发放/发放人样式
.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-compact {
.status-wrapper {
display: inline-flex;
align-items: center;
}
}
// Popover详情样式
.material-detail-popover {
.detail-title {
font-size: 14px;
font-weight: 600;
color: #303133;
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #EBEEF5;
}
.detail-section {
margin-bottom: 16px;
&:last-child {
margin-bottom: 0;
}
// 横向布局
&.horizontal {
display: flex;
align-items: center;
gap: 12px;
.section-label {
margin-bottom: 0;
white-space: nowrap;
}
.section-content {
flex: 1;
}
}
.section-label {
font-size: 12px;
color: #909399;
margin-bottom: 8px;
font-weight: 500;
}
:deep(.el-tag) {
.tag-icon {
font-size: 12px;
}
}
}
.material-list {
display: flex;
flex-direction: column;
gap: 8px;
.material-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
padding: 6px 10px;
border-radius: 4px;
&.warning {
background-color: #fef0f0;
color: #f56c6c;
.el-icon {
color: #f56c6c;
}
}
&.success {
background-color: #f0f9ff;
color: #67c23a;
.el-icon {
color: #67c23a;
}
}
.el-icon {
font-size: 14px;
}
}
}
.remark-box {
display: flex;
align-items: flex-start;
gap: 8px;
padding: 12px;
background-color: #fef0f0;
border-radius: 4px;
border-left: 3px solid #f56c6c;
.remark-icon {
color: #f56c6c;
font-size: 16px;
flex-shrink: 0;
margin-top: 1px;
}
.remark-text {
color: #f56c6c;
font-size: 13px;
line-height: 1.6;
word-break: break-all;
flex: 1;
}
}
}
</style>