zhangwencui
2 天以前 7de7862e8feaaefdf5e9492867db12013a88e9fc
销售台账审核反审核功能
已添加2个文件
已修改2个文件
1029 ■■■■ 文件已修改
src/api/salesManagement/reverseAuditHistory.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/inventoryManagement/receiptManagement/Record.vue 299 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/reverseAuditHistory/index.vue 472 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/salesLedger/index.vue 231 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/salesManagement/reverseAuditHistory.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
import request from "@/utils/request";
// åˆ†é¡µæŸ¥è¯¢åå®¡åŽ†å²
export function reverseAuditHistoryList(query) {
  return request({
    url: "/sales/ledger/reverseAuditHistory/list",
    method: "get",
    params: query,
  });
}
// ä¿å­˜åå®¡å¿«ç…§
export function saveReverseAuditSnapshot(data) {
  return request({
    url: "/sales/ledger/reverseAuditHistory/save",
    method: "post",
    data,
  });
}
// èŽ·å–å¿«ç…§è¯¦æƒ…
export function getReverseAuditSnapshotDetail(id) {
  return request({
    url: `/sales/ledger/reverseAuditHistory/${id}`,
    method: "get",
  });
}
src/views/inventoryManagement/receiptManagement/Record.vue
@@ -9,26 +9,26 @@
                        value-format="YYYY-MM-DD"
                        format="YYYY-MM-DD"
                        clearable
                        @change="handleQuery"/>
                        @change="handleQuery" />
        <span class="search_title ml10">产品大类:</span>
        <el-input v-model="searchForm.productName"
                  style="width: 240px"
                  placeholder="请输入"
                  clearable/>
                  clearable />
        <span class="search_title ml10">合同号:</span>
        <el-input v-model="searchForm.salesContractNo"
                  style="width: 240px"
                  placeholder="请输入合同号"
                  clearable/>
                  clearable />
        <span class="search_title ml10">来源:</span>
        <el-select v-model="searchForm.recordType"
                  style="width: 240px"
                  placeholder="请选择"
                  clearable>
                   style="width: 240px"
                   placeholder="请选择"
                   clearable>
          <el-option v-for="item in stockRecordTypeOptions"
                     :key="item.value"
                     :label="item.label"
                     :value="item.value"/>
                     :value="item.value" />
        </el-select>
        <el-button type="primary"
                   @click="handleQuery"
@@ -54,40 +54,40 @@
                height="calc(100vh - 18.5em)">
        <el-table-column align="center"
                         type="selection"
                         width="55"/>
                         width="55" />
        <el-table-column align="center"
                         label="序号"
                         type="index"
                         width="60"/>
                         width="60" />
        <el-table-column label="入库批次"
                         prop="inboundBatches"
                         width="280"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column label="合同号"
                         prop="salesContractNo"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column label="入库时间"
                         prop="createTime"
                         :formatter="formatTableDateYmd"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column label="产品大类"
                         prop="productName"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column label="规格型号"
                         prop="model"
                         show-overflow-tooltip/>
       <el-table-column label="厚度(mm)"
                        prop="thickness"
                        show-overflow-tooltip />
                         show-overflow-tooltip />
        <el-table-column label="厚度(mm)"
                         prop="thickness"
                         show-overflow-tooltip />
        <el-table-column label="单位"
                         prop="unit"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column label="入库数量"
                         prop="stockInNum"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column label="入库人"
                         prop="createBy"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column label="来源"
                         prop="recordType"
                         show-overflow-tooltip>
@@ -101,170 +101,171 @@
                  layout="total, sizes, prev, pager, next, jumper"
                  :page="page.current"
                  :limit="page.size"
                  @pagination="pageProductChange"/>
                  @pagination="pageProductChange" />
    </div>
  </div>
</template>
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
import {
  ref,
  reactive,
  toRefs,
  onMounted,
  getCurrentInstance,
} from "vue";
import {ElMessageBox} from "element-plus";
import {
  getStockInRecordListPage,
  batchDeleteStockInRecords,
} from "@/api/inventoryManagement/stockInRecord.js";
import {
  findAllQualifiedStockInRecordTypeOptions, findAllUnQualifiedStockInRecordTypeOptions,
} from "@/api/basicData/enum.js";
import {parseTime} from "@/utils/ruoyi";
  import pagination from "@/components/PIMTable/Pagination.vue";
  import { ref, reactive, toRefs, onMounted, getCurrentInstance } from "vue";
  import { ElMessageBox } from "element-plus";
  import {
    getStockInRecordListPage,
    batchDeleteStockInRecords,
  } from "@/api/inventoryManagement/stockInRecord.js";
  import {
    findAllQualifiedStockInRecordTypeOptions,
    findAllUnQualifiedStockInRecordTypeOptions,
  } from "@/api/basicData/enum.js";
  import { parseTime } from "@/utils/ruoyi";
const {proxy} = getCurrentInstance();
  const { proxy } = getCurrentInstance();
const formatTableDateYmd = (row, column, cellValue) => {
  if (cellValue == null || cellValue === "") {
    return "";
  }
  return parseTime(cellValue, "{y}-{m}-{d}") || "";
};
  const formatTableDateYmd = (row, column, cellValue) => {
    if (cellValue == null || cellValue === "") {
      return "";
    }
    return parseTime(cellValue, "{y}-{m}-{d}") || "";
  };
const props = defineProps({
  type: {
    type: String,
    required: true,
    default: '0'
  }
})
  const props = defineProps({
    type: {
      type: String,
      required: true,
      default: "0",
    },
  });
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
// æ¥æºç±»åž‹é€‰é¡¹
const stockRecordTypeOptions = ref([]);
const page = reactive({
  current: 1,
  size: 10,
});
const total = ref(0);
  const tableData = ref([]);
  const selectedRows = ref([]);
  const tableLoading = ref(false);
  // æ¥æºç±»åž‹é€‰é¡¹
  const stockRecordTypeOptions = ref([]);
  const page = reactive({
    current: 1,
    size: 10,
  });
  const total = ref(0);
const data = reactive({
  searchForm: {
    productName: "",
    salesContractNo: "",
    timeStr: "",
    recordType: "",
  },
});
const {searchForm} = toRefs(data);
// æŸ¥è¯¢åˆ—表
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  page.current = 1;
  getList();
};
  const data = reactive({
    searchForm: {
      productName: "",
      salesContractNo: "",
      timeStr: "",
      recordType: "",
    },
  });
  const { searchForm } = toRefs(data);
  // æŸ¥è¯¢åˆ—表
  /** æœç´¢æŒ‰é’®æ“ä½œ */
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
const getRecordType = (recordType) => {
  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
}
  const getRecordType = recordType => {
    return (
      stockRecordTypeOptions.value.find(item => item.value === recordType)
        ?.label || ""
    );
  };
const pageProductChange = obj => {
  page.current = obj.page;
  page.size = obj.limit;
  getList();
};
  const pageProductChange = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
const getList = () => {
  tableLoading.value = true;
  const params = {...page, type: props.type};
  params.timeStr = searchForm.value.timeStr;
  params.productName = searchForm.value.productName;
  params.salesContractNo = searchForm.value.salesContractNo;
  params.recordType = searchForm.value.recordType;
  getStockInRecordListPage(params)
  const getList = () => {
    tableLoading.value = true;
    const params = { ...page, type: props.type };
    params.timeStr = searchForm.value.timeStr;
    params.productName = searchForm.value.productName;
    params.salesContractNo = searchForm.value.salesContractNo;
    params.recordType = searchForm.value.recordType;
    getStockInRecordListPage(params)
      .then(res => {
        tableData.value = res.data.records;
        total.value = res.data.total || 0;
      }).finally(() => {
    tableLoading.value = false;
  })
};
// èŽ·å–æ¥æºç±»åž‹é€‰é¡¹
const fetchStockRecordTypeOptions = () => {
  if (props.type === '0') {
    findAllQualifiedStockInRecordTypeOptions()
        .then(res => {
          stockRecordTypeOptions.value = res.data;
        })
    return
  }
  findAllUnQualifiedStockInRecordTypeOptions()
      .then(res => {
        stockRecordTypeOptions.value = res.data;
      })
}
      .finally(() => {
        tableLoading.value = false;
      });
  };
// è¡¨æ ¼é€‰æ‹©æ•°æ®
const handleSelectionChange = selection => {
  selectedRows.value = selection.filter(item => item.id);
};
  // èŽ·å–æ¥æºç±»åž‹é€‰é¡¹
  const fetchStockRecordTypeOptions = () => {
    if (props.type === "0") {
      findAllQualifiedStockInRecordTypeOptions().then(res => {
        stockRecordTypeOptions.value = res.data;
      });
      return;
    }
    findAllUnQualifiedStockInRecordTypeOptions().then(res => {
      stockRecordTypeOptions.value = res.data;
    });
  };
const expandedRowKeys = ref([]);
  // è¡¨æ ¼é€‰æ‹©æ•°æ®
  const handleSelectionChange = selection => {
    selectedRows.value = selection.filter(item => item.id);
  };
// å¯¼å‡º
const handleOut = () => {
  ElMessageBox.confirm("是否确认导出?", "导出", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
  const expandedRowKeys = ref([]);
  // å¯¼å‡º
  const handleOut = () => {
    ElMessageBox.confirm("是否确认导出?", "导出", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        // æ ¹æ®ä¸åŒçš„ tab ç±»åž‹è°ƒç”¨ä¸åŒçš„导出接口
        proxy.download("/stockInRecord/exportStockInRecord", {type: props.type}, props.type === '0' ? "合格入库.xlsx" : "不合格入库.xlsx");
        proxy.download(
          "/stockInRecord/exportStockInRecord",
          { type: props.type },
          props.type === "0" ? "合格入库.xlsx" : "不合格入库.xlsx"
        );
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
  };
// åˆ é™¤
const handleDelete = () => {
  if (selectedRows.value.length === 0) {
    proxy.$modal.msgWarning("请选择数据");
    return;
  }
  const ids = selectedRows.value.map(item => item.id);
  // åˆ é™¤
  const handleDelete = () => {
    if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
    }
    const ids = selectedRows.value.map(item => item.id);
  ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    type: "warning",
  })
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        batchDeleteStockInRecords(ids)
            .then(() => {
              proxy.$modal.msgSuccess("删除成功");
              getList();
            })
            .catch(() => {
              proxy.$modal.msgError("删除失败");
            });
          .then(() => {
            proxy.$modal.msgSuccess("删除成功");
            getList();
          })
          .catch(() => {
            proxy.$modal.msgError("删除失败");
          });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
};
  };
onMounted(() => {
  getList();
  fetchStockRecordTypeOptions();
});
  onMounted(() => {
    getList();
    fetchStockRecordTypeOptions();
  });
</script>
<style scoped lang="scss"></style>
src/views/salesManagement/reverseAuditHistory/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,472 @@
<template>
  <div class="app-container">
    <div class="search_form">
      <el-form :model="searchForm"
               :inline="true">
        <el-form-item label="客户名称:">
          <el-select v-model="searchForm.customerId"
                     filterable
                     placeholder="请选择客户名称"
                     clearable
                     style="width: 220px"
                     @change="handleQuery">
            <el-option v-for="item in customerOption"
                       :key="item.id"
                       :label="item.customerName"
                       :value="item.id">
              {{ item.customerName + "——" + item.taxpayerIdentificationNumber }}
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="销售合同号:">
          <el-input v-model="searchForm.salesContractNo"
                    placeholder="请输入"
                    clearable
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="项目名称:">
          <el-input v-model="searchForm.projectName"
                    placeholder="请输入"
                    clearable
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="录入日期:">
          <el-date-picker v-model="searchForm.entryDate"
                          value-format="YYYY-MM-DD"
                          format="YYYY-MM-DD"
                          type="daterange"
                          placeholder="请选择"
                          clearable
                          @change="handleQuery" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary"
                     @click="handleQuery">搜索</el-button>
          <el-button @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div class="table_list">
      <el-table :data="tableData"
                border
                v-loading="loading">
        <el-table-column label="序号"
                         type="index"
                         width="60"
                         align="center" />
        <el-table-column label="反审时间"
                         prop="counterReviewTime"
                         align="center">
          <template #default="scope">
            {{ formatTime(scope.row.counterReviewTime) }}
          </template>
        </el-table-column>
        <el-table-column label="反审人"
                         prop="counterReviewPerson"
                         align="center" />
        <el-table-column label="销售合同号"
                         prop="salesContractNo" />
        <el-table-column label="客户名称"
                         prop="customerName"
                         show-overflow-tooltip />
        <el-table-column label="项目名称"
                         prop="projectName"
                         show-overflow-tooltip />
        <el-table-column label="合同金额(元)"
                         prop="contractAmount"
                         align="right">
          <template #default="scope">
            {{ formattedNumber(null, null, scope.row.contractAmount) }}
          </template>
        </el-table-column>
        <el-table-column label="操作"
                         width="100"
                         align="center"
                         fixed="right">
          <template #default="scope">
            <el-button link
                       type="primary"
                       @click="handleView(scope.row)">查看快照</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0"
                  :total="total"
                  :page="page.current"
                  :limit="page.size"
                  @pagination="paginationChange" />
    </div>
    <!-- å¿«ç…§è¯¦æƒ…对话框 -->
    <el-dialog v-model="dialogVisible"
               title="反审数据快照详情"
               width="85%">
      <div class="snapshot-detail">
        <el-divider content-position="left">基本信息</el-divider>
        <el-descriptions border
                         :column="3">
          <el-descriptions-item label="销售合同号">{{ currentSnapshot.salesContractNo }}</el-descriptions-item>
          <el-descriptions-item label="业务员">{{ currentSnapshot.salesman }}</el-descriptions-item>
          <el-descriptions-item label="客户名称">{{ currentSnapshot.customerName }}</el-descriptions-item>
          <el-descriptions-item label="项目名称">{{ currentSnapshot.projectName }}</el-descriptions-item>
          <el-descriptions-item label="签订日期">{{ currentSnapshot.executionDate }}</el-descriptions-item>
          <el-descriptions-item label="交货日期">{{ currentSnapshot.deliveryDate }}</el-descriptions-item>
          <el-descriptions-item label="录入人">{{ currentSnapshot.entryPersonName || currentSnapshot.entryPerson }}</el-descriptions-item>
          <el-descriptions-item label="录入日期">{{ currentSnapshot.entryDate }}</el-descriptions-item>
          <el-descriptions-item label="合同金额(元)">{{ formattedNumber(null, null, currentSnapshot.contractAmount) }}</el-descriptions-item>
          <el-descriptions-item label="反审时间">{{ formatTime(currentSnapshot.counterReviewTime) }}</el-descriptions-item>
          <el-descriptions-item label="反审人">{{ currentSnapshot.counterReviewPerson }}</el-descriptions-item>
        </el-descriptions>
        <el-divider content-position="left"
                    style="margin-top: 30px;">产品信息</el-divider>
        <el-table :data="currentSnapshot.productData"
                  border
                  stripe
                  show-summary
                  :summary-method="summarizeMainTable">
          <el-table-column align="center"
                           label="序号"
                           type="index"
                           width="60" />
          <el-table-column label="产品大类"
                           prop="productCategory"
                           min-width="120"
                           show-overflow-tooltip />
          <el-table-column label="规格型号"
                           prop="specificationModel"
                           min-width="150"
                           show-overflow-tooltip />
          <el-table-column label="厚度(mm)"
                           prop="thickness"
                           width="90"
                           align="center" />
          <el-table-column label="楼层编号"
                           prop="floorCode"
                           min-width="120"
                           show-overflow-tooltip />
          <el-table-column label="含税单价(元)"
                           prop="taxInclusiveUnitPrice"
                           width="110"
                           align="right">
            <template #default="scope">
              {{ formattedNumber(null, null, scope.row.taxInclusiveUnitPrice) }}
            </template>
          </el-table-column>
          <el-table-column label="宽(mm)"
                           prop="width"
                           width="80"
                           align="center" />
          <el-table-column label="高(mm)"
                           prop="height"
                           width="80"
                           align="center" />
          <el-table-column label="数量"
                           prop="quantity"
                           width="80"
                           align="center" />
          <el-table-column label="结算单片面积(㎡)"
                           prop="settlePieceArea"
                           width="130"
                           align="center">
            <template #default="scope">
              {{ scope.row.settlePieceArea ? Number(scope.row.settlePieceArea).toFixed(4) : "" }}
            </template>
          </el-table-column>
          <el-table-column label="面积(m²)"
                           prop="actualTotalArea"
                           width="110"
                           align="center">
            <template #default="scope">
              {{ scope.row.actualTotalArea ? Number(scope.row.actualTotalArea).toFixed(4) : "" }}
            </template>
          </el-table-column>
          <el-table-column label="税率(%)"
                           prop="taxRate"
                           width="80"
                           align="center" />
          <el-table-column label="含税总价(元)"
                           prop="taxInclusiveTotalPrice"
                           width="110"
                           align="right">
            <template #default="scope">
              {{ formattedNumber(null, null, scope.row.taxInclusiveTotalPrice) }}
            </template>
          </el-table-column>
          <el-table-column label="不含税总价(元)"
                           prop="taxExclusiveTotalPrice"
                           width="110"
                           align="right">
            <template #default="scope">
              {{ formattedNumber(null, null, scope.row.taxExclusiveTotalPrice) }}
            </template>
          </el-table-column>
          <el-table-column label="加工要求"
                           prop="processRequirement"
                           min-width="150"
                           show-overflow-tooltip />
          <el-table-column label="发票类型"
                           prop="invoiceType"
                           width="100"
                           align="center" />
          <el-table-column label="额外加工"
                           min-width="180">
            <template #default="scope">
              <div v-if="scope.row.salesProductProcessList && scope.row.salesProductProcessList.length > 0">
                <el-tag v-for="(item, idx) in scope.row.salesProductProcessList"
                        :key="idx"
                        size="small"
                        type="info"
                        style="margin: 2px;">
                  {{ item.processName }} ({{ item.quantity }})
                </el-tag>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="备注"
                           prop="remark"
                           min-width="120"
                           show-overflow-tooltip />
          <el-table-column label="重箱"
                           prop="heavyBox"
                           width="100"
                           show-overflow-tooltip />
        </el-table>
        <el-row :gutter="30"
                style="margin-top: 20px;">
          <el-col :span="12">
            <div class="remark-section">
              <div class="label">备注:</div>
              <div class="content">{{ currentSnapshot.remarks || "无" }}</div>
            </div>
          </el-col>
          <el-col :span="12">
            <div class="remark-section">
              <div class="label">客户备注:</div>
              <div class="content">{{ currentSnapshot.customerRemarks || "无" }}</div>
            </div>
          </el-col>
        </el-row>
      </div>
      <template #footer>
        <el-button @click="dialogVisible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
  import { ref, reactive, onMounted, getCurrentInstance } from "vue";
  import {
    customerList,
    ledgerListPage,
    getSalesLedgerWithProducts,
  } from "@/api/salesManagement/salesLedger.js";
  import pagination from "@/components/PIMTable/Pagination.vue";
  import dayjs from "dayjs";
  const { proxy } = getCurrentInstance();
  const loading = ref(false);
  const tableData = ref([]);
  const total = ref(0);
  const dialogVisible = ref(false);
  const currentSnapshot = ref({});
  const customerOption = ref([]);
  const searchForm = reactive({
    customerId: undefined,
    salesContractNo: "",
    projectName: "",
    width: undefined,
    height: undefined,
    entryDate: [],
    deliveryStatus: undefined,
    stockStatus: undefined,
    reverseAuditDate: [],
  });
  const page = reactive({
    current: 1,
    size: 10,
  });
  const getList = () => {
    loading.value = true;
    const params = {
      ...page,
      salesContractNo: searchForm.salesContractNo,
      projectName: searchForm.projectName,
      width: searchForm.width,
      height: searchForm.height,
      deliveryStatus: searchForm.deliveryStatus,
      stockStatus: searchForm.stockStatus,
      reviewStatus: 2, // å›ºå®šä¼ 2
      beginTime: searchForm.reverseAuditDate?.[0],
      endTime: searchForm.reverseAuditDate?.[1],
      entryDateStart: searchForm.entryDate?.[0],
      entryDateEnd: searchForm.entryDate?.[1],
    };
    // æŸ¥è¯¢å®¢æˆ·åç§°ä¸Žå°è´¦ä¿æŒä¸€è‡´ï¼šå…ˆé€‰ customerId,再映射为 customerName æŸ¥è¯¢
    const selectedCustomer = (customerOption.value || []).find(
      item => String(item?.id ?? "") === String(searchForm.customerId ?? "")
    );
    if (selectedCustomer?.customerName) {
      params.customerName = String(selectedCustomer.customerName).trim();
    }
    ledgerListPage(params)
      .then(res => {
        tableData.value = res.records || [];
        total.value = res.total || 0;
      })
      .catch(err => {
        console.error("获取反审历史失败:", err);
        tableData.value = [];
        total.value = 0;
      })
      .finally(() => {
        loading.value = false;
      });
  };
  const handleQuery = () => {
    page.current = 1;
    getList();
  };
  const paginationChange = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getList();
  };
  const resetQuery = () => {
    searchForm.customerId = undefined;
    searchForm.salesContractNo = "";
    searchForm.projectName = "";
    searchForm.width = undefined;
    searchForm.height = undefined;
    searchForm.entryDate = [];
    searchForm.deliveryStatus = undefined;
    searchForm.stockStatus = undefined;
    searchForm.reverseAuditDate = [];
    page.current = 1;
    handleQuery();
  };
  const getCustomerOption = () => {
    customerList().then(res => {
      customerOption.value = res || [];
    });
  };
  const handleView = row => {
    getSalesLedgerWithProducts({ id: row.id, type: 1 }).then(res => {
      currentSnapshot.value = { ...res };
      // å­—段名兼容处理,与销售台账保持一致
      currentSnapshot.value.customerRemarks =
        res?.customerRemarks ?? res?.customer_remarks ?? "";
      dialogVisible.value = true;
    });
  };
  const formattedNumber = (row, column, cellValue) => {
    if (cellValue == null || cellValue === "") return "0.00";
    return Number(cellValue).toLocaleString("zh-CN", {
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    });
  };
  const formatTime = time => {
    if (!time) return "";
    return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
  };
  const summarizeMainTable = param => {
    const { columns, data } = param;
    const sums = [];
    columns.forEach((column, index) => {
      if (index === 0) {
        sums[index] = "合计";
        return;
      }
      const prop = column.property;
      if (
        [
          "quantity",
          "actualTotalArea",
          "taxInclusiveTotalPrice",
          "taxExclusiveTotalPrice",
        ].includes(prop)
      ) {
        const values = data.map(item => Number(item[prop]));
        if (!values.every(value => isNaN(value))) {
          const sum = values.reduce((prev, curr) => {
            const value = Number(curr);
            if (!isNaN(value)) {
              return prev + curr;
            } else {
              return prev;
            }
          }, 0);
          if (prop === "quantity") {
            sums[index] = sum;
          } else if (prop === "actualTotalArea") {
            sums[index] = sum.toFixed(4);
          } else {
            sums[index] = sum.toLocaleString("zh-CN", {
              minimumFractionDigits: 2,
              maximumFractionDigits: 2,
            });
          }
        } else {
          sums[index] = "";
        }
      } else {
        sums[index] = "";
      }
    });
    return sums;
  };
  onMounted(() => {
    getCustomerOption();
    getList();
  });
</script>
<style scoped lang="scss">
  .app-container {
    padding: 20px;
  }
  .search_form {
    margin-bottom: 20px;
  }
  .table_list {
    background: #fff;
    padding: 20px;
    border-radius: 4px;
  }
  .snapshot-detail {
    max-height: 70vh;
    overflow-y: auto;
    padding-right: 10px;
    .remark-section {
      margin-bottom: 15px;
      .label {
        font-weight: bold;
        color: #606266;
        margin-bottom: 8px;
      }
      .content {
        padding: 10px;
        background-color: #f5f7fa;
        border-radius: 4px;
        min-height: 40px;
        white-space: pre-wrap;
      }
    }
  }
</style>
src/views/salesManagement/salesLedger/index.vue
@@ -105,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>
@@ -255,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"
@@ -381,6 +385,18 @@
                    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="入库状态"
                         width="120"
                         align="center">
@@ -433,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>
@@ -491,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"
@@ -508,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"
@@ -524,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>
@@ -539,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">
@@ -551,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>
@@ -565,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"
@@ -582,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>
@@ -591,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>
@@ -629,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>
@@ -643,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"
@@ -664,7 +686,8 @@
                               :precision="2"
                               style="width: 100%"
                               placeholder="请输入"
                               clearable />
                               clearable
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.thickness ?? "" }}</span>
            </template>
          </el-table-column>
@@ -677,7 +700,8 @@
                        v-model="scope.row.floorCode"
                        placeholder="请输入"
                        clearable
                        style="width: 100%" />
                        style="width: 100%"
                        :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.floorCode ?? "" }}</span>
            </template>
          </el-table-column>
@@ -712,7 +736,8 @@
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSizeChange(scope.row)"
                               @input="() => handleInlineSizeChange(scope.row)" />
                               @input="() => handleInlineSizeChange(scope.row)"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.width ?? "" }}</span>
            </template>
          </el-table-column>
@@ -730,7 +755,8 @@
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSizeChange(scope.row)"
                               @input="() => handleInlineSizeChange(scope.row)" />
                               @input="() => handleInlineSizeChange(scope.row)"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.height ?? "" }}</span>
            </template>
          </el-table-column>
@@ -748,7 +774,8 @@
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineQuantityChange(scope.row)"
                               @input="() => handleInlineQuantityChange(scope.row)" />
                               @input="() => handleInlineQuantityChange(scope.row)"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.quantity ?? "" }}</span>
            </template>
          </el-table-column>
@@ -765,7 +792,8 @@
                               style="width: 100%"
                               placeholder="请输入"
                               clearable
                               @change="() => handleInlineSettleAreaChange(scope.row)" />
                               @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>
@@ -780,7 +808,8 @@
                               :step="1"
                               :precision="4"
                               style="width: 100%"
                               placeholder="自动计算" />
                               placeholder="自动计算"
                               :disabled="Number(form.reviewStatus) === 1" />
              <span v-else>{{ scope.row.actualTotalArea ? Number(scope.row.actualTotalArea).toFixed(4) : "" }}</span>
            </template>
          </el-table-column>
@@ -793,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"
@@ -825,10 +855,11 @@
                        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>
          <el-table-column label="发票类型"
                           prop="invoiceType"
                           min-width="120">
@@ -837,7 +868,8 @@
                         v-model="scope.row.invoiceType"
                         placeholder="请选择"
                         clearable
                         style="width: 100%">
                         style="width: 100%"
                         :disabled="Number(form.reviewStatus) === 1">
                <el-option label="增普票"
                           value="增普票" />
                <el-option label="增专票"
@@ -855,7 +887,8 @@
                        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>
@@ -867,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>
@@ -978,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>
@@ -1003,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>
@@ -1016,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"
@@ -1024,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>
@@ -1051,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>
@@ -1080,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>
@@ -1093,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>
@@ -1941,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);
@@ -2011,6 +2050,7 @@
      entryDateEnd: undefined,
      deliveryStatus: undefined, // å‘货状态:1未发货 2审批中 3审批不通过 4审批通过 5已发货 6部分发货
      stockStatus: undefined, // å…¥åº“状态:0未入库 1部分入库 2已入库
      reviewStatus: undefined, // å®¡æ ¸çŠ¶æ€ï¼š0待审核 1已审核 2已反审
    },
    form: {
      salesContractNo: "",
@@ -2022,6 +2062,8 @@
      maintenanceTime: "",
      productData: [],
      executionDate: "",
      reviewStatus: undefined,
      stockStatus: undefined,
    },
    rules: {
      salesman: [{ required: true, message: "请选择", trigger: "change" }],
@@ -2219,7 +2261,9 @@
    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 ?? "";
@@ -2354,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) {
@@ -2956,6 +2996,67 @@
    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;
    }
    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;
@@ -2965,7 +3066,7 @@
    tableLoading.value = true;
    const { entryDate, ...rest } = searchForm;
    // å°†èŒƒå›´æ—¥æœŸå­—段传递给后端
    const params = { ...rest, ...page };
    const params = { ...rest, ...page, reviewStatusList: [0, 1] };
    // ç§»é™¤å½•入日期的默认值设置,只保留范围日期字段
    delete params.entryDate;
    // æŸ¥è¯¢å®¢æˆ·åç§°ä¸Žæ–°å¢žä¿æŒä¸€è‡´ï¼šå…ˆé€‰ customerId,再映射为 customerName æŸ¥è¯¢
@@ -2983,15 +3084,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 {
@@ -3065,7 +3164,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 {
@@ -3096,9 +3197,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({
@@ -3656,6 +3764,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 => {
@@ -3919,7 +4029,11 @@
      const templateUrl = HISTORY_IMPORT_TEMPLATE_URL_MAP[command];
      const fileName = HISTORY_IMPORT_TEMPLATE_FILE_NAME_MAP[command];
      if (templateUrl) {
        proxy.download(templateUrl, {}, fileName || "销售发货历史数据导入模板.xlsx");
        proxy.download(
          templateUrl,
          {},
          fileName || "销售发货历史数据导入模板.xlsx"
        );
        return;
      }
    }
@@ -3981,6 +4095,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 = [];
@@ -4099,7 +4222,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();
@@ -4583,8 +4707,7 @@
    // å…è®¸ï¼š1未发货、3审批不通过、4审批通过、6部分发货;不允许:2审批中、5已发货
    const statusItem = selectedRows.value[0].deliveryStatus;
    const ledgerAllowsDelivery = s =>
      [1, 3, 4, 6].includes(Number(s));
    const ledgerAllowsDelivery = s => [1, 3, 4, 6].includes(Number(s));
    let isTrue = true;
    selectedRows.value.forEach(row => {
      if (!ledgerAllowsDelivery(row.deliveryStatus)) {
@@ -4811,7 +4934,7 @@
        const run = async () => {
          for (const salesLedgerId of uniqueLedgerIds) {
            await addShippingInfo({
              scanOutbound:  false,
              scanOutbound: false,
              salesLedgerId,
              type: deliveryForm.value.type,
              approveUserIds,