Kaynağa Gözat

fix(group-package):优化表单验证与菜品选择逻辑

- 修改 selectedDishId 类型以支持字符串和数字
-优化新增分组时的表单验证清除逻辑,使用 nextTick 和 setTimeout 确保 DOM 更新完成
- 统一触发表单验证的方法,使用 packageFormRef 替代 ruleFormRef
- 新增清除新增菜品验证状态的逻辑,避免立即显示验证错误- 改进菜品列表过滤方法,排除已在其他分组中选择的菜品,但保留当前编辑项
- 调整 filterDishList 执行顺序以确保选中状态正确设置
congxuesong 1 ay önce
ebeveyn
işleme
7c6ac7954c
1 değiştirilmiş dosya ile 88 ekleme ve 17 silme
  1. 88 17
      src/views/groupPackageManagement/newGroup.vue

+ 88 - 17
src/views/groupPackageManagement/newGroup.vue

@@ -918,7 +918,7 @@ const lifeGroupBuyThalis = ref([
 const dishDialogVisible = ref(false);
 const dishSearchKeyword = ref("");
 const filteredDishList: any = ref([]);
-const selectedDishId = ref<number | null>(null);
+const selectedDishId = ref<number | string | null>(null);
 const currentDishGroupIndex = ref<number>(-1);
 const currentDishIndex = ref<number>(-1);
 
@@ -1317,13 +1317,26 @@ const addGroup = () => {
   groupCollapsedStates.value.push(false);
 
   // 清除表单验证状态,避免新分组显示验证错误
-  // 只清除验证状态,不重新触发验证
-  // 让用户操作时(如点击添加菜品)再触发验证
+  // 使用延迟清除,确保在验证规则更新和 DOM 渲染完成后再清除
   nextTick(() => {
-    if (packageFormRef.value) {
-      packageFormRef.value.clearValidate();
-    }
-    skipLastGroupValidation = false;
+    requestAnimationFrame(() => {
+      setTimeout(() => {
+        if (packageFormRef.value) {
+          // 只清除新添加分组的验证状态
+          const newGroupIndex = lifeGroupBuyThalis.value.length - 1;
+          const propsToClear = [
+            `groups.${newGroupIndex}.groupName`,
+            `groups.${newGroupIndex}.dishes.0.detailId`,
+            `groups.${newGroupIndex}.dishes.0.qty`
+          ];
+          // Element Plus 的 clearValidate 可以接受字符串数组
+          propsToClear.forEach(prop => {
+            packageFormRef.value?.clearValidate(prop);
+          });
+        }
+        skipLastGroupValidation = false;
+      }, 150);
+    });
   });
 };
 
@@ -1428,7 +1441,9 @@ const addDish = (groupIndex: number) => {
     ElMessage.warning("请先完成现有菜品的填写");
     // 触发表单验证,显示验证错误
     nextTick(() => {
-      ruleFormRef.value?.validateField("lifeGroupBuyThalis");
+      if (packageFormRef.value) {
+        packageFormRef.value.validate(() => {});
+      }
     });
     return;
   }
@@ -1438,7 +1453,9 @@ const addDish = (groupIndex: number) => {
     ElMessage.warning("请先完成现有菜品的填写");
     // 触发表单验证,显示验证错误
     nextTick(() => {
-      ruleFormRef.value?.validateField("lifeGroupBuyThalis");
+      if (packageFormRef.value) {
+        packageFormRef.value.validate(() => {});
+      }
     });
     return;
   }
@@ -1452,7 +1469,9 @@ const addDish = (groupIndex: number) => {
       ElMessage.warning("请先完成现有菜品的填写");
       // 触发表单验证,显示验证错误
       nextTick(() => {
-        ruleFormRef.value?.validateField("lifeGroupBuyThalis");
+        if (packageFormRef.value) {
+          packageFormRef.value.validate(() => {});
+        }
       });
       return;
     }
@@ -1462,7 +1481,9 @@ const addDish = (groupIndex: number) => {
       ElMessage.warning("请先完成现有菜品的填写");
       // 触发表单验证,显示验证错误
       nextTick(() => {
-        ruleFormRef.value?.validateField("lifeGroupBuyThalis");
+        if (packageFormRef.value) {
+          packageFormRef.value.validate(() => {});
+        }
       });
       return;
     }
@@ -1473,7 +1494,9 @@ const addDish = (groupIndex: number) => {
       ElMessage.warning("请先完成现有菜品的填写");
       // 触发表单验证,显示验证错误
       nextTick(() => {
-        ruleFormRef.value?.validateField("lifeGroupBuyThalis");
+        if (packageFormRef.value) {
+          packageFormRef.value.validate(() => {});
+        }
       });
       return;
     }
@@ -1491,6 +1514,27 @@ const addDish = (groupIndex: number) => {
     qty: "",
     dishesUnit: ""
   });
+
+  // 清除新添加菜品的验证状态,避免立即显示验证错误
+  // 使用延迟清除,确保在验证规则更新和 DOM 渲染完成后再清除
+  nextTick(() => {
+    requestAnimationFrame(() => {
+      setTimeout(() => {
+        if (packageFormRef.value) {
+          // 只清除新添加菜品的验证状态
+          const newDishIndex = group.dishes.length - 1;
+          const propsToClear = [
+            `groups.${groupIndex}.dishes.${newDishIndex}.detailId`,
+            `groups.${groupIndex}.dishes.${newDishIndex}.qty`
+          ];
+          // Element Plus 的 clearValidate 可以接受字符串
+          propsToClear.forEach(prop => {
+            packageFormRef.value?.clearValidate(prop);
+          });
+        }
+      }, 150);
+    });
+  });
 };
 
 /**
@@ -1525,10 +1569,10 @@ const openDishDialog = async (groupIndex: number, dishIndex: number) => {
   if (res && res.code == 200) {
     dishOptions.value = res.data;
   }
-  filterDishList();
   // 如果已有选中的菜品,设置选中状态
   const currentDish = lifeGroupBuyThalis.value[groupIndex].dishes[dishIndex];
   selectedDishId.value = currentDish?.detailId || null;
+  filterDishList();
   dishDialogVisible.value = true;
 };
 
@@ -1569,14 +1613,41 @@ const confirmDishSelection = () => {
 
 /**
  * 过滤菜品列表
+ * 排除已经在其他分组中被选择的菜品(当前正在编辑的菜品除外)
  */
 const filterDishList = () => {
-  if (!dishSearchKeyword.value || dishSearchKeyword.value.trim() === "") {
-    filteredDishList.value = [...dishOptions.value];
-  } else {
+  // 获取当前正在编辑的菜品ID(如果有)
+  const currentDishId = selectedDishId.value;
+
+  // 收集所有其他分组中已选择的菜品ID
+  const selectedDishIds = new Set<number | string>();
+  lifeGroupBuyThalis.value.forEach((group, groupIndex) => {
+    if (group.dishes && group.dishes.length > 0) {
+      group.dishes.forEach((dish, dishIndex) => {
+        // 排除当前正在编辑的菜品
+        if (dish.detailId && !(groupIndex === currentDishGroupIndex.value && dishIndex === currentDishIndex.value)) {
+          selectedDishIds.add(dish.detailId);
+        }
+      });
+    }
+  });
+
+  // 先根据搜索关键词过滤
+  let filtered = dishOptions.value;
+  if (dishSearchKeyword.value && dishSearchKeyword.value.trim() !== "") {
     const keyword = dishSearchKeyword.value.trim().toLowerCase();
-    filteredDishList.value = dishOptions.value.filter(dish => dish.dishName.toLowerCase().includes(keyword));
+    filtered = dishOptions.value.filter(dish => dish.dishName.toLowerCase().includes(keyword));
   }
+
+  // 再排除已在其他分组中被选择的菜品(但保留当前正在编辑的菜品)
+  filteredDishList.value = filtered.filter(dish => {
+    // 如果是当前正在编辑的菜品,保留
+    if (currentDishId && dish.id === currentDishId) {
+      return true;
+    }
+    // 如果菜品已在其他分组中被选择,排除
+    return !selectedDishIds.has(dish.id);
+  });
 };
 
 // ==================== 表单引用 ====================