diff --git a/app/Exports/CommonExport.php b/app/Exports/CommonExport.php index 97daf33..c90a038 100755 --- a/app/Exports/CommonExport.php +++ b/app/Exports/CommonExport.php @@ -8,11 +8,19 @@ namespace App\Exports; use App\Exceptions\ErrorException; use Illuminate\Support\Collection; use Maatwebsite\Excel\Concerns\FromCollection; +use Maatwebsite\Excel\Concerns\WithStyles; +use Maatwebsite\Excel\Concerns\WithColumnWidths; +use Maatwebsite\Excel\Concerns\WithEvents; +use Maatwebsite\Excel\Events\AfterSheet; +use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; +use PhpOffice\PhpSpreadsheet\Style\Alignment; -class CommonExport implements FromCollection +class CommonExport implements FromCollection, WithStyles, WithColumnWidths, WithEvents { public $fields; public $data; + public $hasUsersField = false; + public $usersColumnIndex = null; public function __construct($data, $exportFields) { @@ -20,8 +28,137 @@ class CommonExport implements FromCollection $this->fields = $exportFields; // 数据 $this->data = $data; + + // 检查是否有 users 字段 + if (is_array($exportFields)) { + $index = 1; + foreach (array_keys($exportFields) as $field) { + if (str_contains($field, 'users')) { + $this->hasUsersField = true; + $this->usersColumnIndex = $this->getColumnLetter($index); + } + $index++; + } + } + } + + /** + * 获取列字母 + */ + private function getColumnLetter($columnNumber) + { + $letter = ''; + while ($columnNumber > 0) { + $columnNumber--; + $letter = chr(65 + ($columnNumber % 26)) . $letter; + $columnNumber = intval($columnNumber / 26); + } + return $letter; + } + + /** + * 设置列宽 + */ + public function columnWidths(): array + { + $widths = []; + $index = 1; + foreach (array_keys($this->fields) as $field) { + $letter = $this->getColumnLetter($index); + if (str_contains($field, 'users')) { + // 学员信息列设置较宽 + $widths[$letter] = 80; + } elseif (str_contains($field, 'partners') || str_contains($field, 'project_users')) { + // 股东和项目经理列 + $widths[$letter] = 50; + } elseif (str_contains($field, 'all_course')) { + // 课程列 + $widths[$letter] = 40; + } elseif (str_contains($field, 'company_name') || str_contains($field, 'address')) { + // 公司名称和地址 + $widths[$letter] = 30; + } else { + // 默认列宽 + $widths[$letter] = 15; + } + $index++; + } + return $widths; + } + + /** + * 设置样式 + */ + public function styles(Worksheet $sheet): array + { + $rowCount = count($this->data) + 1; // 数据行数 + 表头 + $colCount = count($this->fields); + $lastCol = $this->getColumnLetter($colCount); + + return [ + // 表头样式 + 1 => [ + 'font' => ['bold' => true, 'size' => 12], + 'alignment' => [ + 'horizontal' => Alignment::HORIZONTAL_CENTER, + 'vertical' => Alignment::VERTICAL_CENTER, + ], + 'fill' => [ + 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, + 'startColor' => ['rgb' => 'E0E0E0'], + ], + ], + // 所有数据区域样式 + "A1:{$lastCol}{$rowCount}" => [ + 'alignment' => [ + 'vertical' => Alignment::VERTICAL_TOP, + 'wrapText' => true, // 自动换行 + ], + 'borders' => [ + 'allBorders' => [ + 'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, + 'color' => ['rgb' => 'CCCCCC'], + ], + ], + ], + ]; } + /** + * 注册事件 + */ + public function registerEvents(): array + { + return [ + AfterSheet::class => function (AfterSheet $event) { + $sheet = $event->sheet->getDelegate(); + $rowCount = count($this->data) + 1; + + // 设置表头行高 + $sheet->getRowDimension(1)->setRowHeight(25); + + // 遍历数据行,根据内容设置行高 + for ($row = 2; $row <= $rowCount; $row++) { + // 获取该行的最大内容行数 + $maxLines = 1; + foreach (array_keys($this->fields) as $index => $field) { + $col = $this->getColumnLetter($index + 1); + $cellValue = $sheet->getCell($col . $row)->getValue(); + if ($cellValue) { + $lines = substr_count($cellValue, "\n") + 1; + $maxLines = max($maxLines, $lines); + } + } + // 设置行高(每行内容约15像素,最小20,最大400) + $rowHeight = min(400, max(20, $maxLines * 15)); + $sheet->getRowDimension($row)->setRowHeight($rowHeight); + } + + // 冻结首行 + $sheet->freezePane('A2'); + }, + ]; + } /** * 数组转集合 @@ -162,20 +299,43 @@ class CommonExport implements FromCollection } /** - * 获取手机号 + * 获取学员信息(优化显示格式) * @param $data */ function getUsers($data) { + if (empty($data['users'])) { + return ''; + } + $list = []; + $index = 1; foreach ($data['users'] as $item) { - $base = $item['no'] . '-' . $item['username'] . '-' . $item['is_schoolmate_text'] . '-' . $item['company_position'] . '-' . ($item['mobile'] ?? ''); - foreach ($item['course_signs'] as $i) { - $base .= '-' . $i['course']['name'] . '-' . ($i['created_at'] ?? ''); + // 基本信息行 + $userInfo = []; + $userInfo[] = "【学员{$index}】"; + $userInfo[] = "学号: " . ($item['no'] ?? '-'); + $userInfo[] = "姓名: " . ($item['username'] ?? '-'); + $userInfo[] = "校友: " . ($item['is_schoolmate_text'] ?? '-'); + $userInfo[] = "职位: " . ($item['company_position'] ?? '-'); + $userInfo[] = "手机: " . ($item['mobile'] ?? '-'); + + // 课程报名信息 + if (!empty($item['course_signs'])) { + $userInfo[] = "报名课程:"; + foreach ($item['course_signs'] as $signIndex => $sign) { + $courseName = $sign['course']['name'] ?? '-'; + $signDate = $sign['created_at'] ?? '-'; + $userInfo[] = " " . ($signIndex + 1) . ". {$courseName} ({$signDate})"; + } } - $list[] = $base; + + $list[] = implode("\n", $userInfo); + $index++; } - return implode("、\r\n", $list); + + // 用分隔线分隔不同学员 + return implode("\n" . str_repeat("-", 40) . "\n", $list); } }