master
cody 2 weeks ago
parent 5e997b9ed5
commit 7cf9530b07

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

Loading…
Cancel
Save