招生
This commit is contained in:
57
src/views/recruit/backSchoolCheckin/index.vue
Normal file
57
src/views/recruit/backSchoolCheckin/index.vue
Normal file
@@ -0,0 +1,57 @@
|
||||
<!--
|
||||
- Copyright (c) 2018-2025, cyweb All rights reserved.
|
||||
-
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions are met:
|
||||
-
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
- this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in the
|
||||
- documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of the pig4cloud.com developer nor the names of its
|
||||
- contributors may be used to endorse or promote products derived from
|
||||
- this software without specific prior written permission.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-tabs v-model="activeName" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="回校列表" name="tab">
|
||||
<tab-index ref="tabIndexRef" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="回校统计" name="static">
|
||||
<static-index ref="staticIndexRef" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="backSchool">
|
||||
import { ref, nextTick, defineAsyncComponent } from 'vue'
|
||||
|
||||
const TabIndex = defineAsyncComponent(() => import('./tabIndex.vue'))
|
||||
const StaticIndex = defineAsyncComponent(() => import('./staticIndex.vue'))
|
||||
|
||||
const activeName = ref('tab')
|
||||
const tabIndexRef = ref()
|
||||
const staticIndexRef = ref()
|
||||
|
||||
const handleTabClick = (tab: any) => {
|
||||
if (tab.paneName == 'tab') {
|
||||
nextTick(() => {
|
||||
tabIndexRef.value?.init()
|
||||
})
|
||||
} else {
|
||||
nextTick(() => {
|
||||
staticIndexRef.value?.init()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
170
src/views/recruit/backSchoolCheckin/staticIndex.vue
Normal file
170
src/views/recruit/backSchoolCheckin/staticIndex.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
<!--
|
||||
- Copyright (c) 2018-2025, cyweb All rights reserved.
|
||||
-
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions are met:
|
||||
-
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
- this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in the
|
||||
- documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of the pig4cloud.com developer nor the names of its
|
||||
- contributors may be used to endorse or promote products derived from
|
||||
- this software without specific prior written permission.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<el-form :model="queryForm" inline class="mb-4" ref="searchFormRef">
|
||||
<el-form-item label="招生计划" prop="groupId">
|
||||
<el-select v-model="queryForm.groupId" filterable clearable placeholder="请选择招生计划" @change="getTabStaticDataList" style="width: 150px;">
|
||||
<el-option
|
||||
v-for="item in planList"
|
||||
:key="item.id"
|
||||
:label="item.groupName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="getTabStaticDataList">查询</el-button>
|
||||
<el-button type="primary" plain icon="Refresh" class="ml10" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="tableData"
|
||||
v-loading="dataListLoading"
|
||||
border
|
||||
stripe
|
||||
show-summary
|
||||
:summary-method="getSummaries"
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
>
|
||||
<el-table-column prop="groupId" label="招生计划" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getPlanName(scope.row.groupId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="zymc" label="专业名称" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="wlx" label="未联系" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="yjbd" label="已经报到" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="tcbd" label="推迟报到" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="fqbd" label="放弃报到" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="fwlx" label="无法联系" align="center" show-overflow-tooltip />
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="backSchoolCheckinStaticIndex">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
||||
import { getTabStaticDataList as getTabStaticDataListApi } from '/@/api/recruit/recruitstudentsignup'
|
||||
// @ts-ignore
|
||||
import global from '@/components/tools/commondict'
|
||||
import { useTable } from '/@/hooks/table'
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
const searchFormRef = ref()
|
||||
|
||||
// 数据
|
||||
const planList = ref<any[]>([])
|
||||
const tableData = ref<any[]>([])
|
||||
const dataListLoading = ref(false)
|
||||
|
||||
// 查询表单
|
||||
const queryForm = reactive({
|
||||
groupId: ''
|
||||
})
|
||||
|
||||
// 获取计划名称
|
||||
const getPlanName = (groupId: string) => {
|
||||
const item = planList.value.find(item => item.id === groupId)
|
||||
return item ? item.groupName : ''
|
||||
}
|
||||
|
||||
// 表格样式
|
||||
const { tableStyle } = useTable({ queryForm: queryForm, pageList: async () => ({ data: { records: [], total: 0 } }), createdIsNeed: false })
|
||||
|
||||
// 获取汇总数据
|
||||
const getSummaries = (param: any) => {
|
||||
const { columns, data } = param
|
||||
const sums: any[] = []
|
||||
columns.forEach((column: any, index: number) => {
|
||||
if (index === 0) {
|
||||
sums[index] = '总计'
|
||||
} else if (index != 1) {
|
||||
const values = data.map((item: any) => Number(item[column.property]))
|
||||
if (!values.every((value: any) => isNaN(value))) {
|
||||
sums[index] = values.reduce((prev: number, curr: number) => {
|
||||
const value = Number(curr)
|
||||
if (!isNaN(value)) {
|
||||
return prev + curr
|
||||
} else {
|
||||
return prev
|
||||
}
|
||||
}, 0)
|
||||
} else {
|
||||
sums[index] = '--'
|
||||
}
|
||||
} else {
|
||||
sums[index] = '--'
|
||||
}
|
||||
})
|
||||
return sums
|
||||
}
|
||||
|
||||
// 获取统计数据
|
||||
const getTabStaticDataList = async () => {
|
||||
try {
|
||||
tableData.value = []
|
||||
dataListLoading.value = true
|
||||
const response = await getTabStaticDataListApi(queryForm)
|
||||
tableData.value = response.data.data || []
|
||||
} catch (error) {
|
||||
console.error('获取统计数据失败', error)
|
||||
} finally {
|
||||
dataListLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
const resetQuery = () => {
|
||||
searchFormRef.value?.resetFields()
|
||||
queryForm.groupId = ''
|
||||
if (planList.value.length > 0) {
|
||||
queryForm.groupId = planList.value[0].id
|
||||
}
|
||||
getTabStaticDataList()
|
||||
}
|
||||
|
||||
// 初始化
|
||||
const init = async () => {
|
||||
try {
|
||||
const data = await list()
|
||||
planList.value = data.data.data || []
|
||||
if (planList.value.length > 0) {
|
||||
queryForm.groupId = planList.value[0].id
|
||||
getTabStaticDataList()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
275
src/views/recruit/backSchoolCheckin/statistics.vue
Normal file
275
src/views/recruit/backSchoolCheckin/statistics.vue
Normal file
@@ -0,0 +1,275 @@
|
||||
<!--
|
||||
- Copyright (c) 2018-2025, cyweb All rights reserved.
|
||||
-
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions are met:
|
||||
-
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
- this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in the
|
||||
- documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of the pig4cloud.com developer nor the names of its
|
||||
- contributors may be used to endorse or promote products derived from
|
||||
- this software without specific prior written permission.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-form :model="queryForm" inline class="mb-4" ref="searchFormRef">
|
||||
<el-form-item label="入学年份" prop="grade">
|
||||
<el-select v-model="queryForm.grade" filterable clearable placeholder="请选择入学年份">
|
||||
<el-option
|
||||
v-for="item in gradeList"
|
||||
:key="item.year"
|
||||
:label="item.year"
|
||||
:value="item.year"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学院" prop="deptCode">
|
||||
<el-select v-model="queryForm.deptCode" filterable clearable placeholder="请选择学院">
|
||||
<el-option
|
||||
v-for="item in deptList"
|
||||
:key="item.deptCode"
|
||||
:label="item.deptName"
|
||||
:value="item.deptCode"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="班级" prop="classCode">
|
||||
<el-select v-model="queryForm.classCode" filterable clearable placeholder="请选择班级">
|
||||
<el-option
|
||||
v-for="item in classData"
|
||||
:key="item.classCode"
|
||||
:label="item.classNo"
|
||||
:value="item.classCode"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="searchData">查询</el-button>
|
||||
<el-button type="primary" plain icon="Refresh" class="ml10" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="mb15">
|
||||
<el-button
|
||||
v-if="permissions.recruit_newstucheckin_statistics_output"
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
:loading="exportLoading"
|
||||
@click="handleExportOut"
|
||||
>
|
||||
导出
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="tableData"
|
||||
height="650"
|
||||
show-summary
|
||||
:summary-method="getSummaries"
|
||||
stripe
|
||||
border
|
||||
v-loading="tableLoading"
|
||||
:header-cell-style="{ 'text-align': 'center' }"
|
||||
:cell-style="{ 'text-align': 'center' }"
|
||||
class="el_table_job_fair_stu"
|
||||
>
|
||||
<el-table-column type="index" width="50" fixed label="序号" />
|
||||
<el-table-column prop="deptName" label="学院" />
|
||||
<el-table-column prop="classNo" label="班级" />
|
||||
<el-table-column prop="classNum" label="预计报到人数" />
|
||||
<el-table-column prop="checkInOk" label="已经报到" />
|
||||
<el-table-column prop="postpone" label="推迟报到" />
|
||||
<el-table-column prop="abandon" label="放弃报到" />
|
||||
<el-table-column prop="missing" label="无法联系" />
|
||||
<el-table-column prop="contact" label="未联系" />
|
||||
<el-table-column prop="checkInRate" label="报到率" />
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="backSchoolCheckin-statistics">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { getDataStatistics } from '/@/api/recruit/newstucheckin'
|
||||
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
||||
import { getDeptList } from '/@/api/basic/basicclass'
|
||||
import { getClasslist } from '/@/api/stuwork/stupunlish'
|
||||
import axios from 'axios'
|
||||
|
||||
// 使用 Pinia store
|
||||
const userInfoStore = useUserInfo()
|
||||
const { userInfos } = storeToRefs(userInfoStore)
|
||||
|
||||
// 创建权限对象
|
||||
const permissions = computed(() => {
|
||||
const perms: Record<string, boolean> = {}
|
||||
userInfos.value.authBtnList.forEach((perm: string) => {
|
||||
perms[perm] = true
|
||||
})
|
||||
return perms
|
||||
})
|
||||
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
|
||||
// 引用
|
||||
const searchFormRef = ref()
|
||||
|
||||
// 状态
|
||||
const tableData = ref<any[]>([])
|
||||
const tableLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
const gradeList = ref<any[]>([])
|
||||
const deptList = ref<any[]>([])
|
||||
const classData = ref<any[]>([])
|
||||
|
||||
// 查询表单
|
||||
const queryForm = reactive({
|
||||
grade: '',
|
||||
deptCode: '',
|
||||
classCode: ''
|
||||
})
|
||||
|
||||
// 初始化
|
||||
const init = async () => {
|
||||
await Promise.all([
|
||||
getGradeData(),
|
||||
getDeptData(),
|
||||
getClassData()
|
||||
])
|
||||
getList()
|
||||
}
|
||||
|
||||
// 查看所有入学年份
|
||||
const getGradeData = async () => {
|
||||
try {
|
||||
const data = await list()
|
||||
gradeList.value = data.data.data || []
|
||||
} catch (error) {
|
||||
console.error('获取入学年份失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 查找所有二级学院
|
||||
const getDeptData = async () => {
|
||||
try {
|
||||
const data = await getDeptList()
|
||||
deptList.value = data.data.data || []
|
||||
} catch (error) {
|
||||
console.error('获取学院列表失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 查找所有班级
|
||||
const getClassData = async () => {
|
||||
try {
|
||||
const data = await getClasslist()
|
||||
classData.value = data.data.data || []
|
||||
} catch (error) {
|
||||
console.error('获取班级列表失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据列表
|
||||
const getList = async () => {
|
||||
try {
|
||||
tableLoading.value = true
|
||||
const response = await getDataStatistics(queryForm)
|
||||
tableData.value = response.data.data || []
|
||||
} catch (error) {
|
||||
console.error('获取数据失败', error)
|
||||
} finally {
|
||||
tableLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 查询
|
||||
const searchData = () => {
|
||||
getList()
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
const resetQuery = () => {
|
||||
searchFormRef.value?.resetFields()
|
||||
queryForm.grade = ''
|
||||
queryForm.deptCode = ''
|
||||
queryForm.classCode = ''
|
||||
getList()
|
||||
}
|
||||
|
||||
// 导出
|
||||
const handleExportOut = async () => {
|
||||
try {
|
||||
exportLoading.value = true
|
||||
const res = await axios({
|
||||
method: 'post',
|
||||
url: '/recruit/newstucheckin/exportDataStatistics',
|
||||
data: queryForm,
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
const blob = new Blob([res.data])
|
||||
const fileName = '新生报到统计.xls'
|
||||
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 (error: any) {
|
||||
message.error(error.msg || '导出失败')
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 合计方法
|
||||
const getSummaries = (param: any) => {
|
||||
const { columns, data } = param
|
||||
const sums: any[] = []
|
||||
columns.forEach((column: any, index: number) => {
|
||||
if (index === 0) {
|
||||
sums[index] = '合计'
|
||||
return
|
||||
}
|
||||
if (index === 1 || index === 2) {
|
||||
sums[index] = ''
|
||||
return
|
||||
}
|
||||
const values = data.map((item: any) => Number(item[column.property]))
|
||||
if (!values.every((value: any) => isNaN(value))) {
|
||||
sums[index] = values.reduce((prev: number, curr: any) => {
|
||||
const value = Number(curr)
|
||||
if (!isNaN(value)) {
|
||||
return prev + curr
|
||||
} else {
|
||||
return prev
|
||||
}
|
||||
}, 0)
|
||||
sums[index] += ''
|
||||
}
|
||||
})
|
||||
return sums
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
159
src/views/recruit/backSchoolCheckin/stu-check-in.vue
Normal file
159
src/views/recruit/backSchoolCheckin/stu-check-in.vue
Normal file
@@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog v-model="newStuCheckInDialog" width="40%">
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input v-model="form.name" disabled style="width: 80%" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="性别" prop="gender">
|
||||
<el-select v-model="form.gender" placeholder="请选择性别" disabled style="width: 80%">
|
||||
<el-option
|
||||
v-for="item in genderData"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="身份证号" prop="idNumber">
|
||||
<el-input v-model="form.idNumber" disabled style="width: 80%" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="报到状态" prop="backSchoolState">
|
||||
<el-select v-model="form.backSchoolState" filterable placeholder="请选择报到状态" style="width: 80%">
|
||||
<el-option
|
||||
v-for="item in checkInStatusData"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="回校备注" prop="backSchoolRemark">
|
||||
<el-input v-model="form.backSchoolRemark" :rows="2" style="width: 80%" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="checkIn" :loading="submitLoading">确定</el-button>
|
||||
<el-button @click="newStuCheckInDialog = false">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="backSchoolCheckin-stu-check-in">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { useDict } from '/@/hooks/dict'
|
||||
import { putBackObj } from '/@/api/recruit/recruitstudentsignup'
|
||||
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
|
||||
// 字典
|
||||
const { getTypeValue } = useDict()
|
||||
|
||||
// 定义 emits
|
||||
const emit = defineEmits(['reload'])
|
||||
|
||||
// 引用
|
||||
const formRef = ref()
|
||||
|
||||
// 状态
|
||||
const newStuCheckInDialog = ref(false)
|
||||
const checkInStatusData = ref<any[]>([])
|
||||
const submitLoading = ref(false)
|
||||
const page = ref<any>({})
|
||||
|
||||
// 固定数据
|
||||
const genderData = [
|
||||
{ label: '女', value: '2' },
|
||||
{ label: '男', value: '1' }
|
||||
]
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
id: '',
|
||||
name: '',
|
||||
backSchoolState: '',
|
||||
gender: '',
|
||||
idNumber: '',
|
||||
backSchoolRemark: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
name: [
|
||||
{ required: true, message: '请输入姓名', trigger: ['blur', 'change'] }
|
||||
],
|
||||
gender: [
|
||||
{ required: true, message: '请输入性别', trigger: ['blur', 'change'] }
|
||||
],
|
||||
idNumber: [
|
||||
{ required: true, message: '请输入身份证号', trigger: ['blur', 'change'] }
|
||||
],
|
||||
backSchoolState: [
|
||||
{ required: true, message: '请输入报到状态', trigger: ['blur', 'change'] }
|
||||
]
|
||||
})
|
||||
|
||||
// 初始化表单
|
||||
const initForm = () => {
|
||||
form.id = ''
|
||||
form.name = ''
|
||||
form.backSchoolState = ''
|
||||
form.gender = ''
|
||||
form.idNumber = ''
|
||||
form.backSchoolRemark = ''
|
||||
}
|
||||
|
||||
// 初始化
|
||||
const init = async (formData: any, pageData: any) => {
|
||||
initForm()
|
||||
page.value = pageData
|
||||
submitLoading.value = false
|
||||
newStuCheckInDialog.value = true
|
||||
checkInStatusData.value = []
|
||||
|
||||
try {
|
||||
const data = await getTypeValue('check_in_status')
|
||||
checkInStatusData.value = data.data.data || []
|
||||
} catch (error) {
|
||||
console.error('获取字典数据失败', error)
|
||||
}
|
||||
|
||||
Object.assign(form, formData)
|
||||
}
|
||||
|
||||
// 报到
|
||||
const checkIn = async () => {
|
||||
if (!formRef.value) return
|
||||
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
submitLoading.value = true
|
||||
await putBackObj(form)
|
||||
message.success('报到成功')
|
||||
emit('reload')
|
||||
newStuCheckInDialog.value = false
|
||||
} catch (error: any) {
|
||||
if (error !== false) {
|
||||
message.error(error.msg || '报到失败')
|
||||
}
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
547
src/views/recruit/backSchoolCheckin/tabIndex.vue
Normal file
547
src/views/recruit/backSchoolCheckin/tabIndex.vue
Normal file
@@ -0,0 +1,547 @@
|
||||
<!--
|
||||
- Copyright (c) 2018-2025, cyweb All rights reserved.
|
||||
-
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions are met:
|
||||
-
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
- this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in the
|
||||
- documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of the pig4cloud.com developer nor the names of its
|
||||
- contributors may be used to endorse or promote products derived from
|
||||
- this software without specific prior written permission.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<el-form :model="queryForm" inline class="mb-4" ref="searchFormRef">
|
||||
<el-form-item label="招生计划" prop="groupId">
|
||||
<el-select v-model="queryForm.groupId" filterable clearable placeholder="请选择招生计划" @change="chanMajor" style="width: 150px;">
|
||||
<el-option
|
||||
v-for="item in planList"
|
||||
:key="item.id"
|
||||
:label="item.groupName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="学院" prop="xy">
|
||||
<el-select v-model="queryForm.xy" filterable clearable placeholder="请选择学院" style="width: 130px;">
|
||||
<el-option
|
||||
v-for="item in deptList"
|
||||
:key="item.deptCode"
|
||||
:label="item.deptName"
|
||||
:value="item.deptCode"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="录取专业" prop="confirmedMajor">
|
||||
<el-select v-model="queryForm.confirmedMajor" filterable clearable placeholder="请选择录取专业">
|
||||
<el-option
|
||||
v-for="item in planMajorList"
|
||||
:key="item.zydm"
|
||||
:label="item.zymc + '(' + item.xz + '年制)'"
|
||||
:value="item.zydm"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="唯一号/姓名/身份证号/学校名称" prop="search">
|
||||
<el-input v-model="queryForm.search" clearable placeholder="唯一号/姓名/身份证号/学校名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="缴费状态" prop="paystatus">
|
||||
<el-select v-model="queryForm.paystatus" filterable clearable placeholder="请选择缴费状态" style="width: 120px;">
|
||||
<el-option
|
||||
v-for="item in paystatusList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="推送状态" prop="pushed">
|
||||
<el-select v-model="queryForm.pushed" filterable clearable placeholder="请选择推送状态" style="width: 120px;">
|
||||
<el-option
|
||||
v-for="item in pushedList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="报到状态" prop="backSchoolState">
|
||||
<el-select v-model="queryForm.backSchoolState" filterable clearable placeholder="请选择报到状态" style="width: 120px;">
|
||||
<el-option
|
||||
v-for="item in backSchoolStateList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
|
||||
<el-button type="primary" plain icon="Refresh" class="ml10" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mb15">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
>
|
||||
名单导出
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="permissions.recruit_recruitstudentsignup_allCX"
|
||||
type="success"
|
||||
plain
|
||||
icon="Search"
|
||||
class="ml10"
|
||||
@click="updateAllFS"
|
||||
>
|
||||
批量查询
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
stripe
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
<el-table-column label="操作" width="200" align="center" fixed="left">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="permissions.recruit_recruitstudentsignup_show && scope.row.pushed == '1' && scope.row.paiedOffline != '10' && (scope.row.clfPayCode != undefined && scope.row.clfPayCode != '')"
|
||||
type="primary"
|
||||
link
|
||||
icon="QrCode"
|
||||
@click="showPayCode(scope.row)"
|
||||
>
|
||||
支付二维码
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="permissions.recruit_recruitstudentsignup_back"
|
||||
type="success"
|
||||
link
|
||||
icon="CircleCheck"
|
||||
@click="handleCheckIn(scope.row)"
|
||||
>
|
||||
报到
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="serialNumber" label="唯一号" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="xy" label="学院" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.auditStatus == 20">
|
||||
{{ getDeptName(scope.row.xy) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="confirmedMajor" label="录取专业" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.auditStatus == 20">
|
||||
{{ getMajorName(scope.row.confirmedMajor) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="姓名" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="gender" label="性别" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getGender(scope.row.gender) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="idNumber" label="身份证号" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="parentTelOne" label="家长电话1" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="parentTelTwo" label="家长电话2" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="backSchoolState" label="报到状态" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getBackSchoolStateLabel(scope.row.backSchoolState) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="backSchoolRemark" label="报到备注" align="center" show-overflow-tooltip />
|
||||
<el-table-column prop="paiedOffline" label="缴费状态" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getStatus(scope.row.paiedOffline) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="pushed" label="推送状态" align="center" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.pushed == 0" style="color: red">{{ getPushed(scope.row.pushed) }}</span>
|
||||
<span v-if="scope.row.pushed == 1" style="color: green">{{ getPushed(scope.row.pushed) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<pagination
|
||||
v-bind="state.pagination"
|
||||
@current-change="currentChangeHandle"
|
||||
@size-change="sizeChangeHandle"
|
||||
/>
|
||||
|
||||
<!-- 支付二维码弹窗 -->
|
||||
<el-dialog v-model="dialogFormVisible" title="支付二维码" width="800px" @close="dialogFormVisible = false">
|
||||
<el-table :data="tableData" border>
|
||||
<el-table-column label="唯一号" prop="serialNumber" align="center" />
|
||||
<el-table-column label="姓名" prop="name" align="center" />
|
||||
<el-table-column label="家长手机号" prop="parentTelOne" align="center" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" icon="Search" @click="updateFS">立即查询</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="padding-top: 20px;">
|
||||
<div id="payQrcode1" style="display: inline-block;">
|
||||
{{ payQrcode1Msg }}
|
||||
</div>
|
||||
<!-- <vue-qr :text="payQrcode1" :size="200" v-if="showPrise1" style="display: inline-block"></vue-qr> -->
|
||||
|
||||
<div id="payQrcode2" style="display: inline-block">
|
||||
{{ payQrcode2Msg }}
|
||||
</div>
|
||||
<!-- <vue-qr :text="payQrcode2" :size="200" v-if="showPrise2" style="display: inline-block"></vue-qr> -->
|
||||
|
||||
<div id="payQrcode3" style="display: inline-block">
|
||||
{{ payQrcode3Msg }}
|
||||
</div>
|
||||
<!-- <vue-qr :text="payQrcode3" :size="200" v-if="showPrise3" style="display: inline-block"></vue-qr> -->
|
||||
</div>
|
||||
<span style="color: red;padding-top: 20px;">** 此界面为查询学生缴款二维码,如有收不到微信推送,或手机号填错的,可直接在此扫码支付,支付成功后,请手动点击"立即查询"按钮,查询该生的缴费情况;因财政收费系统有一定的滞后性,如点击"立即查询"后任显示未交费,请稍后再继续查询,或重新点击"立即查询"按钮 **</span>
|
||||
</el-dialog>
|
||||
|
||||
<stu-check-in ref="stuCheckInRef" @reload="refreshChange" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="backSchoolCheckinTabIndex">
|
||||
import { ref, reactive, computed, onMounted, nextTick, defineAsyncComponent } from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import { BasicTableProps, useTable } from '/@/hooks/table'
|
||||
import { useMessage, useMessageBox } from '/@/hooks/message'
|
||||
import { list } from '/@/api/recruit/recruitstudentplangroup'
|
||||
import { backPush, backSchoolStuPage, batchPushAll } from '/@/api/recruit/recruitstudentsignup'
|
||||
import { getDeptList } from '/@/api/basic/basicclass'
|
||||
import { list as planMajor } from '/@/api/recruit/recruitplanmajor'
|
||||
import { updateFs, updateAllFS } from '/@/api/finance/financenormalstu'
|
||||
import { getTypeValue } from '/@/api/admin/dict'
|
||||
// @ts-ignore
|
||||
import global from '@/components/tools/commondict'
|
||||
|
||||
const StuCheckIn = defineAsyncComponent(() => import('./stu-check-in.vue'))
|
||||
|
||||
// 使用 Pinia store
|
||||
const userInfoStore = useUserInfo()
|
||||
const { userInfos } = storeToRefs(userInfoStore)
|
||||
|
||||
// 创建权限对象
|
||||
const permissions = computed(() => {
|
||||
const perms: Record<string, boolean> = {}
|
||||
userInfos.value.authBtnList.forEach((perm: string) => {
|
||||
perms[perm] = true
|
||||
})
|
||||
return perms
|
||||
})
|
||||
|
||||
// 消息提示 hooks
|
||||
const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
const searchFormRef = ref()
|
||||
const stuCheckInRef = ref()
|
||||
|
||||
// 数据
|
||||
const planList = ref<any[]>([])
|
||||
const planMajorList = ref<any[]>([])
|
||||
const deptList = ref<any[]>([])
|
||||
const backSchoolStateList = ref<any[]>([])
|
||||
const paystatusList = ref([{ label: '已缴费', value: '10' }, { label: '未缴费', value: '0' }, { label: '部分缴费', value: '5' }])
|
||||
const pushedList = ref([{ label: '未推送', value: '0' }, { label: '已推送', value: '1' }])
|
||||
|
||||
// 查询表单
|
||||
const queryForm = reactive({
|
||||
groupId: '',
|
||||
xy: '',
|
||||
confirmedMajor: '',
|
||||
search: '',
|
||||
paystatus: '',
|
||||
pushed: '',
|
||||
backSchoolState: '',
|
||||
isOut: '1',
|
||||
auditStatus: '20'
|
||||
})
|
||||
|
||||
// 弹窗状态
|
||||
const dialogFormVisible = ref(false)
|
||||
const tableData = ref<any[]>([])
|
||||
const payQrcode1 = ref('')
|
||||
const showPrise1 = ref(false)
|
||||
const payQrcode1Msg = ref('')
|
||||
const payQrcode2 = ref('')
|
||||
const payQrcode2Msg = ref('')
|
||||
const showPrise2 = ref(false)
|
||||
const payQrcode3 = ref('')
|
||||
const payQrcode3Msg = ref('')
|
||||
const showPrise3 = ref(false)
|
||||
|
||||
// 获取学院名称
|
||||
const getDeptName = (deptCode: string) => {
|
||||
const item = deptList.value.find(item => item.deptCode === deptCode)
|
||||
return item ? item.deptName : ''
|
||||
}
|
||||
|
||||
// 获取专业名称
|
||||
const getMajorName = (majorCode: string) => {
|
||||
const item = planMajorList.value.find(item => item.zydm === majorCode)
|
||||
return item ? item.zymc : ''
|
||||
}
|
||||
|
||||
// 获取性别
|
||||
const getGender = (gender: string) => {
|
||||
if (gender == '2') {
|
||||
return '女'
|
||||
}
|
||||
if (gender == '1') {
|
||||
return '男'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
// 获取报到状态标签
|
||||
const getBackSchoolStateLabel = (value: string) => {
|
||||
const item = backSchoolStateList.value.find(item => item.value === value)
|
||||
return item ? item.label : ''
|
||||
}
|
||||
|
||||
// 获取缴费状态
|
||||
const getStatus = (type: string) => {
|
||||
if (type == '0') {
|
||||
return '未缴费'
|
||||
} else if (type == '5') {
|
||||
return '部分缴费'
|
||||
} else if (type == '10') {
|
||||
return '已缴费'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
// 获取推送状态
|
||||
const getPushed = (type: string) => {
|
||||
if (type == '0') {
|
||||
return '未推送'
|
||||
} else if (type == '1') {
|
||||
return '已推送'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
// 表格状态
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: queryForm,
|
||||
pageList: async (params: any) => {
|
||||
const response = await backSchoolStuPage(params)
|
||||
return {
|
||||
data: {
|
||||
records: response.data.data.records,
|
||||
total: response.data.data.total
|
||||
}
|
||||
}
|
||||
},
|
||||
createdIsNeed: false
|
||||
})
|
||||
|
||||
// 使用 table hook
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle, downBlobFile } = useTable(state)
|
||||
|
||||
// 招生计划改变
|
||||
const chanMajor = async () => {
|
||||
if (queryForm.groupId) {
|
||||
await getMajorList(queryForm.groupId)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取专业列表
|
||||
const getMajorList = async (groupId: string) => {
|
||||
try {
|
||||
const data = await planMajor({ groupId })
|
||||
planMajorList.value = data.data.data || []
|
||||
} catch (error) {
|
||||
console.error('获取专业列表失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
const init = async () => {
|
||||
try {
|
||||
// 查询报到状态字典
|
||||
const dictData = await getTypeValue('check_in_status')
|
||||
backSchoolStateList.value = dictData.data.data || []
|
||||
|
||||
// 查询二级学院信息
|
||||
const deptData = await getDeptList()
|
||||
deptList.value = deptData.data.data || []
|
||||
|
||||
// 获取招生计划列表
|
||||
const planData = await list()
|
||||
planList.value = planData.data.data || []
|
||||
if (planList.value.length > 0) {
|
||||
queryForm.groupId = planList.value[0].id
|
||||
await getMajorList(queryForm.groupId)
|
||||
}
|
||||
|
||||
getDataList()
|
||||
} catch (error) {
|
||||
console.error('初始化失败', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 打开报到窗口
|
||||
const handleCheckIn = (row: any) => {
|
||||
nextTick(() => {
|
||||
stuCheckInRef.value?.init(row, state.pagination.current)
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新回调
|
||||
const refreshChange = () => {
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 批量查询
|
||||
const updateAllFS = async () => {
|
||||
if (!queryForm.groupId) {
|
||||
message.warning('招生计划不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const plan = planList.value.find(e => e.id === queryForm.groupId)
|
||||
if (!plan) return
|
||||
|
||||
const data = await updateAllFS({ year: plan.year, stuSource: '1' })
|
||||
if (data.data.code == '200') {
|
||||
message.success('正在更新所有缴费单状态,请稍后查看更新结果')
|
||||
}
|
||||
} catch (error: any) {
|
||||
message.error(error.msg || '操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 导出
|
||||
const handleExport = async () => {
|
||||
if (!queryForm.groupId) {
|
||||
message.warning('招生计划不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await downBlobFile(
|
||||
'/recruit/recruitstudentsignup/exportBackData',
|
||||
queryForm,
|
||||
'招生名单导出.xls'
|
||||
)
|
||||
} catch (error: any) {
|
||||
message.error(error.msg || '导出失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 立即查询
|
||||
const updateFS = async () => {
|
||||
if (tableData.value.length === 0) return
|
||||
|
||||
try {
|
||||
const serialNumber = tableData.value[0].serialNumber.substring(1, tableData.value[0].serialNumber.length)
|
||||
await updateFs({ serialNumber })
|
||||
message.success('已提交查询请求,请等待1分钟后重新查询')
|
||||
dialogFormVisible.value = false
|
||||
getDataList()
|
||||
} catch (error: any) {
|
||||
message.error(error.msg || '查询失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 显示支付二维码
|
||||
const showPayCode = (row: any) => {
|
||||
showPrise1.value = false
|
||||
showPrise2.value = false
|
||||
showPrise3.value = false
|
||||
|
||||
payQrcode1.value = ''
|
||||
payQrcode2.value = ''
|
||||
payQrcode3.value = ''
|
||||
|
||||
if (row.clfPayCode && row.clfPayCode != '') {
|
||||
payQrcode1Msg.value = '材料费、代办费'
|
||||
showPrise1.value = true
|
||||
payQrcode1.value = 'https://jscz.govpay.ccb.com/online/fsjf?PyF_BillNo=' + row.clfPayCode + '&Verf_CD=blank&Admn_Rgon_Cd=320400'
|
||||
} else {
|
||||
payQrcode1Msg.value = ''
|
||||
showPrise1.value = false
|
||||
}
|
||||
|
||||
if (row.xfPayCode && row.xfPayCode != '') {
|
||||
payQrcode2Msg.value = '学费'
|
||||
showPrise2.value = true
|
||||
payQrcode2.value = 'https://jscz.govpay.ccb.com/online/fsjf?PyF_BillNo=' + row.xfPayCode + '&Verf_CD=blank&Admn_Rgon_Cd=320400'
|
||||
} else {
|
||||
payQrcode2Msg.value = ''
|
||||
showPrise2.value = false
|
||||
}
|
||||
|
||||
if (row.zdbPayCode && row.zdbPayCode != '') {
|
||||
payQrcode3Msg.value = '中德班学费'
|
||||
showPrise3.value = true
|
||||
payQrcode3.value = 'https://jscz.govpay.ccb.com/online/fsjf?PyF_BillNo=' + row.zdbPayCode + '&Verf_CD=blank&Admn_Rgon_Cd=320400'
|
||||
} else {
|
||||
payQrcode3Msg.value = ''
|
||||
showPrise3.value = false
|
||||
}
|
||||
|
||||
tableData.value = [row]
|
||||
dialogFormVisible.value = true
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
const resetQuery = () => {
|
||||
searchFormRef.value?.resetFields()
|
||||
queryForm.groupId = ''
|
||||
queryForm.xy = ''
|
||||
queryForm.confirmedMajor = ''
|
||||
queryForm.search = ''
|
||||
queryForm.paystatus = ''
|
||||
queryForm.pushed = ''
|
||||
queryForm.backSchoolState = ''
|
||||
queryForm.isOut = '1'
|
||||
queryForm.auditStatus = '20'
|
||||
if (planList.value.length > 0) {
|
||||
queryForm.groupId = planList.value[0].id
|
||||
}
|
||||
getDataList()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user