master
lion 6 months ago
commit 2a04a1f0a3

@ -20,7 +20,30 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
public $fields; public $fields;
public $data; public $data;
public $hasUsersField = false; public $hasUsersField = false;
public $usersColumnIndex = null; public $hasProjectUsersField = 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' => '投资金额',
];
public function __construct($data, $exportFields) public function __construct($data, $exportFields)
{ {
@ -29,17 +52,49 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
// 数据 // 数据
$this->data = $data; $this->data = $data;
// 检查是否有 users 字段 // 构建扩展后的字段列表
if (is_array($exportFields)) { $this->buildExpandedFields();
$index = 1; }
foreach (array_keys($exportFields) as $field) {
if (str_contains($field, 'users')) { /**
$this->hasUsersField = true; * 构建扩展后的字段列表将users和project_users字段展开成多列
$this->usersColumnIndex = $this->getColumnLetter($index); */
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++;
} }
} else {
$this->expandedFields[$field] = $label;
$index++; $index++;
} }
} }
$this->totalColumns = count($this->expandedFields);
}
/**
* 是否需要二级表头
*/
private function needsDoubleHeader()
{
return $this->hasUsersField || $this->hasProjectUsersField;
} }
/** /**
@ -63,22 +118,23 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
{ {
$widths = []; $widths = [];
$index = 1; $index = 1;
foreach (array_keys($this->fields) as $field) { foreach (array_keys($this->expandedFields) as $field) {
$letter = $this->getColumnLetter($index); $letter = $this->getColumnLetter($index);
if (str_contains($field, 'users')) { if (in_array($field, ['user_course', 'user_name'])) {
// 学员信息列设置较宽 $widths[$letter] = 25;
$widths[$letter] = 80; } elseif (in_array($field, ['user_mobile', 'user_sign_date', 'pm_invest_date', 'pm_amount'])) {
} elseif (str_contains($field, 'partners') || str_contains($field, 'project_users')) { $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; $widths[$letter] = 50;
} elseif (str_contains($field, 'all_course')) { } elseif (str_contains($field, 'all_course')) {
// 课程列
$widths[$letter] = 40; $widths[$letter] = 40;
} elseif (str_contains($field, 'company_name') || str_contains($field, 'address')) { } elseif (str_contains($field, 'company_name') || str_contains($field, 'address')) {
// 公司名称和地址
$widths[$letter] = 30; $widths[$letter] = 30;
} else { } else {
// 默认列宽
$widths[$letter] = 15; $widths[$letter] = 15;
} }
$index++; $index++;
@ -91,13 +147,14 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
*/ */
public function styles(Worksheet $sheet): array public function styles(Worksheet $sheet): array
{ {
$rowCount = count($this->data) + 1; // 数据行数 + 表头 $lastCol = $this->getColumnLetter($this->totalColumns);
$colCount = count($this->fields); $dataStartRow = $this->needsDoubleHeader() ? 3 : 2;
$lastCol = $this->getColumnLetter($colCount);
return [ $styles = [];
// 表头样式
1 => [ if ($this->needsDoubleHeader()) {
// 二级表头样式 - 第一行
$styles[1] = [
'font' => ['bold' => true, 'size' => 12], 'font' => ['bold' => true, 'size' => 12],
'alignment' => [ 'alignment' => [
'horizontal' => Alignment::HORIZONTAL_CENTER, 'horizontal' => Alignment::HORIZONTAL_CENTER,
@ -105,23 +162,51 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
], ],
'fill' => [ 'fill' => [
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
'startColor' => ['rgb' => 'E0E0E0'], 'startColor' => ['rgb' => 'D0D0D0'],
], ],
], ];
// 所有数据区域样式 // 二级表头样式 - 第二行
"A1:{$lastCol}{$rowCount}" => [ $styles[2] = [
'font' => ['bold' => true, 'size' => 11],
'alignment' => [ 'alignment' => [
'vertical' => Alignment::VERTICAL_TOP, 'horizontal' => Alignment::HORIZONTAL_CENTER,
'wrapText' => true, // 自动换行 'vertical' => Alignment::VERTICAL_CENTER,
], ],
'borders' => [ 'fill' => [
'allBorders' => [ 'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN, 'startColor' => ['rgb' => 'E8E8E8'],
'color' => ['rgb' => 'CCCCCC'], ],
], ];
} 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;
} }
/** /**
@ -132,34 +217,62 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
return [ return [
AfterSheet::class => function (AfterSheet $event) { AfterSheet::class => function (AfterSheet $event) {
$sheet = $event->sheet->getDelegate(); $sheet = $event->sheet->getDelegate();
$rowCount = count($this->data) + 1;
if ($this->needsDoubleHeader()) {
// 设置表头行高 // 处理二级表头的单元格合并
$sheet->getRowDimension(1)->setRowHeight(25); $this->mergeHeaderCells($sheet);
// 遍历数据行,根据内容设置行高 // 设置表头行高
for ($row = 2; $row <= $rowCount; $row++) { $sheet->getRowDimension(1)->setRowHeight(25);
// 获取该行的最大内容行数 $sheet->getRowDimension(2)->setRowHeight(22);
$maxLines = 1;
foreach (array_keys($this->fields) as $index => $field) { // 冻结前两行
$col = $this->getColumnLetter($index + 1); $sheet->freezePane('A3');
$cellValue = $sheet->getCell($col . $row)->getValue(); } else {
if ($cellValue) { $sheet->getRowDimension(1)->setRowHeight(25);
$lines = substr_count($cellValue, "\n") + 1; $sheet->freezePane('A2');
$maxLines = max($maxLines, $lines);
}
}
// 设置行高每行内容约15像素最小20最大400
$rowHeight = min(400, max(20, $maxLines * 15));
$sheet->getRowDimension($row)->setRowHeight($rowHeight);
} }
// 冻结首行 // 设置数据行高
$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);
} else {
// 其他列:合并第一行和第二行
$col = $this->getColumnLetter($index);
$sheet->mergeCells("{$col}1:{$col}2");
$sheet->setCellValue("{$col}1", $label);
$index++;
}
}
}
/** /**
* 数组转集合 * 数组转集合
* @throws ErrorException * @throws ErrorException
@ -173,65 +286,222 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
if (!is_array($this->fields)) { if (!is_array($this->fields)) {
throw new ErrorException('导出字段必须是数组'); throw new ErrorException('导出字段必须是数组');
} }
// 获取表头
$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');
}
}
// 获取字段指向
$fields = array_keys($this->fields);
$newList = []; $newList = [];
foreach ($this->data as $info) {
$temp = []; if ($this->needsDoubleHeader()) {
foreach ($fields as $field) { // 有需要展开的字段:创建二级表头
if (str_contains($field, 'idcard')) { // 第一行表头(主表头)- 在 mergeHeaderCells 中处理
// 身份证 $header1 = [];
$temp[$field] = ' ' . $this->getDotValue($info, $field); foreach ($this->fields as $field => $label) {
} elseif (str_contains($field, 'all_course')) { if (str_contains($field, 'users') && !str_contains($field, 'project_users')) {
// 所有课程 foreach (self::USERS_SUB_COLUMNS as $subLabel) {
$temp[$field] = $this->allCourse($info); $header1[] = '';
} elseif (str_contains($field, 'partners')) { }
// 股东信息
$temp[$field] = $this->partners($info);
} elseif (str_contains($field, 'project_users')) { } elseif (str_contains($field, 'project_users')) {
// 项目经理 foreach (self::PROJECT_USERS_SUB_COLUMNS as $subLabel) {
$temp[$field] = $this->projectManager($info); $header1[] = '';
} elseif (str_contains($field, 'users')) { }
// 学员信息
$temp[$field] = $this->getUsers($info);
} else { } else {
$temp[$field] = $this->getDotValue($info, $field); $header1[] = '';
} }
} }
// 如果有自定义数据,全部附件上去 $newList[] = $header1;
$t2 = [];
// 第二行表头(子表头)
$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;
}
} 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'] ?? []);
$newList[] = $row;
}
}
}
} else {
// 没有需要展开的字段:使用原有逻辑
$header = array_values($this->fields);
$moreFileds = [];
if (empty($clear)) { if (empty($clear)) {
if (isset($info['data']) && $info['data'] && !empty($moreFileds)) { if (isset($this->data[0]['data']) && is_array($this->data[0]['data'])) {
$dataCollect = collect($info['data']); $moreHeader = array_column($this->data[0]['data'], 'name');
foreach ($moreFileds as $moreFiled) { $header = array_merge($header, $moreHeader);
$value = ($dataCollect->where('field', $moreFiled)->first()['value']) ?? ''; $moreFileds = array_column($this->data[0]['data'], 'field');
if (str_contains($moreFiled, 'idcard')) { }
$t2[$moreFiled] = ' ' . $value; }
} else { $newList[] = $header;
$t2[$moreFiled] = $value;
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);
} 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);
} }
$newList[] = $temp + $t2;
} }
array_unshift($newList, $header); //插入表头
$this->totalRows = count($newList) - ($this->needsDoubleHeader() ? 2 : 1);
return new Collection($newList); 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;
}
/**
* 获取展开的学员数据(每个学员每条课程一行)
*/
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)
{
$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, '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 $key
@ -293,49 +563,9 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
{ {
$list = []; $list = [];
foreach ($data['project_users'] as $item) { 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); return implode("、\r\n", $list);
} }
/**
* 获取学员信息(优化显示格式)
* @param $data
*/
function getUsers($data)
{
if (empty($data['users'])) {
return '';
}
$list = [];
$index = 1;
foreach ($data['users'] as $item) {
// 基本信息行
$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[] = implode("\n", $userInfo);
$index++;
}
// 用分隔线分隔不同学员
return implode("\n" . str_repeat("-", 40) . "\n", $list);
}
} }

@ -50,7 +50,7 @@ class CalendarsController extends BaseController
public function index() public function index()
{ {
$all = \request()->all(); $all = \request()->all();
$list = Calendar::with('course', 'courseContent','historyCourses') $list = Calendar::with('course', 'courseContent', 'historyCourses')
->where(function ($query) use ($all) { ->where(function ($query) use ($all) {
if (isset($all['month'])) { if (isset($all['month'])) {
$query->where('start_time', 'like', $all['month'] . '%'); $query->where('start_time', 'like', $all['month'] . '%');
@ -61,7 +61,21 @@ class CalendarsController extends BaseController
$list = $list->toArray(); $list = $list->toArray();
return Excel::download(new CommonExport($list, $all['export_fields'] ?? ''), ($all['file_name'] ?? '') . date('YmdHis') . '.xlsx'); return Excel::download(new CommonExport($list, $all['export_fields'] ?? ''), ($all['file_name'] ?? '') . date('YmdHis') . '.xlsx');
} }
return $this->success($list); // 本月日历天数
$monthDayCalendar = Calendar::where(function ($query) use ($all) {
if (isset($all['month'])) {
$query->where('start_time', 'like', $all['month'] . '%');
}
})->where('is_count_days', 1)->sum('days');
// 本年日历天数
$yearDayCalendar = Calendar::where(function ($query) use ($all) {
if (isset($all['month'])) {
// 获取$all['month']的年份部分
$year = date('Y', strtotime($all['month']));
$query->where('start_time', 'like', $year . '%');
}
})->where('is_count_days', 1)->sum('days');
return $this->success(compact('list', 'monthDayCalendar', 'yearDayCalendar'));
} }
/** /**

@ -141,7 +141,7 @@ class OtherController extends CommonController
// 重点上市公司 // 重点上市公司
$list['cover_stock_total'] = CourseSign::shangshi(); $list['cover_stock_total'] = CourseSign::shangshi();
// 本月课程 // 本月课程
$monthCourses = Calendar::with('course.teacher')->where('type', 1) $monthCourses = Calendar::with('course.teacher')
->where('date', 'like', '%' . date('Y-m') . '%') ->where('date', 'like', '%' . date('Y-m') . '%')
->get(); ->get();
// 课程统计 // 课程统计
@ -222,7 +222,7 @@ class OtherController extends CommonController
$course_type_id = $params['course_type_id']; $course_type_id = $params['course_type_id'];
$courses = $params['courses']; $courses = $params['courses'];
// 被投企业数 // 被投企业数
$list['course_signs_invested'] = CourseSign::yhInvested($start_date, $end_date); // $list['course_signs_invested'] = CourseSign::yhInvested($start_date, $end_date, $courses->pluck('id')->toArray());
// 报名人数 // 报名人数
$list['course_signs_total'] = CourseSign::courseSignsTotal($start_date, $end_date, null, $courses->pluck('id')); $list['course_signs_total'] = CourseSign::courseSignsTotal($start_date, $end_date, null, $courses->pluck('id'));
// 审核通过人数 // 审核通过人数
@ -233,10 +233,14 @@ class OtherController extends CommonController
$calendar = Calendar::where(function ($query) use ($start_date, $end_date) { $calendar = Calendar::where(function ($query) use ($start_date, $end_date) {
$query->whereBetween('start_time', [$start_date, $end_date]) $query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]); ->orWhereBetween('end_time', [$start_date, $end_date]);
})->whereIn('course_id', $courses->pluck('id')); })->where(function ($query) use ($courses) {
if (request('course_type_id')) {
$query->whereIn('course_id', $courses->pluck('id'));
}
});
$list['course_total'] = (clone $calendar)->count(); $list['course_total'] = (clone $calendar)->count();
// 开课天数 // 开课天数
$list['course_day_total'] = (clone $calendar)->sum('days'); $list['course_day_total'] = (clone $calendar)->where('is_count_days', 1)->sum('days');
// 上市公司数(所有上市公司) // 上市公司数(所有上市公司)
$list['company_market_total'] = Company::companyMarket($start_date, $end_date); $list['company_market_total'] = Company::companyMarket($start_date, $end_date);
@ -272,7 +276,7 @@ class OtherController extends CommonController
foreach ($courseTypes as $courseType) { foreach ($courseTypes as $courseType) {
// 获取课程 // 获取课程
$courses2 = Course::where('type', $courseType->id) $courses2 = Course::where('type', $courseType->id)
->whereHas('course', function ($query) use ($start_date, $end_date) { ->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询 // 开始结束日期的筛选。or查询
if ($start_date && $end_date) { if ($start_date && $end_date) {
$query->whereBetween('start_date', [$start_date, $end_date]) $query->whereBetween('start_date', [$start_date, $end_date])
@ -288,11 +292,19 @@ class OtherController extends CommonController
'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), null), 'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), null),
'course_name' => $course->name, 'course_name' => $course->name,
'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id]), 'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id]),
// 跟班学员数量
'genban_total' => CourseSign::genban($start_date, $end_date, [$course->id]),
// 被投企业数
'yh_invested_total' => CourseSign::yhInvested($start_date, $end_date, [$course->id]),
// 元禾同事数
'company_join_total' => CourseSign::companyJoin($start_date, $end_date, [$course->id]),
]; ];
} }
} }
// 附加历史课程数据 // 附加历史课程数据
$historyCourses = HistoryCourse::where(function ($query) use ($start_date, $end_date) { $historyCourses = HistoryCourse::whereHas('calendar', function ($query) {
$query->where('is_count_people', 1);
})->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询 // 开始结束日期的筛选。or查询
$query->whereBetween('start_time', [$start_date, $end_date]) $query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]); ->orWhereBetween('end_time', [$start_date, $end_date]);
@ -353,7 +365,7 @@ class OtherController extends CommonController
switch ($export_type) { switch ($export_type) {
case 'course_signs_invested': case 'course_signs_invested':
// 被投企业明细 - 使用与coursesHome相同的算法 // 被投企业明细 - 使用与coursesHome相同的算法
$companies = CourseSign::yhInvested($start_date, $end_date, true); $companies = CourseSign::yhInvested($start_date, $end_date, $course_ids, true);
foreach ($companies as $company) { foreach ($companies as $company) {
$data[] = [ $data[] = [
'company_name' => $company->company_name, 'company_name' => $company->company_name,
@ -493,6 +505,9 @@ class OtherController extends CommonController
'course_type_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses2->pluck('id')), 'course_type_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses2->pluck('id')),
'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), null), 'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), null),
'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id]), 'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id]),
'genban_total' => CourseSign::genban($start_date, $end_date, [$course->id]),
'yh_invested_total' => CourseSign::yhInvested($start_date, $end_date, [$course->id]),
'company_join_total' => CourseSign::companyJoin($start_date, $end_date, [$course->id]),
]; ];
} }
} }
@ -502,6 +517,9 @@ class OtherController extends CommonController
'course_type_signs_pass' => '课程体系培养人数', 'course_type_signs_pass' => '课程体系培养人数',
'course_type_signs_pass_unique' => '课程体系去重培养人数', 'course_type_signs_pass_unique' => '课程体系去重培养人数',
'course_signs_pass' => '课程培养人数', 'course_signs_pass' => '课程培养人数',
'genban_total' => '跟班学员数',
'yh_invested_total' => '被投企业数',
'company_join_total' => '元禾同事数',
]; ];
$filename = '课程分类明细'; $filename = '课程分类明细';
break; break;
@ -573,6 +591,7 @@ class OtherController extends CommonController
'mobile' => $user->mobile ?? '', 'mobile' => $user->mobile ?? '',
'company_name' => $user->company_name ?? '', 'company_name' => $user->company_name ?? '',
'company_position' => $user->company_position ?? '', 'company_position' => $user->company_position ?? '',
'from' => $user->from ?? '',
]; ];
} }
$fields = [ $fields = [
@ -581,6 +600,7 @@ class OtherController extends CommonController
'mobile' => '手机号', 'mobile' => '手机号',
'company_name' => '企业名称', 'company_name' => '企业名称',
'company_position' => '职位', 'company_position' => '职位',
'from' => '标签',
]; ];
$filename = '跟班学员明细'; $filename = '跟班学员明细';
break; break;
@ -677,8 +697,12 @@ class OtherController extends CommonController
case 'course_total': case 'course_total':
// 开课场次明细 - 与coursesHome算法一致 // 开课场次明细 - 与coursesHome算法一致
$calendars = Calendar::whereIn('course_id', $course_ids) $calendars = Calendar::whereBetween('date', [$start_date, $end_date])
->whereBetween('date', [$start_date, $end_date]) ->where(function ($query) use ($course_ids) {
if (request('course_type_id')) {
$query->whereIn('course_id', $course_ids);
}
})
->with('course') ->with('course')
->get(); ->get();
@ -705,8 +729,12 @@ class OtherController extends CommonController
case 'course_day_total': case 'course_day_total':
// 开课天数明细 - 与coursesHome算法一致 // 开课天数明细 - 与coursesHome算法一致
$calendars = Calendar::whereIn('course_id', $course_ids) $calendars = Calendar::whereBetween('date', [$start_date, $end_date])
->whereBetween('date', [$start_date, $end_date]) ->where(function ($query) use ($course_ids) {
if (request('course_type_id')) {
$query->whereIn('course_id', $course_ids);
}
})->where('is_count_days', 1)
->with('course') ->with('course')
->get(); ->get();

@ -110,7 +110,9 @@ class CourseSign extends SoftDeletesModel
// 基础数据 // 基础数据
$baseTotal = $totalQuery->count(); $baseTotal = $totalQuery->count();
// 历史数据 // 历史数据
$historyTotal = HistoryCourse::where(function ($query) use ($start_date, $end_date) { $historyTotal = HistoryCourse::whereHas('calendar', function ($query) {
$query->where('is_count_people', 1);
})->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询 // 开始结束日期的筛选。or查询
$query->whereBetween('start_time', [$start_date, $end_date]) $query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]); ->orWhereBetween('end_time', [$start_date, $end_date]);
@ -133,7 +135,9 @@ class CourseSign extends SoftDeletesModel
} else { } else {
$baseTotal = $user->count(); $baseTotal = $user->count();
// 历史数据 // 历史数据
$historyTotal = HistoryCourse::where(function ($query) use ($start_date, $end_date) { $historyTotal = HistoryCourse::whereHas('calendar', function ($query) {
$query->where('is_count_people', 1);
})->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询 // 开始结束日期的筛选。or查询
$query->whereBetween('start_time', [$start_date, $end_date]) $query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]); ->orWhereBetween('end_time', [$start_date, $end_date]);
@ -144,20 +148,57 @@ class CourseSign extends SoftDeletesModel
} }
/** /**
* 指定时间内的被投企业 * 被投企业统计
* @param string|null $start_date 开始日期
* @param string|null $end_date 结束日期
* @param array|null $course_ids 课程ID仅在自定义时间时生效
* @param bool $retList 是否返回列表
*/ */
public static function yhInvested($start_date = null, $end_date = null, $retList = false) public static function yhInvested($start_date = null, $end_date = null, $course_ids = null, $retList = false)
{ {
$courseSignByTypeQuery = self::getStudentList($start_date, $end_date, 1, null); // 判断是否使用默认时间
$list = Company::whereHas('users', function ($query) use ($courseSignByTypeQuery) { $isDefaultDate = empty($start_date) || $start_date == CourseType::START_DATE || empty($course_ids);
$query->whereIn('id', $courseSignByTypeQuery->get()->pluck('user_id')); dd(empty($start_date) , $start_date == CourseType::START_DATE , empty($course_ids));
// 获取学员ID列表
if ($isDefaultDate) {
// 默认时间:获取所有学员,不限制课程
$userIds = self::getStudentList($start_date, $end_date, 1, null)->get()->pluck('user_id');
} else {
// 自定义时间:按课程筛选学员
$userIds = self::getStudentList($start_date, $end_date, 1, $course_ids)->get()->pluck('user_id');
}
// 获取这些学员所在的被投企业
$companies = Company::whereHas('users', function ($query) use ($userIds) {
$query->whereIn('id', $userIds);
})->where('is_yh_invested', 1)->get(); })->where('is_yh_invested', 1)->get();
// 自定义时间:需要按被投时间筛选
if (!$isDefaultDate) {
$startDate = substr($start_date, 0, 10);
$endDate = substr($end_date, 0, 10);
// 筛选出被投时间在范围内的企业
$filteredCompanies = [];
foreach ($companies as $company) {
$projectUsers = $company->project_users ?? [];
foreach ($projectUsers as $item) {
$investDate = $item['investDate'] ?? null;
// 检查被投时间是否在范围内
if ($investDate && $investDate >= $startDate && $investDate <= $endDate) {
$filteredCompanies[] = $company;
break; // 只要有一条满足就加入
}
}
}
$companies = collect($filteredCompanies);
}
// 返回结果
if ($retList) { if ($retList) {
// 返回列表 return $companies->values();
return $list;
} else { } else {
// 返回统计数据 return $companies->count();
return $list->count();
} }
} }
@ -173,7 +214,7 @@ class CourseSign extends SoftDeletesModel
{ {
$courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids); $courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids);
$courseSigns = $courseSignsQuery->whereHas('user', function ($query) { $courseSigns = $courseSignsQuery->whereHas('user', function ($query) {
$query->where('from', '%' . '跟班学员' . '%'); $query->where('from', 'like', '%跟班学员%');
})->get(); })->get();
if ($retList) { if ($retList) {
@ -337,10 +378,21 @@ class CourseSign extends SoftDeletesModel
// 检测关键词 // 检测关键词
$companyNameKeyword = [ $companyNameKeyword = [
'元禾控股', '元禾原点', '元禾厚望', '元禾重元', '元禾控股',
'元禾璞华', '元禾谷风', '元禾绿柳', '元禾辰坤', '元禾沙湖', '元禾原点',
'禾裕集团', '苏州科服', '信诚管理咨询', '元禾厚望',
'集成电路公司', '常州团队', '国企元禾' '元禾重元',
'元禾璞华',
'元禾谷风',
'元禾绿柳',
'元禾辰坤',
'元禾沙湖',
'禾裕集团',
'苏州科服',
'信诚管理咨询',
'集成电路公司',
'常州团队',
'国企元禾'
]; ];
$company = Company::where(function ($query) use ($companyNameKeyword) { $company = Company::where(function ($query) use ($companyNameKeyword) {
foreach ($companyNameKeyword as $item) { foreach ($companyNameKeyword as $item) {
@ -372,7 +424,7 @@ class CourseSign extends SoftDeletesModel
{ {
$courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids); $courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids);
$courseSigns = $courseSignsQuery->whereHas('user', function ($query) { $courseSigns = $courseSignsQuery->whereHas('user', function ($query) {
$query->where('from', '%' . '跟班学员' . '%'); $query->where('from', 'like', '%跟班学员%');
})->get(); })->get();
if ($retList) { if ($retList) {
return User::with('company')->whereIn('id', $courseSigns->pluck('user_id'))->get(); return User::with('company')->whereIn('id', $courseSigns->pluck('user_id'))->get();

@ -13,8 +13,8 @@ return new class extends Migration {
public function up() public function up()
{ {
Schema::table('calendars', function (Blueprint $table) { Schema::table('calendars', function (Blueprint $table) {
$table->tinyInteger('is_count_days')->default(1)->comment('是否统计天数 0否 1是'); $table->tinyInteger('is_count_days')->nullable()->comment('是否统计天数 0否 1是');
$table->tinyInteger('is_count_people')->default(1)->comment('是否统计人数 0否 1是'); $table->tinyInteger('is_count_people')->nullable()->comment('是否统计人数 0否 1是');
}); });
} }

Loading…
Cancel
Save