diff --git a/app/Http/Controllers/Admin/OtherController.php b/app/Http/Controllers/Admin/OtherController.php index b0840d7..ef14eae 100755 --- a/app/Http/Controllers/Admin/OtherController.php +++ b/app/Http/Controllers/Admin/OtherController.php @@ -27,6 +27,8 @@ 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 { @@ -129,7 +131,7 @@ class OtherController extends CommonController // 已开设期数 $courseType->course_periods_total = Course::where('type', $courseType->id)->count(); // 培养人数去重 - $courseType->course_signs_total = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses->pluck('id'), null, $userIds); + $courseType->course_signs_total = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses->pluck('id'), null); } // 苏州区域数据 $suzhouArea = Company::where('company_city', '苏州市')->groupBy('company_area') @@ -157,8 +159,7 @@ class OtherController extends CommonController ]; } // 本月课程 - $monthCourses = Course::with('teacher')->where('start_date', 'like', '%' . date('Y-m') . '%') - ->get(); + $monthCourses = Course::with('teacher')->where('start_date', 'like', '%' . date('Y-m') . '%')->get(); // 时间轴 $time_axis = TimeEvent::orderBy('sort', 'asc')->orderBy('id', 'desc')->get(); // 动态信息 @@ -186,67 +187,344 @@ class OtherController extends CommonController */ public function coursesHome() { - $start_date = request('start_date', CourseType::START_DATE); - $end_date = request('end_date', date('Y-m-d')); + $params = $this->getCoursesHomeParams(); + $courses = $this->getCoursesByTypeIds($params['course_type_id']); + // 报名人数 + $course_signs_total = CourseSign::courseSignsTotal($params['start_date'], $params['end_date']); + // 审核通过人数 + $course_signs_pass = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1); + // 审核通过人数去重 + $course_signs_pass_unique = CourseSign::courseSignsTotalByUnique($params['start_date'], $params['end_date'], 1, null, null); + // 开课场次 + $calendar = $this->getCalendarsByCourses($courses, $params['start_date'], $params['end_date']); + $course_total = $calendar->count(); + // 开课天数 + $course_day_total = $calendar->sum('days'); + // 课程分类明细统计 + $courseTypesSum = $this->getCourseTypesSum($params['start_date'], $params['end_date'], $params['course_type_id']); + // 区域明细统计 + $areas = $this->getAreasStatistics($params['start_date'], $params['end_date'], $courses); + + return $this->success(compact( + 'course_signs_total', + 'course_signs_pass', + 'course_signs_pass_unique', + 'course_total', + 'course_day_total', + 'courseTypesSum', + 'areas' + )); + } + + /** + * @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_total-报名人数明细, course_signs_pass-审核通过人数明细, course_signs_pass_unique-审核通过人数去重明细, course_total-开课场次明细, course_type_detail-课程分类明细, area_detail-区域明细"), + * @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=false, description="课程体系id,多个英文逗号"), + * @OA\Parameter(name="course_id", in="query", @OA\Schema(type="string"), required=false, description="课程id,用于课程分类明细"), + * @OA\Parameter(name="area", 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="导出Excel文件" + * ) + * ) + */ + public function coursesHomeExport() + { + $export_type = request('export_type'); + $params = $this->getCoursesHomeParams(); + $course_id = request('course_id', ''); + $area = request('area', ''); + + // 验证导出类型 + $allowed_types = [ + 'course_signs_total', + 'course_signs_pass', + 'course_signs_pass_unique', + 'course_total', + 'course_type_detail', + 'area_detail' + ]; + if (!in_array($export_type, $allowed_types)) { + return $this->fail([ResponseCode::ERROR_PARAMETER, '导出类型不正确']); + } + + $courses = $this->getCoursesByTypeIds($params['course_type_id']); + $data = []; + $filename = ''; + $error = ''; + + switch ($export_type) { + case 'course_signs_total': + $list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], null, null, null, true); + $list->load(['user', 'course']); + $data = $this->formatCourseSignsData($list); + $filename = '报名人数明细'; + break; + + case 'course_signs_pass': + $list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1, null, null, true); + $list->load(['user', 'course']); + $data = $this->formatCourseSignsData($list); + $filename = '审核通过人数明细'; + break; + + case 'course_signs_pass_unique': + $list = CourseSign::courseSignsTotalByUnique($params['start_date'], $params['end_date'], 1, null, null, true); + $data = $this->formatUsersData($list); + $filename = '审核通过人数去重明细'; + break; + + case 'course_total': + $list = $this->getCalendarsByCourses($courses, $params['start_date'], $params['end_date']); + $list->load('course'); + $data = $this->formatCalendarData($list); + $filename = '开课场次明细'; + break; + + case 'course_type_detail': + if (!$course_id) { + return $this->fail([ResponseCode::ERROR_PARAMETER, '课程分类明细需要提供course_id参数']); + } + $course_ids = explode(',', $course_id); + $list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1, $course_ids, null, true); + $list->load(['user', 'course']); + $data = $this->formatCourseSignsData($list); + $filename = '课程分类明细'; + break; + + case 'area_detail': + if (!$area) { + return $this->fail([ResponseCode::ERROR_PARAMETER, '区域明细需要提供area参数']); + } + $list = CourseSign::courseSignsTotal($params['start_date'], $params['end_date'], 1, $courses->pluck('id'), $area, true); + $list->load(['user', 'course']); + $data = $this->formatCourseSignsData($list); + $filename = '区域明细_' . $area; + break; + } + + if (empty($data)) { + return $this->fail([ResponseCode::ERROR_PARAMETER, '没有可导出的数据']); + } + + // 定义导出字段 + $exportFields = $this->getExportFields($export_type); + + // 导出Excel + return Excel::download( + new CommonExport($data, $exportFields), + $filename . '_' . date('YmdHis') . '.xlsx' + ); + } + + /** + * 获取课程统计参数 + */ + private function getCoursesHomeParams() + { $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) - // ->where('start_date', '<=', $end_date) - // ->where('start_date', '>=', $start_date) + + return [ + 'start_date' => request('start_date', CourseType::START_DATE), + 'end_date' => request('end_date', date('Y-m-d')), + 'course_type_id' => $course_type_id, + ]; + } + + /** + * 根据课程体系ID获取课程列表 + */ + private function getCoursesByTypeIds($course_type_id) + { + return Course::whereIn('type', $course_type_id)->get(); + } + + /** + * 根据课程列表获取日历数据 + */ + private function getCalendarsByCourses($courses, $start_date, $end_date) + { + return Calendar::whereIn('course_id', $courses->pluck('id')) + ->whereBetween('date', [$start_date, $end_date]) ->get(); + } - // 报名人数 - $list['course_signs_total'] = CourseSign::courseSignsTotal($start_date, $end_date); - // 审核通过人数 - $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, $userIds); - // 开课场次 - $calendar = Calendar::whereIn('course_id', $courses->pluck('id'))->whereBetween('date', [$start_date, $end_date])->get(); - $list['course_total'] = $calendar->count(); - // 开课天数 - $list['course_day_total'] = $calendar->sum(function ($course) { - $start = Carbon::parse($course->start_time); - $end = Carbon::parse($course->end_time); - return $end->diffInDays($start) + 1; // 包含起始和结束日期 - }); - // 课程分类明细统计 + /** + * 获取课程分类明细统计 + */ + private function getCourseTypesSum($start_date, $end_date, $course_type_id) + { $courseTypesSum = []; $courseTypes = CourseType::whereIn('id', $course_type_id)->get(); foreach ($courseTypes as $courseType) { - // 获取课程 - $courses2 = Course::where('type', $courseType->id) - // ->where('start_date', '<=', $end_date) - // ->where('start_date', '>=', $start_date) - ->get(); + $courses2 = Course::where('type', $courseType->id)->get(); foreach ($courses2 as $course) { $courseTypesSum[] = [ 'course_type' => $courseType->name, - // 培养人数 '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, $userIds), - 'user_ids' => $userIds, + 'course_type_signs_pass_unique' => CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses2->pluck('id'), null), 'course_name' => $course->name, 'course_signs_pass' => CourseSign::courseSignsTotal($start_date, $end_date, 1, [$course->id]), ]; } } - // 区域明细统计 + return $courseTypesSum; + } + + /** + * 获取区域明细统计 + */ + private function getAreasStatistics($start_date, $end_date, $courses) + { $areas = ParameterDetail::where('parameter_id', 5)->get(); foreach ($areas as $area) { $area->course_signs_pass = CourseSign::courseSignsTotal($start_date, $end_date, 1, $courses->pluck('id'), $area->value); - $area->course_signs_pass_unique = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses->pluck('id'), $area->value, $userIds); - $area->user_ids = $userIds; + $area->course_signs_pass_unique = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, $courses->pluck('id'), $area->value); } - return $this->success(compact('list', 'courseTypesSum', 'areas')); + return $areas; + } + + /** + * 格式化课程报名数据 + */ + private function formatCourseSignsData($list) + { + $data = []; + foreach ($list as $item) { + $user = $item->user; + $course = $item->course; + $data[] = [ + 'name' => $user ? ($user->name ?? $user->username ?? '') : '', + 'mobile' => $user->mobile ?? '', + 'company_name' => $user->company_name ?? '', + 'company_position' => $user->company_position ?? '', + 'company_area' => $user->company_area ?? '', + 'course_name' => $course->name ?? '', + 'status_text' => $item->status_text ?? '', + 'fee_status_text' => $item->fee_status_text ?? '', + 'created_at' => $item->created_at ?? '', + ]; + } + return $data; + } + + /** + * 格式化用户数据(去重) + */ + private function formatUsersData($list) + { + $data = []; + foreach ($list as $user) { + $data[] = [ + 'name' => $user->name ?? $user->username ?? '', + 'mobile' => $user->mobile ?? '', + 'company_name' => $user->company_name ?? '', + 'company_position' => $user->company_position ?? '', + 'company_area' => $user->company_area ?? '', + 'email' => $user->email ?? '', + ]; + } + return $data; + } + + /** + * 格式化日历数据 + */ + private function formatCalendarData($list) + { + $data = []; + foreach ($list as $item) { + $course = $item->course; + $data[] = [ + 'course_name' => $course ? ($course->name ?? '') : '', + 'date' => $item->date ?? '', + 'start_time' => $item->start_time ?? '', + 'end_time' => $item->end_time ?? '', + 'type_text' => $item->type_text ?? '', + 'is_publish_text' => $item->is_publish_text ?? '', + ]; + } + return $data; + } + + /** + * 获取导出字段配置 + */ + private function getExportFields($export_type) + { + $fields = [ + 'course_signs_total' => [ + 'name' => '姓名', + 'mobile' => '手机号', + 'company_name' => '公司名称', + 'company_position' => '职务', + 'company_area' => '公司区域', + 'course_name' => '课程名称', + 'status_text' => '审核状态', + 'fee_status_text' => '缴费状态', + 'created_at' => '报名时间', + ], + 'course_signs_pass' => [ + 'name' => '姓名', + 'mobile' => '手机号', + 'company_name' => '公司名称', + 'company_position' => '职务', + 'company_area' => '公司区域', + 'course_name' => '课程名称', + 'fee_status_text' => '缴费状态', + 'created_at' => '报名时间', + ], + 'course_signs_pass_unique' => [ + 'name' => '姓名', + 'mobile' => '手机号', + 'company_name' => '公司名称', + 'company_position' => '职务', + 'company_area' => '公司区域', + 'email' => '邮箱', + ], + 'course_total' => [ + 'course_name' => '课程名称', + 'date' => '日期', + 'start_time' => '开始时间', + 'end_time' => '结束时间', + 'type_text' => '类型', + 'is_publish_text' => '是否发布', + ], + 'course_type_detail' => [ + 'name' => '姓名', + 'mobile' => '手机号', + 'company_name' => '公司名称', + 'company_position' => '职务', + 'company_area' => '公司区域', + 'course_name' => '课程名称', + 'fee_status_text' => '缴费状态', + 'created_at' => '报名时间', + ], + 'area_detail' => [ + 'name' => '姓名', + 'mobile' => '手机号', + 'company_name' => '公司名称', + 'company_position' => '职务', + 'company_area' => '公司区域', + 'course_name' => '课程名称', + 'fee_status_text' => '缴费状态', + 'created_at' => '报名时间', + ], + ]; + + return $fields[$export_type] ?? []; } /** diff --git a/app/Models/CourseSign.php b/app/Models/CourseSign.php index 9b328af..54d81e3 100755 --- a/app/Models/CourseSign.php +++ b/app/Models/CourseSign.php @@ -78,7 +78,7 @@ class CourseSign extends SoftDeletesModel /** * 指定时间内的报名信息(未去重) */ - public static function courseSignsTotal($start_date, $end_date, $status = null, $course_ids = null, $area = null) + public static function courseSignsTotal($start_date, $end_date, $status = null, $course_ids = null, $area = null, $retList = false) { $total = CourseSign::whereDate('created_at', '>=', $start_date) ->whereDate('created_at', '<=', $end_date) @@ -98,15 +98,20 @@ class CourseSign extends SoftDeletesModel if (isset($course_ids)) { $query->whereIn('course_id', $course_ids); } - })->whereNotIn('status', [4, 5]) - ->count(); - return $total; + })->whereNotIn('status', [4, 5]); + if ($retList) { + // 返回列表 + return $total->get(); + } else { + // 返回统计数据 + return $total->count(); + } } /** * 指定时间内的报名信息(去重) */ - public static function courseSignsTotalByUnique($start_date, $end_date, $status = null, $course_ids = null, $area = null, &$userIds = null) + public static function courseSignsTotalByUnique($start_date, $end_date, $status = null, $course_ids = null, $area = null, $retList = false) { $courseSignByType = CourseSign::whereDate('created_at', '>=', $start_date) ->whereDate('created_at', '<=', $end_date) @@ -128,30 +133,14 @@ class CourseSign extends SoftDeletesModel } })->whereNotIn('status', [4, 5]) ->get(); - $userIds = $courseSignByType->implode('user_id', ','); - return User::whereIn('id', $courseSignByType->pluck('user_id'))->distinct('mobile')->count(); + $user = User::whereIn('id', $courseSignByType->pluck('user_id'))->distinct('mobile'); + if ($retList) { + // 列表 + return $user->get(); + } else { + // 统计数据 + return $user->count(); + } } - - /** - * 指定时间内的被投企业 - */ - public static function yhInvested($start_date, $end_date, $status = null, $course_ids = null) - { - $courseSignByType = CourseSign::whereDate('created_at', '>=', $start_date) - ->whereDate('created_at', '<=', $end_date) - ->where(function ($query) use ($status, $course_ids) { - if (isset($status)) { - $query->where('status', $status); - } - if (isset($course_ids)) { - $query->whereIn('course_id', $course_ids); - } - })->whereNotIn('status', [4, 5]) - ->get(); - return Company::whereHas('users', function ($query) use ($courseSignByType) { - $query->whereIn('id', $courseSignByType->pluck('user_id')); - })->where('is_yh_invested', 1)->count(); - } - } diff --git a/routes/api.php b/routes/api.php index 847adc7..9398cef 100755 --- a/routes/api.php +++ b/routes/api.php @@ -38,6 +38,7 @@ Route::group(["namespace" => "Admin", "prefix" => "admin"], function () { Route::get('other/home-v2', [\App\Http\Controllers\Admin\OtherController::class, "homeV2"]); Route::get('other/courses-home', [\App\Http\Controllers\Admin\OtherController::class, "coursesHome"]); + Route::get('other/courses-home-export', [\App\Http\Controllers\Admin\OtherController::class, "coursesHomeExport"]); // 验证码登陆 Route::get('auth/sms-login', [\App\Http\Controllers\Admin\AuthController::class, "smsLogin"]);