From 9863a23eb9723c0f0d58bed60531092ce3e0a66a Mon Sep 17 00:00:00 2001 From: cody <648753004@qq.com> Date: Sat, 17 Jan 2026 14:30:38 +0800 Subject: [PATCH] update --- .../Admin/EmployeeParticipationController.php | 65 +++++-- .../Controllers/Admin/OtherController.php | 30 ++-- app/Models/CourseSign.php | 161 +++++++++--------- app/Models/StockCompany.php | 41 +++++ 4 files changed, 184 insertions(+), 113 deletions(-) diff --git a/app/Http/Controllers/Admin/EmployeeParticipationController.php b/app/Http/Controllers/Admin/EmployeeParticipationController.php index 308324e..33f8ce6 100644 --- a/app/Http/Controllers/Admin/EmployeeParticipationController.php +++ b/app/Http/Controllers/Admin/EmployeeParticipationController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin; use App\Exports\BaseExport; use App\Helpers\ResponseCode; +use App\Models\Course; use App\Models\CustomForm; use App\Models\CustomFormField; use App\Models\EmployeeParticipation; @@ -245,28 +246,58 @@ class EmployeeParticipationController extends BaseController $tempFile = $file->getRealPath(); $dataArray = (new FastExcel)->import($tempFile)->toArray(); - // 固定的字段映射(Excel表头中文 => 数据库字段名) - $fieldMapping = [ - '类型' => 'type', - '开始日期' => 'start_date', - '结束日期' => 'end_date', - '数量' => 'total', - '课程类型ID' => 'course_type_id', - '课程ID' => 'course_id', - '课程名称' => 'course_name', - '公司名字' => 'company_name', - '姓名' => 'name', - '部门' => 'department', + // 类型映射:中文 => 数字 + $typeMapping = [ + '元和员工参与' => 1, + '干部培训' => 2, + ]; + + // 类型名称映射:数字 => 中文 + $typeNameMapping = [ + 1 => '元和员工参与', + 2 => '干部培训', ]; $list = []; foreach ($dataArray as $key => $value) { $list[$key] = []; - // 根据固定字段映射转换数据 - foreach ($fieldMapping as $excelHeader => $dbField) { - if (isset($value[$excelHeader])) { - $list[$key][$dbField] = $value[$excelHeader]; - } + + // 只读取 Excel 中的字段:类型、课程名称、公司名称、姓名、部门 + $courseName = $value['课程名称'] ?? null; + $typeText = $value['类型'] ?? null; + + // 转换类型:中文 -> 数字 + $type = null; + if ($typeText) { + $type = $typeMapping[$typeText] ?? null; + } + + // 根据课程名称查找课程信息 + $course = null; + if ($courseName) { + $course = Course::where('name', $courseName)->first(); + } + + // 填充基础字段 + $list[$key]['type'] = $type; + $list[$key]['type_name'] = $type ? ($typeNameMapping[$type] ?? '') : ''; + $list[$key]['course_name'] = $courseName; + $list[$key]['company_name'] = $value['公司名称'] ?? null; + $list[$key]['name'] = $value['姓名'] ?? null; + $list[$key]['department'] = $value['部门'] ?? null; + + // 根据课程信息填充其他字段 + if ($course) { + $list[$key]['start_date'] = $course->start_date; + $list[$key]['end_date'] = $course->end_date; + $list[$key]['course_type_id'] = $course->type; + $list[$key]['course_id'] = $course->id; + } else { + // 如果找不到课程,字段设为 null + $list[$key]['start_date'] = null; + $list[$key]['end_date'] = null; + $list[$key]['course_type_id'] = null; + $list[$key]['course_id'] = null; } } return $this->success($list); diff --git a/app/Http/Controllers/Admin/OtherController.php b/app/Http/Controllers/Admin/OtherController.php index 0994eea..372db79 100755 --- a/app/Http/Controllers/Admin/OtherController.php +++ b/app/Http/Controllers/Admin/OtherController.php @@ -134,8 +134,8 @@ class OtherController extends CommonController // 校友总数 $list['schoolmate_total'] = User::where('is_schoolmate', 1)->count(); - // 今年新增校友数 - $list['schoolmate_year'] = User::where('is_schoolmate', 1)->where('created_at', 'like', '%' . date('Y') . '%')->count(); + // 今年新增校友数(根据schoolmate_time字段统计) + $list['schoolmate_year'] = User::where('is_schoolmate', 1)->whereYear('schoolmate_time', date('Y'))->count(); // 投后企业 $list['company_invested_total'] = CourseSign::yhInvestedTotal(CourseType::START_DATE, date('Y-m-d'), null); // 元和员工参与人数 @@ -318,20 +318,25 @@ class OtherController extends CommonController // 跟班学员数(在指定时间范围内报名的学员中,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表获取,stock_date在指定时间范围内) + $list['company_market_year_total'] = StockCompany::getByDateRange($start_date, $end_date); - // 入学后上市公司数量(从stock_companys表获取,is_after_enrollment = 1) - $list['company_market_after_enrollment_total'] = StockCompany::where('is_after_enrollment', 1)->count(); + // 入学后上市公司数量(从stock_companys表获取,is_after_enrollment = 1,stock_date在指定时间范围内) + $list['company_market_after_enrollment_total'] = StockCompany::getAfterEnrollment($start_date, $end_date); - // 累计被投企业数 + // 累计被投企业数,被投企业覆盖数 $list['course_signs_invested'] = CourseSign::yhInvestedTotal(CourseType::START_DATE, $end_date, $course_ids); - // 入学后被投企业数量(在指定时间范围内报名的学员所在公司中,在入学后被投的公司数量) + // 当前被投企业覆盖数(根据传入的开始结束时间统计) + $list['course_signs_invested_current'] = CourseSign::yhInvestedTotal($start_date, $end_date, $course_ids); + + // 当前入学后被投企业数量(在指定时间范围内报名的学员所在公司中,在入学后被投的公司数量) $list['company_invested_after_enrollment_total'] = CourseSign::companyInvestedAfterEnrollment($start_date, $end_date, $course_ids); - // 今年被投企业数 + // 累计入学后被投企业数量(从CourseType::START_DATE开始的入学后被投企业数量) + $list['company_invested_after_enrollment_total_cumulative'] = CourseSign::companyInvestedAfterEnrollment(CourseType::START_DATE, $end_date, $course_ids); + + // 当前被投企业数 $list['company_invested_year_total'] = CourseSign::companyInvestedYear($start_date, $end_date, $course_ids); // 元和员工参与人数 @@ -1101,8 +1106,7 @@ class OtherController extends CommonController case 'company_market_year_total': // 今年上市公司明细 - 从stock_companys表获取,与coursesHome统计逻辑保持一致 - $currentYear = date('Y'); - $stockCompanies = StockCompany::with('company')->whereYear('stock_date', $currentYear)->get(); + $stockCompanies = StockCompany::getByDateRange($start_date, $end_date, true)->load('company'); foreach ($stockCompanies as $stockCompany) { // 通过company_id关联到Company表获取详细信息 @@ -1222,7 +1226,7 @@ class OtherController extends CommonController case 'company_market_after_enrollment_total': // 入学后上市公司明细 - 从stock_companys表获取,与coursesHome统计逻辑保持一致 - $stockCompanies = StockCompany::with('company')->where('is_after_enrollment', 1)->get(); + $stockCompanies = StockCompany::getAfterEnrollment($start_date, $end_date, true)->load('company'); foreach ($stockCompanies as $stockCompany) { // 通过company_id关联到Company表获取详细信息 diff --git a/app/Models/CourseSign.php b/app/Models/CourseSign.php index 9041e70..ebfeaff 100755 --- a/app/Models/CourseSign.php +++ b/app/Models/CourseSign.php @@ -188,33 +188,6 @@ class CourseSign extends SoftDeletesModel $companies = Company::approvedStudents()->whereHas('users', function ($query) use ($userIds) { $query->whereIn('id', $userIds); })->where('is_yh_invested', 1)->get(); - // 自定义时间:需要按被投时间筛选 - // 筛选出被投时间在范围内的企业 - $filteredCompanies = []; - foreach ($companies as $company) { - $projectUsers = $company->project_users ?? []; - $hasValidInvestDate = false; - $allInvestDatesNull = true; - - foreach ($projectUsers as $item) { - $investDate = $item['investDate'] ?? null; - // 检查是否有有效的被投时间 - if ($investDate) { - $allInvestDatesNull = false; - // 检查被投时间是否在范围内 - if ($investDate <= $end_date) { - $hasValidInvestDate = true; - break; // 只要有一条满足就加入 - } - } - } - - // 如果有有效的被投时间在范围内,或者所有被投时间都是null,则加入结果 - if ($hasValidInvestDate || $allInvestDatesNull) { - $filteredCompanies[] = $company; - } - } - $companies = collect($filteredCompanies); // 返回结果 if ($retList) { @@ -482,63 +455,84 @@ class CourseSign extends SoftDeletesModel } /** - * 入学后被投企业数量(在指定时间范围内报名的学员所在公司中,在入学后被投的公司数量) + * 当前入学后被投企业数量(被投时间在指定时间范围内,且学员入学时间小于等于被投时间的公司数量) * @param string $start_date 开始日期 * @param string $end_date 结束日期 - * @param array|null $course_ids 课程ID数组,不传则统计所有课程 + * @param array|null $course_ids 课程ID数组(已废弃,保留以兼容) * @param bool $retList 是否返回列表,false返回数量,true返回列表 * @return int|array */ public static function companyInvestedAfterEnrollment($start_date, $end_date, $course_ids = null, $retList = false) { - $courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids); - $courseSignsForInvest = $courseSignsQuery->with(['user.company', 'course'])->get(); + // 获取所有被投企业 + $companies = Company::approvedStudents()->where('is_yh_invested', 1)->get(); $companiesAfterEnrollment = []; - foreach ($courseSignsForInvest as $sign) { - if ($sign->user && $sign->user->company && $sign->user->company->is_yh_invested == 1) { - // 入学时间:使用参与课程的课程开始时间(course->start_date),不使用报名时间(created_at) - $enrollmentDate = null; - if ($sign->course && $sign->course->start_date) { - $enrollmentDate = \Carbon\Carbon::parse($sign->course->start_date)->format('Y-m-d'); - } - // 如果没有课程开始时间,跳过这条记录 - if (!$enrollmentDate) { - continue; - } + foreach ($companies as $company) { + $projectUsers = $company->project_users ?? []; - // 从 project_users 中检查是否有任何一个被投时间 >= 课程开始时间(入学时间) - $projectUsers = $sign->user->company->project_users; - $hasInvestAfterEnrollment = false; - $investDate = null; - if (!empty($projectUsers) && is_array($projectUsers)) { - foreach ($projectUsers as $projectUser) { - if (!empty($projectUser['investDate'])) { - $currentInvestDate = $projectUser['investDate']; - // 只要有一个被投时间 >= 课程开始时间(入学时间),就满足条件 - if ($currentInvestDate >= $enrollmentDate) { - $hasInvestAfterEnrollment = true; - // 记录满足条件的被投时间(如果有多个,记录最早的) - if ($investDate === null || $currentInvestDate < $investDate) { - $investDate = $currentInvestDate; + // 遍历被投时间,找到在指定时间范围内的被投时间 + foreach ($projectUsers as $projectUser) { + $investDate = $projectUser['investDate'] ?? null; + + // 检查被投时间是否在指定时间范围内 + if ($investDate && $investDate >= $start_date && $investDate <= $end_date) { + // 获取该公司的所有学员 + $users = $company->users()->get(); + + // 检查是否有学员的入学时间(课程开始时间)小于等于被投时间 + $hasValidEnrollment = false; + $firstEnrollmentDate = null; + $matchedUsers = []; + + foreach ($users as $user) { + // 获取该学员的所有审核通过的课程报名记录 + $courseSigns = self::where('user_id', $user->id) + ->where('status', 1) + ->with('course') + ->get(); + + foreach ($courseSigns as $courseSign) { + if ($courseSign->course && $courseSign->course->start_date) { + $enrollmentDate = \Carbon\Carbon::parse($courseSign->course->start_date)->format('Y-m-d'); + + // 检查入学时间是否小于等于被投时间 + if ($enrollmentDate <= $investDate) { + $hasValidEnrollment = true; + // 记录最早的入学时间 + if ($firstEnrollmentDate === null || $enrollmentDate < $firstEnrollmentDate) { + $firstEnrollmentDate = $enrollmentDate; + } + if ($retList) { + $matchedUsers[] = $user; + } + break; // 只要有一个课程满足条件即可 } } } } - } - // 只要有一个被投时间 >= 课程开始时间(入学时间),说明是入学后被投 - if ($hasInvestAfterEnrollment && $investDate) { - $companyId = $sign->user->company->id; - if (!isset($companiesAfterEnrollment[$companyId])) { - $companiesAfterEnrollment[$companyId] = [ - 'company' => $sign->user->company, - 'first_enrollment_date' => $enrollmentDate, // 首次入学时间(课程开始时间) - 'invest_date' => $investDate, - 'users' => [], - ]; - } - if ($retList) { - $companiesAfterEnrollment[$companyId]['users'][] = $sign->user; + + // 如果有学员的入学时间小于等于被投时间,则计入统计 + if ($hasValidEnrollment) { + $companyId = $company->id; + if (!isset($companiesAfterEnrollment[$companyId])) { + $companiesAfterEnrollment[$companyId] = [ + 'company' => $company, + 'first_enrollment_date' => $firstEnrollmentDate, + 'invest_date' => $investDate, + 'users' => [], + ]; + } + if ($retList) { + // 合并用户列表(去重) + $existingUserIds = array_column($companiesAfterEnrollment[$companyId]['users'], 'id'); + foreach ($matchedUsers as $user) { + if (!in_array($user->id, $existingUserIds)) { + $companiesAfterEnrollment[$companyId]['users'][] = $user; + } + } + } + break; // 只要有一个被投时间满足条件即可 } } } @@ -630,18 +624,22 @@ class CourseSign extends SoftDeletesModel } } - // 如果 config 中没有数据,使用空数组(避免 SQL 错误) + // 如果 config 中没有数据,直接返回空 if (empty($companyNameKeyword)) { - $list = collect([]); - } else { - $list = User::whereIn('id', $courseSignByType->pluck('user_id')) - ->where(function ($query) use ($companyNameKeyword) { - foreach ($companyNameKeyword as $item) { - $query->orWhere('company_name', 'like', '%' . $item . '%'); - } - })->get(); + if ($retList) { + return collect([]); + } else { + return 0; + } } + $list = User::whereIn('id', $courseSignByType->pluck('user_id')) + ->where(function ($query) use ($companyNameKeyword) { + foreach ($companyNameKeyword as $item) { + $query->orWhere('company_name', 'like', '%' . $item . '%'); + } + })->get(); + if ($retList) { // 返回列表 return $list; @@ -708,10 +706,7 @@ class CourseSign extends SoftDeletesModel */ public static function isSuzhou($user = null, $company = null) { - // 判断是否为苏州地区:user表的company_address包含"苏州",或关联公司的company_address包含"苏州",或company_city包含"苏州" - if ($user && $user->company_address && strpos($user->company_address, '苏州') !== false) { - return true; - } + // 判断是否为苏州地区:关联公司的company_address包含"苏州",或company_city包含"苏州" if ($company && $company->company_address && strpos($company->company_address, '苏州') !== false) { return true; } diff --git a/app/Models/StockCompany.php b/app/Models/StockCompany.php index e114974..644881f 100644 --- a/app/Models/StockCompany.php +++ b/app/Models/StockCompany.php @@ -27,5 +27,46 @@ class StockCompany extends SoftDeletesModel { return $this->belongsTo(Company::class, 'company_id', 'id'); } + + /** + * 获取指定时间范围内的上市公司数量(统计或列表) + * @param string|null $start_date 开始日期 + * @param string|null $end_date 结束日期 + * @param bool $retList 是否返回列表,false返回数量,true返回列表 + * @return int|\Illuminate\Database\Eloquent\Collection + */ + public static function getByDateRange($start_date = null, $end_date = null, $retList = false) + { + $query = self::when($start_date && $end_date, function ($query) use ($start_date, $end_date) { + $query->whereBetween('stock_date', [$start_date, $end_date]); + }); + + if ($retList) { + return $query->get(); + } else { + return $query->count(); + } + } + + /** + * 获取入学后上市的公司数量(统计或列表) + * @param string|null $start_date 开始日期 + * @param string|null $end_date 结束日期 + * @param bool $retList 是否返回列表,false返回数量,true返回列表 + * @return int|\Illuminate\Database\Eloquent\Collection + */ + public static function getAfterEnrollment($start_date = null, $end_date = null, $retList = false) + { + $query = self::where('is_after_enrollment', 1) + ->when($start_date && $end_date, function ($query) use ($start_date, $end_date) { + $query->whereBetween('stock_date', [$start_date, $end_date]); + }); + + if ($retList) { + return $query->get(); + } else { + return $query->count(); + } + } }