Files
school-developer/src/views/recruit/backSchoolCheckin/statistics.vue
吴红兵 b997b3ba48 fix
2026-03-07 12:35:45 +08:00

244 lines
6.9 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="hasAuth('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 { useAuth } from '/@/hooks/auth';
import { useMessage } from '/@/hooks/message';
import { getDataStatistics } from '/@/api/recruit/newstucheckin';
import { getList } from '/@/api/recruit/recruitstudentplangroup';
import { getDeptList } from '/@/api/basic/basicclass';
import { queryAllClass } from '/@/api/basic/basicclass';
import axios from 'axios';
const { hasAuth } = useAuth();
// 消息提示 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 queryAllClass();
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>