浏览代码

feat(tournaments): 添加赛事分配盲注功能

- 新增分配盲注按钮和相关功能
- 实现获取赛事盲注列表和分配盲注的接口
- 添加分配盲注的表单和对话框组件
- 优化赛事列表页面,增加分配状态显示
fugui001 6 月之前
父节点
当前提交
0d45398434

+ 63 - 0
src/api/demo/tournaments/index.ts

@@ -0,0 +1,63 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+import { TournamentsVO, TournamentsForm, TournamentsQuery } from '@/api/demo/tournaments/types';
+
+/**
+ * 查询【请填写功能名称】列表
+ * @param query
+ * @returns {*}
+ */
+
+export const listTournaments = (query?: TournamentsQuery): AxiosPromise<TournamentsVO[]> => {
+  return request({
+    url: '/demo/tournaments/list',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 查询【请填写功能名称】详细
+ * @param id
+ */
+export const getTournaments = (id: string | number): AxiosPromise<TournamentsVO> => {
+  return request({
+    url: '/demo/tournaments/' + id,
+    method: 'get'
+  });
+};
+
+/**
+ * 新增【请填写功能名称】
+ * @param data
+ */
+export const addTournaments = (data: TournamentsForm) => {
+  return request({
+    url: '/demo/tournaments',
+    method: 'post',
+    data: data
+  });
+};
+
+/**
+ * 修改【请填写功能名称】
+ * @param data
+ */
+export const updateTournaments = (data: TournamentsForm) => {
+  return request({
+    url: '/demo/tournaments',
+    method: 'put',
+    data: data
+  });
+};
+
+/**
+ * 删除【请填写功能名称】
+ * @param id
+ */
+export const delTournaments = (id: string | number | Array<string | number>) => {
+  return request({
+    url: '/demo/tournaments/' + id,
+    method: 'delete'
+  });
+};

+ 154 - 0
src/api/demo/tournaments/types.ts

@@ -0,0 +1,154 @@
+export interface TournamentsVO {
+  /**
+   */
+  id: string | number;
+
+  /**
+   * 赛事名称
+   */
+  name: string;
+
+  /**
+   * 比赛开始时间
+   */
+  startTime: string;
+
+  /**
+   * 游戏类型
+   */
+  gameType: number;
+
+  /**
+   * 起始记分牌数量
+   */
+  startingChips: number;
+
+  /**
+   * 级别持续时间(分钟)
+   */
+  levelDuration: number;
+
+  /**
+   * 截止报名级别
+   */
+  lateRegistrationLevel: number;
+
+  /**
+   * 最大参赛人数
+   */
+  maxPlayers: number;
+
+  /**
+   * 赛事状态
+   */
+  status: number;
+
+  /**
+   */
+  createdAt: string;
+
+  /**
+   */
+  updatedAt: string;
+}
+
+export interface TournamentsForm extends BaseEntity {
+  /**
+   */
+  id?: string | number;
+
+  /**
+   * 赛事名称
+   */
+  name?: string;
+
+  /**
+   * 比赛开始时间
+   */
+  startTime?: string;
+
+  /**
+   * 游戏类型
+   */
+  gameType?: number;
+
+  /**
+   * 起始记分牌数量
+   */
+  startingChips?: number;
+
+  /**
+   * 级别持续时间(分钟)
+   */
+  levelDuration?: number;
+
+  /**
+   * 截止报名级别
+   */
+  lateRegistrationLevel?: number;
+
+  /**
+   * 最大参赛人数
+   */
+  maxPlayers?: number;
+
+  /**
+   * 赛事状态
+   */
+  status?: number;
+
+  /**
+   */
+  createdAt?: string;
+
+  /***/
+  updatedAt?: string;
+}
+
+export interface TournamentsQuery extends PageQuery {
+  /**
+   * 赛事名称
+   */
+  name?: string;
+
+  /**
+   * 比赛开始时间
+   */
+  startTime?: string;
+
+  /**
+   * 游戏类型
+   */
+  gameType?: number;
+
+  /**
+   * 起始记分牌数量
+   */
+  startingChips?: number;
+
+  /**
+   * 级别持续时间(分钟)
+   */
+  levelDuration?: number;
+
+  /**
+   * 截止报名级别
+   */
+  lateRegistrationLevel?: number;
+
+  /**
+   * 最大参赛人数
+   */
+  maxPlayers?: number;
+
+  /**
+   * 赛事状态
+   */
+  status?: number;
+  createdAt?: string;
+  updatedAt?: string;
+  /**
+   * 日期范围参数
+   */
+  params?: any;
+}

+ 27 - 1
src/api/system/business/tournaments/index.ts

@@ -1,6 +1,12 @@
 import request from '@/utils/request';
 import { AxiosPromise } from 'axios';
-import { TournamentsVO, TournamentsForm, TournamentsQuery } from '@/api/system/business/tournaments/types';
+import {
+  TournamentsVO,
+  TournamentsForm,
+  TournamentsQuery,
+  TournamentsBindStructuresQuery,
+  TournamentsBindStructuresVO
+} from '@/api/system/business/tournaments/types';
 
 /**
  * 查询【请填写功能名称】列表
@@ -61,3 +67,23 @@ export const delTournaments = (id: string | number | Array<string | number>) =>
     method: 'delete'
   });
 };
+
+export const getSelectTournamentBlindStructuresList = (query?: TournamentsBindStructuresQuery): AxiosPromise<TournamentsBindStructuresVO[]> => {
+  return request({
+    url: '/business/tournaments/selectTournamentBlindStructuresList',
+    method: 'get',
+    params: query
+  });
+};
+
+/**
+ * 分配盲注给赛事
+ * @param data 请求数据 { tournamentId, blindStructureIds }
+ */
+export const assignTournamentBlindStructures = (data: { tournamentId: number; blindStructureIds: number[] }): AxiosPromise<void> => {
+  return request({
+    url: '/business/tournaments/assignTournamentBlindStructures',
+    method: 'post',
+    data: data
+  });
+};

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

@@ -152,3 +152,18 @@ export interface TournamentsQuery extends PageQuery {
    */
   params?: any;
 }
+
+export interface TournamentsBindStructuresQuery extends PageQuery {
+  /**
+   * 赛事ID
+   */
+  tournamentId?: number;
+}
+
+export interface TournamentsBindStructuresVO {
+  blindStructuresId: number;
+  blindStructuresName: string;
+  blindDescription: string;
+  tournamentsName: string;
+  allocationStatus: number;
+}

+ 160 - 11
src/views/system/business/tournaments/index.vue

@@ -79,6 +79,13 @@
             <el-tooltip content="删除" placement="top">
               <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['business:tournaments:remove']"></el-button>
             </el-tooltip>
+
+            <!-- 新增:分配按钮 -->
+            <el-tooltip content="分配盲注" placement="top">
+              <el-button link type="success" icon="Document" @click="openAssignDialog(scope.row)" v-hasPermi="['business:tournaments:assign']">
+                分配
+              </el-button>
+            </el-tooltip>
           </template>
         </el-table-column>
       </el-table>
@@ -107,14 +114,6 @@
         <el-form-item label="最大参赛人数" prop="maxPlayers">
           <el-input v-model="form.maxPlayers" placeholder="请输入最大参赛人数" />
         </el-form-item>
-<!--        <el-form-item label="" prop="createdAt">
-          <el-date-picker clearable v-model="form.createdAt" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择">
-          </el-date-picker>
-        </el-form-item>
-        <el-form-item label="" prop="updatedAt">
-          <el-date-picker clearable v-model="form.updatedAt" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择">
-          </el-date-picker>
-        </el-form-item>-->
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -123,12 +122,65 @@
         </div>
       </template>
     </el-dialog>
+
+    <!-- 分配模态框 -->
+    <el-dialog title="分配盲注信息" v-model="assignDialog.visible" width="660px" append-to-body destroy-on-close>
+      <el-form ref="assignFormRef" :model="assignForm" label-width="100px">
+        <!-- 可勾选的列表 -->
+        <el-form-item label="">
+          <div style="display: flex; justify-content: center">
+            <el-table
+              border
+              ref="assignTable"
+              :data="assignList"
+              @selection-change="handleAssignSelectionChange"
+              :row-key="'blindStructuresId'"
+              style="width: 100%"
+            >
+              <el-table-column type="selection" width="55" align="center" />
+              <el-table-column label="blindStructuresId" align="center" prop="blindStructuresId" v-if="true" />
+              <el-table-column prop="blindStructuresName" label="盲注结构名称" align="center" />
+              <el-table-column prop="blindDescription" label="盲注结构描述" align="center" />
+              <el-table-column prop="allocationStatus" label="绑定情况" align="center">
+                <template #default="scope">
+                  {{ scope.row.allocationStatus === 0 ? '未绑定' : '已绑定' }}
+                </template>
+              </el-table-column>
+              <el-table-column prop="tournamentsName" label="赛事名称" align="center" />
+            </el-table>
+          </div>
+          <!-- 分页(如果数据量大) -->
+          <pagination
+            v-if="assignTotal > 0"
+            :total="assignTotal"
+            v-model:page="assignQuery.pageNum"
+            v-model:limit="assignQuery.pageSize"
+            @pagination="getAssignList"
+          />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="dialog-footer" style="text-align: center">
+          <el-button :loading="buttonLoading" type="primary" @click="submitAssign">保 存</el-button>
+          <el-button @click="assignDialog.visible = false">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="Tournaments" lang="ts">
-import { listTournaments, getTournaments, delTournaments, addTournaments, updateTournaments } from '@/api/system/business/tournaments';
-import { TournamentsVO, TournamentsQuery, TournamentsForm } from '@/api/system/business/tournaments/types';
+import {
+  listTournaments,
+  getTournaments,
+  delTournaments,
+  addTournaments,
+  updateTournaments,
+  getSelectTournamentBlindStructuresList,
+  assignTournamentBlindStructures
+} from '@/api/system/business/tournaments';
+import { TournamentsVO, TournamentsQuery, TournamentsForm, TournamentsBindStructuresVO } from '@/api/system/business/tournaments/types';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
@@ -149,6 +201,30 @@ const dialog = reactive<DialogOption>({
   title: ''
 });
 
+const assignDialog = reactive({
+  visible: false,
+  title: '分配盲注'
+});
+
+const assignForm = reactive({
+  tournamentId: undefined as number | undefined,
+  selectedIds: [] as number[]
+});
+
+const assignList = ref<TournamentsBindStructuresVO[]>([]);
+const assignSelectedList = ref<TournamentsBindStructuresVO[]>([]);
+const assignTotal = ref(0);
+
+const assignQuery = reactive<{
+  pageNum: number;
+  pageSize: number;
+  tournamentId: number | undefined;
+}>({
+  pageNum: 1,
+  pageSize: 10,
+  tournamentId: undefined
+});
+
 const initFormData: TournamentsForm = {
   id: undefined,
   name: undefined,
@@ -183,7 +259,7 @@ const data = reactive<PageData<TournamentsForm, TournamentsQuery>>({
     id: [{ required: true, message: '不能为空', trigger: 'blur' }],
     name: [{ required: true, message: '赛事名称不能为空', trigger: 'blur' }],
     startTime: [{ required: true, message: '比赛开始时间不能为空', trigger: 'blur' }],
-   /* gameType: [{ required: true, message: '游戏类型不能为空', trigger: 'change' }],*/
+    /* gameType: [{ required: true, message: '游戏类型不能为空', trigger: 'change' }],*/
     startingChips: [{ required: true, message: '起始记分牌数量不能为空', trigger: 'blur' }],
     levelDuration: [{ required: true, message: '级别持续时间不能为空', trigger: 'blur' }],
     lateRegistrationLevel: [{ required: true, message: '截止报名级别不能为空', trigger: 'blur' }],
@@ -291,4 +367,77 @@ const handleExport = () => {
 onMounted(() => {
   getList();
 });
+
+async function getAssignList() {
+  const res = await getSelectTournamentBlindStructuresList(assignQuery);
+  assignList.value = res.rows;
+  assignTotal.value = res.total;
+}
+
+async function openAssignDialog(row: TournamentsVO) {
+  assignForm.tournamentId = Number(row.id);
+  assignQuery.tournamentId = Number(row.id); // 这里明确转成 number
+  // 加载盲注列表
+/*  await getAssignList();*/
+  assignDialog.visible = true;
+  // 请求分配盲注结构列表
+  getAssignList().then(() => {
+    nextTick(() => {
+      initSelectedRows(); // 等待 DOM 完全渲染后再初始化选中状态
+    });
+  });
+}
+
+function handleAssignSelectionChange(selection: TournamentsBindStructuresVO[]) {
+  assignSelectedList.value = selection;
+  assignForm.selectedIds = selection.map((item) => item.blindStructuresId);
+}
+
+async function submitAssign() {
+  if (!assignForm.tournamentId || assignForm.selectedIds.length === 0) {
+    proxy?.$modal.msgError('请选择至少一个盲注结构');
+    return;
+  }
+
+  buttonLoading.value = true;
+  try {
+    await assignTournamentBlindStructures({
+      tournamentId: assignForm.tournamentId,
+      blindStructureIds: assignForm.selectedIds
+    });
+
+    proxy?.$modal.msgSuccess('分配成功');
+    assignDialog.visible = false;
+  } catch (err) {
+    proxy?.$modal.msgError('分配失败');
+  } finally {
+    buttonLoading.value = false;
+  }
+}
+
+const assignTable = ref(); // 对应 el-table 的 ref
+
+// 初始化选中行
+function initSelectedRows() {
+  const selected = assignList.value.filter((item) => item.allocationStatus === 1);
+  selected.forEach((item) => {
+    const row = assignList.value.find((r) => r.blindStructuresId === item.blindStructuresId);
+    if (row) {
+      assignTable.value?.toggleRowSelection(row, true);
+    }
+  });
+  assignForm.selectedIds = selected.map((item) => item.blindStructuresId);
+}
+
+watch(
+  () => assignList.value,
+  (newVal) => {
+    if (newVal.length > 0) {
+      nextTick(() => {
+        initSelectedRows();
+      });
+    }
+  },
+  { deep: true, immediate: true }
+);
 </script>