You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1992 lines
100 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Http\Controllers\Admin;
use App\Helpers\ResponseCode;
use App\Jobs\CancelAppointMeet;
use App\Models\Admin;
use App\Models\Appointment;
use App\Models\AppointmentConfig;
use App\Models\Article;
use App\Models\Calendar;
use App\Models\CarparkLog;
use App\Models\Company;
use App\Models\CourseSign;
use App\Models\CourseType;
use App\Models\CourseTypeDataOverviewConfig;
use App\Models\CustomFormField;
use App\Models\Department;
use App\Models\HistoryCourse;
use App\Models\ParameterDetail;
use App\Models\StockCompany;
use App\Models\SupplyDemand;
use App\Models\TimeEvent;
use App\Models\User;
use App\Repositories\DoorRepository;
use App\Repositories\EntranceRepository;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Models\Course;
use EasyWeChat\Factory;
use Illuminate\Filesystem\Filesystem;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\CommonExport;
class OtherController extends CommonController
{
/**
* @OA\Get(
* path="/api/admin/other/home",
* tags={"其他"},
* summary="驾驶舱",
* description="",
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function home()
{
// 校友总数
$schoolmate['schoolmate_total'] = User::where('is_schoolmate', 1)->count();
// 2025年校友数
$schoolmate['schoolmate_year'] = User::where('is_schoolmate', 1)->where('created_at', 'like', '%' . date('Y') . '%')->count();
// 开课场次(全部)
$calendar = Calendar::get();
$company['course_total'] = $calendar->count();
$company['course_day_total'] = $calendar->sum(function ($course) {
$start = Carbon::parse($course->start_time);
$end = Carbon::parse($course->end_time);
return $end->diffInDays($start) + 1; // 包含起始和结束日期
});
// 开课场次(当年)
$calendarYear = Calendar::where('date', 'like', '%' . date('Y') . '%')->get();
$company['course_total_year'] = $calendarYear->count();
$company['course_day_total_year'] = $calendarYear->sum(function ($course) {
$start = Carbon::parse($course->start_time);
$end = Carbon::parse($course->end_time);
return $end->diffInDays($start) + 1; // 包含起始和结束日期
});
// 校友企业总融资额
$company['company_fund'] = Company::approvedStudents()->where('is_schoolmate', 1)->sum('company_fund');
// 校友企业总估值
$company['valuation'] = Company::approvedStudents()->where('is_schoolmate', 1)->sum('valuation');
// 校友企业所属领域
$industryTotal = [];
$industries = ParameterDetail::where('parameter_id', 4)->get();
foreach ($industries as $item) {
$level2Names = ParameterDetail::where('parameter_id', 10)->where('remark', $item->value)->pluck('value');
$industryTotal[] = [
'industry' => $item->value,
'total' => User::whereIn('company_industry', $level2Names)->count()
];
}
// 课程统计
$courseTypes = CourseType::where('is_chart', 1)->get();
foreach ($courseTypes as $courseType) {
$courseIds = Course::where('type', $courseType->id)->pluck('id');
$courseType->course_signs_total = CourseSign::whereIn('course_id', $courseIds)
->where('status', 1)
->count();
}
// 苏州区域数据
$suzhou = Company::approvedStudents()->where('company_city', '苏州市')
// 根据company_area分组查询公司数量
->select('company_area', DB::raw('count(*) as company_total'))
->groupBy('company_area')
->get();
// 全国数据
$country = Company::approvedStudents()->select('company_city', DB::raw('count(*) as company_total'))
->groupBy('company_city')
->get();
return $this->success(compact('courseTypes', 'schoolmate', 'company', 'industryTotal', 'suzhou', 'country'));
}
/**
* @OA\Get(
* path="/api/admin/other/home-v2",
* tags={"其他"},
* summary="驾驶舱V2",
* description="",
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function homeV2()
{
// 默认开始时间
$start_date = CourseType::START_DATE;
// 默认结束日期一年以后
$end_date = date('Y-m-d', strtotime('+10 year'));
// 校友总数
$list['schoolmate_total'] = User::where('is_schoolmate', 1)->count();
// 今年新增校友数
$list['schoolmate_year'] = User::where('is_schoolmate', 1)->where('created_at', 'like', '%' . date('Y') . '%')->count();
// 投后企业
$list['company_invested_total'] = CourseSign::yhInvestedTotal(CourseType::START_DATE, date('Y-m-d'), null);
// 元和员工参与人数
$list['company_join_total'] = CourseSign::companyJoin();
// 全市干部参与企业
$list['company_ganbu_total'] = CourseSign::ganbu();
// 三个全覆盖
// 苏州头部企业
$list['cover_head_total'] = CourseSign::toubuqiye();
// 高层次人才
// 获取人才培训课程
$list['cover_rencai_total'] = CourseSign::rencai();
// 重点上市公司
$list['cover_stock_total'] = CourseSign::shangshi();
// 培养人次1
$start_date = CourseType::START_DATE;
// 默认结束日期一年以后
$end_date = date('Y-m-d', strtotime('+10 year'));
// 培养人次
$list['course_signs_pass'] = CourseSign::courseSignsTotal($start_date, $end_date, 1);
// 培养人数
$list['course_signs_pass_unique'] = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, null, null);
// 跟班学员数
$list['genban_total'] = CourseSign::genban($start_date, $end_date);
// 本月课程
$monthCourses = Calendar::with('course.teacher')
->where('start_time', 'like', '%' . date('Y-m') . '%')
->get();
// 苏州区域数据
$suzhouArea = Company::approvedStudents()->where('company_city', '苏州市')->groupBy('company_area')
->whereNotNull('company_area')
->get(['company_area']);
$suzhou = [];
foreach ($suzhouArea as $item) {
$suzhou[] = [
'area' => $item->company_area,
'total' => User::whereHas('company', function ($query) use ($item) {
$query->where('company_area', $item->company_area);
})->where('is_schoolmate', 1)->count()
];
}
// 全国数据
$countryArea = Company::approvedStudents()->groupBy('company_city')->whereNotNull('company_city')->get(['company_city']);
$country = [];
foreach ($countryArea as $item) {
$total = User::whereHas('company', function ($query) use ($item) {
$query->where('company_city', $item->company_city);
})->where('is_schoolmate', 1)->count();
if (empty($total)) {
continue;
}
$country[] = [
'area' => $item->company_city,
'total' => User::whereHas('company', function ($query) use ($item) {
$query->where('company_city', $item->company_city);
})->where('is_schoolmate', 1)->count()
];
}
// 时间轴
$time_axis = TimeEvent::orderBy('sort', 'asc')->get();
// 动态信息
$article['xiaoyou'] = Article::where('type', 1)->limit(7)->orderBy('sort', 'desc')->get();
$article['yejie'] = Article::where('type', 2)->limit(7)->orderBy('sort', 'desc')->get();
$article['supply_demands'] = SupplyDemand::limit(7)->orderBy('created_at', 'desc')->get();
// 课程体系筛选
// 1. 从配置表读取配置列表
$yearConfigs = CourseTypeDataOverviewConfig::where('status', true)
->orderBy('sort', 'asc')
->get();
// 2. 查询对应的 CourseType
$allCourseTypes = CourseType::where('is_chart', 1)
->orderBy('sort', 'asc')
->where('is_history', 0)
->get();
// 3. 循环所有配置,对每个配置进行统计
foreach ($yearConfigs as $config) {
// 根据配置获取日期范围
$configStartDate = $config->start_date;
$configEndDate = $config->end_date ? $config->end_date : date('Y-m-d', strtotime('+10 year'));
// 复制 CourseType 集合(避免引用问题)
$courseTypes = $allCourseTypes->map(function ($item) {
return clone $item;
});
// 对每个 CourseType 进行统计
foreach ($courseTypes as $courseType) {
// 历史课程数据(添加时间范围限制)
$historyCourse = HistoryCourse::whereHas('typeDetail', function ($query) use ($courseType) {
$query->where('name', 'like', '%' . $courseType->name . '%');
})->where(function ($query) use ($configStartDate, $configEndDate) {
$query->whereBetween('start_time', [$configStartDate, $configEndDate])
->orWhereBetween('end_time', [$configStartDate, $configEndDate]);
})->get();
// 实际课程数据(添加时间范围限制)
$courses = Course::where('type', $courseType->id)->where('is_chart', 1)
->where(function ($query) use ($configStartDate, $configEndDate) {
$query->whereBetween('start_date', [$configStartDate, $configEndDate])
->orWhereBetween('end_date', [$configStartDate, $configEndDate]);
})->get();
// 历史课程期数
$courseType->history_course_periods_total = $historyCourse->count();
// 现在课程期数(添加时间范围限制)
$courseType->now_course_periods_total = $courses->count();
// 历史课程培养人数去重
$courseType->history_course_signs_total = $historyCourse->sum('course_type_signs_pass_unique');
// 现在课程培养人数(使用配置的日期范围)
$courseType->now_course_signs_total = CourseSign::courseSignsTotalByUnique($configStartDate, $configEndDate, 1, $courses->pluck('id'), false, false);
// 已开设期数
$courseType->course_periods_total = $courseType->now_course_periods_total + $courseType->history_course_periods_total;
// 培养人数去重
$courseType->course_signs_total = $courseType->history_course_signs_total + $courseType->now_course_signs_total;
}
// 将统计数据直接组合到配置对象中
$config->courseTypes = $courseTypes;
// 总期数
$config->course_periods_total = $courseTypes->sum('course_periods_total');
// 总去重人数
$coursesAll = Course::whereIn('type', $allCourseTypes->pluck('id'))
->where('is_chart', 1)
->where(function ($query) use ($configStartDate, $configEndDate) {
$query->whereBetween('start_date', [$configStartDate, $configEndDate])
->orWhereBetween('end_date', [$configStartDate, $configEndDate]);
})->get();
$config->course_signs_unique_total = $courseTypes->sum('history_course_signs_total') + CourseSign::courseSignsTotalByUnique($configStartDate, $configEndDate, 1, $coursesAll->pluck('id'), false, false);
}
return $this->success(compact('list', 'suzhou', 'country', 'monthCourses', 'time_axis', 'article', 'yearConfigs'));
}
/**
* @OA\Get(
* path="/api/admin/other/courses-home",
* tags={"其他"},
* summary="课程统计",
* description="",
* @OA\Parameter(name="start_date", in="query", @OA\Schema(type="string"), required=true, description="开始日期"),
* @OA\Parameter(name="end_date", in="query", @OA\Schema(type="string"), required=true, description="结束日期"),
* @OA\Parameter(name="course_type_id", in="query", @OA\Schema(type="string"), required=true, description="课程体系id多个英文逗号"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function coursesHome()
{
// 获取公共参数
$params = $this->getCoursesHomeParams();
$start_date = $params['start_date'];
$end_date = $params['end_date'];
$course_type_id = $params['course_type_id'];
$courses = $params['courses'];
// 报名人数
$list['course_signs_total'] = CourseSign::courseSignsTotal($start_date, $end_date, null, $courses->pluck('id'));
// 审核通过人数
$list['course_signs_pass'] = CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses->pluck('id'));
// 审核通过人数去重
$list['course_signs_pass_unique'] = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses->pluck('id'), null);
// 开课场次
$list['course_total'] = Calendar::getCourseTotal($start_date, $end_date, $course_type_id);
// 开课天数
$list['course_day_total'] = Calendar::getCourseDayTotal($start_date, $end_date, $course_type_id);
$course_ids = $courses->pluck('id');
// 上市公司数(所有上市公司)
$list['company_market_total'] = CourseSign::shangshi($start_date, $end_date, $course_ids);
// 跟班学员数在指定时间范围内报名的学员中from为'跟班学员'的数量)
$list['ganbu_total'] = CourseSign::genban($start_date, $end_date, $course_ids);
// 今年上市公司数量从stock_companys表获取stock_date在今年
$currentYear = date('Y');
$list['company_market_year_total'] = StockCompany::whereYear('stock_date', $currentYear)->count();
// 入学后上市公司数量从stock_companys表获取is_after_enrollment = 1
$list['company_market_after_enrollment_total'] = StockCompany::where('is_after_enrollment', 1)->count();
// 累计被投企业数
$list['course_signs_invested'] = CourseSign::yhInvestedTotal(CourseType::START_DATE, $end_date, $course_ids);
// 入学后被投企业数量(在指定时间范围内报名的学员所在公司中,在入学后被投的公司数量)
$list['company_invested_after_enrollment_total'] = CourseSign::companyInvestedAfterEnrollment($start_date, $end_date, $course_ids);
// 今年被投企业数
$list['company_invested_year_total'] = CourseSign::companyInvestedYear($start_date, $end_date, $course_ids);
// 元和员工参与人数
$list['company_join_total'] = CourseSign::companyJoin($start_date, $end_date, $course_ids, false, true);
// 全市干部参与企业
$list['company_ganbu_total'] = CourseSign::ganbu($start_date, $end_date, $course_ids);
// 苏州头部企业
$list['cover_head_total'] = CourseSign::toubuqiye($start_date, $end_date, $course_ids);
// 高层次人才
$list['cover_rencai_total'] = CourseSign::rencai($start_date, $end_date, $course_ids);
// 重点上市公司
$list['cover_stock_total'] = CourseSign::shangshi($start_date, $end_date, $course_ids);
// 课程分类明细统计
$courseTypesSum = [];
$courseTypes = CourseType::whereIn('id', $course_type_id)->get();
foreach ($courseTypes as $courseType) {
// 获取课程
$courses2 = Course::where('type', $courseType->id)
->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询
if ($start_date && $end_date) {
$query->whereBetween('start_date', [$start_date, $end_date])
->orWhereBetween('end_date', [$start_date, $end_date]);
}
})->where('is_chart', 1)->orderBy('start_date', 'asc')->get();
foreach ($courses2 as $course) {
$courseTypesSum[] = [
'course_type' => $courseType->name,
// 培养人数
'course_type_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses2->pluck('id'), false, false),
// 去重培养人数
'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), false, false),
'course_name' => $course->name,
'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id], false, false),
// 跟班学员数量
'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], false, false, false),
];
}
}
// 附加历史课程数据
$courseTypesHistory = CourseType::where('is_history', 1)->whereIn('id', $course_type_id)->get();
foreach ($courseTypesHistory as $historyCourse) {
$courses3 = HistoryCourse::whereHas('calendar', function ($query) {
$query->where('is_count_people', 1);
})->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询
$query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]);
})->where('type', $historyCourse->id)->get();
foreach ($courses3 as $course) {
$courseTypesSum[] = [
'course_type' => $historyCourse->name,
'course_name' => $course->course_name,
// 课程类型培养人数
'course_type_signs_pass' => $courses3->sum('course_type_signs_pass'),
// 课程类型去重培养人数
'course_type_signs_pass_unique' => $courses3->sum('course_type_signs_pass_unique'),
// 课程人数
'course_signs_pass' => $course->course_signs_pass,
// 跟班学员数量
'genban_total' => 0,
// 被投企业数
'yh_invested_total' => 0,
// 元禾同事数
'company_join_total' => 0,
];
}
}
// 区域明细统计
$areas = CourseSign::area($start_date, $end_date, 1, $courses->pluck('id'), true);
// 获取统计项元数据
$statistics_metadata = Course::getStatisticsMetadata();
return $this->success(compact('list', 'courseTypesSum', 'areas', 'statistics_metadata'));
}
/**
* @OA\Get(
* path="/api/admin/other/courses-home-export",
* tags={"其他"},
* summary="课程统计明细导出",
* description="导出课程统计数据的明细",
* @OA\Parameter(name="export_type", in="query", @OA\Schema(type="string"), required=true, description="导出类型course_signs_invested-被投企业明细, course_signs_total-报名人数明细, course_signs_pass-审核通过人数明细, course_signs_pass_unique-审核通过人数去重明细, courseTypesSum-课程分类明细, areas-区域明细, company_market_total-上市公司明细, ganbu_total-跟班学员明细, company_market_year_total-今年上市公司明细, company_market_after_enrollment_total-入学后上市公司明细, company_invested_after_enrollment_total-入学后被投企业明细, company_invested_year_total-年份范围内被投企业明细, course_total-开课场次明细, course_day_total-开课天数明细, company_join_total-元和员工参与企业明细, company_ganbu_total-全市干部参与企业明细, cover_head_total-苏州头部企业明细, cover_rencai_total-高层次人才明细, cover_stock_total-重点上市公司明细"),
* @OA\Parameter(name="start_date", in="query", @OA\Schema(type="string"), required=false, description="开始日期"),
* @OA\Parameter(name="end_date", in="query", @OA\Schema(type="string"), required=false, description="结束日期"),
* @OA\Parameter(name="course_type_id", in="query", @OA\Schema(type="string"), required=false, description="课程体系id多个英文逗号"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="导出Excel文件"
* )
* )
*/
public function coursesHomeExport()
{
$export_type = request('export_type');
if (!$export_type) {
return $this->fail([ResponseCode::ERROR_PARAMETER, '导出类型不能为空']);
}
// 获取参数与coursesHome保持一致
$params = $this->getCoursesHomeParams();
$start_date = $params['start_date'];
$end_date = $params['end_date'];
$course_type_id = $params['course_type_id'];
$courses = $params['courses'];
$course_ids = $courses->pluck('id');
$data = [];
$fields = [];
$filename = '';
switch ($export_type) {
case 'course_signs_invested':
// 被投企业明细 - 使用与coursesHome相同的算法
// 确保 $course_ids 是数组格式
$courseIdsArray = $course_ids ? (is_array($course_ids) ? $course_ids : $course_ids->toArray()) : null;
$companies = CourseSign::yhInvestedTotal(CourseType::START_DATE, $end_date, $courseIdsArray, true);
foreach ($companies as $company) {
// 获取该公司的学员信息
// 使用与yhInvestedTotal相同的筛选逻辑status=1筛选course_ids和日期范围
// 直接通过公司ID查询学员
$userIds = User::where('company_id', $company->id)->pluck('id')->toArray();
if (empty($userIds)) {
// 如果没有学员,设置空值
$userNamesStr = '';
$courseNamesStr = '';
$courseTypesStr = '';
$totalCourseCount = 0;
} else {
$userCourseSigns = CourseSign::getStudentList(CourseType::START_DATE, $end_date, 1, $courseIdsArray)
->whereIn('user_id', $userIds)
->with(['user', 'course.typeDetail'])
->get();
// 按学员分组
$usersData = [];
foreach ($userCourseSigns as $sign) {
if (!$sign->user) {
continue;
}
$userId = $sign->user_id;
if (!isset($usersData[$userId])) {
$usersData[$userId] = [
'user' => $sign->user,
'courseSigns' => [],
];
}
$usersData[$userId]['courseSigns'][] = $sign;
}
// 收集所有学员的姓名、课程名称、课程体系
$userNames = [];
$allCourseNames = [];
$allCourseTypes = [];
$totalCourseCount = 0;
foreach ($usersData as $userData) {
$user = $userData['user'];
$courseSigns = collect($userData['courseSigns']);
if ($courseSigns->isNotEmpty()) {
$userNames[] = $user->name ?? '';
// 收集课程名称
$courseNames = $courseSigns->pluck('course.name')->filter()->unique()->values()->toArray();
$allCourseNames = array_merge($allCourseNames, $courseNames);
// 收集课程体系
$courseTypes = $courseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->toArray();
$allCourseTypes = array_merge($allCourseTypes, $courseTypes);
// 累计报名课程数
$totalCourseCount += $courseSigns->count();
}
}
// 去重并合并
$userNamesStr = implode('、', array_filter(array_unique($userNames)));
$courseNamesStr = implode('、', array_filter(array_unique($allCourseNames)));
$courseTypesStr = implode('、', array_filter(array_unique($allCourseTypes)));
}
$data[] = [
'company_name' => $company->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'company_date' => $company->company_date ?? '',
'company_address' => $company->company_address ?? '',
'business_scope' => $company->business_scope ?? '',
'contact_phone' => $company->contact_phone ?? '',
'contact_mail' => $company->contact_mail ?? '',
'company_tag' => $company->company_tag ?? '',
'credit_code' => ' ' . $company->credit_code ?? '',
'user_names' => $userNamesStr,
'course_names' => $courseNamesStr,
'course_types' => $courseTypesStr,
'course_count' => $totalCourseCount,
];
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'company_date' => '成立时间',
'company_address' => '地址',
'business_scope' => '营业范围',
'contact_phone' => '联系电话',
'contact_mail' => '联系邮箱',
'company_tag' => '企业资质',
'credit_code' => '统一社会信用代码',
'user_names' => '学员姓名',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '被投企业明细';
break;
case 'course_signs_total':
// 报名人数明细 - 使用courseSignsTotal方法获取列表与coursesHome算法一致
$courseSigns = CourseSign::courseSignsTotal($start_date, $end_date, null, $course_ids, true);
// 加载关联关系
$courseSigns->load(['user', 'course']);
foreach ($courseSigns as $sign) {
$data[] = [
'user_name' => $sign->user->name ?? '',
'mobile' => $sign->user->mobile ?? '',
'company_name' => $sign->user->company_name ?? '',
'company_area' => $sign->user->company_area ?? '',
'course_name' => $sign->course->name ?? '',
'status_text' => $sign->status_text ?? '',
'created_at' => $sign->created_at ? $sign->created_at->format('Y-m-d H:i:s') : '',
];
}
$fields = [
'user_name' => '学员姓名',
'mobile' => '手机号',
'company_name' => '企业名称',
'company_area' => '所在区域',
'course_name' => '课程名称',
'status_text' => '审核状态',
'created_at' => '报名时间',
];
$filename = '报名人数明细';
break;
case 'course_signs_pass':
// 审核通过人数明细 - 使用courseSignsTotal方法获取列表与coursesHome算法一致
$courseSigns = CourseSign::courseSignsTotal($start_date, $end_date, 1, $course_ids, true);
// 加载关联关系
$courseSigns->load(['user', 'course']);
foreach ($courseSigns as $sign) {
$data[] = [
'user_name' => $sign->user->name ?? '',
'mobile' => $sign->user->mobile ?? '',
'company_name' => $sign->user->company->company_name ?? '',
'company_area' => $sign->user->company->company_area ?? '',
'company_industry' => $sign->user->company->company_industry ?? '',
'course_name' => $sign->course->name ?? '',
'course_type' => $sign->course->typeDetail->name ?? '',
// 'created_at' => $sign->created_at ? $sign->created_at->format('Y-m-d H:i:s') : '',
];
}
$fields = [
'user_name' => '学员姓名',
'mobile' => '手机号',
'company_name' => '企业名称',
'company_area' => '所在区域',
'course_name' => '课程名称',
'course_type' => '课程类型',
// 'created_at' => '报名时间',
];
$filename = '审核通过人数明细';
break;
case 'course_signs_pass_unique':
// 审核通过人数去重明细 - 使用courseSignsTotalByUnique方法获取列表与coursesHome保持一致
$users = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $course_ids, true);
// 预加载 company 关系,避免 N+1 查询问题
$users->load('company');
foreach ($users as $user) {
// 获取该学员报名的课程列表 - 使用与getStudentList完全一致的逻辑
$userCourseSigns = CourseSign::where(function ($query) use ($course_ids) {
// status = 1
$query->where('status', 1);
// course_ids筛选
if ($course_ids && $course_ids->isNotEmpty()) {
$query->whereIn('course_id', $course_ids);
}
})
->whereHas('course', function ($query) use ($start_date, $end_date) {
$query->where('is_chart', 1);
// 开始结束日期的筛选。or查询
if ($start_date && $end_date) {
$query->where(function ($q) use ($start_date, $end_date) {
$q->whereBetween('start_date', [$start_date, $end_date])
->orWhereBetween('end_date', [$start_date, $end_date]);
});
}
})
->whereNotIn('status', [4, 5, 6])
->where('user_id', $user->id)
->with(['course.typeDetail'])
->get();
// 获取课程名称列表,用中文顿号分隔
$courseNames = $userCourseSigns->pluck('course.name')->filter()->unique()->values()->implode('、');
// 获取课程体系列表,用中文顿号分隔
$courseTypes = $userCourseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->implode('、');
// 企查查企业(来自 company 表)
$qccCompanyName = $user->company && $user->company->company_name
? $user->company->company_name
: '';
// 用户填写企业(来自 user 表)
$userCompanyName = $user->company_name ?? '';
// 优先使用 company 关系的企业信息,如果不存在则使用 User 表的字段
$companyArea = $user->company && $user->company->company_area
? $user->company->company_area
: ($user->company_area ?? '');
$companyIndustry = $user->company && $user->company->company_industry
? $user->company->company_industry
: ($user->company_industry ?? '');
$data[] = [
'user_name' => $user->name ?? '',
'mobile' => $user->mobile ?? '',
'qcc_company_name' => $qccCompanyName,
'user_company_name' => $userCompanyName,
'company_position' => $user->company_position ?? '',
'company_area' => $companyArea,
'company_industry' => $companyIndustry,
'course_types' => $courseTypes,
'course_names' => $courseNames,
'course_count' => $userCourseSigns->count(),
];
}
$fields = [
'user_name' => '学员姓名',
'mobile' => '手机号',
'qcc_company_name' => '企查查企业',
'user_company_name' => '用户填写企业',
'company_position' => '职务',
'company_area' => '所在区域',
'company_industry' => '所属行业',
'course_types' => '课程体系',
'course_names' => '报名课程',
'course_count' => '报名课程数',
];
$filename = '审核通过人数去重明细';
break;
case 'courseTypesSum':
// 课程分类明细 - 与coursesHome中的courseTypesSum逻辑保持一致
$courseTypes = CourseType::whereIn('id', $course_type_id)->get();
foreach ($courseTypes as $courseType) {
// 获取课程 - 添加日期筛选逻辑
$courses2 = Course::where('type', $courseType->id)
->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询
if ($start_date && $end_date) {
$query->whereBetween('start_date', [$start_date, $end_date])
->orWhereBetween('end_date', [$start_date, $end_date]);
}
})->orderBy('start_date', 'asc')->get();
foreach ($courses2 as $course) {
$data[] = [
'course_type' => $courseType->name,
'course_name' => $course->name,
'course_type_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses2->pluck('id'), false, false),
'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), false, false),
'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id], false, false),
'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], false, false),
];
}
}
// 附加历史课程数据
$courseTypesHistory = CourseType::where('is_history', 1)->whereIn('id', $course_type_id)->get();
foreach ($courseTypesHistory as $historyCourse) {
$courses3 = HistoryCourse::whereHas('calendar', function ($query) {
$query->where('is_count_people', 1);
})->where(function ($query) use ($start_date, $end_date) {
// 开始结束日期的筛选。or查询
$query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]);
})->where('type', $historyCourse->id)->get();
foreach ($courses3 as $course) {
$data[] = [
'course_type' => $historyCourse->name,
'course_name' => $course->course_name,
// 课程类型培养人数
'course_type_signs_pass' => $courses3->sum('course_type_signs_pass'),
// 课程类型去重培养人数
'course_type_signs_pass_unique' => $courses3->sum('course_type_signs_pass_unique'),
// 课程人数
'course_signs_pass' => $course->course_signs_pass,
// 跟班学员数量
'genban_total' => 0,
// 被投企业数
'yh_invested_total' => 0,
// 元禾同事数
'company_join_total' => 0,
];
}
}
$fields = [
'course_type' => '课程体系',
'course_name' => '课程名称',
'course_type_signs_pass' => '课程体系培养人数',
'course_type_signs_pass_unique' => '课程体系去重培养人数',
'course_signs_pass' => '课程培养人数',
'genban_total' => '跟班学员数',
'yh_invested_total' => '被投企业数',
'company_join_total' => '元禾同事数',
];
$filename = '课程分类明细';
break;
case 'areas':
// 区域明细 - 导出course_signs_pass列表数据附加区域信息
$courseSigns = CourseSign::area($start_date, $end_date, 1, $courses->pluck('id'), false);
// 加载关联关系
$courseSigns->load(['user.company', 'course']);
foreach ($courseSigns as $sign) {
$data[] = [
'company_name' => $sign->user->company->company_name ?? '',
'company_area' => $sign->user->company->company_area ?? '',
'company_city' => $sign->user->company->company_city ?? '',
'company_province' => $sign->user->company->company_province ?? '',
'user_name' => $sign->user->name ?? '',
'mobile' => $sign->user->mobile ?? '',
'course_name' => $sign->course->name ?? '',
// 'created_at' => $sign->created_at ? $sign->created_at->format('Y-m-d H:i:s') : '',
];
}
$fields = [
'company_name' => '企业名称',
'company_area' => '公司区域',
'company_city' => '公司城市',
'company_province' => '公司省份',
'user_name' => '学员姓名',
'mobile' => '手机号',
'course_name' => '课程名称',
// 'created_at' => '报名时间',
];
$filename = '区域明细';
break;
case 'company_market_total':
// 上市公司明细 - 所有上市公司,关联学员、课程信息
// 数据结构:主表是公司,子数据是学员信息
// 导出时:公司信息只在第一行显示,后续行公司信息为空
$companiesData = CourseSign::shangshi($start_date, $end_date, $course_ids->toArray(), true);
foreach ($companiesData as $item) {
$company = $item['company'];
$users = $item['users'] ?? [];
// 公司基本信息(只在第一行使用)
$companyInfo = [
'company_name' => $company->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'company_date' => $company->company_date ?? '',
'stock_date' => $company->stock_date ?? '',
'company_address' => $company->company_address ?? '',
'company_city' => $company->company_city ?? '',
'company_area' => $company->company_area ?? '',
'company_tag' => $company->company_tag ?? '',
];
if (empty($users)) {
// 如果没有学员报名记录,仍然导出公司基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_name' => '',
'course_type' => '',
'course_types' => '',
'course_count' => 0,
]);
} else {
// 每个学员一行,多个课程合并显示
$isFirstRow = true;
foreach ($users as $userInfo) {
$courses = $userInfo['courses'] ?? [];
// 合并同一学员的多个课程:格式为"课程体系-课程名称,课程体系-课程名称"
$courseList = [];
foreach ($courses as $courseInfo) {
$courseType = $courseInfo['course_type'] ?? '';
$courseName = $courseInfo['course_name'] ?? '';
if ($courseType && $courseName) {
$courseList[] = $courseType . '-' . $courseName;
} elseif ($courseName) {
$courseList[] = $courseName;
}
}
$courseDisplay = implode("\r\n", $courseList);
// 获取课程体系列表,用中文顿号分隔
$courseTypes = collect($courses)
->pluck('course_type')
->filter()
->unique()
->values()
->implode('、');
// 报名课程数
$courseCount = count($courses);
if ($isFirstRow) {
// 第一行:显示公司信息
$data[] = array_merge($companyInfo, [
'user_name' => $userInfo['user_name'] ?? '',
'course_name' => $courseDisplay,
'course_type' => '', // 课程类型已合并到课程名称中
'course_types' => $courseTypes,
'course_count' => $courseCount,
]);
$isFirstRow = false;
} else {
// 后续行:公司信息为空
$data[] = [
'company_name' => '',
'company_legal_representative' => '',
'company_date' => '',
'stock_date' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'user_name' => $userInfo['user_name'] ?? '',
'course_name' => $courseDisplay,
'course_types' => $courseTypes,
'course_count' => $courseCount,
];
}
}
}
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'company_date' => '成立时间',
'stock_date' => '上市日期',
'company_address' => '地址',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'user_name' => '学员姓名',
'course_name' => '课程信息',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '上市公司明细';
break;
case 'ganbu_total':
// 跟班学员明细 - 使用模型方法
$users = CourseSign::genban($start_date, $end_date, $course_ids, true);
foreach ($users as $user) {
// 获取该学员的课程报名记录
$userCourseSigns = CourseSign::where(function ($query) use ($course_ids) {
// status = 1
$query->where('status', 1);
// course_ids筛选
if ($course_ids && $course_ids->isNotEmpty()) {
$query->whereIn('course_id', $course_ids);
}
})
->whereHas('course', function ($query) use ($start_date, $end_date) {
$query->where('is_chart', 1);
// 开始结束日期的筛选。or查询
if ($start_date && $end_date) {
$query->where(function ($q) use ($start_date, $end_date) {
$q->whereBetween('start_date', [$start_date, $end_date])
->orWhereBetween('end_date', [$start_date, $end_date]);
});
}
})
->whereNotIn('status', [4, 5, 6])
->where('user_id', $user->id)
->with(['course.typeDetail'])
->get();
// 获取课程名称列表,用中文顿号分隔
$courseNames = $userCourseSigns->pluck('course.name')->filter()->unique()->values()->implode('、');
// 获取课程体系列表,用中文顿号分隔
$courseTypes = $userCourseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->implode('、');
// 报名课程数
$courseCount = $userCourseSigns->count();
$data[] = [
'name' => $user->username ?? '',
'sex' => $user->sex ?? '',
'mobile' => $user->mobile ?? '',
'company_name' => $user->company_name ?? '',
'company_position' => $user->company_position ?? '',
'from' => $user->from ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
];
}
$fields = [
'name' => '姓名',
'sex' => '性别',
'mobile' => '手机号',
'company_name' => '企业名称',
'company_position' => '职位',
'from' => '标签',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '跟班学员明细';
break;
case 'company_market_year_total':
// 今年上市公司明细 - 从stock_companys表获取与coursesHome统计逻辑保持一致
$currentYear = date('Y');
$stockCompanies = StockCompany::with('company')->whereYear('stock_date', $currentYear)->get();
foreach ($stockCompanies as $stockCompany) {
// 通过company_id关联到Company表获取详细信息
$company = $stockCompany->company_id ? $stockCompany->company : null;
if (!$company) {
// 如果没有company_id尝试通过公司名称关联
$company = Company::where('company_name', $stockCompany->company_name)->first();
}
// 公司基本信息(只在第一行使用)
$companyInfo = [
'company_name' => $stockCompany->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'stock_date' => $stockCompany->stock_date ?? '',
'is_after_enrollment' => $stockCompany->is_after_enrollment == 1 ? '是' : '否',
'company_address' => $company->company_address ?? '',
'company_city' => $company->company_city ?? '',
'company_area' => $company->company_area ?? '',
'company_tag' => $company->company_tag ?? '',
];
// 获取该公司的学员信息
if ($company) {
$users = $company->users()
->whereHas('courseSigns', function ($q) {
$q->where('status', 1);
})
->with([
'courseSigns' => function ($query) {
$query->where('status', 1)
->with(['course.typeDetail']);
}
])
->get();
if ($users->isEmpty()) {
// 如果没有学员,仍然导出公司基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_names' => '',
'course_types' => '',
'course_count' => 0,
]);
} else {
// 每个学员一行
$isFirstRow = true;
foreach ($users as $user) {
$courseSigns = $user->courseSigns ?? collect([]);
// 获取课程名称列表,用中文顿号分隔
$courseNames = $courseSigns->pluck('course.name')->filter()->unique()->values()->implode('、');
// 获取课程体系列表,用中文顿号分隔
$courseTypes = $courseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->implode('、');
// 报名课程数
$courseCount = $courseSigns->count();
if ($isFirstRow) {
// 第一行:显示公司信息
$data[] = array_merge($companyInfo, [
'user_name' => $user->name ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
]);
$isFirstRow = false;
} else {
// 后续行:公司信息为空
$data[] = [
'company_name' => '',
'company_legal_representative' => '',
'stock_date' => '',
'is_after_enrollment' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'user_name' => $user->name ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
];
}
}
}
} else {
// 如果没有关联的公司,只导出基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_names' => '',
'course_types' => '',
'course_count' => 0,
]);
}
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'stock_date' => '上市日期',
'is_after_enrollment' => '是否入学后上市',
'company_address' => '地址',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'user_name' => '学员姓名',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '今年上市公司明细';
break;
case 'company_market_after_enrollment_total':
// 入学后上市公司明细 - 从stock_companys表获取与coursesHome统计逻辑保持一致
$stockCompanies = StockCompany::with('company')->where('is_after_enrollment', 1)->get();
foreach ($stockCompanies as $stockCompany) {
// 通过company_id关联到Company表获取详细信息
$company = $stockCompany->company_id ? $stockCompany->company : null;
if (!$company) {
// 如果没有company_id尝试通过公司名称关联
$company = Company::where('company_name', $stockCompany->company_name)->first();
}
// 公司基本信息(只在第一行使用)
$companyInfo = [
'company_name' => $stockCompany->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'stock_date' => $stockCompany->stock_date ?? '',
'enrollment_date' => $stockCompany->enrollment_date ?? '',
'is_after_enrollment' => $stockCompany->is_after_enrollment == 1 ? '是' : '否',
'company_address' => $company->company_address ?? '',
'company_city' => $company->company_city ?? '',
'company_area' => $company->company_area ?? '',
'company_tag' => $company->company_tag ?? '',
];
// 获取该公司的学员信息
if ($company) {
$users = $company->users()
->whereHas('courseSigns', function ($q) {
$q->where('status', 1);
})
->with([
'courseSigns' => function ($query) {
$query->where('status', 1)
->with(['course.typeDetail']);
}
])
->get();
if ($users->isEmpty()) {
// 如果没有学员,仍然导出公司基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_names' => '',
'course_types' => '',
'course_count' => 0,
]);
} else {
// 每个学员一行
$isFirstRow = true;
foreach ($users as $user) {
$courseSigns = $user->courseSigns ?? collect([]);
// 获取课程名称列表,用中文顿号分隔
$courseNames = $courseSigns->pluck('course.name')->filter()->unique()->values()->implode('、');
// 获取课程体系列表,用中文顿号分隔
$courseTypes = $courseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->implode('、');
// 报名课程数
$courseCount = $courseSigns->count();
if ($isFirstRow) {
// 第一行:显示公司信息
$data[] = array_merge($companyInfo, [
'user_name' => $user->name ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
]);
$isFirstRow = false;
} else {
// 后续行:公司信息为空
$data[] = [
'company_name' => '',
'company_legal_representative' => '',
'stock_date' => '',
'enrollment_date' => '',
'is_after_enrollment' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'user_name' => $user->name ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
];
}
}
}
} else {
// 如果没有关联的公司,只导出基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_names' => '',
'course_types' => '',
'course_count' => 0,
]);
}
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'stock_date' => '上市日期',
'enrollment_date' => '入学时间',
'is_after_enrollment' => '是否入学后上市',
'company_address' => '地址',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'user_name' => '学员姓名',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '入学后上市公司明细';
break;
case 'company_invested_after_enrollment_total':
// 入学后被投企业明细 - 使用模型方法
$companiesAfterEnrollment = CourseSign::companyInvestedAfterEnrollment($start_date, $end_date, $course_ids, true);
foreach ($companiesAfterEnrollment as $item) {
$company = $item['company'];
$userNames = collect($item['users'])->pluck('name')->filter()->unique()->implode("\n\r");
$data[] = [
'company_name' => $company->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'company_date' => $company->company_date ?? '',
'invest_date' => $item['invest_date'] ?? '',
'first_sign_date' => $item['first_sign_date'],
'user_names' => $userNames,
'company_address' => $company->company_address ?? '',
'company_city' => $company->company_city ?? '',
'company_area' => $company->company_area ?? '',
];
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'company_date' => '成立时间',
'invest_date' => '被投日期',
'first_sign_date' => '首次报名时间',
'user_names' => '学员姓名',
'company_address' => '地址',
'company_city' => '所在城市',
'company_area' => '所在区域',
];
$filename = '入学后被投企业明细';
break;
case 'company_invested_year_total':
// 年份范围内被投企业明细 - 所有年份范围内被投企业,关联学员、课程信息
// 数据结构:主表是公司,子数据是学员信息
// 导出时:公司信息只在第一行显示,后续行公司信息为空
$companiesData = CourseSign::companyInvestedYear($start_date, $end_date, $course_ids, true);
foreach ($companiesData as $item) {
$company = $item['company'];
$users = $item['users'] ?? [];
// 公司基本信息(只在第一行使用)
$companyInfo = [
'company_name' => $company->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'company_date' => $company->company_date ?? '',
'company_address' => $company->company_address ?? '',
'company_city' => $company->company_city ?? '',
'company_area' => $company->company_area ?? '',
'company_tag' => $company->company_tag ?? '',
];
if (empty($users)) {
// 如果没有学员报名记录,仍然导出公司基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_name' => '',
'course_type' => '',
]);
} else {
// 每个学员一行,多个课程合并显示
$isFirstRow = true;
foreach ($users as $userInfo) {
$courses = $userInfo['courses'] ?? [];
// 合并同一学员的多个课程:格式为"课程体系-课程名称,课程体系-课程名称"
$courseList = [];
foreach ($courses as $courseInfo) {
$courseType = $courseInfo['course_type'] ?? '';
$courseName = $courseInfo['course_name'] ?? '';
if ($courseType && $courseName) {
$courseList[] = $courseType . '-' . $courseName;
} elseif ($courseName) {
$courseList[] = $courseName;
}
}
$courseDisplay = implode("\r\n", $courseList);
if ($isFirstRow) {
// 第一行:显示公司信息
$data[] = array_merge($companyInfo, [
'user_name' => $userInfo['user_name'] ?? '',
'course_name' => $courseDisplay,
'course_type' => '', // 课程类型已合并到课程名称中
]);
$isFirstRow = false;
} else {
// 后续行:公司信息为空
$data[] = [
'company_name' => '',
'company_legal_representative' => '',
'company_date' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'user_name' => $userInfo['user_name'] ?? '',
'course_name' => $courseDisplay,
];
}
}
}
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'company_date' => '成立时间',
'company_address' => '地址',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'user_name' => '学员姓名',
'course_name' => '课程信息',
];
$filename = '年份范围内被投企业明细';
break;
case 'course_total':
// 开课场次明细 - 与coursesHome算法一致
$calendars = Calendar::getCalendarsByDateRange($start_date, $end_date, $course_type_id)
->with('course')
->get();
foreach ($calendars as $calendar) {
$data[] = [
'course_name' => $calendar->course->name ?? '',
'title' => $calendar->title ?? '',
'date' => $calendar->date ?? '',
'start_time' => $calendar->start_time,
'end_time' => $calendar->end_time,
'address' => $calendar->address ?? '',
];
}
$fields = [
'course_name' => '课程名称',
'title' => '标题',
'date' => '日期',
'start_time' => '开始时间',
'end_time' => '结束时间',
'address' => '地址',
];
$filename = '开课场次明细';
break;
case 'course_day_total':
// 开课天数明细 - 与coursesHome算法一致
$calendars = Calendar::getCalendarsByDateRange($start_date, $end_date, $course_type_id)
->where('is_count_days', 1)
->with('course')
->get();
foreach ($calendars as $calendar) {
$data[] = [
'course_name' => $calendar->course->name ?? '',
'title' => $calendar->title ?? '',
'date' => $calendar->date ?? '',
'start_time' => $calendar->start_time ? date('Y-m-d H:i:s', strtotime($calendar->start_time)) : '',
'end_time' => $calendar->end_time ? date('Y-m-d H:i:s', strtotime($calendar->end_time)) : '',
'days' => $calendar->days ?? 0,
'address' => $calendar->address ?? '',
];
}
$fields = [
'course_name' => '课程名称',
'title' => '标题',
'date' => '日期',
'start_time' => '开始时间',
'end_time' => '结束时间',
'days' => '天数',
'address' => '地址',
];
$filename = '开课天数明细';
break;
case 'company_join_total':
// 元和员工参与人员明细 - 使用模型方法(现在返回的是用户列表)
// 注意第5个参数 $needHistory 需要与 coursesHome 方法保持一致true
$users = CourseSign::companyJoin($start_date, $end_date, $course_ids, true, true);
// 加载关联关系
$users->load('company');
foreach ($users as $user) {
// 获取该学员的课程报名记录
// 使用与 companyJoin 方法完全相同的 getStudentList 逻辑,确保数据一致
$userCourseSigns = CourseSign::getStudentList($start_date, $end_date, null, $course_ids)
->where('user_id', $user->id)
->with(['course.typeDetail'])
->get();
// 获取课程名称列表,用中文顿号分隔
$courseNames = $userCourseSigns->pluck('course.name')->filter()->unique()->values()->implode('、');
// 获取课程体系列表,用中文顿号分隔
$courseTypes = $userCourseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->implode('、');
// 报名课程数
$courseCount = $userCourseSigns->count();
$data[] = [
'user_name' => $user->name ?? '',
'mobile' => $user->mobile ?? '',
'company_name' => $user->company->company_name ?? $user->company_name,
'company_position' => $user->company_position ?? '',
'company_city' => $user->company->company_city ?? '',
'company_area' => $user->company->company_area ?? '',
'company_legal_representative' => $user->company->company_legal_representative ?? '',
'company_date' => $user->company->company_date ?? '',
'company_address' => $user->company->company_address ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
];
}
$fields = [
'user_name' => '学员姓名',
'mobile' => '手机号',
'company_name' => '企业名称',
'company_position' => '职位',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_legal_representative' => '法人',
'company_date' => '成立时间',
'company_address' => '地址',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '元和员工参与企业明细';
break;
case 'company_ganbu_total':
// 全市干部参与企业明细 - 使用模型方法
$users = CourseSign::ganbu($start_date, $end_date, $course_ids, true);
foreach ($users as $user) {
$data[] = [
'user_name' => $user->name ?? '',
'mobile' => $user->mobile ?? '',
'company_name' => $user->company->company_name ?? '',
'company_area' => $user->company->company_area ?? '',
'company_city' => $user->company->company_city ?? '',
'company_position' => $user->company_position ?? '',
];
}
$fields = [
'user_name' => '学员姓名',
'mobile' => '手机号',
'company_name' => '企业名称',
'company_area' => '所在区域',
'company_city' => '所在城市',
'company_position' => '职位',
];
$filename = '全市干部参与企业明细';
break;
case 'cover_head_total':
// 苏州头部企业明细 - 使用模型方法
// 确保 $course_ids 是数组格式
$courseIdsArray = $course_ids ? (is_array($course_ids) ? $course_ids : $course_ids->toArray()) : null;
$companies = CourseSign::toubuqiye($start_date, $end_date, $courseIdsArray, true);
// 预先获取所有符合条件的课程报名记录与toubuqiye方法逻辑一致
$courseSignsQuery = CourseSign::getStudentList($start_date, $end_date, 1, $courseIdsArray);
$allCourseSigns = $courseSignsQuery->with(['user', 'course.typeDetail'])->get();
// 按公司ID分组课程报名记录
$companyCourseSigns = [];
foreach ($allCourseSigns as $sign) {
if (!$sign->user || !$sign->user->company) {
continue;
}
$companyId = $sign->user->company->id;
if (!isset($companyCourseSigns[$companyId])) {
$companyCourseSigns[$companyId] = [];
}
$companyCourseSigns[$companyId][] = $sign;
}
foreach ($companies as $company) {
// 获取该公司的学员信息(只包含有课程报名的学员)
$userCourseSigns = collect($companyCourseSigns[$company->id] ?? []);
// 公司基本信息(只在第一行使用)
$companyInfo = [
'company_name' => $company->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'company_date' => $company->company_date ?? '',
'company_address' => $company->company_address ?? '',
'company_city' => $company->company_city ?? '',
'company_area' => $company->company_area ?? '',
'company_tag' => $company->company_tag ?? '',
'business_scope' => $company->business_scope ?? '',
'contact_phone' => $company->contact_phone ?? '',
'contact_mail' => $company->contact_mail ?? '',
];
if ($userCourseSigns->isEmpty()) {
// 如果没有学员,仍然导出公司基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_names' => '',
'course_types' => '',
'course_count' => 0,
]);
} else {
// 按学员分组
$usersData = [];
foreach ($userCourseSigns as $sign) {
if (!$sign->user) {
continue;
}
$userId = $sign->user_id;
if (!isset($usersData[$userId])) {
$usersData[$userId] = [
'user' => $sign->user,
'courseSigns' => [],
];
}
$usersData[$userId]['courseSigns'][] = $sign;
}
// 每个学员一行
$isFirstRow = true;
foreach ($usersData as $userData) {
$user = $userData['user'];
$courseSigns = collect($userData['courseSigns']);
if ($courseSigns->isEmpty()) {
continue;
}
// 获取课程名称列表,用中文顿号分隔
$courseNames = $courseSigns->pluck('course.name')->filter()->unique()->values()->implode('、');
// 获取课程体系列表,用中文顿号分隔
$courseTypes = $courseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->implode('、');
// 报名课程数
$courseCount = $courseSigns->count();
if ($isFirstRow) {
// 第一行:显示公司信息
$data[] = array_merge($companyInfo, [
'user_name' => $user->name ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
]);
$isFirstRow = false;
} else {
// 后续行:公司信息为空
$data[] = [
'company_name' => '',
'company_legal_representative' => '',
'company_date' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'business_scope' => '',
'contact_phone' => '',
'contact_mail' => '',
'user_name' => $user->name ?? '',
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
];
}
}
}
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'company_date' => '成立时间',
'company_address' => '地址',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'business_scope' => '营业范围',
'contact_phone' => '联系电话',
'contact_mail' => '联系邮箱',
'user_name' => '学员姓名',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '苏州头部企业明细';
break;
case 'cover_rencai_total':
// 高层次人才明细 - 使用模型方法
// 确保 $course_ids 是数组格式
$courseIdsArray = $course_ids ? (is_array($course_ids) ? $course_ids : $course_ids->toArray()) : null;
$users = CourseSign::rencai($start_date, $end_date, $courseIdsArray, true);
// 加载关联关系
$users->load('company');
// 获取所有用户的课程报名记录使用与rencai相同的筛选条件
$userIds = $users->pluck('id')->toArray();
$userCourseSigns = CourseSign::getStudentList($start_date, $end_date, 1, $courseIdsArray)
->whereIn('user_id', $userIds)
->with(['user', 'course.typeDetail'])
->get();
// 按用户ID分组课程报名记录
$userCourseSignsMap = [];
foreach ($userCourseSigns as $sign) {
if (!$sign->user) {
continue;
}
$userId = $sign->user_id;
if (!isset($userCourseSignsMap[$userId])) {
$userCourseSignsMap[$userId] = [];
}
$userCourseSignsMap[$userId][] = $sign;
}
foreach ($users as $user) {
// 获取该用户的课程报名记录
$courseSigns = collect($userCourseSignsMap[$user->id] ?? []);
if ($courseSigns->isEmpty()) {
// 如果没有课程报名记录,设置空值
$courseNamesStr = '';
$courseTypesStr = '';
$totalCourseCount = 0;
} else {
// 收集课程名称
$courseNames = $courseSigns->pluck('course.name')->filter()->unique()->values()->toArray();
$courseNamesStr = implode('、', array_filter($courseNames));
// 收集课程体系
$courseTypes = $courseSigns->pluck('course.typeDetail.name')
->filter()
->unique()
->values()
->toArray();
$courseTypesStr = implode('、', array_filter($courseTypes));
// 统计报名课程数
$totalCourseCount = $courseSigns->count();
}
$data[] = [
'user_name' => $user->name ?? '',
'mobile' => $user->mobile ?? '',
'company_name' => $user->company_name ?? '',
'company_area' => $user->company_area ?? '',
'company_city' => $user->company->company_city ?? '',
'company_position' => $user->company_position ?? '',
'education' => $user->education ?? '',
'course_names' => $courseNamesStr,
'course_types' => $courseTypesStr,
'course_count' => $totalCourseCount,
];
}
$fields = [
'user_name' => '学员姓名',
'mobile' => '手机号',
'company_name' => '企业名称',
'company_area' => '所在区域',
'company_city' => '所在城市',
'company_position' => '职位',
'education' => '学历',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '高层次人才明细';
break;
case 'cover_stock_total':
// 重点上市公司明细 - 使用模型方法
$companiesData = CourseSign::shangshi($start_date, $end_date, $course_ids, true);
foreach ($companiesData as $item) {
$company = $item['company'];
$users = $item['users'] ?? [];
// 公司基本信息(只在第一行使用)
$companyInfo = [
'company_name' => $company->company_name,
'company_legal_representative' => $company->company_legal_representative ?? '',
'company_date' => $company->company_date ?? '',
'stock_date' => $company->stock_date ?? '',
'company_address' => $company->company_address ?? '',
'company_city' => $company->company_city ?? '',
'company_area' => $company->company_area ?? '',
'company_tag' => $company->company_tag ?? '',
'business_scope' => $company->business_scope ?? '',
'contact_phone' => $company->contact_phone ?? '',
'contact_mail' => $company->contact_mail ?? '',
];
if (empty($users)) {
// 如果没有学员,仍然导出公司基本信息
$data[] = array_merge($companyInfo, [
'user_name' => '',
'course_names' => '',
'course_types' => '',
'course_count' => 0,
]);
} else {
// 每个学员一行
$isFirstRow = true;
foreach ($users as $userInfo) {
$user = $userInfo['user'] ?? null;
$courses = $userInfo['courses'] ?? [];
if (empty($courses)) {
// 如果没有课程,仍然显示学员信息
$courseNames = '';
$courseTypes = '';
$courseCount = 0;
} else {
// 收集课程名称
$courseNames = collect($courses)->pluck('course_name')->filter()->unique()->values()->implode('、');
// 收集课程体系
$courseTypes = collect($courses)->pluck('course_type')->filter()->unique()->values()->implode('、');
// 报名课程数
$courseCount = count($courses);
}
if ($isFirstRow) {
// 第一行:显示公司信息
$data[] = array_merge($companyInfo, [
'user_name' => $userInfo['user_name'] ?? ($user->name ?? ''),
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
]);
$isFirstRow = false;
} else {
// 后续行:公司信息为空
$data[] = [
'company_name' => '',
'company_legal_representative' => '',
'company_date' => '',
'stock_date' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'business_scope' => '',
'contact_phone' => '',
'contact_mail' => '',
'user_name' => $userInfo['user_name'] ?? ($user->name ?? ''),
'course_names' => $courseNames,
'course_types' => $courseTypes,
'course_count' => $courseCount,
];
}
}
}
}
$fields = [
'company_name' => '企业名称',
'company_legal_representative' => '法人',
'company_date' => '成立时间',
'stock_date' => '上市日期',
'company_address' => '地址',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'business_scope' => '营业范围',
'contact_phone' => '联系电话',
'contact_mail' => '联系邮箱',
'user_name' => '学员姓名',
'course_names' => '课程名称',
'course_types' => '课程体系',
'course_count' => '报名课程数',
];
$filename = '重点上市公司明细';
break;
default:
return $this->fail([ResponseCode::ERROR_PARAMETER, '不支持的导出类型']);
}
if (empty($data)) {
return $this->fail([ResponseCode::ERROR_PARAMETER, '暂无数据可导出']);
}
return Excel::download(
new CommonExport($data, $fields),
$filename . '_' . date('YmdHis') . '.xlsx'
);
}
/**
* 获取coursesHome方法的公共参数提取公共逻辑
* @return array
*/
private function getCoursesHomeParams()
{
$start_date = request('start_date', CourseType::START_DATE);
// 默认结束日期一年以后
$end_date = request('end_date', date('Y-m-d', strtotime('+10 year')));
$course_type_id = request('course_type_id', '');
if ($course_type_id) {
// 部分
$course_type_id = explode(',', $course_type_id);
} else {
// 全部
$course_type_id = CourseType::pluck('id')->toArray();
}
// 课程
$courses = Course::whereIn('type', $course_type_id)->get();
return [
'start_date' => $start_date,
'end_date' => $end_date,
'course_type_id' => $course_type_id,
'courses' => $courses,
];
}
/**
* @OA\Post(
* path="/api/admin/other/admin-user-list",
* tags={"其他"},
* summary="后台用户列表",
* description="",
* @OA\Parameter(name="page_size", in="query", @OA\Schema(type="string"), required=false, description="每页显示的条数"),
* @OA\Parameter(name="page", in="query", @OA\Schema(type="string"), required=false, description="页码"),
* @OA\Parameter(name="sort_name", in="query", @OA\Schema(type="string"), required=false, description="排序字段名字"),
* @OA\Parameter(name="sort_type", in="query", @OA\Schema(type="string"), required=false, description="排序类型"),
* @OA\Parameter(name="department_id", in="query", @OA\Schema(type="int"), required=false, description="部门id"),
* @OA\Parameter(name="keyword", in="query", @OA\Schema(type="string"), required=false, description="关键词"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function adminUserList()
{
$all = \request()->all();
$list = Admin::where(function ($query) use ($all) {
if (isset($all['department_id'])) {
$query->where('department_id', $all['department_id']);
}
if (isset($all['keyword'])) {
$query->where('name', 'like', '%' . $all['keyword'] . '%')->orWhere('username', 'like', '%' . $all['keyword'] . '%')->orWhere('mobile', 'like', '%' . $all['keyword'] . '%');
}
})->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')
->paginate($all['page_size'] ?? 20);
return $this->success($list);
}
/**
* @OA\Post(
* path="/api/admin/other/admin-department-list",
* tags={"其他"},
* summary="后台部门列表",
* description="",
* @OA\Parameter(name="page_size", in="query", @OA\Schema(type="string"), required=false, description="每页显示的条数"),
* @OA\Parameter(name="page", in="query", @OA\Schema(type="string"), required=false, description="页码。不传则全部,传入则分页"),
* @OA\Parameter(name="sort_name", in="query", @OA\Schema(type="string"), required=false, description="排序字段名字"),
* @OA\Parameter(name="sort_type", in="query", @OA\Schema(type="string"), required=false, description="排序类型"),
* @OA\Parameter(name="keyword", in="query", @OA\Schema(type="string"), required=false, description="关键词"),
* @OA\Parameter(name="show_tree", in="query", @OA\Schema(type="string"), required=false, description="是否显示树形结构 0否1是"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function adminDepartmentList()
{
$all = \request()->all();
$list = Department::with('users')->where(function ($query) use ($all) {
if (isset($all['keyword'])) {
$query->where('name', 'like', '%' . $all['keyword'] . '%');
}
});
if (isset($all['show_tree']) && $all['show_tree']) {
// 显示树形结构
$list = array2tree($list->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')->get()->toArray());
} else {
$list = $list->orderBy($all['sort_name'] ?? 'id', $all['sort_type'] ?? 'desc')->paginate($all['page_size'] ?? 20);
}
return $this->success($list);
}
/**
* @OA\Get(
* path="/api/admin/other/table-fileds",
* tags={"其他"},
* summary="获取表字段",
* description="",
* @OA\Parameter(name="table_name", in="query", @OA\Schema(type="string"), required=true, description="table_name"),
* @OA\Parameter(name="except", in="query", @OA\Schema(type="string"), required=true, description="排除的字段数组"),
* @OA\Parameter(name="token", in="query", @OA\Schema(type="string"), required=true, description="token"),
* @OA\Response(
* response="200",
* description="暂无"
* )
* )
*/
public function tableFileds()
{
$all = \request()->all();
$messages = [
'table_name.required' => '表名必填',
];
$validator = Validator::make($all, [
'table_name' => 'required'
], $messages);
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$except = request('except');
$detail = (new CustomFormField())->getRowTableFieldsByComment($all['table_name']);
$list = [];
if ($except) {
foreach ($detail as $key => $item) {
if (in_array($key, $except)) {
continue;
}
$list[] = $item;
}
} else {
$list = $detail;
}
return $this->success($list);
}
public function test()
{
$model = new DoorRepository();
$result = $model->getAllDoorInfo();
dd(json_encode($result, JSON_UNESCAPED_UNICODE));
}
/**
* 车辆进出场日志
*/
public function postCarInInfo()
{
$all = request()->all();
CarparkLog::add(1, $all, $all['plateNo']);
return $this->success($all);
}
/**
* 车辆出场日志
*/
public function postCarOutInfo()
{
$all = request()->all();
CarparkLog::add(2, $all, $all['plateNo']);
return $this->success($all);
}
}