|
|
|
|
@ -75,6 +75,10 @@
|
|
|
|
|
<el-option label="已支付" value="paid" />
|
|
|
|
|
<el-option label="待支付" value="submitted" />
|
|
|
|
|
</el-select>
|
|
|
|
|
<el-select v-model="filterPeriod" placeholder="报名期次" clearable style="width: 200px;">
|
|
|
|
|
<el-option label="第一期 5月22-24日" value="第一期 5月22-24日" />
|
|
|
|
|
<el-option label="第二期 6月12-14日" value="第二期 6月12-14日" />
|
|
|
|
|
</el-select>
|
|
|
|
|
<el-button type="primary" icon="Search" @click="handleSearch">搜索</el-button>
|
|
|
|
|
<el-button icon="Refresh" @click="refreshData">刷新</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
@ -83,19 +87,30 @@
|
|
|
|
|
<div class="admin-table-card">
|
|
|
|
|
<div class="table-header">
|
|
|
|
|
<h3>报名信息列表</h3>
|
|
|
|
|
<el-button type="success" icon="Download" @click="exportData">
|
|
|
|
|
导出数据
|
|
|
|
|
</el-button>
|
|
|
|
|
<div class="table-header-actions">
|
|
|
|
|
<span v-if="multipleSelection.length > 0" class="selection-info">
|
|
|
|
|
已选择 {{ multipleSelection.length }} 项
|
|
|
|
|
</span>
|
|
|
|
|
<el-button type="success" icon="Download" @click="exportData">
|
|
|
|
|
导出数据{{ multipleSelection.length > 0 ? `(${multipleSelection.length}条)` : '' }}
|
|
|
|
|
</el-button>
|
|
|
|
|
<el-button type="warning" icon="Download" @click="exportAllData" :loading="exportAllLoading">
|
|
|
|
|
全部导出
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<el-table
|
|
|
|
|
ref="tableRef"
|
|
|
|
|
:data="filteredData"
|
|
|
|
|
stripe
|
|
|
|
|
border
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
v-loading="loading"
|
|
|
|
|
:header-cell-style="{ background: '#f5f7fa', color: '#303133', fontWeight: '600' }"
|
|
|
|
|
@selection-change="handleSelectionChange"
|
|
|
|
|
>
|
|
|
|
|
<el-table-column type="selection" width="50" align="center" />
|
|
|
|
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
|
|
|
|
<el-table-column prop="id" label="报名编号" width="140" align="center">
|
|
|
|
|
<template #default="{ row }">
|
|
|
|
|
@ -208,18 +223,22 @@
|
|
|
|
|
import { ref, reactive, computed, onMounted } from 'vue'
|
|
|
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
|
|
import { getRegistrationList, getRegistrationStatistics, updateRegistrationStatus, getRegistrationDetail } from '../../api/registration'
|
|
|
|
|
import { getRegistrationList, getRegistrationStatistics, updateRegistrationStatus, getRegistrationDetail, getAllRegistrations } from '../../api/registration'
|
|
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
// 数据
|
|
|
|
|
const loading = ref(false)
|
|
|
|
|
const searchKeyword = ref('')
|
|
|
|
|
const filterStatus = ref('')
|
|
|
|
|
const filterPeriod = ref('')
|
|
|
|
|
const currentPage = ref(1)
|
|
|
|
|
const pageSize = ref(10)
|
|
|
|
|
const total = ref(0)
|
|
|
|
|
const detailDialogVisible = ref(false)
|
|
|
|
|
const currentDetail = ref(null)
|
|
|
|
|
const tableRef = ref(null)
|
|
|
|
|
const multipleSelection = ref([])
|
|
|
|
|
const exportAllLoading = ref(false)
|
|
|
|
|
|
|
|
|
|
// 管理员信息
|
|
|
|
|
const adminUser = reactive({
|
|
|
|
|
@ -250,7 +269,8 @@ const loadData = async () => {
|
|
|
|
|
keyword: searchKeyword.value,
|
|
|
|
|
pageNum: currentPage.value,
|
|
|
|
|
pageSize: pageSize.value,
|
|
|
|
|
status: filterStatus.value
|
|
|
|
|
status: filterStatus.value,
|
|
|
|
|
period: filterPeriod.value
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 映射接口字段
|
|
|
|
|
@ -377,14 +397,63 @@ const editStatus = (row) => {
|
|
|
|
|
}).catch(() => {})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 表格勾选
|
|
|
|
|
const handleSelectionChange = (val) => {
|
|
|
|
|
multipleSelection.value = val
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 全部导出
|
|
|
|
|
const exportAllData = async () => {
|
|
|
|
|
exportAllLoading.value = true
|
|
|
|
|
try {
|
|
|
|
|
const res = await getAllRegistrations()
|
|
|
|
|
const list = res.data.map(item => ({
|
|
|
|
|
报名编号: item.bmId,
|
|
|
|
|
姓名: item.name,
|
|
|
|
|
所在单位: item.company,
|
|
|
|
|
推荐人: item.referrer,
|
|
|
|
|
推荐人单位: item.referrerCompany,
|
|
|
|
|
部门: item.department || '',
|
|
|
|
|
职务: item.title,
|
|
|
|
|
手机号: item.phone,
|
|
|
|
|
邮箱: item.email,
|
|
|
|
|
身份证号: item.idCard,
|
|
|
|
|
期次: item.period,
|
|
|
|
|
金额: item.fee,
|
|
|
|
|
状态: item.status === 'paid' ? '已支付' : '待支付',
|
|
|
|
|
报名时间: formatTime(item.submitTime),
|
|
|
|
|
备注: item.remark || ''
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
const headers = Object.keys(list[0]).join(',')
|
|
|
|
|
const rows = list.map(item => Object.values(item).join(','))
|
|
|
|
|
const csv = [headers, ...rows].join('\n')
|
|
|
|
|
|
|
|
|
|
const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8' })
|
|
|
|
|
const url = URL.createObjectURL(blob)
|
|
|
|
|
const link = document.createElement('a')
|
|
|
|
|
link.href = url
|
|
|
|
|
link.download = `报名数据(全部)_${new Date().toLocaleDateString()}.csv`
|
|
|
|
|
link.click()
|
|
|
|
|
URL.revokeObjectURL(url)
|
|
|
|
|
|
|
|
|
|
ElMessage.success(`全部导出成功,共${list.length}条数据!`)
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('全部导出失败', e)
|
|
|
|
|
ElMessage.error('导出失败,请重试')
|
|
|
|
|
}
|
|
|
|
|
exportAllLoading.value = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 导出数据
|
|
|
|
|
const exportData = () => {
|
|
|
|
|
if (allData.value.length === 0) {
|
|
|
|
|
const exportList = multipleSelection.value.length > 0 ? multipleSelection.value : allData.value
|
|
|
|
|
if (exportList.length === 0) {
|
|
|
|
|
ElMessage.warning('暂无数据可导出')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const exportData = allData.value.map(item => ({
|
|
|
|
|
const exportRows = exportList.map(item => ({
|
|
|
|
|
报名编号: item.id,
|
|
|
|
|
姓名: item.name,
|
|
|
|
|
所在单位: item.organization,
|
|
|
|
|
@ -403,8 +472,8 @@ const exportData = () => {
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
// 简单导出为CSV
|
|
|
|
|
const headers = Object.keys(exportData[0]).join(',')
|
|
|
|
|
const rows = exportData.map(item => Object.values(item).join(','))
|
|
|
|
|
const headers = Object.keys(exportRows[0]).join(',')
|
|
|
|
|
const rows = exportRows.map(item => Object.values(item).join(','))
|
|
|
|
|
const csv = [headers, ...rows].join('\n')
|
|
|
|
|
|
|
|
|
|
const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8' })
|
|
|
|
|
@ -571,6 +640,18 @@ onMounted(() => {
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.table-header-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.selection-info {
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
color: var(--primary-color);
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.table-header h3 {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|