<template>
  <div class="app-container sale-order-page">
    <!-- 上：搜索 + 按钮组 -->
    <el-card shadow="never" class="top-card">
      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px">
        <el-form-item label="日期" prop="dateRange">
          <el-date-picker
            v-model="queryParams.dateRange"
            type="daterange"
            value-format="yyyy-MM-dd"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            style="width: 260px"
            clearable
          />
        </el-form-item>

        <el-form-item label="客户" prop="customerNum">
          <el-select v-model="queryParams.customerNum" placeholder="请选择客户" filterable clearable style="width: 200px">
            <el-option v-for="item in customerOptions" :key="item.customerNum" :value="item.customerNum" :label="item.customerName" />
          </el-select>
        </el-form-item>

        <el-form-item label="业务员" prop="employeeNum">
          <el-select v-model="queryParams.employeeNum" placeholder="请选择业务员" filterable clearable style="width: 200px">
            <el-option v-for="item in salespersonOptions" :key="item.employeeNum" :value="item.employeeNum" :label="item.employeeName" />
          </el-select>
        </el-form-item>

        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">查询</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>

      <el-row :gutter="10" class="mb8">
        <el-col :span="1.5">
          <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDeleteAll">批量删除</el-button>
        </el-col>
      </el-row>
    </el-card>

    <br />

    <!-- 下：表格 -->
    <el-card shadow="never" class="bottom-card">
      <el-table border stripe v-loading="loading" ref="multipleTable" :data="list" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="单据日期" align="center" prop="documentDate" min-width="110" />
        <el-table-column label="单据编号" align="center" prop="orderNum" min-width="150" />
        <el-table-column label="销售日期" align="center" prop="saleDate" min-width="110" />
        <el-table-column label="客户编号" align="center" prop="customerNum" min-width="120" />
        <el-table-column label="客户名称" align="center" prop="customerName" min-width="140" />
        <el-table-column label="业务员" align="center" prop="employeeNum" min-width="120" />
        <el-table-column label="应收客户" align="center" prop="customerName" min-width="140" />
        <el-table-column label="备注" align="center" prop="remark" min-width="160" />
        <el-table-column label="总计金额" align="center" prop="totalAmount" min-width="110" />
        <el-table-column label="备注1" align="center" prop="remark1" min-width="160" />
        <el-table-column label="操作" align="center" fixed="right" width="180">
          <template slot-scope="scope">
            <el-button type="text" size="mini" icon="el-icon-document" @click="handleDetail(scope.row)">查看详细</el-button>
            <el-button type="text" size="mini" icon="el-icon-edit" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button type="text" size="mini" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>

      <pagination
        v-show="total > 0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>

    <!-- 新增/编辑/查看：全屏弹框 -->
    <el-dialog :title="dialogTitle" :visible.sync="dialogOpen" fullscreen append-to-body class="sale-order-dialog">
      <!-- 查看详情：无左侧树；表头/底部用带边框描述列表，中间仅明细表格 -->
      <div v-if="dialogMode === 'view'" class="dialog-detail-body">
        <el-card shadow="never" class="dialog-detail-card">
          <el-descriptions :column="3" border size="small" class="detail-desc detail-desc--head">
            <el-descriptions-item label="单据日期">{{ emptyDisplay(form.documentDate) }}</el-descriptions-item>
            <el-descriptions-item label="单据编号">{{ emptyDisplay(form.orderNum) }}</el-descriptions-item>
            <el-descriptions-item label="销售日期">{{ emptyDisplay(form.saleDate) }}</el-descriptions-item>
            <el-descriptions-item label="客户编号">{{ emptyDisplay(form.customerNum) }}</el-descriptions-item>
            <el-descriptions-item label="客户名称">{{ emptyDisplay(form.customerName) }}</el-descriptions-item>
            <el-descriptions-item label="业务员">{{ getEmployeeName(form.employeeNum) }}</el-descriptions-item>
            <el-descriptions-item label="应收客户">{{ emptyDisplay(form.customerName) }}</el-descriptions-item>
            <el-descriptions-item label="备注" :span="2">{{ emptyDisplay(form.remark) }}</el-descriptions-item>
          </el-descriptions>

          <div class="dialog-goods-table-wrap dialog-goods-table-wrap--detail">
            <el-table border stripe class="dialog-goods-table dialog-goods-table--readonly" :data="dialogGoodsList" height="100%">
              <el-table-column label="货品编号" align="center" prop="goodsNum" min-width="120" show-overflow-tooltip />
              <el-table-column label="货品名称" align="center" prop="goodsName" min-width="130" show-overflow-tooltip />
              <el-table-column label="规格" align="center" prop="goodsSpec" min-width="100" show-overflow-tooltip />
              <el-table-column label="基本计量数量" align="center" prop="baseNum" min-width="120" />
              <el-table-column label="基本计量单位" align="center" prop="baseUnit" min-width="110" />
              <el-table-column label="辅助计量数量" align="center" prop="assNum" min-width="120" />
              <el-table-column label="辅助计量单位" align="center" prop="assUnit" min-width="110" />
              <el-table-column label="单价" align="center" prop="unitPrice" min-width="100" />
              <el-table-column label="小计" align="center" prop="subTotal" min-width="100" />
              <el-table-column label="备注" align="center" prop="lineRemark" min-width="120" show-overflow-tooltip />
            </el-table>
          </div>

          <el-descriptions :column="3" border size="small" class="detail-desc detail-desc--foot">
            <el-descriptions-item label="总计金额">{{ emptyDisplay(form.totalAmount) }}</el-descriptions-item>
            <el-descriptions-item label="备注1" :span="2">{{ emptyDisplay(form.remark1) }}</el-descriptions-item>
          </el-descriptions>
        </el-card>
      </div>

      <el-row v-else :gutter="12" class="dialog-layout">
        <!-- 左：树（物流线->市场->客户，仅客户可选；编辑时全部禁用） -->
        <el-col :span="4" class="dialog-left">
          <el-card shadow="never" class="dialog-tree-card">
            <el-tree
              ref="dialogTree"
              :data="dialogTreeData"
              :props="dialogTreeProps"
              node-key="id"
              highlight-current
              default-expand-all
              :expand-on-click-node="false"
              class="dialog-tree-inner"
              @node-click="handleDialogTreeNodeClick"
            >
              <span slot-scope="{ data }" class="tree-node" :class="getDialogTreeNodeClass(data)">
                {{ data.label }}
              </span>
            </el-tree>
          </el-card>
        </el-col>

        <!-- 右：表头字段 + 可编辑明细 + 底部汇总 -->
        <el-col :span="20" class="dialog-right">
          <el-card shadow="never" class="dialog-form-card">
            <div class="dialog-form-body">
              <el-form ref="dialogForm" :model="form" :rules="dialogFormRules" label-width="100px" size="small" class="dialog-head-form">
                <el-row :gutter="12">
                  <el-col :span="8">
                    <el-form-item label="单据日期" prop="documentDate">
                      <el-date-picker
                        v-model="form.documentDate"
                        type="date"
                        value-format="yyyy-MM-dd"
                        placeholder="单据日期"
                        style="width: 100%"
                        :disabled="isDialogEditHeadDisabled"
                      />
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="单据编号" prop="orderNum">
                      <el-input v-model="form.orderNum" placeholder="请输入单据编号" clearable :disabled="isDialogEditHeadDisabled" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="销售日期" prop="saleDate">
                      <el-date-picker
                        v-model="form.saleDate"
                        type="date"
                        value-format="yyyy-MM-dd"
                        placeholder="销售日期"
                        style="width: 100%"
                        :disabled="isDialogEditHeadDisabled"
                      />
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="客户编号" prop="customerNum">
                      <el-input v-model="form.customerNum" placeholder="左侧树选择客户" readonly :disabled="isDialogEditHeadDisabled" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="客户名称" prop="customerName">
                      <el-input v-model="form.customerName" placeholder="左侧树选择客户" readonly :disabled="isDialogEditHeadDisabled" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="业务员" prop="employeeNum">
                      <el-select
                        v-model="form.employeeNum"
                        placeholder="请选择业务员"
                        filterable
                        clearable
                        style="width: 100%"
                        :disabled="isDialogEditHeadDisabled"
                      >
                        <el-option v-for="item in salespersonOptions" :key="item.employeeNum" :value="item.employeeNum" :label="item.employeeName" />
                      </el-select>
                    </el-form-item>
                  </el-col>
                  <el-col :span="8">
                    <el-form-item label="应收客户" prop="customerName">
                      <el-input v-model="form.customerName" placeholder="默认同客户名称，可改" clearable :disabled="isDialogEditHeadDisabled" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="16">
                    <el-form-item label="备注" prop="remark">
                      <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注（选填）" />
                    </el-form-item>
                  </el-col>
                </el-row>

                <div class="dialog-goods-toolbar">
                  <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAddDialogGoodsRow">添加明细</el-button>
                </div>

              <div class="dialog-goods-table-wrap">
                <el-table border stripe class="dialog-goods-table" :data="dialogGoodsList" height="360px">
                <el-table-column label="货品编号" align="center" prop="goodsNum" min-width="140">
                  <template slot-scope="{ row, $index }">
                    <el-input v-model="row.goodsNum" size="mini" placeholder="货品编号" clearable>
                      <template slot="append">
                        <el-tooltip content="查询物料" placement="top">
                          <el-button
                            type="primary"
                            icon="el-icon-search"
                            circle
                            size="mini"
                            @click="openDialogMaterialQuery($index)"
                          />
                        </el-tooltip>
                      </template>
                    </el-input>
                  </template>
                </el-table-column>
                <el-table-column label="货品名称" align="center" prop="goodsName" min-width="130">
                  <template slot-scope="{ row }">
                    <el-input v-model="row.goodsName" size="mini" placeholder="货品名称" clearable />
                  </template>
                </el-table-column>
                <el-table-column label="规格" align="center" prop="goodsSpec" min-width="100">
                  <template slot-scope="{ row }">
                    <el-input v-model="row.goodsSpec" size="mini" placeholder="规格" clearable />
                  </template>
                </el-table-column>
                <el-table-column label="基本计量数量" align="center" prop="baseNum" min-width="120">
                  <template slot-scope="{ row, $index }">
                    <decimal-input
                      v-model="row.baseNum"
                      :precision="2"
                      :min="0"
                      placeholder="数量"
                      @change="() => recalcDialogGoodsLine($index)"
                    />
                  </template>
                </el-table-column>
                <el-table-column label="基本计量单位" align="center" prop="baseUnit" min-width="110">
                  <template slot-scope="{ row }">
                    <el-input v-model="row.baseUnit" size="mini" placeholder="单位" clearable />
                  </template>
                </el-table-column>
                <el-table-column label="辅助计量数量" align="center" prop="assNum" min-width="120">
                  <template slot-scope="{ row, $index }">
                    <decimal-input
                      v-model="row.assNum"
                      :precision="2"
                      :min="0"
                      placeholder="数量"
                      @change="() => syncDialogGoodsBaseNumFromAssist(row, $index)"
                    />
                  </template>
                </el-table-column>
                <el-table-column label="辅助计量单位" align="center" prop="assUnit" min-width="110">
                  <template slot-scope="{ row }">
                    <el-input v-model="row.assUnit" size="mini" placeholder="单位" clearable />
                  </template>
                </el-table-column>
                <el-table-column label="单价" align="center" prop="unitPrice" min-width="100">
                  <template slot-scope="{ row, $index }">
                    <decimal-input v-model="row.unitPrice" :precision="2" :min="0" placeholder="单价" @change="() => recalcDialogGoodsLine($index)" />
                  </template>
                </el-table-column>
                <el-table-column label="小计" align="center" prop="subTotal" min-width="100">
                  <template slot-scope="{ row }">
                    <el-input :value="row.subTotal != null && row.subTotal !== '' ? row.subTotal : ''" size="mini" readonly placeholder="自动计算" />
                  </template>
                </el-table-column>
                <el-table-column label="备注" align="center" prop="remark" min-width="120">
                  <template slot-scope="{ row }">
                    <el-input v-model="row.remark" size="mini" placeholder="备注" clearable />
                  </template>
                </el-table-column>
                <el-table-column label="操作" align="center" width="70" fixed="right">
                  <template slot-scope="{ $index }">
                    <el-button type="text" icon="el-icon-delete" :disabled="dialogGoodsList.length <= 1" @click="handleRemoveDialogGoodsRow($index)" />
                  </template>
                </el-table-column>
              </el-table>
              </div>

                <el-row :gutter="12" class="dialog-footer-form">
                  <el-col :span="8">
                    <el-form-item label="总计金额" prop="totalAmount">
                      <el-input v-model="form.totalAmount" readonly placeholder="由明细小计汇总" />
                    </el-form-item>
                  </el-col>
                  <el-col :span="16">
                    <el-form-item label="备注1" prop="remark1">
                      <el-input v-model="form.remark1" type="textarea" :rows="2" placeholder="请输入备注1（选填）" />
                    </el-form-item>
                  </el-col>
                </el-row>
              </el-form>
            </div>
          </el-card>
        </el-col>
      </el-row>

      <div slot="footer" class="dialog-footer">
        <template v-if="dialogMode === 'view'">
          <el-button type="primary" @click="dialogOpen = false">关 闭</el-button>
        </template>
        <template v-else>
          <el-button @click="dialogOpen = false">取 消</el-button>
          <el-button type="primary" @click="submitForm">确 定</el-button>
        </template>
      </div>
    </el-dialog>

    <!-- 明细行货品速查（单选）；选后拉取客户价 -->
    <query-material
      ref="queryMaterial"
      :isMultiple="false"
      :excludeGoodsNums="dialogMaterialExcludeGoodsNums"
      @selectList="handleDialogMaterialSelect"
    />
  </div>
</template>

<script>
import { formatDateYMS } from "@/utils";
import { getStaffList } from "@/api/baseInfo/staff";
import { getSaleOrderTree, getSaleOrderPage, getGoodsPriceInfo, addSaleOrder, editSaleOrder , delSaleOrder, getSaleOrderById } from "@/api/sale/saleOrder";
import { getClienteleList } from "@/api/sale/clientele";
import QueryMaterial from "@/views/components/queryMaterial.vue";

export default {
  name: "SaleOrder",
  components: { QueryMaterial },
  data() {
    return {
      /** 列表加载状态 */
      loading: false,
      /** 表格数据 */
      list: [],
      /** 总数 */
      total: 0,
      /** 选中 ids */
      ids: [],
      /** 批量删除禁用控制 */
      multiple: true,
      /** 查询参数（必须包含 pageNum/pageSize） */
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        dateRange: [],
        customerNum: null,
        employeeNum: null,
        documentDateStart: null,
        documentDateEnd: null
      },
      /** 客户下拉（预留接口，当前模拟） */
      customerOptions: [],
      /** 业务员下拉（预留接口，当前模拟） */
      salespersonOptions: [],
      /** 新增弹框 */
      dialogOpen: false,
      dialogTitle: "新增",
      /** 弹框模式：add / edit / view（查看详情无树、只读） */
      dialogMode: "add",
      /** 新增/编辑表头 + 底部汇总（与列表字段对齐） */
      form: {
        id: null,
        documentDate: null,
        orderNum: null,
        saleDate: null,
        customerNum: null,
        customerName: null,
        employeeNum: null,
        remark: null,
        /** 只读展示：由明细小计汇总 */
        totalAmount: "0.00",
        remark1: null,
        goods: [],
      },
      /** 弹框内可编辑明细行 */
      dialogGoodsList: [],
      /** 物料速查：当前正在选料的明细行下标 */
      currentDialogMaterialRowIndex: null,
      /** 物料速查：已选货品编号，禁止重复选（不含当前行） */
      dialogMaterialExcludeGoodsNums: [],

      /** 弹框左侧树数据（模拟 + 预留接口） */
      dialogTreeData: [],
      /** 弹框树 props 映射 */
      dialogTreeProps: {
        children: "children",
        label: "label",
      },
    };
  },
  watch: {
    'queryParams.dateRange': {
      handler(newVal) {
        if(newVal && newVal.length === 2) {
        this.queryParams.documentDateStart = newVal[0];
        this.queryParams.documentDateEnd = newVal[1];
      } else {
        this.queryParams.documentDateStart = null;
        this.queryParams.documentDateEnd = null;
      }
      },
      deep: true,
      immediate: true,
    },
  },
  computed: {
    /**
     * 弹框表单校验规则：除「备注」「备注1」外表头字段必填；明细在提交时由 getDialogGoodsValidationError 与 totalAmount 规则配合校验
     */
    dialogFormRules() {
      return {
        documentDate: [{ required: true, message: "请选择单据日期", trigger: "change" }],
        orderNum: [{ required: true, message: "请输入单据编号", trigger: "blur" }],
        saleDate: [{ required: true, message: "请选择销售日期", trigger: "change" }],
        customerNum: [{ required: true, message: "请从左侧树选择客户", trigger: "change" }],
        employeeNum: [{ required: true, message: "请选择业务员", trigger: "change" }],
        customerName: [{ required: true, message: "请输入应收客户", trigger: "blur" }],
        totalAmount: [{ validator: this.validateDialogTotalAmountField, trigger: "change" }],
      };
    },
    /** 编辑弹框：单据日期/编号/销售日期/客户/业务员等表头不可改 */
    isDialogEditHeadDisabled() {
      return this.dialogMode === "edit";
    },
  },
  created() {
    /** 初始化：日期默认明天到明天 */
    const today = formatDateYMS(new Date().getTime() + 24 * 60 * 60 * 1000);
    this.queryParams.dateRange = [today, today];
    this.queryParams.documentDateStart = today;
    this.queryParams.documentDateEnd = today;
    /** 初始化：下拉数据（预留接口） */
    this.fetchCustomerOptions();
    this.fetchSalespersonOptions();
    /** 初始化：弹框左侧树（预留接口） */
    this.fetchDialogTreeData();
    /** 初始化：默认查询 */
    this.getList();
  },
  methods: {
    /*** 获取业务员名称 ***/
    getEmployeeName(employeeNum) {
      return this.salespersonOptions.find(item => item.employeeNum === employeeNum)?.employeeName;
    },
    /**
     * 预留：获取弹框左侧树（物流线->市场->客户）
     */
    fetchDialogTreeData() {
      getSaleOrderTree({}).then(res => {
        this.dialogTreeData = res.data;
      });
    },

    /**
     * 弹框树：节点 class 控制
     * - 编辑时：全部禁用
     * - 新增时：仅 customer 可点（小手），其它不允许选中
     */
    getDialogTreeNodeClass(data) {
      if (this.dialogMode === "edit") return "tree-node--disabled";
      if (data && data.type === "customer") return "tree-node--customer";
      return "tree-node--disabled";
    },

    /**
     * 弹框树点击：仅客户可选中；编辑模式禁止选择
     */
    handleDialogTreeNodeClick(data) {
      console.log(data)
      if (this.dialogMode === "edit") return;
      if (!data || data.type !== "customer") {
        this.$nextTick(() => {
          if (this.$refs.dialogTree) this.$refs.dialogTree.setCurrentKey(null);
        });
        return;
      }
      this.form.customerNum = data.customerNum || null;
      this.form.customerName = data.customerName || data.label || null;
      /** 应收客户默认带出为客户名称，可再改 */
      if (this.form.customerName) {
        this.form.receivableCustomer = this.form.customerName;
      }
      this.$nextTick(() => {
        if (this.$refs.dialogTree) this.$refs.dialogTree.setCurrentKey(data.id);
        if (this.$refs.dialogForm) {
          this.$refs.dialogForm.validateField("customerNum");
          this.$refs.dialogForm.validateField("customerName");
        }
      });
    },

    /**
     * 根据 customerNo 在树中定位节点 id
     */
    findDialogCustomerNodeId(customerNum) {
      const target = customerNum != null ? String(customerNum) : "";
      let hit = null;
      const walk = (nodes) => {
        (nodes || []).forEach((n) => {
          if (hit) return;
          if (n && n.type === "customer" && String(n.customerNum) === target) {
            hit = n.id;
            return;
          }
          if (n && n.children) walk(n.children);
        });
      };
      walk(this.dialogTreeData);
      return hit;
    },
    /**
     * 获取客户下拉数据
     */
    fetchCustomerOptions() {
      getClienteleList({}).then(res => {
        this.customerOptions = res.data;
      });
    },
    /**
     * 获取业务员下拉数据（employeeType === '3'）
     */
    fetchSalespersonOptions() {
      getStaffList({}).then((res) => {
        const list = (res && res.data) || [];
        const filtered = (list || []).filter((item) => String(item.employeeType) === "3");
        this.salespersonOptions = filtered;
      });
    },
    /**
     * 获取列表（预留接口）
     */
    getList() {
      /** TODO：接入销售订单分页接口（POST/GET 以后台为准），携带 queryParams + dateRange 拆分 start/end */
      this.loading = true;
      getSaleOrderPage(this.queryParams).then(res => {
        this.list = res.data.records;
        this.total = res.data.total;
        this.loading = false;
      });
    },
    /**
     * 查询按钮
     */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /**
     * 重置按钮
     */
    resetQuery() {
      const today = formatDateYMS(new Date().getTime());
      this.queryParams = {
        pageNum: 1,
        pageSize: 10,
        dateRange: [today, today],
        customerNum: null,
        employeeNum: null,
      };
      this.handleQuery();
    },
    /**
     * 表格勾选变化
     * @param {Array} selection 选中行
     */
    handleSelectionChange(selection) {
      this.ids = (selection || []).map((r) => r.id);
      this.multiple = this.ids.length === 0;
    },
    /**
     * 空明细行（弹框表格）
     */
    createEmptyDialogGoodsRow() {
      return {
        orderNum: null,
        goodsNum: null,
        goodsName: null,
        goodsSpec: null,
        baseNum: null,
        baseUnit: null,
        assNum: null,
        assistUnit: null,
        unitPrice: null,
        remark: null,
        conversionValue: null,
      };
    },
    /**
     * 打开明细行物料速查（单选）
     * @param {number} rowIndex 当前表格行下标
     */
    openDialogMaterialQuery(rowIndex) {
      this.currentDialogMaterialRowIndex = rowIndex;
      /** 其它行已选编号禁止再选，避免重复明细 */
      this.dialogMaterialExcludeGoodsNums = (this.dialogGoodsList || [])
        .map((r, i) => {
          if (i === rowIndex || !r) return null;
          const n = r.goodsNum;
          return n != null && String(n).trim() !== "" ? String(n) : null;
        })
        .filter(Boolean);
      if (this.$refs.queryMaterial) this.$refs.queryMaterial.open();
    },
    /**
     * 物料速查确定：写入货品信息，再按单据日期+客户+货品编号查询价格
     * @param {Array<Object>} list 选中行（单选时为 1 条）
     */
    handleDialogMaterialSelect(list) {
      const selected = list || [];
      if (!selected.length) return;
      const idx = this.currentDialogMaterialRowIndex;
      if (idx == null || idx < 0) return;
      const row = this.dialogGoodsList[idx];
      if (!row) return;
      const item = selected[0];
      /** 速查行字段 -> 销售订单明细 */
      this.$set(row, "goodsNum", item.goodsNum != null ? item.goodsNum : null);
      this.$set(row, "goodsName", item.goodsName != null ? item.goodsName : null);
      this.$set(row, "goodsSpec", item.goodsSpec != null ? item.goodsSpec : null);
      this.$set(row, "baseUnit", item.unit != null ? item.unit : null);
      this.$set(row, "assUnit", item.assUnit != null ? item.assUnit : null);
      /** 换算值：基本计量数量 = conversionValue × 辅助计量数量 */
      this.$set(
        row,
        "conversionValue",
        item.conversionValue != null && item.conversionValue !== "" ? item.conversionValue : null
      );
      this.syncDialogGoodsBaseNumFromAssist(row, idx);
      this.fetchGoodsPriceInfoForDialogRow(idx);
    },
    /**
     * 是否存在有效换算值（此时基本数量由辅助数量推算，输入框禁用）
     * @param {Object} row 明细行
     * @returns {boolean}
     */
    isDialogGoodsBaseNumDerivedFromAssist(row) {
      const cv = Number(row && row.conversionValue);
      return Number.isFinite(cv) && cv > 0;
    },
    /**
     * 按换算值同步基本计量数量：baseNum = conversionValue × assNum，并重算小计
     * @param {Object} row 明细行
     * @param {number} index 行下标
     */
    syncDialogGoodsBaseNumFromAssist(row, index) {
      if (!row) return;
      const cv = Number(row.conversionValue);
      const assRaw = row.assNum;
      const hasAss =
        assRaw !== null &&
        assRaw !== undefined &&
        String(assRaw).trim() !== "" &&
        !Number.isNaN(Number(assRaw));

      if (!Number.isFinite(cv) || cv <= 0) {
        this.recalcDialogGoodsLine(index);
        return;
      }
      if (!hasAss) {
        this.$set(row, "baseNum", null);
        this.recalcDialogGoodsLine(index);
        return;
      }
      const ass = Number(assRaw);
      if (ass >= 0) {
        this.$set(row, "baseNum", (cv * ass).toFixed(2));
      }
      this.recalcDialogGoodsLine(index);
    },
    /**
     * 调用 getGoodsPriceInfo：单据日期、客户编号、货品编号
     * @param {number} index 明细行下标
     */
    fetchGoodsPriceInfoForDialogRow(index) {
      const row = this.dialogGoodsList[index];
      if (!row) return;
      const documentDate = this.form.documentDate;
      const customerNum = this.form.customerNum;
      const goodsNum = row.goodsNum;
      if (!documentDate) {
        this.$message.warning("请先选择单据日期");
        return;
      }
      if (customerNum == null || String(customerNum).trim() === "") {
        this.$message.warning("请先在左侧树选择客户");
        return;
      }
      if (goodsNum == null || String(goodsNum).trim() === "") {
        return;
      }
      const payload = {
        documentDate: String(documentDate).trim(),
        customerNum: String(customerNum).trim(),
        goodsNum: String(goodsNum).trim(),
      };
      getGoodsPriceInfo(payload)
        .then((res) => {
          this.applyGoodsPriceInfoToDialogRow(row, res && res.data);
          /** 价格接口若带回数量字段，有换算值时仍以「辅助×换算」为准写回基本数量 */
          this.syncDialogGoodsBaseNumFromAssist(row, index);
        })
        .catch(() => {});
    },
    /**
     * 将价格接口返回合并到明细行（字段名随后端可再调）
     * @param {Object} row 明细行
     * @param {*} data 接口 data
     */
    applyGoodsPriceInfoToDialogRow(row, data) {
      if (data == null) return;
      let d = data;
      if (Array.isArray(d)) {
        d = d[0];
        if (d == null) return;
      }
      if (typeof d !== "object") return;
      /** 单价：兼容常见字段名 */
      const price =
        d.unitPrice != null
          ? d.unitPrice
          : d.salePrice != null
            ? d.salePrice
            : d.price != null
              ? d.price
              : null;
      if (price != null && price !== "") this.$set(row, "unitPrice", price);
      /** 可选：计量单位、规格、辅助数量等若接口带回则覆盖（基本数量有换算值时在 sync 里重算） */
      ["goodsSpec", "baseUnit", "assUnit", "assNum"].forEach((k) => {
        if (d[k] != null && d[k] !== "") this.$set(row, k, d[k]);
      });
      if (!this.isDialogGoodsBaseNumDerivedFromAssist(row)) {
        if (d.baseNum != null && d.baseNum !== "") this.$set(row, "baseNum", d.baseNum);
      }
    },
    /**
     * 按行重算小计（基本计量数量 × 单价）并汇总总计金额
     * @param {number} index 行下标
     */
    recalcDialogGoodsLine(index) {
      const row = this.dialogGoodsList[index];
      if (!row) return;
      const q = Number(row.baseNum);
      const p = Number(row.unitPrice);
      const sub = Number.isFinite(q) && Number.isFinite(p) ? (q * p).toFixed(2) : null;
      this.$set(row, "subTotal", sub);
      this.recalcDialogTotalAmount();
    },
    /**
     * 汇总明细小计到表头总计金额（只读）
     */
    recalcDialogTotalAmount() {
      let sum = 0;
      (this.dialogGoodsList || []).forEach((r) => {
        const v = Number(r && r.subTotal);
        if (Number.isFinite(v)) sum += v;
      });
      this.form.totalAmount = sum.toFixed(2);
    },
    /**
     * 表单项「总计金额」校验：明细除行备注外必填，且合计须大于 0
     * @param {Object} rule 规则对象
     * @param {*} value 当前值
     * @param {Function} callback 回调
     */
    validateDialogTotalAmountField(rule, value, callback) {
      const detailErr = this.getDialogGoodsValidationError();
      if (detailErr) {
        callback(new Error(detailErr));
        return;
      }
      const t = parseFloat(value);
      if (!Number.isFinite(t) || t <= 0) {
        callback(new Error("请完善明细中的数量与单价，总计金额须大于0"));
        return;
      }
      callback();
    },
    /**
     * 空值在详情描述列表中显示为「—」
     * @param {*} val 原值
     * @returns {string}
     */
    emptyDisplay(val) {
      if (val === null || val === undefined) return "—";
      const s = String(val).trim();
      return s === "" ? "—" : s;
    },
    /**
     * 从列表行解析明细数据（无则返回模拟行，接入详情接口后删除模拟）
     * @param {Object} row 列表行
     * @returns {Array<Object>}
     */
    resolveDetailGoodsFromRow(row) {
      const list = row && row.goods;
      if (Array.isArray(list) && list.length) {
        return list.map((item) => ({ ...item }));
      }
      return [
        {
          goodsNum: "M001",
          goodsName: "示例货品",
          goodsSpec: "标品",
          baseQty: "1",
          baseUnit: "kg",
          assistQty: "1",
          assistUnit: "箱",
          unitPrice: "10",
          subTotal: "10.00",
          lineRemark: null,
        },
      ];
    },
    /**
     * 校验明细行必填（行「备注」选填）
     * @returns {string|null} 错误提示或 null
     */
    getDialogGoodsValidationError() {
      const list = this.dialogGoodsList || [];
      if (!list.length) return "请至少添加一行明细";
      const emptyStr = (v) => v == null || String(v).trim() === "";
      const emptyNum = (v) => v == null || String(v).trim() === "" || Number.isNaN(Number(v));
      for (let i = 0; i < list.length; i++) {
        const r = list[i];
        const tip = `第${i + 1}行`;
        if (emptyStr(r.goodsNum)) return `${tip}：请填写货品编号`;
        if (emptyNum(r.baseNum) || Number(r.baseNum) < 0) return `${tip}：请填写基本计量数量`;
        if (emptyNum(r.assNum) || Number(r.assNum) < 0) return `${tip}：请填写辅助计量数量`;
        if (emptyNum(r.unitPrice) || Number(r.unitPrice) < 0) return `${tip}：请填写单价`;
        if (emptyNum(r.subTotal) || Number(r.subTotal) < 0) return `${tip}：小计无效，请检查数量与单价`;
      }
      return null;
    },
    /**
     * 添加一行明细
     */
    handleAddDialogGoodsRow() {
      this.dialogGoodsList.push(this.createEmptyDialogGoodsRow());
    },
    /**
     * 删除一行明细（至少保留一行）
     * @param {number} index 行下标
     */
    handleRemoveDialogGoodsRow(index) {
      if (this.dialogGoodsList.length <= 1) return;
      this.dialogGoodsList.splice(index, 1);
      this.recalcDialogTotalAmount();
    },
    /**
     * 新增按钮：打开全屏弹框（单据日期、销售日期默认明天）
     */
    handleAdd() {
      const tomorrow = formatDateYMS(Date.now() + 24 * 60 * 60 * 1000);
      this.dialogTitle = "新增";
      this.dialogMode = "add";
      this.form = {
        id: null,
        documentDate: tomorrow,
        orderNum: null,
        saleDate: tomorrow,
        customerNum: null,
        customerName: null,
        employeeNum: null,
        remark: null,
        totalAmount: "0.00",
        remark1: null,
        goods: [],
      };
      this.dialogGoodsList = [this.createEmptyDialogGoodsRow()];
      this.dialogOpen = true;
      this.$nextTick(() => {
        if (this.$refs.dialogTree) this.$refs.dialogTree.setCurrentKey(null);
        if (this.$refs.dialogForm) this.$refs.dialogForm.clearValidate();
      });
    },
    handleEdit(row) {
      this.dialogTitle = "编辑";
      this.dialogMode = "edit";
      getSaleOrderById({ id: row.id }).then(res => {
        this.form = res.data;
        this.dialogGoodsList = this.resolveDetailGoodsFromRow(res.data);
        this.dialogOpen = true;
        this.$nextTick(() => {
          if (this.$refs.dialogTree) this.$refs.dialogTree.setCurrentKey(null);
          if (this.$refs.dialogForm) this.$refs.dialogForm.clearValidate();
        });
      });
    },
    /**
     * 批量删除按钮（预留）
     */
    handleDeleteAll() {
      /** TODO：接入批量删除接口 */
      this.$message.info("批量删除待接入接口");
    },
    /**
     * 查看详细：全屏弹框，无左侧树；表头/底部为带边框描述列表，中间为只读明细表
     * @param {Object} row 当前行
     */
    handleDetail(row) {
       /** 编辑：明细（接入接口后由 row.detailList 替换） */
      this.dialogTitle = "查看详情";
      this.dialogMode = "view";
      getSaleOrderById({ id: row.id }).then(res => {
        this.form = res.data;
        this.dialogGoodsList = this.resolveDetailGoodsFromRow(res.data);
        // this.recalcDialogTotalAmount();
        this.dialogOpen = true;

      /** 编辑时：树保持高亮当前客户，但不允许再选 */
        this.$nextTick(() => {
          const id = this.findDialogCustomerNodeId(this.form.customerNum);
          if (this.$refs.dialogTree) this.$refs.dialogTree.setCurrentKey(id || null);
          if (this.$refs.dialogForm) this.$refs.dialogForm.clearValidate();
        });
      });
     
    },
    /**
     * 删除（单行）
     * @param {Object} row 当前行
     */
    handleDelete(row) {
      /** TODO：接入删除接口 */
      this.$confirm("确定要删除这条数据吗？", "提示", { type: "warning" })
        .then(() => {
          delSaleOrder({ ids: row.id }).then(res => {
            this.$message.success("删除成功");
            this.getList();
          });
        })
        .catch(() => {});
    },
    /**
     * 弹框确定（预留）：校验除备注、备注1 外的必填项及明细
     */
    submitForm() {
      if (this.dialogMode === "view") return;
      const formRef = this.$refs.dialogForm;
      if (!formRef) return;
      formRef.validate((valid) => {
        if (!valid) {
          this.$message.warning("请完善必填项");
          return;
        }
        if(this.dialogMode === "add") {
          this.form.goods = this.dialogGoodsList;
          addSaleOrder(this.form).then(res => {
            this.$message.success("保存成功");
            this.dialogOpen = false;
            this.getList();
          });
        } else {
          this.form.goods = this.dialogGoodsList;
          editSaleOrder(this.form).then(res => {
            this.$message.success("保存成功");
            this.dialogOpen = false;
            this.getList();
          });
        }
      });
    },
  },
};
</script>

<style scoped lang="scss">
.sale-order-page {
  display: flex;
  flex-direction: column;
}

/** 全屏弹框：整页不出现滚动条，仅表格区域内部可滚动（明细多行时） */
::v-deep .sale-order-dialog.el-dialog.is-fullscreen {
  margin: 0 !important;
  width: 100% !important;
  height: 100vh;
  max-height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

::v-deep .sale-order-dialog .el-dialog__header {
  flex-shrink: 0;
}

::v-deep .sale-order-dialog .el-dialog__body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  padding: 12px;
  box-sizing: border-box;
}

::v-deep .sale-order-dialog .el-dialog__footer {
  flex-shrink: 0;
}

/** 弹框内左右布局（占满 body 可用高度，不出现外层滚动） */
::v-deep .sale-order-dialog .dialog-layout.el-row {
  display: flex;
  flex-wrap: nowrap;
  height: 100%;
  min-height: 0;
}

::v-deep .sale-order-dialog .dialog-layout .el-col {
  float: none;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

::v-deep .sale-order-dialog .dialog-layout .el-col.dialog-right {
  flex: 1;
  min-width: 0;
}

::v-deep .dialog-tree-card.el-card,
::v-deep .dialog-form-card.el-card {
  flex: 1;
  min-height: 800px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.dialog-tree-card,
.dialog-form-card {
  height: 100%;
  min-height: 800px;
}

/** 查看详情：无树，描述列表 + 表格 */
.dialog-detail-body {
  height: 100%;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

::v-deep .dialog-detail-card.el-card {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

::v-deep .dialog-detail-card > .el-card__body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 12px;
  box-sizing: border-box;
}

.detail-desc {
  flex-shrink: 0;
}

.detail-desc--foot {
  margin-top: 8px;
}

.dialog-goods-table-wrap--detail {
  flex: 1;
  min-height: 0;
  margin: 12px 0;
  overflow: hidden;
}

.dialog-form-body {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  overflow: hidden;
}

.dialog-head-form {
  flex-shrink: 0;
}

.dialog-goods-toolbar {
  flex-shrink: 0;
  margin: 8px 0;
}

/** 明细表容器：吃掉剩余高度，由 el-table 内部 body 滚动 */
.dialog-goods-table-wrap {
  flex: 1;
  min-height: 400px;
  overflow: hidden;
}

.dialog-goods-table {
  width: 100%;
}

.dialog-footer-form {
  flex-shrink: 0;
  margin-top: 12px;
}

::v-deep .dialog-goods-table .el-table__body-wrapper .cell {
  padding-left: 6px;
  padding-right: 6px;
}

::v-deep .dialog-tree-card > .el-card__body {
  height: 100%;
  padding: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

::v-deep .dialog-form-card > .el-card__body {
  height: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

::v-deep .dialog-tree-inner.el-tree {
  flex: 1;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  padding: 8px 0;
}

/** 客户节点可点：鼠标小手 */
.tree-node--customer {
  cursor: pointer;
}

/** 禁用节点：鼠标默认 + 灰色 */
.tree-node--disabled {
  cursor: not-allowed;
  color: #c0c4cc;
}

/** 树高亮：浅蓝 */
::v-deep .sale-order-dialog .el-tree-node.is-current > .el-tree-node__content {
  background-color: #d9ecff !important;
}
</style>
