fix: 修复赛事管理excel导出

This commit is contained in:
Shu Guang 2025-05-17 19:22:42 +08:00
parent 87d3ffdf39
commit 724731f52a

View File

@ -20,25 +20,28 @@
> >
<template #header> <template #header>
<a-button-group> <a-button-group>
<a-button type="primary" v-if="$store.state.user.userPrivileges!=2" @click="addRace"> <a-button
type="primary"
v-if="$store.state.user.userPrivileges != 2"
@click="addRace"
>
添加赛事 添加赛事
</a-button> </a-button>
<a-button type="primary" v-if="$store.state.user.userPrivileges==2" @click="addBao"> <a-button
type="primary"
v-if="$store.state.user.userPrivileges == 2"
@click="addBao"
>
我要报名 我要报名
</a-button> </a-button>
<a-button <a-button
v-if="$store.state.user.userPrivileges!=2" v-if="$store.state.user.userPrivileges != 2"
:disabled="!selectedKeys.length" :disabled="!selectedKeys.length"
@click="batchDelete" @click="batchDelete"
> >
批量删除 ({{ selectedKeys.length }}) 批量删除 ({{ selectedKeys.length }})
</a-button> </a-button>
<a-button <a-button :loading="exporting" @click="exportAll">
:loading="exporting"
@click="exportAll"
>
全量导出 全量导出
</a-button> </a-button>
</a-button-group> </a-button-group>
@ -47,18 +50,18 @@
<a-space> <a-space>
<!-- 成绩录入 --> <!-- 成绩录入 -->
<a-tooltip v-if="isStudent" title="无权限"> <a-tooltip v-if="isStudent" title="无权限">
<a> <a> 无权限 </a>
无权限
</a>
</a-tooltip> </a-tooltip>
<!--编辑--> <!--编辑-->
<a @click="editRace(record)" v-if="$store.state.user.userPrivileges!=2"> <a
@click="editRace(record)"
v-if="$store.state.user.userPrivileges != 2"
>
<a-icon type="edit" /> <a-icon type="edit" />
</a> </a>
<!--删除--> <!--删除-->
<a-popconfirm <a-popconfirm
v-if="$store.state.user.userPrivileges!=2" v-if="$store.state.user.userPrivileges != 2"
title="确认删除?" title="确认删除?"
placement="left" placement="left"
@confirm="deleteRace(record)" @confirm="deleteRace(record)"
@ -75,18 +78,19 @@
</template> </template>
<script> <script>
import { raceLevelMap, raceLevels,competitionStatus } from '@/utils/const'; import { raceLevelMap, raceLevels, competitionStatus } from "@/utils/const";
import { AllUser } from '@/api'; import { AllUser } from "@/api";
import { exportData } from '@/utils/excel'; import { exportData } from "@/utils/excel";
import EditRace from '@/components/edit/EditRace'; import EditRace from "@/components/edit/EditRace";
import Baoming from '@/components/edit/Baoming'; import Baoming from "@/components/edit/Baoming";
import AddRecord from '@/components/record/AddRecord'; import AddRecord from "@/components/record/AddRecord";
import dayjs from 'dayjs'; import dayjs from "dayjs";
import * as XLSX from "xlsx";
export default { export default {
name: 'Race', name: "Race",
metaInfo: { metaInfo: {
title: '赛事管理', title: "赛事管理",
}, },
data() { data() {
return { return {
@ -96,8 +100,8 @@ export default {
races: [], races: [],
users: [], // users: [], //
current: 1, current: 1,
originalRaces: [], originalRaces: [],
query:{}, query: {},
pageSize: 10, pageSize: 10,
total: 0, total: 0,
tableColumns: [], tableColumns: [],
@ -116,12 +120,14 @@ export default {
return this.$store.state.user.userPrivileges == 2; return this.$store.state.user.userPrivileges == 2;
}, },
}, },
async mounted() { async mounted() {
await this.getAllUsers(); // await this.getAllUsers(); //
this.$watch(() => [this.pageSize, this.current], this.getData, { immediate: true }); this.$watch(() => [this.pageSize, this.current], this.getData, {
immediate: true,
});
}, },
methods: { methods: {
async getAllUsers() { async getAllUsers() {
try { try {
const response = await AllUser(); const response = await AllUser();
this.users = response.data; this.users = response.data;
@ -129,89 +135,95 @@ export default {
} catch (error) { } catch (error) {
console.error("Failed to load users", error); console.error("Failed to load users", error);
} }
},createTableColumns(users) { },
const competitionStatusMap = [ createTableColumns(users) {
{ label: '进行中', value: 0 }, const competitionStatusMap = [
{ label: '已终止', value: 1 }, { label: "进行中", value: 0 },
]; { label: "已终止", value: 1 },
console.log(users) ];
return [ console.log(users);
return [
{ title: '赛事名称', dataIndex: 'competitionName', align: 'center' }, { title: "赛事名称", dataIndex: "competitionName", align: "center" },
{ {
title: '负责人', title: "负责人",
dataIndex: 'userId', dataIndex: "userId",
customRender: (text) => { customRender: (text) => {
if (!text) { if (!text) {
return '无'; return "无";
}
const user = users.find(u => u.userId === text);
return user ? user.userName : '无';
}, align: 'center'
},
{
title: '开始时间',
dataIndex: 'registrationStartTime',
customRender: (text, record) => formatDate(record.registrationStartTime)
, align: 'center'
},
{
title: '结束时间',
dataIndex: 'registrationEndTime',
customRender: (text, record) => formatDate(record.registrationEndTime)
, align: 'center'
},
{ title: '参考材料', dataIndex: 'announcementLink' , align: 'center'},
{
title: '状态',
dataIndex: 'competitionStatus',
customRender: (text, record) => {
const statusObject = competitionStatusMap.find(item => item.value === record.competitionStatus);
return statusObject ? statusObject.label : '未知状态';
} }
, align: 'center' const user = users.find((u) => u.userId === text);
return user ? user.userName : "无";
},
align: "center",
}, },
{ {
title: '操作', title: "开始时间",
align: 'center', dataIndex: "registrationStartTime",
scopedSlots: { customRender: (text, record) =>
customRender: 'action', formatDate(record.registrationStartTime),
}, align: "center",
}, },
]; {
},createSearchOptions() { title: "结束时间",
return [ dataIndex: "registrationEndTime",
{ customRender: (text, record) =>
label: '赛事名称', formatDate(record.registrationEndTime),
key: 'title', align: "center",
default: '', },
component: 'input', { title: "参考材料", dataIndex: "announcementLink", align: "center" },
}, {
{ title: "状态",
label: '负责人', dataIndex: "competitionStatus",
key: 'sponsor', customRender: (text, record) => {
default: '', const statusObject = competitionStatusMap.find(
component: 'input', (item) => item.value === record.competitionStatus
}, );
{ return statusObject ? statusObject.label : "未知状态";
label: '状态', },
key: 'collageId', align: "center",
default: undefined, },
component: 'select', {
props: { title: "操作",
options: competitionStatus, align: "center",
}, scopedSlots: {
customRender: "action",
},
},
];
}, },
createSearchOptions() {
return [
{
label: "赛事名称",
key: "title",
default: "",
component: "input",
},
{
label: "负责人",
key: "sponsor",
default: "",
component: "input",
},
{
label: "状态",
key: "collageId",
default: undefined,
component: "select",
props: {
options: competitionStatus,
},
},
{ {
label: '时间', label: "时间",
key: 'date', key: "date",
default: () => [], default: () => [],
mapper: ({ date }) => date.join('~'), mapper: ({ date }) => date.join("~"),
component: 'range-picker', component: "range-picker",
},
];
}, },
];
},
changePage({ pageSize, current }) { changePage({ pageSize, current }) {
Object.assign(this, { pageSize, current }); Object.assign(this, { pageSize, current });
}, },
@ -220,194 +232,263 @@ export default {
this.getData(); this.getData();
}, },
getData() { getData() {
this.query = this.$refs.searchForm.getResult(); this.query = this.$refs.searchForm.getResult();
console.log(this.query) console.log(this.query);
this.loading = true; this.loading = true;
this.$api.AllCompetition({ this.$api
}).then(data => { .AllCompetition({})
this.originalRaces = data.data; .then((data) => {
this.filterRaces(); // this.originalRaces = data.data;
this.total = data.data.length; this.filterRaces(); //
}).catch(e => { this.total = data.data.length;
console.error(e); })
this.$message.error(e.msg || '获取数据失败'); .catch((e) => {
}).finally(() => { console.error(e);
this.loading = false; this.$message.error(e.msg || "获取数据失败");
}); })
.finally(() => {
this.loading = false;
});
}, },
// //
filterRaces() { filterRaces() {
let filteredRaces = this.originalRaces.slice(); // let filteredRaces = this.originalRaces.slice(); //
console.log(filteredRaces) console.log(filteredRaces);
// //
if (this.query.collageId) { if (this.query.collageId) {
filteredRaces = filteredRaces.filter(user => user.competitionStatus == this.query.collageId); filteredRaces = filteredRaces.filter(
} (user) => user.competitionStatus == this.query.collageId
// );
if (this.query.title) { }
filteredRaces = filteredRaces.filter(user => user.competitionName.includes(this.query.title)); //
} if (this.query.title) {
// filteredRaces = filteredRaces.filter((user) =>
if (this.query.sponsor) { user.competitionName.includes(this.query.title)
filteredRaces = filteredRaces.filter(user => user.userName.includes(this.query.sponsor)); );
} }
//
if (this.query.sponsor) {
filteredRaces = filteredRaces.filter((user) =>
user.userName.includes(this.query.sponsor)
);
}
this.races = filteredRaces;
this.races = filteredRaces; },
}, //
//
addBao() { addBao() {
let vnode; let vnode;
this.$confirm({ this.$confirm({
title: '我要报名', title: "我要报名",
content: h => (vnode = <Baoming />), content: (h) => (vnode = <Baoming />),
onOk: async () => { onOk: async () => {
const values = await vnode.componentInstance.validate(); const values = await vnode.componentInstance.validate();
const data = { const data = {
studentId: this.$store.state.user.userId, studentId: this.$store.state.user.userId,
competitionId: values.competitionId, competitionId: values.competitionId,
teamLeaderId: values.teamLeaderId, teamLeaderId: values.teamLeaderId,
competitionType: values.competitionType, competitionType: values.competitionType,
registrationTime: dayjs(new Date).format('YYYY-M-D HH:mm:ss'), registrationTime: dayjs(new Date()).format("YYYY-M-D HH:mm:ss"),
registrationStatus: '等待学校审核', registrationStatus: "等待学校审核",
}; };
console.log(data) console.log(data);
return this.$api.Enroll(data).then(data => { return this.$api
this.$message.success("报名成功"); .Enroll(data)
}).catch(e => { .then((data) => {
this.$message.error(e.msg || '报名失败'); this.$message.success("报名成功");
throw e; })
}); .catch((e) => {
this.$message.error(e.msg || "报名失败");
throw e;
});
}, },
}); });
}, },
// //
addRace() { addRace() {
let vnode; let vnode;
this.$confirm({ this.$confirm({
title: '新增赛事', title: "新增赛事",
content: h => (vnode = <EditRace />), content: (h) => (vnode = <EditRace />),
onOk: async () => { onOk: async () => {
const values = await vnode.componentInstance.validate(); const values = await vnode.componentInstance.validate();
const data = { const data = {
competitionName: values.competitionName, competitionName: values.competitionName,
userId: values.userId, userId: values.userId,
registrationStartTime: values.registrationStartTime, registrationStartTime: values.registrationStartTime,
registrationEndTime: values.registrationEndTime, registrationEndTime: values.registrationEndTime,
announcementLink: values.announcementLink, announcementLink: values.announcementLink,
competitionStatus: values.competitionStatus, competitionStatus: values.competitionStatus,
}; };
return this.$api.AddCompetition(data).then(data => { return this.$api
this.$message.success("添加成功"); .AddCompetition(data)
this.getData(); .then((data) => {
}).catch(e => { this.$message.success("添加成功");
this.$message.error(e.msg || '添加失败'); this.getData();
throw e; })
}); .catch((e) => {
this.$message.error(e.msg || "添加失败");
throw e;
});
}, },
}); });
},// }, //
formatDateTime(isoDateTime) { formatDateTime(isoDateTime) {
const date = new Date(isoDateTime); const date = new Date(isoDateTime);
const formattedDateTime = `${date.getFullYear()}-${this.padZero(date.getMonth() + 1)}-${this.padZero(date.getDate())} ${this.padZero(date.getHours())}:${this.padZero(date.getMinutes())}:${this.padZero(date.getSeconds())}`; const formattedDateTime = `${date.getFullYear()}-${this.padZero(
return formattedDateTime; date.getMonth() + 1
}, )}-${this.padZero(date.getDate())} ${this.padZero(
// date.getHours()
padZero(num) { )}:${this.padZero(date.getMinutes())}:${this.padZero(date.getSeconds())}`;
return num < 10 ? '0' + num : num; return formattedDateTime;
}, },
// //
padZero(num) {
return num < 10 ? "0" + num : num;
},
//
editRace(race) { editRace(race) {
let vnode; let vnode;
this.$confirm({ this.$confirm({
title: '编辑赛事', title: "编辑赛事",
content: h => (vnode = <EditRace data={race} />), content: (h) => (vnode = <EditRace data={race} />),
onOk: async () => { onOk: async () => {
const values = await vnode.componentInstance.validate(); const values = await vnode.componentInstance.validate();
// formatDateTime // formatDateTime
values.registrationStartTime = this.formatDateTime(values.registrationStartTime); values.registrationStartTime = this.formatDateTime(
values.registrationEndTime = this.formatDateTime(values.registrationEndTime); values.registrationStartTime
);
values.registrationEndTime = this.formatDateTime(
values.registrationEndTime
);
values.competitionId = race.competitionId; values.competitionId = race.competitionId;
const data = { const data = {
competitionId: values.competitionId, competitionId: values.competitionId,
competitionName: values.competitionName, competitionName: values.competitionName,
userId: values.userId, userId: values.userId,
registrationStartTime: values.registrationStartTime, registrationStartTime: values.registrationStartTime,
registrationEndTime: values.registrationEndTime, registrationEndTime: values.registrationEndTime,
announcementLink: values.announcementLink, announcementLink: values.announcementLink,
competitionStatus: values.competitionStatus, competitionStatus: values.competitionStatus,
}; };
return this.$api.UpCompetition(data).then(data => { return this.$api
this.$message.success('修改成功'); .UpCompetition(data)
this.getData(); .then((data) => {
}).catch(e => { this.$message.success("修改成功");
this.$message.error(e.msg || '修改失败'); this.getData();
throw e; })
}); .catch((e) => {
this.$message.error(e.msg || "修改失败");
throw e;
});
}, },
}); });
}, },
// //
deleteRace(race) { deleteRace(race) {
this.loading = true; this.loading = true;
this.$api.DeleteCompetition([race.competitionId]).then(data => { this.$api
this.$message.success(data.msg); .DeleteCompetition([race.competitionId])
this.getData(); .then((data) => {
}).catch(e => { this.$message.success(data.msg);
console.error(e); this.getData();
this.$message.error(e.msg || '删除失败'); })
}).finally(() => { .catch((e) => {
this.loading = false; console.error(e);
}); this.$message.error(e.msg || "删除失败");
})
.finally(() => {
this.loading = false;
});
}, },
batchDelete() { batchDelete() {
this.$modal.confirm({ this.$modal.confirm({
title: `确认删除选中的${this.selectedKeys.length}项数据?`, title: `确认删除选中的${this.selectedKeys.length}项数据?`,
onOk: () => this.$api.deleteRace(this.selectedKeys) onOk: () =>
.then(() => { this.$api
this.$message.success('删除成功!'); .deleteRace(this.selectedKeys)
this.selectedKeys.splice(0); .then(() => {
this.getData(); this.$message.success("删除成功!");
}).catch(e => { this.selectedKeys.splice(0);
this.$message.error(e.msg || '删除失败!'); this.getData();
throw e; })
}), .catch((e) => {
this.$message.error(e.msg || "删除失败!");
throw e;
}),
}); });
}, },
addRecord(race) { addRecord(race) {
let vnode; let vnode;
this.$confirm({ this.$confirm({
title: '成绩录入', title: "成绩录入",
content: h => (vnode = <AddRecord />), content: (h) => (vnode = <AddRecord />),
onOk: async () => { onOk: async () => {
const form = vnode.componentInstance; const form = vnode.componentInstance;
const values = await form.validate(); const values = await form.validate();
return this.$api.addRecord({ return this.$api
race_id: race.race_id, .addRecord({
sid: this.$store.state.user.account, race_id: race.race_id,
score: values.score, sid: this.$store.state.user.account,
tid: values.tid, score: values.score,
}).then(data => { tid: values.tid,
this.$message.success(data.msg); })
}).catch(e => { .then((data) => {
this.$message.error(e.msg || '系统错误'); this.$message.success(data.msg);
throw e; })
}); .catch((e) => {
this.$message.error(e.msg || "系统错误");
throw e;
});
}, },
}); });
}, },
exportAll() { // script
this.exporting = true;
this.$api.AllCompetition(this.query).then(data => { // methods exportAll
return exportExcel(data.data); async exportAll() {
}).catch(e => { try {
console.error(e); this.exporting = true;
this.$message.error(e.msg || '导出失败'); const response = await this.$api.AllCompetition();
}).finally(() => {
if (response.code === 200 && response.data) {
//
const exportData = response.data.map((item) => {
const user = this.users.find((u) => u.userId === item.userId);
return {
赛事名称: item.competitionName,
负责人: user ? user.userName : "未知",
开始时间: this.formatDateTime(item.registrationStartTime),
结束时间: this.formatDateTime(item.registrationEndTime),
参考材料: item.announcementLink,
状态: item.competitionStatus === 0 ? "进行中" : "已终止",
报名人数: item.registrationCount || "0",
};
});
// 簿
const wb = XLSX.utils.book_new();
//
const ws = XLSX.utils.json_to_sheet(exportData);
// 簿
XLSX.utils.book_append_sheet(wb, ws, "赛事信息");
//
XLSX.writeFile(wb, `赛事信息表-${dayjs().format("YYYY-MM-DD")}.xlsx`);
this.$message.success("导出成功");
} else {
this.$message.error("导出失败:没有数据");
}
} catch (error) {
console.error("导出失败:", error);
this.$message.error("导出失败:" + (error.message || "系统错误"));
} finally {
this.exporting = false; this.exporting = false;
}); }
}, },
// exportExcel
}, },
}; };
@ -416,26 +497,26 @@ function formatDate(dateString) {
const date = new Date(dateString); const date = new Date(dateString);
if (isNaN(date.getTime())) { if (isNaN(date.getTime())) {
console.error(`Invalid date: ${dateString}`); console.error(`Invalid date: ${dateString}`);
return 'Invalid Date'; return "Invalid Date";
} }
const year = date.getFullYear(); const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, '0'); const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`; return `${year}-${month}-${day}`;
} }
function exportExcel(data) { function exportExcel(data) {
const header = this.createTableColumns().map(v => v.title); const header = this.createTableColumns().map((v) => v.title);
header.pop(); // header.pop(); //
return exportData({ return exportData({
name: '赛事信息', name: "赛事信息",
data, data,
header, header,
keyMap: { keyMap: {
competitionName: '赛事名称', competitionName: "赛事名称",
userId: '主办方', userId: "主办方",
announcementLink: '参考资料', announcementLink: "参考资料",
registrationStartTime: '开始时间', registrationStartTime: "开始时间",
registrationEndTime: '结束时间', registrationEndTime: "结束时间",
}, },
}); });
} }