gongchunyi
2 天以前 0a3b748bd80bc33dc5b7eb8e90a7fb394e703b07
src/views/salesManagement/salesLedger/components/salesDeliveryPrint.js
@@ -30,6 +30,84 @@
const getOrderNo = (data, row, item) =>
  item?.salesContractNo || item?.orderNo || data?.salesContractNo || row?.salesContractNo || "";
const PRODUCT_NAME_FIELD_KEYS = [
  "productDescription",
  "productName",
  "name",
  "title",
  "goodsName",
  "materialName",
  "glassName",
];
const PRODUCT_NAME_LIST_FIELD_KEYS = [
  "productDescriptionList",
  "productNameList",
  "productDescriptions",
  "productNames",
  "nameList",
  "goodsNameList",
  "detailProductNames",
  "productInfoList",
];
const SPECIFICATION_FIELD_KEYS = ["specificationModel", "specification", "model", "spec"];
const normalizeNameList = (value) => {
  if (Array.isArray(value)) {
    return value
      .flatMap((item) => normalizeNameList(item))
      .map((item) => String(item).trim())
      .filter(Boolean);
  }
  if (value && typeof value === "object") {
    const objectListNames = PRODUCT_NAME_LIST_FIELD_KEYS.flatMap((key) => normalizeNameList(value?.[key]));
    if (objectListNames.length) return objectListNames;
    return PRODUCT_NAME_FIELD_KEYS.flatMap((key) => normalizeNameList(value?.[key]));
  }
  if (typeof value === "string") {
    const text = value.trim();
    if (!text) return [];
    const parts = text
      .split(/[,\n,、;;]/)
      .map((item) => item.trim())
      .filter(Boolean);
    return parts.length > 1 ? parts : [text];
  }
  if (value === null || value === undefined) return [];
  const text = String(value).trim();
  return text ? [text] : [];
};
const extractNameListByKeys = (source, keys) => {
  if (!source || typeof source !== "object") return [];
  return keys.flatMap((key) => normalizeNameList(source?.[key]));
};
const resolveProductName = (item, fallbackNames, index) => {
  const itemNames = [
    ...extractNameListByKeys(item, PRODUCT_NAME_LIST_FIELD_KEYS),
    ...extractNameListByKeys(item, PRODUCT_NAME_FIELD_KEYS),
  ];
  if (itemNames.length > 1) {
    return itemNames[index] || itemNames[0] || "";
  }
  return itemNames[0] || fallbackNames[index] || fallbackNames[0] || "";
};
const resolveSpecificationModel = (...sources) => {
  for (const source of sources) {
    if (!source || typeof source !== "object") continue;
    for (const key of SPECIFICATION_FIELD_KEYS) {
      const value = source?.[key];
      if (value !== undefined && value !== null && String(value).trim()) {
        return String(value).trim();
      }
    }
  }
  return "";
};
const splitItemsByPage = (items, pageSize) => {
  const list = Array.isArray(items) ? items : [];
  if (list.length === 0) return [[]];
@@ -42,19 +120,38 @@
const normalizeInvoiceData = (raw, selectedRow) => {
  const data = raw ?? {};
  const groups = Array.isArray(data.groups) ? data.groups : [];
  if (!groups.length) return data;
  const groups = Array.isArray(data.groups)
    ? data.groups
    : Array.isArray(data.groupList)
      ? data.groupList
      : [];
  const dataLevelNames = [
    ...extractNameListByKeys(data, PRODUCT_NAME_LIST_FIELD_KEYS),
    ...extractNameListByKeys(data, PRODUCT_NAME_FIELD_KEYS),
  ];
  const items = groups.flatMap((group) =>
    (Array.isArray(group?.items) ? group.items : []).map((item) => ({
      ...item,
      // 优先使用明细自身产品名,避免分组名称覆盖导致“一个产品名挂多种明细”
      productDescription:
        item?.productDescription || item?.productName || group?.productName || "",
      salesContractNo: group?.salesContractNo || item?.salesContractNo || "",
      widthHeight: item?.widthHeight || "",
    }))
  );
  const items = groups.length
    ? groups.flatMap((group) => {
        const groupItems = Array.isArray(group?.items) ? group.items : [];
        const groupNames = [
          ...extractNameListByKeys(group, PRODUCT_NAME_LIST_FIELD_KEYS),
          ...extractNameListByKeys(group, PRODUCT_NAME_FIELD_KEYS),
        ];
        return groupItems.map((item, index) => ({
          ...item,
          // 优先使用明细自身产品名,兼容“名称数组/分隔字符串”的接口格式
          productDescription: resolveProductName(item, groupNames, index),
          specificationModel: resolveSpecificationModel(item, group, data),
          salesContractNo: group?.salesContractNo || item?.salesContractNo || "",
          widthHeight: item?.widthHeight || "",
        }));
      })
    : (Array.isArray(data.items) ? data.items : []).map((item, index) => ({
        ...item,
        productDescription: resolveProductName(item, dataLevelNames, index),
        specificationModel: resolveSpecificationModel(item, data, selectedRow),
        widthHeight: item?.widthHeight || "",
      }));
  return {
    ...data,
@@ -74,10 +171,15 @@
  const list = Array.isArray(items) ? items : [];
  const map = new Map();
  list.forEach((item) => {
    const key = `${item?.productDescription || ""}__${getOrderNo(data, row, item)}`;
    const key = `${item?.productDescription || ""}__${item?.specificationModel || ""}__${getOrderNo(
      data,
      row,
      item
    )}`;
    if (!map.has(key)) {
      map.set(key, {
        productName: item?.productDescription || "",
        specificationModel: item?.specificationModel || "",
        orderNo: getOrderNo(data, row, item),
        items: [],
      });
@@ -259,7 +361,7 @@
                  serial += group.items.length;
                  return `
          <tr class="group-title">
            <td colspan="5" class="left">产品名称: ${escapeHtml(group.productName)}</td>
            <td colspan="5" class="left">产品名称: ${escapeHtml(group.productName)}${group.specificationModel ? ` 规格型号: ${escapeHtml(group.specificationModel)}` : ""}</td>
            <td colspan="2" class="left">订单编号: ${escapeHtml(group.orderNo)}</td>
          </tr>
          ${rows}