Forráskód Böngészése

feat(system): 优化投诉管理并添加审核功能

- 添加获取所有用户排名的接口和相关页面功能
- 实现查看比赛结果和审核功能
- 优化历史记录查询逻辑
- 更新比赛信息展示,增加申诉状态提示
fugui001 4 hónapja
szülő
commit
f36d0ed828

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

@@ -1,6 +1,7 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
 import { ComplaintsVO, ComplaintsForm, ComplaintsQuery } from '@/api/system/business/complaints/types';
+import { ClaimsQuery, ClaimsVO } from '@/api/system/business/claims/types';
 
 /**
  * 查询用户申诉列表
@@ -60,3 +61,14 @@ export const delComplaints = (id: string | number | Array<string | number>) => {
     method: 'delete'
   });
 };
+/**
+ * 获取所有用户名及排名
+ * @param id
+ */
+export const getAllUserRankByTournamentId = (query?: ComplaintsQuery): AxiosPromise<ClaimsVO[]> => {
+  return request({
+    url: '/business/complaints/getAllUserRankByTournamentId',
+    method: 'get',
+    params: query
+  });
+};

+ 2 - 0
src/api/system/business/complaints/types.ts

@@ -43,6 +43,8 @@ export interface ComplaintsVO {
    * 申诉状态
    */
   statusText: string;
+
+  playerId: number;
 }
 
 export interface ComplaintsForm extends BaseEntity {

+ 2 - 2
src/api/system/business/history/types.ts

@@ -176,9 +176,9 @@ export interface HistoryQuery extends PageQuery {
    */
   params?: any;
 
-  historyId?: number;
+  historyId?: string;
 
-  playerId?: number;
+  playerId?: string;
 
   tableId?: number;
 

+ 1 - 0
src/api/system/business/tournaments/types.ts

@@ -81,6 +81,7 @@ export interface TournamentsVO {
   itemsPrizeList?: ItemsPrize[];
   tournamentsBiId?: string;
   signNum?: number;
+  isComplaints?: boolean;
 }
 
 export interface TournamentsForm extends BaseEntity {

+ 151 - 3
src/views/system/business/complaints/index.vue

@@ -84,7 +84,9 @@
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
           <template #default="scope">
             <el-tooltip content="查看比赛结果" placement="top">
-              <el-button link type="primary" icon="View" v-hasPermi="['system:complaints:edit']"> 查看比赛结果 </el-button>
+              <el-button link type="primary" icon="View" @click="handleSeeRank(scope.row)" v-hasPermi="['system:complaints:edit']">
+                查看比赛结果
+              </el-button>
             </el-tooltip>
             <!-- status 为 1:显示“处理”按钮 -->
             <el-tooltip v-if="scope.row.status === 1" content="处理" placement="top">
@@ -139,12 +141,94 @@
         </div>
       </template>
     </el-dialog>
+
+    <el-dialog
+      :title="`${tournamentInfo.name} ${tournamentInfo.tournamentsBiId}`"
+      v-model="auditDialog.visible"
+      width="1000px"
+      append-to-body
+      @close="cancelAudit"
+    >
+      <!-- 查看对局记录按钮 -->
+      <!--      <div class="dialog-header-actions" v-if="auditDialog.mode === 'view'">
+        <el-button type="primary">查看对局记录</el-button>
+      </div>-->
+
+      <!-- 比赛信息展示 -->
+      <div class="tournament-info" v-if="tournamentInfo.id">
+        <p>比赛时间:{{ tournamentInfo.startTime }} ~ {{ tournamentInfo.endTime }}</p>
+        <p>参加人数:{{ tournamentInfo.signNum }}人</p>
+        <p v-if="tournamentInfo.isComplaints" style="color: red">本场比赛仍有选手存在异议,请处理申述后继续授作。</p>
+        <!--        <p>比赛类型:{{ tournamentInfo.id }}</p>
+        <p>报名条件:{{ tournamentInfo.itemsName }} x {{ tournamentInfo.itemsNum }}</p>
+        <p>盲注表:{{ tournamentInfo.blindStructuresName }}</p>
+        <p>报名截止等级:{{ 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>
+        <el-table-column label="奖励" align="center">
+          <template #default="scope">
+            <div v-for="(prize, index) in scope.row.rewardVoList" :key="index">{{ prize.itemName }} {{ prize.quantity }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="状态" align="center">
+          <template #default="scope">
+            <!-- 只有 claimedText 存在时才显示 -->
+            <el-tag v-if="scope.row.claimedText" :type="scope.row.claimed === 3 ? 'danger' : 'primary'" size="small">
+              {{ scope.row.claimedText }}
+            </el-tag>
+            <!-- 否则显示空 -->
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" align="center" width="350" class-name="small-padding fixed-width">
+          <template #default="scope">
+            <div style="display: flex; justify-content: center; gap: 16px">
+              <el-tooltip content="查看牌局" placement="top">
+                <el-button link type="primary" icon="View" @click="handleViewHistory(scope.row)">查看牌局</el-button>
+              </el-tooltip>
+            </div>
+          </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">
+          <el-button @click="cancelAudit">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="Complaints" lang="ts">
-import { listComplaints, getComplaints, delComplaints, addComplaints, updateComplaints } from '@/api/system/business/complaints';
+import {
+  listComplaints,
+  getComplaints,
+  delComplaints,
+  addComplaints,
+  updateComplaints,
+  getAllUserRankByTournamentId
+} from '@/api/system/business/complaints';
 import { ComplaintsVO, ComplaintsQuery, ComplaintsForm } from '@/api/system/business/complaints/types';
+import { ref } from 'vue';
+import { TournamentsVO } from '@/api/system/business/tournaments/types';
+import { ClaimsVO } from '@/api/system/business/claims/types';
+import { getTournaments } from '@/api/system/business/tournaments';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { complaints_status } = toRefs<any>(proxy?.useDict('complaints_status'));
 
@@ -195,7 +279,19 @@ const data = reactive<PageData<ComplaintsForm, ComplaintsQuery>>({
     id: [{ required: true, message: '不能为空', trigger: 'blur' }]
   }
 });
-
+const tournamentInfo = ref<Partial<TournamentsVO>>({
+  id: '',
+  startTime: '',
+  endTime: '',
+  itemsNum: 0,
+  itemsName: '',
+  blindStructureId: 0,
+  blindStructuresName: '',
+  lateRegistrationLevel: 0,
+  tournamentsBiId: '',
+  signNum: 0,
+  isComplaints: false
+});
 const { queryParams, form, rules } = toRefs(data);
 
 /** 查询用户申诉列表 */
@@ -307,7 +403,59 @@ const handleExport = () => {
     `complaints_${new Date().getTime()}.xlsx`
   );
 };
+const auditDialog = ref({
+  visible: false,
+  title: '',
+  mode: 'view' as 'view' | 'audit'
+});
+
+const auditData = ref<ClaimsVO[]>([]);
+// 创建新的查询参数对象,不影响原始 queryParams
+const auditQueryParams = {
+  pageNum: 1,
+  pageSize: 10,
+  tournamentId: null as number | null
+};
+const auditTotal = ref(0);
+// 模拟打开对话框并获取数据
+const handleSeeRank = async (row: ComplaintsVO) => {
+  auditDialog.value.visible = true;
+  const _id = row?.tournamentId || ids.value[0];
+  auditQueryParams.tournamentId = Number(_id);
+  await getAuditData(1);
 
+  try {
+    const res = await getTournaments(_id);
+    if (res.code === 200) {
+      tournamentInfo.value = res.data;
+    }
+  } catch (error) {
+    console.error('获取数据失败', error);
+  }
+};
+const getAuditData = async (pageNum: number) => {
+  try {
+    auditQueryParams.pageNum = pageNum;
+    const res = await getAllUserRankByTournamentId(auditQueryParams);
+    auditData.value = res.rows;
+    auditTotal.value = res.total;
+  } catch (error) {
+    console.error('获取审核数据失败', error);
+  }
+};
+// 关闭对话框
+const cancelAudit = () => {
+  auditDialog.value.visible = false;
+};
+const handleViewHistory = (row: ComplaintsVO) => {
+  const tournamentId = row.tournamentId;
+  const playerId = row.id;
+  proxy?.$router.push({
+    path: '/business/history',
+    query: { tournamentId: String(tournamentId), playerId: String(playerId) }
+  });
+  auditDialog.value.visible = false;
+};
 onMounted(() => {
   getList();
 });

+ 6 - 9
src/views/system/business/history/index.vue

@@ -242,7 +242,7 @@ import {
   selectAllHandNumber
 } from '@/api/system/business/history';
 import { getTournaments } from '@/api/system/business/tournaments';
-import { selectBlindLevelsById, selectBlindLevelsByTournament } from '@/api/system/business/levels';
+import {  selectBlindLevelsByTournament } from '@/api/system/business/levels';
 import { HistoryVO, HistoryQuery, HistoryForm } from '@/api/system/business/history/types';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
@@ -501,11 +501,11 @@ const tableNumberData = ref<any[]>([]);
 const getTableData = async (playerId: string | number, tournamentId: string | number) => {
   try {
     // 确保 playerId 和 tournamentId 为 number 类型
-    const playerIdNum = Number(playerId);
-    const tournamentIdNum = Number(tournamentId);
+    const playerIdNum = String(playerId);
+    const tournamentIdNum = String(tournamentId);
     /*    if (!isNaN(playerIdNum) && !isNaN(tournamentIdNum)) {*/
     queryParams.value.tournamentId = tournamentIdNum;
-    if (!isNaN(playerIdNum)) {
+    if (playerIdNum !== null && playerIdNum !== undefined) {
       queryParams.value.playerId = playerIdNum;
       queryParams.value.handId = null;
     } else {
@@ -615,10 +615,9 @@ watch(
   () => route.query,
   async (newQuery) => {
     const { tournamentId, playerId } = newQuery;
-
     if (tournamentId && playerId) {
-      const playerIdNum = Number(playerId);
-      const tournamentIdNum = Number(tournamentId);
+      const playerIdNum = String(playerId);
+      const tournamentIdNum = String(tournamentId);
       await getTableData(playerIdNum, tournamentIdNum);
       /*   if (!isNaN(playerIdNum) && !isNaN(tournamentIdNum)) {
         await getTableData(playerIdNum, tournamentIdNum);
@@ -725,12 +724,10 @@ const handlePlayerSearch = async () => {
     const res = await selectAllHandZhuoCi2(queryParams.value);
     if (res.code === 200) {
       tableData.value = res.data;
-
       // 如果有桌次数据,进一步获取局数数据
       if (tableData.value.length > 0) {
         const firstTable = tableData.value[0];
         selectedTableId.value = firstTable.tableId;
-
         // 更新 queryParams 以获取局数数据
         queryParams.value.tableId = firstTable.tableId;
         const res = await selectAllHandNumber(queryParams.value);

+ 3 - 1
src/views/system/business/tournaments/index.vue

@@ -390,6 +390,7 @@
           <el-button type="primary" @click="handleViewLevelsSee(tournamentInfo)">预览</el-button>
         </p>
         <p v-if="auditDialog.mode === 'view'">报名截止等级:{{ tournamentInfo.lateRegistrationLevel }}</p>
+        <p v-if="tournamentInfo.isComplaints" style="color: red">本场比赛仍有选手存在异议,请处理申述后继续授作。</p>
       </div>
 
       <!-- 表格内容 -->
@@ -1073,7 +1074,8 @@ const tournamentInfo = ref<Partial<TournamentsVO>>({
   blindStructuresName: '',
   lateRegistrationLevel: 0,
   tournamentsBiId: '',
-  signNum: 0
+  signNum: 0,
+  isComplaints: false
 });
 
 const auditData = ref<ClaimsVO[]>([]);