<template>
  <!-- 团购包管理 - 新增/编辑页面 -->
  <div class="table-box" style="width: 100%; min-height: 100%; background-color: white">
    <div class="header">
      <el-button @click="goBack"> 返回 </el-button>
      <h2 class="title">新建团购</h2>
    </div>
    <el-form :model="storeInfoModel" ref="ruleFormRef" :rules="rules" label-width="120px" class="formBox">
      <div class="content">
        <!-- 左侧内容区域 -->
        <div class="contentLeft">
          <!-- 基础信息模块 -->
          <div class="model">
            <h3 style="font-weight: bold">基础信息：</h3>
            <!-- 团购图片上传 prop="imageValueStr" 本地服务测不了上传图片 先去掉必填-->
            <el-form-item label="图片">
              <div class="upload-area" :class="{ 'upload-full': uploadedImageCount >= uploadMaxCount }">
                <el-upload
                  ref="uploadRef"
                  v-model:file-list="storeInfoModel.imageValueStr"
                  list-type="picture-card"
                  :accept="'.jpg,.png'"
                  :limit="uploadMaxCount"
                  :auto-upload="false"
                  :disabled="hasUnuploadedImages"
                  multiple
                  :on-change="handleUploadChange"
                  :on-exceed="handleUploadExceed"
                  :on-preview="handlePictureCardPreview"
                  :before-remove="handleBeforeRemove"
                  :on-remove="handleRemove"
                  :show-file-list="true"
                >
                  <template #trigger>
                    <div v-if="uploadedImageCount < uploadMaxCount" class="upload-trigger-card el-upload--picture-card">
                      <el-icon>
                        <Plus />
                      </el-icon>
                      <div class="upload-tip">({{ uploadedImageCount }}/{{ uploadMaxCount }})</div>
                    </div>
                  </template>
                </el-upload>
              </div>
            </el-form-item>
            <!-- 团购名称 -->
            <el-form-item label="团购名称" prop="groupName">
              <el-input maxlength="30" v-model="storeInfoModel.groupName" placeholder="请填写团购名称" clearable />
            </el-form-item>
            <!-- 开始售卖时间设置方式 -->
            <el-form-item label="开始售卖时间" prop="startTimeType">
              <el-radio-group v-model="storeInfoModel.startTimeType" class="ml-4">
                <el-radio v-for="status in storeStatusList" :value="status.value" :key="status.value">
                  {{ status.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
            <!-- 自定义开始售卖时间（当选择"设置售卖时间"时显示） -->
            <el-form-item label="" prop="startTimeValue" v-if="storeInfoModel.startTimeType == 1">
              <el-date-picker
                v-model="storeInfoModel.startTimeValue"
                format="YYYY/MM/DD"
                value-format="YYYY-MM-DD"
                placeholder="请选择开始售卖时间"
                :disabled-date="disabledStartDate"
              />
            </el-form-item>
            <!-- 结束售卖时间 -->
            <el-form-item label="结束售卖时间" prop="endTime">
              <el-date-picker
                v-model="storeInfoModel.endTime"
                format="YYYY/MM/DD"
                value-format="YYYY-MM-DD"
                placeholder="请选择结束售卖时间"
                :disabled-date="disabledEndDate"
              />
            </el-form-item>
            <!-- 库存数量 -->
            <el-form-item label="库存数量" prop="inventoryNum">
              <el-input v-model="storeInfoModel.inventoryNum" maxlength="15" placeholder="请填写库存数量" clearable />
            </el-form-item>
            <!-- 每人限购设置 -->
            <el-form-item label="每人限购" prop="quotaType">
              <el-radio-group v-model="storeInfoModel.quotaType" class="ml-4">
                <el-radio v-for="status in perList" :value="status.value" :key="status.value">
                  {{ status.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
            <!-- 自定义限购数量（当选择"自定义限购数量"时显示） -->
            <el-form-item label="" prop="quotaValue" v-if="storeInfoModel.quotaType == 1">
              <el-input v-model="storeInfoModel.quotaValue" maxlength="15" placeholder="请填写自定义限购数量" clearable />
            </el-form-item>
            <!-- 套餐内容 -->
            <el-form-item label="套餐内容" class="package-content-item">
              <el-form
                ref="packageFormRef"
                :model="packageFormModel"
                :rules="packageFormRules"
                label-width="0"
                class="package-content-form"
              >
                <div class="package-content-wrapper">
                  <div class="package-content-header">
                    <el-button type="primary" @click="addGroup" class="add-group-btn"> 添加分组 </el-button>
                    <el-button
                      type="primary"
                      link
                      @click="toggleAllGroupsCollapse"
                      :icon="allGroupsCollapsed ? ArrowDown : ArrowUp"
                      v-show="lifeGroupBuyThalis.length > 1"
                    >
                      {{ allGroupsCollapsed ? "展开全部" : "收起全部" }}
                    </el-button>
                  </div>
                  <transition-group name="group-fade" tag="div" class="package-content-container">
                    <div v-for="item in visibleGroups" :key="item.originalIndex" class="package-group">
                      <div class="package-group-header">
                        <span class="group-index">{{ item.group.groupName }}</span>
                        <div class="header-right">
                          <el-button
                            type="primary"
                            link
                            @click="toggleGroupCollapse(item.originalIndex)"
                            :icon="isGroupCollapsed(item.originalIndex) ? ArrowDown : ArrowUp"
                            v-show="item.group.dishes.length > 1"
                          >
                            {{ isGroupCollapsed(item.originalIndex) ? "展开" : "收起" }}
                          </el-button>
                          <el-button
                            type="danger"
                            link
                            @click="removeGroup(item.originalIndex)"
                            :icon="Delete"
                            v-show="lifeGroupBuyThalis.length > 1"
                          >
                            删除
                          </el-button>
                        </div>
                      </div>
                      <div class="package-group-content">
                        <el-form-item
                          :prop="`groups.${item.originalIndex}.groupName`"
                          :rules="packageFormRules[`groups.${item.originalIndex}.groupName`]"
                          class="category-form-item"
                        >
                          <div class="category-row">
                            <span class="label">类别</span>
                            <el-input v-model="item.group.groupName" placeholder="请输入" maxlength="10" clearable />
                          </div>
                        </el-form-item>
                        <!-- 第一行菜品，始终显示 -->
                        <div v-if="item.group.dishes && item.group.dishes.length > 0" class="dish-row">
                          <el-form-item
                            :prop="`groups.${item.originalIndex}.dishes.0.detailId`"
                            :rules="packageFormRules[`groups.${item.originalIndex}.dishes.0.detailId`]"
                            class="dish-form-item"
                          >
                            <span class="label">菜品</span>
                            <div class="dish-select-block" @click="openDishDialog(item.originalIndex, 0)">
                              <span v-if="item.group.dishes[0].dishName" class="dish-selected-name"
                                >{{ item.group.dishes[0].dishName }}，¥{{ item.group.dishes[0].dishPrice }}/{{
                                  item.group.dishes[0].dishesUnit
                                }}</span
                              >
                              <span v-else class="dish-placeholder">请选择</span>
                            </div>
                          </el-form-item>
                          <el-form-item
                            :prop="`groups.${item.originalIndex}.dishes.0.qty`"
                            :rules="packageFormRules[`groups.${item.originalIndex}.dishes.0.qty`]"
                            class="dish-form-item"
                          >
                            <span class="label">数量</span>
                            <el-input v-model="item.group.dishes[0].qty" placeholder="请输入" clearable class="quantity-input" />
                            <el-button
                              :icon="Delete"
                              link
                              type="danger"
                              @click="removeDish(item.originalIndex, 0)"
                              class="delete-dish-btn"
                              v-show="item.group.dishes.length > 1"
                            />
                          </el-form-item>
                        </div>
                        <!-- 第二行及以后的菜品，收起时隐藏 -->
                        <transition name="slide-fade">
                          <div v-if="!isGroupCollapsed(item.originalIndex)" class="extra-dishes-container">
                            <div
                              v-for="(dish, dishIndex) in item.group.dishes"
                              :key="dishIndex"
                              class="dish-row"
                              v-show="dishIndex > 0"
                            >
                              <el-form-item
                                :prop="`groups.${item.originalIndex}.dishes.${dishIndex}.detailId`"
                                :rules="packageFormRules[`groups.${item.originalIndex}.dishes.${dishIndex}.detailId`]"
                                class="dish-form-item"
                              >
                                <span class="label">菜品</span>
                                <div class="dish-select-block" @click="openDishDialog(item.originalIndex, dishIndex)">
                                  <span v-if="dish.dishName" class="dish-selected-name"
                                    >{{ dish.dishName }}，¥{{ dish.dishPrice }}/{{ dish.dishesUnit }}</span
                                  >
                                  <span v-else class="dish-placeholder">请选择</span>
                                </div>
                              </el-form-item>
                              <el-form-item
                                :prop="`groups.${item.originalIndex}.dishes.${dishIndex}.qty`"
                                :rules="packageFormRules[`groups.${item.originalIndex}.dishes.${dishIndex}.qty`]"
                                class="dish-form-item"
                              >
                                <span class="label">数量</span>
                                <el-input v-model="dish.qty" placeholder="请输入" clearable class="quantity-input" />
                                <el-button
                                  :icon="Delete"
                                  link
                                  type="danger"
                                  @click="removeDish(item.originalIndex, dishIndex)"
                                  class="delete-dish-btn"
                                />
                              </el-form-item>
                            </div>
                            <el-button type="primary" @click="addDish(item.originalIndex)" class="add-dish-btn"> 添加 </el-button>
                          </div>
                        </transition>
                      </div>
                    </div>
                  </transition-group>
                </div>
              </el-form>
            </el-form-item>
          </div>
          <!-- 价格信息模块 -->
          <div class="model">
            <h3 style="font-weight: bold">价格：</h3>
            <!-- 原价 -->
            <el-form-item label="原价" prop="originalPrice">
              <el-input maxlength="50" v-model="storeInfoModel.originalPrice" placeholder="请填写原价" clearable />
            </el-form-item>
            <!-- 优惠价 -->
            <el-form-item label="优惠价" prop="preferentialPrice">
              <el-input maxlength="50" v-model="storeInfoModel.preferentialPrice" placeholder="请填写优惠价" clearable />
            </el-form-item>
          </div>
        </div>
        <!-- 右侧内容区域 -->
        <div class="contentRight">
          <!-- 购买须知模块 -->
          <div class="model">
            <h3 style="font-weight: bold">购买须知：</h3>
            <el-form-item label="有效期" prop="effectiveDateType">
              <el-radio-group v-model="storeInfoModel.effectiveDateType" class="ml-4">
                <el-radio v-for="status in expirationDateStatusList" :value="status.value" :key="status.value">
                  {{ status.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
            <el-form-item label="" prop="expirationDate" v-if="storeInfoModel.effectiveDateType == 0">
              <div class="expiration-date-container">
                <span class="expiration-label">用户购买</span>
                <el-input-number v-model="storeInfoModel.expirationDate" placeholder="请输入" :min="0" class="expiration-input" />
                <span class="expiration-label">天内有效</span>
              </div>
            </el-form-item>
            <el-form-item label="" prop="expirationDateList" v-else>
              <el-date-picker
                v-model="storeInfoModel.expirationDateList"
                type="daterange"
                value-format="YYYY-MM-DD"
                range-separator="-"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                :disabled-date="disabledEffectiveDate"
              />
            </el-form-item>
            <el-form-item label="不可用日期" prop="disableDateType">
              <el-radio-group v-model="storeInfoModel.disableDateType" class="ml-4">
                <el-radio v-for="status in unavailableDatesList" :value="status.value" :key="status.value">
                  {{ status.label }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
            <template v-if="storeInfoModel.disableDateType == 1">
              <el-form-item label="" prop="unavailableWeekdays">
                <div class="unavailable-dates-container">
                  <!-- 星期选择 -->
                  <div class="date-select-section">
                    <div class="section-title">星期</div>
                    <div class="button-group">
                      <el-button
                        v-for="weekday in weekdayList"
                        :key="weekday.oName"
                        :type="storeInfoModel.unavailableWeekdays?.includes(weekday.oName) ? 'primary' : ''"
                        class="date-select-btn"
                        @click="toggleWeekday(weekday.oName)"
                      >
                        {{ weekday.name }}
                      </el-button>
                    </div>
                  </div>
                </div>
              </el-form-item>
              <el-form-item label="" prop="unavailableHolidays">
                <div class="unavailable-dates-container">
                  <!-- 节日选择 -->
                  <div class="date-select-section">
                    <div class="section-title">节日</div>
                    <div class="button-group">
                      <el-button
                        v-for="holiday in holidayList"
                        :key="holiday.id"
                        :type="storeInfoModel.unavailableHolidays?.includes(String(holiday.id)) ? 'primary' : ''"
                        class="date-select-btn"
                        @click="toggleHoliday(holiday.id)"
                      >
                        {{ holiday.festivalName }}
                      </el-button>
                    </div>
                  </div>
                </div>
              </el-form-item>
            </template>
            <el-form-item label="" prop="customUnavailableDates" v-else-if="storeInfoModel.disableDateType == 2">
              <div class="date-picker-container">
                <el-button
                  :icon="Plus"
                  class="add-date-btn"
                  type="primary"
                  :disabled="storeInfoModel.disableDateList.length >= 10"
                  @click="addDate"
                >
                  添加日期
                </el-button>
                <div v-for="(item, index) in storeInfoModel.disableDateList" :key="index" class="date-item">
                  <el-date-picker
                    v-model="storeInfoModel.disableDateList[index]"
                    type="daterange"
                    value-format="YYYY-MM-DD"
                    range-separator="-"
                    start-placeholder="开始时间"
                    end-placeholder="结束时间"
                    class="date-picker"
                    :disabled-date="disabledCustomUnavailableDate"
                  />
                  <el-button
                    :icon="Delete"
                    type="danger"
                    circle
                    size="small"
                    class="delete-btn"
                    @click="removeDate(index)"
                    v-show="storeInfoModel.disableDateList.length > 1"
                  />
                </div>
              </div>
            </el-form-item>
            <!-- 预约规则  prop="reservationRules"-->
            <el-form-item label="预约规则">
              <el-input
                maxlength="300"
                v-model="storeInfoModel.reservationRules"
                :rows="4"
                type="textarea"
                placeholder="请输入预约规则"
                show-word-limit
              />
            </el-form-item>
            <!-- 使用规则  prop="useRules"-->
            <el-form-item label="使用规则">
              <el-input
                maxlength="300"
                v-model="storeInfoModel.useRules"
                :rows="4"
                type="textarea"
                placeholder="请输入使用规则"
                show-word-limit
              />
            </el-form-item>
            <!-- 适用人数 -->
            <el-form-item label="适用人数" prop="applicableNum">
              <el-input v-model="storeInfoModel.applicableNum" maxlength="15" placeholder="请填写适用人数" clearable />
            </el-form-item>
            <!-- 其他规则  prop="otherRules"-->
            <el-form-item label="其他规则">
              <el-input
                maxlength="300"
                v-model="storeInfoModel.otherRules"
                :rows="4"
                type="textarea"
                placeholder="请输入其他规则"
                show-word-limit
              />
            </el-form-item>
            <!-- 发票信息  prop="invoiceInformation"-->
            <el-form-item label="发票信息">
              <el-checkbox-group v-model="storeInfoModel.invoiceInformation">
                <el-checkbox v-for="bt in businessTypes" :key="bt.value" :value="bt.value" :label="bt.label">
                  {{ bt.label }}
                </el-checkbox>
              </el-checkbox-group>
            </el-form-item>
            <!-- 发票说明  prop="invoiceDescribe"-->
            <el-form-item label="发票说明">
              <el-input v-model="storeInfoModel.invoiceDescribe" maxlength="30" placeholder="请填写发票说明" clearable />
            </el-form-item>
          </div>
        </div>
      </div>
    </el-form>
    <!-- 底部按钮区域 -->
    <div class="button-container">
      <el-button @click="handleSubmit('cg')" :disabled="hasUnuploadedImages"> 存草稿 </el-button>
      <el-button type="primary" @click="handleSubmit()" :disabled="hasUnuploadedImages"> 确定 </el-button>
    </div>
    <!-- 图片预览 -->
    <el-image-viewer
      v-if="imageViewerVisible"
      :url-list="imageViewerUrlList"
      :initial-index="imageViewerInitialIndex"
      @close="imageViewerVisible = false"
    />
    <!-- 菜品选择对话框 -->
    <el-dialog v-model="dishDialogVisible" title="菜品" width="600px" :close-on-click-modal="false">
      <div class="dish-dialog-content">
        <el-input
          v-model="dishSearchKeyword"
          placeholder="请输入菜品名称"
          clearable
          class="dish-search-input"
          @input="filterDishList"
        />
        <el-scrollbar height="400px" class="dish-list-container">
          <template v-if="filteredDishList.length > 0">
            <div
              v-for="dish in filteredDishList"
              :key="dish.id"
              :class="['dish-item', { 'dish-item-selected': selectedDishId === dish.id }]"
              @click="selectDish(dish)"
            >
              <div class="dish-image">
                <el-image v-if="dish.imgUrl" :src="dish.imgUrl" fit="cover" class="dish-img" />
                <div v-else class="dish-image-placeholder">
                  <el-icon><Picture /></el-icon>
                </div>
              </div>
              <div class="dish-info">
                <div class="dish-name">
                  {{ dish.dishName }}
                </div>
                <div class="dish-price">¥{{ dish.dishPrice }}/{{ dish.dishesUnit }}</div>
              </div>
            </div>
          </template>
          <div v-else class="dish-empty-state">
            <div class="empty-text">暂无可选择菜品</div>
            <div class="empty-hint">请去全部-门店装修-菜品管理中添加</div>
          </div>
        </el-scrollbar>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="confirmDishSelection"> 确定 </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="tsx" name="newGroup">
/**
 * 团购包管理 - 新增/编辑页面
 * 功能：支持团购包的新增和编辑操作
 */
import { ref, reactive, onMounted, watch, nextTick, computed } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, Delete, ArrowDown, ArrowUp, Picture } from "@element-plus/icons-vue";
import { saveDraft, getHolidayList, getMenuByStoreId, getThaliById, saveThali } from "@/api/modules/groupPackageManagement";
import { useRouter, useRoute } from "vue-router";
import type { UploadProps, FormInstance, UploadInstance, UploadFile } from "element-plus";
import { localGet } from "@/utils";
import {
  validatePositiveInteger,
  validateDateRangeArray,
  validateConditionalRequired,
  validateDateListArray,
  validatePriceFormat
} from "@/utils/eleValidate";

// ==================== 响应式数据定义 ====================

// 图片预览相关
const imageViewerVisible = ref(false);
const imageViewerUrlList = ref<string[]>([]);
const imageViewerInitialIndex = ref(0);

// 路由相关
const router = useRouter();
const route = useRoute();

// 页面状态
const type = ref<string>(""); // 页面类型：add-新增, edit-编辑
const id = ref<string>(""); // 页面ID参数

// 文件上传地址
const uploadUrl = ref(`${import.meta.env.VITE_API_URL_STORE}/file/uploadImg`);

const imgType = ref(16);
const uploadMaxCount = 9;
const uploadRef = ref<UploadInstance>();
const uploading = ref(false);
const pendingUploadFiles = ref<UploadFile[]>([]);
const generateImgSort = (() => {
  let seed = Date.now();
  return () => {
    seed += 1;
    return seed;
  };
})();

// ==================== 验证辅助函数 ====================
// 验证函数已从 @/utils/eleValidate 导入

// ==================== 表单验证规则 ====================
const rules = reactive({
  imageValueStr: [{ required: true, message: "请上传图片" }],
  groupName: [{ required: true, message: "请填写团购名称" }],
  startTimeType: [{ required: true, message: "请选择开始售卖时间" }],
  startTimeValue: [
    { required: true, message: "请选择开始售卖时间" },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (storeInfoModel.value.startTimeType === 1) {
          if (!value) {
            callback(new Error("请选择开始售卖时间"));
            return;
          }
          const selectedDate = new Date(value);
          const today = new Date();
          today.setHours(0, 0, 0, 0);
          if (selectedDate < today) {
            callback(new Error("开始售卖时间不能早于当前时间"));
            return;
          }
          // 如果结束时间已设置，验证开始时间必须早于结束时间
          if (storeInfoModel.value.endTime) {
            const endDate = new Date(storeInfoModel.value.endTime);
            if (selectedDate >= endDate) {
              callback(new Error("开始售卖时间必须早于结束售卖时间"));
              return;
            }
          }
        }
        callback();
      },
      trigger: "change"
    }
  ],
  endTime: [
    { required: true, message: "请选择结束售卖时间" },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (!value) {
          callback(new Error("请选择结束售卖时间"));
          return;
        }
        const selectedDate = new Date(value);
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        if (selectedDate < today) {
          callback(new Error("结束售卖时间不能早于当前时间"));
          return;
        }
        // 如果开始时间已设置，验证结束时间必须晚于开始时间
        if (storeInfoModel.value.startTimeType === 1 && storeInfoModel.value.startTimeValue) {
          const startDate = new Date(storeInfoModel.value.startTimeValue);
          if (selectedDate <= startDate) {
            callback(new Error("结束售卖时间必须晚于开始售卖时间"));
            return;
          }
        }
        callback();
      },
      trigger: "change"
    }
  ],
  inventoryNum: [
    { required: true, message: "请填写库存数量" },
    {
      validator: (rule: any, value: any, callback: any) => {
        // 先验证是否为正整数
        validatePositiveInteger("库存数量必须为正整数", { required: false })(rule, value, (error: any) => {
          if (error) {
            callback(error);
            return;
          }
          // 验证最大值
          if (value) {
            const numValue = Number(value);
            if (!isNaN(numValue) && numValue > 99999) {
              callback(new Error("库存数量不得大于99999"));
              return;
            }
          }
          callback();
        });
      },
      trigger: "blur"
    }
  ],
  quotaType: [{ required: true, message: "请选择每人限购" }],
  quotaValue: [
    {
      required: true,
      validator: (rule: any, value: any, callback: any) => {
        if (storeInfoModel.value.quotaType === 1) {
          if (!value || value.toString().trim() === "") {
            callback(new Error("请输入自定义限购数量"));
            return;
          }
          validatePositiveInteger("自定义限购数量必须为正整数")(rule, value, callback);
        } else {
          callback();
        }
      },
      trigger: "blur"
    }
  ],
  lifeGroupBuyThalis: [
    {
      required: true,
      validator: (rule: any, value: any, callback: any) => {
        try {
          // 只检查是否有至少一个分组，详细验证由独立的套餐内容表单处理
          const thalis = lifeGroupBuyThalis.value;
          if (!thalis || thalis.length === 0) {
            callback(new Error("请至少添加一个套餐分组"));
            return;
          }
          callback();
        } catch (error) {
          // 如果验证过程中出错，直接通过验证，避免报错
          callback();
        }
      },
      trigger: "blur"
    }
  ],
  originalPrice: [
    {
      validator: (rule: any, value: any, callback: any) => {
        // 非必填，如果为空则直接通过
        if (!value || value.toString().trim() === "") {
          callback();
          return;
        }
        const num = Number(value);
        if (isNaN(num) || num <= 0) {
          callback(new Error("原价必须为正数"));
          return;
        }
        callback();
      },
      trigger: "blur"
    },
    {
      validator: validatePriceFormat("整数部分最多6位，小数部分最多2位"),
      trigger: "blur"
    }
  ],
  preferentialPrice: [
    { required: true, message: "请输入优惠价" },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (!value || value.toString().trim() === "") {
          callback();
          return;
        }
        const num = Number(value);
        if (isNaN(num) || num <= 0) {
          callback(new Error("优惠价必须为正数"));
          return;
        }
        callback();
      },
      trigger: "blur"
    },
    {
      validator: validatePriceFormat("整数部分最多6位，小数部分最多2位"),
      trigger: "blur"
    }
  ],
  effectiveDateType: [{ required: true, message: "请选择有效期" }],
  expirationDate: [
    {
      required: true,
      validator: (rule: any, value: any, callback: any) => {
        if (storeInfoModel.value.effectiveDateType === 0) {
          if (value === null || value === undefined || value === "") {
            callback(new Error("请输入用户购买天数"));
            return;
          }
          validatePositiveInteger("用户购买天数必须为正整数", { required: false, checkLeadingZero: false })(
            rule,
            value,
            callback
          );
        } else {
          callback();
        }
      },
      trigger: "blur"
    }
  ],
  expirationDateList: [
    {
      required: true,
      validator: (rule: any, value: any, callback: any) => {
        if (storeInfoModel.value.effectiveDateType === 1) {
          if (!value || value.length !== 2) {
            callback(new Error("请选择指定时间段"));
            return;
          }
          validateDateRangeArray("开始时间必须早于结束时间", true, "时间不能早于当前时间")(rule, value, callback);
        } else {
          callback();
        }
      },
      trigger: "change"
    }
  ],
  disableDateType: [{ required: true, message: "请选择不可用日期" }],
  unavailableWeekdays: [
    {
      required: true,
      validator: validateConditionalRequired(() => storeInfoModel.value.disableDateType === 1, "至少需要选择一个星期"),
      trigger: "change"
    }
  ],
  unavailableHolidays: [
    {
      required: true,
      validator: validateConditionalRequired(() => storeInfoModel.value.disableDateType === 1, "至少需要选择一个节日"),
      trigger: "change"
    }
  ],
  customUnavailableDates: [
    {
      required: true,
      validator: (rule: any, value: any, callback: any) => {
        if (storeInfoModel.value.disableDateType === 2) {
          if (!storeInfoModel.value.disableDateList || storeInfoModel.value.disableDateList.length === 0) {
            callback(new Error("至少需要添加一个自定义不可用日期"));
            return;
          }

          const dateList = storeInfoModel.value.disableDateList;
          const today = new Date();
          today.setHours(0, 0, 0, 0);

          // 用于存储所有日期范围，用于检查重复
          const dateRanges: Array<{ start: Date; end: Date; index: number }> = [];

          for (let i = 0; i < dateList.length; i++) {
            const dateItem = dateList[i];
            if (!dateItem || !Array.isArray(dateItem) || dateItem.length !== 2) {
              callback(new Error(`第${i + 1}个日期项未完整填写`));
              return;
            }

            const startDate = new Date(dateItem[0]);
            const endDate = new Date(dateItem[1]);
            startDate.setHours(0, 0, 0, 0);
            endDate.setHours(0, 0, 0, 0);

            // 验证不能早于今天
            if (startDate < today) {
              callback(new Error(`第${i + 1}个日期项的开始时间不能早于当前时间`));
              return;
            }
            if (endDate < today) {
              callback(new Error(`第${i + 1}个日期项的结束时间不能早于当前时间`));
              return;
            }

            // 验证开始时间不能晚于结束时间（允许相等，即可以选择单天）
            if (startDate > endDate) {
              callback(new Error(`第${i + 1}个日期项的开始时间不能晚于结束时间`));
              return;
            }

            // 存储日期范围用于重复检查
            dateRanges.push({ start: startDate, end: endDate, index: i });
          }

          // 检查日期范围是否重复
          for (let i = 0; i < dateRanges.length; i++) {
            for (let j = i + 1; j < dateRanges.length; j++) {
              const range1 = dateRanges[i];
              const range2 = dateRanges[j];

              // 检查两个日期范围是否有重叠
              // 重叠条件：range1的开始时间 <= range2的结束时间 && range1的结束时间 >= range2的开始时间
              if (range1.start.getTime() <= range2.end.getTime() && range1.end.getTime() >= range2.start.getTime()) {
                callback(new Error(`第${range1.index + 1}个日期项与第${range2.index + 1}个日期项存在重复，请重新选择`));
                return;
              }
            }
          }

          callback();
        } else {
          callback();
        }
      },
      trigger: "change"
    }
  ],
  reservationRules: [{ required: true, message: "请输入预约规则" }],
  useRules: [{ required: true, message: "请输入使用规则" }],
  applicableNum: [
    {
      validator: (rule: any, value: any, callback: any) => {
        // 非必填，如果为空则直接通过
        if (!value || value.toString().trim() === "") {
          callback();
          return;
        }
        // 先验证是否为正整数
        validatePositiveInteger("适用人数必须为正整数", { required: false })(rule, value, (error: any) => {
          if (error) {
            callback(error);
            return;
          }
          // 验证范围：1-99999
          const numValue = Number(value);
          if (!isNaN(numValue)) {
            if (numValue < 1) {
              callback(new Error("适用人数不能小于1"));
              return;
            }
            if (numValue > 99999) {
              callback(new Error("适用人数不能大于99999"));
              return;
            }
          }
          callback();
        });
      },
      trigger: "blur"
    }
  ],
  otherRules: [{ required: true, message: "请输入其他规则" }],
  invoiceInformation: [{ required: true, message: "请选择发票信息" }],
  invoiceDescribe: [{ required: true, message: "请输入发票说明" }]
});

// ==================== 团购包信息数据模型 ====================
const storeInfoModel = ref<any>({
  // 团购图片列表
  imageValueStr: [],
  imageId: [],
  // 团购名称
  groupName: "",
  // 开始售卖时间设置方式：0-审核通过后立即开始，1-设置售卖时间
  startTimeType: 0,
  // 开始售卖时间（当storeStatus为1时必填）
  startTimeValue: "",
  // 结束售卖时间
  endTime: "",
  // 库存数量
  inventoryNum: "",
  // 每人限购设置：0-不限量，1-自定义限购数量
  quotaType: 0,
  // 自定义限购数量（当quotaType为1时必填）
  quotaValue: 0,
  // 套餐内容（虚拟字段，用于表单验证，实际数据在 lifeGroupBuyThalis 变量中）
  lifeGroupBuyThalis: null,
  // 原价
  originalPrice: "",
  // 优惠价
  preferentialPrice: "",
  // 有效期设置：0-指定天数，1-指定时间段内可用
  effectiveDateType: 0,
  expirationDate: 0,
  expirationDateList: [],
  // 不可用日期设置：0-全部日期可用，1-限制日期，2-自定义不可用日期
  disableDateType: 0,
  // 限制日期 - 星期选择（数组，存储选中的星期值）
  unavailableWeekdays: [],
  // 限制日期 - 节日选择（数组，存储选中的节日值）
  unavailableHolidays: [],
  // 自定义不可用日期列表
  disableDateList: [],
  // 预约规则
  reservationRules: "",
  // 使用规则
  useRules: "",
  // 适用人数
  applicableNum: "",
  // 其他规则
  otherRules: "",
  // 发票信息（复选框，可多选）
  invoiceInformation: [],
  // 发票说明
  invoiceDescribe: ""
});

// ==================== 下拉选项数据 ====================

// 发票类型列表
const businessTypes = ref([
  { value: 0, label: "提供电子发票" },
  { value: 1, label: "提供纸质发票" }
]);

// 开始售卖时间设置方式列表
const storeStatusList = ref([
  { value: 0, label: "审核通过后立即开始" },
  { value: 1, label: "设置售卖时间" }
]);

// 每人限购设置
const perList = ref([
  { value: 0, label: "不限量" },
  { value: 1, label: "自定义限购数量" }
]);
// 有效期设置
const expirationDateStatusList = ref([
  { value: 0, label: "指定天数" },
  { value: 1, label: "指定时间段内可用" }
]);
// 有效期设置
const unavailableDatesList = ref([
  { value: 0, label: "全部日期可用" },
  { value: 1, label: "限制日期" },
  { value: 2, label: "自定义不可用日期" }
]);

// 星期选项列表
const weekdayList = ref([
  { name: "周一", id: "0", oName: "星期一" },
  { name: "周二", id: "1", oName: "星期二" },
  { name: "周三", id: "2", oName: "星期三" },
  { name: "周四", id: "3", oName: "星期四" },
  { name: "周五", id: "4", oName: "星期五" },
  { name: "周六", id: "5", oName: "星期六" },
  { name: "周日", id: "6", oName: "星期日" }
]);

// 节日选项列表
const holidayList: any = ref([]);

// 菜品选项列表
const dishOptions: any = ref([]);

// 套餐内容（数组，每个元素是一个分组）
const lifeGroupBuyThalis = ref([
  {
    groupName: "", // 类别
    dishes: [
      // 菜品列表
      {
        detailId: "", // 菜品ID
        dishName: "", // 菜品名称
        dishPrice: "", // 菜品价格
        qty: "", // 数量
        dishesUnit: ""
      }
    ]
  }
]);

// 菜品选择对话框相关
const dishDialogVisible = ref(false);
const dishSearchKeyword = ref("");
const filteredDishList: any = ref([]);
const selectedDishId = ref<number | string | null>(null);
const currentDishGroupIndex = ref<number>(-1);
const currentDishIndex = ref<number>(-1);

// 套餐内容整体展开收起状态
const allGroupsCollapsed = ref(false);
// 每个分组的收起状态（数组，索引对应分组索引）
const groupCollapsedStates = ref<boolean[]>([false]); // 默认第一个分组展开

// 计算属性：过滤要显示的分组（收起全部时只显示第一个分组），保留原始索引
const visibleGroups = computed(() => {
  if (allGroupsCollapsed.value) {
    return lifeGroupBuyThalis.value.map((group, index) => ({ group, originalIndex: index })).filter((_, index) => index === 0);
  }
  return lifeGroupBuyThalis.value.map((group, index) => ({ group, originalIndex: index }));
});

// 计算属性：获取已成功上传的图片数量
const uploadedImageCount = computed(() => {
  return storeInfoModel.value.imageValueStr.filter((file: any) => file.status === "success" && file.imageId).length;
});

// 计算属性：检查是否有未上传完成的图片
const hasUnuploadedImages = computed(() => {
  // 检查是否有正在上传的文件
  if (uploading.value || pendingUploadFiles.value.length > 0) {
    return true;
  }
  // 检查文件列表中是否有状态为 "ready"（待上传）或 "uploading"（上传中）的图片
  if (storeInfoModel.value.imageValueStr && storeInfoModel.value.imageValueStr.length > 0) {
    return storeInfoModel.value.imageValueStr.some((file: any) => {
      return file.status === "ready" || file.status === "uploading";
    });
  }
  return false;
});

// ==================== 监听器 ====================

/**
 * 监听不可用日期选项变化
 * 当切换到自定义不可用日期时，确保至少有一个日期项
 */
watch(
  () => storeInfoModel.value.disableDateType,
  newVal => {
    if (newVal === 2) {
      // 切换到自定义不可用日期时，如果disableDateList为空，则添加一个默认项
      if (!storeInfoModel.value.disableDateList || storeInfoModel.value.disableDateList.length === 0) {
        storeInfoModel.value.disableDateList = [null];
      }
    }
  },
  { immediate: true }
);

/**
 * 监听开始售卖时间变化
 * 当开始时间改变时，重新验证结束时间
 */
watch(
  () => storeInfoModel.value.startTimeValue,
  () => {
    if (storeInfoModel.value.endTime) {
      nextTick(() => {
        ruleFormRef.value?.validateField("endTime");
      });
    }
  }
);

/**
 * 监听结束售卖时间变化
 * 当结束时间改变时，重新验证开始时间
 */
watch(
  () => storeInfoModel.value.endTime,
  () => {
    if (storeInfoModel.value.startTimeType === 1 && storeInfoModel.value.startTimeValue) {
      nextTick(() => {
        ruleFormRef.value?.validateField("startTimeValue");
      });
    }
  }
);

/**
 * 监听所有分组的类别值变化
 * 当任何一个分组的类别值改变时，重新验证所有分组的类别字段，确保重复性校验实时生效
 */
watch(
  () => lifeGroupBuyThalis.value.map(group => group.groupName),
  () => {
    // 当类别值改变时，重新验证所有分组的类别字段
    nextTick(() => {
      if (packageFormRef.value) {
        lifeGroupBuyThalis.value.forEach((_, groupIndex) => {
          const prop = `groups.${groupIndex}.groupName`;
          packageFormRef.value?.validateField(prop, () => {});
        });
      }
    });
  },
  { deep: true }
);

// ==================== 生命周期钩子 ====================

/**
 * 组件挂载时初始化
 * 从路由参数中获取页面类型和ID
 */
onMounted(async () => {
  id.value = (route.query.id as string) || "";
  type.value = (route.query.type as string) || "";
  let params = {
    year: new Date().getFullYear(),
    page: 1,
    size: 500,
    openFlag: 1,
    holidayName: ""
  };
  let res: any = await getHolidayList(params);
  if (res && res.code == 200) {
    holidayList.value = res.data.records;
  }
  if (type.value != "add") {
    const params = {
      id: id.value,
      userId: localGet("userId")
    };
    let res: any = await getThaliById(params);
    storeInfoModel.value = { ...storeInfoModel.value, ...res.data.lifeGroupBuyMain };
    storeInfoModel.value.imageId = storeInfoModel.value.imageId ? storeInfoModel.value.imageId.split(",") : [];
    let imageValueStr: any[] = [];
    handleImageParam(storeInfoModel.value.imageValueStr || [], imageValueStr);
    // 将 imageId 关联到对应的文件对象中
    if (imageValueStr.length > 0 && storeInfoModel.value.imageId.length > 0) {
      imageValueStr.forEach((file, index) => {
        if (storeInfoModel.value.imageId[index]) {
          file.imageId = storeInfoModel.value.imageId[index];
        }
      });
    }
    storeInfoModel.value.imageValueStr = imageValueStr;
    storeInfoModel.value.invoiceInformation = storeInfoModel.value.invoiceType ? storeInfoModel.value.invoiceType.split(";") : [];
    // 确保星期和节日字段存在
    if (storeInfoModel.value.disableDateType == 1) {
      const listVal = storeInfoModel.value.disableDateValue ? storeInfoModel.value.disableDateValue.split(";") : [];
      storeInfoModel.value.unavailableWeekdays = listVal[0] ? listVal[0].split(",").filter((item: string) => item) : [];
      storeInfoModel.value.unavailableHolidays = listVal[1] ? listVal[1].split(",").filter((item: string) => item) : [];
    }
    if (res.data.lifeGroupBuyThalis && res.data.lifeGroupBuyThalis.length > 0) {
      lifeGroupBuyThalis.value = res.data.lifeGroupBuyThalis;
      // 确保每个分组都有必要的字段
      lifeGroupBuyThalis.value.forEach((group: any) => {
        if (!group.dishes || group.dishes.length === 0) {
          group.dishes = [
            {
              detailId: "",
              qty: ""
            }
          ];
        }
      });
      // 初始化所有分组的收起状态为展开
      groupCollapsedStates.value = new Array(lifeGroupBuyThalis.value.length).fill(false);
    } else {
      // 如果没有数据，使用默认值
      lifeGroupBuyThalis.value = [
        {
          groupName: "",
          dishes: [
            {
              detailId: "",
              dishName: "",
              dishPrice: "",
              qty: "",
              dishesUnit: ""
            }
          ]
        }
      ];
      // 初始化默认分组的收起状态为展开
      groupCollapsedStates.value = [false];
    }
    // 确保自定义不可用日期字段存在
    if (storeInfoModel.value.disableDateType === 2) {
      // 后端直接返回 disableDateList 字段，如果为空则初始化为默认值
      if (!storeInfoModel.value.disableDateList || storeInfoModel.value.disableDateList.length === 0) {
        storeInfoModel.value.disableDateList = [null];
      }
    }
  }
});
// ==================== 事件处理函数 ====================
/**
 * 返回上一页
 */
const goBack = () => {
  router.go(-1);
};

const beforeAvatarUpload = (file: any) => {
  console.log(file);
  return false;
};
/**
 * 检查文件是否在排队中（未上传）
 * @param file 文件对象
 * @returns 是否在排队中
 */
const isFilePending = (file: any): boolean => {
  // 只检查 ready 状态（排队中），不包括 uploading（正在上传）
  if (file.status === "ready") {
    return true;
  }
  // 检查是否在待上传队列中
  if (pendingUploadFiles.value.some(item => item.uid === file.uid)) {
    return true;
  }
  return false;
};

/**
 * 图片上传 - 删除前确认
 * @param uploadFile 要删除的文件对象
 * @param uploadFiles 当前文件列表
 * @returns Promise<boolean>，true 允许删除，false 阻止删除
 */
const handleBeforeRemove = async (uploadFile: any, uploadFiles: any[]): Promise<boolean> => {
  // 如果文件在排队中（未上传），禁止删除
  if (isFilePending(uploadFile)) {
    ElMessage.warning("图片尚未上传，请等待上传完成后再删除");
    return false;
  }
  try {
    await ElMessageBox.confirm("确定要删除这张图片吗？", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    });
    // 用户确认删除，返回 true 允许删除
    return true;
  } catch {
    // 用户取消删除，返回 false 阻止删除
    return false;
  }
};

/**
 * 图片上传 - 移除图片回调（删除成功后调用）
 * @param uploadFile 已删除的文件对象
 * @param uploadFiles 删除后的文件列表
 */
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  // 从被删除的文件对象中获取 imageId
  const file = uploadFile as any;
  const imageId = file.imageId;
  if (imageId) {
    // 从 imageId 数组中删除对应的 imageId
    const index = storeInfoModel.value.imageId.indexOf(imageId);
    if (index > -1) {
      storeInfoModel.value.imageId.splice(index, 1);
    }
  }
  if (file.url && file.url.startsWith("blob:")) {
    URL.revokeObjectURL(file.url);
  }
  // 同步文件列表
  storeInfoModel.value.imageValueStr = [...uploadFiles];
  // 删除成功后提示
  ElMessage.success("图片已删除");
};

/**
 * 上传文件超出限制提示
 */
const handleUploadExceed: UploadProps["onExceed"] = () => {
  ElMessage.warning(`最多只能上传${uploadMaxCount}张图片`);
};

/**
 * el-upload 文件变更（选中或移除）
 */
const handleUploadChange: UploadProps["onChange"] = async (uploadFile, uploadFiles) => {
  // 检查文件类型，只允许 jpg 和 png
  if (uploadFile.raw) {
    const fileType = uploadFile.raw.type.toLowerCase();
    const fileName = uploadFile.name.toLowerCase();
    const validTypes = ["image/jpeg", "image/jpg", "image/png"];
    const validExtensions = [".jpg", ".jpeg", ".png"];

    // 检查 MIME 类型或文件扩展名
    const isValidType = validTypes.includes(fileType) || validExtensions.some(ext => fileName.endsWith(ext));

    if (!isValidType) {
      // 从文件列表中移除不符合类型的文件
      const index = storeInfoModel.value.imageValueStr.findIndex((f: any) => f.uid === uploadFile.uid);
      if (index > -1) {
        storeInfoModel.value.imageValueStr.splice(index, 1);
      }
      // 从 uploadFiles 中移除
      const uploadIndex = uploadFiles.findIndex((f: any) => f.uid === uploadFile.uid);
      if (uploadIndex > -1) {
        uploadFiles.splice(uploadIndex, 1);
      }
      // 如果文件有 blob URL，释放它
      if (uploadFile.url && uploadFile.url.startsWith("blob:")) {
        URL.revokeObjectURL(uploadFile.url);
      }
      ElMessage.warning("只支持上传 JPG 和 PNG 格式的图片");
      return;
    }
  }

  // 同步文件列表到表单数据（只添加通过验证的文件）
  const existingIndex = storeInfoModel.value.imageValueStr.findIndex((f: any) => f.uid === uploadFile.uid);
  if (existingIndex === -1) {
    storeInfoModel.value.imageValueStr.push(uploadFile);
  }

  const readyFiles = storeInfoModel.value.imageValueStr.filter(file => file.status === "ready");
  if (readyFiles.length) {
    readyFiles.forEach(file => {
      if (!pendingUploadFiles.value.some(item => item.uid === file.uid)) {
        pendingUploadFiles.value.push(file);
      }
    });
  }
  processUploadQueue();
};

/**
 * 处理上传队列 - 逐个上传文件
 */
const processUploadQueue = async () => {
  if (uploading.value || pendingUploadFiles.value.length === 0) {
    return;
  }
  // 每次只取一个文件进行上传
  const file = pendingUploadFiles.value.shift();
  if (file) {
    await uploadSingleFile(file);
    // 继续处理队列中的下一个文件
    processUploadQueue();
  }
};

/**
 * 单文件上传图片
 * @param file 待上传的文件
 */
const uploadSingleFile = async (file: UploadFile) => {
  if (!file.raw) {
    return;
  }

  const formData = new FormData();
  const storeId = Number(localGet("createdId"));
  const rawFile = file.raw as File;
  const sortValue = generateImgSort();

  formData.append("file", rawFile);
  formData.append(
    "list",
    JSON.stringify([
      {
        storeId,
        imgType: imgType.value,
        imgSort: sortValue
      }
    ])
  );

  file.status = "uploading";
  file.percentage = 0;
  uploading.value = true;

  try {
    const response = await fetch(uploadUrl.value, {
      method: "POST",
      body: formData,
      credentials: "include"
    });
    if (!response.ok) {
      throw new Error("上传失败");
    }
    const result = await response.json();

    if (result?.code === 200 && result.data) {
      // 处理单个文件的上传结果
      const imageId = String(Array.isArray(result.data) ? result.data[0] : result.data);
      file.status = "success";
      file.percentage = 100;
      (file as any).imageId = imageId;
      file.response = { data: imageId };

      if (!Array.isArray(storeInfoModel.value.imageId)) {
        storeInfoModel.value.imageId = [];
      }
      if (!storeInfoModel.value.imageId.includes(imageId)) {
        storeInfoModel.value.imageId.push(imageId);
      }
    } else {
      throw new Error(result?.msg || "图片上传失败");
    }
  } catch (error: any) {
    file.status = "fail";
    if (file.url && file.url.startsWith("blob:")) {
      URL.revokeObjectURL(file.url);
    }
    // 从文件列表中移除失败的文件
    const index = storeInfoModel.value.imageValueStr.findIndex((f: any) => f.uid === file.uid);
    if (index > -1) {
      storeInfoModel.value.imageValueStr.splice(index, 1);
    }
    ElMessage.error(error?.message || "图片上传失败");
  } finally {
    uploading.value = false;
    // 触发视图更新
    storeInfoModel.value.imageValueStr = [...storeInfoModel.value.imageValueStr];
  }
};

/**
 * 图片预览 - 使用 el-image 预览功能
 * @param file 上传文件对象
 */
const handlePictureCardPreview = (file: any) => {
  // 如果文件在排队中（未上传），禁止预览
  if (isFilePending(file)) {
    ElMessage.warning("图片尚未上传，请等待上传完成后再预览");
    return;
  }
  // 如果文件正在上传中，允许预览（使用本地预览）
  if (file.status === "uploading" && file.url) {
    imageViewerUrlList.value = [file.url];
    imageViewerInitialIndex.value = 0;
    imageViewerVisible.value = true;
    return;
  }
  // 获取所有图片的 URL 列表（只包含已上传成功的图片）
  const urlList = storeInfoModel.value.imageValueStr
    .filter((item: any) => item.status === "success" && (item.url || item.response?.data))
    .map((item: any) => item.url || item.response?.data);
  // 找到当前点击的图片索引
  const currentIndex = urlList.findIndex((url: string) => url === (file.url || file.response?.data));
  if (currentIndex < 0) {
    ElMessage.warning("图片尚未上传完成，无法预览");
    return;
  }
  imageViewerUrlList.value = urlList;
  imageViewerInitialIndex.value = currentIndex;
  imageViewerVisible.value = true;
};

/**
 * 添加自定义不可用日期
 */
const addDate = () => {
  // 检查最大数量限制
  if (storeInfoModel.value.disableDateList.length >= 10) {
    ElMessage.warning("最多只能添加10个自定义不可用日期");
    return;
  }
  storeInfoModel.value.disableDateList.push(null);
};

/**
 * 删除自定义不可用日期
 * @param index 要删除的日期索引
 */
const removeDate = (index: number) => {
  if (storeInfoModel.value.disableDateList.length <= 1) {
    ElMessage.warning("至少需要保留一个日期项");
    return;
  }
  storeInfoModel.value.disableDateList.splice(index, 1);
  // 删除日期项后，重新验证表单以清除旧的验证错误
  nextTick(() => {
    ruleFormRef.value?.validateField("customUnavailableDates");
  });
};

/**
 * 切换星期选择
 * @param value 星期值
 */
const toggleWeekday = value => {
  if (!storeInfoModel.value.unavailableWeekdays) {
    storeInfoModel.value.unavailableWeekdays = [];
  }
  const index = storeInfoModel.value.unavailableWeekdays.indexOf(value);
  if (index > -1) {
    storeInfoModel.value.unavailableWeekdays.splice(index, 1);
  } else {
    storeInfoModel.value.unavailableWeekdays.push(value);
  }
  console.log(storeInfoModel.value.unavailableWeekdays);
  // 触发表单验证
  nextTick(() => {
    ruleFormRef.value?.validateField("unavailableWeekdays");
  });
};

/**
 * 切换节日选择
 * @param value 节日值
 */
const toggleHoliday = value => {
  if (!storeInfoModel.value.unavailableHolidays) {
    storeInfoModel.value.unavailableHolidays = [];
  }
  // 统一转换为字符串进行比较
  const valueStr = String(value);
  const index = storeInfoModel.value.unavailableHolidays.findIndex((item: any) => String(item) === valueStr);
  if (index > -1) {
    storeInfoModel.value.unavailableHolidays.splice(index, 1);
  } else {
    storeInfoModel.value.unavailableHolidays.push(valueStr);
  }
  // 触发表单验证
  nextTick(() => {
    ruleFormRef.value?.validateField("unavailableHolidays");
  });
};

/**
 * 添加套餐分组
 */
const addGroup = () => {
  if (!lifeGroupBuyThalis.value) {
    lifeGroupBuyThalis.value = [];
  }

  // 检查分组数量限制（最多20个）
  if (lifeGroupBuyThalis.value.length >= 20) {
    ElMessage.warning("最多只能添加20个分组");
    return;
  }

  // 使用表单验证来验证所有现有分组
  if (packageFormRef.value) {
    packageFormRef.value.validate((valid: boolean) => {
      if (!valid) {
        ElMessage.warning("请先完成现有分组的填写");
        return;
      }

      // 验证通过，添加新分组
      lifeGroupBuyThalis.value.push({
        groupName: "",
        dishes: [
          {
            detailId: "",
            dishName: "",
            dishPrice: "",
            qty: "",
            dishesUnit: ""
          }
        ]
      });

      // 初始化新分组的收起状态为展开
      groupCollapsedStates.value.push(false);

      // 清除表单验证状态，避免新分组显示验证错误
      // 使用延迟清除，确保在验证规则更新和 DOM 渲染完成后再清除
      nextTick(() => {
        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);
              });
            }
          }, 50);
        });
      });
    });
  } else {
    // 如果表单引用不存在，直接添加（兜底逻辑）
    lifeGroupBuyThalis.value.push({
      groupName: "",
      dishes: [
        {
          detailId: "",
          dishName: "",
          dishPrice: "",
          qty: "",
          dishesUnit: ""
        }
      ]
    });
    groupCollapsedStates.value.push(false);
  }
};

/**
 * 删除套餐分组
 * @param groupIndex 分组索引
 */
const removeGroup = (groupIndex: number) => {
  if (lifeGroupBuyThalis.value.length <= 1) {
    ElMessage.warning("至少需要保留一个分组");
    return;
  }
  ElMessageBox.confirm("确定要删除这个分组吗？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning"
  })
    .then(() => {
      lifeGroupBuyThalis.value.splice(groupIndex, 1);
      // 同步删除收起状态数组中的对应项
      if (groupCollapsedStates.value.length > groupIndex) {
        groupCollapsedStates.value.splice(groupIndex, 1);
      }
      ElMessage.success("删除成功");
    })
    .catch(() => {});
};

/**
 * 判断分组是否收起
 * @param groupIndex 分组索引
 * @returns 是否收起（收起时只显示类别和第一行菜品，隐藏其他菜品行）
 */
const isGroupCollapsed = (groupIndex: number): boolean => {
  // 如果"收起全部"状态为true，第一个分组应该展开（显示所有菜品），其他分组收起
  if (allGroupsCollapsed.value) {
    return groupIndex !== 0;
  }
  // 否则根据分组的收起状态判断
  return groupCollapsedStates.value[groupIndex] === true;
};

/**
 * 切换单个分组的收起/展开状态
 * @param groupIndex 分组索引
 */
const toggleGroupCollapse = (groupIndex: number) => {
  // 如果当前是"收起全部"状态，先取消该状态
  if (allGroupsCollapsed.value) {
    allGroupsCollapsed.value = false;
    // 设置所有分组状态：第一个分组当前是展开的，其他分组当前是收起的
    // 所以第一个分组应该设置为收起，其他分组应该设置为展开
    groupCollapsedStates.value = new Array(lifeGroupBuyThalis.value.length).fill(true);
    groupCollapsedStates.value[0] = false; // 第一个分组原本是展开的
    // 然后切换当前分组的状态
    groupCollapsedStates.value[groupIndex] = !groupCollapsedStates.value[groupIndex];
  } else {
    // 确保数组长度足够
    while (groupCollapsedStates.value.length <= groupIndex) {
      groupCollapsedStates.value.push(false);
    }
    groupCollapsedStates.value[groupIndex] = !groupCollapsedStates.value[groupIndex];
  }
};

/**
 * 切换所有分组的收起/展开状态
 * 收起全部时保留第一个分组展开
 */
const toggleAllGroupsCollapse = () => {
  if (allGroupsCollapsed.value) {
    // 展开全部：将所有分组设置为展开状态
    allGroupsCollapsed.value = false;
    groupCollapsedStates.value = groupCollapsedStates.value.map(() => false);
  } else {
    // 收起全部：收起除第一个分组外的所有分组
    allGroupsCollapsed.value = true;
    groupCollapsedStates.value = groupCollapsedStates.value.map((_, index) => index !== 0);
    // 确保数组长度足够
    while (groupCollapsedStates.value.length < lifeGroupBuyThalis.value.length) {
      groupCollapsedStates.value.push(true);
    }
  }
};

/**
 * 添加菜品
 * @param groupIndex 分组索引
 */
const addDish = (groupIndex: number) => {
  const group = lifeGroupBuyThalis.value[groupIndex];

  // 检查菜品数量限制（每个分组最多20个菜品）
  if (group.dishes && group.dishes.length >= 20) {
    ElMessage.warning("每个分组最多只能添加20个菜品");
    return;
  }

  // 使用表单验证来验证当前分组的所有字段
  if (packageFormRef.value) {
    // 收集当前分组的所有字段路径
    const fieldsToValidate: string[] = [];

    // 添加类别字段
    fieldsToValidate.push(`groups.${groupIndex}.groupName`);

    // 添加当前分组所有菜品的字段
    if (group.dishes && group.dishes.length > 0) {
      group.dishes.forEach((_, dishIndex) => {
        fieldsToValidate.push(`groups.${groupIndex}.dishes.${dishIndex}.detailId`);
        fieldsToValidate.push(`groups.${groupIndex}.dishes.${dishIndex}.qty`);
      });
    }

    if (fieldsToValidate.length === 0) {
      // 如果没有字段需要验证，直接添加
      if (!group.dishes) {
        group.dishes = [];
      }
      group.dishes.push({
        detailId: "",
        dishName: "",
        dishPrice: "",
        qty: "",
        dishesUnit: ""
      });
      return;
    }

    // 使用 Promise 等待所有字段验证完成
    const validatePromises = fieldsToValidate.map(field => {
      return new Promise<boolean>(resolve => {
        packageFormRef.value?.validateField(field, (isValid: boolean) => {
          resolve(isValid);
        });
      });
    });

    Promise.all(validatePromises).then(results => {
      const allValid = results.every(result => result === true);

      if (!allValid) {
        ElMessage.warning("请先完成现有菜品的填写");
        return;
      }

      // 验证通过，添加新菜品
      if (!group.dishes) {
        group.dishes = [];
      }
      group.dishes.push({
        detailId: "",
        dishName: "",
        dishPrice: "",
        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);
              });
            }
          }, 50);
        });
      });
    });
  } else {
    // 如果表单引用不存在，直接添加（兜底逻辑）
    if (!group.dishes) {
      group.dishes = [];
    }
    group.dishes.push({
      detailId: "",
      dishName: "",
      dishPrice: "",
      qty: "",
      dishesUnit: ""
    });
  }
};

/**
 * 删除菜品
 * @param groupIndex 分组索引
 * @param dishIndex 菜品索引
 */
const removeDish = (groupIndex: number, dishIndex: number) => {
  const dishes = lifeGroupBuyThalis.value[groupIndex].dishes;
  if (dishes.length <= 1) {
    ElMessage.warning("至少需要保留一个菜品");
    return;
  }
  dishes.splice(dishIndex, 1);
};

/**
 * 打开菜品选择对话框
 * @param groupIndex 分组索引
 * @param dishIndex 菜品索引
 */
const openDishDialog = async (groupIndex: number, dishIndex: number) => {
  currentDishGroupIndex.value = groupIndex;
  currentDishIndex.value = dishIndex;
  dishSearchKeyword.value = "";
  const params = {
    storeId: localGet("createdId"),
    phoneId: 18641153170,
    dishType: 0
  };
  const res = await getMenuByStoreId(params);
  if (res && res.code == 200) {
    dishOptions.value = res.data;
  }
  // 如果已有选中的菜品，设置选中状态
  const currentDish = lifeGroupBuyThalis.value[groupIndex].dishes[dishIndex];
  selectedDishId.value = currentDish?.detailId || null;
  filterDishList();
  dishDialogVisible.value = true;
};

/**
 * 选择菜品
 * @param dish 菜品对象
 */
const selectDish = (dish: any) => {
  selectedDishId.value = dish.id;
};

/**
 * 确认菜品选择
 */
const confirmDishSelection = () => {
  if (selectedDishId.value === null) {
    ElMessage.warning("请选择一个菜品");
    return;
  }
  const selectedDish: any = dishOptions.value.find(dish => dish.id === selectedDishId.value);
  if (selectedDish && currentDishGroupIndex.value >= 0 && currentDishIndex.value >= 0) {
    const dish = lifeGroupBuyThalis.value[currentDishGroupIndex.value].dishes[currentDishIndex.value];
    dish.detailId = selectedDish.id;
    dish.dishName = selectedDish.dishName;
    dish.dishPrice = selectedDish.dishPrice;
    dish.dishesUnit = selectedDish.dishesUnit;
    dishDialogVisible.value = false;
    // 重新验证对应的字段，如果验证通过，错误提示会消失
    nextTick(() => {
      if (packageFormRef.value) {
        const prop = `groups.${currentDishGroupIndex.value}.dishes.${currentDishIndex.value}.detailId`;
        packageFormRef.value.validateField(prop, () => {});
      }
    });
  }
};

/**
 * 过滤菜品列表
 * 排除已经在其他分组中被选择的菜品（当前正在编辑的菜品除外）
 */
const filterDishList = () => {
  // 获取当前正在编辑的菜品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();
    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);
  });
};

// ==================== 表单引用 ====================
const ruleFormRef = ref<FormInstance>(); // 表单引用
const packageFormRef = ref<FormInstance>(); // 套餐内容表单引用

// 套餐内容表单模型（用于验证）
const packageFormModel = computed(() => {
  return {
    groups: lifeGroupBuyThalis.value
  };
});

// 套餐内容验证规则
const packageFormRules = computed(() => {
  const rules: any = {};
  lifeGroupBuyThalis.value.forEach((group, groupIndex) => {
    // 类别验证规则 - 使用与 prop 相同的路径格式
    rules[`groups.${groupIndex}.groupName`] = [
      {
        required: true,
        message: `第${groupIndex + 1}个分组的类别不能为空`,
        trigger: "blur"
      },
      {
        validator: (rule: any, value: any, callback: any) => {
          // 如果值为空，由 required 规则处理，这里直接通过
          if (!value || value.toString().trim() === "") {
            callback();
            return;
          }
          const trimmedValue = value.toString().trim();
          // 检查长度（不得大于10字）
          if (trimmedValue.length > 10) {
            callback(new Error("类别不得大于10字"));
            return;
          }
          // 检查是否与其他分组的类别重复
          for (let i = 0; i < lifeGroupBuyThalis.value.length; i++) {
            // 跳过当前分组
            if (i === groupIndex) {
              continue;
            }
            const otherGroupName = lifeGroupBuyThalis.value[i].groupName;
            // 如果其他分组的类别值与当前值相同（忽略前后空格），则重复
            if (otherGroupName && otherGroupName.toString().trim() === trimmedValue) {
              callback(new Error(`第${groupIndex + 1}个分组的类别与第${i + 1}个分组的类别重复`));
              return;
            }
          }
          callback();
        },
        trigger: "blur"
      }
    ];

    // 每个菜品的验证规则
    if (group.dishes) {
      group.dishes.forEach((dish, dishIndex) => {
        // 菜品选择验证
        rules[`groups.${groupIndex}.dishes.${dishIndex}.detailId`] = [
          {
            required: true,
            message: `第${groupIndex + 1}个分组的第${dishIndex + 1}个菜品未选择`,
            trigger: "change"
          }
        ];

        // 菜品数量验证
        rules[`groups.${groupIndex}.dishes.${dishIndex}.qty`] = [
          {
            required: true,
            message: `第${groupIndex + 1}个分组的第${dishIndex + 1}个菜品数量不能为空`,
            trigger: "blur"
          },
          {
            validator: (rule: any, value: any, callback: any) => {
              // 先验证是否为正整数
              validatePositiveInteger(`第${groupIndex + 1}个分组的第${dishIndex + 1}个菜品数量必须为正整数`, {
                required: false
              })(rule, value, (error: any) => {
                if (error) {
                  callback(error);
                  return;
                }
                // 验证最大值
                if (value) {
                  const numValue = Number(value);
                  if (!isNaN(numValue) && numValue > 99999) {
                    callback(new Error("数量不得大于99999"));
                    return;
                  }
                }
                callback();
              });
            },
            trigger: "blur"
          }
        ];
      });
    }
  });
  return rules;
});

/**
 * 提交数据（新增/编辑）
 * 验证表单，通过后调用相应的API接口
 */
const handleSubmit = async (type?) => {
  // 检查是否有未上传完成的图片
  if (hasUnuploadedImages.value) {
    ElMessage.warning("请等待图片上传完成后再提交");
    return;
  }
  let params: any = { ...storeInfoModel.value };
  // 确保 imageId 是数组，然后转换为逗号分隔的字符串
  if (Array.isArray(params.imageId)) {
    params.imageId = params.imageId.join(",");
  } else {
    params.imageId = "";
  }
  if (params.disableDateType == 1) {
    params.disableDateValue = params.unavailableWeekdays.join(",") + ";" + params.unavailableHolidays.join(",");
  }
  params.invoiceType = params.invoiceInformation.join(",");
  delete params.unavailableWeekdays;
  delete params.unavailableHolidays;
  const paramsObj: any = {
    lifeGroupBuyMain: params,
    lifeGroupBuyThalis: lifeGroupBuyThalis.value
  };
  paramsObj.lifeGroupBuyMain.status = type ? "0" : "1";
  paramsObj.lifeGroupBuyMain.groupType = localGet("businessSection");
  paramsObj.lifeGroupBuyMain.storeId = localGet("createdId");
  if (id.value) {
    paramsObj.lifeGroupBuyMain.id = id.value;
  }
  console.log(paramsObj);
  if (type) {
    if (!storeInfoModel.value.groupName) {
      ElMessage.warning("请填写团购名称");
      return;
    }
    let res: any = await saveDraft(paramsObj);
    if (res && res.code == 200) {
      ElMessage.success("保存成功");
      goBack();
    }
  } else {
    await ruleFormRef.value!.validate(async valid => {
      if (!valid) {
        ElMessage.warning("请完善表单内容信息");
        return;
      }
      // 验证套餐内容表单
      if (packageFormRef.value) {
        let packageValid = false;
        await new Promise<void>(resolve => {
          packageFormRef.value!.validate(valid => {
            packageValid = valid;
            if (!valid) {
              ElMessage.warning("请完善套餐内容信息");
            }
            resolve();
          });
        });
        if (!packageValid) {
          return;
        }
      }
      // 组装提交参数
      let res: any = await saveThali(paramsObj);
      if (res && res.code == 200) {
        ElMessage.success("保存成功");
        goBack();
      }
    });
  }
};

// ==================== 工具函数 ====================

/**
 * 禁用开始售卖时间的日期
 * 不能选择早于当前时间的日期
 * @param time 日期对象
 * @returns 是否禁用该日期
 */
const disabledStartDate = (time: Date) => {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return time.getTime() < today.getTime();
};

/**
 * 禁用结束售卖时间的日期
 * 不能选择早于当前时间的日期，也不能选择早于或等于开始售卖时间的日期
 * @param time 日期对象
 * @returns 是否禁用该日期
 */
const disabledEndDate = (time: Date) => {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  // 不能早于当前时间
  if (time.getTime() < today.getTime()) {
    return true;
  }
  // 如果开始售卖时间已设置，不能早于或等于开始时间
  if (storeInfoModel.value.startTimeType === 1 && storeInfoModel.value.startTimeValue) {
    const startDate = new Date(storeInfoModel.value.startTimeValue);
    startDate.setHours(0, 0, 0, 0);
    return time.getTime() <= startDate.getTime();
  }
  return false;
};

/**
 * 禁用指定时间段内可用的日期
 * 不能选择早于当前时间的日期
 * @param time 日期对象
 * @returns 是否禁用该日期
 */
const disabledEffectiveDate = (time: Date) => {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return time.getTime() < today.getTime();
};

/**
 * 禁用自定义不可用日期的日期
 * 不能选择早于当前时间的日期
 * @param time 日期对象
 * @returns 是否禁用该日期
 */
const disabledCustomUnavailableDate = (time: Date) => {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return time.getTime() < today.getTime();
};

/**
 * 处理图片结果
 * 将上传组件的文件对象或URL字符串转换为URL数组
 * @param list 图片列表（可能是文件对象或URL字符串）
 * @returns URL字符串数组
 */
const handleImageResult = (list: any[]): string[] => {
  let result: string[] = [];
  (list || []).forEach((item: any) => {
    if (item.uid) {
      // 如果是上传组件的文件对象，取url属性
      result.push(item.url);
    } else {
      // 如果是URL字符串，直接添加
      result.push(item);
    }
  });
  return result;
};

//图片list 转换为upload 组件的参数
const handleImageParam = (list: any[], result: any[]) => {
  (list || []).forEach((item: any) => {
    // 使用split方法以'/'为分隔符将URL拆分成数组
    const parts = item.split("/");
    // 取数组的最后一项，即图片名称
    const imageName = parts[parts.length - 1];
    result.push({
      name: imageName,
      percentage: 100,
      url: item
    });
  });
};
</script>

<style scoped lang="scss">
/* 页面容器 */
.table-box {
  display: flex;
  flex-direction: column;
  height: auto !important;
  min-height: 100%;
}

/* 头部区域 */
.header {
  display: flex;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #e4e7ed;
}
.title {
  flex: 1;
  margin: 0;
  font-size: 18px;
  font-weight: bold;
  text-align: center;
}

/* 内容区域布局 */
.content {
  display: flex;
  flex: 1;
  column-gap: 20px;
  width: 98%;
  margin: 20px auto;

  /* 左侧内容区域 */
  .contentLeft {
    width: 50%;
  }

  /* 右侧内容区域 */
  .contentRight {
    width: 50%;
  }
}

/* 模块容器 */
.model {
  margin-bottom: 50px;
}

/* el-upload 图片预览铺满容器 */
:deep(.el-upload-list--picture-card) {
  .el-upload-list__item {
    overflow: hidden;
    .el-upload-list__item-thumbnail {
      width: 100%;
      height: 100%;
      object-fit: fill;
    }
  }

  /* 排队中（未上传）的图片禁用样式 */
  .el-upload-list__item[data-status="ready"],
  .el-upload-list__item.is-ready {
    position: relative;
    pointer-events: none;
    cursor: not-allowed;
    opacity: 0.6;
    &::after {
      position: absolute;
      inset: 0;
      z-index: 1;
      content: "";
      background-color: rgb(0 0 0 / 30%);
    }
    .el-upload-list__item-actions {
      pointer-events: none;
      opacity: 0.5;
    }
  }

  /* 上传项悬停和聚焦时显示状态标签 */
  .el-upload-list__item:hover .el-upload-list__item-status-label {
    display: inline-flex !important;
    opacity: 1 !important;
  }
  .el-upload-list__item.is-success:focus .el-upload-list__item-status-label {
    display: inline-flex !important;
    opacity: 1 !important;
  }

  /* 隐藏关闭提示图标 */
  .el-icon--close-tip {
    display: none !important;
  }
}
.upload-trigger-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: 28px;
  color: #8c939d;
  .upload-tip {
    margin-top: 8px;
    font-size: 14px;
    color: #8c939d;
  }
}

/* 上传区域样式 */
.upload-area {
  min-height: 300px;
  padding: 20px;
  :deep(.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label) {
    display: inline-flex !important;
    opacity: 1 !important;
  }
  :deep(.el-upload-list__item.is-success:focus .el-upload-list__item-status-label) {
    display: inline-flex !important;
    opacity: 1 !important;
  }
  :deep(.el-upload-list--picture-card .el-icon--close-tip) {
    display: none !important;
  }
  &.upload-full {
    :deep(.el-upload--picture-card) {
      display: none !important;
    }
  }
}

/* 上传滚动条样式 */
.upload-scrollbar {
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden;
  }
}

/* 表单容器 */
.formBox {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 100%;
}

/* 底部按钮容器 - 居中显示 */
.button-container {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: center;
  padding: 20px 0;
  margin-top: 20px;
}

/* 日期选择器容器 */
.date-picker-container {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}

/* 添加日期按钮 */
.add-date-btn {
  width: fit-content;
  margin-bottom: 8px;
}

/* 日期项容器 */
.date-item {
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 8px;

  // background-color: #f5f7fa;
  border-radius: 4px;
  transition: background-color 0.1s;
  &:hover {
    background-color: #ecf5ff;
  }
}

/* 日期选择器 */
.date-item .date-picker {
  flex: 1;
  max-width: 500px;
}

/* 删除按钮 */
.date-item .delete-btn {
  flex-shrink: 0;
}

/* 有效期天数容器 */
.expiration-date-container {
  display: flex;
  gap: 12px;
  align-items: center;
  width: fit-content;
  padding: 8px 12px;

  // background-color: #f5f7fa;
  border-radius: 4px;
}

/* 有效期标签文字 */
.expiration-label {
  font-size: 14px;
  color: #606266;
  white-space: nowrap;
}

/* 有效期输入框 */
.expiration-input {
  width: 150px;
}

/* 不可用日期容器 */
.unavailable-dates-container {
  display: flex;
  flex-direction: column;
  gap: 20px;
  width: 100%;
}

/* 日期选择区块 */
.date-select-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* 区块标题 */
.section-title {
  font-size: 14px;
  font-weight: 500;
  color: #606266;
}

/* 按钮组 */
.button-group {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* 日期选择按钮 */
.date-select-btn {
  min-width: 80px;
  height: 36px;
  padding: 8px 16px;
  margin: 0;
  font-size: 14px;
  border-radius: 4px;
  transition: all 0.1s;
}

/* 套餐内容相关样式 */
.package-content-item {
  width: 100%;
}
.package-content-form {
  width: 100%;
}

/* 表单项基础样式 */
.package-content-form :deep(.el-form-item) {
  margin-bottom: 0;
}
.package-content-form :deep(.el-form-item__label) {
  display: none;
}

/* 类别表单项样式 */
.category-form-item {
  width: 100%;
  margin-bottom: 16px;
}
.category-form-item :deep(.el-form-item__content) {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  width: 100%;
}
.category-form-item :deep(.el-form-item__error) {
  position: static;
  width: 100%;
  padding-top: 4px;
  padding-left: 62px;
  margin-top: 0;
  font-size: 12px;
  line-height: 1.5;
  color: #f56c6c;
}
.category-row .el-input {
  flex: 1;
  max-width: 400px;
}

/* 菜品表单项样式 */
.dish-form-item {
  position: relative;
  flex: 1;
  margin-bottom: 0;
}
.dish-form-item :deep(.el-form-item__content) {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}
.dish-form-item :deep(.el-form-item__error) {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1;
  padding-top: 4px;
  padding-right: 4px;
  font-size: 12px;
  line-height: 1.5;
  color: #f56c6c;
  white-space: nowrap;
  background-color: #ffffff;
}
.package-content-wrapper {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
}
.package-content-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}
.add-group-btn {
  width: fit-content;
}
.package-content-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
}
.package-group {
  overflow: hidden;
  background-color: white;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
}
.package-group-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 50px;
  padding: 12px 16px;
  background-color: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
}
.group-index {
  flex: 1;
  overflow: hidden;
  font-size: 14px;
  font-weight: 500;
  color: #303133;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.header-right {
  display: flex;
  flex-shrink: 0;
  gap: 12px;
  align-items: center;
}
.package-group-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 60px;
  padding: 16px;
}
.extra-dishes-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 0;
}
.extra-dishes-container .dish-row {
  margin-bottom: 4px;
}
.extra-dishes-container .dish-row:last-child {
  margin-bottom: 0;
}
.package-group-collapsed {
  padding: 16px;
  background-color: #fafafa;
  border-top: 1px solid #e4e7ed;
}
.collapsed-dish-row {
  display: flex;
  gap: 12px;
  align-items: center;
}
.dish-info-text {
  font-size: 14px;
  color: #606266;
  white-space: nowrap;
}
.dish-info-text.empty-text {
  color: #c0c4cc;
}
.category-row {
  display: flex;
  gap: 12px;
  align-items: center;
  width: 100%;
}
.dish-row {
  position: relative;
  display: flex;
  gap: 12px;
  align-items: flex-start;
  width: 100%;
  margin-bottom: 4px;
}
.dish-row:last-child {
  padding-bottom: 0;
  margin-bottom: 0;
}

/* 当表单项有错误时，增加底部间距 */
.dish-row .dish-form-item.is-error {
  margin-bottom: 0;
}
.label {
  min-width: 50px;
  font-size: 14px;
  color: #606266;
  white-space: nowrap;
}
.dish-select-block {
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
  max-width: 300px;
  min-height: 32px;
  padding: 0 11px;
  cursor: pointer;
  background-color: #ffffff;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
}
.dish-select-block:hover {
  border-color: #c0c4cc;
}
.dish-select-block:focus-within {
  border-color: #409eff;
}

/* 当菜品选择有验证错误时，显示错误边框 */
.dish-form-item.is-error .dish-select-block {
  border-color: #f56c6c;
}
.dish-form-item.is-error .dish-select-block:hover {
  border-color: #f56c6c;
}
.dish-form-item.is-error .dish-select-block:focus-within {
  border-color: #f56c6c;
}

/* 优化表单项的错误状态 */
.package-content-form :deep(.el-form-item.is-error .el-input__wrapper) {
  box-shadow: 0 0 0 1px #f56c6c inset;
}
.package-content-form :deep(.el-form-item.is-error .el-input__wrapper:hover) {
  box-shadow: 0 0 0 1px #f56c6c inset;
}
.package-content-form :deep(.el-form-item.is-error .el-input__wrapper.is-focus) {
  box-shadow: 0 0 0 1px #f56c6c inset;
}
.dish-selected-name {
  font-size: 14px;
  color: #606266;
}
.dish-placeholder {
  font-size: 14px;
  color: #c0c4cc;
}
.quantity-input {
  flex-shrink: 0;
  width: 150px;
}
.delete-dish-btn {
  flex-shrink: 0;
  margin-left: 8px;
}
.add-dish-btn {
  width: fit-content;
  margin-top: 8px;
}

/* 优化菜品行的布局，确保在有验证错误时也能正确显示 */
.dish-row .dish-form-item {
  min-width: 0;
}
.dish-row .dish-form-item:first-child {
  flex: 1;
  min-width: 200px;
  max-width: 350px;
}
.dish-row .dish-form-item:last-child {
  display: flex;
  flex: 0 0 auto;
  gap: 8px;
  align-items: center;
}

/* 确保数量输入框和删除按钮在同一行 */
.dish-form-item:last-child :deep(.el-form-item__content) {
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
  align-items: center;
}

/* 响应式布局优化 */
@media (width <= 768px) {
  .dish-row {
    flex-direction: column;
    align-items: stretch;
  }
  .dish-row .dish-form-item {
    width: 100%;
    max-width: 100%;
  }
  .dish-row .dish-form-item:first-child {
    max-width: 100%;
  }
  .category-row {
    flex-direction: column;
    align-items: stretch;
  }
  .category-row .el-input {
    max-width: 100%;
  }
}

/* 菜品选择对话框样式 */
.dish-dialog-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.dish-search-input {
  width: 100%;
}
.dish-list-container {
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden;
  }
  :deep(.el-scrollbar__view) {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
}
.dish-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  text-align: center;
}
.empty-text {
  margin-bottom: 8px;
  font-size: 16px;
  color: #909399;
}
.empty-hint {
  font-size: 14px;
  color: #c0c4cc;
}
.dish-item {
  position: relative;
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 12px;
  cursor: pointer;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  transition: all 0.1s;
}
.dish-item:hover {
  background-color: #f5f7fa;
  border-color: #409eff;
}
.dish-item-selected {
  background-color: #ecf5ff;
  border-color: #409eff;
  border-width: 1px;
}
.dish-item-selected:hover {
  background-color: #d9ecff;
}
.dish-image {
  flex-shrink: 0;
  width: 60px;
  height: 60px;
  overflow: hidden;
  background-color: #f5f7fa;
  border-radius: 4px;
}
.dish-img {
  width: 100%;
  height: 100%;
}
.dish-image-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: 24px;
  color: #c0c4cc;
}
.dish-info {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 4px;
}
.dish-name {
  font-size: 14px;
  font-weight: 500;
  color: #606266;
}
.dish-price {
  font-size: 14px;
  color: #909399;
}
.dish-selected-icon {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  font-size: 16px;
  color: #ffffff;
  background-color: #409eff;
  border-radius: 50%;
}
.dialog-footer {
  display: flex;
  justify-content: center;
}

/* 展开收起动画 - 高度过渡 */
.slide-fade-enter-active {
  overflow: hidden;
  transition:
    max-height 0.1s ease-out,
    opacity 0.1s ease-out;
}
.slide-fade-leave-active {
  overflow: hidden;
  transition:
    max-height 0.1s ease-in,
    opacity 0.1s ease-in;
}
.slide-fade-enter-from {
  max-height: 0;
  opacity: 0;
}
.slide-fade-leave-to {
  max-height: 0;
  opacity: 0;
}
.slide-fade-enter-to,
.slide-fade-leave-from {
  max-height: 2000px;
  opacity: 1;
}

/* 分组收起全部动画 */
.group-fade-enter-active {
  transition: all 0.1s ease-out;
}
.group-fade-leave-active {
  transition: all 0.1s ease-in;
}
.group-fade-enter-from {
  opacity: 0;
  transform: translateY(-10px);
}
.group-fade-leave-to {
  opacity: 0;
  transform: translateY(-10px);
}
.group-fade-move {
  transition: transform 0.1s linear;
}
</style>
