Преглед изворни кода

feat(system): 优化比赛奖金审核功能

- 新增删除用户获奖名额功能
- 优化查看比赛信息和审核数据展示
- 添加分页功能
- 修复部分功能按钮显示逻辑
- 优化对话框样式和交互
fugui001 пре 5 месеци
родитељ
комит
1ab0f2b0dd

+ 12 - 0
src/api/system/business/claims/index.ts

@@ -61,3 +61,15 @@ export const delClaims = (id: string | number | Array<string | number>) => {
     method: 'delete'
   });
 };
+
+/**
+ * 删除本场比赛的用户奖励
+ * @param data
+ */
+export const deleteClaim = (data: { id: number; tournamentId: number }) => {
+  return request({
+    url: '/business/claims/deleteByCriteria',
+    method: 'post',
+    data
+  });
+};

+ 114 - 0
src/views/system/business/structures/BlindTableUploadDialog.vue

@@ -0,0 +1,114 @@
+<!--<template>-->
+<!--  <el-dialog :title="title" v-model="visible" width="500px" append-to-body @close="handleClose">-->
+<!--    <el-form ref="formRef" :model="formData" :rules="rules" label-width="120px">-->
+<!--      <el-form-item label="名称" prop="name">-->
+<!--        <el-input v-model="formData.name" placeholder="请输入名称" />-->
+<!--      </el-form-item>-->
+
+<!--      <el-form-item label="上传文件" prop="file">-->
+<!--        <div class="upload-container">-->
+<!--          <el-upload-->
+<!--            class="upload-demo"-->
+<!--            action="#"-->
+<!--            :on-change="handleFileChange"-->
+<!--            :file-list="fileList"-->
+<!--            :auto-upload="false"-->
+<!--            :limit="1"-->
+<!--            accept=".xlsx,.xls"-->
+<!--          >-->
+<!--            <template #trigger>-->
+<!--              <el-button type="primary">点击上传</el-button>-->
+<!--            </template>-->
+
+<!--            <template #tip>-->
+<!--              <div class="el-upload__tip">-->
+<!--                <el-link type="primary" @click="downloadTemplate">-->
+<!--                  <el-icon name="download" /> 模板下载-->
+<!--                </el-link>-->
+<!--                |-->
+<!--                <el-button link @click="openPreview">-->
+<!--                  <el-icon name="document" /> 预 览-->
+<!--                </el-button>-->
+<!--              </div>-->
+<!--            </template>-->
+<!--          </el-upload>-->
+<!--        </div>-->
+<!--      </el-form-item>-->
+
+<!--      <el-form-item label="备注" prop="description">-->
+<!--        <el-input v-model="formData.description" type="textarea" placeholder="请输入备注" />-->
+<!--      </el-form-item>-->
+<!--    </el-form>-->
+
+<!--    <template #footer>-->
+<!--      <div class="dialog-footer">-->
+<!--        <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>-->
+<!--        <el-button @click="cancel">取 消</el-button>-->
+<!--      </div>-->
+<!--    </template>-->
+<!--  </el-dialog>-->
+<!--</template>-->
+
+<!--<script setup>import { ref, defineProps, defineEmits } from 'vue';-->
+
+<!--const props = defineProps({-->
+<!--  modelValue: Boolean,-->
+<!--  title: String,-->
+<!--  formData: Object,-->
+<!--  rules: Object,-->
+<!--  fileList: Array-->
+<!--});-->
+
+<!--const emit = defineEmits(['update:modelValue', 'submit', 'cancel', 'file-change', 'download-template', 'open-preview']);-->
+
+<!--const visible = ref(false);-->
+<!--const formRef = ref(null);-->
+
+<!--const buttonLoading = ref(false);-->
+
+<!--const handleClose = () => {-->
+<!--  emit('update:modelValue', false);-->
+<!--};-->
+
+<!--const handleFileChange = (file) => {-->
+<!--  emit('file-change', file);-->
+<!--};-->
+
+<!--const downloadTemplate = () => {-->
+<!--  emit('download-template');-->
+<!--};-->
+
+<!--const openPreview = () => {-->
+<!--  emit('open-preview');-->
+<!--};-->
+
+<!--const submitForm = () => {-->
+<!--  formRef.value?.validate(async (valid) => {-->
+<!--    if (valid) {-->
+<!--      buttonLoading.value = true;-->
+<!--      try {-->
+<!--        const formData = new FormData();-->
+
+<!--        if (props.fileList.length > 0 && props.fileList[0].raw) {-->
+<!--          formData.append('file', props.fileList[0].raw);-->
+<!--        } else {-->
+<!--          buttonLoading.value = false;-->
+<!--          return;-->
+<!--        }-->
+
+<!--        formData.append('name', props.formData.name || '');-->
+<!--        formData.append('description', props.formData.description || '');-->
+
+<!--        await emit('submit', formData);-->
+<!--        buttonLoading.value = false;-->
+<!--      } catch (error) {-->
+<!--        buttonLoading.value = false;-->
+<!--      }-->
+<!--    }-->
+<!--  });-->
+<!--};-->
+
+<!--const cancel = () => {-->
+<!--  emit('cancel');-->
+<!--};-->
+<!--</script>-->

+ 122 - 25
src/views/system/business/tournaments/index.vue

@@ -109,15 +109,14 @@
           <template #default="scope">
             <div style="display: flex; flex-direction: column; gap: 5px">
               <el-tooltip content="查看" placement="top">
-                <el-button link type="primary" icon="View" @click="handleUpdate(scope.row, 'view')">查看</el-button>
+                <el-button link type="primary" icon="View" @click="openAuditDialog(scope.row.id, 'view')">查看</el-button>
               </el-tooltip>
               <el-tooltip content="编辑" placement="top">
                 <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row, 'edit')">编辑</el-button>
               </el-tooltip>
               <el-tooltip content="领奖审核" placement="top">
-                <el-button link type="primary" icon="Edit" @click="openAuditDialog(scope.row.id)">领奖审核</el-button>
+                <el-button link type="primary" icon="Edit" @click="openAuditDialog(scope.row.id, 'audit')">领奖审核</el-button>
               </el-tooltip>
-
               <!--              <el-tooltip content="分配盲注" placement="top">
                 <el-button link type="success" icon="Document" @click="openAssignDialog(scope.row)"> 分配 </el-button>
               </el-tooltip>-->
@@ -361,7 +360,7 @@
       @close="cancelAudit"
     >
       <!-- 查看对局记录按钮 -->
-      <div class="dialog-header-actions">
+      <div class="dialog-header-actions" v-if="auditDialog.mode === 'view'">
         <el-button type="primary">查看对局记录</el-button>
       </div>
 
@@ -369,14 +368,18 @@
       <div class="tournament-info" v-if="tournamentInfo.id">
         <p>比赛时间:{{ tournamentInfo.startTime }} ~ {{ tournamentInfo.endTime }}</p>
         <p>参加人数:{{ tournamentInfo.id }}人</p>
-        <p v-if="tournamentInfo.id">比赛类型:{{ tournamentInfo.id }}</p>
-        <p v-if="tournamentInfo.id">报名条件:{{ tournamentInfo.itemsName }} x {{ tournamentInfo.itemsNum }}</p>
-        <p v-if="tournamentInfo.id">盲注表:{{ tournamentInfo.blindStructuresName }}</p>
-        <p v-if="tournamentInfo.id">报名截止等级:{{ tournamentInfo.lateRegistrationLevel }}</p>
+        <p v-if="auditDialog.mode === 'view'">比赛类型:{{ tournamentInfo.id }}</p>
+        <p v-if="auditDialog.mode === 'view'">报名条件:{{ tournamentInfo.itemsName }} x {{ tournamentInfo.itemsNum }}</p>
+        <p v-if="auditDialog.mode === 'view'">
+          盲注表:{{ tournamentInfo.blindStructuresName }}
+          <el-button type="primary" @click="handleViewLevelsSee(tournamentInfo)">预览</el-button>
+        </p>
+        <p v-if="auditDialog.mode === 'view'">报名截止等级:{{ tournamentInfo.lateRegistrationLevel }}</p>
       </div>
 
       <!-- 表格内容 -->
       <el-table :data="auditData" border style="width: 100%">
+        <el-table-column prop="id" label="id" align="center" v-if="false"></el-table-column>
         <el-table-column prop="rank" label="排名" align="center"></el-table-column>
         <el-table-column prop="playerName" label="用户名" align="center"></el-table-column>
         <el-table-column prop="phone" label="手机" align="center"></el-table-column>
@@ -394,15 +397,24 @@
               <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">查看牌局</el-button>
             </el-tooltip>
             <el-tooltip content="审核" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">审核</el-button>
+              <el-button link type="primary" icon="Audit">审核</el-button>
             </el-tooltip>
             <el-tooltip content="移除" placement="top">
-              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">移除</el-button>
+              <el-button link type="primary" icon="Delete" @click="handleClaimsDelete(scope.row)">移除</el-button>
             </el-tooltip>
           </template>
         </el-table-column>
       </el-table>
-
+      <!-- 分页组件 -->
+      <div class="pagination-container" style="margin-top: 20px; text-align: center">
+        <el-pagination
+          v-model:current-page="auditQueryParams.pageNum"
+          v-model:page-size="auditQueryParams.pageSize"
+          :total="auditTotal"
+          layout="prev, pager, next"
+          @current-change="getAuditData"
+        />
+      </div>
       <!-- 对话框底部按钮 -->
       <template #footer>
         <div class="dialog-footer">
@@ -410,6 +422,16 @@
         </div>
       </template>
     </el-dialog>
+
+    <el-dialog title="移除获奖名额" v-model="removeDialog.visible" width="30%">
+      <span>是否移除用户:{{ removeDialog.playerName }}{{ removeDialog.phone }} 在本次比赛中的获奖名额?</span>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="cancelRemove">取消</el-button>
+          <el-button type="danger" @click="confirmRemove">确认移除</el-button>
+        </span>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
@@ -427,7 +449,7 @@ import {
 import { selectItemsSelList } from '@/api/system/business/items';
 import { selectBlindLevelsById } from '@/api/system/business/levels';
 import { selectBlingStructuresInfo } from '@/api/system/business/structures';
-import { listClaims } from '@/api/system/business/claims';
+import { listClaims, deleteClaim } from '@/api/system/business/claims';
 import { TournamentsVO, TournamentsQuery, TournamentsForm, TournamentsBindStructuresVO } from '@/api/system/business/tournaments/types';
 import { ref } from 'vue';
 import LevelsIndex from '@/views/system/business/levels/index.vue';
@@ -1022,7 +1044,8 @@ const handleSortChange = ({ prop, order }) => {
 
 const auditDialog = ref({
   visible: false,
-  title: ''
+  title: '',
+  mode: 'view' as 'view' | 'audit'
 });
 
 const tournamentInfo = ref<Partial<TournamentsVO>>({
@@ -1038,33 +1061,107 @@ const tournamentInfo = ref<Partial<TournamentsVO>>({
 });
 
 const auditData = ref<ClaimsVO[]>([]);
-
+// 创建新的查询参数对象,不影响原始 queryParams
+const auditQueryParams = {
+  pageNum: 1,
+  pageSize: 10,
+  tournamentId: null as number | null
+};
+const auditTotal = ref(0);
 // 模拟打开对话框并获取数据
-const openAuditDialog = async (tournamentId) => {
+const openAuditDialog = async (row: TournamentsVO | number, mode: 'view' | 'audit' = 'view') => {
   auditDialog.value.visible = true;
+  auditDialog.value.mode = mode; // 设置模式
+
+  let tournamentId: number;
+
+  if (typeof row === 'number') {
+    tournamentId = row;
+  }
+
+  auditQueryParams.tournamentId = tournamentId;
+  await getAuditData(1);
+
   try {
     const res = await getTournaments(tournamentId);
-    debugger;
     if (res.code === 200) {
       tournamentInfo.value = res.data;
     }
-    // 创建新的查询参数对象,不影响原始 queryParams
-    const auditQueryParams = {
-      pageNum: 1,
-      pageSize: 10,
-      tournamentId: tournamentId
-    };
-    const res2 = await listClaims(auditQueryParams);
-    auditData.value = res2.rows;
   } catch (error) {
     console.error('获取数据失败', error);
   }
 };
-
+const getAuditData = async (pageNum: number) => {
+  try {
+    auditQueryParams.pageNum = pageNum;
+    const res = await listClaims(auditQueryParams);
+    auditData.value = res.rows;
+    auditTotal.value = res.total;
+  } catch (error) {
+    console.error('获取审核数据失败', error);
+  }
+};
 // 关闭对话框
 const cancelAudit = () => {
   auditDialog.value.visible = false;
   /*tournamentInfo.value = {};
   auditData.value = [];*/
 };
+
+const removeDialog = ref({
+  visible: false,
+  id: null,
+  tournamentId: null,
+  playerName: '',
+  phone: ''
+});
+
+const handleClaimsDelete = (row: ClaimsVO) => {
+  removeDialog.value.visible = true;
+  removeDialog.value.id = row.id; // 假设 row 中有 id 字段
+  removeDialog.value.tournamentId = row.tournamentId; // 假设 row 中有 tournamentId 字段
+  removeDialog.value.playerName = row.playerName; // 假设 row 中有 playerName 字段
+  removeDialog.value.phone = row.phone;
+};
+
+const cancelRemove = () => {
+  removeDialog.value.visible = false;
+};
+
+const confirmRemove = async () => {
+  try {
+    const res = await deleteClaim({
+      id: removeDialog.value.id,
+      tournamentId: removeDialog.value.tournamentId
+    });
+    if (res.code === 200) {
+      ElMessage.success('移除成功');
+      // 重新加载审核数据
+      const auditQueryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        tournamentId: tournamentInfo.value.id
+      };
+      const res2 = await listClaims(auditQueryParams);
+      auditData.value = res2.rows;
+    } else {
+      ElMessage.error(res.msg);
+    }
+  } catch (error) {
+    ElMessage.error('移除失败,请重试');
+  } finally {
+    removeDialog.value.visible = false;
+  }
+};
+
+const handleViewLevelsSee = (tournamentsVO: TournamentsVO | undefined | null) => {
+  if (!tournamentsVO || !tournamentsVO.blindStructureId) {
+    proxy?.$modal.msgWarning('该赛事未绑定盲注表');
+    return;
+  }
+
+  dialogParams.value.blindStructureId = tournamentsVO.blindStructureId;
+  dialogParams.value.name = tournamentsVO.blindStructuresName ?? '';
+  levelsDialogVisible.value = true;
+};
 </script>