|
|
<?php
|
|
|
/**
|
|
|
* 前端自定义的导出类
|
|
|
*/
|
|
|
|
|
|
namespace App\Exports;
|
|
|
|
|
|
use App\Exceptions\ErrorException;
|
|
|
use App\Models\CourseType;
|
|
|
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, WithStyles, WithColumnWidths, WithEvents
|
|
|
{
|
|
|
public $fields;
|
|
|
public $data;
|
|
|
public $hasUsersField = false;
|
|
|
public $hasProjectUsersField = false;
|
|
|
public $hasHistoryCoursesField = false;
|
|
|
public $totalColumns = 0;
|
|
|
public $totalRows = 0;
|
|
|
public $expandedFields = [];
|
|
|
|
|
|
// 学员信息子列定义
|
|
|
const USERS_SUB_COLUMNS = [
|
|
|
'user_index' => '序号',
|
|
|
'user_no' => '学号',
|
|
|
'user_name' => '姓名',
|
|
|
'user_schoolmate' => '校友',
|
|
|
'user_position' => '职位',
|
|
|
'user_mobile' => '手机',
|
|
|
'user_course' => '报名课程',
|
|
|
'user_sign_date' => '报名时间',
|
|
|
];
|
|
|
|
|
|
// 项目经理信息子列定义
|
|
|
const PROJECT_USERS_SUB_COLUMNS = [
|
|
|
'pm_platform' => '管理平台',
|
|
|
'pm_name' => '项目经理',
|
|
|
'pm_invest_date' => '首次出资时间',
|
|
|
'pm_amount' => '投资金额',
|
|
|
];
|
|
|
|
|
|
// 历史课程信息子列定义
|
|
|
const HISTORY_COURSES_SUB_COLUMNS = [
|
|
|
'hc_course_type' => '课程体系',
|
|
|
'hc_course_name' => '课程名称',
|
|
|
'hc_signs_pass' => '培养人数未去重',
|
|
|
'hc_signs_pass_unique' => '培养人数去重',
|
|
|
'hc_course_signs_pass' => '课程培养人数',
|
|
|
];
|
|
|
|
|
|
public function __construct($data, $exportFields)
|
|
|
{
|
|
|
// 需要导出的字段。格式:['name'=>'名字','user.sex'=>'性别']
|
|
|
$this->fields = $exportFields;
|
|
|
// 数据
|
|
|
$this->data = $data;
|
|
|
|
|
|
// 构建扩展后的字段列表
|
|
|
$this->buildExpandedFields();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 构建扩展后的字段列表(将users和project_users字段展开成多列)
|
|
|
*/
|
|
|
private function buildExpandedFields()
|
|
|
{
|
|
|
if (!is_array($this->fields)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
$index = 1;
|
|
|
foreach ($this->fields as $field => $label) {
|
|
|
if (str_contains($field, 'users') && !str_contains($field, 'project_users')) {
|
|
|
$this->hasUsersField = true;
|
|
|
// 展开学员信息为多列
|
|
|
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++;
|
|
|
}
|
|
|
} elseif (str_contains($field, 'history_courses')) {
|
|
|
$this->hasHistoryCoursesField = true;
|
|
|
// 展开历史课程信息为多列
|
|
|
foreach (self::HISTORY_COURSES_SUB_COLUMNS as $subField => $subLabel) {
|
|
|
$this->expandedFields[$subField] = $subLabel;
|
|
|
$index++;
|
|
|
}
|
|
|
} else {
|
|
|
$this->expandedFields[$field] = $label;
|
|
|
$index++;
|
|
|
}
|
|
|
}
|
|
|
$this->totalColumns = count($this->expandedFields);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 是否需要二级表头
|
|
|
*/
|
|
|
private function needsDoubleHeader()
|
|
|
{
|
|
|
return $this->hasUsersField || $this->hasProjectUsersField || $this->hasHistoryCoursesField;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取列字母
|
|
|
*/
|
|
|
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->expandedFields) as $field) {
|
|
|
$letter = $this->getColumnLetter($index);
|
|
|
if (in_array($field, ['user_course', 'user_name'])) {
|
|
|
$widths[$letter] = 25;
|
|
|
} 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 (in_array($field, ['pm_platform', 'pm_name'])) {
|
|
|
$widths[$letter] = 18;
|
|
|
} elseif (str_contains($field, 'partners')) {
|
|
|
$widths[$letter] = 50;
|
|
|
} elseif (str_contains($field, 'hc_course_type') || str_contains($field, 'hc_course_name')) {
|
|
|
$widths[$letter] = 25;
|
|
|
} elseif (str_contains($field, 'hc_')) {
|
|
|
$widths[$letter] = 18;
|
|
|
} elseif (str_contains($field, 'history_courses')) {
|
|
|
// 历史课程信息通常较长,适当放宽列宽(如果没有展开的情况)
|
|
|
$widths[$letter] = 40;
|
|
|
} 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
|
|
|
{
|
|
|
$lastCol = $this->getColumnLetter($this->totalColumns);
|
|
|
$dataStartRow = $this->needsDoubleHeader() ? 3 : 2;
|
|
|
|
|
|
$styles = [];
|
|
|
|
|
|
if ($this->needsDoubleHeader()) {
|
|
|
// 二级表头样式 - 第一行
|
|
|
$styles[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' => 'D0D0D0'],
|
|
|
],
|
|
|
];
|
|
|
// 二级表头样式 - 第二行
|
|
|
$styles[2] = [
|
|
|
'font' => ['bold' => true, 'size' => 11],
|
|
|
'alignment' => [
|
|
|
'horizontal' => Alignment::HORIZONTAL_CENTER,
|
|
|
'vertical' => Alignment::VERTICAL_CENTER,
|
|
|
],
|
|
|
'fill' => [
|
|
|
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
|
|
|
'startColor' => ['rgb' => 'E8E8E8'],
|
|
|
],
|
|
|
];
|
|
|
} else {
|
|
|
// 单行表头样式
|
|
|
$styles[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'],
|
|
|
],
|
|
|
];
|
|
|
}
|
|
|
|
|
|
// 所有数据区域样式
|
|
|
$styles["A1:{$lastCol}" . ($this->totalRows + $dataStartRow - 1)] = [
|
|
|
'alignment' => [
|
|
|
'vertical' => Alignment::VERTICAL_CENTER,
|
|
|
'wrapText' => true,
|
|
|
],
|
|
|
'borders' => [
|
|
|
'allBorders' => [
|
|
|
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
|
|
|
'color' => ['rgb' => 'CCCCCC'],
|
|
|
],
|
|
|
],
|
|
|
];
|
|
|
|
|
|
return $styles;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 注册事件
|
|
|
*/
|
|
|
public function registerEvents(): array
|
|
|
{
|
|
|
return [
|
|
|
AfterSheet::class => function (AfterSheet $event) {
|
|
|
$sheet = $event->sheet->getDelegate();
|
|
|
|
|
|
if ($this->needsDoubleHeader()) {
|
|
|
// 处理二级表头的单元格合并
|
|
|
$this->mergeHeaderCells($sheet);
|
|
|
|
|
|
// 设置表头行高
|
|
|
$sheet->getRowDimension(1)->setRowHeight(25);
|
|
|
$sheet->getRowDimension(2)->setRowHeight(22);
|
|
|
|
|
|
// 冻结前两行
|
|
|
$sheet->freezePane('A3');
|
|
|
} else {
|
|
|
$sheet->getRowDimension(1)->setRowHeight(25);
|
|
|
$sheet->freezePane('A2');
|
|
|
}
|
|
|
|
|
|
// 设置数据行高
|
|
|
$dataStartRow = $this->needsDoubleHeader() ? 3 : 2;
|
|
|
for ($row = $dataStartRow; $row <= $this->totalRows + $dataStartRow - 1; $row++) {
|
|
|
$sheet->getRowDimension($row)->setRowHeight(22);
|
|
|
}
|
|
|
},
|
|
|
];
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 合并表头单元格
|
|
|
*/
|
|
|
private function mergeHeaderCells(Worksheet $sheet)
|
|
|
{
|
|
|
$index = 1;
|
|
|
foreach ($this->fields as $field => $label) {
|
|
|
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);
|
|
|
} elseif (str_contains($field, 'history_courses')) {
|
|
|
// 历史课程信息列:合并第一行的多个单元格
|
|
|
$startCol = $this->getColumnLetter($index);
|
|
|
$endCol = $this->getColumnLetter($index + count(self::HISTORY_COURSES_SUB_COLUMNS) - 1);
|
|
|
$sheet->mergeCells("{$startCol}1:{$endCol}1");
|
|
|
$sheet->setCellValue("{$startCol}1", $label);
|
|
|
$index += count(self::HISTORY_COURSES_SUB_COLUMNS);
|
|
|
} else {
|
|
|
// 其他列:合并第一行和第二行
|
|
|
$col = $this->getColumnLetter($index);
|
|
|
$sheet->mergeCells("{$col}1:{$col}2");
|
|
|
$sheet->setCellValue("{$col}1", $label);
|
|
|
$index++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 数组转集合
|
|
|
* @throws ErrorException
|
|
|
*/
|
|
|
public function collection()
|
|
|
{
|
|
|
$clear = request('clear', 0);
|
|
|
if (empty($this->fields)) {
|
|
|
throw new ErrorException('导出字段不能为空');
|
|
|
}
|
|
|
if (!is_array($this->fields)) {
|
|
|
throw new ErrorException('导出字段必须是数组');
|
|
|
}
|
|
|
|
|
|
$newList = [];
|
|
|
|
|
|
if ($this->needsDoubleHeader()) {
|
|
|
// 有需要展开的字段:创建二级表头
|
|
|
// 第一行表头(主表头)- 在 mergeHeaderCells 中处理
|
|
|
$header1 = [];
|
|
|
foreach ($this->fields as $field => $label) {
|
|
|
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[] = '';
|
|
|
}
|
|
|
} elseif (str_contains($field, 'history_courses')) {
|
|
|
foreach (self::HISTORY_COURSES_SUB_COLUMNS as $subLabel) {
|
|
|
$header1[] = '';
|
|
|
}
|
|
|
} else {
|
|
|
$header1[] = '';
|
|
|
}
|
|
|
}
|
|
|
$newList[] = $header1;
|
|
|
|
|
|
// 第二行表头(子表头)
|
|
|
$header2 = [];
|
|
|
foreach ($this->fields as $field => $label) {
|
|
|
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;
|
|
|
}
|
|
|
} elseif (str_contains($field, 'history_courses')) {
|
|
|
foreach (self::HISTORY_COURSES_SUB_COLUMNS as $subLabel) {
|
|
|
$header2[] = $subLabel;
|
|
|
}
|
|
|
} else {
|
|
|
$header2[] = '';
|
|
|
}
|
|
|
}
|
|
|
$newList[] = $header2;
|
|
|
|
|
|
// 数据行:每个展开记录占一行
|
|
|
foreach ($this->data as $info) {
|
|
|
$expandedRows = $this->getExpandedRows($info);
|
|
|
if (empty($expandedRows)) {
|
|
|
// 没有展开数据,输出一行空数据
|
|
|
$row = $this->buildExpandedRow($info, [], [], []);
|
|
|
$newList[] = $row;
|
|
|
} else {
|
|
|
foreach ($expandedRows as $expandedRow) {
|
|
|
$row = $this->buildExpandedRow($info, $expandedRow['users'] ?? [], $expandedRow['project_users'] ?? [], $expandedRow['history_courses'] ?? []);
|
|
|
$newList[] = $row;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
// 没有需要展开的字段:使用原有逻辑
|
|
|
$header = array_values($this->fields);
|
|
|
$moreFileds = [];
|
|
|
if (empty($clear)) {
|
|
|
if (isset($this->data[0]['data']) && is_array($this->data[0]['data'])) {
|
|
|
$moreHeader = array_column($this->data[0]['data'], 'name');
|
|
|
$header = array_merge($header, $moreHeader);
|
|
|
$moreFileds = array_column($this->data[0]['data'], 'field');
|
|
|
}
|
|
|
}
|
|
|
$newList[] = $header;
|
|
|
|
|
|
foreach ($this->data as $info) {
|
|
|
$temp = [];
|
|
|
foreach (array_keys($this->fields) as $field) {
|
|
|
if (str_contains($field, 'idcard')) {
|
|
|
$temp[$field] = ' ' . $this->getDotValue($info, $field);
|
|
|
} elseif (str_contains($field, 'all_course')) {
|
|
|
$temp[$field] = $this->allCourse($info);
|
|
|
} elseif (str_contains($field, 'partners')) {
|
|
|
$temp[$field] = $this->partners($info);
|
|
|
} elseif (str_contains($field, 'history_courses')) {
|
|
|
// 历史课程信息字段,格式化为多行文本
|
|
|
$temp[$field] = $this->historyCourses($info);
|
|
|
} else {
|
|
|
$temp[$field] = $this->getDotValue($info, $field);
|
|
|
}
|
|
|
}
|
|
|
$t2 = [];
|
|
|
if (empty($clear)) {
|
|
|
if (isset($info['data']) && $info['data'] && !empty($moreFileds)) {
|
|
|
$dataCollect = collect($info['data']);
|
|
|
foreach ($moreFileds as $moreFiled) {
|
|
|
$value = ($dataCollect->where('field', $moreFiled)->first()['value']) ?? '';
|
|
|
if (str_contains($moreFiled, 'idcard')) {
|
|
|
$t2[$moreFiled] = ' ' . $value;
|
|
|
} else {
|
|
|
$t2[$moreFiled] = $value;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
$newList[] = array_values($temp + $t2);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$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) : [];
|
|
|
$historyCoursesData = $this->hasHistoryCoursesField ? $this->getHistoryCoursesExpanded($info) : [];
|
|
|
|
|
|
// 计算最大行数
|
|
|
$maxRows = max(count($usersData), count($projectUsersData), count($historyCoursesData), 1);
|
|
|
|
|
|
$result = [];
|
|
|
for ($i = 0; $i < $maxRows; $i++) {
|
|
|
$result[] = [
|
|
|
'users' => $usersData[$i] ?? [],
|
|
|
'project_users' => $projectUsersData[$i] ?? [],
|
|
|
'history_courses' => $historyCoursesData[$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;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取展开的历史课程数据(每条历史课程一行)
|
|
|
*/
|
|
|
private function getHistoryCoursesExpanded($info)
|
|
|
{
|
|
|
if (empty($info['history_courses']) || !is_array($info['history_courses'])) {
|
|
|
return [];
|
|
|
}
|
|
|
|
|
|
$result = [];
|
|
|
foreach ($info['history_courses'] as $item) {
|
|
|
// 获取课程体系名称
|
|
|
$courseTypeName = '';
|
|
|
if (isset($item['type_detail']) && isset($item['type_detail']['name'])) {
|
|
|
// 关联数据可能是 type_detail(下划线形式)
|
|
|
$courseTypeName = $item['type_detail']['name'];
|
|
|
} elseif (isset($item['typeDetail']) && isset($item['typeDetail']['name'])) {
|
|
|
// 关联数据可能是 typeDetail(驼峰形式)
|
|
|
$courseTypeName = $item['typeDetail']['name'];
|
|
|
} elseif (isset($item['type'])) {
|
|
|
// 如果只有类型ID,尝试查询类型名称
|
|
|
$typeId = $item['type'];
|
|
|
try {
|
|
|
$courseType = CourseType::find($typeId);
|
|
|
if ($courseType) {
|
|
|
$courseTypeName = $courseType->name;
|
|
|
} else {
|
|
|
$courseTypeName = $typeId; // 如果查询不到,显示ID
|
|
|
}
|
|
|
} catch (\Exception $e) {
|
|
|
$courseTypeName = $typeId; // 查询失败,显示ID
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$result[] = [
|
|
|
'hc_course_type' => $courseTypeName,
|
|
|
'hc_course_name' => $item['course_name'] ?? '',
|
|
|
'hc_signs_pass' => $item['course_type_signs_pass'] ?? 0,
|
|
|
'hc_signs_pass_unique' => $item['course_type_signs_pass_unique'] ?? 0,
|
|
|
'hc_course_signs_pass' => $item['course_signs_pass'] ?? 0,
|
|
|
];
|
|
|
}
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取展开的学员数据(每个学员每条课程一行)
|
|
|
*/
|
|
|
private function getUsersExpanded($info)
|
|
|
{
|
|
|
if (empty($info['users'])) {
|
|
|
return [];
|
|
|
}
|
|
|
|
|
|
$result = [];
|
|
|
$userIndex = 1;
|
|
|
foreach ($info['users'] as $user) {
|
|
|
if (!empty($user['course_signs'])) {
|
|
|
foreach ($user['course_signs'] as $signIndex => $sign) {
|
|
|
$result[] = [
|
|
|
'user_index' => $signIndex === 0 ? $userIndex : '',
|
|
|
'user_no' => $signIndex === 0 ? ($user['no'] ?? '-') : '',
|
|
|
'user_name' => $signIndex === 0 ? ($user['username'] ?? '-') : '',
|
|
|
'user_schoolmate' => $signIndex === 0 ? ($user['is_schoolmate_text'] ?? '-') : '',
|
|
|
'user_position' => $signIndex === 0 ? ($user['company_position'] ?? '-') : '',
|
|
|
'user_mobile' => $signIndex === 0 ? ($user['mobile'] ?? '-') : '',
|
|
|
'user_course' => $sign['course']['name'] ?? '-',
|
|
|
'user_sign_date' => isset($sign['created_at']) ? substr($sign['created_at'], 0, 10) : '-',
|
|
|
];
|
|
|
}
|
|
|
} else {
|
|
|
$result[] = [
|
|
|
'user_index' => $userIndex,
|
|
|
'user_no' => $user['no'] ?? '-',
|
|
|
'user_name' => $user['username'] ?? '-',
|
|
|
'user_schoolmate' => $user['is_schoolmate_text'] ?? '-',
|
|
|
'user_position' => $user['company_position'] ?? '-',
|
|
|
'user_mobile' => $user['mobile'] ?? '-',
|
|
|
'user_course' => '-',
|
|
|
'user_sign_date' => '-',
|
|
|
];
|
|
|
}
|
|
|
$userIndex++;
|
|
|
}
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 构建包含展开数据的行
|
|
|
*/
|
|
|
private function buildExpandedRow($info, $userData, $projectUserData, $historyCourseData = [])
|
|
|
{
|
|
|
$row = [];
|
|
|
foreach ($this->fields as $field => $label) {
|
|
|
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, 'history_courses')) {
|
|
|
// 填充历史课程信息列
|
|
|
foreach (array_keys(self::HISTORY_COURSES_SUB_COLUMNS) as $subField) {
|
|
|
$row[] = $historyCourseData[$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);
|
|
|
} else {
|
|
|
$row[] = $this->getDotValue($info, $field);
|
|
|
}
|
|
|
}
|
|
|
return $row;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* .号转数组层级并返回对应的值
|
|
|
* @param $key
|
|
|
* @param null $default
|
|
|
* @return mixed|null
|
|
|
*/
|
|
|
function getDotValue($config, $key, $default = null)
|
|
|
{
|
|
|
// 如果在第一层,就直接返回
|
|
|
if (isset($config[$key])) {
|
|
|
return $config[$key];
|
|
|
}
|
|
|
// 如果找不到,直接返回默认值
|
|
|
if (false === strpos($key, '.')) {
|
|
|
return $default;
|
|
|
}
|
|
|
// 临时数组
|
|
|
$tempArr = explode('.', $key);
|
|
|
foreach ($tempArr as $segment) {
|
|
|
if (!is_array($config) || !array_key_exists($segment, $config)) {
|
|
|
return $default;
|
|
|
}
|
|
|
$config = $config[$segment];
|
|
|
}
|
|
|
return $config;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取所有课程名称
|
|
|
* @param $data
|
|
|
*/
|
|
|
function allCourse($data)
|
|
|
{
|
|
|
$list = [];
|
|
|
foreach ($data['course_signs'] as $item) {
|
|
|
$list[] = $item['course']['name'] ?? '';
|
|
|
}
|
|
|
return implode("、\r\n", $list);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取所有历史课程信息(用于日历导出)
|
|
|
* @param $data
|
|
|
* @return string
|
|
|
*/
|
|
|
function historyCourses($data)
|
|
|
{
|
|
|
if (empty($data['history_courses']) || !is_array($data['history_courses'])) {
|
|
|
return '';
|
|
|
}
|
|
|
|
|
|
$list = [];
|
|
|
foreach ($data['history_courses'] as $item) {
|
|
|
$courseName = $item['course_name'] ?? '';
|
|
|
$type = $item['type'] ?? '';
|
|
|
$pass = $item['course_type_signs_pass'] ?? 0;
|
|
|
$passUnique = $item['course_type_signs_pass_unique'] ?? 0;
|
|
|
$signPass = $item['course_signs_pass'] ?? 0;
|
|
|
$start = $item['start_time'] ?? '';
|
|
|
$end = $item['end_time'] ?? '';
|
|
|
|
|
|
// 构造单行描述:课程名称[体系ID](开始~结束) 培养人数/去重/课程人数
|
|
|
$parts = [];
|
|
|
if ($courseName !== '') {
|
|
|
$parts[] = $courseName;
|
|
|
}
|
|
|
if ($type !== '') {
|
|
|
$parts[] = "[类型:{$type}]";
|
|
|
}
|
|
|
if ($start !== '' || $end !== '') {
|
|
|
$parts[] = "({$start}~{$end})";
|
|
|
}
|
|
|
$parts[] = "培养:{$pass}/去重:{$passUnique}/课程:{$signPass}";
|
|
|
|
|
|
$list[] = implode(' ', $parts);
|
|
|
}
|
|
|
|
|
|
// 每门历史课程占一行
|
|
|
return implode("\r\n", $list);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取所有股东信息
|
|
|
* @param $data
|
|
|
*/
|
|
|
function partners($data)
|
|
|
{
|
|
|
$list = [];
|
|
|
foreach ($data['partners'] as $item) {
|
|
|
$list[] = $item['stockName'] . '-' . $item['stockPercent'] ?? '';
|
|
|
}
|
|
|
return implode("、\r\n", $list);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取所有项目经理
|
|
|
* @param $data
|
|
|
*/
|
|
|
function projectManager($data)
|
|
|
{
|
|
|
$list = [];
|
|
|
foreach ($data['project_users'] as $item) {
|
|
|
$list[] = $item['groupName'] . '-' . ($item['userName'] ?? '') . '-' . ($item['investDate'] ?? '') . '-' . ($item['amount'] ?? '');
|
|
|
}
|
|
|
return implode("、\r\n", $list);
|
|
|
}
|
|
|
|
|
|
}
|