276 lines
7.7 KiB
Vue
276 lines
7.7 KiB
Vue
<!--
|
|
- 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="newstucheckin-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 { getList } 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 getList()
|
|
gradeList.value = data.data || []
|
|
} catch (error) {
|
|
console.error('获取入学年份失败', error)
|
|
}
|
|
}
|
|
|
|
// 查找所有二级学院
|
|
const getDeptData = async () => {
|
|
try {
|
|
const data = await getDeptList()
|
|
deptList.value = data.data || []
|
|
} catch (error) {
|
|
console.error('获取学院列表失败', error)
|
|
}
|
|
}
|
|
|
|
// 查找所有班级
|
|
const getClassData = async () => {
|
|
try {
|
|
const data = await getClasslist()
|
|
classData.value = data.data || []
|
|
} catch (error) {
|
|
console.error('获取班级列表失败', error)
|
|
}
|
|
}
|
|
|
|
// 获取数据列表
|
|
const getList = async () => {
|
|
try {
|
|
tableLoading.value = true
|
|
const response = await getDataStatistics(queryForm)
|
|
tableData.value = response.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>
|