zhangwencui
2026-05-29 befbda496fbf663c857e89f3daf3dc2dbcdcd624
src/views/salesManagement/salesLedger/index.vue
@@ -64,10 +64,14 @@
                       :value="1" />
            <el-option label="审批中"
                       :value="2" />
            <el-option label="审批失败"
            <el-option label="审批不通过"
                       :value="3" />
            <el-option label="已发货"
            <el-option label="审批通过"
                       :value="4" />
            <el-option label="已发货"
                       :value="5" />
            <el-option label="部分发货"
                       :value="6" />
          </el-select>
        </el-form-item>
        <el-form-item label="入库状态:">
@@ -101,6 +105,10 @@
                                       @confirm="handleProcessFlowSelectConfirm" />
        <el-space wrap>
          <el-button type="primary"
                     @click="handleAudit">审核</el-button>
          <el-button type="primary"
                     @click="handleReverseAudit">反审</el-button>
          <el-button type="primary"
                     @click="handleSalesStock">入库</el-button>
          <el-button type="primary"
                     @click="openForm('add')">新增台账</el-button>
@@ -118,8 +126,8 @@
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="notShipped">未发货</el-dropdown-item>
                <el-dropdown-item command="shipped">已发货</el-dropdown-item>
                <el-dropdown-item command="notShipped">未出库</el-dropdown-item>
                <el-dropdown-item command="shipped">已出库</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
@@ -158,7 +166,7 @@
                style="width: 100%"
                :summary-method="summarizeMainTable"
                @expand-change="expandChange"
                height="calc(100vh - 18.5em)">
                height="calc(100vh - 22em)">
        <el-table-column align="center"
                         type="selection"
                         width="55"
@@ -238,6 +246,8 @@
                <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 === 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-else
@@ -249,7 +259,7 @@
                               align="center">
                <template #default="scope">
                  <el-tag v-if="scope.row.productStockStatus == 1"
                  type="warning">部分入库</el-tag>
                          type="warning">部分入库</el-tag>
                  <el-tag v-else-if="scope.row.productStockStatus == 2"
                          type="success">已入库</el-tag>
                  <el-tag v-else-if="scope.row.productStockStatus == 0"
@@ -369,8 +379,22 @@
                    type="primary">审批通过</el-tag>
            <el-tag v-else-if="Number(scope.row.deliveryStatus) === 5"
                    type="success">已发货</el-tag>
            <el-tag v-else-if="Number(scope.row.deliveryStatus) === 6"
                    type="warning">部分发货</el-tag>
            <el-tag v-else
                    type="info">-</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="审核状态"
                         width="120"
                         align="center">
          <template #default="scope">
            <el-tag v-if="Number(scope.row.reviewStatus) === 0"
                    type="warning">待审核</el-tag>
            <el-tag v-else-if="Number(scope.row.reviewStatus) === 1"
                    type="success">已审核</el-tag>
            <el-tag v-else
                    type="info">待审核</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="入库状态"
@@ -383,6 +407,8 @@
                    type="success">部分入库</el-tag>
            <el-tag v-else-if="Number(scope.row.stockStatus) === 2"
                    type="success">已入库</el-tag>
            <el-tag v-else-if="Number(scope.row.stockStatus) === 3"
                    type="warning">审批中</el-tag>
            <el-tag v-else
                    type="info">-</el-tag>
          </template>
@@ -423,7 +449,7 @@
            <el-button link
                       type="primary"
                       @click="openProcessFlowSelect(scope.row)"
                       :disabled="!scope.row.isEdit">工艺路线</el-button>
                       :disabled="!scope.row.isEdit || Number(scope.row.reviewStatus) === 1">工艺路线</el-button>
            <el-button link
                       type="primary"
                       @click="downLoadFile(scope.row)">附件</el-button>
@@ -481,7 +507,7 @@
              <el-select v-model="form.salesman"
                         placeholder="请选择"
                         clearable
                         :disabled="operationType === 'view'">
                         :disabled="operationType === 'view' || Number(form.reviewStatus) === 1">
                <el-option v-for="item in userList"
                           :key="item.nickName"
                           :label="item.nickName"
@@ -498,7 +524,7 @@
                         filterable
                         placeholder="请选择"
                         clearable
                         :disabled="operationType === 'view'">
                         :disabled="operationType === 'view' || Number(form.reviewStatus) === 1">
                <el-option v-for="item in customerOption"
                           :key="item.id"
                           :label="item.customerName"
@@ -514,7 +540,7 @@
              <el-input v-model="form.projectName"
                        placeholder="请输入"
                        clearable
                        :disabled="operationType === 'view'" />
                        :disabled="operationType === 'view' || Number(form.reviewStatus) === 1" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -529,7 +555,7 @@
                              type="date"
                              placeholder="请选择"
                              clearable
                              :disabled="operationType === 'view'" />
                              :disabled="operationType === 'view' || Number(form.reviewStatus) === 1" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
@@ -541,7 +567,8 @@
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
                              clearable
                              :disabled="operationType === 'view' || Number(form.reviewStatus) === 1" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -555,7 +582,8 @@
                         :reserve-keyword="false"
                         placeholder="请选择"
                         clearable
                         @change="changs">
                         @change="changs"
                         :disabled="operationType === 'view' || Number(form.reviewStatus) === 1">
                <el-option v-for="item in userList"
                           :key="item.userId"
                           :label="item.nickName"
@@ -572,7 +600,8 @@
                              format="YYYY-MM-DD"
                              type="date"
                              placeholder="请选择"
                              clearable />
                              clearable
                              :disabled="operationType === 'view' || Number(form.reviewStatus) === 1" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -581,13 +610,14 @@
                        prop="entryDate">
            <el-button v-if="operationType !== 'view'"
                       type="primary"
                       :disabled="hasEditingProductRow()"
                       :disabled="hasEditingProductRow() || Number(form.reviewStatus) === 1"
                       @click="addProductInline">
              添加
            </el-button>
            <el-button v-if="operationType !== 'view'"
                       plain
                       type="danger"
                       :disabled="Number(form.reviewStatus) === 1"
                       @click="deleteProduct">删除</el-button>
          </el-form-item>
        </el-row>
@@ -619,7 +649,8 @@
                              :render-after-expand="false"
                              style="width: 100%"
                              :filter-node-method="filterProductCategoryNode"
                              @change="(val) => handleInlineProductCategoryChange(scope.row, val)" />
                              @change="(val) => handleInlineProductCategoryChange(scope.row, val)"
                              :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.productCategory ?? "" }}</span>
            </template>
          </el-table-column>
@@ -633,7 +664,8 @@
                         clearable
                         filterable
                         style="width: 100%"
                         @change="(val) => handleInlineProductModelChange(scope.row, val)">
                         @change="(val) => handleInlineProductModelChange(scope.row, val)"
                         :disabled="Number(form.reviewStatus) === 1">
                <el-option v-for="item in modelOptions"
                           :key="item.id"
                           :label="item.model"
@@ -654,94 +686,23 @@
                               :precision="2"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable />
                               clearable
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.thickness ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="宽(mm)"
                           prop="width"
                           min-width="160">
          <el-table-column label="楼层编号"
                           prop="floorCode"
                           min-width="250"
                           show-overflow-tooltip>
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.width"
                               :min="0"
                               :step="1"
                               :precision="2"
                               style="width:100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSizeChange(scope.row)"
                               @input="() => handleInlineSizeChange(scope.row)" />
              <span v-else>{{ scope.row.width ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="高(mm)"
                           prop="height"
                           min-width="160">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.height"
                               :min="0"
                               :step="1"
                               :precision="2"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSizeChange(scope.row)"
                               @input="() => handleInlineSizeChange(scope.row)" />
              <span v-else>{{ scope.row.height ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="结算单片面积(㎡)"
                           prop="settlePieceArea"
                           min-width="200">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.settlePieceArea"
                               :min="0"
                               :step="1"
                               :precision="4"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSettleAreaChange(scope.row)" />
              <span v-else>{{ scope.row.settlePieceArea ? Number(scope.row.settlePieceArea).toFixed(4) : "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="数量"
                           prop="quantity"
                           min-width="150">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.quantity"
                               :step="1"
                               :min="0"
                               :precision="0"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineQuantityChange(scope.row)"
                               @input="() => handleInlineQuantityChange(scope.row)" />
              <span v-else>{{ scope.row.quantity ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="面积(m²)"
                           prop="actualTotalArea"
                           min-width="200">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.actualTotalArea"
                               :min="0"
                               :step="1"
                               :precision="4"
                               style="width: 100%"
                               placeholder="自动计算" />
              <span v-else>{{ scope.row.actualTotalArea ? Number(scope.row.actualTotalArea).toFixed(4) : "" }}</span>
              <el-input v-if="scope.row.__editing"
                        v-model="scope.row.floorCode"
                        placeholder="请输入"
                        clearable
                        style="width: 100%"
                        :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.floorCode ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="含税单价(元)"
@@ -761,6 +722,97 @@
              <span v-else>{{ formattedNumber(null, null, scope.row.taxInclusiveUnitPrice) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="宽(mm)"
                           prop="width"
                           min-width="160">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.width"
                               :min="0"
                               :step="1"
                               :precision="2"
                               style="width:100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSizeChange(scope.row)"
                               @input="() => handleInlineSizeChange(scope.row)"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.width ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="高(mm)"
                           prop="height"
                           min-width="160">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.height"
                               :min="0"
                               :step="1"
                               :precision="2"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSizeChange(scope.row)"
                               @input="() => handleInlineSizeChange(scope.row)"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.height ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="数量"
                           prop="quantity"
                           min-width="150">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.quantity"
                               :step="1"
                               :min="0"
                               :precision="0"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineQuantityChange(scope.row)"
                               @input="() => handleInlineQuantityChange(scope.row)"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.quantity ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="结算单片面积(㎡)"
                           prop="settlePieceArea"
                           min-width="200">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.settlePieceArea"
                               :min="0"
                               :step="1"
                               :precision="4"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSettleAreaChange(scope.row)"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.settlePieceArea ? Number(scope.row.settlePieceArea).toFixed(4) : "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="面积(m²)"
                           prop="actualTotalArea"
                           min-width="200">
            <template #default="scope">
              <el-input-number v-if="scope.row.__editing"
                               controls-position="right"
                               v-model="scope.row.actualTotalArea"
                               :min="0"
                               :step="1"
                               :precision="4"
                               style="width: 100%"
                               placeholder="自动计算"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.actualTotalArea ? Number(scope.row.actualTotalArea).toFixed(4) : "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="税率(%)"
                           prop="taxRate"
                           min-width="120">
@@ -770,7 +822,8 @@
                         placeholder="请选择"
                         clearable
                         style="width: 100%"
                         @change="() => handleInlineTaxRateChange(scope.row)">
                         @change="() => handleInlineTaxRateChange(scope.row)"
                         :disabled="Number(form.reviewStatus) === 1">
                <el-option label="1"
                           value="1" />
                <el-option label="3"
@@ -793,23 +846,6 @@
                           prop="taxExclusiveTotalPrice"
                           :formatter="formattedNumber"
                           min-width="120" />
          <el-table-column label="发票类型"
                           prop="invoiceType"
                           min-width="120">
            <template #default="scope">
              <el-select v-if="scope.row.__editing"
                         v-model="scope.row.invoiceType"
                         placeholder="请选择"
                         clearable
                         style="width: 100%">
                <el-option label="增普票"
                           value="增普票" />
                <el-option label="增专票"
                           value="增专票" />
              </el-select>
              <span v-else>{{ scope.row.invoiceType ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="加工要求"
                           prop="processRequirement"
                           min-width="160"
@@ -819,8 +855,27 @@
                        v-model="scope.row.processRequirement"
                        placeholder="请输入"
                        clearable
                        style="width: 100%" />
                        style="width: 100%"
                        :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.processRequirement ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="发票类型"
                           prop="invoiceType"
                           min-width="120">
            <template #default="scope">
              <el-select v-if="scope.row.__editing"
                         v-model="scope.row.invoiceType"
                         placeholder="请选择"
                         clearable
                         style="width: 100%"
                         :disabled="Number(form.reviewStatus) === 1">
                <el-option label="增普票"
                           value="增普票" />
                <el-option label="增专票"
                           value="增专票" />
              </el-select>
              <span v-else>{{ scope.row.invoiceType ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="备注"
@@ -832,21 +887,9 @@
                        v-model="scope.row.remark"
                        placeholder="请输入"
                        clearable
                        style="width: 100%" />
                        style="width: 100%"
                        :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.remark ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="楼层编号"
                           prop="floorCode"
                           min-width="250"
                           show-overflow-tooltip>
            <template #default="scope">
              <el-input v-if="scope.row.__editing"
                        v-model="scope.row.floorCode"
                        placeholder="请输入"
                        clearable
                        style="width: 100%" />
              <span v-else>{{ scope.row.floorCode ?? "" }}</span>
            </template>
          </el-table-column>
          <el-table-column label="重箱"
@@ -857,7 +900,8 @@
                        v-model="scope.row.heavyBox"
                        placeholder="请输入"
                        clearable
                        style="width: 100%" />
                        style="width: 100%"
                        :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.heavyBox ?? "" }}</span>
            </template>
          </el-table-column>
@@ -968,7 +1012,7 @@
                <el-button link
                           type="primary"
                           size="small"
                           :disabled="isProductShipped(scope.row) || hasEditingProductRow()"
                           :disabled="isProductShipped(scope.row) || Number(form.reviewStatus) === 1"
                           @click="copyProductInline(scope.row, scope.$index)">
                  复制新建
                </el-button>
@@ -993,7 +1037,7 @@
                    <el-button type="primary"
                               plain
                               size="small"
                               :disabled="isProductShipped(scope.row)"
                               :disabled="isProductShipped(scope.row) || Number(form.reviewStatus) === 1"
                               @click="startAddOtherAmountForRow(scope.row)">
                      新增
                    </el-button>
@@ -1006,7 +1050,7 @@
                               clearable
                               placeholder="请选择额外加工项目"
                               style="width: 100%;"
                               :disabled="isProductShipped(scope.row)">
                               :disabled="isProductShipped(scope.row) || Number(form.reviewStatus) === 1">
                      <el-option v-for="item in otherAmountSelectOptions"
                                 :key="item.id"
                                 :label="item.processName"
@@ -1014,13 +1058,13 @@
                    </el-select>
                    <div style="display:flex; justify-content:flex-end; gap: 8px;">
                      <el-button size="small"
                                 :disabled="isProductShipped(scope.row)"
                                 :disabled="isProductShipped(scope.row) || Number(form.reviewStatus) === 1"
                                 @click="scope.row.__inlineOtherAmountAdding = false; scope.row.__inlineOtherAmountAddId = null">
                        取消
                      </el-button>
                      <el-button type="primary"
                                 size="small"
                                 :disabled="isProductShipped(scope.row) || scope.row.__inlineOtherAmountAddId === null || scope.row.__inlineOtherAmountAddId === undefined || scope.row.__inlineOtherAmountAddId === ''"
                                 :disabled="isProductShipped(scope.row) || Number(form.reviewStatus) === 1 || scope.row.__inlineOtherAmountAddId === null || scope.row.__inlineOtherAmountAddId === undefined || scope.row.__inlineOtherAmountAddId === ''"
                                 @click="confirmAddOtherAmountForRow(scope.row)">
                        确认添加
                      </el-button>
@@ -1041,12 +1085,12 @@
                                       :precision="0"
                                       style="width: 120px;"
                                       placeholder="数量"
                                       :disabled="operationType === 'view' || isProductShipped(scope.row)"
                                       :disabled="operationType === 'view' || isProductShipped(scope.row) || Number(form.reviewStatus) === 1"
                                       @change="handleOtherAmountQuantityChange(scope.row)" />
                      <el-button type="danger"
                                 link
                                 size="small"
                                 :disabled="isProductShipped(scope.row)"
                                 :disabled="isProductShipped(scope.row) || Number(form.reviewStatus) === 1"
                                 @click="removeOtherAmountAtForRow(scope.row, idx)">
                        删除
                      </el-button>
@@ -1070,7 +1114,7 @@
                        clearable
                        type="textarea"
                        :rows="2"
                        :disabled="operationType === 'view'" />
                        :disabled="operationType === 'view' || Number(form.reviewStatus) === 1" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -1083,7 +1127,7 @@
                        clearable
                        type="textarea"
                        :rows="2"
                        :disabled="operationType === 'view'" />
                        :disabled="operationType === 'view' || Number(form.reviewStatus) === 1" />
            </el-form-item>
          </el-col>
        </el-row>
@@ -1931,9 +1975,14 @@
            const ctx = canvas.getContext("2d");
            canvas.width = Math.max(QR_SIZE + horizontalPad * 2, 280);
            ctx.font = `${fontSize}px "Microsoft YaHei", "PingFang SC", sans-serif`;
            const lines = wrapLedgerQrTextLines(ctx, label, canvas.width - horizontalPad * 2);
            const lines = wrapLedgerQrTextLines(
              ctx,
              label,
              canvas.width - horizontalPad * 2
            );
            const textBlockHeight = lines.length * lineHeight;
            canvas.height = padTop + QR_SIZE + gapAfterQr + textBlockHeight + bottomPad;
            canvas.height =
              padTop + QR_SIZE + gapAfterQr + textBlockHeight + bottomPad;
            ctx.fillStyle = "#ffffff";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
@@ -1999,8 +2048,9 @@
      entryDate: null, // 录入日期
      entryDateStart: undefined,
      entryDateEnd: undefined,
      deliveryStatus: undefined, // 发货状态:1未发货 2审批中 3审批失败 4已发货
      deliveryStatus: undefined, // 发货状态:1未发货 2审批中 3审批不通过 4审批通过 5已发货 6部分发货
      stockStatus: undefined, // 入库状态:0未入库 1部分入库 2已入库
      reviewStatus: undefined, // 审核状态:0待审核 1已审核 2已反审
    },
    form: {
      salesContractNo: "",
@@ -2012,6 +2062,8 @@
      maintenanceTime: "",
      productData: [],
      executionDate: "",
      reviewStatus: undefined,
      stockStatus: undefined,
    },
    rules: {
      salesman: [{ required: true, message: "请选择", trigger: "change" }],
@@ -2209,13 +2261,22 @@
    copied.productModelId = row.productModelId ?? null;
    copied.specificationModel = row.specificationModel ?? "";
    copied.thickness =
      row.thickness !== null && row.thickness !== undefined && row.thickness !== ""
      row.thickness !== null &&
      row.thickness !== undefined &&
      row.thickness !== ""
        ? Number(row.thickness)
        : null;
    copied.floorCode = row?.floorCode ?? row?.floor_code ?? "";
    // 复制新建仅带出产品大类与规格型号,其他数字字段全部留空,避免出现 0.00
    const srcUnit = row?.taxInclusiveUnitPrice;
    const unitNum =
      srcUnit !== null && srcUnit !== undefined && srcUnit !== ""
        ? Number(srcUnit)
        : NaN;
    copied.taxInclusiveUnitPrice = Number.isFinite(unitNum) ? unitNum : null;
    // 复制新建带出:产品大类、规格型号、厚度、楼层编号、单价;其余数量/面积/总价等留空,避免出现 0.00
    copied.quantity = null;
    copied.taxInclusiveUnitPrice = null;
    copied.taxInclusiveTotalPrice = null;
    copied.taxExclusiveTotalPrice = null;
    copied.width = null;
@@ -2337,10 +2398,6 @@
    }
    if (row.actualTotalArea <= 0) {
      proxy.$modal.msgWarning("面积必须大于0");
      return false;
    }
    if (row.taxInclusiveUnitPrice <= 0) {
      proxy.$modal.msgWarning("含税单价必须大于0");
      return false;
    }
    if (!row.productModelId) {
@@ -2908,7 +2965,15 @@
    notShipped: "/sales/ledger/salesHistory/notShippingImport",
    shipped: "/sales/ledger/salesHistory/shippingImport",
  };
  const HISTORY_IMPORT_TEMPLATE_URL_MAP = {
    notShipped: "/sales/ledger/salesHistory/notShippingImportTemplate",
    shipped: "/sales/ledger/salesHistory/shippingImportTemplate",
  };
  const HISTORY_IMPORT_TEMPLATE_FILE_NAME_MAP = {
    notShipped: "销售发货历史数据导入模板-未发货.xlsx",
    shipped: "销售发货历史数据导入模板-已发货.xlsx",
  };
  const currentImportCommand = ref("default");
  const changeDaterange = value => {
    if (value) {
      searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
@@ -2931,6 +2996,77 @@
    expandedRowKeys.value = [];
    getList();
  };
  /** 审核按钮操作 */
  const handleAudit = async () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择要审核的数据");
      return;
    }
    const canNotAudit = selectedRows.value.filter(
      row => Number(row.reviewStatus) !== 0
    );
    if (canNotAudit.length > 0) {
      proxy.$modal.msgWarning("选中的数据中包含非待审核项,请重新选择");
      return;
    }
    // 录入人不能审核该条数据
    const isEntryPerson = selectedRows.value.some(
      row => String(row.entryPerson) === String(userStore.id)
    );
    if (isEntryPerson) {
      proxy.$modal.msgWarning("录入人不能审核自己提交的数据");
      return;
    }
    try {
      await ElMessageBox.confirm("是否确认审核选中的销售台账?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      });
      for (const row of selectedRows.value) {
        await addOrUpdateSalesLedger({ ...row, reviewStatus: 1 });
      }
      proxy.$modal.msgSuccess("审核成功");
      getList();
    } catch (error) {
      console.log(error);
    }
  };
  /** 反审按钮操作 */
  const handleReverseAudit = async () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择要反审的数据");
      return;
    }
    const canNotReverse = selectedRows.value.filter(
      row => Number(row.reviewStatus) !== 1
    );
    if (canNotReverse.length > 0) {
      proxy.$modal.msgWarning("选中的数据中包含非已审核项,请重新选择");
      return;
    }
    try {
      await ElMessageBox.confirm("是否确认反审选中的销售台账?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      });
      for (const row of selectedRows.value) {
        await addOrUpdateSalesLedger({ ...row, reviewStatus: 2 });
      }
      proxy.$modal.msgSuccess("反审成功");
      getList();
    } catch (error) {
      console.log(error);
    }
  };
  const paginationChange = obj => {
    page.current = obj.page;
    page.size = obj.limit;
@@ -2940,7 +3076,7 @@
    tableLoading.value = true;
    const { entryDate, ...rest } = searchForm;
    // 将范围日期字段传递给后端
    const params = { ...rest, ...page };
    const params = { ...rest, ...page, reviewStatusList: [0, 1] };
    // 移除录入日期的默认值设置,只保留范围日期字段
    delete params.entryDate;
    // 查询客户名称与新增保持一致:先选 customerId,再映射为 customerName 查询
@@ -2958,15 +3094,13 @@
        delete params.customerName;
      }
    }
    const widthValue =
      params.width != null ? String(params.width).trim() : "";
    const widthValue = params.width != null ? String(params.width).trim() : "";
    if (widthValue) {
      params.width = widthValue;
    } else {
      delete params.width;
    }
    const heightValue =
      params.height != null ? String(params.height).trim() : "";
    const heightValue = params.height != null ? String(params.height).trim() : "";
    if (heightValue) {
      params.height = heightValue;
    } else {
@@ -3040,7 +3174,9 @@
      const res = await productList({ salesLedgerId: id, type: 1 });
      stockProductList.value = [];
      stockProductList.value =
        res.data.filter(item => item.productStockStatus == 0 || item.productStockStatus == 1) || [];
        res.data.filter(
          item => item.productStockStatus == 0 || item.productStockStatus == 1
        ) || [];
    } catch (e) {
      proxy?.$modal?.msgError?.("获取产品或审批人失败");
    } finally {
@@ -3071,9 +3207,16 @@
    proxy?.$modal?.loading?.("正在入库,请稍候...");
    try {
      const approveUserIds = stockApproverNodes.value.map(node => node.userId).join(",");
      const approveUserIds = stockApproverNodes.value
        .map(node => node.userId)
        .join(",");
      const approveUserName = stockApproverNodes.value
        .map(node => stockApproverOptions.value.find(item => String(item.userId) === String(node.userId))?.userName)
        .map(
          node =>
            stockApproverOptions.value.find(
              item => String(item.userId) === String(node.userId)
            )?.userName
        )
        .filter(Boolean)
        .join(",");
      await salesStock({
@@ -3631,6 +3774,8 @@
        }
        form.value.tempFileIds = tempFileIds;
        form.value.type = 1;
        form.value.reviewStatus = 0; // 默认审核状态为待审核
        form.value.stockStatus = 0; // 默认入库状态为未入库
        const submitPayload = { ...form.value };
        delete submitPayload.paymentMethod;
        addOrUpdateSalesLedger(submitPayload).then(res => {
@@ -3875,18 +4020,33 @@
  };
  // 导入
  const handleImport = () => {
    currentImportCommand.value = "default";
    openImportDialog("导入销售台账", "/sales/ledger/import");
  };
  // 历史迁移
  const handleHistoryImportCommand = command => {
    const url = HISTORY_IMPORT_URL_MAP[command];
    if (!url) return;
    const title = command === "shipped" ? "历史迁移-已发货" : "历史迁移-未发货";
    currentImportCommand.value = command;
    const title = command === "shipped" ? "历史迁移-已出库" : "历史迁移-未出库";
    openImportDialog(title, url);
  };
  // 下载导入模板
  const downloadTemplate = () => {
    const command = currentImportCommand.value;
    if (command && command !== "default") {
      const templateUrl = HISTORY_IMPORT_TEMPLATE_URL_MAP[command];
      const fileName = HISTORY_IMPORT_TEMPLATE_FILE_NAME_MAP[command];
      if (templateUrl) {
        proxy.download(
          templateUrl,
          {},
          fileName || "销售发货历史数据导入模板.xlsx"
        );
        return;
      }
    }
    proxy.download("/sales/ledger/exportTemplate", {}, "销售台账导入模板.xlsx");
  };
  const onClose = () => {
@@ -3945,6 +4105,15 @@
      return;
    }
    const ids = selectedRows.value.map(item => item.id);
    // 检查是否有已审核的台账
    const audited = selectedRows.value.filter(
      row => Number(row.reviewStatus) === 1
    );
    if (audited.length > 0) {
      proxy.$modal.msgWarning("选中的数据中包含已审核项,不能删除");
      return;
    }
    // 检查是否有已进行发货或发货完成的销售订单,若有则不允许删除
    const cannotDeleteNames = [];
@@ -4063,7 +4232,8 @@
        const processCardData = res?.data ?? {};
        // 补齐二维码所需的台账标识(后端数据有时不带 id)
        if (processCardData && typeof processCardData === "object") {
          processCardData.salesLedgerId = processCardData.salesLedgerId ?? selectedId;
          processCardData.salesLedgerId =
            processCardData.salesLedgerId ?? selectedId;
          processCardData.salesContractNo =
            (processCardData.salesContractNo ?? "").trim() ||
            String(selectedRow?.salesContractNo ?? "").trim();
@@ -4481,15 +4651,15 @@
      return false;
    }
    // 如果后端返回了台账级发货状态(deliveryStatus)
    // 1=已发货,则禁止再次发货
    // 台账级发货状态(deliveryStatus):2审批中、5已发货 时不可再发起本行发货;6部分发货仍可按明细继续发
    const deliveryStatus = row.deliveryStatus;
    if (
      deliveryStatus !== null &&
      deliveryStatus !== undefined &&
      String(deliveryStatus).trim() !== ""
    ) {
      if (Number(deliveryStatus) === 1) return false;
      const ds = Number(deliveryStatus);
      if (ds === 2 || ds === 5) return false;
    }
    // 获取发货状态
@@ -4545,12 +4715,15 @@
      return;
    }
    // 只允许【未发货/审批失败】进入发货流程
    // 允许:1未发货、3审批不通过、4审批通过、6部分发货;不允许:2审批中、5已发货
    const statusItem = selectedRows.value[0].deliveryStatus;
    const ledgerAllowsDelivery = s => [1, 3, 4, 6].includes(Number(s));
    let isTrue = true;
    selectedRows.value.forEach(row => {
      if (row.deliveryStatus != 1 && row.deliveryStatus != 3) {
        proxy.$modal.msgWarning("仅未发货或审批失败的台账可以发货");
      if (!ledgerAllowsDelivery(row.deliveryStatus)) {
        proxy.$modal.msgWarning(
          "仅未发货、审批不通过、审批通过或部分发货的台账可以发货"
        );
        isTrue = false;
        return;
      }
@@ -4587,9 +4760,9 @@
      return;
    }
    // 已发货台账:弹窗提醒,不能再次发货(4 视为已发货)
    // 已全部发货(5)的台账:弹窗提醒,不能再次发货
    const shippedLedgers = selectedRows.value.filter(
      r => Number(r.deliveryStatus) === 4
      r => Number(r.deliveryStatus) === 5
    );
    if (shippedLedgers.length === selectedRows.value.length) {
      try {
@@ -4646,9 +4819,9 @@
    try {
      const targets = [];
      for (const ledger of selectedRows.value) {
        //如果已经是“审批中(2)”或“已发货(4)”,则跳过,不允许重复操作
        // 审批中(2)、已全部发货(5) 跳过;部分发货(6) 等仍收集可发明细
        const status = Number(ledger.deliveryStatus);
        if (status === 2 || status === 4) {
        if (status === 2 || status === 5) {
          console.warn(
            `台账编号 ${ledger.salesContractNo} 状态为 ${status},跳过发货`
          );
@@ -4704,10 +4877,11 @@
  // 打开发货弹框(单条)
  const openDeliveryForm = async row => {
    // 只允许【未发货/审批失败】发货;已发货/审批中不允许
    const status = Number(row.deliveryStatus);
    if (status !== 1 && status !== 3) {
      proxy.$modal.msgWarning("只有发货状态为未发货或审批失败的记录才可以发货");
    if (![1, 3, 4, 6].includes(status)) {
      proxy.$modal.msgWarning(
        "只有发货状态为未发货、审批不通过、审批通过或部分发货的记录才可以发货"
      );
      return;
    }
@@ -4770,6 +4944,7 @@
        const run = async () => {
          for (const salesLedgerId of uniqueLedgerIds) {
            await addShippingInfo({
              scanOutbound: false,
              salesLedgerId,
              type: deliveryForm.value.type,
              approveUserIds,