From 7cf9530b070d8363d5b0577a88bfa2239130664f Mon Sep 17 00:00:00 2001 From: cody <648753004@qq.com> Date: Wed, 26 Nov 2025 21:25:56 +0800 Subject: [PATCH] update --- app/Exports/CommonExport.php | 153 ++++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 37 deletions(-) diff --git a/app/Exports/CommonExport.php b/app/Exports/CommonExport.php index 4367da7..8b1f56b 100755 --- a/app/Exports/CommonExport.php +++ b/app/Exports/CommonExport.php @@ -20,7 +20,7 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With public $fields; public $data; public $hasUsersField = false; - public $usersColumnStartIndex = null; + public $hasProjectUsersField = false; public $totalColumns = 0; public $totalRows = 0; public $expandedFields = []; @@ -37,6 +37,14 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With 'user_sign_date' => '报名时间', ]; + // 项目经理信息子列定义 + const PROJECT_USERS_SUB_COLUMNS = [ + 'pm_platform' => '管理平台', + 'pm_name' => '项目经理', + 'pm_invest_date' => '首次出资时间', + 'pm_amount' => '投资金额', + ]; + public function __construct($data, $exportFields) { // 需要导出的字段。格式:['name'=>'名字','user.sex'=>'性别'] @@ -49,7 +57,7 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With } /** - * 构建扩展后的字段列表(将users字段展开成多列) + * 构建扩展后的字段列表(将users和project_users字段展开成多列) */ private function buildExpandedFields() { @@ -59,14 +67,20 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With $index = 1; foreach ($this->fields as $field => $label) { - if (str_contains($field, 'users')) { + if (str_contains($field, 'users') && !str_contains($field, 'project_users')) { $this->hasUsersField = true; - $this->usersColumnStartIndex = $index; // 展开学员信息为多列 foreach (self::USERS_SUB_COLUMNS as $subField => $subLabel) { $this->expandedFields[$subField] = $subLabel; $index++; } + } elseif (str_contains($field, 'project_users')) { + $this->hasProjectUsersField = true; + // 展开项目经理信息为多列 + foreach (self::PROJECT_USERS_SUB_COLUMNS as $subField => $subLabel) { + $this->expandedFields[$subField] = $subLabel; + $index++; + } } else { $this->expandedFields[$field] = $label; $index++; @@ -75,6 +89,14 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With $this->totalColumns = count($this->expandedFields); } + /** + * 是否需要二级表头 + */ + private function needsDoubleHeader() + { + return $this->hasUsersField || $this->hasProjectUsersField; + } + /** * 获取列字母 */ @@ -100,11 +122,13 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With $letter = $this->getColumnLetter($index); if (in_array($field, ['user_course', 'user_name'])) { $widths[$letter] = 25; - } elseif (in_array($field, ['user_mobile', 'user_sign_date'])) { + } elseif (in_array($field, ['user_mobile', 'user_sign_date', 'pm_invest_date', 'pm_amount'])) { $widths[$letter] = 15; } elseif (in_array($field, ['user_index', 'user_schoolmate'])) { $widths[$letter] = 8; - } elseif (str_contains($field, 'partners') || str_contains($field, 'project_users')) { + } elseif (in_array($field, ['pm_platform', 'pm_name'])) { + $widths[$letter] = 18; + } elseif (str_contains($field, 'partners')) { $widths[$letter] = 50; } elseif (str_contains($field, 'all_course')) { $widths[$letter] = 40; @@ -124,11 +148,11 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With public function styles(Worksheet $sheet): array { $lastCol = $this->getColumnLetter($this->totalColumns); - $dataStartRow = $this->hasUsersField ? 3 : 2; + $dataStartRow = $this->needsDoubleHeader() ? 3 : 2; $styles = []; - if ($this->hasUsersField) { + if ($this->needsDoubleHeader()) { // 二级表头样式 - 第一行 $styles[1] = [ 'font' => ['bold' => true, 'size' => 12], @@ -194,7 +218,7 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With AfterSheet::class => function (AfterSheet $event) { $sheet = $event->sheet->getDelegate(); - if ($this->hasUsersField) { + if ($this->needsDoubleHeader()) { // 处理二级表头的单元格合并 $this->mergeHeaderCells($sheet); @@ -210,7 +234,7 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With } // 设置数据行高 - $dataStartRow = $this->hasUsersField ? 3 : 2; + $dataStartRow = $this->needsDoubleHeader() ? 3 : 2; for ($row = $dataStartRow; $row <= $this->totalRows + $dataStartRow - 1; $row++) { $sheet->getRowDimension($row)->setRowHeight(22); } @@ -225,17 +249,22 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With { $index = 1; foreach ($this->fields as $field => $label) { - if (str_contains($field, 'users')) { + if (str_contains($field, 'users') && !str_contains($field, 'project_users')) { // 学员信息列:合并第一行的多个单元格 $startCol = $this->getColumnLetter($index); $endCol = $this->getColumnLetter($index + count(self::USERS_SUB_COLUMNS) - 1); $sheet->mergeCells("{$startCol}1:{$endCol}1"); $sheet->setCellValue("{$startCol}1", $label); - - // 学员信息子表头不需要合并 $index += count(self::USERS_SUB_COLUMNS); + } elseif (str_contains($field, 'project_users')) { + // 项目经理信息列:合并第一行的多个单元格 + $startCol = $this->getColumnLetter($index); + $endCol = $this->getColumnLetter($index + count(self::PROJECT_USERS_SUB_COLUMNS) - 1); + $sheet->mergeCells("{$startCol}1:{$endCol}1"); + $sheet->setCellValue("{$startCol}1", $label); + $index += count(self::PROJECT_USERS_SUB_COLUMNS); } else { - // 非学员信息列:合并第一行和第二行 + // 其他列:合并第一行和第二行 $col = $this->getColumnLetter($index); $sheet->mergeCells("{$col}1:{$col}2"); $sheet->setCellValue("{$col}1", $label); @@ -260,16 +289,19 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With $newList = []; - if ($this->hasUsersField) { - // 有学员字段:创建二级表头 + if ($this->needsDoubleHeader()) { + // 有需要展开的字段:创建二级表头 // 第一行表头(主表头)- 在 mergeHeaderCells 中处理 $header1 = []; foreach ($this->fields as $field => $label) { - if (str_contains($field, 'users')) { - // 学员信息占用多列,第一行只需要占位 + if (str_contains($field, 'users') && !str_contains($field, 'project_users')) { foreach (self::USERS_SUB_COLUMNS as $subLabel) { $header1[] = ''; } + } elseif (str_contains($field, 'project_users')) { + foreach (self::PROJECT_USERS_SUB_COLUMNS as $subLabel) { + $header1[] = ''; + } } else { $header1[] = ''; } @@ -279,33 +311,36 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With // 第二行表头(子表头) $header2 = []; foreach ($this->fields as $field => $label) { - if (str_contains($field, 'users')) { + if (str_contains($field, 'users') && !str_contains($field, 'project_users')) { foreach (self::USERS_SUB_COLUMNS as $subLabel) { $header2[] = $subLabel; } + } elseif (str_contains($field, 'project_users')) { + foreach (self::PROJECT_USERS_SUB_COLUMNS as $subLabel) { + $header2[] = $subLabel; + } } else { $header2[] = ''; } } $newList[] = $header2; - // 数据行:每个学员的每条课程记录占一行 + // 数据行:每个展开记录占一行 foreach ($this->data as $info) { - $usersData = $this->getUsersExpanded($info); - if (empty($usersData)) { - // 没有学员数据,输出一行空数据 - $row = $this->buildRowWithoutUsers($info, []); + $expandedRows = $this->getExpandedRows($info); + if (empty($expandedRows)) { + // 没有展开数据,输出一行空数据 + $row = $this->buildExpandedRow($info, [], []); $newList[] = $row; } else { - // 每个学员记录一行 - foreach ($usersData as $userData) { - $row = $this->buildRowWithoutUsers($info, $userData); + foreach ($expandedRows as $expandedRow) { + $row = $this->buildExpandedRow($info, $expandedRow['users'] ?? [], $expandedRow['project_users'] ?? []); $newList[] = $row; } } } } else { - // 没有学员字段:使用原有逻辑 + // 没有需要展开的字段:使用原有逻辑 $header = array_values($this->fields); $moreFileds = []; if (empty($clear)) { @@ -326,8 +361,6 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With $temp[$field] = $this->allCourse($info); } elseif (str_contains($field, 'partners')) { $temp[$field] = $this->partners($info); - } elseif (str_contains($field, 'project_users')) { - $temp[$field] = $this->projectManager($info); } else { $temp[$field] = $this->getDotValue($info, $field); } @@ -350,10 +383,53 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With } } - $this->totalRows = count($newList) - ($this->hasUsersField ? 2 : 1); + $this->totalRows = count($newList) - ($this->needsDoubleHeader() ? 2 : 1); return new Collection($newList); } + /** + * 获取展开后的所有行数据 + */ + private function getExpandedRows($info) + { + $usersData = $this->hasUsersField ? $this->getUsersExpanded($info) : []; + $projectUsersData = $this->hasProjectUsersField ? $this->getProjectUsersExpanded($info) : []; + + // 计算最大行数 + $maxRows = max(count($usersData), count($projectUsersData), 1); + + $result = []; + for ($i = 0; $i < $maxRows; $i++) { + $result[] = [ + 'users' => $usersData[$i] ?? [], + 'project_users' => $projectUsersData[$i] ?? [], + ]; + } + + return $result; + } + + /** + * 获取展开的项目经理数据(每条记录一行) + */ + private function getProjectUsersExpanded($info) + { + if (empty($info['project_users'])) { + return []; + } + + $result = []; + foreach ($info['project_users'] as $item) { + $result[] = [ + 'pm_platform' => $item['groupName'] ?? '-', + 'pm_name' => $item['userName'] ?? '-', + 'pm_invest_date' => $item['investDate'] ?? '-', + 'pm_amount' => $item['amount'] ?? '-', + ]; + } + return $result; + } + /** * 获取展开的学员数据(每个学员每条课程一行) */ @@ -397,25 +473,28 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With } /** - * 构建包含学员数据的行 + * 构建包含展开数据的行 */ - private function buildRowWithoutUsers($info, $userData) + private function buildExpandedRow($info, $userData, $projectUserData) { $row = []; foreach ($this->fields as $field => $label) { - if (str_contains($field, 'users')) { + if (str_contains($field, 'users') && !str_contains($field, 'project_users')) { // 填充学员信息列 foreach (array_keys(self::USERS_SUB_COLUMNS) as $subField) { $row[] = $userData[$subField] ?? ''; } + } elseif (str_contains($field, 'project_users')) { + // 填充项目经理信息列 + foreach (array_keys(self::PROJECT_USERS_SUB_COLUMNS) as $subField) { + $row[] = $projectUserData[$subField] ?? ''; + } } elseif (str_contains($field, 'idcard')) { $row[] = ' ' . $this->getDotValue($info, $field); } elseif (str_contains($field, 'all_course')) { $row[] = $this->allCourse($info); } elseif (str_contains($field, 'partners')) { $row[] = $this->partners($info); - } elseif (str_contains($field, 'project_users')) { - $row[] = $this->projectManager($info); } else { $row[] = $this->getDotValue($info, $field); } @@ -484,7 +563,7 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With { $list = []; foreach ($data['project_users'] as $item) { - $list[] = $item['groupName'] . '-' . ($item['userName'] ?? '') . '-' . ($item['investDate'] ?? ''); + $list[] = $item['groupName'] . '-' . ($item['userName'] ?? '') . '-' . ($item['investDate'] ?? '') . '-' . ($item['amount'] ?? ''); } return implode("、\r\n", $list); }