Просмотр исходного кода

feat(business): 增加套票功能并优化道具管理- 新增套票类型道具,支持多个子道具组合
- 添加道具类型选择和子道具配置功能
- 优化道具列表展示,增加类型值和积分值字段- 修复道具添加和修改功能,支持套票类型的数据保存

fugui001 3 месяцев назад
Родитель
Сommit
be119d430f
2 измененных файлов с 185 добавлено и 18 удалено
  1. 11 1
      src/api/system/business/items/types.ts
  2. 174 17
      src/views/system/business/items/index.vue

+ 11 - 1
src/api/system/business/items/types.ts

@@ -28,6 +28,8 @@ export interface ItemsVO {
    *
    */
   updatedAt: string;
+
+  itemsPrizeList?: ItemsPrize[];
 }
 
 export interface ItemsForm extends BaseEntity {
@@ -65,8 +67,16 @@ export interface ItemsForm extends BaseEntity {
    * 积分值
    */
   itemValue?: number;
-}
 
+  itemTypeCode?: string;
+
+  itemsPrizeList?: ItemsPrize[];
+}
+export interface ItemsPrize {
+  ranking: number;
+  itemId: number;
+  quantity: number;
+}
 export interface ItemsQuery extends PageQuery {
   /**
    * 道具名称

+ 174 - 17
src/views/system/business/items/index.vue

@@ -8,7 +8,6 @@
               <el-input v-model="queryParams.name" placeholder="请输入道具名称" clearable @keyup.enter="handleQuery" />
             </el-form-item>
 
-
             <el-form-item label="道具描述" prop="itemDesc">
               <el-input v-model="queryParams.itemDesc" placeholder="请输入道具描述" clearable @keyup.enter="handleQuery" />
             </el-form-item>
@@ -25,15 +24,15 @@
     <el-card shadow="never">
       <template #header>
         <el-row :gutter="10" class="mb8">
-<!--          <el-col :span="1.5">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['business:items:add']">新增</el-button>
-          </el-col>-->
+          <el-col :span="1.5">
+            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['business:items:add']">新增套票</el-button>
+          </el-col>
           <el-col :span="1.5">
             <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['business:items:edit']"
               >修改</el-button
             >
           </el-col>
-<!--          <el-col :span="1.5">
+          <!--          <el-col :span="1.5">
             <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['business:items:remove']"
               >删除</el-button
             >
@@ -49,7 +48,7 @@
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column label="" align="center" prop="id" v-if="false" />
         <el-table-column label="道具名称" align="center" prop="name" />
-        <el-table-column label="道具类型" align="center" prop="itemType" />
+        <el-table-column label="类型" align="center" prop="itemType" />
         <el-table-column label="积分值" align="center" prop="itemValue" />
         <el-table-column label="道具描述" align="center" prop="itemDesc" />
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -57,7 +56,7 @@
             <el-tooltip content="修改" placement="top">
               <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['business:items:edit']"></el-button>
             </el-tooltip>
-<!--            <el-tooltip content="删除" placement="top">
+            <!--            <el-tooltip content="删除" placement="top">
               <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['business:items:remove']"></el-button>
             </el-tooltip>-->
           </template>
@@ -66,24 +65,48 @@
 
       <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
-    <!-- 添加或修改道具对话框 -->
+    <!-- 添加或修改道具对话框 disabled-->
     <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
       <el-form ref="itemsFormRef" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="道具名称" prop="name">
           <el-input v-model="form.name" placeholder="请输入道具名称" />
         </el-form-item>
 
-        <el-form-item label="道具类型" prop="itemType">
-          <el-input v-model="form.itemType" placeholder="请输入道具类型" disabled/>
+        <el-form-item label="道具类型" prop="gameType">
+          <el-select aria-required="true" v-model="form.itemTypeCode" placeholder="请选择">
+            <el-option v-for="dict in tools_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+          </el-select>
         </el-form-item>
 
-        <el-form-item label="积分值" prop="itemValue">
+        <el-form-item label="类型值" prop="itemType">
+          <el-input v-model="form.itemType" placeholder="请输入类型值" />
+        </el-form-item>
+
+        <el-form-item label="积分值" prop="itemValue" v-if="form.itemTypeCode !== '2'">
           <el-input v-model="form.itemValue" placeholder="请输入积分值" />
         </el-form-item>
 
-        <el-form-item label="道具描述" prop="itemDesc">
+        <el-form-item label="道具描述" prop="itemDesc" v-if="form.itemTypeCode !== '2'">
           <el-input v-model="form.itemDesc" type="textarea" placeholder="请输入内容" />
         </el-form-item>
+
+        <el-form-item label="道具详情" v-if="form.itemTypeCode !== '1'">
+          <div v-for="(reward, index) in formPrize.rewards" :key="index" style="display: flex; align-items: center; margin-bottom: 8px">
+            <span>第{{ reward.ranking }}个</span>
+
+            <!-- 道具选择 -->
+            <el-select v-model="reward.itemId" placeholder="选项" style="width: 120px; margin-right: 8px">
+              <el-option v-for="item in itemOptions" :key="item.id" :label="item.label" :value="item.id" />
+            </el-select>
+
+            <!-- 数量输入 -->
+            <el-input v-model="reward.quantity" placeholder="请输入数量" style="width: 100px; margin-right: 8px" />
+
+            <!-- 操作按钮 -->
+            <el-button type="primary" @click="addReward" v-if="index === 0">+</el-button>
+            <el-button type="primary" @click="removeReward(index)" v-if="index !== 0">-</el-button>
+          </div>
+        </el-form-item>
       </el-form>
       <template #footer>
         <div class="dialog-footer">
@@ -101,7 +124,8 @@ import { ItemsVO, ItemsQuery, ItemsForm } from '@/api/system/business/items/type
 // ✅ 引入 parseTime
 import { parseTime } from '@/utils/dateUtils';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
+const { tournaments_type, tools_type } = toRefs<any>(proxy?.useDict('tournaments_type', 'tools_type'));
+import { selectItemsSelList } from '@/api/system/business/items';
 const itemsList = ref<ItemsVO[]>([]);
 const buttonLoading = ref(false);
 const loading = ref(true);
@@ -126,7 +150,8 @@ const initFormData: ItemsForm = {
   itemDesc: undefined,
   itemValue: undefined,
   createdAt: undefined,
-  updatedAt: undefined
+  updatedAt: undefined,
+  itemTypeCode: '1'
 };
 const data = reactive<PageData<ItemsForm, ItemsQuery>>({
   form: { ...initFormData },
@@ -145,7 +170,16 @@ const data = reactive<PageData<ItemsForm, ItemsQuery>>({
     itemType: [{ required: true, message: '道具类型不能为空', trigger: 'change' }]
   }
 });
-
+const formPrize = reactive({
+  // ...其他表单字段
+  rewards: [
+    {
+      ranking: 1,
+      itemId: null,
+      quantity: null
+    }
+  ]
+});
 const { queryParams, form, rules } = toRefs(data);
 
 /** 查询道具列表 */
@@ -191,6 +225,7 @@ const handleSelectionChange = (selection: ItemsVO[]) => {
 /** 新增按钮操作 */
 const handleAdd = () => {
   reset();
+  resetFormPrize();
   dialog.visible = true;
   dialog.title = '添加道具';
 };
@@ -198,9 +233,27 @@ const handleAdd = () => {
 /** 修改按钮操作 */
 const handleUpdate = async (row?: ItemsVO) => {
   reset();
+  resetFormPrize();
   const _id = row?.id || ids.value[0];
   const res = await getItems(_id);
   Object.assign(form.value, res.data);
+  // 处理奖励表单数据
+  const prizeItems = res.data.itemsPrizeList || [];
+  if (prizeItems.length > 0) {
+    formPrize.rewards = prizeItems.map((item, index) => ({
+      ranking: item.ranking || index + 1,
+      itemId: Number(item.itemId),
+      quantity: Number(item.quantity)
+    }));
+  } else {
+    formPrize.rewards = [
+      {
+        ranking: 1,
+        itemId: null,
+        quantity: null
+      }
+    ];
+  }
   dialog.visible = true;
   dialog.title = '修改道具';
 };
@@ -210,10 +263,52 @@ const submitForm = () => {
   itemsFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
       buttonLoading.value = true;
+      // ✅ 新增校验:如果是套票('2'),则必须有道具详情且数量不能为0
+      if (form.value.itemTypeCode === '2') {
+        // 检查是否存在有效道具详情
+        const validRewards = formPrize.rewards.filter(
+          (reward) =>
+            reward.itemId !== null &&
+            reward.itemId !== undefined &&
+            reward.itemId !== '' &&
+            reward.quantity !== null &&
+            reward.quantity !== undefined &&
+            reward.quantity !== ''
+        );
+
+        // 如果没有有效道具详情
+        if (validRewards.length === 0) {
+          ElMessage.error('请选择至少一个有效的道具详情');
+          buttonLoading.value = false;
+          return;
+        }
+
+        // 检查是否有数量为0或负数的情况
+        const invalidQuantity = validRewards.some(
+          (reward) => Number(reward.quantity) <= 0
+        );
+
+        if (invalidQuantity) {
+          ElMessage.error('道具数量必须大于0');
+          buttonLoading.value = false;
+          return;
+        }
+      }
+
+      // 构造最终要提交的数据对象
+      const formData: ItemsForm = {
+        ...data.form,
+        itemsPrizeList: formPrize.rewards.map((reward) => ({
+          ranking: Number(reward.ranking),
+          itemId: Number(reward.itemId),
+          quantity: Number(reward.quantity)
+        }))
+      };
+      debugger;
       if (form.value.id) {
-        await updateItems(form.value).finally(() => (buttonLoading.value = false));
+        await updateItems(formData).finally(() => (buttonLoading.value = false));
       } else {
-        await addItems(form.value).finally(() => (buttonLoading.value = false));
+        await addItems(formData).finally(() => (buttonLoading.value = false));
       }
       proxy?.$modal.msgSuccess('操作成功');
       dialog.visible = false;
@@ -241,8 +336,70 @@ const handleExport = () => {
     `道具${parseTime(new Date(), '{y}{m}{d}{h}{i}{s}')}.xlsx`
   );
 };
+const addReward = () => {
+  const currentLength = formPrize.rewards.length;
+
+  // 判断是否超过 itemOptions 的数量限制
+  if (currentLength < itemOptions.value.length) {
+    formPrize.rewards.push({
+      ranking: currentLength + 1, // 自动生成排名,从 1 开始
+      itemId: null,
+      quantity: null
+    });
+  } else {
+    ElMessage.warning(`最多只能添加 ${itemOptions.value.length} 个项`);
+  }
+};
+// 下拉选项数据 selectBlingStructuresInfo
+const itemOptions = ref<{ id: number; label: string }[]>([]);
+
+// 加载报名条件选项
+const loadItemOptions = async () => {
+  try {
+    const res = await selectItemsSelList();
+    if (res.code === 200) {
+      // 类型断言
+      const data = res.data as unknown as { id: number; name: string }[];
+
+      // 过滤掉 id === 2 的项,并映射为 { id, label }
+      itemOptions.value = data
+        .filter((item) => item.id !== 2) // ✅ 过滤 id 为 2 的
+        .filter((item) => item.id !== 2001) // ✅ 过滤 id 为 2 的
+        .map((item) => ({
+          id: item.id,
+          label: item.name
+        }));
+    } else {
+      ElMessage.error('加载失败:' + res.msg);
+    }
+  } catch (error) {
+    console.error('请求出错:', error);
+    ElMessage.error('请求失败,请检查网络');
+  }
+};
+const removeReward = (index: number) => {
+  formPrize.rewards.splice(index, 1);
 
+  // 删除后重新设置排名
+  formPrize.rewards.forEach((r, i) => {
+    r.ranking = i + 1;
+  });
+};
+// 用于保存原始的默认奖励结构
+const defaultReward = {
+  ranking: 1,
+  itemId: null,
+  quantity: null
+};
+
+// 重置函数
+const resetFormPrize = () => {
+  // 清空 rewards 并添加默认项
+  formPrize.rewards.splice(0); // 清空数组
+  formPrize.rewards.push({ ...defaultReward }); // 添加初始项
+};
 onMounted(() => {
+  loadItemOptions();
   getList();
 });
 </script>