|
@@ -61,91 +61,95 @@
|
|
|
</template>
|
|
|
|
|
|
<el-table v-loading="loading" border :data="gameEventList" @selection-change="handleSelectionChange">
|
|
|
- <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
|
|
|
+ <el-table-column type="selection" width="55" align="center" />
|
|
|
+ <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="left" width="220">
|
|
|
<template #default="scope">
|
|
|
<div class="operation-buttons">
|
|
|
- <el-tooltip content="修改" placement="top">
|
|
|
- <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:gameEvent:edit']">
|
|
|
- <span class="button-text">修改</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
- <!-- 删除操作 -->
|
|
|
- <el-tooltip :content="getDeleteTooltip(scope.row)" placement="top">
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="danger"
|
|
|
- icon="Delete"
|
|
|
- :disabled="!canDelete(scope.row)"
|
|
|
- @click="handleDelete(scope.row)"
|
|
|
- v-hasPermi="['system:event:remove']"
|
|
|
- >
|
|
|
- <span class="button-text">删除</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
- <!-- 下载模板 -->
|
|
|
- <el-tooltip content="下载报名信息模板" placement="top">
|
|
|
- <el-button link type="warning" icon="Download" @click="handleDownloadTemplate(scope.row)">
|
|
|
- <span class="button-text">下载</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
- <!-- 导入报名信息 -->
|
|
|
- <el-tooltip content="导入报名信息" placement="top">
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="info"
|
|
|
- icon="FolderOpened"
|
|
|
- @click="handleImportRegistration(scope.row)"
|
|
|
- v-hasPermi="['system:gameEvent:import']"
|
|
|
- >
|
|
|
- <span class="button-text">导入</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
- <!-- 添加参赛者 -->
|
|
|
- <el-tooltip content="添加参赛者" placement="top">
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="success"
|
|
|
- icon="User"
|
|
|
- @click="handleAddParticipant(scope.row)"
|
|
|
- v-hasPermi="['system:gameEvent:addParticipant']"
|
|
|
- >
|
|
|
- <span class="button-text">参赛者</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
- <!-- 添加裁判 -->
|
|
|
- <el-tooltip content="添加裁判" placement="top">
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="primary"
|
|
|
- icon="Avatar"
|
|
|
- @click="handleAddReferee(scope.row)"
|
|
|
- v-hasPermi="['system:gameEvent:addReferee']"
|
|
|
- >
|
|
|
- <span class="button-text">裁判</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
- <!-- 预览按钮 -->
|
|
|
- <el-tooltip content="预览" placement="top">
|
|
|
- <el-button link type="info" icon="View" @click="handlePreview(scope.row)" v-hasPermi="['system:gameEvent:view']">
|
|
|
- <span class="button-text">预览</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
- <!-- 比赛数据按钮 -->
|
|
|
- <el-tooltip content="比赛排行榜" placement="top">
|
|
|
- <el-button
|
|
|
- link
|
|
|
- type="warning"
|
|
|
- icon="DataAnalysis"
|
|
|
- @click="handleGameData(scope.row)"
|
|
|
- v-hasPermi="['system:gameEvent:gameData']"
|
|
|
- >
|
|
|
- <span class="button-text">排行榜</span>
|
|
|
- </el-button>
|
|
|
- </el-tooltip>
|
|
|
+ <!-- 第一行:基本操作 -->
|
|
|
+ <div class="button-row">
|
|
|
+ <el-tooltip content="修改" placement="top">
|
|
|
+ <el-button link type="primary" icon="Edit" size="small" @click="handleUpdate(scope.row)" v-hasPermi="['system:gameEvent:edit']"></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-tooltip :content="getDeleteTooltip(scope.row)" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="danger"
|
|
|
+ icon="Delete"
|
|
|
+ size="small"
|
|
|
+ :disabled="!canDelete(scope.row)"
|
|
|
+ @click="handleDelete(scope.row)"
|
|
|
+ v-hasPermi="['system:event:remove']"
|
|
|
+ ></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-tooltip content="预览" placement="top">
|
|
|
+ <el-button link type="primary" icon="View" size="small" @click="handlePreview(scope.row)" v-hasPermi="['system:gameEvent:view']"></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-tooltip content="比赛数据" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="success"
|
|
|
+ icon="DataAnalysis"
|
|
|
+ size="small"
|
|
|
+ @click="handleGameData(scope.row)"
|
|
|
+ v-hasPermi="['system:gameEvent:gameData']"
|
|
|
+ ></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 第二行:管理操作 -->
|
|
|
+ <div class="button-row">
|
|
|
+ <el-tooltip content="下载模板" placement="top">
|
|
|
+ <el-button link type="info" icon="Download" size="small" @click="handleDownloadTemplate(scope.row)"></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-tooltip content="导入报名" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="warning"
|
|
|
+ icon="FolderOpened"
|
|
|
+ size="small"
|
|
|
+ @click="handleImportRegistration(scope.row)"
|
|
|
+ v-hasPermi="['system:gameEvent:import']"
|
|
|
+ ></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-tooltip content="添加参赛者" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="primary"
|
|
|
+ icon="User"
|
|
|
+ size="small"
|
|
|
+ @click="handleAddParticipant(scope.row)"
|
|
|
+ v-hasPermi="['system:gameEvent:addParticipant']"
|
|
|
+ ></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ <el-tooltip content="添加裁判" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="primary"
|
|
|
+ icon="Avatar"
|
|
|
+ size="small"
|
|
|
+ @click="handleAddReferee(scope.row)"
|
|
|
+ v-hasPermi="['system:gameEvent:addReferee']"
|
|
|
+ ></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 第三行:文章操作 -->
|
|
|
+ <div class="button-row">
|
|
|
+ <el-tooltip content="编写文章" placement="top">
|
|
|
+ <el-button
|
|
|
+ link
|
|
|
+ type="warning"
|
|
|
+ icon="EditPen"
|
|
|
+ size="small"
|
|
|
+ @click="handleWriteArticle(scope.row)"
|
|
|
+ v-hasPermi="['system:gameEvent:writeArticle']"
|
|
|
+ ></el-button>
|
|
|
+ </el-tooltip>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column type="selection" width="55" align="center" />
|
|
|
+
|
|
|
<el-table-column label="主键" align="center" prop="eventId" v-if="columns[0].visible" />
|
|
|
<el-table-column label="赛事编号" align="center" prop="eventCode" v-if="columns[1].visible" />
|
|
|
<el-table-column label="赛事名称" align="center" prop="eventName" v-if="columns[2].visible" />
|
|
@@ -327,7 +331,7 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
-
|
|
|
+
|
|
|
<!-- 用户导入对话框 -->
|
|
|
<el-dialog v-model="upload.open" :title="upload.title" width="400px" append-to-body>
|
|
|
<el-upload
|
|
@@ -722,13 +726,13 @@ const activeTab = ref('competition-process');
|
|
|
// 标签页与类型值的映射关系
|
|
|
const tabTypeMapping: Record<string, number> = {
|
|
|
'competition-process': 1, // 竞赛流程
|
|
|
- 'competition-items': 2, // 竞赛项目
|
|
|
- 'activity-agenda': 3, // 活动议程
|
|
|
+ 'competition-items': 2, // 竞赛项目
|
|
|
+ 'activity-agenda': 3, // 活动议程
|
|
|
'project-introduction': 4, // 项目介绍
|
|
|
- 'competition-flow': 5, // 竞赛流程
|
|
|
- 'event-grouping': 6, // 赛事分组
|
|
|
- 'athlete-handbook': 7, // 运动员号码簿
|
|
|
- 'project-venue': 8 // 项目场地
|
|
|
+ 'competition-flow': 5, // 竞赛流程
|
|
|
+ 'event-grouping': 6, // 赛事分组
|
|
|
+ 'athlete-handbook': 7, // 运动员号码簿
|
|
|
+ 'project-venue': 8 // 项目场地
|
|
|
};
|
|
|
|
|
|
const articleData = reactive({
|
|
@@ -774,7 +778,7 @@ const handleWriteArticle = async (row: GameEventVO) => {
|
|
|
articleDialog.currentEventId = row.eventId;
|
|
|
articleDialog.visible = true;
|
|
|
activeTab.value = 'competition-process';
|
|
|
-
|
|
|
+
|
|
|
// 加载默认标签页(竞赛流程)的数据
|
|
|
await loadTabData('competition-process');
|
|
|
};
|
|
@@ -782,12 +786,12 @@ const handleWriteArticle = async (row: GameEventVO) => {
|
|
|
/** 加载指定标签页的数据 */
|
|
|
const loadTabData = async (tabName: string) => {
|
|
|
const type = tabTypeMapping[tabName];
|
|
|
-
|
|
|
+
|
|
|
if (articleDialog.currentEventId && type) {
|
|
|
try {
|
|
|
const response = await getEventMdByEventAndType(articleDialog.currentEventId, type);
|
|
|
const eventMd = response.data;
|
|
|
-
|
|
|
+
|
|
|
const dataKey = getDataKeyByTabName(tabName);
|
|
|
if (dataKey && articleData[dataKey]) {
|
|
|
if (eventMd) {
|
|
@@ -839,14 +843,14 @@ const getDataKeyByTabName = (tabName: string): keyof typeof articleData | null =
|
|
|
/** 关闭文章编写对话框 */
|
|
|
const handleCloseArticleDialog = () => {
|
|
|
// 清空所有文章数据
|
|
|
- Object.keys(articleData).forEach(key => {
|
|
|
+ Object.keys(articleData).forEach((key) => {
|
|
|
const dataKey = key as keyof typeof articleData;
|
|
|
articleData[dataKey].id = undefined;
|
|
|
articleData[dataKey].title = '';
|
|
|
articleData[dataKey].content = '';
|
|
|
articleData[dataKey].remark = '';
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
// 重置对话框状态
|
|
|
articleDialog.visible = false;
|
|
|
articleDialog.currentEventId = undefined;
|
|
@@ -863,14 +867,14 @@ const handleSaveArticle = async () => {
|
|
|
const currentTabName = activeTab.value;
|
|
|
const type = tabTypeMapping[currentTabName];
|
|
|
const dataKey = getDataKeyByTabName(currentTabName);
|
|
|
-
|
|
|
+
|
|
|
if (!dataKey || !articleData[dataKey]) {
|
|
|
proxy?.$modal.msgError('获取当前标签页数据失败');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
const currentData = articleData[dataKey];
|
|
|
-
|
|
|
+
|
|
|
if (!currentData.title?.trim()) {
|
|
|
proxy?.$modal.msgError('标题不能为空');
|
|
|
return;
|
|
@@ -888,7 +892,7 @@ const handleSaveArticle = async () => {
|
|
|
|
|
|
await editEventMd(formData);
|
|
|
proxy?.$modal.msgSuccess('文章保存成功');
|
|
|
-
|
|
|
+
|
|
|
// 重新加载当前标签页数据以获取最新的ID
|
|
|
await loadTabData(currentTabName);
|
|
|
} catch (error) {
|
|
@@ -919,30 +923,44 @@ onActivated(() => {
|
|
|
<style scoped>
|
|
|
.operation-buttons {
|
|
|
display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- gap: 8px;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4px;
|
|
|
+ align-items: center;
|
|
|
+ min-width: 200px;
|
|
|
+}
|
|
|
+
|
|
|
+.button-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 6px;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
+ flex-wrap: wrap;
|
|
|
}
|
|
|
|
|
|
.operation-buttons .el-button {
|
|
|
+ min-width: 28px;
|
|
|
+ min-height: 28px;
|
|
|
+ padding: 4px 6px;
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: all 0.2s ease;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
- gap: 4px;
|
|
|
- padding: 6px 12px;
|
|
|
- border-radius: 6px;
|
|
|
- transition: all 0.3s ease;
|
|
|
+ justify-content: center;
|
|
|
}
|
|
|
|
|
|
.operation-buttons .el-button:hover {
|
|
|
transform: translateY(-1px);
|
|
|
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
|
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
|
|
|
}
|
|
|
|
|
|
-.button-text {
|
|
|
- font-size: 12px;
|
|
|
- font-weight: 500;
|
|
|
- white-space: nowrap;
|
|
|
+.operation-buttons .el-button[disabled] {
|
|
|
+ opacity: 0.5;
|
|
|
+ cursor: not-allowed;
|
|
|
+}
|
|
|
+
|
|
|
+.operation-buttons .el-button[disabled]:hover {
|
|
|
+ transform: none;
|
|
|
+ box-shadow: none;
|
|
|
}
|
|
|
|
|
|
/* 为不同类型的按钮设置不同的颜色主题 */
|
|
@@ -967,17 +985,36 @@ onActivated(() => {
|
|
|
}
|
|
|
|
|
|
/* 响应式设计 */
|
|
|
-@media (max-width: 1200px) {
|
|
|
+@media (max-width: 1400px) {
|
|
|
.operation-buttons {
|
|
|
- gap: 4px;
|
|
|
+ min-width: 180px;
|
|
|
}
|
|
|
|
|
|
+ .button-row {
|
|
|
+ gap: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
.operation-buttons .el-button {
|
|
|
- padding: 4px 8px;
|
|
|
+ min-width: 24px;
|
|
|
+ min-height: 24px;
|
|
|
+ padding: 3px 5px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 1200px) {
|
|
|
+ .operation-buttons {
|
|
|
+ min-width: 160px;
|
|
|
+ gap: 2px;
|
|
|
}
|
|
|
|
|
|
- .button-text {
|
|
|
- font-size: 11px;
|
|
|
+ .button-row {
|
|
|
+ gap: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .operation-buttons .el-button {
|
|
|
+ min-width: 22px;
|
|
|
+ min-height: 22px;
|
|
|
+ padding: 2px 4px;
|
|
|
}
|
|
|
}
|
|
|
</style>
|