Browse Source

feat(event-group-config): 添加决赛组别和调度设置功能

- 为决赛组别添加时间验证和动态显示名称
- 增加调度设置包括调度次数和间隔天数配置
- 更新表单验证规则并修复表单引用错误
- 添加新的字段映射和默认值设置
- 优化赛事标识和晋级条件界面布局
- 调整奖励内容提交逻辑和验证条件
- 修改分页大小从10调整为50条记录
- 临时注释部分奖励验证逻辑以优化流程
fugui001 3 weeks ago
parent
commit
c10e6636ca

+ 8 - 2
src/api/system/business/eventGroupConfig/types.ts

@@ -28,7 +28,10 @@ export interface EventGroupConfigVO {
    *
    */
   createdAt: string;
-
+  finalIntervalDays: number;
+  finalTime: string;
+  scheduleCount?: number;
+  scheduleIntervalDay?: number;
   /**
    * 组别列表
    */
@@ -65,7 +68,10 @@ export interface EventGroupConfigForm extends BaseEntity {
    */
   startDate?: string;
   finalStartDate?: string;
-
+  finalIntervalDays?: string | number;
+  finalTime?: string | number;
+  scheduleCount?: string | number;
+  scheduleIntervalDay?: string | number;
   /**
    *
    */

+ 52 - 11
src/views/system/business/eventGroupConfig/index.vue

@@ -160,9 +160,9 @@
             <el-button type="primary" icon="Minus" @click="removeGroup(index)" v-else style="width: 40px; height: 40px" />
           </div>
         </el-form-item>
-        <el-form-item label="决赛组别">
+        <el-form-item label="决赛组别" prop="finalTime">
           <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px">
-            <span style="width: 60px">决赛组</span>
+            <span style="width: 60px"> {{ groupForm.finalName }}</span>
             间隔天数:<el-input-number
               v-model="groupForm.finalIntervalDays"
               :min="0"
@@ -193,7 +193,28 @@
           />
         </el-form-item>
       </el-form>
-
+      <el-form-item label="调度设置" prop="scheduleCount">
+        <div style="display: flex; align-items: center; gap: 20px">
+          <span>调度次数:</span>
+          <el-input-number
+            v-model="groupForm.scheduleCount"
+            :min="1"
+            :max="31"
+            controls-position="right"
+            placeholder="调度次数"
+            style="width: 120px"
+          />
+          <span>间隔天数:</span>
+          <el-input-number
+            v-model="groupForm.scheduleIntervalDay"
+            :min="0"
+            :max="7"
+            controls-position="right"
+            placeholder="间隔天数"
+            style="width: 120px"
+          />
+        </div>
+      </el-form-item>
       <template #footer>
         <div class="dialog-footer">
           <el-button :loading="buttonLoading" @click="submitGroupForm" type="primary">确 定</el-button>
@@ -231,6 +252,7 @@ const total = ref(0);
 
 const queryFormRef = ref<ElFormInstance>();
 const eventGroupConfigFormRef = ref<ElFormInstance>();
+const groupFormRef = ref<ElFormInstance>();
 
 const dialog = reactive<DialogOption>({
   visible: false,
@@ -284,7 +306,7 @@ const cancel = () => {
 /** 表单重置 */
 const reset = () => {
   form.value = { ...initFormData };
-  eventGroupConfigFormRef.value?.resetFields();
+  groupFormRef.value?.resetFields();
 };
 
 /** 搜索按钮操作 */
@@ -324,8 +346,11 @@ const resetAll = () => {
     finalStartDate: '',
     generateDays: 1,
     name: '',
+    finalName: '决赛组',
     finalIntervalDays: 0,
-    finalTime: ''
+    finalTime: '',
+    scheduleCount: 0,
+    scheduleIntervalDay: 0
   };
 
   // 重置 groupList
@@ -344,6 +369,7 @@ const handleUpdate = async (row?: EventGroupConfigVO) => {
     Object.assign(form.value, res.data);
     form.value.regularTemplateId = Number(res.data.regularTemplateId);
     form.value.finalTemplateId = Number(res.data.finalTemplateId);
+    form.value.finalStartDate = res.data.finalStartDate;
     // 处理 groupList 数据
     if (res.data.groups && Array.isArray(res.data.groups)) {
       groupList.value = res.data.groups.map((group) => ({
@@ -362,7 +388,10 @@ const handleUpdate = async (row?: EventGroupConfigVO) => {
     groupForm.value.startDate = res.data.startDate;
     groupForm.value.name = res.data.name;
     groupForm.value.finalStartDate = res.data.finalStartDate;
-
+    groupForm.value.finalIntervalDays = res.data.finalIntervalDays;
+    groupForm.value.finalTime = res.data.finalTime;
+    groupForm.value.scheduleCount = res.data.scheduleCount;
+    groupForm.value.scheduleIntervalDay = res.data.scheduleIntervalDay;
     dialog.title = '修改';
   } else {
     // 新增情况
@@ -421,7 +450,6 @@ const handleBlindStructureChange = async () => {
     console.error('请求出错:', error);
   }
 };
-
 // 组别表单数据
 const groupForm = ref<{
   regularTemplateId: string | number;
@@ -430,8 +458,11 @@ const groupForm = ref<{
   finalStartDate: string;
   generateDays: number;
   name: string;
+  finalName: string;
   finalIntervalDays: number;
   finalTime: string;
+  scheduleCount: number;
+  scheduleIntervalDay: number;
 }>({
   regularTemplateId: '',
   finalTemplateId: '',
@@ -439,8 +470,11 @@ const groupForm = ref<{
   finalStartDate: '',
   generateDays: 1,
   name: '',
+  finalName: '决赛组',
   finalIntervalDays: 0,
-  finalTime: ''
+  finalTime: '',
+  scheduleCount: 0,
+  scheduleIntervalDay: 0
 });
 
 // 组别列表(修改为包含时间和名称的对象数组)
@@ -450,8 +484,11 @@ const groupRules = {
   name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
   startDate: [{ required: true, message: '常规组日期不能为空', trigger: 'blur' }],
   finalStartDate: [{ required: true, message: '决赛组日期不能为空', trigger: 'blur' }],
+  scheduleCount: [{ required: true, message: '调度次数不能为空', trigger: 'blur' }],
+  scheduleIntervalDay: [{ required: true, message: '间隔天数不能为空', trigger: 'blur' }],
   regularTemplateId: [{ required: true, message: '请输入组别模板名称', trigger: 'blur' }],
-  finalTemplateId: [{ required: true, message: '请选择赛制类型', trigger: 'change' }]
+  finalTemplateId: [{ required: true, message: '请选择赛制类型', trigger: 'change' }],
+  finalTime: [{ required: true, message: '决赛组时间不能为空', trigger: 'change' }]
 };
 
 // 添加组别方法(修改)
@@ -499,17 +536,21 @@ const removeGroup = (index: number) => {
 const submitGroupForm = async () => {
   try {
     // 验证表单
-    await eventGroupConfigFormRef.value?.validate();
+    await groupFormRef.value?.validate();
 
     buttonLoading.value = true;
 
-    // 将 groupForm 和 groupList 数据整合到 form.value 中
+    // 将 groupForm 和 groupList 数据整合到 form.value 中 "groupForm.finalTime" groupForm.finalIntervalDays
     form.value = {
       ...form.value,
       regularTemplateId: groupForm.value.regularTemplateId,
       finalTemplateId: groupForm.value.finalTemplateId,
       startDate: groupForm.value.startDate,
       finalStartDate: groupForm.value.finalStartDate,
+      finalIntervalDays: groupForm.value.finalIntervalDays,
+      finalTime: groupForm.value.finalTime,
+      scheduleIntervalDay: groupForm.value.scheduleIntervalDay,
+      scheduleCount: groupForm.value.scheduleCount,
       name: groupForm.value.name || '', // 如果名称字段在 groupForm 中
       groups: groupList.value.map((group) => ({
         groupName: group.name,

+ 2 - 2
src/views/system/business/tournamentsTemplate/index.vue

@@ -1131,10 +1131,10 @@ const handleUpdate = async (row?: TournamentsVO, mode: 'edit' | 'view' = 'edit')
 const submitForm = () => {
   tournamentsFormRef.value?.validate(async (valid: boolean) => {
     // 校验奖励内容是否至少填写了一项
-    if (!formPrize.rewards.some((r) => r.itemId && r.quantity)) {
+   /* if (!formPrize.rewards.some((r) => r.itemId && r.quantity)) {
       ElMessage.warning('请至少填写一项奖励内容');
       return;
-    }
+    }*/
 
     if (!valid) return;
     try {

+ 1 - 1
src/views/system/business/type/index.vue

@@ -186,7 +186,7 @@ const data = reactive<PageData<TypeForm, TypeQuery>>({
   form: { ...initFormData },
   queryParams: {
     pageNum: 1,
-    pageSize: 10,
+    pageSize: 50,
     name: undefined,
     typeCode: undefined,
     typeValue: undefined,

+ 46 - 69
src/views/system/physical/tournaments/index.vue

@@ -394,19 +394,9 @@
           </div>
         </el-form-item>
 
-
         <el-form-item label="赛事标识" prop="tournamentType">
-          <el-select
-            v-model="form.tournamentType"
-            placeholder="请选择"
-            :disabled="dialog.mode === 'view'"
-          >
-            <el-option
-              v-for="item in tournamentTypeOptions"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            />
+          <el-select v-model="form.tournamentType" placeholder="请选择" :disabled="dialog.mode === 'view'">
+            <el-option v-for="item in tournamentTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
         <el-form-item label="目标锦标赛" prop="targetTournamentId" v-if="form.tournamentType === 1">
@@ -419,19 +409,10 @@
             :loading="selectLoading"
             clearable
           >
-            <el-option
-              v-for="item in selectOptions"
-              :key="item.id"
-              :label="item.label"
-              :value="item.id"
-            />
+            <el-option v-for="item in selectOptions" :key="item.id" :label="item.label" :value="item.id" />
           </el-select>
-         </el-form-item>
-        <el-form-item
-          label="晋级条件类型"
-          prop="qualifierType"
-          v-if="form.tournamentType === 1"
-        >
+        </el-form-item>
+        <el-form-item label="晋级条件类型" prop="qualifierType" v-if="form.tournamentType === 1">
           <el-select
             aria-required="true"
             v-model="form.qualifierType"
@@ -443,35 +424,13 @@
           </el-select>
         </el-form-item>
 
-        <el-form-item
-          label="晋级条件值"
-          prop="qualifierValue"
-          v-if="form.tournamentType === 1 && form.qualifierType === '2'"
-        >
-          <el-input
-            v-model="form.qualifierValue"
-            placeholder="请输入晋级条件值"
-            :disabled="dialog.mode === 'view'"
-          />
+        <el-form-item label="晋级条件值" prop="qualifierValue" v-if="form.tournamentType === 1 && form.qualifierType === '2'">
+          <el-input v-model="form.qualifierValue" placeholder="请输入晋级条件值" :disabled="dialog.mode === 'view'" />
         </el-form-item>
 
-        <el-form-item
-          label="晋级级别"
-          prop="qualifierValue"
-          v-if="form.tournamentType === 1 && form.qualifierType === '1'"
-        >
-          <el-select
-            v-model="form.qualifierValue"
-            placeholder="选项"
-            style="width: 200px"
-            :disabled="dialog.mode === 'view'"
-          >
-            <el-option
-              v-for="item in itemOptionsStructuresLevel2"
-              :key="item.id"
-              :label="item.label"
-              :value="item.id"
-            />
+        <el-form-item label="晋级级别" prop="qualifierValue" v-if="form.tournamentType === 1 && form.qualifierType === '1'">
+          <el-select v-model="form.qualifierValue" placeholder="选项" style="width: 200px" :disabled="dialog.mode === 'view'">
+            <el-option v-for="item in itemOptionsStructuresLevel2" :key="item.id" :label="item.label" :value="item.id" />
           </el-select>
         </el-form-item>
       </el-form>
@@ -497,7 +456,14 @@
 </template>
 
 <script setup name="Tournaments" lang="ts">
-import { listTournaments, getTournaments, delTournaments, addTournaments, updateTournaments, selectPhysicalTournamentsLeagueId } from '@/api/system/physical/tournaments';
+import {
+  listTournaments,
+  getTournaments,
+  delTournaments,
+  addTournaments,
+  updateTournaments,
+  selectPhysicalTournamentsLeagueId
+} from '@/api/system/physical/tournaments';
 import { TournamentsVO, TournamentsQuery, TournamentsForm } from '@/api/system/physical/tournaments/types';
 import { selectItemsSelList, selectXianXiaItemsSelList } from '@/api/system/business/items';
 import { selectPhysicalBlingStructuresInfo } from '@/api/system/physical/blindStructures';
@@ -512,7 +478,7 @@ import { JudgeVO } from '@/api/system/physical/judge/types';
 import { ElSelect } from 'element-plus';
 import { ref } from 'vue';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { game_variant_type, tournaments_time, physical_tournaments_type , qualifier_type } = toRefs<any>(
+const { game_variant_type, tournaments_time, physical_tournaments_type, qualifier_type } = toRefs<any>(
   proxy?.useDict('game_variant_type', 'tournaments_time', 'physical_tournaments_type', 'qualifier_type')
 );
 const tournamentsList = ref<TournamentsVO[]>([]);
@@ -569,7 +535,7 @@ const initFormData: TournamentsForm = {
   targetTournamentId: undefined,
   qualifierType: undefined,
   qualifierValue: undefined,
-  tournamentType: 0, // 👈 默认普通赛
+  tournamentType: 0 // 👈 默认普通赛
 };
 const data = reactive<PageData<TournamentsForm, TournamentsQuery>>({
   form: { ...initFormData },
@@ -617,9 +583,16 @@ const data = reactive<PageData<TournamentsForm, TournamentsQuery>>({
     lateRegistrationLevel: [{ required: true, message: '截止报名级别不能为空', trigger: 'change' }],
     signTime: [{ required: true, message: '报名时间不能为空', trigger: 'change' }],
     // ...其他规则
+    // ... existing code ...
     itemsId: [
       {
         validator: (rule, value, callback) => {
+          // 当 tournamentType 为 1(卫星赛)时,不进行校验
+          if (data.form.tournamentType === 1) {
+            callback();
+            return;
+          }
+
           // 检查是否至少有一个报名条件被设置
           const hasValidCondition = formConditions.conditions.some((condition) => condition.itemId && condition.quantity);
 
@@ -850,13 +823,13 @@ const handleUpdate = async (row?: TournamentsVO, mode: 'edit' | 'view' = 'edit')
       quantity: Number(item.quantity)
     }));
   } else {
-    formPrize.rewards = [
+    /*formPrize.rewards = [
       {
         ranking: 1,
         itemId: null,
         quantity: null
       }
-    ];
+    ];*/
   }
   // ✅ 主动触发盲注等级加载
   if (form.value.blindStructureId) {
@@ -871,11 +844,12 @@ const handleUpdate = async (row?: TournamentsVO, mode: 'edit' | 'view' = 'edit')
 const submitForm = () => {
   tournamentsFormRef.value?.validate(async (valid: boolean) => {
     // 校验奖励内容是否至少填写了一项
-    if (!formPrize.rewards.some((r) => r.itemId && r.quantity)) {
-      ElMessage.warning('请至少填写一项奖励内容');
-      return;
-    }
-
+   /* if (data.form.tournamentType !== 1) {
+      if (!formPrize.rewards.some((r) => r.itemId && r.quantity)) {
+        ElMessage.warning('请至少填写一项奖励内容');
+        return;
+      }
+    }*/
     if (!valid) return;
     try {
       buttonLoading.value = true;
@@ -884,11 +858,6 @@ const submitForm = () => {
       const formData: TournamentsForm = {
         ...data.form,
         competitionIcon: data.form.competitionIcon, // 确保 iconUrl 存在
-        itemsPrizeList: formPrize.rewards.map((reward) => ({
-          ranking: Number(reward.ranking),
-          itemId: Number(reward.itemId),
-          quantity: Number(reward.quantity)
-        })),
         // 添加报名条件数据
         itemsConditionList: formConditions.conditions
           .filter((condition) => condition.itemId && condition.quantity) // 过滤掉未填写的条件
@@ -898,6 +867,16 @@ const submitForm = () => {
             quantity: Number(condition.quantity)
           }))
       };
+      // 只有在有奖励数据时才添加 itemsPrizeList
+      if (formPrize.rewards && formPrize.rewards.length > 0) {
+        formData.itemsPrizeList = formPrize.rewards
+          .filter((reward) => reward.itemId && reward.itemId !== 0) // 过滤掉 itemId 为 0 的项
+          .map((reward) => ({
+            ranking: Number(reward.ranking),
+            itemId: Number(reward.itemId),
+            quantity: Number(reward.quantity)
+          }));
+      }
       // 提交数据(区分新增/编辑)
       let response;
       if (formData.id) {
@@ -1416,8 +1395,6 @@ const loadTargetTournaments = (query: string) => {
     return;
   }
   // 这里可加模糊搜索逻辑(如 filter)
-  selectOptions.value = leagueRelatedTournaments.value.filter(item =>
-    item.name.toLowerCase().includes(query.toLowerCase())
-  );
+  selectOptions.value = leagueRelatedTournaments.value.filter((item) => item.name.toLowerCase().includes(query.toLowerCase()));
 };
 </script>