<template>
  <basic-container class="loading-manage-page">
    <div class="loading-manage-page__search">
      <el-form :model="searchForm" label-position="right" label-width="160px">
        <div class="loading-manage-page__search-grid">
          <el-form-item label="配载单号">
            <el-input v-model="searchForm.loadingNo" clearable placeholder="请输入" />
          </el-form-item>
          <el-form-item label="项目名称">
            <el-select
              v-model="searchForm.projectName"
              clearable
              filterable
              remote
              reserve-keyword
              :remote-method="loadProjectOptions"
              :loading="projectLoading"
              placeholder="请输入"
              @visible-change="visible => visible && loadProjectOptions(searchForm.projectName)"
            >
              <el-option
                v-for="item in projectOptions"
                :key="item.id || item.projectName"
                :label="item.projectName"
                :value="item.projectName"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="客户名称">
            <el-select
              v-model="searchForm.customerName"
              clearable
              filterable
              remote
              reserve-keyword
              :remote-method="loadCustomerOptions"
              :loading="customerLoading"
              placeholder="请输入"
              @visible-change="visible => visible && loadCustomerOptions(searchForm.customerName)"
            >
              <el-option
                v-for="item in customerOptions"
                :key="item.id || item.customerName"
                :label="item.customerName"
                :value="item.customerName"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="运输类型">
            <el-select
              v-model="searchForm.transportType"
              clearable
              filterable
              placeholder="请选择"
              @visible-change="visible => visible && loadTransportTypeOptions()"
            >
              <el-option
                v-for="item in transportTypeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>

          <template v-if="searchExpanded">
            <el-form-item label="运单号">
              <el-input v-model="searchForm.waybillNo" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="货物类型">
              <el-select
                v-model="searchForm.cargoType"
                clearable
                filterable
                remote
                reserve-keyword
                :remote-method="loadCargoTypeOptions"
                :loading="cargoTypeLoading"
                placeholder="请输入"
                @visible-change="visible => visible && loadCargoTypeOptions(searchForm.cargoType)"
              >
                <el-option
                  v-for="item in cargoTypeOptions"
                  :key="item.id || item.cargoName || item.cargoType"
                  :label="item.cargoName || item.cargoType || item.label"
                  :value="item.cargoName || item.cargoType || item.label"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="发货地址">
              <el-input v-model="searchForm.departureAddress" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="收货地址">
              <el-input v-model="searchForm.arrivalAddress" clearable placeholder="请输入" />
            </el-form-item>

            <el-form-item label="货物名称">
              <el-input v-model="searchForm.cargoName" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="司机名称">
              <el-select
                v-model="searchForm.driverName"
                clearable
                filterable
                remote
                reserve-keyword
                :remote-method="loadDriverOptions"
                :loading="driverLoading"
                placeholder="请输入"
                @visible-change="visible => visible && loadDriverOptions(searchForm.driverName)"
              >
                <el-option
                  v-for="item in driverOptions"
                  :key="item.id || item.driverName || item.name"
                  :label="item.driverName || item.name"
                  :value="item.driverName || item.name"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="车/船/航班/班列">
              <el-input v-model="searchForm.vehicleNo" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="原始单号">
              <el-input v-model="searchForm.originalNo" clearable placeholder="请输入" />
            </el-form-item>

            <el-form-item label="承运商名称">
              <el-select
                v-model="searchForm.carrierName"
                clearable
                filterable
                remote
                reserve-keyword
                :remote-method="loadCarrierOptions"
                :loading="carrierLoading"
                placeholder="请输入"
                @visible-change="visible => visible && loadCarrierOptions(searchForm.carrierName)"
              >
                <el-option
                  v-for="item in carrierOptions"
                  :key="item.id || item.customerName || item.carrierName"
                  :label="item.customerName || item.carrierName || item.name"
                  :value="item.customerName || item.carrierName || item.name"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="数据来源">
              <el-select v-model="searchForm.dataSource" clearable placeholder="请选择">
                <el-option
                  v-for="item in dataSourceOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="开始日期">
              <el-date-picker
                v-model="searchForm.startDateRange"
                type="daterange"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                start-placeholder="请选择"
                end-placeholder="请选择"
                range-separator="-"
              />
            </el-form-item>
            <el-form-item label="结束日期">
              <el-date-picker
                v-model="searchForm.endDateRange"
                type="daterange"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                start-placeholder="请选择"
                end-placeholder="请选择"
                range-separator="-"
              />
            </el-form-item>
          </template>

          <el-form-item label="状态">
            <el-select v-model="searchForm.businessStatus" clearable placeholder="请选择">
              <el-option
                v-for="item in statusOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="运单批次号">
            <el-input v-model="searchForm.batchNo" clearable placeholder="请输入" />
          </el-form-item>
          <el-form-item label="计划名称">
            <el-select
              v-model="searchForm.planName"
              clearable
              filterable
              remote
              reserve-keyword
              :remote-method="loadPlanOptions"
              :loading="planLoading"
              placeholder="请输入"
              @visible-change="visible => visible && loadPlanOptions(searchForm.planName)"
            >
              <el-option
                v-for="item in planOptions"
                :key="item.id || item.planName"
                :label="item.planName"
                :value="item.planName"
              />
            </el-select>
          </el-form-item>
          <div class="loading-manage-page__search-actions">
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button @click="handleResetSearch">重置</el-button>
            <el-link type="primary" @click="searchExpanded = !searchExpanded">{{ searchExpanded ? '收起筛选' : '展开筛选' }}</el-link>
          </div>
        </div>
      </el-form>
    </div>

    <div class="loading-manage-page__toolbar">
      <div class="loading-manage-page__toolbar-left">
        <el-button type="primary" @click="openLoadingDialog('add')">新建配载</el-button>
        <el-button type="primary" plain @click="handleExport">批量导出</el-button>
        <el-button type="primary" plain @click="handleBatchComplete">批量完成</el-button>
      </div>
      <div class="loading-manage-page__toolbar-right">
        <el-tooltip content="刷新" placement="top">
          <el-button :icon="Refresh" text @click="loadTable" />
        </el-tooltip>
        <el-tooltip content="表格密度" placement="top">
          <el-button :icon="Rank" text @click="toggleTableSize" />
        </el-tooltip>
        <el-tooltip content="列设置" placement="top">
          <el-button :icon="Setting" text @click="handleColumnSetting" />
        </el-tooltip>
      </div>
    </div>

    <el-table
      ref="tableRef"
      v-loading="loading"
      :data="tableData"
      :size="tableSize"
      border
      row-key="id"
      class="loading-manage-page__table"
      @selection-change="selectionChange"
    >
      <el-table-column type="selection" width="52" fixed="left" align="center" />
      <el-table-column type="index" label="序号" width="58" fixed="left" align="center" />
      <el-table-column label="配载单号" prop="loadingNo" min-width="170" fixed="left">
        <template #default="{ row }">
          <el-link
            type="primary"
            class="loading-manage-page__link"
            @click="openLoadingDialog('view', row)"
          >{{ row.loadingNo }}</el-link>
        </template>
      </el-table-column>
      <el-table-column label="配载子单号" prop="loadingSubNos" min-width="220">
        <template #default="{ row }">
          <div class="loading-manage-page__multi-line">
            <el-link
              v-for="item in splitText(row.loadingSubNos)"
              :key="item"
              type="primary"
              class="loading-manage-page__sub-link"
            >{{ item }}</el-link>
          </div>
        </template>
      </el-table-column>
      <el-table-column
        label="车牌号/航班号/船号/班列号"
        prop="vehicleNo"
        min-width="210"
        show-overflow-tooltip
      />
      <el-table-column label="司机" prop="driverName" min-width="120" show-overflow-tooltip />
      <el-table-column label="联系电话" prop="driverPhone" min-width="140" show-overflow-tooltip />
      <el-table-column label="承运类型" prop="carrierType" min-width="120" show-overflow-tooltip />
      <el-table-column
        label="发货地"
        prop="departureAddress"
        min-width="180"
        show-overflow-tooltip
      />
      <el-table-column label="途经地" prop="transitAddress" min-width="190" show-overflow-tooltip />
      <el-table-column label="到货地" prop="arrivalAddress" min-width="180" show-overflow-tooltip />
      <el-table-column label="承运商" prop="carrierName" min-width="160" show-overflow-tooltip />
      <el-table-column
        label="运输类型"
        prop="transportType"
        min-width="150"
        show-overflow-tooltip
      />
      <el-table-column label="数据来源" prop="dataSource" min-width="130" show-overflow-tooltip />
      <el-table-column label="创建时间" prop="createTime" min-width="170" show-overflow-tooltip  sortable/>
      <el-table-column label="更新时间" prop="updateTime" min-width="170" show-overflow-tooltip  sortable/>
      <el-table-column
        label="过程节点"
        prop="currentProcessNode"
        min-width="130"
        show-overflow-tooltip
      />
      <el-table-column label="状态" prop="businessStatus" width="110" fixed="right" align="center">
        <template #default="{ row }">
          <span :class="['loading-manage-page__status', `is-${row.businessStatus || 'unknown'}`]">
            {{ statusText(row) }}
          </span>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="320" fixed="right" align="left">
        <template #default="{ row }">
          <div class="loading-manage-page__actions">
            <el-link
              v-for="action in rowActions(row)"
              :key="action.type"
              type="primary"
              @click="handleRowAction(action.type, row)"
            >{{ action.label }}</el-link>
          </div>
        </template>
      </el-table-column>
    </el-table>

    <div class="loading-manage-page__pagination">
      <el-pagination
        v-model:current-page="page.currentPage"
        v-model:page-size="page.pageSize"
        background
        :page-sizes="page.pageSizes"
        layout="total, sizes, prev, pager, next, jumper"
        :total="page.total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>

    <el-dialog
      v-model="dialogVisible"
      :title="dialogTitle"
      append-to-body
      destroy-on-close
      width="96%"
      top="3vh"
      class="loading-manage-dialog"
      @closed="resetLoadingDialog"
    >
      <div v-loading="dialogLoading" class="loading-manage-dialog__body">
        <el-form
          ref="loadingFormRef"
          :model="dialogForm"
          :disabled="dialogReadonly"
          label-position="right"
          label-width="auto"
          class="loading-manage-dialog__form"
        >
          <section-card title="配载基本信息">
            <div class="loading-manage-dialog__grid">
            <el-form-item label="配载单号">
              <el-input v-model="dialogForm.loadingNo" disabled placeholder="系统自动生成" />
            </el-form-item>
            <el-form-item label="运输类型" required>
              <el-select
                v-model="dialogForm.transportType"
                filterable
                clearable
                placeholder="请选择"
                @visible-change="visible => visible && loadTransportTypeOptions()"
              >
                <el-option
                  v-for="item in transportTypeOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="项目名称">
              <el-input v-model="dialogForm.projectName" readonly placeholder="从待配载运单带出" />
            </el-form-item>
            <el-form-item label="客户名称">
              <el-input v-model="dialogForm.customerName" readonly placeholder="从待配载运单带出" />
            </el-form-item>
            <el-form-item label="原始单号">
              <el-input v-model="dialogForm.originalNo" readonly placeholder="从待配载运单带出" />
            </el-form-item>
            <el-form-item label="运单批次号">
              <el-input v-model="dialogForm.batchNo" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="数据来源">
              <el-select v-model="dialogForm.dataSource" clearable placeholder="请选择">
                <el-option
                  v-for="item in dataSourceOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="计划名称">
              <el-select
                v-model="dialogForm.planName"
                clearable
                filterable
                remote
                reserve-keyword
                :remote-method="loadPlanOptions"
                :loading="planLoading"
                placeholder="请输入"
                @visible-change="visible => visible && loadPlanOptions(dialogForm.planName)"
              >
                <el-option
                  v-for="item in planOptions"
                  :key="item.id || item.planName"
                  :label="item.planName"
                  :value="item.planName"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="开始日期">
              <el-date-picker
                v-model="dialogForm.startDate"
                type="date"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                placeholder="请选择"
              />
            </el-form-item>
            <el-form-item label="结束日期">
              <el-date-picker
                v-model="dialogForm.endDate"
                type="date"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                placeholder="请选择"
              />
            </el-form-item>
            <el-form-item label="配载子单号" class="loading-manage-dialog__span-2">
              <el-input
                v-model="dialogForm.loadingSubNos"
                readonly
                type="textarea"
                :rows="2"
                placeholder="添加待配载运单后自动生成"
              />
            </el-form-item>
          </div>
          </section-card>

          <section-card title="筛选待配载运单">
            <template #extra>
              <el-link v-if="!dialogReadonly" type="primary" @click="loadCandidateWaybills">筛选</el-link>
            </template>
            <div class="loading-manage-dialog__candidate-search" v-if="candidateSearchVisible">
            <el-row :gutter="16">
              <el-col :span="6">
                <el-form-item label="运单号">
                  <el-input v-model="candidateQuery.waybillNo" clearable placeholder="请输入" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="项目名称">
                  <el-select
                    v-model="candidateQuery.projectName"
                    clearable
                    filterable
                    remote
                    reserve-keyword
                    :remote-method="loadProjectOptions"
                    :loading="projectLoading"
                    placeholder="请输入"
                    @visible-change="
                      visible => visible && loadProjectOptions(candidateQuery.projectName)
                    "
                  >
                    <el-option
                      v-for="item in projectOptions"
                      :key="item.id || item.projectName"
                      :label="item.projectName"
                      :value="item.projectName"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="发货地址">
                  <el-input
                    v-model="candidateQuery.departureAddress"
                    clearable
                    placeholder="请输入"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="货物名称">
                  <el-input v-model="candidateQuery.cargoName" clearable placeholder="请输入" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="收货地址">
                  <el-input
                    v-model="candidateQuery.arrivalAddress"
                    clearable
                    placeholder="请输入"
                  />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="客户名称">
                  <el-select
                    v-model="candidateQuery.customerName"
                    clearable
                    filterable
                    remote
                    reserve-keyword
                    :remote-method="loadCustomerOptions"
                    :loading="customerLoading"
                    placeholder="请输入"
                    @visible-change="
                      visible => visible && loadCustomerOptions(candidateQuery.customerName)
                    "
                  >
                    <el-option
                      v-for="item in customerOptions"
                      :key="item.id || item.customerName"
                      :label="item.customerName"
                      :value="item.customerName"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="货物类型">
                  <el-select
                    v-model="candidateQuery.cargoType"
                    clearable
                    filterable
                    remote
                    reserve-keyword
                    :remote-method="loadCargoTypeOptions"
                    :loading="cargoTypeLoading"
                    placeholder="请输入"
                    @visible-change="
                      visible => visible && loadCargoTypeOptions(candidateQuery.cargoType)
                    "
                  >
                    <el-option
                      v-for="item in cargoTypeOptions"
                      :key="item.id || item.cargoName || item.cargoType"
                      :label="item.cargoName || item.cargoType || item.label"
                      :value="item.cargoName || item.cargoType || item.label"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="原始单号">
                  <el-input v-model="candidateQuery.originalNo" clearable placeholder="请输入" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="车/船/航班/班列">
                  <el-input v-model="candidateQuery.vehicleNo" clearable placeholder="请输入" />
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="承运商名称">
                  <el-select
                    v-model="candidateQuery.carrierName"
                    clearable
                    filterable
                    remote
                    reserve-keyword
                    :remote-method="loadCarrierOptions"
                    :loading="carrierLoading"
                    placeholder="请输入"
                    @visible-change="
                      visible => visible && loadCarrierOptions(candidateQuery.carrierName)
                    "
                  >
                    <el-option
                      v-for="item in carrierOptions"
                      :key="item.id || item.customerName || item.carrierName"
                      :label="item.customerName || item.carrierName || item.name"
                      :value="item.customerName || item.carrierName || item.name"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="司机">
                  <el-select
                    v-model="candidateQuery.driverName"
                    clearable
                    filterable
                    remote
                    reserve-keyword
                    :remote-method="loadDriverOptions"
                    :loading="driverLoading"
                    placeholder="请输入"
                    @visible-change="
                      visible => visible && loadDriverOptions(candidateQuery.driverName)
                    "
                  >
                    <el-option
                      v-for="item in driverOptions"
                      :key="item.id || item.driverName || item.name"
                      :label="item.driverName || item.name"
                      :value="item.driverName || item.name"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="6">
                <el-form-item label="运输类型">
                  <el-select
                    v-model="candidateQuery.transportType"
                    clearable
                    filterable
                    placeholder="请选择"
                    @visible-change="visible => visible && loadTransportTypeOptions()"
                  >
                    <el-option
                      v-for="item in transportTypeOptions"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :span="24" class="loading-manage-dialog__candidate-actions">
                <el-button type="primary" @click="handleCandidateSearch">查询</el-button>
                <el-button @click="handleCandidateReset">重置</el-button>
                <el-link type="primary" @click="candidateSearchVisible = false"
                  >收起</el-link>
              </el-col>
            </el-row>
          </div>
          <div class="loading-manage-dialog__selected-summary">
            <span>已选择 {{ selectedWaybillRows.length }} 条运单</span>
          </div>
          <el-table
            ref="candidateTableRef"
            v-loading="candidateLoading"
            :data="candidateRows"
            border
            height="260"
            row-key="id"
            @selection-change="candidateSelectionChange"
          >
            <el-table-column type="selection" width="52" fixed="left" align="center" />
            <el-table-column type="index" label="序号" width="60" align="center" />
            <el-table-column
              prop="waybillNo"
              label="运单号"
              min-width="150"
              show-overflow-tooltip
            />
            <el-table-column
              prop="projectName"
              label="项目名称"
              min-width="160"
              show-overflow-tooltip
            />
            <el-table-column
              prop="customerName"
              label="客户名称"
              min-width="160"
              show-overflow-tooltip
            />
            <el-table-column
              prop="transportType"
              label="运输类型"
              min-width="130"
              show-overflow-tooltip
            />
            <el-table-column
              prop="cargoName"
              label="货物名称"
              min-width="140"
              show-overflow-tooltip
            />
            <el-table-column
              prop="cargoType"
              label="货物类型"
              min-width="140"
              show-overflow-tooltip
            />
            <el-table-column
              prop="departureAddress"
              label="发货地址"
              min-width="220"
              show-overflow-tooltip
            />
            <el-table-column
              prop="arrivalAddress"
              label="收货地址"
              min-width="220"
              show-overflow-tooltip
            />
            <el-table-column
              prop="vehicleNo"
              label="车/船/航班/班列"
              min-width="160"
              show-overflow-tooltip
            />
            <el-table-column
              prop="carrierName"
              label="承运商名称"
              min-width="160"
              show-overflow-tooltip
            />
            <el-table-column prop="driverName" label="司机" min-width="120" show-overflow-tooltip />
            <el-table-column
              prop="originalNo"
              label="原始单号"
              min-width="130"
              show-overflow-tooltip
            />
          </el-table>
          <div class="loading-manage-dialog__pagination">
            <el-pagination
              v-model:current-page="candidatePage.currentPage"
              v-model:page-size="candidatePage.pageSize"
              :page-sizes="candidatePage.pageSizes"
              layout="total, prev, pager, next, sizes"
              :total="candidatePage.total"
              @size-change="handleCandidateSizeChange"
              @current-change="handleCandidateCurrentChange"
            />
          </div>
          </section-card>

          <section-card title="待配载列表">
            <el-table
              :data="selectedWaybillRows"
              border
              class="loading-manage-dialog__selected-table"
            >
            <el-table-column type="index" label="序号" width="70" align="center" />
            <el-table-column prop="waybillNo" label="运单号" min-width="150">
              <template #default="{ row }">
                <el-link type="primary">{{ row.waybillNo }}</el-link>
              </template>
            </el-table-column>
            <el-table-column prop="projectName" label="项目名称" min-width="160" />
            <el-table-column
              prop="departureAddress"
              label="发货地"
              min-width="220"
              show-overflow-tooltip
            />
            <el-table-column
              prop="arrivalAddress"
              label="到货地"
              min-width="220"
              show-overflow-tooltip
            />
            <el-table-column label="操作" width="110" fixed="right">
              <template #default="{ $index }">
                <el-link
                  v-if="!dialogReadonly"
                  type="primary"
                  @click="removeSelectedWaybill($index)"
                >移除</el-link>
              </template>
            </el-table-column>
            </el-table>
          </section-card>

          <section-card title="路线信息">
            <div class="loading-manage-dialog__route-list" v-if="routeNodes.length">
            <div
              v-for="(node, index) in routeNodes"
              :key="node.key"
              class="loading-manage-dialog__route-item"
              draggable="true"
              @dragstart="handleRouteDragStart(index)"
              @dragover.prevent
              @drop="handleRouteDrop(index)"
            >
              <el-icon class="loading-manage-dialog__route-handle"><Rank /></el-icon>
              <span class="loading-manage-dialog__route-type">{{ routeTypeText(index) }}</span>
              <span class="loading-manage-dialog__route-address">{{ node.address }}</span>
              <span class="loading-manage-dialog__route-tags">
                <el-tag v-for="tag in node.tags" :key="tag" size="small">{{ tag }}</el-tag>
              </span>
            </div>
            </div>
            <el-empty v-else description="添加待配载运单后自动生成路线" :image-size="72" />
          </section-card>

          <section-card title="货物信息">
            <el-table :data="cargoRows" border class="loading-manage-dialog__cargo-table">
            <el-table-column type="index" label="序号" width="70" align="center" fixed="left" />
            <el-table-column prop="projectName" label="项目名称" min-width="150" />
            <el-table-column prop="cargoName" label="货物名称" min-width="140" />
            <el-table-column prop="cargoType" label="货物类型" min-width="140" />
            <el-table-column prop="packageType" label="包装" min-width="100" />
            <el-table-column prop="weight" label="重量（吨）" min-width="120" />
            <el-table-column prop="volume" label="体积（方）" min-width="120" />
            <el-table-column prop="quantity" label="数量" min-width="100" />
            <el-table-column prop="planDate" label="计划日期" min-width="130"  sortable/>
            <el-table-column prop="unitPrice" label="货物单价（元）" min-width="150" />
            <el-table-column prop="materialCode" label="物料编码" min-width="130" />
            <el-table-column prop="equipmentCode" label="设备编码" min-width="130" />
            <el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip />
            </el-table>
          </section-card>

          <section-card title="任务信息">
            <div class="loading-manage-dialog__carrier-tabs">
            <el-segmented
              v-model="dialogForm.carrierType"
              :options="carrierTypeOptions"
              :disabled="dialogReadonly"
              @change="handleCarrierTypeChange"
            />
          </div>
          <div class="loading-manage-dialog__grid">
            <el-form-item v-if="dialogForm.carrierType !== '自运'" label="承运商" required>
              <el-select
                v-model="dialogForm.carrierName"
                clearable
                filterable
                remote
                reserve-keyword
                :remote-method="loadCarrierOptions"
                :loading="carrierLoading"
                placeholder="请输入"
                @visible-change="visible => visible && loadCarrierOptions(dialogForm.carrierName)"
              >
                <el-option
                  v-for="item in carrierOptions"
                  :key="item.id || item.customerName || item.carrierName"
                  :label="item.customerName || item.carrierName || item.name"
                  :value="item.customerName || item.carrierName || item.name"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="司机" :required="dialogForm.carrierType === '自运'">
              <el-select
                v-model="dialogForm.driverName"
                clearable
                filterable
                allow-create
                default-first-option
                remote
                reserve-keyword
                :remote-method="loadDriverOptions"
                :loading="driverLoading"
                placeholder="请输入"
                @change="handleDriverChange"
                @visible-change="visible => visible && loadDriverOptions(dialogForm.driverName)"
              >
                <el-option
                  v-for="item in driverOptions"
                  :key="item.id || item.driverName || item.name"
                  :label="item.driverName || item.name"
                  :value="item.driverName || item.name"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="手机号" :required="dialogForm.carrierType === '自运'">
              <el-input v-model="dialogForm.driverPhone" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="车牌号" required>
              <el-input v-model="dialogForm.vehicleNo" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="挂车车牌号">
              <el-input v-model="dialogForm.trailerVehicleNo" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="押运人">
              <el-input v-model="dialogForm.escortName" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="押运人手机号">
              <el-input v-model="dialogForm.escortPhone" clearable placeholder="请输入" />
            </el-form-item>
            <el-form-item label="里程(km)">
              <el-input
                v-model="dialogForm.mileage"
                clearable
                placeholder="请输入"
                @input="handleMileageInput"
              />
            </el-form-item>
            <el-form-item label="预计发货日期">
              <el-date-picker
                v-model="dialogForm.estimatedStartDate"
                type="date"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                placeholder="请选择"
              />
            </el-form-item>
            <el-form-item label="预计完成日期">
              <el-date-picker
                v-model="dialogForm.estimatedEndDate"
                type="date"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                placeholder="请选择"
              />
            </el-form-item>
            <el-form-item label="备注" class="loading-manage-dialog__span-2">
              <el-input
                v-model="dialogForm.taskRemark"
                type="textarea"
                :rows="3"
                maxlength="500"
                show-word-limit
                placeholder="请输入，500字以内"
              />
            </el-form-item>
          </div>
          </section-card>
        </el-form>
      </div>

      <template #footer>
        <div class="loading-manage-dialog__footer">
          <template v-if="dialogReadonly">
            <el-button @click="dialogVisible = false">关闭</el-button>
          </template>
          <template v-else>
            <el-button @click="clearLoadingDialog">清空</el-button>
            <el-button type="primary" plain :loading="dialogSaving === 'draft'" @click="saveDraft">
              暂存
            </el-button>
            <el-button type="primary" :loading="dialogSaving === 'submit'" @click="submitLoading">
              {{ dialogMode === 'reassign' ? '确认派单' : '确认' }}
            </el-button>
          </template>
        </div>
      </template>
    </el-dialog>
  </basic-container>
</template>

<script>
import request from '@/axios';
import { exportBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import * as loadingApi from '@/api/business/loading-manage';
import { getList as getProjectList } from '@/api/business/project-apply';
import { getList as getPlanList } from '@/api/business/transport-plan';
import {
  getList as getWaybillList,
  getDetail as getWaybillDetail,
} from '@/api/business/waybill-manage';
import { getParentOptions as getCargoTypeOptions } from '@/api/base/cargo-type';
import { getList as getCustomerList } from '@/api/vehicle/customer-archive';
import { getList as getDriverList } from '@/api/transportCapacity/driver';
import {
  carrierTypeOptions,
  loadingManageConfig,
  loadingStatusMap,
  loadingStatusOptions,
} from '@/option/business/loading-manage';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Rank, Refresh, Setting } from '@element-plus/icons-vue';
import dayjs from 'dayjs';

const defaultTransportType = '公路整车';
const defaultCandidateTransportType = '公路运输';

const createSearchForm = () => ({
  loadingNo: '',
  projectName: '',
  customerName: '',
  transportType: defaultTransportType,
  waybillNo: '',
  cargoType: '',
  departureAddress: '',
  arrivalAddress: '',
  cargoName: '',
  driverName: '',
  vehicleNo: '',
  originalNo: '',
  carrierName: '',
  dataSource: '',
  startDateRange: [],
  endDateRange: [],
  businessStatus: '',
  planName: '',
  batchNo: '',
});

const createCandidateSearchForm = () => ({
  waybillNo: '',
  projectName: '',
  departureAddress: '',
  cargoName: '',
  arrivalAddress: '',
  customerName: '',
  cargoType: '',
  originalNo: '',
  vehicleNo: '',
  carrierName: '',
  driverName: '',
  transportType: defaultCandidateTransportType,
});

const createDialogForm = () => ({
  id: '',
  loadingNo: '',
  loadingSubNos: '',
  waybillIdsJson: '',
  projectName: '',
  customerName: '',
  transportType: '',
  cargoType: '',
  cargoName: '',
  vehicleNo: '',
  trailerVehicleNo: '',
  driverName: '',
  driverPhone: '',
  carrierType: '承运商',
  carrierName: '',
  escortName: '',
  escortPhone: '',
  departureAddress: '',
  transitAddress: '',
  arrivalAddress: '',
  originalNo: '',
  dataSource: '手工创建',
  startDate: '',
  endDate: '',
  planName: '',
  batchNo: '',
  currentProcessNode: '接单',
  mileage: '',
  estimatedStartDate: dayjs().format('YYYY-MM-DD'),
  estimatedEndDate: '',
  taskRemark: '',
  goodsJson: '',
  routeJson: '',
  taskInfoJson: '',
  businessStatus: 'draft',
});

const unwrapRecords = res => {
  const data = res?.data || res;
  if (Array.isArray(data)) return data;
  if (Array.isArray(data?.records)) return data.records;
  if (Array.isArray(data?.data)) return data.data;
  if (Array.isArray(data?.data?.records)) return data.data.records;
  return [];
};

const unwrapPage = res => {
  const data = res?.data?.data || res?.data || res;
  return {
    records: data?.records || [],
    total: Number(data?.total || 0),
  };
};

const parseJsonArray = value => {
  if (Array.isArray(value)) return value;
  if (typeof value !== 'string' || !value.trim()) return [];
  try {
    const result = JSON.parse(value);
    if (Array.isArray(result)) return result;
    if (Array.isArray(result.records)) return result.records;
    if (Array.isArray(result.rows)) return result.rows;
    return [];
  } catch (error) {
    return [];
  }
};

const uniqueText = (rows, prop) =>
  [
    ...new Set(
      rows
        .map(row => row?.[prop])
        .filter(value => value !== undefined && value !== null && value !== '')
    ),
  ].join('、');

export default {
  components: {
    Rank,
  },
  data() {
    return {
      Rank,
      Refresh,
      Setting,
      loading: false,
      tableSize: 'default',
      tableData: [],
      page: {
        currentPage: 1,
        pageSize: 10,
        total: 0,
        pageSizes: [10, 20, 50, 100],
      },
      searchExpanded: true,
      searchForm: createSearchForm(),
      selectionRows: [],
      dialogVisible: false,
      dialogMode: 'add',
      dialogLoading: false,
      dialogSaving: '',
      dialogForm: createDialogForm(),
      candidateSearchVisible: true,
      candidateQuery: createCandidateSearchForm(),
      candidateLoading: false,
      candidateRows: [],
      candidateSelection: [],
      candidatePage: {
        currentPage: 1,
        pageSize: 10,
        total: 0,
        pageSizes: [10, 20, 50, 100],
      },
      selectedWaybillRows: [],
      routeNodes: [],
      cargoRows: [],
      routeDragIndex: -1,
      transportTypeOptions: [],
      projectOptions: [],
      customerOptions: [],
      cargoTypeOptions: [],
      driverOptions: [],
      carrierOptions: [],
      planOptions: [],
      projectLoading: false,
      customerLoading: false,
      cargoTypeLoading: false,
      driverLoading: false,
      carrierLoading: false,
      planLoading: false,
      carrierTypeOptions,
      statusOptions: loadingStatusOptions,
      dataSourceOptions: loadingManageConfig.dataSourceOptions,
      config: loadingManageConfig,
    };
  },
  computed: {
    dialogReadonly() {
      return this.dialogMode === 'view';
    },
    dialogTitle() {
      const titleMap = {
        add: '新建配载',
        edit: '编辑配载单',
        view: '配载单详情',
        copy: '复制配载单',
        reassign: '重新派单',
      };
      return titleMap[this.dialogMode] || '配载管理';
    },
  },
  mounted() {
    this.loadTransportTypeOptions();
    this.loadTable();
  },
  methods: {
    buildQueryParams(form) {
      const params = { ...form };
      const [startDateStart, startDateEnd] = params.startDateRange || [];
      const [endDateStart, endDateEnd] = params.endDateRange || [];
      delete params.startDateRange;
      delete params.endDateRange;
      return {
        ...params,
        startDateStart,
        startDateEnd,
        endDateStart,
        endDateEnd,
      };
    },
    async loadTable() {
      this.loading = true;
      try {
        const res = await loadingApi.getList(
          this.page.currentPage,
          this.page.pageSize,
          this.buildQueryParams(this.searchForm)
        );
        const page = unwrapPage(res);
        this.tableData = page.records;
        this.page.total = page.total;
      } finally {
        this.loading = false;
      }
    },
    handleSearch() {
      this.page.currentPage = 1;
      this.loadTable();
    },
    handleResetSearch() {
      this.searchForm = createSearchForm();
      this.page.currentPage = 1;
      this.loadTable();
    },
    handleSizeChange(size) {
      this.page.currentPage = 1;
      this.page.pageSize = size;
      this.loadTable();
    },
    handleCurrentChange(current) {
      this.page.currentPage = current;
      this.loadTable();
    },
    selectionChange(rows) {
      this.selectionRows = rows || [];
    },
    toggleTableSize() {
      const order = ['default', 'small', 'large'];
      const index = order.indexOf(this.tableSize);
      this.tableSize = order[(index + 1) % order.length];
    },
    handleColumnSetting() {
      ElMessage.info('列设置按原型保留入口，当前默认展示全部列表字段');
    },
    statusText(row) {
      return row.businessStatusName || loadingStatusMap[row.businessStatus] || '未知';
    },
    splitText(value) {
      if (!value) return [];
      return String(value)
        .split(/[\n,，]+/)
        .map(item => item.trim())
        .filter(Boolean);
    },
    rowActions(row) {
      const status = row.businessStatus;
      if (status === 'draft') {
        return [
          { type: 'edit', label: '编辑' },
          { type: 'delete', label: '删除' },
          { type: 'copy', label: '复制' },
        ];
      }
      if (status === 'pending') {
        return [
          { type: 'view', label: '详情' },
          { type: 'reassign', label: '重新派单' },
          { type: 'edit', label: '编辑' },
          { type: 'copy', label: '复制' },
          { type: 'cancel', label: '取消' },
        ];
      }
      if (status === 'running') {
        return [
          { type: 'view', label: '详情' },
          { type: 'copy', label: '复制' },
          { type: 'complete', label: '完成' },
        ];
      }
      if (status === 'completed' || status === 'cancelled') {
        return [
          { type: 'view', label: '详情' },
          { type: 'copy', label: '复制' },
        ];
      }
      return [{ type: 'view', label: '详情' }];
    },
    handleRowAction(type, row) {
      const actionMap = {
        view: () => this.openLoadingDialog('view', row),
        edit: () => this.openLoadingDialog('edit', row),
        reassign: () => this.openLoadingDialog('reassign', row),
        copy: () => this.copyLoading(row),
        delete: () => this.deleteLoading(row),
        cancel: () => this.cancelLoading(row),
        complete: () => this.completeLoading(row),
      };
      actionMap[type]?.();
    },
    async openLoadingDialog(mode, row) {
      this.dialogMode = mode;
      this.dialogVisible = true;
      this.dialogLoading = true;
      this.resetDialogData();
      try {
        if (row?.id) {
          const res = await loadingApi.getDetail(row.id);
          this.dialogForm = {
            ...createDialogForm(),
            ...(res.data?.data || res.data || {}),
          };
          await this.restoreWaybillRows(
            this.dialogForm.waybillIdsJson,
            this.dialogForm.loadingSubNos
          );
          this.restoreRouteAndCargo();
          await this.loadCandidateWaybills();
        } else {
          this.dialogForm = createDialogForm();
          this.candidateQuery = createCandidateSearchForm();
          await this.loadCandidateWaybills();
        }
      } finally {
        this.dialogLoading = false;
      }
    },
    resetLoadingDialog() {
      this.resetDialogData();
      this.dialogSaving = '';
      this.dialogLoading = false;
    },
    resetDialogData() {
      this.dialogForm = createDialogForm();
      this.candidateQuery = createCandidateSearchForm();
      this.candidateRows = [];
      this.candidateSelection = [];
      this.selectedWaybillRows = [];
      this.routeNodes = [];
      this.cargoRows = [];
      this.candidatePage.currentPage = 1;
      this.candidatePage.total = 0;
      this.candidateSearchVisible = true;
    },
    clearLoadingDialog() {
      this.resetDialogData();
      this.loadCandidateWaybills();
    },
    restoreRouteAndCargo() {
      const routeRows = parseJsonArray(this.dialogForm.routeJson);
      const cargoRows = parseJsonArray(this.dialogForm.goodsJson);
      this.routeNodes = routeRows.length
        ? routeRows
        : this.buildRouteNodes(this.selectedWaybillRows);
      this.cargoRows = cargoRows.length ? cargoRows : this.buildCargoRows(this.selectedWaybillRows);
    },
    async restoreWaybillRows(idsJson, loadingSubNos) {
      const ids = parseJsonArray(idsJson).filter(Boolean);
      if (ids.length) {
        const rows = await Promise.all(
          ids.map(id =>
            getWaybillDetail(id)
              .then(res => res.data?.data || res.data)
              .catch(() => null)
          )
        );
        this.selectedWaybillRows = rows.filter(Boolean);
        this.rebuildSummaryFromWaybills(false);
        return;
      }
      this.selectedWaybillRows = this.splitText(loadingSubNos).map(waybillNo => ({ waybillNo }));
      this.rebuildSummaryFromWaybills(false);
    },
    async loadCandidateWaybills() {
      this.candidateLoading = true;
      try {
        const res = await getWaybillList(
          this.candidatePage.currentPage,
          this.candidatePage.pageSize,
          {
            ...this.buildQueryParams(this.candidateQuery),
            businessStatus: 'pending',
            onlyUnassignedLoading: 1,
          }
        );
        const page = unwrapPage(res);
        this.candidateRows = page.records;
        this.candidatePage.total = page.total;
      } finally {
        this.candidateLoading = false;
      }
    },
    handleCandidateSearch() {
      this.candidatePage.currentPage = 1;
      this.loadCandidateWaybills();
    },
    handleCandidateReset() {
      this.candidateQuery = createCandidateSearchForm();
      this.candidatePage.currentPage = 1;
      this.loadCandidateWaybills();
    },
    handleCandidateSizeChange(size) {
      this.candidatePage.currentPage = 1;
      this.candidatePage.pageSize = size;
      this.loadCandidateWaybills();
    },
    handleCandidateCurrentChange(current) {
      this.candidatePage.currentPage = current;
      this.loadCandidateWaybills();
    },
    candidateSelectionChange(rows) {
      this.candidateSelection = rows || [];
    },
    addSelectedWaybills() {
      const exists = new Set(this.selectedWaybillRows.map(row => String(row.id || row.waybillNo)));
      const nextRows = [...this.selectedWaybillRows];
      this.candidateSelection.forEach(row => {
        const key = String(row.id || row.waybillNo);
        if (!exists.has(key)) {
          nextRows.push(row);
          exists.add(key);
        }
      });
      this.selectedWaybillRows = nextRows;
      this.rebuildSummaryFromWaybills();
      this.$refs.candidateTableRef?.clearSelection?.();
      this.candidateSelection = [];
    },
    removeSelectedWaybill(index) {
      this.selectedWaybillRows.splice(index, 1);
      this.rebuildSummaryFromWaybills();
    },
    rebuildSummaryFromWaybills(rebuildRoute = true) {
      const rows = this.selectedWaybillRows;
      this.dialogForm.loadingSubNos = rows
        .map(row => row.waybillNo)
        .filter(Boolean)
        .join('\n');
      this.dialogForm.waybillIdsJson = JSON.stringify(rows.map(row => row.id).filter(Boolean));
      this.dialogForm.projectName = uniqueText(rows, 'projectName');
      this.dialogForm.customerName = uniqueText(rows, 'customerName');
      this.dialogForm.originalNo = uniqueText(rows, 'originalNo');
      this.dialogForm.cargoType = uniqueText(rows, 'cargoType');
      this.dialogForm.cargoName = uniqueText(rows, 'cargoName');
      if (!this.dialogForm.transportType) {
        this.dialogForm.transportType = rows.find(row => row.transportType)?.transportType || '';
      }
      if (!this.dialogForm.carrierName) {
        this.dialogForm.carrierName = rows.find(row => row.carrierName)?.carrierName || '';
      }
      if (!this.dialogForm.driverName) {
        this.dialogForm.driverName = rows.find(row => row.driverName)?.driverName || '';
      }
      if (!this.dialogForm.driverPhone) {
        this.dialogForm.driverPhone = rows.find(row => row.driverPhone)?.driverPhone || '';
      }
      if (!this.dialogForm.vehicleNo) {
        this.dialogForm.vehicleNo = rows.find(row => row.vehicleNo)?.vehicleNo || '';
      }
      if (rebuildRoute) {
        this.routeNodes = this.buildRouteNodes(rows);
      }
      this.cargoRows = this.buildCargoRows(rows);
      this.syncRouteAddressFields();
    },
    buildRouteNodes(rows) {
      const nodeMap = new Map();
      rows.forEach((row, rowIndex) => {
        const departure = row.departureAddress || row.departureName;
        const arrival = row.arrivalAddress || row.arrivalName;
        if (departure) {
          if (!nodeMap.has(departure)) nodeMap.set(departure, { address: departure, tags: [] });
          nodeMap.get(departure).tags.push(`装${rowIndex + 1}`);
        }
        if (arrival) {
          if (!nodeMap.has(arrival)) nodeMap.set(arrival, { address: arrival, tags: [] });
          nodeMap.get(arrival).tags.push(`卸${rowIndex + 1}`);
        }
      });
      return [...nodeMap.values()].map((node, index) => ({
        ...node,
        key: `${node.address}-${index}`,
      }));
    },
    routeTypeText(index) {
      if (index === 0) return '起';
      if (index === this.routeNodes.length - 1) return '终';
      return '经';
    },
    handleRouteDragStart(index) {
      this.routeDragIndex = index;
    },
    handleRouteDrop(index) {
      if (this.routeDragIndex < 0 || this.routeDragIndex === index) return;
      const rows = [...this.routeNodes];
      const [target] = rows.splice(this.routeDragIndex, 1);
      rows.splice(index, 0, target);
      this.routeNodes = rows;
      this.routeDragIndex = -1;
      this.syncRouteAddressFields();
    },
    syncRouteAddressFields() {
      const nodes = this.routeNodes.filter(item => item.address);
      this.dialogForm.departureAddress = nodes[0]?.address || '';
      this.dialogForm.arrivalAddress = nodes[nodes.length - 1]?.address || '';
      this.dialogForm.transitAddress = nodes
        .slice(1, -1)
        .map(item => item.address)
        .join('，');
    },
    buildCargoRows(rows) {
      return rows.flatMap(row => {
        const goodsRows = parseJsonArray(row.goodsJson);
        if (goodsRows.length) {
          return goodsRows.map(item => this.normalizeCargoRow(row, item));
        }
        return [this.normalizeCargoRow(row, row)];
      });
    },
    normalizeCargoRow(waybill, item = {}) {
      return {
        projectName: item.projectName || waybill.projectName || '',
        cargoName: item.cargoName || item.goodsName || waybill.cargoName || '',
        cargoType: item.cargoType || item.goodsType || waybill.cargoType || '',
        packageType: item.packageType || item.package || '',
        weight: item.weight || item.cargoWeight || '',
        volume: item.volume || item.cargoVolume || '',
        quantity: item.quantity || item.cargoQuantity || waybill.quantity || '',
        planDate: item.planDate || waybill.startDate || '',
        unitPrice: item.unitPrice || waybill.unitPrice || '',
        materialCode: item.materialCode || '',
        equipmentCode: item.equipmentCode || '',
        remark: item.remark || '',
      };
    },
    normalizePayload() {
      this.syncRouteAddressFields();
      this.rebuildSummaryFromWaybills(false);
      return {
        ...this.dialogForm,
        routeJson: JSON.stringify(this.routeNodes),
        goodsJson: JSON.stringify(this.cargoRows),
        taskInfoJson: JSON.stringify({
          carrierType: this.dialogForm.carrierType,
          carrierName: this.dialogForm.carrierName,
          driverName: this.dialogForm.driverName,
          driverPhone: this.dialogForm.driverPhone,
          vehicleNo: this.dialogForm.vehicleNo,
          trailerVehicleNo: this.dialogForm.trailerVehicleNo,
          escortName: this.dialogForm.escortName,
          escortPhone: this.dialogForm.escortPhone,
          mileage: this.dialogForm.mileage,
          estimatedStartDate: this.dialogForm.estimatedStartDate,
          estimatedEndDate: this.dialogForm.estimatedEndDate,
          taskRemark: this.dialogForm.taskRemark,
        }),
      };
    },
    validatePayload(draftMode = false) {
      if (!this.selectedWaybillRows.length) {
        ElMessage.warning('请选择待配载运单');
        return false;
      }
      if (!this.dialogForm.transportType) {
        ElMessage.warning('请选择运输类型');
        return false;
      }
      if (draftMode) {
        return true;
      }
      if (!this.dialogForm.departureAddress || !this.dialogForm.arrivalAddress) {
        ElMessage.warning('请确认配载路线');
        return false;
      }
      if (!this.dialogForm.carrierType) {
        ElMessage.warning('请选择承运类型');
        return false;
      }
      if (!this.dialogForm.vehicleNo) {
        ElMessage.warning('请输入车牌号');
        return false;
      }
      if (this.dialogForm.carrierType === '自运') {
        if (!this.dialogForm.driverName || !this.dialogForm.driverPhone) {
          ElMessage.warning('请输入司机和司机手机号');
          return false;
        }
      } else if (!this.dialogForm.carrierName) {
        ElMessage.warning('请选择承运商');
        return false;
      }
      return true;
    },
    async saveDraft() {
      if (!this.validatePayload(true)) return;
      this.dialogSaving = 'draft';
      try {
        const res = await loadingApi.saveDraft(this.normalizePayload());
        this.dialogForm = {
          ...this.dialogForm,
          ...(res.data?.data || res.data || {}),
        };
        ElMessage.success('暂存成功');
        this.loadTable();
      } finally {
        this.dialogSaving = '';
      }
    },
    async submitLoading() {
      if (!this.validatePayload(false)) return;
      this.dialogSaving = 'submit';
      try {
        const payload = this.normalizePayload();
        if (this.dialogMode === 'reassign') {
          await loadingApi.reassign(payload);
          ElMessage.success('派单成功');
        } else {
          await loadingApi.submit(payload);
          ElMessage.success('确认成功');
        }
        this.dialogVisible = false;
        this.loadTable();
      } finally {
        this.dialogSaving = '';
      }
    },
    async copyLoading(row) {
      await loadingApi.copy(row.id);
      ElMessage.success('复制成功');
      this.loadTable();
    },
    deleteLoading(row) {
      ElMessageBox.confirm(`确定删除配载单 ${row.loadingNo}？`, '提示', { type: 'warning' })
        .then(async () => {
          const res = await loadingApi.remove(row.id);
          const result = res.data?.data || {};
          ElMessage.success(`删除成功 ${result.successCount || 0} 条`);
          this.loadTable();
        })
        .catch(() => {});
    },
    cancelLoading(row) {
      ElMessageBox.confirm(`确定取消配载单 ${row.loadingNo}？`, '提示', { type: 'warning' })
        .then(async () => {
          await loadingApi.cancel(row.id);
          ElMessage.success('取消成功');
          this.loadTable();
        })
        .catch(() => {});
    },
    completeLoading(row) {
      ElMessageBox.confirm(`确定完成配载单 ${row.loadingNo}？`, '提示', { type: 'warning' })
        .then(async () => {
          await loadingApi.complete(row.id);
          ElMessage.success('完成成功');
          this.loadTable();
        })
        .catch(() => {});
    },
    handleBatchComplete() {
      if (!this.selectionRows.length) {
        ElMessage.warning('请选择需要批量完成的配载单');
        return;
      }
      ElMessageBox.confirm('确定对选中的配载单执行批量完成？', '提示', { type: 'warning' })
        .then(async () => {
          const ids = this.selectionRows.map(row => row.id).join(',');
          const res = await loadingApi.batchComplete(ids);
          const result = res.data?.data || {};
          ElMessage.success(
            `批量完成成功 ${result.successCount || 0} 条，跳过 ${result.skippedCount || 0} 条`
          );
          this.loadTable();
        })
        .catch(() => {});
    },
    handleExport() {
      const ids = this.selectionRows.map(row => row.id).join(',');
      exportBlob(
        loadingApi.exportUrl,
        {
          ...this.buildQueryParams(this.searchForm),
          ids,
        },
        {
          feedback: true,
        }
      ).then(res => {
        downloadXls(res.data, `配载管理${dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
      });
    },
    handleCarrierTypeChange() {
      if (this.dialogForm.carrierType === '自运') {
        this.dialogForm.carrierName = '';
      }
    },
    handleDriverChange(value) {
      const driver = this.driverOptions.find(item => (item.driverName || item.name) === value);
      if (driver && !this.dialogForm.driverPhone) {
        this.dialogForm.driverPhone = driver.mobile || driver.driverPhone || driver.phone || '';
      }
    },
    handleMileageInput(value) {
      this.dialogForm.mileage = String(value || '').replace(/[^\d.]/g, '');
    },
    async loadTransportTypeOptions() {
      if (this.transportTypeOptions.length) return;
      const res = await request({
        url: '/blade-system/dict-biz/dictionary',
        method: 'get',
        params: { code: 'transport_type' },
      });
      const records = unwrapRecords(res);
      this.transportTypeOptions = records.map(item => ({
        label: item.dictValue || item.label || item.name,
        value: item.dictKey || item.value || item.dictValue || item.name,
      }));
      if (!this.transportTypeOptions.length) {
        this.transportTypeOptions = [{ label: defaultTransportType, value: defaultTransportType }];
      }
    },
    async loadProjectOptions(keyword = '') {
      this.projectLoading = true;
      try {
        this.projectOptions = unwrapRecords(await getProjectList(1, 20, { projectName: keyword }));
      } finally {
        this.projectLoading = false;
      }
    },
    async loadCustomerOptions(keyword = '') {
      this.customerLoading = true;
      try {
        this.customerOptions = unwrapRecords(
          await getCustomerList(1, 20, { customerName: keyword })
        );
      } finally {
        this.customerLoading = false;
      }
    },
    async loadCargoTypeOptions(keyword = '') {
      this.cargoTypeLoading = true;
      try {
        this.cargoTypeOptions = unwrapRecords(await getCargoTypeOptions(keyword));
      } finally {
        this.cargoTypeLoading = false;
      }
    },
    async loadDriverOptions(keyword = '') {
      this.driverLoading = true;
      try {
        this.driverOptions = unwrapRecords(await getDriverList(1, 20, { driverName: keyword }));
      } finally {
        this.driverLoading = false;
      }
    },
    async loadCarrierOptions(keyword = '') {
      this.carrierLoading = true;
      try {
        this.carrierOptions = unwrapRecords(
          await getCustomerList(1, 20, { customerName: keyword })
        );
      } finally {
        this.carrierLoading = false;
      }
    },
    async loadPlanOptions(keyword = '') {
      this.planLoading = true;
      try {
        this.planOptions = unwrapRecords(await getPlanList(1, 20, { planName: keyword }));
      } finally {
        this.planLoading = false;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.loading-manage-page {
  .loading-manage-page__search {
    padding: 12px 12px 4px;
    margin-bottom: 8px;
    background: #fff;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  }

  .loading-manage-page__search-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 8px 24px;
  }

  .loading-manage-page__search-actions {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    min-height: 32px;
  }

  .loading-manage-page__toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: 12px 0;
  }

  .loading-manage-page__toolbar-left,
  .loading-manage-page__toolbar-right {
    display: flex;
    align-items: center;
    gap: 12px;
  }

  .loading-manage-page__table {
    width: 100%;
  }

  .loading-manage-page__link,
  .loading-manage-page__sub-link {
    padding: 0;
    min-height: auto;
  }

  .loading-manage-page__multi-line {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1.6;
  }

  .loading-manage-page__status {
    color: #303133;
  }

  .loading-manage-page__status.is-running {
    color: #1dbf00;
  }

  .loading-manage-page__status.is-cancelled {
    color: #909399;
  }

  .loading-manage-page__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 12px;
  }

  .loading-manage-page__actions .el-button {
    margin-left: 0;
    padding: 0;
  }

  .loading-manage-page__pagination {
    display: flex;
    justify-content: flex-end;
    padding: 12px 0 0;
    background: #fff;
  }

  :deep(.el-form-item) {
    margin-bottom: 8px;
  }

  :deep(.el-form-item__label) {
    white-space: nowrap;
  }

  :deep(.el-input),
  :deep(.el-select),
  :deep(.el-date-editor.el-input),
  :deep(.el-date-editor.el-input__wrapper),
  :deep(.el-date-editor--daterange) {
    width: 100%;
  }

  :deep(.el-table) {
    --el-table-border-color: #eff1f7;
    --el-table-row-hover-bg-color: #f5f7fa;
  }

  :deep(.el-table__body tr:nth-child(even) > td) {
    background: #fafafa;
  }
}

.loading-manage-dialog {
  .loading-manage-dialog__body {
    max-height: 78vh;
    overflow-y: auto;
    padding-right: 4px;
  }

  .loading-manage-dialog__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 24px;
  }

  .loading-manage-dialog__span-2 {
    grid-column: span 2;
  }

  .loading-manage-dialog__title-action {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .loading-manage-dialog__candidate-search {
    padding: 4px 0;
    margin-bottom: 8px;
  }

  .loading-manage-dialog__candidate-actions,
  .loading-manage-dialog__collapsed-search,
  .loading-manage-dialog__table-toolbar,
  .loading-manage-dialog__pagination,
  .loading-manage-dialog__footer {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
  }

  .loading-manage-dialog__table-toolbar {
    justify-content: space-between;
    margin: 10px 0;
  }

  .loading-manage-dialog__pagination {
    padding: 10px 0 4px;
  }

  .loading-manage-dialog__route-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }

  .loading-manage-dialog__route-item {
    display: grid;
    grid-template-columns: 28px 36px minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
    min-height: 44px;
    padding: 8px 12px;
    border: 1px solid #eff1f7;
    background: #fff;
    cursor: move;
  }

  .loading-manage-dialog__route-handle {
    color: #909399;
  }

  .loading-manage-dialog__route-type {
    width: 28px;
    height: 28px;
    line-height: 28px;
    text-align: center;
    border-radius: 50%;
    color: #fff;
    background: #409eff;
  }

  .loading-manage-dialog__route-address {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .loading-manage-dialog__route-tags {
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 6px;
  }

  .loading-manage-dialog__carrier-tabs {
    margin-bottom: 12px;
  }

  :deep(.dialog-section-title) {
    display: flex;
    align-items: center;
    margin: 16px 0 12px;
    font-weight: 600;
    color: #303133;
  }

  :deep(.dialog-section-title)::before {
    content: '';
    width: 4px;
    height: 16px;
    margin-right: 8px;
    background: #409eff;
  }

  :deep(.el-form-item) {
    margin-bottom: 16px;
  }

  :deep(.el-form-item__label) {
    text-align: right;
    white-space: nowrap;
  }

  :deep(.el-input),
  :deep(.el-select),
  :deep(.el-date-editor.el-input),
  :deep(.el-date-editor.el-input__wrapper) {
    width: 100%;
  }

  :deep(.el-table) {
    --el-table-border-color: #eff1f7;
  }
}
</style>
