gongchunyi
2026-09-29 eee1310bc134b2bb7c8a406750cb64e9fe226ac2
src/views/salesManagement/salesLedger/index.vue
@@ -24,6 +24,18 @@
                    prefix-icon="Search"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="发货状态:">
          <el-select v-model="searchForm.shippingStatus"
                     placeholder="请选择"
                     clearable
                     style="width: 160px"
                     @change="handleQuery">
            <el-option label="未发货"
                       value="未发货" />
            <el-option label="已发货"
                       value="已发货" />
          </el-select>
        </el-form-item>
        <el-form-item label="录入日期:">
          <el-date-picker v-model="searchForm.entryDate"
                          value-format="YYYY-MM-DD"
@@ -96,6 +108,8 @@
                               prop="specificationModel" />
              <el-table-column label="单位"
                               prop="unit" />
              <el-table-column label="件数"
                               prop="packagingSpec" />
              <el-table-column label="产品状态"
                               width="100px"
                               align="center">
@@ -118,6 +132,21 @@
                  <el-tag :type="getShippingStatusType(scope.row)"
                          size="small">
                    {{ getShippingStatusText(scope.row) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column label="发货类型"
                               width="100"
                               align="center">
                <template #default="scope">
                  <el-tag v-if="getShippingTypeText(scope.row)"
                          :type="getShippingTypeTag(scope.row)"
                          size="small">
                    {{ getShippingTypeText(scope.row) }}
                  </el-tag>
                  <el-tag v-else
                          type="info"
                          size="small">-
                  </el-tag>
                </template>
              </el-table-column>
@@ -241,15 +270,21 @@
                       type="primary"
                       @click="openForm('view', scope.row)">详情
            </el-button>
            <el-button link
                       type="primary"
                       @click="openForm('edit', scope.row)"
                       :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">编辑
            </el-button>
            <el-tooltip :content="editDisabledReason(scope.row)"
                        :disabled="!editDisabledReason(scope.row)"
                        placement="top">
              <span>
                <el-button link
                           type="primary"
                           @click="openForm('edit', scope.row)"
                           :disabled="isLedgerEditDisabled(scope.row)">编辑
                </el-button>
              </span>
            </el-tooltip>
            <el-button link
                       type="primary"
                       @click="openFileDialog(scope.row)">附件
            </el-button>
            </el-button> <!--downloadOrder(scope.row.id) 下载-->
          </template>
        </el-table-column>
      </el-table>
@@ -329,7 +364,7 @@
                           :label="item.customerName"
                           :value="item.id">
                  {{
                    item.customerName + "——" + item.taxpayerIdentificationNumber
                    item.taxpayerIdentificationNumber ? item.customerName + "——" + item.taxpayerIdentificationNumber : item.customerName
                  }}
                </el-option>
              </el-select>
@@ -378,7 +413,7 @@
                         :reserve-keyword="false"
                         placeholder="请选择"
                         clearable
                         :disabled="operationType === 'view'"
                         disabled
                         @change="changs">
                <el-option v-for="item in userList"
                           :key="item.userId"
@@ -450,6 +485,8 @@
                           prop="specificationModel" />
          <el-table-column label="单位"
                           prop="unit" />
          <el-table-column label="件数"
                           prop="packagingSpec" />
          <el-table-column label="数量"
                           prop="quantity" />
          <el-table-column label="税率(%)"
@@ -604,35 +641,22 @@
               :rules="productRules"
               ref="productFormRef">
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="产品大类:"
                          prop="productCategory">
              <el-tree-select v-model="productForm.productCategory"
                              placeholder="请选择"
                              clearable
                              filterable
                              check-strictly
                              @change="getModels"
                              :data="productOptions"
                              :render-after-expand="false"
                              style="width: 100%" />
          <el-col :span="12">
            <el-form-item label="产品大类:" prop="productCategory">
              <el-input v-model="productForm.productCategory"
                        placeholder="点击选择"
                        readonly
                        @click="showProductSelectDialog = true"
                        style="cursor:pointer" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="规格型号:"
                          prop="productModelId">
              <el-select v-model="productForm.productModelId"
                         placeholder="请选择"
                         clearable
                         @change="getProductModel"
                         filterable>
                <el-option v-for="item in modelOptions"
                           :key="item.id"
                           :label="item.model"
                           :value="item.id" />
              </el-select>
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="productModelId">
              <el-input v-model="productForm.specificationModel"
                        placeholder="点击选择"
                        readonly
                        @click="showProductSelectDialog = true"
                        style="cursor:pointer" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -657,6 +681,15 @@
                           :label="dict.label"
                           :value="dict.value" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="件数:"
                          prop="packagingSpec">
              <el-input v-model="productForm.packagingSpec"
                        clearable />
            </el-form-item>
          </el-col>
        </el-row>
@@ -726,12 +759,12 @@
            <el-form-item label="是否生产:"
                          prop="isProduction">
              <div style="display: flex; align-items: center; width: 100%;">
                <el-radio-group v-model="productForm.isProduction">
                  <el-radio label="是"
                            :value="true" />
                  <el-radio label="否"
                            :value="false" />
                </el-radio-group>
              <el-radio-group v-model="productForm.isProduction">
                <el-radio label="是"
                          :value="true" />
                <el-radio label="否"
                          :value="false" />
              </el-radio-group>
                <div 
                  v-if="currentStock !== null" 
                  :style="{
@@ -757,6 +790,9 @@
        </el-row>
      </el-form>
    </FormDialog>
    <ProductSelectDialog v-model="showProductSelectDialog"
                         @confirm="handleProductSelect"
                         single />
    <!-- 导入弹窗 -->
    <FormDialog v-model="importUpload.open"
                :title="importUpload.title"
@@ -920,7 +956,7 @@
    <!-- 发货弹框 -->
    <el-dialog v-model="deliveryFormVisible"
               title="发货信息"
               width="40%"
               width="960px"
               @close="closeDeliveryDia">
      <el-form :model="deliveryForm"
               label-width="120px"
@@ -939,6 +975,8 @@
                           value="货车" />
                <el-option label="快递"
                           value="快递" />
                <el-option label="自送"
                           value="自送" />
              </el-select>
            </el-form-item>
          </el-col>
@@ -948,10 +986,16 @@
                        disabled />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="已选择发货数量:">
              <el-input :model-value="selectedDeliveryQuantity"
                        disabled />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="30">
          <el-col :span="24"
                  v-if="deliveryForm.type === '货车'">
        <el-row :gutter="30"
                v-if="deliveryForm.type === '货车'">
          <el-col :span="24">
            <el-form-item label="发货车牌号:"
                          prop="shippingCarNumber">
              <el-input v-model="deliveryForm.shippingCarNumber"
@@ -959,8 +1003,10 @@
                        clearable />
            </el-form-item>
          </el-col>
          <el-col :span="24"
                  v-else-if="false">
        </el-row>
        <el-row :gutter="30"
                v-else-if="deliveryForm.type === '快递'">
          <el-col :span="24">
            <el-form-item label="快递公司:"
                          prop="expressCompany">
              <el-input v-model="deliveryForm.expressCompany"
@@ -970,7 +1016,7 @@
          </el-col>
        </el-row>
        <el-row :gutter="30"
                >
                v-if="deliveryForm.type === '快递'">
          <el-col :span="24">
            <el-form-item label="快递单号:"
                          prop="expressNumber">
@@ -1000,6 +1046,13 @@
                <el-table-column label="批号"
                                 prop="batchNo"
                                 min-width="180" />
                <el-table-column label="销售订单号"
                                 min-width="180"
                                 show-overflow-tooltip>
                  <template #default="scope">
                    {{ formatDeliveryBatchSalesOrderNo(scope.row) }}
                  </template>
                </el-table-column>
                <el-table-column label="产品大类"
                                 prop="productName"
                                 min-width="100" />
@@ -1023,8 +1076,6 @@
                    <el-input-number v-model="scope.row.deliveryQuantity"
                                     :min="0"
                                     :max="getDeliveryBatchDeliveryMax(scope.row)"
                                     :precision="2"
                                     :step="0.01"
                                     controls-position="right"
                                     @change="handleDeliveryBatchQuantityChange(scope.row)"
                                     style="width: 100%;" />
@@ -1069,7 +1120,9 @@
    delProduct,
    delLedgerFile,
    getProductInventory,
    getPrintData,
  } from "@/api/salesManagement/salesLedger.js";
  import { downloadSalesJpg, printSalesMulti } from "@/utils/documentPrint.js";
  import { getStockInventoryByModelId } from "@/api/inventoryManagement/stockInventory.js";
  import { modelList, productTreeList } from "@/api/basicData/product.js";
  import useFormData from "@/hooks/useFormData.js";
@@ -1079,8 +1132,10 @@
    tableAmountFormatter,
    formatDecimal,
    buildAmountSummaryFormat,
    roundAmount,
  } from "@/utils/numberFormat";
  import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
  import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
  import { getCurrentDate } from "@/utils/index.js";
  import { listCustomer } from "@/api/basicData/customer.js";
@@ -1109,6 +1164,7 @@
  const total = ref(0);
  const fileList = ref([]);
  const deliveryFileList = ref([]);
  const showProductSelectDialog = ref(false);
  // 用户信息表单弹框数据
  const operationType = ref("");
@@ -1117,6 +1173,8 @@
    searchForm: {
      customerName: "", // 客户名称
      salesContractNo: "", // 销售合同编号
      projectName: "", // 项目名称
      shippingStatus: "", // 发货状态(未发货/已发货)
      entryDate: null, // 录入日期
      entryDateStart: undefined,
      entryDateEnd: undefined,
@@ -1151,9 +1209,12 @@
  const currentId = ref("");
  const productFormData = reactive({
    productForm: {
      productId: "",
      productCategory: "",
      productModelId: "",
      specificationModel: "",
      unit: "",
      packagingSpec: "",
      quantity: "",
      taxInclusiveUnitPrice: "",
      taxRate: "",
@@ -1163,11 +1224,8 @@
      isProduction: false,
    },
    productRules: {
      productCategory: [{ required: true, message: "请选择", trigger: "change" }],
      productModelId: [{ required: true, message: "请选择", trigger: "change" }],
      specificationModel: [
        { required: true, message: "请选择", trigger: "change" },
      ],
      productCategory: [{ required: true, message: "请选择产品大类", trigger: "change" }],
      productModelId: [{ required: true, message: "请选择规格型号", trigger: "change" }],
      unit: [{ required: true, message: "请输入", trigger: "blur" }],
      quantity: [{ required: true, message: "请输入", trigger: "blur" }],
      taxInclusiveUnitPrice: [
@@ -1221,6 +1279,8 @@
      item?.stockQuantity;
    return quantity ?? 0;
  };
  const formatDeliveryBatchSalesOrderNo = item =>
    item?.salesContractNo || "--";
  const currentStock = ref(null);
  const fetchCurrentStock = async (productModelId) => {
    if (!productModelId) {
@@ -1228,7 +1288,7 @@
      return;
    }
    try {
      const res = await getStockInventoryByModelId(productModelId);
      const res = await getStockInventoryByModelId(productModelId, currentId.value);
      const rawList = Array.isArray(res?.data)
        ? res.data
        : res?.data?.records || res?.data?.rows || [];
@@ -1236,7 +1296,7 @@
      rawList.forEach(item => {
        total += Number(getDeliveryBatchQuantity(item) || 0);
      });
      currentStock.value = total;
      currentStock.value = roundAmount(total);
    } catch (e) {
      console.error(e);
      currentStock.value = 0;
@@ -1245,35 +1305,45 @@
  const getCurrentDeliveryRowQuantity = () => {
    return Number(currentDeliveryRow.value?.noQuantity || 0);
  };
  const selectedDeliveryQuantity = computed(() => {
    return roundAmount(
      (deliveryForm.value.batchNoList || []).reduce(
        (sum, item) => sum + Number(item?.deliveryQuantity || 0),
        0
      )
    );
  });
  const getDeliveryBatchDeliveryMax = row => {
    const productQuantity = getCurrentDeliveryRowQuantity();
    const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
    const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
      (sum, item) => {
        if (item?.id === row?.id) return sum;
        return sum + Number(item?.deliveryQuantity || 0);
      },
      0
    const otherBatchTotal = roundAmount(
      (deliveryForm.value.batchNoList || []).reduce(
        (sum, item) => {
          if (item?.id === row?.id) return sum;
          return sum + Number(item?.deliveryQuantity || 0);
        },
        0
      )
    );
    const remainingProductQuantity = Math.max(
      0,
      productQuantity - otherBatchTotal
    const remainingProductQuantity = roundAmount(
      Math.max(0, productQuantity - otherBatchTotal)
    );
    return Math.max(0, Math.min(batchQuantity, remainingProductQuantity));
  };
  const handleDeliveryBatchQuantityChange = row => {
    const productQuantity = getCurrentDeliveryRowQuantity();
    const batchQuantity = Number(getDeliveryBatchQuantity(row) || 0);
    const otherBatchTotal = (deliveryForm.value.batchNoList || []).reduce(
      (sum, item) => {
        if (item?.id === row?.id) return sum;
        return sum + Number(item?.deliveryQuantity || 0);
      },
      0
    const otherBatchTotal = roundAmount(
      (deliveryForm.value.batchNoList || []).reduce(
        (sum, item) => {
          if (item?.id === row?.id) return sum;
          return sum + Number(item?.deliveryQuantity || 0);
        },
        0
      )
    );
    const remainingProductQuantity = Math.max(
      0,
      productQuantity - otherBatchTotal
    const remainingProductQuantity = roundAmount(
      Math.max(0, productQuantity - otherBatchTotal)
    );
    const currentValue = Number(row?.deliveryQuantity || 0);
@@ -1290,9 +1360,9 @@
      item => Number(item?.deliveryQuantity || 0) > 0
    );
  };
  const getDeliveryBatchNoList = async productModelId => {
  const getDeliveryBatchNoList = async (productModelId, salesLedgerId) => {
    if (!productModelId) return [];
    const res = await getStockInventoryByModelId(productModelId);
    const res = await getStockInventoryByModelId(productModelId, salesLedgerId);
    const rawList = Array.isArray(res?.data)
      ? res.data
      : res?.data?.records || res?.data?.rows || [];
@@ -1327,7 +1397,7 @@
      shippingCarNumber: "",
      expressCompany: "",
      expressNumber: "",
      type: "货车", // 货车, 快递
      type: "货车", // 货车, 快递, 自送
    },
    deliveryRules: {
      shippingCarNumber: [
@@ -1493,11 +1563,35 @@
  };
  const canEditLedger = row => isCurrentUserMaintainer(row);
  const canDeleteLedger = row => isCurrentUserMaintainer(row);
  /**
   * 需要生产的订单:生产计划已下发(含部分下发)后不可编辑;
   * 走库存的订单:已发货后不可编辑,否则可以编辑。
   */
  const editDisabledReason = row => {
    if (!row) return "";
    if (!canEditLedger(row)) return "当前系统登录人不是维护人,不能编辑数据";
    if (row.hasProductionRecord) return "生产计划已下发,不能编辑";
    if (!row.isEdit) return "订单已发货,不能编辑";
    return "";
  };
  const isLedgerEditDisabled = row => !!editDisabledReason(row);
  const sensitiveAmountFormatter = (row, column, cellValue) => {
    if (!isCurrentUserMaintainer(row)) {
      return "*****";
    }
    return formattedNumber(row, column, cellValue);
  };
  // ProductSelectDialog 选中回调
  const handleProductSelect = (products) => {
    if (!products || !products.length) return;
    const p = products[0];
    productForm.value.productId = p.productId;
    productForm.value.productCategory = p.productName || '';
    productForm.value.productModelId = p.id;
    productForm.value.specificationModel = p.model || '';
    productForm.value.unit = p.unit || '';
    fetchCurrentStock(productForm.value.productModelId);
    showProductSelectDialog.value = false;
  };
  // 获取tree子数据
  const getModels = value => {
@@ -1615,9 +1709,9 @@
      param,
      ["contractAmount", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice"],
      buildAmountSummaryFormat([
        "contractAmount",
        "taxInclusiveTotalPrice",
        "taxExclusiveTotalPrice",
      "contractAmount",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
      ])
    );
  };
@@ -1644,9 +1738,9 @@
    return proxy.summarizeTable(
      param,
      [
        "taxInclusiveUnitPrice",
        "taxInclusiveTotalPrice",
        "taxExclusiveTotalPrice",
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
      ],
      buildAmountSummaryFormat([
        "taxInclusiveUnitPrice",
@@ -1657,9 +1751,12 @@
  };
  // 打开弹框
  const openForm = async (type, row) => {
    if (type === "edit" && row && !canEditLedger(row)) {
      proxy.$modal.msgWarning("当前系统登录人不是维护人,不能编辑数据");
      return;
    if (type === "edit" && row) {
      const disabledReason = editDisabledReason(row);
      if (disabledReason) {
        proxy.$modal.msgWarning(disabledReason);
        return;
      }
    }
    operationType.value = type;
    form.value = {};
@@ -2082,359 +2179,31 @@
      });
  };
  // 打印功能
  // 打印功能 - 多选合并预览
  const handlePrint = async () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择要打印的数据");
      return;
    }
    // 显示加载状态
    proxy.$modal.loading("正在获取产品数据,请稍候...");
    proxy.$modal.loading("正在加载打印数据...");
    try {
      // 为每个选中的销售台账记录查询对应的产品数据
      const printDataWithProducts = [];
      const orders = [];
      let companyName = '';
      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);
          // 即使某个记录的产品数据获取失败,也要包含该记录
          printDataWithProducts.push({
            ...row,
            products: [],
          });
        const res = await getPrintData(row.id);
        const data = res.data || res;
        companyName = data.companyName || companyName;
        orders.push(data.ledger);
        }
      }
      printData.value = printDataWithProducts;
      console.log("打印数据(包含产品):", printData.value);
      printPreviewVisible.value = true;
    } catch (error) {
      console.error("获取产品数据失败:", error);
      proxy.$modal.msgError("获取产品数据失败,请重试");
      printSalesMulti(companyName, orders);
    } catch (e) {
      console.error('打印失败:', e);
      proxy.$modal.msgError("打印失败");
    } finally {
      proxy.$modal.closeLoading();
    }
  };
  // 执行打印
  const executePrint = () => {
    console.log("开始执行打印,数据条数:", printData.value.length);
    console.log("打印数据:", printData.value);
    // 创建一个新的打印窗口
    const printWindow = window.open("", "_blank", "width=800,height=600");
    // 构建打印内容
    let printContent = `
                                                                                  <!DOCTYPE html>
                                                                                  <html>
                                                                                  <head>
                                                                                    <meta charset="UTF-8">
                                                                                    <title>打印预览</title>
                                                                                    <style>
                                                                                      body {
                                                                                        margin: 0;
                                                                                        padding: 0;
                                                                                        font-family: "SimSun", serif;
                                                                                        background: white;
                                                                                      }
                                                                                                                                   .print-page {
                                                                                          width: 200mm;
                                                                                          height: 75mm;
                                                                                          padding: 10mm;
                                                                                          padding-left: 20mm;
                                                                                          background: white;
                                                                                          box-sizing: border-box;
                                                                                          page-break-after: always;
                                                                                          page-break-inside: avoid;
                                                                                        }
                                                                                       .print-page:last-child {
                                                                                         page-break-after: avoid;
                                                                                       }
                                                                                      .delivery-note {
                                                                                        width: 100%;
                                                                                        height: 100%;
                                                                                        font-size: 12px;
                                                                                        line-height: 1.2;
                                                                                        display: flex;
                                                                                        flex-direction: column;
                                                                                        color: #000;
                                                                                      }
                                                                                      .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;
                                                                                      }
                                                                                      .info-section {
                                                                                        margin-bottom: 8px;
                                                                                        display: flex;
                                                                                        justify-content: space-between;
                                                                                        align-items: center;
                                                                                      }
                                                                                      .info-row {
                                                                                        line-height: 20px;
                                                                                      }
                                                                                      .label {
                                                                                        font-weight: bold;
                                                                                        width: 60px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                      .value {
                                                                                        margin-right: 20px;
                                                                                        min-width: 80px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                               .table-section {
                                                                                               margin-bottom: 40px;
                                                                                        //  flex: 0.6;
                                                                                       }
                                                                                      .product-table {
                                                                                        width: 100%;
                                                                                        border-collapse: collapse;
                                                                                        border: 1px solid #000;
                                                                                      }
                                                                                               .product-table th, .product-table td {
                                                                                         border: 1px solid #000;
                                                                                         padding: 6px;
                                                                                         text-align: center;
                                                                                         font-size: 12px;
                                                                                         line-height: 1.4;
                                                                                       }
                                                                                      .product-table th {
                                                                                        font-weight: bold;
                                                                                      }
                                                                                      .total-value {
                                                                                        font-weight: bold;
                                                                                      }
                                                                                      .footer-section {
                                                                                        margin-top: auto;
                                                                                      }
                                                                                      .footer-row {
                                                                                        display: flex;
                                                                                        margin-bottom: 3px;
                                                                                        line-height: 22px;
                                                                                        justify-content: space-between;
                                                                                      }
                                                                                      .footer-item {
                                                                                        display: flex;
                                                                                        margin-right: 20px;
                                                                                      }
                                                                                      .footer-item .label {
                                                                                        font-weight: bold;
                                                                                        width: 80px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                      .footer-item .value {
                                                                                        min-width: 80px;
                                                                                        font-size: 12px;
                                                                                      }
                                                                                      .address-item .address-value {
                                                                                        min-width: 200px;
                                                                                      }
                                                                                      @media print {
                                                                                        body {
                                                                                          margin: 0;
                                                                                          padding: 0;
                                                                                        }
                                                                                                   .print-page {
                                                                                           margin: 0;
                                                                                           padding: 10mm;
                                                                                           /* padding-left: 20mm; */
                                                                                           page-break-inside: avoid;
                                                                                           page-break-after: always;
                                                                                         }
                                                                                         .print-page:last-child {
                                                                                           page-break-after: avoid;
                                                                                         }
                                                                                      }
                                                                                    </style>
                                                                                  </head>
                                                                                  <body>
                                                                                `;
    // 为每条数据生成打印页面
    printData.value.forEach((item, index) => {
      printContent += `
                                                                                    <div class="print-page">
                                                                                      <div class="delivery-note">
                                                                                        <div class="header">
                                                                                          <div class="document-title">零售发货单</div>
                                                                                        </div>
                                                                                        <div class="info-section">
                                                                                          <div class="info-row">
                                                                                            <div>
                                                                                              <span class="label">发货日期:</span>
                                                                                              <span class="value">${formatDate(
                                                                                                item.createTime
                                                                                              )}</span>
                                                                                            </div>
                                                                                            <div>
                                                                                              <span class="label">客户名称:</span>
                                                                                              <span class="value">${
                                                                                                item.customerName
                                                                                              }</span>
                                                                                            </div>
                                                                                          </div>
                                                                                          <div class="info-row">
                                                                                            <span class="label">单号:</span>
                                                                                            <span class="value">${
                                                                                              item.salesContractNo ||
                                                                                              ""
                                                                                            }</span>
                                                                                          </div>
                                                                                        </div>
                                                                                        <div class="table-section">
                                                                                          <table class="product-table">
                                                                                            <thead>
                                                                                              <tr>
                                                                                                <th>产品名称</th>
                                                                                                <th>规格型号</th>
                                                                                                <th>单位</th>
                                                                                                <th>单价</th>
                                                                                                <th>零售数量</th>
                                                                                                <th>零售金额</th>
                                                                                              </tr>
                                                                                            </thead>
                                                                                            <tbody>
                                                                                              ${
                                                                                                item.products &&
                                                                                                item
                                                                                                  .products
                                                                                                  .length >
                                                                                                  0
                                                                                                  ? item.products
                                                                                                      .map(
                                                                                                        product => `
                                                                                                  <tr>
                                                                                                    <td>${
                                                                                                      product.productCategory ||
                                                                                                      ""
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.specificationModel ||
                                                                                                      ""
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.unit ||
                                                                                                      ""
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.taxInclusiveUnitPrice ||
                                                                                                      "0"
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.quantity ||
                                                                                                      "0"
                                                                                                    }</td>
                                                                                                    <td>${
                                                                                                      product.taxInclusiveTotalPrice ||
                                                                                                      "0"
                                                                                                    }</td>
                                                                                                  </tr>
                                                                                                `
                                                                                                      )
                                                                                                      .join(
                                                                                                        ""
                                                                                                      )
                                                                                                  : '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>'
                                                                                              }
                                                                                            </tbody>
                                                                                            <tfoot>
                                                                                              <tr>
                                                                                                <td class="label">合计</td>
                                                                                                <td class="total-value"></td>
                                                                                                <td class="total-value"></td>
                                                                                                <td class="total-value"></td>
                                                                                                <td class="total-value">${getTotalQuantityForPrint(
                                                                                                  item.products
                                                                                                )}</td>
                                                                                                <td class="total-value">${getTotalAmountForPrint(
                                                                                                  item.products
                                                                                                )}</td>
                                                                                              </tr>
                                                                                            </tfoot>
                                                                                          </table>
                                                                                        </div>
                                                                                        <div class="footer-section">
                                                                                          <div class="footer-row">
                                                                                            <div class="footer-item">
                                                                                              <span class="label">收货电话:</span>
                                                                                              <span class="value"></span>
                                                                                            </div>
                                                                                            <div class="footer-item">
                                                                                              <span class="label">收货人:</span>
                                                                                              <span class="value"></span>
                                                                                            </div>
                                                                                            <div class="footer-item address-item">
                                                                                              <span class="label">收货地址:</span>
                                                                                              <span class="value address-value"></span>
                                                                                            </div>
                                                                                          </div>
                                                                                          <div class="footer-row">
                                                                                            <div class="footer-item">
                                                                                              <span class="label">操作员:</span>
                                                                                              <span class="value">${
                                                                                                userStore.nickName ||
                                                                                                "撕开前"
                                                                                              }</span>
                                                                                            </div>
                                                                                            <div class="footer-item">
                                                                                              <span class="label">打印日期:</span>
                                                                                              <span class="value">${formatDateTime(
                                                                                                new Date()
                                                                                              )}</span>
                                                                                            </div>
                                                                                          </div>
                                                                                        </div>
                                                                                      </div>
                                                                                    </div>
                                                                                  `;
    });
    printContent += `
                                                                                  </body>
                                                                                  </html>
                                                                                `;
    // 写入内容到新窗口
    printWindow.document.write(printContent);
    printWindow.document.close();
    // 等待内容加载完成后打印
    printWindow.onload = () => {
      setTimeout(() => {
        printWindow.print();
        printWindow.close();
        printPreviewVisible.value = false;
      }, 500);
    };
  };
  // 格式化日期
  const formatDate = dateString => {
    if (!dateString) return getCurrentDate();
@@ -2728,16 +2497,33 @@
  };
  /**
   * 获取发货类型文本(货车/快递/自送)
   * 子表行未返回发货类型字段,依据互斥的发货信息推断:
   * 有车牌为货车,有快递公司/单号为快递,已发货但两者皆无为自送
   */
  const getShippingTypeText = row => {
    if (!row) return "";
    if (row.shippingCarNumber) return "货车";
    if (row.expressCompany || row.expressNumber) return "快递";
    if (row.shippingDate) return "自送";
    return "";
  };
  const getShippingTypeTag = row => {
    const type = getShippingTypeText(row);
    const typeTagMap = {
      货车: "warning",
      快递: "primary",
      自送: "success",
    };
    return typeTagMap[type] || "info";
  };
  /**
   * 判断是否可以发货
   * 只有在产品状态是充足,发货状态是待发货和审核拒绝的时候才可以发货
   * @param row 行数据
   */
  const canShip = row => {
    // 产品状态必须是充足(approveStatus === 1)
    if (row.approveStatus !== 1) {
      return false;
    }
    // 获取发货状态
    const shippingStatus = row.shippingStatus;
@@ -2765,19 +2551,42 @@
    fileDialogVisible.value = true;
  };
  // 下载销售单
  const downloadOrder = async (id) => {
    try {
      const res = await getPrintData(id);
      const data = res.data || res;
      downloadSalesJpg(data.companyName, data.ledger, '销售单_' + (data.ledger.salesContractNo || id) + '.jpg');
    } catch (e) {
      console.error('下载失败:', e);
    }
  };
  // 打印销售单
  const printOrder = async (id) => {
    try {
      const res = await getPrintData(id);
      const data = res.data || res;
      printSales(data.companyName, data.ledger);
    } catch (e) {
      console.error('打印失败:', e);
    }
  };
  // 打开发货弹框
  const openDeliveryForm = async row => {
    // 检查是否可以发货
    if (!canShip(row)) {
      proxy.$modal.msgWarning(
        "只有在产品状态是充足,发货状态是待发货或审核拒绝的时候才可以发货"
        "只有在发货状态是待发货、审核拒绝或部分发货的时候才可以发货"
      );
      return;
    }
    currentDeliveryRow.value = row;
    const batchNoList = await getDeliveryBatchNoList(
      row.productModelId || row.modelId
      row.productModelId || row.modelId,
      row.salesLedgerId
    );
    deliveryForm.value = {
      shippingCarNumber: "",
@@ -2800,9 +2609,11 @@
          proxy.$modal.msgWarning("请至少填写一个批号的发货数量");
          return;
        }
        const totalDeliveryQuantity = selectedBatchRows.reduce(
          (sum, item) => sum + Number(item.deliveryQuantity || 0),
          0
        const totalDeliveryQuantity = roundAmount(
          selectedBatchRows.reduce(
            (sum, item) => sum + Number(item.deliveryQuantity || 0),
            0
          )
        );
        const currentRowNoQuantity = Number(
          currentDeliveryRow.value?.noQuantity || 0
@@ -2884,8 +2695,12 @@
    if (val === "货车") {
      deliveryForm.value.expressCompany = "";
      deliveryForm.value.expressNumber = "";
    } else if (val === "快递") {
      deliveryForm.value.shippingCarNumber = "";
    } else {
      deliveryForm.value.shippingCarNumber = "";
      deliveryForm.value.expressCompany = "";
      deliveryForm.value.expressNumber = "";
    }
  };
@@ -3108,4 +2923,4 @@
      page-break-after: avoid;
    }
  }
</style>
</style>