diff --git a/frontend/src/pages/Expansion.tsx b/frontend/src/pages/Expansion.tsx index 4c3a616c..010631ba 100644 --- a/frontend/src/pages/Expansion.tsx +++ b/frontend/src/pages/Expansion.tsx @@ -323,9 +323,36 @@ function formatExportProjectListCell(projects?: Array<{ opportunityCode?: string } return projects - .map((project, index) => { + .map((project) => { const content = formatExportProjectCell(project); - return content ? `项目${index + 1} ${content}` : ""; + return content || ""; + }) + .filter(Boolean) + .join("\n"); +} + +function formatExportContactCell(contact?: { name?: string | null; mobile?: string | null; title?: string | null }) { + if (!contact) { + return ""; + } + + const segments = [ + normalizeExportText(contact.name) ? `姓名:${normalizeExportText(contact.name)}` : "", + normalizeExportText(contact.mobile) ? `联系电话:${normalizeExportText(contact.mobile)}` : "", + normalizeExportText(contact.title) ? `职位:${normalizeExportText(contact.title)}` : "", + ].filter(Boolean); + return segments.join("|"); +} + +function formatExportContactListCell(contacts?: Array<{ name?: string | null; mobile?: string | null; title?: string | null }>) { + if (!contacts?.length) { + return ""; + } + + return contacts + .map((contact) => { + const content = formatExportContactCell(contact); + return content || ""; }) .filter(Boolean) .join("\n"); @@ -421,7 +448,6 @@ function buildSalesExportData(items: SalesExpansionItem[]) { } function buildChannelExportHeaders(items: ChannelExpansionItem[]) { - const maxContacts = Math.max(0, ...items.map((item) => item.contacts?.length ?? 0)); const headers = [ "编码", "渠道名称", @@ -439,12 +465,9 @@ function buildChannelExportHeaders(items: ChannelExpansionItem[]) { "以前是否做过云桌面项目", "跟进项目金额", "项目信息", + "人员信息", ]; - for (let index = 0; index < maxContacts; index += 1) { - headers.push(`人员${index + 1}姓名`, `人员${index + 1}联系电话`, `人员${index + 1}职位`); - } - headers.push("备注说明"); headers.push("创建人", "更新修改时间"); headers.push("跟进记录"); @@ -452,8 +475,6 @@ function buildChannelExportHeaders(items: ChannelExpansionItem[]) { } function buildChannelExportData(items: ChannelExpansionItem[]) { - const maxContacts = Math.max(0, ...items.map((item) => item.contacts?.length ?? 0)); - return items.map((item) => { const row = [ normalizeExportText(item.channelCode), @@ -472,17 +493,9 @@ function buildChannelExportData(items: ChannelExpansionItem[]) { formatExportBoolean(item.hasDesktopExp), normalizeExportText(formatRelatedProjectAmount(item.relatedProjects)), formatExportProjectListCell(item.relatedProjects), + formatExportContactListCell(item.contacts), ]; - for (let index = 0; index < maxContacts; index += 1) { - const contact = item.contacts?.[index]; - row.push( - normalizeExportText(contact?.name), - normalizeExportText(contact?.mobile), - normalizeExportText(contact?.title), - ); - } - row.push(normalizeExportText(item.notes)); row.push( normalizeExportText(item.owner), @@ -1643,6 +1656,7 @@ export default function Expansion() { worksheet.views = [{ state: "frozen", ySplit: 1 }]; const projectInfoColumnIndex = headers.indexOf("项目信息") + 1; + const contactInfoColumnIndex = headers.indexOf("人员信息") + 1; worksheet.getRow(1).height = 24; worksheet.getRow(1).font = { bold: true }; worksheet.getRow(1).alignment = { vertical: "middle", horizontal: "center" }; @@ -1663,6 +1677,22 @@ export default function Expansion() { ), ) : 30; + const contactInfoColumnWidth = contactInfoColumnIndex > 0 + ? Math.min( + 80, + Math.max( + 16, + getExcelDisplayWidth(headers[contactInfoColumnIndex - 1] || "") + 2, + rows.reduce((maxWidth, row) => { + const cellValue = row[contactInfoColumnIndex - 1]; + const longestLineWidth = typeof cellValue === "string" + ? cellValue.split("\n").reduce((lineMax, line) => Math.max(lineMax, getExcelDisplayWidth(line)), 0) + : 0; + return Math.max(maxWidth, longestLineWidth + 2); + }, 0), + ), + ) + : 30; headers.forEach((header, index) => { const column = worksheet.getColumn(index + 1); @@ -1670,6 +1700,8 @@ export default function Expansion() { column.width = 42; } else if (header === "项目信息") { column.width = projectInfoColumnWidth; + } else if (header === "人员信息") { + column.width = contactInfoColumnWidth; } else if (header.includes("办公地址") || header.includes("备注")) { column.width = 24; } else if (header.includes("渠道属性") || header.includes("内部属性") || header.includes("聚焦行业")) { @@ -1690,7 +1722,7 @@ export default function Expansion() { cell.alignment = { vertical: "top", horizontal: rowNumber === 1 ? "center" : "left", - wrapText: headers[columnNumber - 1] === "跟进记录" || headers[columnNumber - 1] === "项目信息", + wrapText: headers[columnNumber - 1] === "跟进记录" || headers[columnNumber - 1] === "项目信息" || headers[columnNumber - 1] === "人员信息", }; }); if (rowNumber > 1) { @@ -1699,7 +1731,12 @@ export default function Expansion() { typeof projectText === "string" ? projectText : "", projectInfoColumnWidth, ); - row.height = Math.max(22, projectLineCount * 16); + const contactText = contactInfoColumnIndex > 0 ? row.getCell(contactInfoColumnIndex).value as string | null | undefined : ""; + const contactLineCount = getExcelWrappedLineCount( + typeof contactText === "string" ? contactText : "", + contactInfoColumnWidth, + ); + row.height = Math.max(22, Math.max(projectLineCount, contactLineCount) * 16); } });