<template>
  <div class="app-container pre-shipment-page">
    <!-- 上半区 -->
    <div class="section section-top">
      <el-card class="section-card">
        <div class="card-body">
          <el-tabs v-model="activeTab" type="border-card" class="fill-tabs">
            <el-tab-pane label="手工分配" name="manual">
              <div class="tab-pane-body">
                <el-form
                  :model="manualQuery"
                  size="small"
                  label-width="110px"
                  class="manual-query-form"
                >
                  <el-row :gutter="12">
                    <el-col :span="6">
                      <el-form-item label="生产日期" prop="productionDate">
                        <el-date-picker
                          v-model="manualQuery.productionDate"
                          type="date"
                          value-format="yyyy-MM-dd"
                          placeholder="请选择生产日期"
                          style="width: 100%"
                        />
                      </el-form-item>
                    </el-col>
                    <el-col :span="6">
                      <el-form-item label="发货日期" prop="shipDate">
                        <el-date-picker
                          v-model="manualQuery.shipDate"
                          type="date"
                          value-format="yyyy-MM-dd"
                          placeholder="请选择发货日期"
                          style="width: 100%"
                        />
                      </el-form-item>
                    </el-col>
                    <el-col :span="6">
                      <el-form-item label="品种" prop="variety">
                        <el-select
                          v-model="manualQuery.variety"
                          placeholder="请选择品种"
                          clearable
                          filterable
                          style="width: 100%"
                        >
                          <el-option
                            v-for="item in varietyList"
                            :key="item.varietyNo"
                            :value="item.varietyNo"
                            :label="item.varietyName"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="6">
                      <el-form-item label="级别" prop="level">
                        <el-select
                          v-model="manualQuery.level"
                          placeholder="请选择级别"
                          clearable
                          filterable
                          style="width: 100%"
                        >
                          <el-option
                            v-for="item in levelList"
                            :key="item.levelNo"
                            :value="item.levelNo"
                            :label="item.levelName"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                  </el-row>

                  <el-row :gutter="12">
                    <el-col :span="6">
                      <el-form-item label="动物标识" prop="animalTag">
                        <el-input
                          v-model="manualQuery.animalTag"
                          placeholder="请输入动物标识"
                          clearable
                        />
                      </el-form-item>
                    </el-col>
                    <el-col :span="6">
                      <el-form-item label="批次" prop="batch">
                        <el-input
                          v-model="manualQuery.batch"
                          placeholder="请输入批次"
                          clearable
                        />
                      </el-form-item>
                    </el-col>
                    <el-col :span="6">
                      <el-form-item label="白条编号" prop="whiteNo">
                        <el-input
                          v-model="manualQuery.whiteNo"
                          placeholder="请输入白条编号"
                          clearable
                        />
                      </el-form-item>
                    </el-col>
                    <el-col :span="6">
                      <el-form-item
                        label="销售扣水分%"
                        prop="salesMoistureDeduction"
                      >
                        <decimal-input
                          v-model="manualQuery.salesMoistureDeduction"
                          :min="0"
                          :max="100"
                          :precision="2"
                          placeholder="请输入扣水分%"
                        />
                      </el-form-item>
                    </el-col>
                  </el-row>

                  <el-row :gutter="12">
                    <el-col :offset="1" :span="2">
                      <el-form-item label-width="0" prop="enableSort">
                        <el-checkbox v-model="manualQuery.enableSort"
                          >启动排序</el-checkbox
                        >
                      </el-form-item>
                    </el-col>
                    <el-col :span="18">
                      <el-button
                        type="primary"
                        icon="el-icon-search"
                        size="mini"
                        @click="handleManualQuery"
                        >查询</el-button
                      >
                    </el-col>
                  </el-row>
                </el-form>
              </div>
            </el-tab-pane>

            <el-tab-pane label="白条排序设定" name="sort">
              <div class="tab-pane-body">
                <el-form
                  :model="sortForm"
                  size="small"
                  label-width="88px"
                  class="sort-form"
                >
                  <el-row :gutter="12">
                    <el-col :span="8">
                      <el-form-item label="排序1" prop="sort1">
                        <el-select
                          v-model="sortForm.sort1"
                          placeholder="请选择"
                          style="width: 100%"
                        >
                          <el-option
                            v-for="opt in sortOptions"
                            :key="opt.value"
                            :label="opt.label"
                            :value="opt.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="8">
                      <el-form-item label="排序2" prop="sort2">
                        <el-select
                          v-model="sortForm.sort2"
                          placeholder="请选择"
                          style="width: 100%"
                        >
                          <el-option
                            v-for="opt in sortOptions"
                            :key="opt.value"
                            :label="opt.label"
                            :value="opt.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="8">
                      <el-form-item label="排序3" prop="sort3">
                        <el-select
                          v-model="sortForm.sort3"
                          placeholder="请选择"
                          style="width: 100%"
                        >
                          <el-option
                            v-for="opt in sortOptions"
                            :key="opt.value"
                            :label="opt.label"
                            :value="opt.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="8">
                      <el-form-item label="排序4" prop="sort4">
                        <el-select
                          v-model="sortForm.sort4"
                          placeholder="请选择"
                          style="width: 100%"
                        >
                          <el-option
                            v-for="opt in sortOptions"
                            :key="opt.value"
                            :label="opt.label"
                            :value="opt.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                    <el-col :span="8">
                      <el-form-item label="排序5" prop="sort5">
                        <el-select
                          v-model="sortForm.sort5"
                          placeholder="请选择"
                          style="width: 100%"
                        >
                          <el-option
                            v-for="opt in sortOptions"
                            :key="opt.value"
                            :label="opt.label"
                            :value="opt.value"
                          />
                        </el-select>
                      </el-form-item>
                    </el-col>
                  </el-row>
                </el-form>
              </div>
            </el-tab-pane>
          </el-tabs>
        </div>
      </el-card>
    </div>

    <!-- 下半区 -->
    <div class="section section-bottom">
      <el-card class="section-card">
        <div class="card-body">
          <el-row :gutter="16" class="bottom-row">
            <el-col :span="8" class="bottom-col">
              <el-card class="inner-card" shadow="never">
                <div class="inner-card-body">
                  <div class="card-title">可分配白条明细</div>
                  <el-table
                    ref="availableWhiteTable"
                    border
                    stripe
                    highlight-current-row
                    height="calc(100% - 32px)"
                    :data="availableWhiteList"
                    @row-click="handleAvailableWhiteRowClick"
                    @selection-change="handleAvailableWhiteSelectionChange"
                    style="width: 100%;"
                  >
                    <!-- 字段与 allocation/index.vue 保持一致（接口返回什么就展示什么） -->
                    <el-table-column label="白条编号" prop="whiteStripNumber" min-width="140" show-overflow-tooltip />
                   <el-table-column label="品种" prop="varietyName" min-width="100" >
                  <template slot-scope="scope">
                    <span>{{ getVarietyLabel(scope.row.variety) }}</span>
                  </template>
                </el-table-column>
                <el-table-column label="级别" prop="grade" min-width="90" >
                  <template slot-scope="scope">
                    <span>{{ getLevelLabel(scope.row.grade) }}</span>
                  </template>
                </el-table-column>
                <el-table-column label="重量" prop="currentWeightKg" min-width="90" />
                <el-table-column label="锁定物流线" prop="lockedLogisticsLine" min-width="120" />
                <el-table-column label="扣分" prop="qualityDeduction" min-width="80" />
                <el-table-column label="动物标识" prop="animalIdentification" min-width="120" />
                <el-table-column label="物料名称" prop="goodsName" min-width="140" >
                  <template slot-scope="scope">
                    <span>{{ scope.row.goodsName || getGoodsNameByNum(scope.row.goodsNum) }}</span>
                  </template>
                </el-table-column>
                  </el-table>
                </div>
              </el-card>
            </el-col>
            <el-col :span="4" class="bottom-col">
              <el-card class="inner-card" shadow="never">
                <template #header>
                   <div class="card-toolbar">
                    <el-button type="primary" plain icon="el-icon-refresh" size="mini" @click="refreshMiddle">刷新</el-button>
                  </div>
                </template>
                <div class="inner-card-body">
                  <!-- 树状区域：与 allocation/index.vue 一样，用于切换线路/市场/客户维度 -->
                  <el-tree
                    ref="allocationOrderTree"
                    style="margin-top: 8px; height: calc(100% - 32px); overflow: auto;"
                    :data="allocationOrderTreeData"
                    :props="allocationTreeProps"
                    node-key="id"
                    highlight-current
                    default-expand-all
                    :expand-on-click-node="false"
                    :render-content="renderAllocationTreeNode"
                    @node-click="handleAllocationTreeNodeClick"
                  />
                </div>
              </el-card>
            </el-col>
            <el-col :span="12" class="bottom-col">
              <el-card class="inner-card" shadow="never">
                <div class="inner-card-body right-panel">
                  <!-- 1) 批量发货按钮 -->
                  <div class="panel-section panel-section-0">
                    <el-button type="primary" plain icon="el-icon-truck" size="mini" @click="handleBatchShip">批量发货</el-button>
                  </div>

                  <!-- 2) 订单信息汇总（同 allocation） -->
                  <div class="panel-section panel-section-1">
                    <div class="card-title">订单信息汇总</div>
                    <el-table
                      ref="orderSummaryTable"
                      border
                      stripe
                      highlight-current-row
                      height="calc(100% - 28px)"
                      :data="orderSummaryList"
                      @row-click="handleOrderSummaryRowClick"
                      @selection-change="handleOrderSummarySelectionChange"
                      style="width: 100%;"
                    >
                      <!-- 字段与 allocation/index.vue 保持一致 -->
                      <el-table-column label="发货客户" prop="customer_name" min-width="140" show-overflow-tooltip />
                      <el-table-column label="白条数" prop="ass_num" min-width="90" />
                      <el-table-column label="订单未分配数量" prop="orderUnassignedQty" min-width="140" />
                      <el-table-column label="品种" prop="variety_name" min-width="100" show-overflow-tooltip />
                      <el-table-column label="级别" prop="goods_level" min-width="90" show-overflow-tooltip />
                      <el-table-column label="动物标识" prop="animalTag" min-width="120" show-overflow-tooltip />
                      <el-table-column label="物料名称" prop="goods_name" min-width="140" show-overflow-tooltip />
                      <el-table-column label="备注" prop="remark" min-width="160" />
                    </el-table>
                  </div>

                  <!-- 3) 分配结果（同 allocation） -->
                  <div class="panel-section panel-section-2">
                    <div class="card-title">分配结果</div>
                    <el-table
                      ref="allocationResultTable"
                      border
                      stripe
                      highlight-current-row
                      height="calc(100% - 28px)"
                      :data="allocationResultList"
                      @row-click="handleAllocationResultRowClick"
                      style="width: 100%;"
                    >
                      <!-- 以下 prop 与后端 list 返回字段一致；若字段名不同请只改 prop -->
                          <el-table-column label="市场" prop="market" min-width="120" show-overflow-tooltip >
                            <template slot-scope="scope">
                              <span>{{ getBazaarLabel(scope.row.market) }}</span>
                            </template>
                          </el-table-column>
                          <el-table-column label="客户" prop="customerName" min-width="140" show-overflow-tooltip >
                            <template slot-scope="scope">
                              <span>{{getCustomerLabel(scope.row.customer) }}</span>
                            </template>
                          </el-table-column>
                          <el-table-column label="白条编号" prop="whiteStripNumber" min-width="140" show-overflow-tooltip />
                          <el-table-column label="品种" prop="variety" min-width="100" show-overflow-tooltip >
                            <template slot-scope="scope">
                              <span>{{ getVarietyLabel(scope.row.variety) }}</span>
                            </template>
                          </el-table-column>
                          <el-table-column label="级别" prop="grade" min-width="90" show-overflow-tooltip >
                            <template slot-scope="scope">
                              <span>{{ getLevelLabel(scope.row.grade) }}</span>
                            </template>
                          </el-table-column>
                          <el-table-column label="毛色" prop="coatColor" min-width="90" show-overflow-tooltip >
                            <template slot-scope="scope">
                              <span>{{ getCoatLabel(scope.row.coatColor) }}</span>
                            </template>
                          </el-table-column>
                          <el-table-column label="重量" prop="weight" min-width="90" />
                          <el-table-column label="扣分" prop="deductionScore" min-width="80" />
                          <el-table-column label="完成分配" prop="completionStatus" min-width="100" >
                            <template slot-scope="scope">
                              <span>{{ scope.row.completionStatus === 1 ? 'Y' : 'N' }}</span>
                            </template>
                          </el-table-column>
                          <el-table-column label="生猪批次" prop="pigBatch" min-width="120" />
                          <el-table-column label="物料名称" prop="materialName" min-width="140" show-overflow-tooltip >
                            <template slot-scope="scope">
                              <span>{{ getGoodsNameByNum(scope.row.materialCode) }}</span>
                            </template>
                          </el-table-column>
                          <el-table-column label="物料编码" prop="materialCode" min-width="120" show-overflow-tooltip />
                    </el-table>
                  </div>

                  <!-- 4) 按钮组 -->
                  <div class="panel-section panel-section-3">
                    <div class="btn-row">
                      <el-input
                        v-model="whiteNoKeyword"
                        placeholder="白条编号"
                        size="mini"
                        style="width: 300px;"
                        clearable
                      >
                        <template slot="prepend">白条编号</template>
                      </el-input>
                      <el-button size="mini" type="primary" plain icon="el-icon-location" @click="handleLocateWhiteNo">定位</el-button>
                      <el-button size="mini" type="primary" plain @click="handleLock">锁定</el-button>
                      <el-button size="mini" type="warning" plain @click="handleUnlock">解锁</el-button>
                      <el-button size="mini" type="success" plain @click="handleFinishAlloc">完成分配</el-button>
                      <el-button size="mini" type="primary" plain @click="handleLockLine">锁定物流线</el-button>
                    </div>
                  </div>
                </div>
              </el-card>
            </el-col>
          </el-row>
        </div>
      </el-card>
    </div>
  </div>
</template>

<script>
import { getVarietyList } from "@/api/baseInfo/variety";
import { getLevelList } from "@/api/baseInfo/level";
import { getAllocationWhiteList } from "@/api/production/convention";
import { getMaterialList } from "@/api/baseInfo/material";
import { getLineMarketCustomerStats, getSaleOrderGoodsDetailList } from "@/api/sale/saleOrder";
import { addAllocation, editAllocationStatus, delAllocation, getAllocationList, addAllocationBatch } from "@/api/production/allocation";
import { formatDateYMS, getFindByKey } from "@/utils";
import { getClienteleList } from "@/api/sale/clientele";
import { getCoatList } from "@/api/baseInfo/coat";
import { getBazaarList } from "@/api/baseInfo/bazaar";

export default {
  name: "ProductionPreShipment",
  data() {
    return {
      activeTab: "manual",
      varietyList: [],
      levelList: [],
      materialList: [],
      coatList: [],
      bazaarList: [],
      customerList: [],
      availableWhiteList: [],
      availableWhiteSelection: [],
      orderSummaryList: [],
      orderSummarySelection: [],
      allocationOrderTreeData: [],
      selectedAllocationTreeNode: null,
      allocationTreeProps: {
        children: "children",
        label: "label",
      },
      selectedOrderSummaryKey: null,
      selectedOrderSummaryRow: null,
      allocationResultAllList: [],
      allocationResultList: [],
      allocationResultSeq: 0,
      allocationLocked: false,
      whiteNoKeyword: null,
      manualQuery: {
        productionDate: null,
        shipDate: null,
        variety: null,
        level: null,
        animalTag: null,
        batch: null,
        whiteNo: null,
        enableSort: false,
        salesMoistureDeduction: null,
      },
      sortOptions: [
        { label: "无", value: "none" },
        { label: "品种", value: "variety" },
        { label: "重量", value: "weight" },
        { label: "级别", value: "level" },
        { label: "编号", value: "code" },
        { label: "毛色", value: "coat" },
      ],
      sortForm: {
        sort1: "none",
        sort2: "none",
        sort3: "none",
        sort4: "none",
        sort5: "none",
      },
    };
  },
  created() {
    const tomorrow = formatDateYMS(Date.now() + 1000 * 60 * 60 * 24);
    this.manualQuery.productionDate = tomorrow;
    this.manualQuery.shipDate = tomorrow;
    this.getVariety();
    this.getLevel();
    this.getMaterial();
    this.getCoat();
    this.getBazaar();
    this.getCustomer();
    this.fetchAllocationOrderTree();
    this.handleManualQuery();
  },
  mounted() {
    window.addEventListener("keydown", this.onAllocationKeydown, true);
  },
  beforeDestroy() {
    window.removeEventListener("keydown", this.onAllocationKeydown, true);
  },
  methods: {
    getCoat() {
      getCoatList({}).then((res) => {
        this.coatList = res.data || [];
      });
    },
    getBazaar() {
      getBazaarList({}).then((res) => {
        this.bazaarList = res.data || [];
      });
    },
    getCustomer() {
      getClienteleList({}).then((res) => {
        this.customerList = res.data || [];
      });
    },
    getCoatLabel(val) {
      const item = getFindByKey(this.coatList, val, 'coatNum')
      return item ? item.coatName : (val ?? '-')
    },
    getBazaarLabel(val) {
      const item = getFindByKey(this.bazaarList, val, 'marketNum')
      return item ? item.marketName : (val ?? '-')
    },
    getCustomerLabel(val) {
      const item = getFindByKey(this.customerList, val, 'customerNum')
      return item ? item.customerName : (val ?? '-')
    },
    /**
     * 树节点显示文案：label + (goodsCount)
     * @param {Object} node
     * @returns {string}
     */
    getAllocationTreeNodeLabel(node) {
      const label = node && node.label != null ? String(node.label) : "-";
      const cnt =
        node && node.goodsCount != null && node.goodsCount !== "" ? Number(node.goodsCount) : null;
      if (cnt == null || Number.isNaN(cnt)) return label;
      return `${label} (${cnt})`;
    },
    /**
     * 自定义树节点渲染：保持 allocation 同样的显示效果
     * @param {Object} h
     * @param {Object} ctx
     */
    renderAllocationTreeNode(h, ctx) {
      const data = ctx && ctx.data ? ctx.data : null;
      return h("span", [this.getAllocationTreeNodeLabel(data)]);
    },
    /**
     * 前序遍历，取第一个带 id 的节点（与树自上而下展示顺序一致）
     * @param {Array} nodes
     * @returns {Object|null}
     */
    findFirstTreeNodeWithId(nodes) {
      if (!nodes || !nodes.length) return null;
      for (let i = 0; i < nodes.length; i++) {
        const n = nodes[i];
        if (!n) continue;
        if (n.id != null) return n;
        if (n.children && n.children.length) {
          const hit = this.findFirstTreeNodeWithId(n.children);
          if (hit) return hit;
        }
      }
      return null;
    },
    /**
     * 加载树：线路/市场/客户
     * @returns {Promise<void>}
     */
    fetchAllocationOrderTree() {
      const params = { saleDate: this.manualQuery.productionDate };
      return getLineMarketCustomerStats(params).then((res) => {
        this.allocationOrderTreeData = (res && res.data) || [];
        this.$nextTick(() => {
          const first = this.findFirstTreeNodeWithId(this.allocationOrderTreeData);
          if (first) this.handleAllocationTreeNodeClick(first);
        });
      });
    },
    /**
     * 查询「可分配白条明细」
     * 字段与 allocation/index.vue 保持一致：直接使用接口返回，不做重命名/加工
     * @returns {Promise<void>}
     */
    handleManualQuery() {
      const params = {
        productionDate: this.manualQuery.productionDate,
        shipDate: this.manualQuery.shipDate,
        variety: this.manualQuery.variety,
        level: this.manualQuery.level,
        animalTag: this.manualQuery.animalTag,
        batch: this.manualQuery.batch,
        whiteNo: this.manualQuery.whiteNo,
        enableSort: this.manualQuery.enableSort,
      };
      return getAllocationWhiteList(params).then((res) => {
        this.availableWhiteList = (res && res.data) || [];
      });
    },
    refreshMiddle() {
      /** 中间刷新：树 + 三块数据（白条明细 / 订单汇总 / 分配结果） */
      return this.fetchAllocationOrderTree().then(() => {
        const params = this.buildOrderSummaryQueryParams();
        return Promise.all([
          this.handleManualQuery(),
          this.fetchOrderSummaryList(params),
        ]);
      });
    },
    handleAvailableWhiteSelectionChange(val) {
      this.availableWhiteSelection = val || [];
    },
    /**
     * 可分配白条明细：点击行高亮
     * @param {Object} row
     */
    handleAvailableWhiteRowClick(row) {
      if (this.$refs.availableWhiteTable) {
        this.$refs.availableWhiteTable.setCurrentRow(row);
      }
    },
    handleOrderSummarySelectionChange(val) {
      this.orderSummarySelection = val || [];
    },
    /**
     * 订单信息汇总：点击行高亮 + 联动分配结果过滤
     * @param {Object} row
     */
    handleOrderSummaryRowClick(row) {
      if (this.$refs.orderSummaryTable) {
        this.$refs.orderSummaryTable.setCurrentRow(row);
      }
      this.selectedOrderSummaryRow = row || null;
      this.selectedOrderSummaryKey = row && row._osKey != null ? row._osKey : null;
      this.syncAllocationResultList();
      this.fetchAllocationResultAllList();
    },
    /**
     * 分配结果：点击行高亮
     * @param {Object} row
     */
    handleAllocationResultRowClick(row) {
      if (this.$refs.allocationResultTable) {
        this.$refs.allocationResultTable.setCurrentRow(row);
      }
    },
    handleBatchShip() {
      /** 预留：批量发货（当前页只先对齐 allocation 的数据与分配逻辑） */
      if(!this.selectedOrderSummaryRow){
        this.$message.warning("请先选中订单信息汇总");
        return;
      }
      this.$modal.confirm("确定要批量发货吗？").then(() => {
        
      })
      .catch(() => {});
    },
    handleLocateWhiteNo() {
      /** 预留：按白条编号定位（需要后端字段确认后再实现滚动/高亮） */
    },
    handleLock() {
      /** 锁定：禁止分配相关快捷操作（预留） */
      this.allocationLocked = true;
    },
    handleUnlock() {
      /** 解锁：恢复快捷操作（预留） */
      this.allocationLocked = false;
    },
    handleFinishAlloc() {
      /** 完成分配：调用与 allocation 一致的状态接口 */
      if (this.allocationResultList.length <= 0) {
        this.$message.warning("没有可分配的白条");
        return;
      }
      this.$modal.confirm("确定要完成分配吗？").then(() => {
        const params = {
          ids: this.allocationResultList
            .map((r) => r.id ?? r.allocationId)
            .filter((v) => v != null && v !== "")
            .join(","),
        };
        editAllocationStatus(params)
          .then(() => {
            this.$message.success("完成分配成功");
            this.handleManualQuery();
            this.fetchAllocationResultAllList();
          })
          .catch(() => {});
      });
    },
    handleLockLine() {
      /** 预留：锁定物流线 */
    },
    /**
     * 读取 Element 表格当前高亮行
     * @param {string} refName
     * @returns {Object|null}
     */
    getTableCurrentRow(refName) {
      const t = this.$refs[refName];
      if (!t || !t.store || !t.store.states) return null;
      return t.store.states.currentRow;
    },
    /**
     * 键盘左右键：未锁定时，右键将选中白条 + 选中订单行移入分配结果；左键从分配结果移回
     * @param {KeyboardEvent} e
     */
    onAllocationKeydown(e) {
      if (this.allocationLocked) return;
      if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") return;
      const tag = (e.target && e.target.tagName) || "";
      if (["INPUT", "TEXTAREA", "SELECT"].includes(tag)) return;
      if (e.key === "ArrowRight") {
        const ok = this.moveWhiteStripToAllocationResult();
        if (ok) e.preventDefault();
        return;
      }
      if (e.key === "ArrowLeft") {
        const ok = this.moveWhiteStripFromAllocationResult();
        if (ok) e.preventDefault();
      }
    },
    /**
     * 右键：白条 + 订单汇总有当前行时调 addAllocation；成功后刷新三块区域数据
     * @returns {boolean}
     */
    moveWhiteStripToAllocationResult() {
      const blRow = this.getTableCurrentRow("availableWhiteTable");
      const osRow = this.getTableCurrentRow("orderSummaryTable");
      if (!blRow || !osRow) {
        this.$message.warning("请先在「可分配白条明细」与「订单信息汇总」中各选中一行");
        return false;
      }
      const qty = Number(osRow.orderUnassignedQty);
      if (!Number.isNaN(qty) && qty <= 0) {
        this.$message.warning("该订单行未分配数量已为 0，无法继续分配");
        return false;
      }
      const payload = {
        productionDate: this.manualQuery.productionDate,
        deliveryDate: this.manualQuery.shipDate,
        regularId: blRow.id,
        variety: blRow.variety,
        grade: blRow.grade,
        animalIdentification: blRow.animalIdentification,
        batchNumber: blRow.batch,
        whiteStripNumber: blRow.whiteStripNumber,
        weight: blRow.currentWeightKg,
        deductionScore: blRow.qualityDeduction,
        materialCode: blRow.goodsNum,
        pigBatch: blRow.pigBatch,
        coatColor: blRow.coatColor,
        deliveryCustomer: osRow.customer_num,
        lockedLogisticsLine: osRow.line_num,
        market: osRow.market_num,
        customer: osRow.customer_num,
        saleNum: osRow.order_num,
        saleId: osRow.id,
      };
      addAllocation(payload)
        .then((res) => {
          if (res && res.code !== 200) {
            this.$message.error(res.msg || "分配失败");
            return Promise.reject(new Error("BIZ_FAIL"));
          }
          this.$message.success("分配成功");
          const params = this.buildOrderSummaryQueryParams();
          return Promise.all([
            this.handleManualQuery(),
            this.fetchOrderSummaryList(params),
          ]);
        })
        .then(() => {
          this.$nextTick(() => {
            if (this.$refs.availableWhiteTable) {
              this.$refs.availableWhiteTable.setCurrentRow(this.availableWhiteList[0] || null);
            }
            if (this.$refs.allocationResultTable) {
              this.$refs.allocationResultTable.setCurrentRow(this.allocationResultList[0] || null);
            }
          });
        })
        .catch((err) => {
          if (!err || err.message !== "BIZ_FAIL") this.$message.error("分配失败");
        });
      return true;
    },
    /**
     * 左键：取消分配（调用 delAllocation）；成功后刷新三块区域数据
     * @returns {boolean}
     */
    moveWhiteStripFromAllocationResult() {
      const arRow = this.getTableCurrentRow("allocationResultTable");
      if (!arRow) {
        this.$message.warning("请先在「分配结果」中选中一行");
        return false;
      }
      const allocId = arRow._allocId != null ? arRow._allocId : (arRow.id ?? arRow.allocationId);
      if (allocId == null || String(allocId).indexOf("tmp-") === 0) return false;
      delAllocation({ ids: allocId })
        .then((res) => {
          if (res && res.code !== 200) {
            this.$message.error(res.msg || "取消分配失败");
            return Promise.reject(new Error("BIZ_FAIL"));
          }
          this.$message.success("已取消分配");
          const params = this.buildOrderSummaryQueryParams();
          return Promise.all([
            this.handleManualQuery(),
            this.fetchOrderSummaryList(params),
          ]);
        })
        .then(() => {
          this.$nextTick(() => {
            if (this.$refs.allocationResultTable) {
              this.$refs.allocationResultTable.setCurrentRow(this.allocationResultList[0] || null);
            }
          });
        })
        .catch((err) => {
          if (!err || err.message !== "BIZ_FAIL") this.$message.error("取消分配失败");
        });
      return true;
    },
    /** 获取物料列表：用于 goodsNum -> goodsName 兜底展示 */
    getMaterial() {
      getMaterialList({}).then((res) => {
        this.materialList = (res && res.data) || [];
      });
    },
    /** 根据 goodsNum 反查物料名称（表格展示兜底用） */
    getGoodsNameByNum(goodsNum) {
      const key = goodsNum == null ? "" : String(goodsNum).trim();
      if (!key) return "-";
      const item = getFindByKey(this.materialList || [], key, "goodsNum");
      return item ? item.goodsName || "-" : "-";
    },
    getVariety() {
      getVarietyList({}).then((res) => {
        this.varietyList = res.data || [];
      });
    },
    getVarietyLabel(val) {
      const item = getFindByKey(this.varietyList, val, 'varietyNo')
      return item ? item.varietyName : (val ?? '-')
    },
    getLevel() {
      getLevelList({}).then((res) => {
        this.levelList = res.data || [];
      });
    },
    getLevelLabel(val) {
      const item = getFindByKey(this.levelList, val, 'levelNo')
      return item ? item.levelName : (val ?? '-')
    },
    /**
     * 订单汇总查询参数（先按 allocation 的查询维度对齐：生产日期/发货日期）
     * @returns {Object}
     */
    buildOrderSummaryQueryParams() {
      const node = this.selectedAllocationTreeNode;
      const base = {
        saleDate: this.manualQuery.productionDate,
        deliveryDate: this.manualQuery.shipDate,
      };
      if (node) {
        base.lineNum = node.type === "line" ? node.lineNum : null;
        base.marketNum = node.type === "market" ? node.marketNum : null;
        base.customerNum = node.type === "customer" ? node.customerNum : null;
      }
      return base;
    },
    /**
     * 查询订单信息汇总（接口直出字段；只追加 _osKey 便于联动）
     * @param {Object} params
     * @returns {Promise<void>}
     */
    fetchOrderSummaryList(params) {
      return getSaleOrderGoodsDetailList(params).then((res) => {
        const list = (res && res.data) || [];
        this.orderSummaryList = (list || []).map((r, index) => ({
          _osKey: r && r.id != null ? r.id : `os-${index}`,
          ...r,
        }));
        const firstOs = this.orderSummaryList[0] || null;
        this.selectedOrderSummaryRow = firstOs;
        this.selectedOrderSummaryKey = firstOs ? firstOs._osKey : null;
        this.fetchAllocationResultAllList();
        this.syncAllocationResultList();
        this.$nextTick(() => {
          if (this.$refs.orderSummaryTable) {
            this.$refs.orderSummaryTable.setCurrentRow(firstOs);
          }
        });
      });
    },
    /**
     * 树节点点击：切换维度并刷新右侧列表
     * @param {Object} data
     */
    handleAllocationTreeNodeClick(data) {
      if (!data) return;
      this.selectedAllocationTreeNode = data;
      const params = this.buildOrderSummaryQueryParams();
      this.fetchOrderSummaryList(params);
      this.$nextTick(() => {
        if (this.$refs.allocationOrderTree && data.id != null) {
          this.$refs.allocationOrderTree.setCurrentKey(data.id);
        }
      });
    },
    /**
     * 在 getAllocationList 返回行上仅追加页面内部字段，保留接口字段原样
     * @param {Object} r 接口原始行
     * @param {number} index 下标兜底
     * @returns {Object}
     */
    attachAllocationRowMeta(r, index) {
      const saleNum = r && (r.saleNum != null ? r.saleNum : r.sale_num);
      const osIdx = (this.orderSummaryList || []).findIndex(
        (o) =>
          o &&
          (o.order_num === saleNum ||
            o.orderNum === saleNum ||
            String(o.order_num) === String(saleNum) ||
            String(o.orderNum) === String(saleNum))
      );
      const osRow = osIdx >= 0 ? this.orderSummaryList[osIdx] : null;
      const osKey =
        (osRow && osRow._osKey != null ? osRow._osKey : null) ||
        (r && r.osKey != null ? r.osKey : null) ||
        (r && r.orderLineId != null ? r.orderLineId : null) ||
        `alloc-${index}`;
      const id = r && (r.id != null ? r.id : r.allocationId);
      return {
        ...(r || {}),
        _allocId: id != null ? id : `tmp-${index}`,
        _osKey: osKey,
        _orderSummaryIndex: osIdx >= 0 ? osIdx : null,
        _allocQty: 1,
      };
    },
    /**
     * 查询分配结果全量：getAllocationList → allocationResultAllList → syncAllocationResultList
     * @returns {Promise<void>|void}
     */
    fetchAllocationResultAllList() {
      const row = this.selectedOrderSummaryRow;
      if (!row) return;
      const p = {
         saleId: row.id,
      };
      return getAllocationList(p).then((res) => {
        const list = Array.isArray(res && res.data) ? res.data : [];
        this.allocationResultAllList = (list || []).map((apiRow, i) =>
          this.attachAllocationRowMeta(apiRow, i)
        );
        const maxId = (this.allocationResultAllList || []).reduce((m, r) => {
          const v = Number(r && r._allocId);
          return Math.max(m, Number.isNaN(v) ? 0 : v);
        }, 0);
        if (maxId > this.allocationResultSeq) this.allocationResultSeq = maxId;
        this.syncAllocationResultList();
      });
    },
    /** 按当前选中的订单行过滤分配结果 */
    syncAllocationResultList() {
      if (this.selectedOrderSummaryKey == null || this.selectedOrderSummaryKey === "") {
        this.allocationResultList = (this.allocationResultAllList || []).slice();
        return;
      }
      this.allocationResultList = (this.allocationResultAllList || []).filter(
        (r) => r && r._osKey === this.selectedOrderSummaryKey
      );
    },
  },
};
</script>

<style scoped lang="scss">
.pre-shipment-page {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: calc(100vh - 90px);
  min-height: 0;
  overflow: hidden;
  gap: 16px;
}

.section {
  width: 100%;
  min-height: 0;
}

.section-top {
  flex: 0 0 230px;
  max-height: 230px;
}

.section-bottom {
  flex: 1 1 auto;
  min-height: 0;
}

.section-card,
.card-body {
  height: 100%;
}

.section-card ::v-deep .el-card__body {
  height: 100%;
}

.card-body {
  overflow-y: auto;
  overflow-x: hidden; /* 避免 el-row gutter 负 margin 导致横向滚动 */
}

.bottom-row {
  height: 100%;
  margin-left: 0 !important;
  margin-right: 0 !important;
}

.bottom-col,
.inner-card {
  height: 100%;
}

.inner-card ::v-deep .el-card__body {
  height: 100%;
}

.inner-card-body {
  height: 100%;
  overflow: auto;
}

.card-title {
  font-weight: 700;
  color: #606266;
  margin-bottom: 8px;
}

.card-toolbar {
  display: flex;
  justify-content: flex-start;
}

.right-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.panel-section {
  min-height: 0;
}

.panel-section-0 {
  flex: 0 0 auto;
}

.panel-section-1 {
  flex: 0 0 35%;
}

.panel-section-2 {
  flex: 1 1 auto;
}

.panel-section-3 {
  flex: 0 0 auto;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.fill-tabs {
  height: 100%;
}

.fill-tabs ::v-deep .el-tabs__content {
  height: calc(100% - 40px);
  overflow: auto;
}

.manual-query-form,
.sort-form {
  padding: 4px 0;
}
</style>

