| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- <template>
- <div class="p-4">
- <!-- 顶部信息区域 -->
- <el-card shadow="hover" class="mb-4">
- <div class="flex justify-between items-center">
- <div class="text-left">
- <h2 class="text-xl font-bold text-gray-800 mb-2">{{ projectName }} - {{ groupInfo.groupName }}</h2>
- <div class="grid grid-cols-3 gap-4 text-sm text-gray-600">
- <div><span class="font-medium"></span>{{ groupInfo.personNum }}人</div>
- <div><span class="font-medium">组数:</span>{{ groupInfo.includeGroupNum }}组</div>
- <div><span class="font-medium">道数:</span>{{ groupInfo.trackNum }}道</div>
- <div><span class="font-medium">开始时间:</span>{{ groupInfo.beginTime }}</div>
- <div><span class="font-medium">预计结束时间:</span>{{ groupInfo.endTime }}</div>
- <div><span class="font-medium">场地数量:</span>{{ groupInfo.fieldNum }}个</div>
- </div>
- </div>
- <div class="text-right">
- <el-button type="primary" @click="regenerateGroups" :loading="generating">重新生成分组</el-button>
- <el-button @click="goBack">返回</el-button>
- </div>
- </div>
- </el-card>
- <!-- 分组详情表格 -->
- <el-card shadow="hover">
- <template #header>
- <div class="flex justify-between items-center">
- <span class="font-medium">分组详情</span>
- <div class="text-sm text-gray-500">
- 共 {{ groupInfo.includeGroupNum }} 组,{{ groupInfo.trackNum }} 条道
- </div>
- </div>
- </template>
- <div class="overflow-x-auto">
- <table class="w-full border-collapse border border-gray-300">
- <!-- 表头 -->
- <thead>
- <tr class="bg-gray-100">
- <th class="border border-gray-300 px-4 py-2 text-center font-medium">组别</th>
- <th
- v-for="track in groupInfo.trackNum"
- :key="track"
- class="border border-gray-300 px-4 py-2 text-center font-medium"
- >
- 第{{ track }}道
- </th>
- </tr>
- </thead>
-
- <!-- 分组内容 -->
- <tbody>
- <tr
- v-for="groupIndex in groupInfo.includeGroupNum"
- :key="groupIndex"
- class="hover:bg-gray-50"
- >
- <td class="border border-gray-300 px-4 py-3 text-center font-medium bg-blue-50">
- 第{{ groupIndex }}组
- </td>
- <td
- v-for="track in groupInfo.trackNum"
- :key="track"
- class="border border-gray-300 px-4 py-3 text-center"
- >
- <div v-if="getAthleteByGroupAndTrack(groupIndex, track)" class="space-y-1">
- <div class="font-medium text-blue-600">{{ getAthleteByGroupAndTrack(groupIndex, track)?.athleteCode }}</div>
- <div class="text-sm">{{ getAthleteByGroupAndTrack(groupIndex, track)?.name }}</div>
- <div class="text-xs text-gray-500">{{ getAthleteByGroupAndTrack(groupIndex, track)?.teamName || getTeamName(getAthleteByGroupAndTrack(groupIndex, track)?.teamId) }}</div>
- </div>
- <div v-else class="text-gray-400 text-sm">-</div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </el-card>
- <!-- 统计信息 -->
- <el-card shadow="hover" class="mt-4">
- <template #header>
- <span class="font-medium">分组统计</span>
- </template>
-
- <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
- <div class="text-center p-3 bg-blue-50 rounded-lg">
- <div class="text-2xl font-bold text-blue-600">{{ totalAthletes }}</div>
- <div class="text-sm text-gray-600">符合条件的运动员数量</div>
- </div>
- <div class="text-center p-3 bg-green-50 rounded-lg">
- <div class="text-2xl font-bold text-green-600">{{ groupInfo.includeGroupNum }}</div>
- <div class="text-sm text-gray-600">分组数</div>
- </div>
- <div class="text-center p-3 bg-purple-50 rounded-lg">
- <div class="text-2xl font-bold text-purple-600">{{ groupInfo.trackNum }}</div>
- <div class="text-sm text-gray-600">道数</div>
- </div>
- <!-- <div class="text-center p-3 bg-orange-50 rounded-lg">
- <div class="text-2xl font-bold text-orange-600">{{ groupInfo.personNum }}</div>
- <div class="text-sm text-gray-600">{{ groupInfo.groupName }}人数</div>
- </div> -->
- <div class="text-center p-3 bg-orange-50 rounded-lg">
- <div class="text-2xl font-bold text-orange-600">{{ roundType }}</div>
- <div class="text-sm text-gray-600">录取人数</div>
- </div>
- </div>
- </el-card>
-
- </div>
- </template>
- <script setup name="GameEventGroupDetail" lang="ts">
- import { ref, onMounted, getCurrentInstance, onUpdated } from 'vue';
- import { useRoute, useRouter } from 'vue-router';
- import { getGameEventGroup, generateGroups, getGroupResultFromDB } from '@/api/system/gameEventGroup';
- import { getGameEventProject } from '@/api/system/gameEventProject';
- import { GameEventGroupVO } from '@/api/system/gameEventGroup/types';
- import type { ComponentInternalInstance } from 'vue';
- const route = useRoute();
- const router = useRouter();
- const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- // 分组信息
- const groupInfo = ref<GameEventGroupVO>({} as GameEventGroupVO);
- // 分组结果
- const groupResult = ref<Map<string, any>>(new Map());
- // 加载状态
- const loading = ref(false);
- // 生成分组状态
- const generating = ref(false);
- // 项目名称和录取人数
- const projectName = ref('');
- const roundType = ref(0);
- // 总运动员数
- const totalAthletes = ref(0);
- // 获取道次名称
- const getTrackName = (track: number) => {
- const trackNames = ['一', '二', '三', '四', '五', '六', '七', '八','九','十'];
- return trackNames[track - 1] || track;
- };
- // 根据组别和道次获取运动员
- const getAthleteByGroupAndTrack = (groupIndex: number, track: number) => {
- const key = `${groupIndex}-${track}`;
- return groupResult.value.get(key);
- };
- // 根据队伍ID获取队伍名称
- const getTeamName = (teamId: string | number | undefined) => {
- if (!groupResult.value.has('teams')) return '';
- const teams = groupResult.value.get('teams') || [];
- const team = teams.find((t: any) => t.teamId === teamId);
- return team?.teamName || '';
- };
- // 获取分组信息
- const getGroupInfo = async () => {
- try {
- loading.value = true;
- const groupId = route.params.groupId;
- if (!groupId || Array.isArray(groupId)) {
- proxy?.$modal.msgError('分组ID不能为空');
- return;
- }
-
- const res = await getGameEventGroup(groupId);
- groupInfo.value = res.data;
-
- // 优先从数据库读取分组数据
- await loadGroupResultFromDB();
- } catch (error) {
- console.error('获取分组信息失败:', error);
- proxy?.$modal.msgError('获取分组信息失败');
- } finally {
- loading.value = false;
- }
- };
- // 从数据库加载分组结果
- const loadGroupResultFromDB = async () => {
- try {
- const groupId = route.params.groupId;
- if (!groupId || Array.isArray(groupId)) {
- proxy?.$modal.msgError('分组ID不能为空');
- return;
- }
-
- const res = await getGroupResultFromDB(groupId);
- const data = res.data;
-
- if (data.success) {
- // 更新分组结果
- groupResult.value.clear();
-
- // 设置分组结果
- if (data.groupResult) {
- Object.entries(data.groupResult).forEach(([key, athlete]) => {
- groupResult.value.set(key, athlete);
- });
- }
-
- if (data.totalAthletes !== undefined) {
- totalAthletes.value = data.totalAthletes;
- }
-
- // 设置项目信息(从分组信息中获取)
- if (groupInfo.value.projectId) {
- // 获取项目详细信息
- try {
- const projectRes = await getGameEventProject(groupInfo.value.projectId);
- const projectInfo = projectRes.data;
- projectName.value = projectInfo.projectName;
- roundType.value = projectInfo.roundType ? parseInt(projectInfo.roundType) : 0;
- } catch (error) {
- console.error('获取项目信息失败:', error);
- projectName.value = '项目名称'; // 默认值
- roundType.value = 0; // 默认值
- }
- }
-
- console.log('从数据库加载分组结果成功');
- } else {
- // 数据库中没有数据,自动生成分组
- console.log('数据库中没有分组数据,自动生成分组');
- await generateGroupsData();
- }
- } catch (error) {
- console.error('从数据库加载分组结果失败:', error);
- // 加载失败时,自动生成分组
- await generateGroupsData();
- }
- };
- // 生成分组
- const generateGroupsData = async () => {
- try {
- generating.value = true;
-
- const groupId = route.params.groupId;
- if (!groupId || Array.isArray(groupId)) {
- proxy?.$modal.msgError('分组ID不能为空');
- return;
- }
-
- const res = await generateGroups(groupId);
- const data = res.data;
-
- if (data.success) {
- // 更新分组结果
- groupResult.value.clear();
-
- // 设置分组结果
- if (data.groupResult) {
- Object.entries(data.groupResult).forEach(([key, athlete]) => {
- groupResult.value.set(key, athlete);
- });
- }
-
- // 设置其他数据
- if (data.project) {
- projectName.value = data.project.projectName || '';
- roundType.value = data.project.roundType || 0;
- }
-
- if (data.totalAthletes !== undefined) {
- totalAthletes.value = data.totalAthletes;
- }
-
- // 设置队伍信息
- if (data.teams) {
- groupResult.value.set('teams', data.teams);
- }
-
- proxy?.$modal.msgSuccess('分组生成成功');
- } else {
- proxy?.$modal.msgWarning(data.message || '生成分组失败');
- }
- } catch (error) {
- console.error('生成分组失败:', error);
- proxy?.$modal.msgError('生成分组失败');
- } finally {
- generating.value = false;
- }
- };
- // 重新生成分组
- const regenerateGroups = async () => {
- await generateGroupsData();
- };
- // 返回上一页
- const goBack = () => {
- router.go(-1);
- };
- onUpdated(() => {
- getGroupInfo();
- });
- onMounted(() => {
- getGroupInfo();
- });
- </script>
- <style scoped>
- .overflow-x-auto {
- overflow-x: auto;
- }
- /* 响应式表格 */
- @media (max-width: 768px) {
- .grid {
- grid-template-columns: repeat(1, 1fr);
- }
-
- .overflow-x-auto {
- font-size: 12px;
- }
-
- .px-4 {
- padding-left: 8px;
- padding-right: 8px;
- }
-
- .py-3 {
- padding-top: 6px;
- padding-bottom: 6px;
- }
- }
- </style>
|