|
|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|