<template>
  <div class="exam-app-container" style="width: 100%; max-width: 1200px;">
    <!-- ====== 顶部卡片：申请单列表 ====== -->
    <div class="top-section">
      <div class="section-header">
        <span class="section-title">检查项目 ({{ filteredApplicationList.length }})</span>
        <div class="header-actions">
          <el-button type="primary" @click="handleAdd" icon="Plus">新增</el-button>
          <el-button type="success" @click="handleSave" icon="Finished">保存</el-button>
        </div>
      </div>

      <!-- Bug #499: 查询过滤工具栏 -->
      <div class="search-toolbar">
        <el-form :inline="true" size="small">
          <el-form-item label="日期范围">
            <el-date-picker
              v-model="searchForm.dateRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              value-format="YYYY-MM-DD"
              style="width: 240px"
            />
          </el-form-item>
          <el-form-item label="状态">
            <el-select v-model="searchForm.applyStatus" placeholder="全部" clearable style="width: 140px">
              <el-option
                v-for="opt in statusOptions"
                :key="opt.value"
                :label="opt.label"
                :value="opt.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="关键字">
            <el-input
              v-model="searchForm.keyword"
              placeholder="申请单号 / 检查项目"
              clearable
              style="width: 200px"
              @keyup.enter="handleSearch"
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch" icon="Search">搜索</el-button>
            <el-button @click="handleResetSearch" icon="Refresh">重置</el-button>
          </el-form-item>
        </el-form>
      </div>

      <el-table
        v-loading="loading"
        :data="filteredApplicationList"
        :max-height="200"
        highlight-current-row
        @row-click="handleRowClick"
        border
        size="small"
        :header-cell-style="{ background: '#f5f5f5', color: '#303133', fontWeight: '600' }"
      >
        <el-table-column type="selection" width="40" align="center" />
        <el-table-column label="申请ID" prop="id" width="80" align="center" />
        <el-table-column label="申请单号" prop="applyNo" min-width="140" align="center" />
        <el-table-column label="申检部位" prop="inspectionArea" min-width="100" align="center" />
        <el-table-column label="申请医生" prop="applyDocCode" min-width="90" align="center" />
        <el-table-column label="急" prop="isUrgent" width="50" align="center">
          <template #default="{ row }">
            <el-checkbox v-model="row.isUrgent" :true-label="1" :false-label="0" disabled />
          </template>
        </el-table-column>
        <el-table-column label="收费" prop="isCharged" width="50" align="center">
          <template #default="{ row }">
            <el-checkbox v-model="row.isCharged" :true-label="1" :false-label="0" disabled />
          </template>
        </el-table-column>
        <el-table-column label="退费" prop="isRefunded" width="50" align="center">
          <template #default="{ row }">
            <el-checkbox v-model="row.isRefunded" :true-label="1" :false-label="0" disabled />
          </template>
        </el-table-column>
        <el-table-column label="执行" prop="isExecuted" width="50" align="center">
          <template #default="{ row }">
            <el-checkbox v-model="row.isExecuted" :true-label="1" :false-label="0" disabled />
          </template>
        </el-table-column>
        <el-table-column label="金额" prop="totalAmount" width="90" align="right">
          <template #default="{ row }">
            {{ (row.totalAmount || 0).toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="80" align="center" fixed="right">
          <template #default="{ row }">
            <el-button link @click.stop="handlePrint(row)" title="打印">
              <el-icon><Printer /></el-icon>
            </el-button>
            <el-button link type="danger" @click.stop="handleDelete(row)" title="删除">
              <el-icon><Delete /></el-icon>
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <!-- ====== 底部主区：左表单 + 右分类 ====== -->
    <div class="bottom-section">
      <!-- 左：表单区 -->
      <div class="form-panel">
        <el-tabs v-model="activeDetailTab" class="form-tabs">
          <!-- TAB1：检查申请单 -->
          <el-tab-pane label="检查申请单" name="applyForm">
            <el-form ref="formRef" :model="form" :rules="rules" size="small" class="apply-form">
              <el-row :gutter="12">
                <el-col :span="8">
                  <el-form-item label="申请单号" prop="applyNo">
                    <el-input v-model="form.applyNo" readonly placeholder="自动生成" />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="姓名" prop="patientName">
                    <el-input v-model="form.patientName" readonly />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="就诊卡号" prop="medicalrecordNumber">
                    <el-input v-model="form.medicalrecordNumber" readonly />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="8">
                  <el-form-item label="费用性质" prop="natureofCost">
                    <el-select v-model="form.natureofCost" style="width:100%">
                      <el-option label="自费医疗" value="自费医疗" />
                      <el-option label="医保报销" value="医保报销" />
                    </el-select>
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="申请日期" prop="applyTime">
                    <el-date-picker v-model="form.applyTime" type="date" style="width:100%"
                      format="YYYY-MM-DD" value-format="YYYY-MM-DD HH:mm:ss" />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="申请科室" prop="applyDeptCode">
                    <el-input v-model="form.applyDeptCode" disabled />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="8">
                  <el-form-item label="申请医生" prop="applyDocCode">
                    <el-input v-model="form.applyDocCode" disabled />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="执行科室" prop="performDeptCode">
                    <el-select
                      v-model="form.performDeptCode"
                      style="width: 100%"
                      filterable
                      remote
                      reserve-keyword
                      clearable
                      placeholder="请选择执行科室（支持模糊查询）"
                      :remote-method="handleOrgRemoteSearch"
                      :loading="orgLoading"
                    >
                      <el-option
                        v-for="opt in orgFilteredOptions"
                        :key="opt.value"
                        :label="opt.label"
                        :value="opt.value"
                      />
                      <template #empty>
                        <div style="padding: 10px 0; color: #909399; text-align: center;">
                          {{ orgLoading ? '加载中...' : '暂无匹配科室' }}
                        </div>
                      </template>
                    </el-select>
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="24">
                  <el-form-item label="诊断描述" prop="clinicDesc">
                    <el-input v-model="form.clinicDesc" />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="8">
                  <el-form-item label="禁忌症" prop="contraindication">
                    <el-input v-model="form.contraindication" />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="临床诊断" prop="clinicalDiag">
                    <el-input v-model="form.clinicalDiag" />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="病史摘要" prop="medicalHistorySummary">
                    <el-input v-model="form.medicalHistorySummary" />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="24">
                  <el-form-item label="检查目的" prop="purposeDesc">
                    <el-input v-model="form.purposeDesc" />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="8">
                  <el-form-item label="体格检查">
                    <el-input v-model="form.purposeofInspection" placeholder="T(摄氏度) P次/分 R次/分 BF" />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="申检部位">
                    <el-input v-model="form.inspectionArea" readonly />
                  </el-form-item>
                </el-col>
                <!-- Bug #384修复: 添加检查方法只读输入框，联动显示选中的检查方法 -->
                <el-col :span="8">
                  <el-form-item label="检查方法">
                    <el-input v-model="form.selectedMethodDisplay" readonly placeholder="请在右侧选择" />
                  </el-form-item>
                </el-col>
              </el-row>
              <el-row :gutter="12">
                <el-col :span="8">
                  <el-form-item label="备注" prop="applyRemark">
                    <el-input v-model="form.applyRemark" />
                  </el-form-item>
                </el-col>
                <el-col :span="16">
                  <el-form-item label="状态">
                    <el-checkbox v-model="form.isUrgent" :true-label="1" :false-label="0">急</el-checkbox>
                    <el-checkbox v-model="form.isCharged" :true-label="1" :false-label="0" disabled>收费</el-checkbox>
                    <el-checkbox v-model="form.isRefunded" :true-label="1" :false-label="0" disabled>退费</el-checkbox>
                    <el-checkbox v-model="form.isExecuted" :true-label="1" :false-label="0" disabled>执行</el-checkbox>
                  </el-form-item>
                </el-col>
              </el-row>
            </el-form>
          </el-tab-pane>

          <!-- TAB2：检查明细 -->
          <el-tab-pane label="检查明细" name="applyDetail">
            <!-- 🔧 BugFix#426: 支持树形展开显示套餐明细 -->
            <el-table
              ref="detailTableRef"
              :data="selectedItems"
              row-key="id"
              border
              size="small"
              style="width:100%"
              :max-height="350"
              :header-cell-style="{ background: '#f5f5f5', color: '#303133' }"
              :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
              :load="loadPackageDetails"
              lazy
            >
              <el-table-column label="行" type="index" width="45" align="center" />
              <el-table-column label="检查项目" prop="name" min-width="120">
                <template #default="scope">
                  <el-tag v-if="scope.row.isPackage" size="small" type="warning" style="margin-right: 4px">套餐</el-tag>
                  <span>{{ scope.row.name }}</span>
                </template>
              </el-table-column>
              <el-table-column label="部位" prop="applyPart" min-width="90">
                <template #default="scope">
                  <el-input v-model="scope.row.applyPart" size="small" />
                </template>
              </el-table-column>
              <el-table-column label="检查方法" min-width="160">
                <template #default="scope">
                  <el-select
                    v-if="scope.row.methods && scope.row.methods.length > 1"
                    :model-value="scope.row.selectedMethod"
                    value-key="id"
                    size="small"
                    style="width: 100%"
                    placeholder="选择方法"
                    @update:model-value="(val) => onDetailMethodChange(scope.row, val)"
                  >
                    <el-option
                      v-for="meth in scope.row.methods"
                      :key="meth.id"
                      :label="`${meth.name}${meth.packagePrice != null ? ' ¥' + formatDetailAmount(meth.packagePrice) : ''}`"
                      :value="meth"
                    />
                  </el-select>
                  <template v-else>
                    <span v-if="scope.row.selectedMethod">
                      {{ scope.row.selectedMethod.name }}
                    </span>
                    <span v-else-if="scope.row.methods && scope.row.methods.length > 0" style="color: #909399;">
                      未选择
                    </span>
                    <span v-else style="color: #c0c4cc;">-</span>
                  </template>
                </template>
              </el-table-column>
              <el-table-column label="单位" prop="unit" width="55" align="center" />
              <el-table-column label="总量" prop="quantity" width="70" align="center">
                <template #default="scope">
                  <el-input-number v-model="scope.row.quantity" :min="1" size="small" :controls="false" style="width:100%" />
                </template>
              </el-table-column>
              <!-- Bug #384修复: 单价显示套餐价格（如果选中）或部位价格 -->
              <el-table-column label="单价" width="75" align="right">
                <template #default="scope">
                  {{ formatDetailAmount(getSelectedItemAmount(scope.row)) }}
                </template>
              </el-table-column>
              <!-- Bug #384修复: 金额使用有效价格计算 -->
              <el-table-column label="金额" width="80" align="right">
                <template #default="scope">
                  {{ formatDetailAmount(getSelectedItemAmount(scope.row) * (scope.row.quantity || 1)) }}
                </template>
              </el-table-column>
              <el-table-column label="类型" prop="checkType" width="70" align="center" />
              <el-table-column label="国码" prop="nationalCode" width="70" align="center" />
              <el-table-column label="自费" width="50" align="center">
                <template #default>
                  <el-checkbox disabled />
                </template>
              </el-table-column>
            </el-table>
            <div class="total-row">
              合计：<span class="total-amount">{{ totalAmountCalc }}</span>
            </div>
          </el-tab-pane>
        </el-tabs>
      </div>

      <!-- 右：检查项目分类面板 -->
      <div class="category-panel">
        <div class="panel-top">
          <!-- 左侧：分类搜索 + 折叠树 -->
          <div class="category-left">
            <div class="panel-label">检查项目分类</div>
            <el-input
              v-model="dictSearchKey"
              placeholder="搜索检查项目（支持拼音首字母）"
              prefix-icon="Search"
              clearable
              size="small"
              class="search-input"
            />
            <!-- 分类折叠列表 -->
            <div class="collapse-scroll" v-loading="dictLoading">
              <div v-if="filteredCategoryList.length === 0" class="empty-hint">
                {{ dictLoading ? '' : '暂无检查项目，请在"检查项目设置"中配置' }}
              </div>
              <el-collapse
                v-else
                v-model="activeNames"
                accordion
                @change="handleCollapseChange"
              >
                <el-collapse-item
                  v-for="cat in filteredCategoryList"
                  :key="cat.typeId"
                  :name="cat.typeId"
                >
                  <template #title>
                    <span class="cat-title">{{ cat.categoryName }}</span>
                    <span v-if="categoryLoadingSet.has(cat.typeId)" class="loading-dot"></span>
                  </template>
                  <!-- 检查项目（部位/项目列表） -->
                  <div
                    v-for="item in cat.items"
                    :key="item.id"
                    class="item-row"
                  >
                    <el-checkbox
                      v-model="item.checked"
                      @change="(val) => handleItemSelect(val, item, cat)"
                      class="item-checkbox"
                    >
                      {{ item.name }}
                    </el-checkbox>
                    <span class="item-price">¥{{ item.price }}/{{ item.unit || "次" }}</span>
                  </div>
                  <div v-if="categoryLoadingSet.has(cat.typeId)" class="category-loading-hint">
                    加载中...
                  </div>
                </el-collapse-item>
              </el-collapse>
            </div>
          </div>

          <!-- 右侧：已选择（检查项目、检查方法为两类独立选择结果） -->
          <div class="selected-panel">
            <div class="panel-label">已选择:</div>
            <div class="selected-tags">
              <template v-if="selectedItems.length === 0 && selectedMethods.length === 0 && methodsForActiveCategory.length === 0">
                <div class="empty-selected">–</div>
              </template>
              <template v-else>
              <div
                v-for="(item, idx) in selectedItems"
                :key="'project-' + item.id"
                class="selected-item-card"
                :class="{ 'is-expanded': item.projectFoldExpanded }"
              >
                <div
                  class="fold-strip fold-strip-project"
                  :class="{ 'is-open': item.projectFoldExpanded }"
                >
                  <div class="fold-strip-header" @click="toggleProjectFold(item)">
                    <el-icon :class="['fold-chevron', { open: item.projectFoldExpanded }]">
                      <ArrowDown />
                    </el-icon>
                    <div class="fold-header-main">
                      <span class="fold-kicker">检查项目</span>
                      <el-tooltip :content="getDisplayItemName(item)" placement="top" :show-after="400">
                        <span class="fold-title line-clamp-2">{{ getDisplayItemName(item) }}</span>
                      </el-tooltip>
                    </div>
                    <span class="fold-price-strong">¥{{ formatDetailAmount(item.price || 0) }}</span>
                    <el-button link type="danger" size="small" @click.stop="handleRemoveItem(idx, item)">
                      <el-icon><Close /></el-icon>
                    </el-button>
                  </div>
                  <div v-show="item.projectFoldExpanded" class="fold-strip-body">
                    <div v-if="shouldShowItemPackageBody(item)" class="fold-package-wrap">
                      <div v-if="item.packageDetailsLoading" class="package-details-loading">加载中...</div>
                      <template v-else>
                        <div v-if="getPackageDetailsList(item).length === 0" class="package-details-empty">
                          暂无套餐明细
                        </div>
                        <div v-else class="package-details-list">
                          <div
                            v-for="(detail, dIdx) in getPackageDetailsList(item)"
                            :key="detail.id ?? detail.itemCode ?? `d-${dIdx}`"
                            class="detail-row"
                          >
                            <el-tooltip :content="detail.name" placement="top" :show-after="500">
                              <span class="detail-name">{{ detail.name }}</span>
                            </el-tooltip>
                            <div class="detail-meta">
                              <span class="detail-qty">×{{ detail.quantity || 1 }}</span>
                              <span class="detail-price">¥{{ formatDetailAmount(detail.price) }}</span>
                            </div>
                          </div>
                        </div>
                      </template>
                    </div>
                    <div v-else class="fold-strip-muted">暂无项目套餐明细</div>
                  </div>
                </div>
              </div>

              <div
                v-for="(method, idx) in selectedMethods"
                :key="'method-' + method.id"
                class="selected-item-card"
                :class="{ 'is-expanded': method.expanded }"
              >
                <div
                  class="fold-strip fold-strip-method"
                  :class="{ 'is-open': method.expanded }"
                >
                  <div class="fold-strip-header" @click="toggleSelectedMethodFold(method)">
                    <el-icon :class="['fold-chevron', { open: method.expanded }]">
                      <ArrowDown />
                    </el-icon>
                    <div class="fold-header-main">
                      <span class="fold-kicker">检查方法</span>
                      <span
                        class="fold-title fold-title-plain line-clamp-2"
                        :title="getDisplayMethodName(method)"
                      >
                        {{ getDisplayMethodName(method) }}
                      </span>
                    </div>
                    <span
                      v-if="hasStandaloneMethodPackage(method)"
                      class="fold-price-strong warn"
                    >
                      ¥{{ formatDetailAmount(method.packagePrice || method.price || 0) }}
                    </span>
                    <el-button link type="danger" size="small" @click.stop="handleRemoveMethod(idx)">
                      <el-icon><Close /></el-icon>
                    </el-button>
                  </div>
                  <div v-show="method.expanded" class="fold-strip-body">
                    <template v-if="hasStandaloneMethodPackage(method)">
                      <div class="fold-package-wrap fold-method-package-wrap">
                        <div v-if="method.packageLoading" class="package-details-loading">加载中...</div>
                        <template v-else>
                          <div v-if="getStandaloneMethodPackageDetailsList(method).length === 0" class="package-details-empty">
                            暂无检查方法套餐明细
                          </div>
                          <div v-else class="package-details-list method-package-list">
                            <div
                              v-for="(detail, dIdx) in getStandaloneMethodPackageDetailsList(method)"
                              :key="detail.id ?? detail.itemCode ?? `md-${dIdx}`"
                              class="detail-row"
                            >
                              <el-tooltip :content="detail.name" placement="top" :show-after="500">
                                <span class="detail-name">{{ detail.name }}</span>
                              </el-tooltip>
                              <div class="detail-meta">
                                <span class="detail-qty">×{{ detail.quantity || 1 }}</span>
                                <span class="detail-price">¥{{ formatDetailAmount(detail.price) }}</span>
                              </div>
                            </div>
                          </div>
                        </template>
                      </div>
                    </template>
                    <template v-else>
                      <div class="fold-strip-muted">无单独的检查方法套餐明细。</div>
                    </template>
                  </div>
                </div>
              </div>

              <!-- 底部：独立勾选检查方法，样式与左侧项目选择一致 -->
              <div
                v-if="methodsForActiveCategory.length > 0"
                class="selected-global-method-picker"
                @click.stop
              >
                <div class="method-picker-collapse-title" @click="methodPickerExpanded = !methodPickerExpanded">
                  <span class="method-picker-title-main">检查方法</span>
                  <span v-if="activeCategoryName" class="global-method-picker-scope">{{ activeCategoryName }}</span>
                  <el-icon :class="['method-picker-arrow', { expanded: methodPickerExpanded }]">
                    <ArrowDown />
                  </el-icon>
                </div>
                <div v-show="methodPickerExpanded" class="global-method-picker-list">
                  <div
                    v-for="method in methodsForActiveCategory"
                    :key="'g-m-' + method.id"
                    class="item-row method-picker-row"
                  >
                    <el-checkbox
                      :model-value="isStandaloneMethodSelected(method)"
                      @change="(val) => onStandaloneMethodChange(!!val, method)"
                      class="item-checkbox"
                    >
                      <span class="method-label-inner">{{ formatExamMethodCaption(method.name) }}</span>
                    </el-checkbox>
                    <span class="item-price">¥{{ formatDetailAmount(method.packagePrice || method.price || 0) }}</span>
                  </div>
                </div>
              </div>
              </template>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, onMounted, nextTick } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Printer, Delete, ArrowDown, Close } from '@element-plus/icons-vue';
import useUserStore from '@/store/modules/user';
import request from '@/utils/request';
import { listCheckMethod, searchCheckMethod, listCheckPackage } from '@/api/system/checkType';
import { getEncounterDiagnosis } from '../api.js';

const props = defineProps({
  patientInfo: { type: Object, default: () => ({}) },
  activeTab: { type: String, default: '' }
});

// 保存成功后通知父组件刷新医嘱列表
const emit = defineEmits(['saved']);

const userStore = useUserStore();
const loading = ref(false);
const dictLoading = ref(false);
const activeDetailTab = ref('applyForm');
const applicationList = ref([]);
const selectedItems = ref([]);
const selectedMethods = ref([]);
const methodPickerExpanded = ref(true);

// Bug #499: 查询过滤状态
const searchForm = reactive({
  dateRange: [],
  applyStatus: '',
  keyword: ''
});

// 申请单状态选项
const statusOptions = [
  { label: '已开单', value: 0 },
  { label: '已收费', value: 1 },
  { label: '已预约', value: 2 },
  { label: '已签到', value: 3 },
  { label: '部分报告', value: 4 },
  { label: '已完告', value: 5 },
  { label: '已作废', value: 6 }
];

// Bug #499: 过滤后的申请单列表
const filteredApplicationList = computed(() => {
  let result = applicationList.value;

  // 日期范围过滤
  if (searchForm.dateRange && searchForm.dateRange.length === 2) {
    const start = searchForm.dateRange[0];
    const end = searchForm.dateRange[1];
    result = result.filter(item => {
      const d = item.applyTime;
      if (!d) return false;
      const dateStr = d.length > 10 ? d.substring(0, 10) : d;
      return dateStr >= start && dateStr <= end;
    });
  }

  // 状态过滤
  if (searchForm.applyStatus !== '' && searchForm.applyStatus !== null && searchForm.applyStatus !== undefined) {
    result = result.filter(item => item.applyStatus === searchForm.applyStatus);
  }

  // 关键字过滤（申请单号、申检部位、检查项目名）
  if (searchForm.keyword) {
    const kw = searchForm.keyword.toLowerCase();
    result = result.filter(item => {
      return (item.applyNo || '').toLowerCase().includes(kw)
        || (item.inspectionArea || '').toLowerCase().includes(kw);
    });
  }

  return result;
});

// Bug #499: 搜索与重置
function handleSearch() {
  // 过滤逻辑由 computed 自动处理
}

function handleResetSearch() {
  const now = new Date();
  const end = now.toISOString().substring(0, 10);
  const start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString().substring(0, 10);
  searchForm.dateRange = [start, end];
  searchForm.applyStatus = '';
  searchForm.keyword = '';
}

// 初始化默认日期范围为近一周
handleResetSearch();

// 🔧 BugFix#426/#430: 懒加载套餐明细（支持 packageName 解析）
async function loadPackageDetails(row, treeNode, resolve) {
  let packageId = row.packageId;
  if (!packageId && row.packageName) {
    try {
      const pkgRes = await listCheckPackage({ packageName: row.packageName });
      let packages = pkgRes?.data || [];
      if (!Array.isArray(packages)) {
        packages = packages.records || packages.data || [];
      }
      if (packages.length > 0) {
        packageId = packages[0].id;
      }
    } catch (err) {
      console.error('套餐名称解析失败:', err);
    }
  }
  if (!packageId) {
    resolve([]);
    return;
  }
  try {
    const res = await request({
      url: `/system/check-type/package/${packageId}/details`,
      method: 'get'
    });
    const list = parsePackageDetailsPayload(res);
    const children = list.map((child) => ({
      ...child,
      name: child.name || child.itemName,
      unit: child.unit || '次',
      price: child.price ?? child.unitPrice ?? child.itemPrice ?? 0,
      quantity: row.quantity || 1,
      isPackageDetail: true
    }));
    resolve(children);
  } catch (err) {
    console.error('加载套餐明细失败:', err);
    resolve([]);
  }
}

function getPackageDetailsList(item) {
  // 明细挂在行对象上，避免仅写入 methods 内嵌对象时首帧不触发视图更新（体感需点两次才展开）
  if (Array.isArray(item?.packageDetailsDisplay)) {
    return item.packageDetailsDisplay;
  }
  return Array.isArray(item?.packageDetails) ? item.packageDetails : [];
}

function getMethodPackageDetailsList(item) {
  if (Array.isArray(item?.methodPackageDetails)) {
    return item.methodPackageDetails;
  }
  return Array.isArray(item?.selectedMethod?.packageDetails) ? item.selectedMethod.packageDetails : [];
}

/** 有套餐 ID 或 packageName 的已选行才展示右侧套餐区（加载中 / 空 / 明细列表） */
function shouldShowPackageBody(item) {
  return shouldShowItemPackageBody(item) || shouldShowMethodPackageBody(item);
}

function hasItemPackage(item) {
  return !!(item?.packageId || item?.packageName);
}

function hasMethodPackage(item) {
  return !!(item?.selectedMethod?.packageId || item?.selectedMethod?.packageName);
}

function isSamePackage(item) {
  if (!hasItemPackage(item) || !hasMethodPackage(item)) return false;
  if (item.packageId && item.selectedMethod?.packageId) {
    return String(item.packageId) === String(item.selectedMethod.packageId);
  }
  return String(item.packageName || '') === String(item.selectedMethod?.packageName || '');
}

function shouldShowItemPackageBody(item) {
  return hasItemPackage(item);
}

function shouldShowMethodPackageBody(item) {
  return hasMethodPackage(item) && !isSamePackage(item);
}

/** 金额展示：统一两位小数 */
function formatDetailAmount(value) {
  const n = Number(value ?? 0);
  return Number.isFinite(n) ? n.toFixed(2) : '0.00';
}

/** 已选卡片名称：去掉 UI 上冗余的“套餐”前缀，完整名称通过 tooltip 展示 */
function getDisplayItemName(item) {
  return String(item?.name || '').replace(/^套餐[：:\-\s]*/, '');
}

/** 检查方法展示：避免与后端文案重复出现「(方法)(方法)」 */
function formatExamMethodCaption(name) {
  const raw = String(name || '').trim();
  if (!raw) return '';
  if (/^\(方法\)/.test(raw) || /^（方法）/.test(raw)) {
    return raw;
  }
  return `(方法) ${raw}`;
}

/** 已选方法纯文本（用于标题下级展示，不包含「勾选」前缀，去掉后端自带的 (方法) 前缀） */
function getDisplaySelectedMethodName(item) {
  const raw = String(item?.selectedMethod?.name || '').trim();
  if (!raw) return '';
  return raw.replace(/^\(方法\)\s*/, '').replace(/^（方法）\s*/, '').trim();
}

function getSelectedItemAmount(item) {
  return Number(item?.price || 0);
}

function parsePackageDetailsPayload(res) {
  const raw =
    res?.data?.data ??
    res?.data?.records ??
    res?.data ??
    res?.rows ??
    res;
  if (!Array.isArray(raw)) return [];
  return raw;
}

// #428: 为已选择项目加载套餐明细（后端：CheckTypeController /system/check-type/package/{id}/details）
async function loadPackageDetailsForItem(item) {
  let packageId = item.packageId;
  const packageName = item.packageName;
  if (!packageId && !packageName) {
    return;
  }
  item.packageDetailsLoading = true;
  try {
    if (!packageId && packageName) {
      const pkgRes = await listCheckPackage({ packageName });
      let packages = pkgRes?.data || [];
      if (!Array.isArray(packages)) {
        packages = packages.records || packages.data || [];
      }
      if (packages.length === 0) {
        item.packageDetails = [];
        item.packageDetailsDisplay = [];
        return;
      }
      packageId = packages[0].id;
      item.packageId = packageId;
      item.packageName = item.packageName || packageName;
    }
    if (!packageId) {
      item.packageDetails = [];
      item.packageDetailsDisplay = [];
      return;
    }
    const res = await request({
      url: `/system/check-type/package/${packageId}/details`,
      method: 'get'
    });
    const list = parsePackageDetailsPayload(res);
    const mapped = list.map((detail) => ({
      ...detail,
      name: detail.name || detail.itemName,
      unit: detail.unit || '次',
      price: detail.price ?? detail.unitPrice ?? detail.itemPrice ?? 0,
      quantity: detail.quantity || 1
    }));
    item.packageDetailsDisplay = mapped;
    if (res.code === 200 && res.data) {
      item.packageDetails = Array.isArray(res.data)
        ? res.data.map((detail) => ({
            ...detail,
            name: detail.name || detail.itemName,
            unit: detail.unit || '次',
            price: detail.price || detail.unitPrice || 0,
            quantity: detail.quantity || 1
          }))
        : mapped;
    } else {
      item.packageDetails = mapped;
    }
  } catch (err) {
    console.error('加载套餐明细失败:', err);
    item.packageDetailsDisplay = [];
    item.packageDetails = [];
  } finally {
    item.packageDetailsLoading = false;
  }
}
const detailTableRef = ref(null);
const formRef = ref(null);

// ====== 表单数据 ======
const form = reactive({
  applyNo: '',
  patientName: '',
  patientId: '',
  visitNo: '',
  applyDeptCode: '',
  performDeptCode: '',
  applyDocCode: '',
  applyTime: '',
  medicalrecordNumber: '',
  natureofCost: '自费医疗',
  clinicDesc: '',
  contraindication: '',
  medicalHistorySummary: '',
  purposeofInspection: '',
  inspectionArea: '',
  inspectionMethod: '',
  applyRemark: '',
  clinicalDiag: '',
  purposeDesc: '',
  isUrgent: 0,
  pregnancyState: 0,
  allergyDesc: '',
  applyStatus: 0,
  isCharged: 0,
  isRefunded: 0,
  isExecuted: 0,
  examTypeCode: '',   // 检查类型编码，必填字段，保存时从已选项目自动推导
  selectedMethodDisplay: ''  // Bug #384修复: 检查方法显示字段（联动）
});

const rules = {
  natureofCost: [{ required: true, message: '请选择费用性质', trigger: 'change' }],
  applyDeptCode: [{ required: true, message: '请输入申请科室', trigger: 'blur' }],
  applyDocCode: [{ required: true, message: '请输入申请医生', trigger: 'blur' }],
  performDeptCode: [{ required: true, message: '请输入执行科室', trigger: 'blur' }],
  clinicDesc: [{ required: true, message: '请输入诊断描述', trigger: 'blur' }],
  clinicalDiag: [{ required: true, message: '请输入临床诊断', trigger: 'blur' }],
  medicalHistorySummary: [{ required: true, message: '请输入病史摘要', trigger: 'blur' }],
  purposeDesc: [{ required: true, message: '请输入检查目的', trigger: 'blur' }]
};

// ====== 检查项目分类 ======
const categoryList = ref([]);   // 原始分类+项目数据
const dictSearchKey = ref('');
const activeNames = ref('');    // 当前展开的折叠项
const categoryLoadingSet = ref(new Set());  // Bug #500: 正在加载方法的分类集合
const currentActiveCategory = ref(null);  // Bug #500: 记录当前激活的分类，忽略过期请求响应

const allMethods = ref([]);

const activeCategory = computed(() => {
  const id = activeNames.value;
  if (id === '' || id === null || id === undefined) return null;
  return categoryList.value.find((cat) => String(cat.typeId) === String(id)) || null;
});

const activeCategoryName = computed(() => activeCategory.value?.typeName || activeCategory.value?.categoryName || '');

const methodsForActiveCategory = computed(() => {
  const arr = activeCategory.value?.methods;
  return Array.isArray(arr) ? arr : [];
});

// ====== 科室下拉（来源：科室管理）======
const orgLoading = ref(false);
const orgOptions = ref([]); // { label, value }
const orgFilteredOptions = ref([]); // 展示用（截断前200条）

// 加载所有检查方法
async function loadAllMethods() {
  try {
    const res = await listCheckMethod(); // 使用已导入的或者直接利用 request 请求
    let methods = [];
    if (res && res.data) {
      if (Array.isArray(res.data)) {
        methods = res.data;
      } else if (res.data.records) {
        methods = res.data.records;
      } else if (res.data.data && Array.isArray(res.data.data)) {
        methods = res.data.data;
      }
    } else if (Array.isArray(res)) {
      methods = res;
    } else if (res && res.rows) {
      methods = res.rows;
    }
    allMethods.value = methods;
  } catch (err) {
    console.error('加载检查方法失败', err);
  }
}

onMounted(async () => {
  await loadOrgOptions();
  await loadAllMethods();
  await loadCategoryList();
});

async function loadOrgOptions() {
  orgLoading.value = true;
  try {
    const res = await request({
      url: '/base-data-manage/organization/organization',
      method: 'get',
    });
    const records = res?.data?.records || res?.data || [];

    const flat = [];
    const walk = (nodes) => {
      if (!Array.isArray(nodes)) return;
      for (const n of nodes) {
        if (!n) continue;
        // 约定：typeEnum=2 为科室；若没有 typeEnum 也兜底收集
        if (n.name && (n.typeEnum === 2 || n.typeEnum === '2' || n.typeEnum == null)) {
          flat.push({ label: n.name, value: n.name });
        }
        if (Array.isArray(n.children) && n.children.length > 0) walk(n.children);
      }
    };
    walk(records);

    // 去重 + 排序
    const uniq = Array.from(new Map(flat.map(o => [o.value, o])).values())
      .filter(o => o?.value)
      .sort((a, b) => (a.label || '').localeCompare(b.label || '', 'zh-CN'));

    orgOptions.value = uniq;
    orgFilteredOptions.value = uniq.slice(0, 200);
  } catch (e) {
    console.error('加载科室列表失败', e);
    orgOptions.value = [];
    orgFilteredOptions.value = [];
  } finally {
    orgLoading.value = false;
  }
}

function handleOrgRemoteSearch(keyword) {
  const key = (keyword || '').trim().toLowerCase();
  if (!key) {
    orgFilteredOptions.value = orgOptions.value.slice(0, 200);
    return;
  }
  orgFilteredOptions.value = orgOptions.value
    .filter((o) => (o.label || '').toLowerCase().includes(key))
    .slice(0, 200);
}

// 动态可用的检查方法（根据已选部位所属的检查类型进行过滤）
const normalizeTypeValue = value => String(value ?? '').trim().toLowerCase();

const availableMethods = computed(() => {
  // 获取当前已选部位的检查类型（可取第一个选中的部位的 checkType）
  const currentType = form.examTypeCode || (selectedItems.value.length > 0 ? selectedItems.value[0].checkType : '');
  const normalizedCurrentType = normalizeTypeValue(currentType);
  if (normalizedCurrentType) {
    // 兼容脏数据：method 的类型可能落在 checkType/type/typeCode/code/typeName/categoryName 中
    const filtered = allMethods.value.filter(m => {
      const typeCandidates = [
        m.checkType,
        m.type,
        m.typeCode,
        m.code,
        m.typeName,
        m.categoryName
      ].map(normalizeTypeValue).filter(Boolean);
      return typeCandidates.includes(normalizedCurrentType);
    });
    return filtered.length > 0 ? filtered : allMethods.value;
  }
  return allMethods.value;
});

function isStandaloneMethodSelected(method) {
  return selectedMethods.value.some((m) => String(m.id) === String(method?.id));
}

function getDisplayMethodName(method) {
  const raw = String(method?.name || '').trim();
  if (!raw) return '';
  return raw.replace(/^\(方法\)\s*/, '').replace(/^（方法）\s*/, '').trim();
}

function hasStandaloneMethodPackage(method) {
  return !!(method?.packageId || method?.packageName);
}

function getStandaloneMethodPackageDetailsList(method) {
  return Array.isArray(method?.packageDetails) ? method.packageDetails : [];
}

async function onStandaloneMethodChange(checked, method) {
  if (!method) return;
  if (checked) {
    if (!isStandaloneMethodSelected(method)) {
      selectedMethods.value.push({
        ...method,
        expanded: false,
        packageLoading: false,
        packageDetails: []
      });
    }
  } else {
    const idx = selectedMethods.value.findIndex((m) => String(m.id) === String(method.id));
    if (idx > -1) selectedMethods.value.splice(idx, 1);
  }
  updateMethodDisplay();
  await nextTick();
  form.totalAmount = totalAmountCalc.value;
}

// 当可选方法列表改变时，如果当前选中的方法不在新列表中，则清空
// #428: 分类展开时联动加载检查方法
// Bug #500: 使用 categoryLoadingSet 替代 dictLoading，避免切换分类时整个区域闪烁
// Bug #500: 添加 currentActiveCategory 守卫，忽略过期请求响应，防止快速切换时数据闪烁
async function handleCategoryExpand(cat) {
  if (!cat || !cat.typeName) return;

  if ((cat.methods && cat.methods.length > 0) || categoryLoadingSet.value.has(cat.typeId)) return;

  categoryLoadingSet.value.add(cat.typeId);
  currentActiveCategory.value = cat.typeId;
  try {
    const res = await searchCheckMethod({ checkType: cat.typeName });
    // 忽略过期请求：用户已切换到其他分类，丢弃当前响应
    if (currentActiveCategory.value !== cat.typeId) return;
    let data = res?.data?.data || res?.data || res?.rows || res;
    if (!Array.isArray(data) && res?.data && Array.isArray(res.data.data)) {
      data = res.data.data;
    }

    if (Array.isArray(data) && data.length > 0) {
      cat.methods = data.map(m => ({
        id: m.id,
        name: m.name,
        code: m.code,
        price: m.price || 0,
        packageName: m.packageName || '',
        packageId: m.packageId || null,
        packagePrice: m.packagePrice || null,
        serviceFee: m.serviceFee || null
      }));
    }
  } catch (err) {
    if (currentActiveCategory.value !== cat.typeId) return;
    console.error('加载分类检查方法失败', err);
  } finally {
    categoryLoadingSet.value.delete(cat.typeId);
  }
}
// Bug #500修复: 不阻塞 accordion 状态更新，仅防止重复加载同一分类的方法
function handleCollapseChange(activeName) {
  // 始终记录当前激活的分类，确保 handleCategoryExpand 能正确忽略过期请求
  currentActiveCategory.value = activeName || null;
  // 底部「检查方法」勾选区默认展开，不因切换左侧分类而收起
  methodPickerExpanded.value = true;

  if (activeName) {
    // Bug #428修复: 直接从 categoryList（原始响应式数组）查找分类，
    // 确保后续 handleCategoryExpand 对 cat.methods 的赋值能正确触发 Vue 响应式更新
    const cat = categoryList.value.find(c => c.typeId == activeName);
    if (cat && (!cat.methods || cat.methods.length === 0)) {
      handleCategoryExpand(cat);  // 异步加载，不 await
    }
  }
  updateMethodDisplay();
}

watch(availableMethods, (newMethods) => {
  if (form.inspectionMethod && !newMethods.find(m => m.name === form.inspectionMethod)) {
    form.inspectionMethod = '';
  }
});

/**
 * 加载检查类型（分类）和检查项目（部位/项目），按类型分组展示
 */
async function loadCategoryList() {
  dictLoading.value = true;
  try {
    // 1. 加载检查类型（分类名称），只取父级
    const typeRes = await request({
      url: '/system/check-type/list',
      method: 'get',
      params: { pageNo: 1, pageSize: 500 }  // 取全量分类数据
    });
    let types = [];
    if (typeRes && typeRes.data) {
      if (Array.isArray(typeRes.data)) {
        types = typeRes.data;
      } else if (typeRes.data.records) {
        types = typeRes.data.records;
      } else if (typeRes.data.data && Array.isArray(typeRes.data.data)) {
        types = typeRes.data.data;
      }
    } else if (Array.isArray(typeRes)) {
      types = typeRes;
    } else if (typeRes && typeRes.rows) {
      types = typeRes.rows;
    }

    // 2. 加载检查项目（检查部位项目）
    const partRes = await request({ url: '/check/part/list', method: 'get' });
    let parts = [];
    if (partRes && partRes.data) {
      if (Array.isArray(partRes.data)) {
        parts = partRes.data;
      } else if (partRes.data.records) {
        parts = partRes.data.records;
      } else if (partRes.data.data && Array.isArray(partRes.data.data)) {
        parts = partRes.data.data;
      }
    } else if (Array.isArray(partRes)) {
      parts = partRes;
    } else if (partRes && partRes.rows) {
      parts = partRes.rows;
    }

    // 3. 按 checkType 归类
    const dict = [];
    for (const t of types) {
      dict.push({
        typeId: t.id,
        typeCode: t.code,        // 保存 code 用于后备匹配
        orgType: t.type,         // 保存 type 用于后备匹配
        typeName: t.name,        // 保存 name
        categoryName: t.name,
        // “检查类型管理”里配置的执行科室（图三）
        performDeptName: t.department || '',
        items: [],
        methods: []   // #428修复: 初始化 methods 数组，确保 Vue 响应式追踪
      });
    }
    const unclassified = [];
    for (const p of parts) {
      const mapped = {
        id: p.id,
        name: p.name,
        price: p.price || 0,
        serviceFee: p.serviceFee || 0,
        unit: '次',
        checkType: p.checkType || '',
        nationalCode: p.nationalCode || '',
        packageName: p.packageName || '',
        packageId: p.packageId || null,
        checked: false
      };
      
      // 增强匹配逻辑：部位的 checkType (如 'ECG', 'CT') 优先去匹配大类的 orgType，
      // 如果大类的 type 字段脏了（比如填了中文），则尝试匹配 code，甚至是分类名称
      const target = dict.find(d => 
        d.orgType === p.checkType || 
        d.typeCode === p.checkType ||
        d.typeName === p.checkType
      );
      
      if (target) target.items.push(mapped);
      else unclassified.push(mapped);
    }
    if (unclassified.length > 0) {
      dict.push({ typeId: 'uncls', typeCode: '', categoryName: '其他', items: unclassified });
    }
    categoryList.value = dict.filter(d => d.items.length > 0);

    // 默认展开第一个
    if (categoryList.value.length > 0) {
      const firstCat = categoryList.value[0];
      activeNames.value = firstCat.typeId;
      await nextTick();
      await handleCategoryExpand(firstCat);
    }
  } catch (err) {
    console.error('加载检查项目分类失败', err);
  } finally {
    dictLoading.value = false;
  }
}

/** 关键词过滤后的分类列表 */
const filteredCategoryList = computed(() => {
  if (!dictSearchKey.value) return categoryList.value;
  const key = dictSearchKey.value.toLowerCase();
  return categoryList.value.map(cat => ({
    ...cat,
    items: cat.items.filter(item => (item.name || '').toLowerCase().includes(key)),
    methods: cat.methods || []
  })).filter(cat => cat.items.length > 0);
});

// ====== 合计 ======
const totalAmountCalc = computed(() => {
  const itemTotal = selectedItems.value.reduce((sum, item) => {
    const effectivePrice = getSelectedItemAmount(item);
    return sum + (effectivePrice * (item.quantity || 1));
  }, 0);
  const methodTotal = selectedMethods.value.reduce((sum, method) => {
    return sum + Number(method?.packagePrice ?? method?.price ?? 0);
  }, 0);
  const total = itemTotal + methodTotal;
  return total.toFixed(2);
});

// 监听已选项：自动更新申检部位
watch(selectedItems, () => {
  form.inspectionArea = selectedItems.value.map(i => i.name).join('+');
  form.isCharged = selectedItems.value.length > 0 || selectedMethods.value.length > 0 ? 1 : 0;
}, { deep: true });

watch(selectedMethods, () => {
  form.isCharged = selectedItems.value.length > 0 || selectedMethods.value.length > 0 ? 1 : 0;
  updateMethodDisplay();
}, { deep: true });

// 监听患者变化
watch(() => props.patientInfo, (newVal) => {
  if (newVal?.encounterId) {
    initPatientForm(newVal);
    getList();
  }
}, { immediate: true, deep: true });

watch(() => props.activeTab, async (val) => {
  if (val === 'examination') {
    getList();
    // 切换到检查页签时，重新获取临床诊断（确保与诊断页签同步）
    if (props.patientInfo?.encounterId) {
      await loadClinicalDiag();
    }
  }
});

function initPatientForm(patient) {
  form.patientName = patient.patientName || '';
  // 就诊卡号应取值于 identifierNo，而非 busNo（busNo 是病历号）
  form.medicalrecordNumber = patient.identifierNo || patient.visitNo || '';
  form.patientId = patient.patientId || '';
  form.visitNo = patient.visitNo || '';
  form.applyDeptCode = userStore.orgName || patient.organizationName || '';
  form.applyDocCode = userStore.nickName || '';
}

// 加载临床诊断：获取患者主诊断并填充到临床诊断字段
async function loadClinicalDiag() {
  if (!props.patientInfo?.encounterId) return;
  try {
    const res = await getEncounterDiagnosis(props.patientInfo.encounterId);
    const diagnoses = res.data || res.rows || res;
    if (Array.isArray(diagnoses) && diagnoses.length > 0) {
      // Bug #380, #381 修复: 主诊断字段名为 maindiseFlag (后端 DiagnosisQueryDto 定义)
      const mainDiag = diagnoses.find(d => d.maindiseFlag === 1 || d.maindiseFlag === '1');
      // 如果有主诊断使用主诊断，否则使用第一个诊断
      const targetDiag = mainDiag || diagnoses[0];
      // 优先使用 diagnosisName，其次是 conditionName 或 name
      form.clinicalDiag = targetDiag.diagnosisName || targetDiag.conditionName || targetDiag.name || '';
    } else {
      // 如果没有诊断，清空临床诊断字段
      form.clinicalDiag = '';
    }
  } catch (err) {
    console.error('加载临床诊断失败', err);
    // 获取失败时不阻断用户操作，保持字段为空
  }
}

// ====== 申请单 CRUD ======
function getList() {
  loading.value = true;
  request({
    url: '/exam/apply/list',
    method: 'get',
    // 默认只展示本次就诊（encounterId）产生的检查申请单
    params: { encounterId: props.patientInfo?.encounterId || '' }
  }).then(res => {
    applicationList.value = res.rows || res.data || [];
  }).catch(err => console.error('获取申请单列表失败', err))
    .finally(() => { loading.value = false; });
}

function handleAdd() {
  formRef.value?.resetFields();
  Object.assign(form, {
    applyNo: '',
    patientId: props.patientInfo?.patientId || '',
    visitNo: props.patientInfo?.visitNo || '',
    // 保留患者姓名和就诊卡号，不应重置为空
    patientName: props.patientInfo?.patientName || '',
    medicalrecordNumber: props.patientInfo?.identifierNo || '',
    applyDeptCode: userStore.orgName || '',
    performDeptCode: '',
    applyDocCode: userStore.nickName || '',
    applyTime: new Date().toISOString().split('T')[0] + ' 12:00:00',
    natureofCost: '自费医疗',
    clinicDesc: '', contraindication: '', medicalHistorySummary: '',
    purposeofInspection: '', inspectionArea: '', inspectionMethod: '',
    applyRemark: '', clinicalDiag: '', purposeDesc: '',
    isUrgent: 0, pregnancyState: 0, allergyDesc: '',
    applyStatus: 0, isCharged: 0, isRefunded: 0, isExecuted: 0,
    examTypeCode: '',
    selectedMethodDisplay: ''  // Bug #384修复: 重置检查方法显示
  });
  selectedItems.value = [];
  selectedMethods.value = [];
  resetCategoryChecked();
  activeDetailTab.value = 'applyForm';
  // 自动加载临床诊断
  loadClinicalDiag();
}

function handleSave() {
  formRef.value.validate(valid => {
    if (!valid) return;
    if (selectedItems.value.length === 0) {
      ElMessage.warning('请至少选择一个检查明细项目');
      return;
    }
    if (selectedMethods.value.length === 0) {
      ElMessage.warning('请选择检查方法');
      return;
    }
    // 从已选项目推导检查类型编码（取第一个项目的 checkType，如 CT / ECG / GI）
    const firstCheckType = selectedItems.value[0]?.checkType || 'unknown';
    form.examTypeCode = firstCheckType;
    form.totalAmount = totalAmountCalc.value;


    const primaryMethod = selectedMethods.value[0] || null;
    const payload = {
      ...form,
      encounterId: props.patientInfo?.encounterId || null,
      patientIdNum: props.patientInfo?.patientId || null,
      checkMethods: selectedMethods.value.map((method) => ({
        checkMethodId: method.id || null,
        checkMethodName: method.name || null,
        checkMethodCode: method.code || null,
        checkMethodPackageName: method.packageName || null
      })),
      items: selectedItems.value.map((item, index) => ({
        itemCode: String(item.id),
        itemName: item.name,
        bodyPartCode: item.checkType || 'unknown',
        itemFee: getSelectedItemAmount(item),
        performDeptCode: form.performDeptCode || '',
        itemStatus: 0,
        itemSeq: index + 1,
        // 检查方法信息
        checkMethodId: primaryMethod?.id || null,
        checkMethodName: primaryMethod?.name || null,
        checkMethodCode: primaryMethod?.code || null,
        checkMethodPackageName: primaryMethod?.packageName || null  // Bug #384修复: 保存套餐名称
      }))
    };
    request({
      url: '/exam/apply',
      method: payload.applyNo ? 'put' : 'post',
      data: payload
    }).then(res => {
      ElMessage.success('保存成功');
      getList();
      if (res.data) form.applyNo = res.data;
      // 通知父组件刷新医嘱列表
      emit('saved');
    });
  });
}

function handleRowClick(row) {
  Object.assign(form, row);
  form.selectedMethodDisplay = '';  // Bug #384修复: 先清空，后面根据回充数据更新
  selectedItems.value = [];
  selectedMethods.value = [];
  activeDetailTab.value = 'applyForm';
  request({ url: `/exam/apply/${row.applyNo}`, method: 'get' }).then(async res => {
    // 响应结构: Axios拦截器对code===200返回res.data（AjaxResult体）
    // 结构为 { code: 200, data: examApply实体, items: [明细数组] }
    const items = Array.isArray(res.items) ? res.items : [];
    const dataObj = res.data || {};

    // 先填充表单字段
    if (dataObj && typeof dataObj === 'object') Object.assign(form, dataObj);

    if (items.length > 0) {
      try {
        // 为每个项目加载检查方法
        const itemsWithMethods = await Promise.all(items.map(async m => {
          const item = {
            id: m.itemCode, name: m.itemName,
            price: m.itemFee || 0, quantity: 1,
            serviceFee: 0, unit: '次',
            applyPart: m.itemName,
            checkType: m.bodyPartCode || '',
            nationalCode: '', checked: true,
            methods: [],
            selectedMethod: null,
            expanded: false,
            projectFoldExpanded: false,
            methodFoldExpanded: false,
            methodPackageExpanded: false,
            packageDetailsLoading: false,
            isPackage: false,
            packageId: null,
            hasChildren: false  // #426修复: 树形表格懒加载展开标记，后续根据packageId动态设置
          };
          // 加载该项目的检查方法
          if (m.bodyPartCode) {
            try {
              const methodRes = await searchCheckMethod({ checkType: m.bodyPartCode });
              // 正确解析 API 返回结构
              let methodData = methodRes?.data?.data || methodRes?.data || methodRes?.rows || methodRes;
              if (!Array.isArray(methodData) && methodRes?.data && Array.isArray(methodRes.data.data)) {
                methodData = methodRes.data.data;
              }
              if (Array.isArray(methodData)) {
                item.methods = methodData.map(md => ({
                  id: md.id,
                  name: md.name,
                  code: md.code,
                  price: m.itemFee || 0,
                  packageName: md.packageName || '',
                  packageId: md.packageId || null,
                  packagePrice: md.packagePrice || null,
                  serviceFee: md.serviceFee || null
                }));
                // 回充已保存的检查方法
                if (m.checkMethodId) {
                  item.selectedMethod = item.methods.find(md => String(md.id) === String(m.checkMethodId)) || null;
                  if (item.selectedMethod?.packageId) {
                    item.hasChildren = true;  // #426修复
                  }
                }
                if (item.selectedMethod?.packageId) {
                  item.hasChildren = true;  // #426修复
                }
              }
            } catch (err) {
              console.error('加载检查方法失败', err);
            }
          }
          return item;
        }));
        // Bug #408修复: 确保明细数据正确加载到selectedItems
        const methodMap = new Map();
        for (const item of itemsWithMethods) {
          if (item.selectedMethod && !methodMap.has(String(item.selectedMethod.id))) {
            methodMap.set(String(item.selectedMethod.id), {
              ...item.selectedMethod,
              expanded: false,
              packageLoading: false,
              packageDetails: []
            });
          }
          item.selectedMethod = null;
          item.methodPackageDetails = [];
        }
        selectedItems.value = itemsWithMethods;
        selectedMethods.value = Array.from(methodMap.values());
        // 加载套餐明细（单个失败不影响其他项目和明细显示）
        for (const it of selectedItems.value) {
          if (hasItemPackage(it)) {
            try {
              await loadPackageDetailsForItem(it);
            } catch (e) {
              console.error('加载套餐明细失败:', it.name, e);
            }
          }
          it.methodFoldExpanded = false;
          syncItemExpandedFlag(it);
        }
        for (const method of selectedMethods.value) {
          if (hasStandaloneMethodPackage(method)) {
            try {
              await loadStandaloneMethodPackageDetails(method);
            } catch (e) {
              console.error('加载检查方法套餐明细失败:', method.name, e);
            }
          }
        }
        syncCategoryChecked();
        // Bug #384修复: 回充后更新检查方法显示
        updateMethodDisplay();
        // Bug #408修复: 加载申请单详情后自动切换到检查明细页签，确保已加载的明细数据可见
        activeDetailTab.value = 'applyDetail';
      } catch (err) {
        console.error('加载申请单详情失败', err);
        ElMessage.error('加载申请单详情失败');
      }
    }
  }).catch(err => {
    console.error('获取申请单详情失败', err);
    ElMessage.error('获取申请单详情失败');
  });
}

function handlePrint(row) { ElMessage.info('打印申请单：' + row.applyNo); }

function handleDelete(row) {
  ElMessageBox.confirm('确认删除该检查申请单吗？', '警告', { type: 'warning' }).then(() => {
    request({ url: `/exam/apply/${row.applyNo}`, method: 'delete' }).then(() => {
      ElMessage.success('删除成功');
      getList();
      if (form.applyNo === row.applyNo) handleAdd();
    });
  });
}

// ====== 勾选逻辑 ======
async function handleItemSelect(checked, item, cat) {
  if (checked) {
    // Bug #384修复: 检查方法表的 checkType 字段关联的是检查类型的 name（中文名称，如"心电图")
    const effectiveCheckType = cat?.typeName || cat?.categoryName || '';

    // 查询该检查类型对应的检查方法
    let methods = [];
    try {
      if (effectiveCheckType) {
        const res = await searchCheckMethod({ checkType: effectiveCheckType });
        // Bug #384修复: API 返回结构可能是 {data: {data: Array}} 或 {data: Array}
        let data = res?.data?.data || res?.data || res?.rows || res;
        if (!Array.isArray(data) && res?.data && Array.isArray(res.data.data)) {
          data = res.data.data;
        }
        if (Array.isArray(data)) {
          methods = data.map(m => ({
            id: m.id,
            name: m.name,
            code: m.code,
            price: m.price || item.price,  // fallback 到项目价格
            packageName: m.packageName || '',
            packageId: m.packageId || null,
            packagePrice: m.packagePrice || null,  // Bug #384修复: 套餐价格
            serviceFee: m.serviceFee || null      // Bug #384修复: 服务费
          }));
        }
      }
    } catch (err) {
      console.error('加载检查方法失败', err);
    }

    if (selectedItems.value.length > 0) {
      const currentCategory = selectedItems.value[0].checkType;
      // Bug #428修复: 使用 cat.typeName 进行比较（与 effectiveCheckType 保持一致）
      const newCategory = cat.typeName || '';
      if (currentCategory !== newCategory) {
        ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
        item.checked = false;
        return;
      }
    }

    const newRow = {
      id: item.id, name: item.name,
      price: item.price, quantity: 1,
      serviceFee: item.serviceFee || 0,
      unit: item.unit || '次',
      applyPart: item.name,
      checkType: effectiveCheckType,  // Bug #384修复: 使用有效的 checkType
      nationalCode: item.nationalCode || '',
      checked: true,
      methods: methods,
      selectedMethod: null,
      expanded: false,
      projectFoldExpanded: false,
      methodFoldExpanded: false,
      methodPackageExpanded: false,
      isPackage: !!(item.packageId || item.packageName),
      packageName: item.packageName || null,
      packageDetailsLoading: false,
      packageId: item.packageId || null,
      hasChildren: !!(item.packageId || item.packageName)  // #426修复: 树形表格懒加载展开标记，支持 packageName 解析
    };
    selectedItems.value.push(newRow);
    // 必须用数组里的响应式行，不能继续改局部 newRow：push 后列表内是 proxy，改 raw 对象不会触发右侧卡片更新（会一直卡在「加载中」）

    const rowJustAdded = selectedItems.value[selectedItems.value.length - 1];
    syncItemExpandedFlag(rowJustAdded);

    updateMethodDisplay();
    await nextTick();
    form.totalAmount = totalAmountCalc.value;

    // 自动回填执行科室：按检查项目类型 → 检查类型管理里配置的执行科室
    if (selectedItems.value.length === 1 && cat?.performDeptName) {
      form.performDeptCode = cat.performDeptName;
    } else if (!form.performDeptCode && cat?.performDeptName) {
      form.performDeptCode = cat.performDeptName;
    }

  } else {
    const idx = selectedItems.value.findIndex(s => s.id === item.id);
    if (idx > -1) selectedItems.value.splice(idx, 1);
    
    if (selectedItems.value.length === 0) {
      form.performDeptCode = '';
      form.examTypeCode = '';
    }
  }
  // Bug #382 修复：移除自动切换页签逻辑，保持当前页签状态
}

/** expanded 与各折叠条保持一致（明细表等仍可依赖 expanded） */
function syncItemExpandedFlag(row) {
  if (!row) return;
  row.expanded = !!(row.projectFoldExpanded || row.methodFoldExpanded);
}

async function toggleProjectFold(item) {
  item.projectFoldExpanded = !item.projectFoldExpanded;
  syncItemExpandedFlag(item);
  if (item.projectFoldExpanded && hasItemPackage(item) && getPackageDetailsList(item).length === 0 && !item.packageDetailsLoading) {
    await loadPackageDetailsForItem(item);
  }
}

async function toggleMethodPackageExpand(item) {
  item.methodPackageExpanded = !item.methodPackageExpanded;
  if (
    item.methodPackageExpanded &&
    item.selectedMethod &&
    getMethodPackageDetailsList(item).length === 0 &&
    !item.methodPackageLoading
  ) {
    await loadMethodPackageDetails(item, item.selectedMethod);
  }
}

async function toggleSelectedMethodFold(method) {
  method.expanded = !method.expanded;
  if (
    method.expanded &&
    hasStandaloneMethodPackage(method) &&
    getStandaloneMethodPackageDetailsList(method).length === 0 &&
    !method.packageLoading
  ) {
    await loadStandaloneMethodPackageDetails(method);
  }
}

function handleRemoveMethod(idx) {
  selectedMethods.value.splice(idx, 1);
  updateMethodDisplay();
}

async function loadStandaloneMethodPackageDetails(method) {
  method.packageLoading = true;
  method.packageDetails = [];
  try {
    let packageId = method.packageId;
    if (!packageId && !method.packageName) {
      method.packageLoading = false;
      return;
    }
    if (!packageId && method.packageName) {
      const pkgRes = await listCheckPackage({ packageName: method.packageName });
      let packages = pkgRes?.data || [];
      if (!Array.isArray(packages)) {
        packages = packages.records || packages.data || [];
      }
      if (packages.length === 0) {
        method.packageLoading = false;
        return;
      }
      packageId = packages[0].id;
      method.packageId = packageId;
    }
    const detailRes = await request({
      url: `/system/check-type/package/${packageId}/details`,
      method: 'get'
    });
    method.packageDetails = parsePackageDetailsPayload(detailRes).map(d => ({
      id: d.id,
      name: d.name || d.itemName,
      quantity: d.quantity || 1,
      unit: d.unit || '次',
      price: d.price ?? d.unitPrice ?? d.itemPrice ?? 0,
      amount: d.amount || d.total || 0,
      checked: true
    }));
  } catch (err) {
    console.error('加载检查方法套餐明细失败:', err);
    method.packageDetails = [];
  } finally {
    method.packageLoading = false;
  }
}

// 根据检查方法的packageName加载对应的套餐明细
async function loadMethodPackageDetails(item, method) {
  item.methodPackageLoading = true;
  item.methodPackageDetails = [];
  try {
    let packageId = method.packageId;
    if (!packageId && !method.packageName) {
      item.methodPackageLoading = false;
      return;
    }
    // 通过packageName查询套餐获取packageId
    if (!packageId && method.packageName) {
      const pkgRes = await listCheckPackage({ packageName: method.packageName });
      let packages = pkgRes?.data || [];
      if (!Array.isArray(packages)) {
        packages = packages.records || packages.data || [];
      }
      if (packages.length === 0) {
        item.methodPackageLoading = false;
        return;
      }
      packageId = packages[0].id;
      method.packageId = packageId;
    }
    // 查询套餐明细
    const detailRes = await request({
      url: `/system/check-type/package/${packageId}/details`,
      method: 'get'
    });
    const detailList = parsePackageDetailsPayload(detailRes);
    if (detailList.length > 0) {
      const mapped = detailList.map(d => ({
        id: d.id,
        name: d.name || d.itemName,
        quantity: d.quantity || 1,
        unit: d.unit || '次',
        price: d.price ?? d.unitPrice ?? d.itemPrice ?? 0,
        amount: d.amount || d.total || 0,
        checked: true  // 默认勾选
      }));
      item.methodPackageDetails = mapped;
      method.packageDetails = mapped;
    }
  } catch (err) {
    console.error('加载方法套餐明细失败:', err);
    item.methodPackageDetails = [];
  } finally {
    item.methodPackageLoading = false;
  }
}

/** 检查明细表格中切换检查方法 */
async function onDetailMethodChange(row, val) {
  row.selectedMethod = val || null;
  if (val?.packageId || val?.packageName) {
    row.hasChildren = true;  // #426修复
  }
  row.methodPackageDetails = [];
  updateMethodDisplay();
  const open = shouldShowPackageBody(row);
  row.expanded = open;
  row.projectFoldExpanded = shouldShowItemPackageBody(row) && open;
  row.methodFoldExpanded = shouldShowMethodPackageBody(row) && open;
  row.methodPackageExpanded = false;
  syncItemExpandedFlag(row);
  if (hasItemPackage(row)) {
    await loadPackageDetailsForItem(row);
  }
  if (val?.packageId || val?.packageName) {
    await loadMethodPackageDetails(row, val);
  }
  nextTick(() => {
    form.totalAmount = totalAmountCalc.value;
  });
}

// Bug #384修复: 更新检查方法显示字段（取自独立已选检查方法）
function updateMethodDisplay() {
  if (selectedMethods.value.length > 0) {
    form.selectedMethodDisplay = selectedMethods.value.map((method) => method.name).join('、');
    return;
  }
  form.selectedMethodDisplay = '';
}

function handleRemoveItem(idx, item) {
  selectedItems.value.splice(idx, 1);
  // 取消对应 category 中的 checkbox
  for (const cat of categoryList.value) {
    const found = cat.items.find(x => x.id === item.id);
    if (found) { found.checked = false; break; }
  }

  if (selectedItems.value.length === 0) {
    form.performDeptCode = '';
    form.examTypeCode = '';
    updateMethodDisplay();
  } else {
    // Bug #384修复: 移除后重新计算检查方法显示
    updateMethodDisplay();
  }
}

function resetCategoryChecked() {
  for (const cat of categoryList.value)
    for (const item of cat.items) item.checked = false;
}

function syncCategoryChecked() {
  resetCategoryChecked();
  const ids = new Set(selectedItems.value.map(s => s.id));
  for (const cat of categoryList.value)
    for (const item of cat.items)
      if (ids.has(item.id)) item.checked = true;
}

defineExpose({ getList });
</script>

<style scoped>
.exam-app-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 8px;
  height: 100%;
  background: #f0f2f5;
}

/* 顶部申请单列表 */
.top-section {
  background: #fff;
  border-radius: 4px;
  padding: 10px 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}
.section-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
}
.header-actions {
  display: flex;
  gap: 8px;
}

/* Bug #499: 查询过滤工具栏 */
.search-toolbar {
  margin-bottom: 10px;
  padding: 8px 0;
  border-bottom: 1px solid #ebeef5;
}
.search-toolbar :deep(.el-form-item) {
  margin-bottom: 8px;
}
.search-toolbar :deep(.el-form-item__label) {
  font-size: 12px;
}

/* 底部区域：左表单 + 右分类 */
.bottom-section {
  display: flex;
  gap: 10px;
  flex: 1;
  min-height: 0;
}

/* 左：表单面板 */
.form-panel {
  flex: 1;
  background: #fff;
  border-radius: 4px;
  padding: 10px 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
  overflow-y: auto;
  min-width: 0;
}
.form-tabs :deep(.el-tabs__header) {
  margin-bottom: 10px;
}
.apply-form :deep(.el-form-item) {
  margin-bottom: 10px;
}
.apply-form :deep(.el-form-item__label) {
  font-size: 12px;
}
.total-row {
  margin-top: 8px;
  text-align: right;
  font-size: 13px;
  color: #606266;
}
.total-amount {
  font-size: 15px;
  font-weight: bold;
  color: #f56c6c;
  margin-left: 4px;
}

/* 右：分类面板 */
.category-panel {
  width: 560px;
  flex-shrink: 0;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.panel-top {
  display: flex;
  gap: 12px;
  flex: 1;
  min-height: 0;
}
.category-left {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.panel-label {
  font-size: 13px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 6px;
}
.search-input {
  margin-bottom: 8px;
}
.collapse-scroll {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;  /* Bug #500: 防止切换时水平方向溢出导致抖动 */
  min-height: 300px;   /* Bug #500: 增大最小高度，避免折叠动画期间容器高度突变 */
}
.empty-hint {
  color: #909399;
  font-size: 12px;
  text-align: center;
  padding: 20px 0;
}

/* 检查项目分类折叠 */
.cat-title {
  font-size: 13px;
  font-weight: 500;
  color: #303133;
}
/* Bug #500: 分类加载中的小圆点动画 */
.loading-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #409eff;
  margin-left: 6px;
  animation: dotPulse 1s ease-in-out infinite;
}
@keyframes dotPulse {
  0%, 100% { opacity: 0.3; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1.2); }
}
.item-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 3px 4px;
}
.item-row:hover {
  background: #f5f7fa;
}
.item-checkbox {
  flex: 1;
  overflow: hidden;
}
.item-checkbox :deep(.el-checkbox__label) {
  font-size: 12px;
  color: #303133;
}
.item-price {
  font-size: 12px;
  color: #1890FF;
  flex-shrink: 0;
  margin-left: 6px;
}

/* Bug #428修复: 分类下检查方法区域样式 */
.method-section {
  padding: 6px 8px;
  background: #f0f7ff;
  border-radius: 4px;
  margin-top: 6px;
  min-height: 50px;  /* Bug #500: 方法区域预留最小高度，减少加载完成后的高度突变 */
}

.method-section-title {
  font-size: 12px;
  font-weight: 600;
  color: #409eff;
  margin-bottom: 4px;
  padding-bottom: 3px;
  border-bottom: 1px dashed #d9ecff;
}

.method-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 3px 4px;
  border-radius: 3px;
}

.method-row:hover {
  background: #e8f4ff;
}

.method-checkbox {
  flex: 1;
  overflow: hidden;
}

.method-checkbox :deep(.el-checkbox__label) {
  font-size: 12px;
  color: #303133;
}

.method-price-tag {
  font-size: 11px;
  color: #e6a23c;
  font-weight: 500;
  flex-shrink: 0;
  margin-left: 6px;
}

/* Bug #500修复: 方法列表骨架占位样式 */
.method-section-skeleton {
  opacity: 0.6;
  pointer-events: none;
}
.skeleton-method-row {
  height: 22px;
  border-radius: 3px;
  background: linear-gradient(90deg, #e8f4ff 25%, #d0e8ff 50%, #e8f4ff 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s ease-in-out infinite;
  margin-bottom: 4px;
}
@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* 已选择 tags */
/* 已选择：加宽，避免套餐明细挤成一团 */
.selected-panel {
  width: 260px;
  min-width: 240px;
  max-width: 320px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
}
.selected-tags {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-right: 2px;
}
.selected-tag {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.empty-selected {
  color: #c0c4cc;
  font-size: 12px;
}

/* 已选择项目卡片 */
.selected-item-card {
  display: flex;
  flex-direction: column;
  background: #fff;
  border-radius: 6px;
  border: 1px solid #e4e7ed;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  overflow: hidden;
}

/* 项目上 / 方法下：各自独立下拉条 */
.fold-strip {
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.fold-strip:last-child {
  border-bottom: none;
}

.fold-strip-header {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 10px 10px;
  cursor: pointer;
  background: linear-gradient(180deg, #f8fafc 0%, #f0f4f8 100%);
}

.fold-strip-header:hover {
  background: linear-gradient(180deg, #ecf5ff 0%, #e3eef8 100%);
}

.fold-strip-method.is-method-target .fold-strip-header {
  background: linear-gradient(180deg, #e8f3ff 0%, #dceaff 100%);
}

.fold-chevron {
  font-size: 14px;
  color: #909399;
  transition: transform 0.2s ease;
  flex-shrink: 0;
  margin-top: 2px;
  transform: rotate(-90deg);
}

.fold-chevron.open {
  transform: rotate(0deg);
}

.fold-header-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.fold-kicker {
  font-size: 11px;
  font-weight: 600;
  color: #909399;
  letter-spacing: 0.03em;
}

.fold-title {
  font-size: 13px;
  font-weight: 600;
  color: #303133;
  line-height: 1.35;
  word-break: break-word;
}

.fold-title-plain {
  font-weight: 500;
  color: #606266;
}

.line-clamp-2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.fold-price-strong {
  font-size: 13px;
  color: #409eff;
  font-weight: 600;
  flex-shrink: 0;
  margin-top: 2px;
}

.fold-price-strong.warn {
  color: #e6a23c;
}

.fold-strip-body {
  background: #fafbfc;
  padding: 0 10px 10px 36px;
  border-top: 1px dashed var(--el-border-color-lighter);
}

.fold-package-wrap {
  padding-top: 6px;
}

.fold-strip-muted {
  font-size: 12px;
  color: #909399;
  padding: 10px 0 4px;
}

.selected-global-method-picker {
  flex-shrink: 0;
  margin-top: 8px;
  border-radius: 6px;
  border: 1px solid #e4e7ed;
  background: #fff;
  overflow: hidden;
}

.method-picker-collapse-title {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 10px;
  cursor: pointer;
  background: #fff;
}

.method-picker-collapse-title:hover {
  background: #f5f7fa;
}

.method-picker-title-main {
  flex: 1;
  min-width: 0;
  font-size: 13px;
  font-weight: 600;
  color: #303133;
}

.global-method-picker-scope {
  font-size: 12px;
  color: #909399;
  flex-shrink: 0;
}

.method-picker-arrow {
  font-size: 14px;
  color: #909399;
  transition: transform 0.2s ease;
  flex-shrink: 0;
  transform: rotate(-90deg);
}

.method-picker-arrow.expanded {
  transform: rotate(0deg);
}

.global-method-picker-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 6px 8px 8px;
  border-top: 1px solid #ebeef5;
}

.method-picker-row {
  padding: 6px 4px;
  border-radius: 3px;
}

.expand-icon {
  font-size: 14px;
  color: #909399;
  transition: transform 0.2s ease;
  flex-shrink: 0;
  transform: rotate(-90deg);
}

.expand-icon.expanded {
  transform: rotate(0deg);
}

/* Bug #428修复: 套餐明细列表样式 */
.package-details-list {
  padding: 6px 10px;
  background: #fffbe6;
  border-top: 1px solid #ffe58f;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.detail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 2px 6px;
  border-radius: 3px;
  font-size: 11px;
  background: #fff;
}

.detail-row:hover {
  background: #fff9e6;
}

.detail-name {
  color: #303133;
  font-weight: 500;
}

.detail-info {
  color: #909399;
  font-size: 10px;
  white-space: nowrap;
}

.selected-card-section {
  padding: 10px;
  border-bottom: 1px solid #ebeef5;
}

.selected-section-title {
  font-size: 12px;
  font-weight: 600;
  color: #409eff;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px dashed #d9ecff;
}

.selected-method-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 0;
}

.selected-method-option .method-checkbox {
  flex: 1;
  min-width: 0;
}

.selected-method-empty {
  color: #c0c4cc;
  font-size: 12px;
}

.package-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px;
  font-size: 12px;
  font-weight: 600;
  color: #909399;
  cursor: pointer;
  border-bottom: 1px dashed #dcdfe6;
  background: #fffbe6;
}

.package-toggle:hover {
  color: #409eff;
}

/* 收起态：仅展示折叠箭头，不显示「套餐明细」等冗余标题 */
.package-toggle-minimal {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 8px 10px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
  cursor: pointer;
  border-bottom: 1px dashed #e4e7ed;
  background: #fafafa;
}

.package-toggle-minimal:hover {
  color: #409eff;
  background: #f5f9ff;
}



.nested-empty-text {
  font-size: 12px;
  color: var(--el-text-color-placeholder);
  padding-left: 2px;
}

.nested-label-row {
  margin-bottom: 6px;
}

.nested-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--el-text-color-secondary);
  letter-spacing: 0.03em;
}



.method-label-inner {
  font-size: 13px;
}

.package-details-loading,
.package-details-empty {
  padding: 12px 10px;
  font-size: 12px;
  color: #909399;
  text-align: center;
}

.package-details-empty {
  color: #c0c4cc;
}

.package-details-list {
  padding: 10px 10px 12px;
}

.package-details-head {
  font-size: 11px;
  font-weight: 600;
  color: #909399;
  letter-spacing: 0.02em;
  margin-bottom: 8px;
  padding-bottom: 6px;
  border-bottom: 1px dashed #dcdfe6;
}

.detail-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px 12px;
  align-items: start;
  padding: 10px 0;
  border-bottom: 1px solid #ebeef5;
}

.detail-row:last-of-type {
  border-bottom: none;
  padding-bottom: 2px;
}

.detail-name {
  font-size: 12px;
  color: #303133;
  line-height: 1.5;
  word-break: break-word;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

.detail-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
  text-align: right;
}

.detail-qty {
  font-size: 11px;
  color: #909399;
  font-variant-numeric: tabular-nums;
}

.detail-price {
  font-size: 12px;
  font-weight: 600;
  color: #e6a23c;
  font-variant-numeric: tabular-nums;
}

/* 折叠组件细节 */
:deep(.el-collapse) {
  border: none;
}
:deep(.el-collapse-item__header) {
  font-size: 13px;
  padding: 6px 0;
  height: auto;
  line-height: 1.5;
}
/* Bug #500修复: 折叠内容使用明确属性过渡，避免 transition: all 导致子元素意外动画 */
:deep(.el-collapse-item__content) {
  padding-bottom: 4px;
  transition: height 0.3s ease, max-height 0.3s ease;
}
/* Bug #500: 折叠面板动画容器，添加 overflow:hidden 防止展开时内容溢出导致闪烁 */
:deep(.el-collapse-item__wrap) {
  border: none;
  overflow: hidden;
}
:deep(.el-collapse-item) {
  transition: margin 0.2s ease;
}
/* Bug #500: 分类加载中提示样式 */
.category-loading-hint {
  color: #909399;
  font-size: 12px;
  text-align: center;
  padding: 8px 0;
}
</style>
