src/views/salesManagement/salesLedger/index.vue
@@ -6,7 +6,7 @@
          <el-input v-model="searchForm.customerName" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
        </el-form-item>
        <el-form-item label="销售合同号:">
        <el-form-item label="销售单号:">
          <el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search"
            @change="handleQuery" />
        </el-form-item>
@@ -51,11 +51,11 @@
                                              width="100px"
                                              align="center">
                <template #default="scope">
                           <el-tag v-if="scope.row.approveStatus === 1 && (!scope.row.shippingDate || !scope.row.shippingCarNumber)"
                                       type="success">充足</el-tag>
                           <el-tag v-else-if="scope.row.approveStatus === 0 && (scope.row.shippingDate || scope.row.shippingCarNumber)"
                                       type="success">已出库</el-tag>
                           <!-- 已发货显示已出库 -->
                           <el-tag v-if="scope.row.shippingDate" type="success">已出库</el-tag>
                           <!-- 未发货且库存充足 -->
                           <el-tag v-else-if="scope.row.approveStatus === 1" type="success">充足</el-tag>
                           <!-- 未发货且库存不足 -->
                           <el-tag v-else type="danger">不足</el-tag>
                </template>
              </el-table-column>
@@ -93,12 +93,11 @@
              <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
              <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
            <!--操作-->
              <el-table-column Width="60px" label="操作" align="center">
              <el-table-column width="100px" label="操作" align="center">
                <template #default="scope">
                  <el-button
                    link
                    type="primary"
                    size="small"
                  <el-button
                    link
                    type="primary"
                    :disabled="!canShip(scope.row)"
                    @click="openDeliveryForm(scope.row)">
                    发货
@@ -109,7 +108,7 @@
          </template>
        </el-table-column>
        <el-table-column align="center" label="序号" type="index" width="60" />
        <el-table-column label="销售合同号" prop="salesContractNo" width="180" show-overflow-tooltip />
        <el-table-column label="销售单号" prop="salesContractNo" width="180" show-overflow-tooltip />
        <el-table-column label="客户名称" prop="customerName" width="300" show-overflow-tooltip />
        <el-table-column label="业务员" prop="salesman" width="100" show-overflow-tooltip />
        <el-table-column label="项目名称" prop="projectName" width="180" show-overflow-tooltip />
@@ -121,12 +120,10 @@
        <el-table-column label="签订日期" prop="executionDate" width="120" show-overflow-tooltip />
        <el-table-column label="交付日期" prop="deliveryDate" width="120" show-overflow-tooltip />
        <el-table-column label="备注" prop="remarks" width="200" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="100" align="center">
        <el-table-column fixed="right" label="操作" width="130" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit">编辑</el-button>
<!--            <el-button link type="primary" size="small" @click="openForm('view', scope.row)">详情</el-button>-->
            <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">附件</el-button>
<!--            <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">发货</el-button>-->
            <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit">编辑</el-button>
            <el-button link type="primary" @click="downLoadFile(scope.row)">附件</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -146,7 +143,7 @@
            </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="销售合同号:" prop="salesContractNo">
            <el-form-item label="销售单号:" prop="salesContractNo">
              <el-input v-model="form.salesContractNo" placeholder="自动生成" clearable disabled />
            </el-form-item>
          </el-col>
@@ -237,7 +234,7 @@
               <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
               <el-table-column fixed="right" label="操作" min-width="60" align="center" v-if="operationType !== 'view'">
                  <template #default="scope">
                     <el-button link type="primary" size="small"
                     <el-button link type="primary" size="small"
                        :disabled="isProductShipped(scope.row)"
                        @click="openProductForm('edit', scope.row,scope.$index)">编辑</el-button>
                  </template>
@@ -295,7 +292,7 @@
            <el-button type="primary" @click="fetchQuotationList">搜索</el-button>
            <el-button @click="resetQuotationSearch">重置</el-button>
         </div>
         <el-table
            :data="quotationList"
            border
@@ -320,7 +317,7 @@
               </template>
            </el-table-column>
         </el-table>
         <pagination
            v-show="quotationPage.total > 0"
            :total="quotationPage.total"
@@ -329,7 +326,7 @@
            :limit="quotationPage.size"
            @pagination="quotationPaginationChange"
         />
         <template #footer>
            <el-button @click="quotationDialogVisible = false">关闭</el-button>
         </template>
@@ -485,7 +482,7 @@
                     <div class="header">
                        <div class="document-title">零售发货单</div>
                     </div>
                     <div class="info-section">
                        <div class="info-row">
                           <div>
@@ -506,7 +503,7 @@
                           <span class="value">{{ item.salesContractNo }}</span>
                        </div>
                     </div>
                     <div class="table-section">
                        <table class="product-table">
                           <thead>
@@ -544,7 +541,7 @@
                           </tfoot>
                        </table>
                     </div>
                     <div class="footer-section">
                        <div class="footer-row">
                           <div class="footer-item">
@@ -598,6 +595,79 @@
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="发货日期:" prop="shippingDate">
                     <el-date-picker
                        style="width: 100%"
                        v-model="deliveryForm.shippingDate"
                        value-format="YYYY-MM-DD"
                        format="YYYY-MM-DD"
                        type="date"
                        placeholder="请选择发货日期"
                        clearable
                     />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24" v-if="deliveryForm.type === '货车'">
                  <el-form-item label="发货车牌号:" prop="shippingCarNumber">
                     <el-input
                        v-model="deliveryForm.shippingCarNumber"
                        placeholder="请输入发货车牌号"
                        clearable
                     />
                  </el-form-item>
               </el-col>
               <el-col :span="24" v-else>
                  <el-form-item label="快递公司:" prop="expressCompany">
                     <el-input
                        v-model="deliveryForm.expressCompany"
                        placeholder="请输入快递公司"
                        clearable
                     />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30" v-if="deliveryForm.type === '快递'">
               <el-col :span="24">
                  <el-form-item label="快递单号:" prop="expressNumber">
                     <el-input
                        v-model="deliveryForm.expressNumber"
                        placeholder="请输入快递单号"
                        clearable
                     />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="发货图片:">
                     <el-upload
                        v-model:file-list="deliveryFileList"
                        :action="upload.url"
                        multiple
                        ref="deliveryFileUpload"
                        auto-upload
                        :headers="upload.headers"
                        :data="{ type: 9 }"
                        :on-success="handleDeliveryUploadSuccess"
                        :on-remove="handleDeliveryRemove"
                        list-type="picture-card"
                        :limit="9"
                        accept="image/png,image/jpeg,image/jpg"
                     >
                        <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
                        <template #tip>
                           <div class="el-upload__tip">
                              支持 jpg、jpeg、png 格式,最多上传 9 张,单张大小不超过 10MB
                           </div>
                        </template>
                     </el-upload>
                  </el-form-item>
               </el-col>
            </el-row>
        <!-- 审批人选择(仿协同审批里的审批人节点选择) -->
        <el-row>
@@ -633,7 +703,6 @@
                  <div>
                    <el-button
                      type="danger"
                      size="small"
                      @click="removeApproverNode(index)"
                      v-if="approverNodes.length > 1"
                    >删除</el-button>
@@ -646,8 +715,93 @@
         </el-form>
         <template #footer>
            <div class="dialog-footer">
               <el-button type="primary" @click="submitDelivery">确认发货</el-button>
               <el-button type="success" @click="submitOneClickDelivery">一键发货</el-button>
               <el-button type="primary" @click="submitDelivery">提交审批</el-button>
               <el-button @click="closeDeliveryDia">取消</el-button>
            </div>
         </template>
      </el-dialog>
      <!-- 批量一键发货弹框 -->
      <el-dialog
         v-model="batchDeliveryFormVisible"
         title="批量一键发货"
         width="40%"
         @close="closeBatchDeliveryDia"
      >
         <el-form :model="batchDeliveryForm" label-width="120px" label-position="top" :rules="batchDeliveryRules" ref="batchDeliveryFormRef">
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="发货类型:" prop="type">
                     <el-select
                        v-model="batchDeliveryForm.type"
                        placeholder="请选择发货类型"
                        style="width: 100%"
                     >
                        <el-option label="货车" value="货车" />
                        <el-option label="快递" value="快递" />
                     </el-select>
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="发货日期:" prop="shippingDate">
                     <el-date-picker
                        style="width: 100%"
                        v-model="batchDeliveryForm.shippingDate"
                        value-format="YYYY-MM-DD"
                        format="YYYY-MM-DD"
                        type="date"
                        placeholder="请选择发货日期"
                        clearable
                     />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24" v-if="batchDeliveryForm.type === '货车'">
                  <el-form-item label="发货车牌号:">
                     <el-input
                        v-model="batchDeliveryForm.shippingCarNumber"
                        placeholder="请输入发货车牌号"
                        clearable
                     />
                  </el-form-item>
               </el-col>
               <el-col :span="24" v-else>
                  <el-form-item label="快递公司:">
                     <el-input
                        v-model="batchDeliveryForm.expressCompany"
                        placeholder="请输入快递公司"
                        clearable
                     />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30" v-if="batchDeliveryForm.type === '快递'">
               <el-col :span="24">
                  <el-form-item label="快递单号:">
                     <el-input
                        v-model="batchDeliveryForm.expressNumber"
                        placeholder="请输入快递单号"
                        clearable
                     />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-alert
               title="提示:将对该销售台账下所有未发货的产品进行一键发货,自动审批通过并出库"
               type="warning"
               :closable="false"
               show-icon
               style="margin-top: 10px;"
            />
         </el-form>
         <template #footer>
            <div class="dialog-footer">
               <el-button type="success" @click="submitBatchDelivery">确认批量发货</el-button>
               <el-button @click="closeBatchDeliveryDia">取消</el-button>
            </div>
         </template>
      </el-dialog>
@@ -657,8 +811,9 @@
<script setup>
import { getToken } from "@/utils/auth";
import pagination from "@/components/PIMTable/Pagination.vue";
import {onMounted, ref, getCurrentInstance} from "vue";
import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
import {onMounted, ref, getCurrentInstance, h} from "vue";
import { ElButton } from "element-plus";
import { addShippingInfo, oneClickShipping, batchOneClickShipping } from "@/api/salesManagement/deliveryLedger.js";
import { ElMessageBox, ElMessage } from "element-plus";
import { UploadFilled, Download } from "@element-plus/icons-vue";
import useUserStore from "@/store/modules/user";
@@ -802,17 +957,61 @@
// 发货相关
const deliveryFormVisible = ref(false);
const currentDeliveryRow = ref(null);
// 批量一键发货相关
const batchDeliveryFormVisible = ref(false);
const currentBatchDeliveryRow = ref(null);
const batchDeliveryFormData = reactive({
  batchDeliveryForm: {
    type: "货车",
    shippingDate: "",
    shippingCarNumber: "",
    expressCompany: "",
    expressNumber: "",
  },
  batchDeliveryRules: {
    type: [
      { required: true, message: "请选择发货类型", trigger: "change" }
    ],
    shippingDate: [{ required: true, message: "请选择发货日期", trigger: "change" }],
  },
});
const { batchDeliveryForm, batchDeliveryRules } = toRefs(batchDeliveryFormData);
const deliveryFileList = ref([]);
const deliveryFormData = reactive({
  deliveryForm: {
    type: "货车", // 货车, 快递
    shippingDate: "",
    shippingCarNumber: "",
    expressCompany: "",
    expressNumber: "",
  },
  deliveryRules: {
    type: [
      { required: true, message: "请选择发货类型", trigger: "change" }
    ]
    ],
    shippingDate: [{ required: true, message: "请选择发货日期", trigger: "change" }],
    shippingCarNumber: [
      { validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur" }
    ],
    expressCompany: [
      { validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur" }
    ],
  },
});
const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
// 发货类型校验:货车时车牌非必填,快递时要求快递公司
const validateShippingCarNumber = (value, callback) => {
  // 取消车牌必填限制
  callback();
};
const validateExpressCompany = (value, callback) => {
  if (deliveryForm.value.type === "快递") {
    if (!value) return callback(new Error("请输入快递公司"));
  }
  callback();
};
// 发货审批人节点(仿协同审批 infoFormDia.vue)
const approverNodes = ref([{ id: 1, userId: null }]);
@@ -972,7 +1171,7 @@
      if (children && children.length > 0) {
         newItem.children = convertIdToValue(children);
      }
      return newItem;
   });
}
@@ -1003,6 +1202,8 @@
const expandChange = (row, expandedRows) => {
   if (expandedRows.length > 0) {
      expandedRowKeys.value = [];
      // 设置当前展开行,用于一键发货
      currentExpandedRow.value = row;
      try {
         productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
            const index = tableData.value.findIndex((item) => item.id === row.id);
@@ -1016,6 +1217,7 @@
      }
   } else {
      expandedRowKeys.value = [];
      currentExpandedRow.value = null;
   }
};
@@ -1043,13 +1245,58 @@
      "taxExclusiveTotalPrice",
   ]);
};
// 子表合计方法
// 当前展开行的销售台账数据(用于一键发货)
const currentExpandedRow = ref(null);
// 当前展开行是否有未发货产品
const hasUnshippedProducts = ref(false);
// 子表合计方法 - 最后一列显示一键发货按钮
const summarizeChildrenTable = (param) => {
   return proxy.summarizeTable(param, [
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
   ]);
   const { columns, data } = param;
   const sums = [];
   // 检查是否有未发货的产品
   const unshipped = data.filter(item => {
      const status = item.shippingStatus;
      return !item.shippingDate && (!status || status === '待发货' || status === '审核拒绝');
   });
   hasUnshippedProducts.value = unshipped.length > 0;
   columns.forEach((column, index) => {
      if (index === 0) {
         sums[index] = "合计";
         return;
      }
      const prop = column.property;
      const summaryProps = ["taxInclusiveUnitPrice", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice"];
      if (summaryProps.includes(prop)) {
         const values = data.map((item) => Number(item[prop]));
         if (!values.every(isNaN)) {
            const sum = values.reduce((acc, val) => (!isNaN(val) ? acc + val : acc), 0);
            sums[index] = parseFloat(sum).toFixed(2);
         } else {
            sums[index] = "";
         }
      } else if (index === columns.length - 1 && currentExpandedRow.value && hasUnshippedProducts.value) {
         // 最后一列(操作列)渲染一键发货按钮,仅当有未发货产品时显示
         sums[index] = h(
            ElButton,
            {
               type: 'success',
               size: 'small',
               onClick: () => openBatchDeliveryForm(currentExpandedRow.value)
            },
            { default: () => '一键发货' }
         );
      } else {
         sums[index] = "";
      }
   });
   return sums;
};
// 打开弹框
const openForm = async (type, row) => {
@@ -1141,10 +1388,10 @@
const applyQuotation = (row) => {
   if (!row) return;
   selectedQuotation.value = row;
   // 业务员
   form.value.salesman = (row.salesperson || "").trim();
   // 客户名称 -> customerId
   const qCustomerName = String(row.customer || "").trim();
   const customer = (customerOption.value || []).find((c) => {
@@ -1157,7 +1404,7 @@
      // 如果找不到,保留原值(允许用户手动选择/不打断已有输入)
      form.value.customerId = form.value.customerId || "";
   }
   // 产品信息映射:报价 products -> 台账 productData
   const products = Array.isArray(row.products) ? row.products : [];
   productData.value = products.map((p) => {
@@ -1179,7 +1426,7 @@
         invoiceType: "增普票",
      };
   });
   quotationDialogVisible.value = false;
};
function changs(val) {
@@ -1241,6 +1488,7 @@
         addOrUpdateSalesLedger(form.value).then((res) => {
            proxy.$modal.msgSuccess("提交成功");
            closeDia();
            expandedRowKeys.value = [];
            getList();
         });
      }
@@ -1260,7 +1508,7 @@
      proxy.$modal.msgWarning("已发货或审核通过的产品不能编辑");
      return;
   }
   productOperationType.value = type;
   productForm.value = {};
   proxy.resetForm("productFormRef");
@@ -1327,14 +1575,14 @@
      proxy.$modal.msgWarning("请选择数据");
      return;
   }
   // 检查是否有已发货或审核通过的产品
   const shippedProducts = productSelectedRows.value.filter(row => isProductShipped(row));
   if (shippedProducts.length > 0) {
      proxy.$modal.msgWarning("已发货或审核通过的产品不能删除");
      return;
   }
   if (operationType.value === "add") {
      productSelectedRows.value.forEach((selectedRow) => {
         const index = productData.value.findIndex(
@@ -1480,25 +1728,25 @@
      proxy.$modal.msgWarning("请选择要打印的数据");
      return;
   }
   // 显示加载状态
   proxy.$modal.loading("正在获取产品数据,请稍候...");
   try {
      // 为每个选中的销售台账记录查询对应的产品数据
      const printDataWithProducts = [];
      for (const row of selectedRows.value) {
         try {
            // 调用productList接口查询产品数据
            const productRes = await productList({ salesLedgerId: row.id, type: 1 });
            // 将产品数据整合到销售台账记录中
            const rowWithProducts = {
               ...row,
               products: productRes.data || []
            };
            printDataWithProducts.push(rowWithProducts);
         } catch (error) {
            console.error(`获取销售台账 ${row.id} 的产品数据失败:`, error);
@@ -1509,11 +1757,11 @@
            });
         }
      }
      printData.value = printDataWithProducts;
      console.log('打印数据(包含产品):', printData.value);
      printPreviewVisible.value = true;
   } catch (error) {
      console.error('获取产品数据失败:', error);
      proxy.$modal.msgError("获取产品数据失败,请重试");
@@ -1525,10 +1773,10 @@
const executePrint = () => {
   console.log('开始执行打印,数据条数:', printData.value.length);
   console.log('打印数据:', printData.value);
   // 创建一个新的打印窗口
   const printWindow = window.open('', '_blank', 'width=800,height=600');
   // 构建打印内容
   let printContent = `
    <!DOCTYPE html>
@@ -1664,7 +1912,7 @@
    </head>
    <body>
  `;
   // 为每条数据生成打印页面
   printData.value.forEach((item, index) => {
      printContent += `
@@ -1673,7 +1921,7 @@
          <div class="header">
            <div class="document-title">零售发货单</div>
          </div>
          <div class="info-section">
            <div class="info-row">
              <div>
@@ -1761,16 +2009,16 @@
      </div>
    `;
   });
   printContent += `
    </body>
    </html>
  `;
   // 写入内容到新窗口
   printWindow.document.write(printContent);
   printWindow.document.close();
   // 等待内容加载完成后打印
   printWindow.onload = () => {
      setTimeout(() => {
@@ -1861,19 +2109,19 @@
// 根据含税总价计算含税单价和数量
const calculateFromTotalPrice = () => {
   if (isCalculating.value) return;
   const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
   const quantity = parseFloat(productForm.value.quantity);
   if (!totalPrice || !quantity || quantity <= 0) {
      return;
   }
   isCalculating.value = true;
   // 计算含税单价 = 含税总价 / 数量
   productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
@@ -1882,7 +2130,7 @@
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};
@@ -1893,25 +2141,25 @@
      return;
   }
   if (isCalculating.value) return;
   const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
   const quantity = parseFloat(productForm.value.quantity);
   const taxRate = parseFloat(productForm.value.taxRate);
   if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
      return;
   }
   isCalculating.value = true;
   // 先计算含税总价 = 不含税总价 / (1 - 税率/100)
   const taxRateDecimal = taxRate / 100;
   const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
   productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
   // 计算含税单价 = 含税总价 / 数量
   productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
   isCalculating.value = false;
};
@@ -1922,19 +2170,19 @@
      return;
   }
   if (isCalculating.value) return;
   const quantity = parseFloat(productForm.value.quantity);
   const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   isCalculating.value = true;
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
@@ -1943,7 +2191,7 @@
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};
@@ -1954,19 +2202,19 @@
      return;
   }
   if (isCalculating.value) return;
   const quantity = parseFloat(productForm.value.quantity);
   const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   isCalculating.value = true;
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
@@ -1975,7 +2223,7 @@
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};
@@ -1986,23 +2234,23 @@
      return;
   }
   if (isCalculating.value) return;
   const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
   const taxRate = parseFloat(productForm.value.taxRate);
   if (!inclusiveTotalPrice || !taxRate) {
      return;
   }
   isCalculating.value = true;
   // 计算不含税总价
   productForm.value.taxExclusiveTotalPrice =
      proxy.calculateTaxExclusiveTotalPrice(
         inclusiveTotalPrice,
         taxRate
      );
   isCalculating.value = false;
};
/**
@@ -2014,15 +2262,15 @@
   if (row.shippingDate || row.shippingCarNumber) {
      return '已发货';
   }
   // 获取发货状态字段
   const status = row.shippingStatus;
   // 如果状态为空或未定义,默认为"待发货"
   if (status === null || status === undefined || status === '') {
      return '待发货';
   }
   // 状态是字符串
   const statusStr = String(status).trim();
   const statusTextMap = {
@@ -2045,15 +2293,15 @@
   if (row.shippingDate || row.shippingCarNumber) {
      return 'success';
   }
   // 获取发货状态字段
   const status = row.shippingStatus;
   // 如果状态为空或未定义,默认为灰色(待发货)
   if (status === null || status === undefined || status === '') {
      return 'info';
   }
   // 状态是字符串
   const statusStr = String(status).trim();
   const typeTextMap = {
@@ -2077,15 +2325,15 @@
   if (row.approveStatus !== 1) {
      return false;
   }
   // 获取发货状态
   const shippingStatus = row.shippingStatus;
   // 如果已发货(有发货日期或车牌号),不能再次发货
   if (row.shippingDate || row.shippingCarNumber) {
      return false;
   }
   // 发货状态必须是"待发货"或"审核拒绝"
   const statusStr = shippingStatus ? String(shippingStatus).trim() : '';
   return statusStr === '待发货' || statusStr === '审核拒绝';
@@ -2113,15 +2361,35 @@
      proxy.$modal.msgWarning("只有在产品状态是充足,发货状态是待发货或审核拒绝的时候才可以发货");
      return;
   }
   currentDeliveryRow.value = row;
  deliveryForm.value = {
    type: "货车",
    shippingDate: getCurrentDate(),
    shippingCarNumber: "",
    expressCompany: "",
    expressNumber: "",
  };
  deliveryFileList.value = [];
  // 重置审批人节点(默认一个空节点)
  approverNodes.value = [{ id: 1, userId: null }];
  nextApproverId = 2;
   deliveryFormVisible.value = true;
};
// 发货图片上传成功回调
const handleDeliveryUploadSuccess = (res, file, uploadFiles) => {
   if (res.code === 200) {
      file.tempId = res.data.tempId;
      proxy.$modal.msgSuccess("上传成功");
   } else {
      proxy.$modal.msgError(res.msg);
   }
};
// 移除发货图片
const handleDeliveryRemove = (file) => {
   // 文件移除时自动从 fileList 中删除,无需额外处理
};
// 提交发货表单
@@ -2138,10 +2406,22 @@
      // 保存当前展开的行ID,以便发货后重新加载子表格数据
      const currentExpandedKeys = [...expandedRowKeys.value];
      const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
      // 获取上传图片的临时ID
      let tempFileIds = [];
      if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) {
        tempFileIds = deliveryFileList.value.map((item) => item.tempId);
      }
      addShippingInfo({
        salesLedgerId: salesLedgerId,
        salesLedgerProductId: currentDeliveryRow.value.id,
        type: deliveryForm.value.type,
        shippingDate: deliveryForm.value.shippingDate,
        shippingCarNumber: deliveryForm.value.type === "货车" ? deliveryForm.value.shippingCarNumber : "",
        expressCompany: deliveryForm.value.type === "快递" ? deliveryForm.value.expressCompany : "",
        expressNumber: deliveryForm.value.type === "快递" ? deliveryForm.value.expressNumber : "",
        tempFileIds: tempFileIds,
            approveUserIds,
      })
        .then(() => {
@@ -2171,12 +2451,124 @@
  });
};
// 一键发货 - 自动审批通过并出库
const submitOneClickDelivery = () => {
  proxy.$refs["deliveryFormRef"].validate((valid) => {
    if (valid) {
      // 保存当前展开的行ID,以便发货后重新加载子表格数据
      const currentExpandedKeys = [...expandedRowKeys.value];
      const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
      // 获取上传图片的临时ID
      let tempFileIds = [];
      if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) {
        tempFileIds = deliveryFileList.value.map((item) => item.tempId);
      }
      oneClickShipping({
        salesLedgerId: salesLedgerId,
        salesLedgerProductId: currentDeliveryRow.value.id,
        type: deliveryForm.value.type,
        shippingDate: deliveryForm.value.shippingDate,
        shippingCarNumber: deliveryForm.value.type === "货车" ? deliveryForm.value.shippingCarNumber : "",
        expressCompany: deliveryForm.value.type === "快递" ? deliveryForm.value.expressCompany : "",
        expressNumber: deliveryForm.value.type === "快递" ? deliveryForm.value.expressNumber : "",
        tempFileIds: tempFileIds,
      })
        .then(() => {
          proxy.$modal.msgSuccess("一键发货成功");
          closeDeliveryDia();
          // 刷新主表数据
          getList().then(() => {
            // 如果之前有展开的行,重新加载这些行的子表格数据
            if (currentExpandedKeys.length > 0) {
              const loadPromises = currentExpandedKeys.map(ledgerId => {
                return productList({ salesLedgerId: ledgerId, type: 1 }).then((res) => {
                  const index = tableData.value.findIndex((item) => item.id === ledgerId);
                  if (index > -1) {
                    tableData.value[index].children = res.data;
                  }
                });
              });
              Promise.all(loadPromises).then(() => {
                expandedRowKeys.value = currentExpandedKeys;
              });
            }
          });
        })
    }
  });
};
// 关闭发货弹框
const closeDeliveryDia = () => {
  proxy.resetForm("deliveryFormRef");
  deliveryFileList.value = [];
  deliveryFormVisible.value = false;
  currentDeliveryRow.value = null;
};
// 打开批量一键发货弹框
const openBatchDeliveryForm = (row) => {
  currentBatchDeliveryRow.value = row;
  batchDeliveryForm.value = {
    type: "货车",
    shippingDate: getCurrentDate(),
    shippingCarNumber: "",
    expressCompany: "",
    expressNumber: "",
  };
  batchDeliveryFormVisible.value = true;
};
// 关闭批量发货弹框
const closeBatchDeliveryDia = () => {
  proxy.resetForm("batchDeliveryFormRef");
  batchDeliveryFormVisible.value = false;
  currentBatchDeliveryRow.value = null;
};
// 提交批量一键发货
const submitBatchDelivery = () => {
  proxy.$refs["batchDeliveryFormRef"].validate((valid) => {
    if (valid) {
      // 保存当前展开的行ID
      const currentExpandedKeys = [...expandedRowKeys.value];
      const salesLedgerId = currentBatchDeliveryRow.value.id;
      batchOneClickShipping({
        salesLedgerId: salesLedgerId,
        type: batchDeliveryForm.value.type,
        shippingDate: batchDeliveryForm.value.shippingDate,
        shippingCarNumber: batchDeliveryForm.value.type === "货车" ? batchDeliveryForm.value.shippingCarNumber : "",
        expressCompany: batchDeliveryForm.value.type === "快递" ? batchDeliveryForm.value.expressCompany : "",
        expressNumber: batchDeliveryForm.value.type === "快递" ? batchDeliveryForm.value.expressNumber : "",
      })
        .then(() => {
          proxy.$modal.msgSuccess("批量发货成功");
          closeBatchDeliveryDia();
          // 刷新主表数据
          getList().then(() => {
            // 如果之前有展开的行,重新加载这些行的子表格数据
            if (currentExpandedKeys.length > 0) {
              const loadPromises = currentExpandedKeys.map(ledgerId => {
                return productList({ salesLedgerId: ledgerId, type: 1 }).then((res) => {
                  const index = tableData.value.findIndex((item) => item.id === ledgerId);
                  if (index > -1) {
                    tableData.value[index].children = res.data;
                  }
                });
              });
              Promise.all(loadPromises).then(() => {
                expandedRowKeys.value = currentExpandedKeys;
              });
            }
          });
        })
    }
  });
};
const currentFactoryName = ref("");
const getCurrentFactoryName = async () => {
   let res = await userStore.getInfo();
@@ -2196,19 +2588,19 @@
   margin-left: 10px;
}
::v-deep .yellow {
:deep(.yellow) {
  background-color: #FAF0DE;
}
::v-deep .pink {
:deep(.pink) {
  background-color: #FAE1DE;
}
::v-deep .red {
:deep(.red) {
  background-color: #FAE1DE;
}
::v-deep .purple{
:deep(.purple){
  background-color: #F4DEFA;
}
@@ -2234,12 +2626,12 @@
      padding: 15px;
      border-bottom: 1px solid #e4e7ed;
      text-align: center;
      .el-button {
         margin: 0 10px;
      }
   }
   .print-preview-content {
      padding: 20px;
      background-color: #f5f5f5;
@@ -2271,13 +2663,13 @@
.header {
   text-align: center;
   margin-bottom: 8px;
   .company-name {
      font-size: 18px;
      font-weight: bold;
      margin-bottom: 4px;
   }
   .document-title {
      font-size: 16px;
      font-weight: bold;
@@ -2289,16 +2681,16 @@
   display: flex;
   justify-content: space-between;
   align-items: center;
   .info-row {
      line-height: 20px;
      .label {
         font-weight: bold;
         width: 60px;
         font-size: 14px;
      }
      .value {
         margin-right: 20px;
         min-width: 80px;
@@ -2310,12 +2702,12 @@
.table-section {
   margin-bottom: 4px;
   flex: 1;
   .product-table {
      width: 100%;
      border-collapse: collapse;
      border: 1px solid #000;
      th, td {
         border: 1px solid #000;
         padding: 6px;
@@ -2323,16 +2715,16 @@
         font-size: 14px;
         line-height: 1.4;
      }
      th {
         font-weight: bold;
      }
      .total-label {
         text-align: right;
         font-weight: bold;
      }
      .total-value {
         font-weight: bold;
      }
@@ -2345,22 +2737,22 @@
      margin-bottom: 3px;
      line-height: 20px;
      justify-content: space-between;
      .footer-item {
         display: flex;
         margin-right: 20px;
         .label {
            font-weight: bold;
            width: 80px;
            font-size: 14px;
         }
         .value {
            min-width: 80px;
            font-size: 14px;
         }
         &.address-item {
            .address-value {
               min-width: 200px;
@@ -2374,7 +2766,7 @@
   .app-container {
      display: none;
   }
   .print-page {
      box-shadow: none;
      margin: 0;