张诺
10 小时以前 dc8cd97d8c3c565a80e2651efa63f41c4661ee2b
src/views/salesManagement/salesLedger/index.vue
@@ -42,7 +42,7 @@
        <el-table-column align="center" type="selection" width="55" fixed="left"/>
        <el-table-column type="expand" width="60" fixed="left">
          <template #default="props">
            <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
            <el-table :data="props.row.children" border show-summary :summary-method="(param) => summarizeChildrenTable(param, props.row)">
              <el-table-column align="center" label="序号" type="index"/>
              <el-table-column label="产品大类" prop="productCategory" />
              <el-table-column label="规格型号" prop="specificationModel" />
@@ -51,7 +51,9 @@
                                              width="100px"
                                              align="center">
                <template #default="scope">
                           <el-tag v-if="scope.row.approveStatus === 1"
               <el-tag v-if="getShippingStatusText(scope.row) === '已发货'"
                                       type="success">已出库</el-tag>
                           <el-tag v-else-if="scope.row.hasSufficientStock"
                                       type="success">充足</el-tag>
                           <el-tag v-else
                                       type="danger">不足</el-tag>
@@ -87,15 +89,15 @@
              </el-table-column>
              <el-table-column label="数量" prop="quantity" />
              <el-table-column label="税率(%)" prop="taxRate" />
              <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
              <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
              <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
              <el-table-column label="含税单价(元)" prop="taxInclusiveUnitPrice" :formatter="sensitiveAmountFormatter" />
              <el-table-column label="含税总价(元)" prop="taxInclusiveTotalPrice" :formatter="sensitiveAmountFormatter" />
              <el-table-column label="不含税总价(元)" prop="taxExclusiveTotalPrice" :formatter="sensitiveAmountFormatter" />
            <!--操作-->
              <el-table-column Width="60px" label="操作" align="center">
                <template #default="scope">
                  <el-button 
                    link 
                    type="primary"
                    type="primary"
                    size="small"
                    :disabled="!canShip(scope.row)"
                    @click="openDeliveryForm(scope.row)">
@@ -118,12 +120,11 @@
        <el-table-column label="录入日期" prop="entryDate" width="120" show-overflow-tooltip />
        <el-table-column label="签订日期" prop="executionDate" width="120" show-overflow-tooltip />
        <el-table-column label="交付日期" prop="deliveryDate" width="120" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="100" align="center">
        <el-table-column label="其它说明事项" prop="remarks" width="200" show-overflow-tooltip />
        <el-table-column fixed="right" label="操作" min-width="200" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">编辑</el-button>
<!--            <el-button link type="primary" size="small" @click="openForm('view', scope.row)">详情</el-button>-->
            <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">附件</el-button>
<!--            <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">发货</el-button>-->
            <el-button link type="primary" @click="openForm('edit', scope.row)" :disabled="!scope.row.isEdit || scope.row.hasProductionRecord || !canEditLedger(scope.row)">编辑</el-button>
            <el-button link type="primary" @click="downLoadFile(scope.row)">附件</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -149,7 +150,7 @@
          </el-col>
          <el-col :span="12">
            <el-form-item label="业务员:" prop="salesman">
              <el-select v-model="form.salesman" placeholder="请选择" clearable :disabled="operationType === 'view'">
              <el-select v-model="form.salesman" placeholder="请选择" clearable :disabled="operationType === 'view'" filterable>
                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                  :value="item.nickName" />
              </el-select>
@@ -159,7 +160,7 @@
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="客户名称:" prop="customerId">
              <el-select v-model="form.customerId" placeholder="请选择" clearable :disabled="operationType === 'view'">
              <el-select v-model="form.customerId" placeholder="请选择" clearable :disabled="operationType === 'view'" filterable>
                <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
                  {{
                    item.customerName + "——" + item.taxpayerIdentificationNumber
@@ -212,6 +213,11 @@
                              type="date" placeholder="请选择" clearable />
            </el-form-item>
          </el-col>
        <el-col :span="12">
            <el-form-item label="签订地点:" prop="placeOfSinging">
            <el-input v-model="form.placeOfSinging" placeholder="请输入" clearable :disabled="operationType === 'view'" />
            </el-form-item>
          </el-col>
        </el-row>
            <el-row>
               <el-form-item label="产品信息:" prop="entryDate">
@@ -242,14 +248,14 @@
            </el-table>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="备注·:" prop="remark">
                     <el-input v-model="form.remark" placeholder="请输入" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
                  <el-form-item label="其它说明事项:" prop="remarks">
                     <el-input v-model="form.remarks" placeholder="请输入" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
                  </el-form-item>
               </el-col>
            </el-row>
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="附件材料:" prop="remark">
                  <el-form-item label="附件材料:" prop="salesLedgerFiles">
                     <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
                                     :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
                                     :on-success="handleUploadSuccess" :on-remove="handleRemove">
@@ -308,7 +314,7 @@
            <el-table-column prop="status" label="审批状态" width="120" align="center" />
            <el-table-column prop="totalAmount" label="报价金额(元)" width="160" align="right">
               <template #default="scope">
                  {{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
                  {{ Number(scope.row.totalAmount ?? 0).toFixed(3) }}
               </template>
            </el-table-column>
            <el-table-column fixed="right" label="操作" width="120" align="center">
@@ -317,6 +323,15 @@
               </template>
            </el-table-column>
         </el-table>
         <pagination
            v-show="quotationPage.total > 0"
            :total="quotationPage.total"
            layout="total, sizes, prev, pager, next, jumper"
            :page="quotationPage.current"
            :limit="quotationPage.size"
            @pagination="quotationPaginationChange"
         />
         
         <template #footer>
            <el-button @click="quotationDialogVisible = false">关闭</el-button>
@@ -334,11 +349,8 @@
            <el-row :gutter="30">
               <el-col :span="24">
                  <el-form-item label="产品大类:" prop="productCategory">
                     <!-- <el-select v-model="productForm.productCategory" placeholder="请选择" clearable>
                        <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
                     </el-select> -->
                     <el-tree-select v-model="productForm.productCategory" placeholder="请选择" clearable check-strictly
                                             @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
                     <el-tree-select v-model="productForm.productCategory" placeholder="请选择" clearable filterable check-strictly
                                     @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
                  </el-form-item>
               </el-col>
            </el-row>
@@ -360,9 +372,10 @@
               <el-col :span="12">
                  <el-form-item label="税率(%):" prop="taxRate">
                     <el-select v-model="productForm.taxRate" placeholder="请选择" clearable @change="calculateFromTaxRate">
                        <el-option label="1" value="1" />
                        <el-option label="6" value="6" />
                        <el-option label="13" value="13" />
                        <el-option label="0" :value="0" />
                        <el-option label="1" :value="1" />
                        <el-option label="6" :value="6" />
                        <el-option label="13" :value="13" />
                     </el-select>
                  </el-form-item>
               </el-col>
@@ -371,14 +384,14 @@
               <el-col :span="12">
                  <el-form-item label="含税单价(元):" prop="taxInclusiveUnitPrice">
                     <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%"
                                              :precision="2"
                                              :precision="3"
                                              placeholder="请输入" clearable @change="calculateFromUnitPrice" />
                  </el-form-item>
               </el-col>
               <el-col :span="12">
                  <el-form-item label="数量:" prop="quantity">
                     <el-input-number  :step="0.1" :min="0" v-model="productForm.quantity" placeholder="请输入" clearable
                                                :precision="2"
                                                :precision="3"
                                                @change="calculateFromQuantity" style="width: 100%" />
                  </el-form-item>
               </el-col>
@@ -471,7 +484,7 @@
               <div v-for="(item, index) in printData" :key="index" class="print-page">
                  <div class="delivery-note">
                     <div class="header">
                        <div class="company-name">鼎诚瑞实业有限责任公司</div>
                        <div class="company-name">阳光印刷有限责任公司</div>
                        <div class="document-title">零售发货单</div>
                     </div>
                     
@@ -489,7 +502,7 @@
                        <div class="info-row">
                           <div>
                              <span class="label">客户名称:</span>
                              <span class="value">{{ item.customerName || '张爱有' }}</span>
                              <span class="value">{{ item.customerName }}</span>
                           </div>
                           <span class="label">单号:</span>
                           <span class="value">{{ item.salesContractNo }}</span>
@@ -622,7 +635,6 @@
                  <div>
                    <el-button
                      type="danger"
                      size="small"
                      @click="removeApproverNode(index)"
                      v-if="approverNodes.length > 1"
                    >删除</el-button>
@@ -665,11 +677,13 @@
   addOrUpdateSalesLedgerProduct,
   delProduct,
   delLedgerFile, getProductInventory,
   exportSalesContract
} from "@/api/salesManagement/salesLedger.js";
import { modelList, productTreeList } from "@/api/basicData/product.js";
import useFormData from "@/hooks/useFormData.js";
import dayjs from "dayjs";
import { getCurrentDate } from "@/utils/index.js";
import {listCustomerPrivatePool} from "@/api/basicData/customerFile.js";
const userStore = useUserStore();
const { proxy } = getCurrentInstance();
@@ -718,6 +732,7 @@
      entryDate: [{ required: true, message: "请选择", trigger: "change" }],
    deliveryDate: [{ required: true, message: "请选择", trigger: "change" }],
      executionDate: [{ required: true, message: "请选择", trigger: "change" }],
      placeOfSinging: [{ required: true, message: "请输入", trigger: "blur" }],
   },
});
const { form, rules } = toRefs(data);
@@ -733,7 +748,7 @@
      unit: "",
      quantity: "",
      taxInclusiveUnitPrice: "",
      taxRate: "",
      taxRate: 0,
      taxInclusiveTotalPrice: "",
      taxExclusiveTotalPrice: "",
      invoiceType: "",
@@ -749,14 +764,14 @@
      taxInclusiveUnitPrice: [
         { required: true, message: "请输入", trigger: "blur" },
      ],
      taxRate: [{ required: true, message: "请选择", trigger: "change" }],
      // taxRate: [{ required: true, message: "请选择", trigger: "change" }],
      taxInclusiveTotalPrice: [
         { required: true, message: "请输入", trigger: "blur" },
      ],
      taxExclusiveTotalPrice: [
         { required: true, message: "请输入", trigger: "blur" },
      ],
      invoiceType: [{ required: true, message: "请选择", trigger: "change" }],
      // invoiceType: [{ required: true, message: "请选择", trigger: "change" }],
   },
});
const { productForm, productRules } = toRefs(productFormData);
@@ -779,6 +794,12 @@
const quotationSearchForm = reactive({
   quotationNo: "",
   customer: "",
});
// 报价单弹框分页
const quotationPage = reactive({
   current: 1,
   size: 10,
   total: 0,
});
const selectedQuotation = ref(null);
@@ -912,7 +933,49 @@
   });
};
const formattedNumber = (row, column, cellValue) => {
   return parseFloat(cellValue).toFixed(2);
   if (cellValue === undefined || cellValue === null || cellValue === "") {
      return "0.00";
   }
   return parseFloat(cellValue).toFixed(3);
};
const findLedgerRecordByRow = (row) => {
   if (!row) return null;
   if (
      row.maintainer !== undefined ||
      row.maintainerName !== undefined ||
      row.entryPerson !== undefined ||
      row.entryPersonName !== undefined
   ) {
      return row;
   }
   if (row.salesLedgerId !== undefined && row.salesLedgerId !== null) {
      return tableData.value.find((item) => String(item.id) === String(row.salesLedgerId)) || null;
   }
   return null;
};
const isCurrentUserMaintainer = (row) => {
   const ledgerRecord = findLedgerRecordByRow(row);
   if (!ledgerRecord) return true;
   const currentUserId = String(userStore.id ?? "");
   const currentNickName = String(userStore.nickName ?? "").trim();
   const maintainerId = ledgerRecord.maintainerId ?? ledgerRecord.entryPerson;
   const maintainerName =
      ledgerRecord.maintainerName ?? ledgerRecord.maintainer ?? ledgerRecord.entryPersonName;
   if (maintainerId !== undefined && maintainerId !== null && String(maintainerId) !== "") {
      return String(maintainerId) === currentUserId;
   }
   if (maintainerName !== undefined && maintainerName !== null && String(maintainerName).trim() !== "") {
      return String(maintainerName).trim() === currentNickName;
   }
   return true;
};
const canEditLedger = (row) => isCurrentUserMaintainer(row);
const canDeleteLedger = (row) => isCurrentUserMaintainer(row);
const sensitiveAmountFormatter = (row, column, cellValue) => {
   if (!isCurrentUserMaintainer(row)) {
      return "*****";
   }
   return formattedNumber(row, column, cellValue);
};
// 获取tree子数据
const getModels = (value) => {
@@ -1004,6 +1067,7 @@
// 添加表行类名方法
const tableRowClassName = ({ row }) => {
  if (!row.deliveryDate) return '';
  if (row.isFh) return '';
  const diff = row.deliveryDaysDiff;
@@ -1023,26 +1087,50 @@
      "contractAmount",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
   ]);
   ], {
      contractAmount: { decimalPlaces: 3 },
      taxInclusiveTotalPrice: { decimalPlaces: 3 },
      taxExclusiveTotalPrice: { decimalPlaces: 3 },
   });
};
// 子表合计方法
const summarizeChildrenTable = (param) => {
const summarizeChildrenTable = (param, parentRow) => {
   if (!isCurrentUserMaintainer(parentRow)) {
      const { columns } = param;
      return columns.map((column, index) => {
         if (index === 0) {
            return "合计";
         }
         if (["taxInclusiveUnitPrice", "taxInclusiveTotalPrice", "taxExclusiveTotalPrice"].includes(column.property)) {
            return "*****";
         }
         return "";
      });
   }
   return proxy.summarizeTable(param, [
      "taxInclusiveUnitPrice",
      "taxInclusiveTotalPrice",
      "taxExclusiveTotalPrice",
   ]);
   ], {
    taxInclusiveUnitPrice: { decimalPlaces: 3 },
    taxInclusiveTotalPrice: { decimalPlaces: 3 },
    taxExclusiveTotalPrice: { decimalPlaces: 3 },
  });
};
// 打开弹框
const openForm = async (type, row) => {
   if (type === "edit" && row && !canEditLedger(row)) {
      proxy.$modal.msgWarning("当前系统登录人不是维护人,不能编辑数据");
      return;
   }
   operationType.value = type;
   form.value = {};
   productData.value = [];
   selectedQuotation.value = null;
   let userLists = await userListNoPage();
   userList.value = userLists.data;
   customerList().then((res) => {
      customerOption.value = res;
   listCustomerPrivatePool({current: -1,size:-1}).then((res) => {
      customerOption.value = res.data.records;
   });
   form.value.entryPerson = userStore.id;
   if (type === "add") {
@@ -1073,11 +1161,14 @@
const openQuotationDialog = async () => {
   if (operationType.value === "view") return;
   quotationDialogVisible.value = true;
   // 打开弹窗时重置分页到第一页
   quotationPage.current = 1;
   // 先确保客户列表已加载,便于后续回填 customerId
   if (!customerOption.value || customerOption.value.length === 0) {
      try {
         const res = await customerList();
         customerOption.value = res;
         listCustomerPrivatePool({current: -1,size:-1}).then((res) => {
            customerOption.value = res.data.records;
         });
      } catch (e) {
         // ignore,允许用户后续手动选择客户
      }
@@ -1089,14 +1180,15 @@
   quotationLoading.value = true;
   try {
      const params = {
         // 兼容后端分页字段:这里沿用报价页面已有可用的字段命名
         currentPage: 1,
         pageSize: 100,
         // 后端分页字段:current / size
         current: quotationPage.current,
         size: quotationPage.size,
         ...quotationSearchForm,
         status: "通过",
      };
      const res = await getQuotationList(params);
      quotationList.value = res?.data?.records || [];
      quotationPage.total = res?.data?.total || 0;
   } finally {
      quotationLoading.value = false;
   }
@@ -1105,7 +1197,15 @@
const resetQuotationSearch = async () => {
   quotationSearchForm.quotationNo = "";
   quotationSearchForm.customer = "";
   quotationPage.current = 1;
   await fetchQuotationList();
};
// 报价单弹框分页切换
const quotationPaginationChange = (obj) => {
   quotationPage.current = obj.page;
   quotationPage.size = obj.limit;
   fetchQuotationList();
};
// 选中报价单后回填到台账表单
@@ -1134,9 +1234,9 @@
   productData.value = products.map((p) => {
      const quantity = Number(p.quantity ?? 0) || 0;
      const unitPrice = Number(p.unitPrice ?? 0) || 0;
      const taxRate = "13"; // 默认 13%,便于直接提交(如需可在产品中自行修改)
      const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
      const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(taxInclusiveTotalPrice, taxRate);
      const taxRate = Number(p.taxRate ?? 0) || 0; // 默认 13%,便于直接提交(如需可在产品中自行修改)
      const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(3);
      const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(taxInclusiveTotalPrice, taxRate, 3);
      return {
         // 台账字段
         productCategory: p.product || p.productName || "",
@@ -1144,7 +1244,7 @@
         unit: p.unit || "",
         quantity: quantity,
         taxRate: taxRate,
         taxInclusiveUnitPrice: unitPrice.toFixed(2),
         taxInclusiveUnitPrice: unitPrice.toFixed(3),
         taxInclusiveTotalPrice: taxInclusiveTotalPrice,
         taxExclusiveTotalPrice: taxExclusiveTotalPrice,
         invoiceType: "增普票",
@@ -1212,6 +1312,7 @@
         addOrUpdateSalesLedger(form.value).then((res) => {
            proxy.$modal.msgSuccess("提交成功");
            closeDia();
            expandedRowKeys.value = [];
            getList();
         });
      }
@@ -1233,7 +1334,10 @@
   }
   
   productOperationType.value = type;
   productForm.value = {};
   productForm.value = {
      taxRate: 0,
      invoiceType: "增普票"
   };
   proxy.resetForm("productFormRef");
   if (type === "edit") {
      productForm.value = { ...row };
@@ -1268,6 +1372,7 @@
const submitProduct = () => {
   proxy.$refs["productFormRef"].validate((valid) => {
      if (valid) {
         productForm.value.taxRate = productForm.value.taxRate?productForm.value.taxRate:0;
         if (operationType.value === "edit") {
            submitProductEdit();
         } else {
@@ -1404,6 +1509,11 @@
const handleDelete = async () => {
   if (selectedRows.value.length === 0) {
      proxy.$modal.msgWarning("请选择数据");
      return;
   }
   const unauthorizedRows = selectedRows.value.filter((row) => !canDeleteLedger(row));
   if (unauthorizedRows.length > 0) {
      proxy.$modal.msgWarning("当前登录用户不是录入人,不能删除该数据");
      return;
   }
   const ids = selectedRows.value.map((item) => item.id);
@@ -1642,7 +1752,6 @@
      <div class="print-page">
        <div class="delivery-note">
          <div class="header">
            <div class="company-name">鼎诚瑞实业有限责任公司</div>
            <div class="document-title">零售发货单</div>
          </div>
          
@@ -1654,7 +1763,7 @@
              </div>
              <div>
                <span class="label">客户名称:</span>
                <span class="value">${item.customerName || '张爱有'}</span>
                <span class="value">${item.customerName}</span>
              </div>
            </div>
            <div class="info-row">
@@ -1777,7 +1886,7 @@
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.quantity) || 0);
   }, 0);
   return total.toFixed(2);
   return total.toFixed(3);
};
// 计算产品总金额
@@ -1786,7 +1895,7 @@
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
   }, 0);
   return total.toFixed(2);
   return total.toFixed(3);
};
// 用于打印的计算函数
@@ -1795,7 +1904,7 @@
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.quantity) || 0);
   }, 0);
   return total.toFixed(2);
   return total.toFixed(3);
};
const getTotalAmountForPrint = (products) => {
@@ -1803,7 +1912,7 @@
   const total = products.reduce((sum, product) => {
      return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
   }, 0);
   return total.toFixed(2);
   return total.toFixed(3);
};
const mathNum = () => {
@@ -1818,14 +1927,16 @@
   productForm.value.taxInclusiveTotalPrice =
      proxy.calculateTaxIncludeTotalPrice(
         productForm.value.taxInclusiveUnitPrice,
         productForm.value.quantity
         productForm.value.quantity,
         3
      );
   if (productForm.value.taxRate) {
      // 不含税总价计算
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            productForm.value.taxInclusiveTotalPrice,
            productForm.value.taxRate
            productForm.value.taxRate,
            3
         );
   }
};
@@ -1844,14 +1955,15 @@
   isCalculating.value = true;
   
   // 计算含税单价 = 含税总价 / 数量
   productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
   productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(3);
   
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            totalPrice,
            productForm.value.taxRate
            productForm.value.taxRate,
            3
         );
   }
   
@@ -1860,10 +1972,10 @@
// 根据不含税总价计算含税单价和数量
const calculateFromExclusiveTotalPrice = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   // if (!productForm.value.taxRate) {
   //    proxy.$modal.msgWarning("请先选择税率");
   //    return;
   // }
   if (isCalculating.value) return;
   
   const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
@@ -1879,20 +1991,20 @@
   // 先计算含税总价 = 不含税总价 / (1 - 税率/100)
   const taxRateDecimal = taxRate / 100;
   const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
   productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
   productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(3);
   
   // 计算含税单价 = 含税总价 / 数量
   productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
   productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(3);
   
   isCalculating.value = false;
};
// 根据数量变化计算总价
const calculateFromQuantity = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   // if (!productForm.value.taxRate) {
   //    proxy.$modal.msgWarning("请先选择税率");
   //    return;
   // }
   if (isCalculating.value) return;
   
   const quantity = parseFloat(productForm.value.quantity);
@@ -1905,26 +2017,29 @@
   isCalculating.value = true;
   
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(3);
   
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            productForm.value.taxInclusiveTotalPrice,
            productForm.value.taxRate
            productForm.value.taxRate,
            3
         );
   }
   }else{
    productForm.value.taxExclusiveTotalPrice = (unitPrice * quantity).toFixed(3);
  }
   
   isCalculating.value = false;
};
// 根据含税单价变化计算总价
const calculateFromUnitPrice = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   // if (!productForm.value.taxRate) {
   //    proxy.$modal.msgWarning("请先选择税率");
   //    return;
   // }
   if (isCalculating.value) return;
   
   const quantity = parseFloat(productForm.value.quantity);
@@ -1937,14 +2052,15 @@
   isCalculating.value = true;
   
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(3);
   
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
         proxy.calculateTaxExclusiveTotalPrice(
            productForm.value.taxInclusiveTotalPrice,
            productForm.value.taxRate
            productForm.value.taxRate,
            3
         );
   }
   
@@ -1953,10 +2069,10 @@
// 根据税率变化计算不含税总价
const calculateFromTaxRate = () => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   // if (!productForm.value.taxRate) {
   //    proxy.$modal.msgWarning("请先选择税率");
   //    return;
   // }
   if (isCalculating.value) return;
   
   const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
@@ -1972,7 +2088,8 @@
   productForm.value.taxExclusiveTotalPrice =
      proxy.calculateTaxExclusiveTotalPrice(
         inclusiveTotalPrice,
         taxRate
         taxRate,
         3
      );
   
   isCalculating.value = false;
@@ -2045,8 +2162,8 @@
 * @param row 行数据
 */
const canShip = (row) => {
   // 产品状态必须是充足(approveStatus === 1)
   if (row.approveStatus !== 1) {
   // 产品状态必须是充足(基于 hasSufficientStock 判断)
   if (!row || !row.hasSufficientStock) {
      return false;
   }
   
@@ -2062,6 +2179,34 @@
   const statusStr = shippingStatus ? String(shippingStatus).trim() : '';
   return statusStr === '待发货' || statusStr === '审核拒绝';
};
/**
 * 导出销售合同
 *
 * @param row 导出销售合同的相关信息对象
 */
const exportSalesContracts = (row) => {
   exportSalesContract({ id: row.id }).then((res) => {
      if (res) {
         const downloadUrl = window.URL.createObjectURL(res);
      const link = document.createElement('a');
      link.href = downloadUrl;
     console.log(row.executionDate)
      link.download = row.projectName+row.executionDate + "销售合同.docx"; // 设置下载文件名
      link.style.display = 'none'; // 隐藏a标签
      document.body.appendChild(link);
      link.click(); // 触发点击下载
      // 4. 清理资源(避免内存泄漏)
      document.body.removeChild(link);
      window.URL.revokeObjectURL(downloadUrl);
      // 5. 提示导出成功
      proxy.$modal.msgSuccess("导出销售合同成功");
      } else {
         proxy.$modal.msgError(res.msg || "导出销售合同失败");
      }
   });
}
/**
 * 下载文件
@@ -2168,19 +2313,19 @@
   margin-left: 10px;
}
::v-deep .yellow {
:deep(.yellow) {
  background-color: #FAF0DE;
}
::v-deep .pink {
:deep(.pink) {
  background-color: #FAE1DE;
}
::v-deep .red {
:deep(.red) {
  background-color: #FAE1DE;
}
::v-deep .purple{
:deep(.purple){
  background-color: #F4DEFA;
}