gongchunyi
4 天以前 989d2e51cb7295ab79b285f4682d41ae2164a933
src/views/salesManagement/salesLedger/index.vue
@@ -35,27 +35,30 @@
          :bound-route-name="processFlowSelectBoundRouteName"
          @confirm="handleProcessFlowSelectConfirm"
        />
        <div>
          <el-button type="primary" @click="openForm('add')">
            新增台账
          </el-button>
        <el-button type="primary"  @click="handleBulkDelivery">
            发货
          </el-button>
          <el-button type="primary" plain @click="handleImport">导入</el-button>
          <el-button @click="handleOut">导出</el-button>
          <el-button type="danger" plain @click="handleDelete">删除</el-button>
          <el-dropdown @command="handlePrintCommand">
            <el-button type="primary" plain>
              打印单据<el-icon class="el-icon--right"><ArrowDown /></el-icon>
            </el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item command="finishedProcessCard">打印生产流程卡(成品)</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
         <el-space wrap>
               <el-button type="primary" @click="openForm('add')">新增台账</el-button>
               <el-button type="primary" @click="handleBulkDelivery">发货</el-button>
               <el-button type="primary" plain @click="handleImport">导入</el-button>
               <el-button @click="handleOut">导出</el-button>
               <el-button type="danger" plain @click="handleDelete">删除</el-button>
               <el-dropdown @command="handlePrintCommand">
                  <el-button type="primary" plain>
                     打印单据<el-icon class="el-icon--right">
                        <ArrowDown />
                     </el-icon>
                  </el-button>
                  <template #dropdown>
                     <el-dropdown-menu>
                        <el-dropdown-item command="finishedProcessCard">生产流程卡(成品)</el-dropdown-item>
                        <el-dropdown-item command="salesOrder">销售订单</el-dropdown-item>
                        <el-dropdown-item command="salesDeliveryNote">销售发货单</el-dropdown-item>
                     </el-dropdown-menu>
                  </template>
               </el-dropdown>
               <el-button type="primary" plain @click="handlePrintLabel">打印标签</el-button>
            </el-space>
      </div>
      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
        :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" :row-class-name="tableRowClassName" show-summary style="width: 100%"
@@ -65,13 +68,42 @@
          <template #default="props">
            <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
              <el-table-column align="center" label="序号" type="index"/>
         <el-table-column label="楼层编号" prop="floorCode" min-width="100" show-overflow-tooltip />
              <el-table-column label="产品大类" prop="productCategory" />
              <el-table-column label="规格型号" prop="specificationModel" />
              <el-table-column label="厚度" prop="thickness" min-width="90">
                <template #default="scope">
                  {{ scope.row.thickness ?? "" }}
                </template>
              </el-table-column>
                  </el-table-column>
                     <el-table-column label="宽(mm)" prop="width" min-width="80">
                        <template #default="scope">
                           {{ scope.row.width ?? "" }}
                        </template>
                     </el-table-column>
                     <el-table-column label="高(mm)" prop="height" min-width="80">
                        <template #default="scope">
                           {{ scope.row.height ?? "" }}
                        </template>
                     </el-table-column>
                     <el-table-column label="周长(cm)" prop="perimeter" min-width="90">
                        <template #default="scope">
                           {{ scope.row.perimeter ?? "" }}
                        </template>
                     </el-table-column>
                     <el-table-column label="总面积(cm²)" prop="actualTotalArea" min-width="100">
                        <template #default="scope">
                           {{ scope.row.actualTotalArea ?? "" }}
                        </template>
                     </el-table-column>
                     <el-table-column label="加工要求" prop="processRequirement" min-width="120"
                        show-overflow-tooltip />
                     <el-table-column label="备注" prop="remark" min-width="120" show-overflow-tooltip />
                     <el-table-column label="重箱" prop="heavyBox" min-width="80">
                        <template #default="scope">
                           {{ scope.row.heavyBox ?? "" }}
                        </template>
                     </el-table-column>
                     <el-table-column label="产品状态"
                                              width="100px"
                                              align="center">
@@ -255,6 +287,21 @@
               <el-table-column label="厚度" prop="thickness" min-width="90">
                  <template #default="scope">
                     {{ scope.row.thickness ?? "" }}
                  </template>
               </el-table-column>
               <el-table-column label="宽(mm)" prop="width" min-width="80">
                  <template #default="scope">
                     {{ scope.row.width ?? "" }}
                  </template>
               </el-table-column>
               <el-table-column label="高(mm)" prop="height" min-width="80">
                  <template #default="scope">
                     {{ scope.row.height ?? "" }}
                  </template>
               </el-table-column>
               <el-table-column label="面积(m²)" prop="actualTotalArea" min-width="100">
                  <template #default="scope">
                     {{ scope.row.actualTotalArea ?? "" }}
                  </template>
               </el-table-column>
               <el-table-column label="数量" prop="quantity" />
@@ -577,7 +624,7 @@
                        style="width: 100%"
                        placeholder="请输入"
                        clearable
                        @change="recalcAreaTotals"
                        @change="() => { recalcAreaTotals(); calculateFromUnitPrice(true); }"
                     />
                  </el-form-item>
               </el-col>
@@ -890,12 +937,18 @@
   saleProcessBind,
   getSaleProcessBindInfo,
   getProcessCard,
   getSalesOrder,
   getSalesInvoices,
   getSalesLabel,
} 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 { printFinishedProcessCard } from "./components/processCardPrint.js";
import { printSalesOrder } from "./components/salesOrderPrint.js";
import { printSalesDeliveryNote } from "./components/salesDeliveryPrint.js";
import { printSalesLabel } from "./components/salesLabelPrint.js";
// import { salesLedgerProductSetProcessFlowConfig } from "@/api/salesManagement/salesProcessFlowConfig.js";
const userStore = useUserStore();
@@ -1640,8 +1693,9 @@
   productData.value = products.map((p) => {
      const quantity = Number(p.quantity ?? 0) || 0;
      const unitPrice = Number(p.unitPrice ?? 0) || 0;
      const settlePieceArea = Number(p.settlePieceArea ?? 0) || 1;
      const taxRate = "13"; // 默认 13%,便于直接提交(如需可在产品中自行修改)
      const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
      const taxInclusiveTotalPrice = (unitPrice * settlePieceArea * quantity).toFixed(2);
      const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(taxInclusiveTotalPrice, taxRate);
      return {
         // 台账字段
@@ -2023,27 +2077,114 @@
};
const handlePrintCommand = async (command) => {
   if (command !== "finishedProcessCard") return;
   if (selectedRows.value.length !== 1) {
   if (command !== "finishedProcessCard" && command !== "salesOrder" && command !== "salesDeliveryNote") return;
   if (command === "salesDeliveryNote") {
      if (selectedRows.value.length === 0) {
         proxy.$modal.msgWarning("请至少选择一条销售台账数据进行打印");
         return;
      }
      const customerNames = Array.from(
         new Set(selectedRows.value.map((item) => String(item?.customerName ?? "").trim()))
      );
      if (customerNames.length > 1) {
         proxy.$modal.msgWarning("仅支持相同客户名称的销售台账合并发货打印");
         return;
      }
   } else if (selectedRows.value.length !== 1) {
      proxy.$modal.msgWarning("请选择一条销售台账数据进行打印");
      return;
   }
   const selectedRow = selectedRows.value[0];
   const selectedId = selectedRow?.id;
   if (command === "salesDeliveryNote") {
      const selectedIds = selectedRows.value
         .map((item) => item?.id)
         .filter((id) => id !== null && id !== undefined && id !== "");
      if (selectedIds.length !== selectedRows.value.length) {
         proxy.$modal.msgWarning("当前选择数据存在缺少ID的记录,无法打印");
         return;
      }
      const loadingText =
         command === "salesOrder"
            ? "正在获取销售订单数据,请稍候..."
            : command === "salesDeliveryNote"
               ? "正在获取销售发货单数据,请稍候..."
               : "正在获取生产流程卡数据,请稍候...";
      proxy.$modal.loading(loadingText);
      try {
         const res = await getSalesInvoices(selectedIds);
         const salesInvoiceData = res?.data ?? {};
         printSalesDeliveryNote(salesInvoiceData, selectedRow);
      } catch (error) {
         console.error("打印销售发货单失败:", error);
         proxy.$modal.msgError("打印失败,请稍后重试");
      } finally {
         proxy.$modal.closeLoading();
      }
      return;
   }
   if (!selectedId) {
      proxy.$modal.msgWarning("当前选择数据缺少ID,无法打印");
      return;
   }
   proxy.$modal.loading("正在获取生产流程卡数据,请稍候...");
   const loadingText =
      command === "salesOrder"
         ? "正在获取销售订单数据,请稍候..."
         : command === "salesDeliveryNote"
            ? "正在获取销售发货单数据,请稍候..."
            : "正在获取生产流程卡数据,请稍候...";
   proxy.$modal.loading(loadingText);
   try {
      const res = await getProcessCard(selectedId);
      const processCardData = res?.data ?? {};
      printFinishedProcessCard(processCardData);
      if (command === "salesOrder") {
         const res = await getSalesOrder(selectedId);
         const salesOrderData = res?.data ?? {};
         printSalesOrder(salesOrderData);
      } else {
         const res = await getProcessCard(selectedId);
         const processCardData = res?.data ?? {};
         printFinishedProcessCard(processCardData);
      }
   } catch (error) {
      console.error("打印生产流程卡失败:", error);
      console.error(
         command === "salesOrder"
            ? "打印销售订单失败:"
            : command === "salesDeliveryNote"
               ? "打印销售发货单失败:"
               : "打印生产流程卡失败:",
         error
      );
      proxy.$modal.msgError("打印失败,请稍后重试");
   } finally {
      proxy.$modal.closeLoading();
   }
};
const handlePrintLabel = async () => {
   if (selectedRows.value.length !== 1) {
      proxy.$modal.msgWarning("请选择一条销售台账数据进行标签打印");
      return;
   }
   const selectedId = selectedRows.value[0]?.id;
   if (!selectedId) {
      proxy.$modal.msgWarning("当前选择数据缺少ID,无法打印标签");
      return;
   }
   proxy.$modal.loading("正在获取标签数据,请稍候...");
   try {
      const res = await getSalesLabel(selectedId);
      const labelList = res?.data ?? [];
      if (!Array.isArray(labelList) || labelList.length === 0) {
         proxy.$modal.msgWarning("暂无可打印标签数据");
         return;
      }
      printSalesLabel(labelList);
   } catch (error) {
      console.error("打印标签失败:", error);
      proxy.$modal.msgError("打印标签失败,请稍后重试");
   } finally {
      proxy.$modal.closeLoading();
   }
@@ -2057,10 +2198,11 @@
   if (!productForm.value.quantity) {
      return;
   }
   // 含税总价计算
   const settlePieceArea = parseFloat(productForm.value.settlePieceArea) || 1;
   // 含税总价计算 = 单价 * 结算面积 * 数量
   productForm.value.taxInclusiveTotalPrice =
      proxy.calculateTaxIncludeTotalPrice(
         productForm.value.taxInclusiveUnitPrice,
         productForm.value.taxInclusiveUnitPrice * settlePieceArea,
         productForm.value.quantity
      );
   if (productForm.value.taxRate) {
@@ -2123,15 +2265,12 @@
   const computed = Number(computedPieceArea.toFixed(5));
   productForm.value.actualPieceArea = computed;
   // settlePieceArea:若用户未填写/为0,则默认使用宽高计算值
   const settlePieceRaw = Number(productForm.value.settlePieceArea ?? 0) || 0;
   if (!settlePieceRaw) {
      productForm.value.settlePieceArea = computed;
   }
   productForm.value.settlePieceArea = computed;
   recalcPerimeterFromWidthHeight();
   recalcAreaTotals();
   // 面积更新后,重新计算含税总价 = 单价 * 结算面积 * 数量
   calculateFromUnitPrice(true);
};
// 根据含税总价计算含税单价和数量
@@ -2198,19 +2337,20 @@
      return;
   }
   if (isCalculating.value) return;
   const quantity = parseFloat(productForm.value.quantity);
   const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
   const settlePieceArea = parseFloat(productForm.value.settlePieceArea) || 1;
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   isCalculating.value = true;
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 计算含税总价 = 单价 * 结算面积 * 数量
   productForm.value.taxInclusiveTotalPrice = (unitPrice * settlePieceArea * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
@@ -2219,30 +2359,31 @@
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};
// 根据含税单价变化计算总价
const calculateFromUnitPrice = () => {
const calculateFromUnitPrice = (silent = false) => {
   if (!productForm.value.taxRate) {
      proxy.$modal.msgWarning("请先选择税率");
      if (!silent) proxy.$modal.msgWarning("请先选择税率");
      return;
   }
   if (isCalculating.value) return;
   const quantity = parseFloat(productForm.value.quantity);
   const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
   const settlePieceArea = parseFloat(productForm.value.settlePieceArea) || 1;
   if (!quantity || quantity <= 0 || !unitPrice) {
      return;
   }
   isCalculating.value = true;
   // 计算含税总价
   productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
   // 计算含税总价 = 单价 * 结算面积 * 数量
   productForm.value.taxInclusiveTotalPrice = (unitPrice * settlePieceArea * quantity).toFixed(2);
   // 如果有税率,计算不含税总价
   if (productForm.value.taxRate) {
      productForm.value.taxExclusiveTotalPrice =
@@ -2251,7 +2392,7 @@
            productForm.value.taxRate
         );
   }
   isCalculating.value = false;
};