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