Merge branch 'master' of ssh://47.101.48.251:/data/git/wx.sstbc.com

master
lion 1 week ago
commit 14d175393b

@ -226,8 +226,12 @@ class UpdateCompany extends Command
$bar = $this->output->createProgressBar($total);
$bar->start();
// 上市代码正则:数字.SH 或 数字.SZ 或 数字.BJ
$stockCodePattern = '/\d{6}\.(SH|SZ|BJ)/i';
// 上市代码正则:匹配全球各地上市公司股票代码后缀
// 支持的后缀:.SH,.SZ,.BJ,.TW,.HK,.SG,.US,.DE,.FR,.JP,.KR,.N,.O,.A,.PK,.Q,.TO,.AX,.L,-S,-B,-SB,-P,-Z,-W,-SW,-SWR,-R,-WR,-X,-SS,-RS,.WS,.U,.PR,.B,.DB,.UN,.RT,.WT,.E,.C,.D,.F,.G,.H,.I,.J,.K,.L,.M,.N,.O,.P,.V,.Y,.Z
// 简化匹配:只要字符串中包含分隔符(.或-)+指定后缀,就算上市
// 支持格式688001.SH、AAPG.O、TSLA.US、华兴源创688001.SH
// 后缀按长度从长到短排序,避免短后缀误匹配
$stockCodePattern = '/[.\-](SWR|SW|WR|SS|RS|SB|PK|TO|AX|WS|PR|DB|UN|RT|WT|SH|SZ|BJ|TW|HK|SG|US|DE|FR|JP|KR|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|U|V|W|X|Y|Z)(?![A-Za-z0-9])/i';
$updatedCount = 0;
foreach ($companies as $company) {

@ -120,7 +120,14 @@ class CompanyController extends BaseController
}
if ($key == 'company_tag') {
$valueArray = explode(',', $value);
$query->whereIn($key, $valueArray);
if (!empty($valueArray)) {
$query->where(function ($q) use ($valueArray) {
foreach ($valueArray as $item) {
$item = trim($item);
$q->where('company_tag', 'like', '%' . $item . '%');
}
});
}
continue;
}

@ -237,22 +237,23 @@ class OtherController extends CommonController
$course_type_id = request('course_type_id');
if ($course_type_id) {
$course_type_id = explode(',', $course_type_id);
$query->whereIn('course_type_id1', $course_type_id);
$query->whereIn('course_type_id', $course_type_id);
}
});
$list['course_total'] = (clone $calendar)->count();
// 开课天数
$list['course_day_total'] = (clone $calendar)->where('is_count_days', 1)->sum('days');
$course_ids = $courses->pluck('id');
// 上市公司数(所有上市公司)
$list['company_market_total'] = Company::companyMarket($start_date, $end_date);
$list['company_market_total'] = CourseSign::shangshi($start_date, $end_date, $course_ids);
// 跟班学员数在指定时间范围内报名的学员中from为'跟班学员'的数量)
$course_ids = $courses->pluck('id');
$list['ganbu_total'] = CourseSign::genban($start_date, $end_date, $course_ids);
// 今年上市公司数量stock_date在今年
$list['company_market_year_total'] = Company::companyMarketYear($start_date, $end_date, $course_ids);
$list['company_market_year_total'] = CourseSign::companyMarketYear($start_date, $end_date, $course_ids);
// 入学后上市公司数量(在指定时间范围内报名的学员所在公司中,在入学后上市的公司数量)
$list['company_market_after_enrollment_total'] = CourseSign::companyMarketAfterEnrollment($start_date, $end_date, $course_ids);
@ -260,6 +261,9 @@ class OtherController extends CommonController
// 入学后被投企业数量(在指定时间范围内报名的学员所在公司中,在入学后被投的公司数量)
$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);
// 全市干部参与企业
@ -304,30 +308,30 @@ class OtherController extends CommonController
}
}
// 附加历史课程数据
$historyCourses = 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(function ($query) {
$course_type_id = request('course_type_id', '');
$course_type_id = explode(',', $course_type_id);
if ($course_type_id) {
$query->whereIn('type', $course_type_id);
}
})->get();
foreach ($historyCourses as $historyCourse) {
$courseTypesSum[] = [
'course_type' => $historyCourse->typeDetail->name,
// 培养人数
'course_type_signs_pass' => $historyCourse->course_type_signs_pass,
// 去重培养人数
'course_type_signs_pass_unique' => $historyCourse->course_type_signs_pass_unique,
'course_name' => $historyCourse->course_name,
'course_signs_pass' => $historyCourse->course_signs_pass,
];
}
// $historyCourses = 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(function ($query) {
// $course_type_id = request('course_type_id');
// if ($course_type_id) {
// $course_type_id = explode(',', $course_type_id);
// $query->whereIn('type', $course_type_id);
// }
// })->get();
// foreach ($historyCourses as $historyCourse) {
// $courseTypesSum[] = [
// 'course_type' => $historyCourse->typeDetail->name,
// // 培养人数
// 'course_type_signs_pass' => $historyCourses->where('type', $historyCourse->type)->sum('course_type_signs_pass'),
// // 去重培养人数
// 'course_type_signs_pass_unique' => $historyCourses->where('type', $historyCourse->type)->sum('course_type_signs_pass_unique'),
// 'course_name' => $historyCourse->course_name,
// 'course_signs_pass' => $historyCourse->course_signs_pass,
// ];
// }
// 区域明细统计
$areas = CourseSign::area($start_date, $end_date, 1, $courses->pluck('id'), true);
@ -564,10 +568,17 @@ class OtherController extends CommonController
break;
case 'company_market_total':
// 上市公司明细 - 所有上市公司
$companies = Company::companyMarket($start_date, $end_date, true);
foreach ($companies as $company) {
$data[] = [
// 上市公司明细 - 所有上市公司,关联学员、课程信息
// 数据结构:主表是公司,子数据是学员信息
// 导出时:公司信息只在第一行显示,后续行公司信息为空
$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 ?? '',
@ -575,7 +586,60 @@ class OtherController extends CommonController
'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' => '',
'stock_date' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'user_name' => $userInfo['user_name'] ?? '',
'course_name' => $courseDisplay,
];
}
}
}
}
$fields = [
'company_name' => '企业名称',
@ -583,8 +647,11 @@ class OtherController extends CommonController
'company_date' => '成立时间',
'stock_date' => '上市日期',
'company_address' => '地址',
'company_city' => '营业范围',
'company_area' => '联系电话',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'user_name' => '学员姓名',
'course_name' => '课程信息',
];
$filename = '上市公司明细';
break;
@ -614,10 +681,17 @@ class OtherController extends CommonController
break;
case 'company_market_year_total':
// 今年上市公司明细 - 使用模型方法
$companies = Company::companyMarketYear($start_date, $end_date, $course_ids, true);
foreach ($companies as $company) {
$data[] = [
// 今年上市公司明细 - 所有今年上市公司,关联学员、课程信息
// 数据结构:主表是公司,子数据是学员信息
// 导出时:公司信息只在第一行显示,后续行公司信息为空
$companiesData = CourseSign::companyMarketYear($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 ?? '',
@ -625,7 +699,60 @@ class OtherController extends CommonController
'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' => '',
'stock_date' => '',
'company_address' => '',
'company_city' => '',
'company_area' => '',
'company_tag' => '',
'user_name' => $userInfo['user_name'] ?? '',
'course_name' => $courseDisplay,
];
}
}
}
}
$fields = [
'company_name' => '企业名称',
@ -633,8 +760,11 @@ class OtherController extends CommonController
'company_date' => '成立时间',
'stock_date' => '上市日期',
'company_address' => '地址',
'company_city' => '营业范围',
'company_area' => '联系电话',
'company_city' => '所在城市',
'company_area' => '所在区域',
'company_tag' => '企业资质',
'user_name' => '学员姓名',
'course_name' => '课程信息',
];
$filename = '今年上市公司明细';
break;
@ -781,7 +911,7 @@ class OtherController extends CommonController
$data[] = [
'user_name' => $user->name ?? '',
'mobile' => $user->mobile ?? '',
'company_name' => $user->company->company_name ?? '',
'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 ?? '',

@ -55,9 +55,11 @@ class UserController extends BaseController
{
$all = request()->all();
$list = $this->model->with(underlineToHump($all['show_relation'] ?? []))
->with(['courseSigns' => function ($query) use ($all) {
$query->where('status', 1)->with('course.teacher', 'course.typeDetail');
}])->where(function ($query) use ($all) {
->with([
'courseSigns' => function ($query) use ($all) {
$query->where('status', 1)->with('course.teacher', 'course.typeDetail');
}
])->where(function ($query) use ($all) {
if (isset($all['keyword'])) {
$query->whereHas('courses', function ($q) use ($all) {
$q->where('name', 'like', '%' . $all['keyword'] . '%');
@ -196,13 +198,22 @@ class UserController extends BaseController
$start_date = $year . '-01-01';
$end_date = $year . '-12-31';
$list = $this->model->with('appointments', 'companyIndustryDetail',
'companyPositionDetail', 'companyAreaDetail', 'company')
->with(['courseSigns' => function ($query) {
$query->with('course.typeDetail')->orderBy('fee_status', 'desc');
}])->withCount(['appointments' => function ($query) {
$query->whereIn('status', [0, 1]);
}]);
$list = $this->model->with(
'appointments',
'companyIndustryDetail',
'companyPositionDetail',
'companyAreaDetail',
'company'
)
->with([
'courseSigns' => function ($query) {
$query->with('course.typeDetail')->orderBy('fee_status', 'desc');
}
])->withCount([
'appointments' => function ($query) {
$query->whereIn('status', [0, 1]);
}
]);
// 是否被投企业
if (isset($all['is_yh_invested'])) {
$list = $list->whereHas('company', function ($query) use ($all) {
@ -213,11 +224,27 @@ class UserController extends BaseController
}
});
}
// company_tag等价于company_type新旧数据兼容
if (isset($all['company_type'])) {
$all['company_tag'] = $all['company_type'];
}
// 新数据
if (isset($all['company_tag'])) {
$list = $list->whereHas('company', function ($query) use ($all) {
$query->where('company_tag', 'like', '%' . $all['company_tag'] . '%');
$string = explode(',', $all['company_tag']);
$query->where(function ($q) use ($string) {
foreach ($string as $index => $v) {
if ($index === 0) {
$q->where('company_tag', 'like', '%' . trim($v) . '%');
} else {
$q->orWhere('company_tag', 'like', '%' . trim($v) . '%');
}
}
});
});
}
$list = $list->whereHas('courseSigns', function ($query) use ($all) {
if (isset($all['course_id'])) {
$query->where('course_id', $all['course_id']);
@ -302,14 +329,6 @@ class UserController extends BaseController
$company_area = explode(',', $all['company_area']);
$query->whereIn('company_area', $company_area);
}
if (isset($all['company_type'])) {
$company_type = explode(',', $all['company_type']);
$query->where(function ($q) use ($company_type) {
foreach ($company_type as $v) {
$q->orWhereRaw('FIND_IN_SET(?, company_type)', [$v]);
}
});
}
if (isset($all['company_industry'])) {
$company_industry = explode(',', $all['company_industry']);
$query->where(function ($q) use ($company_industry) {
@ -521,7 +540,8 @@ class UserController extends BaseController
} else {
if (in_array($k, ['company_type', 'type'])) {
$list[$key][$k] = str_replace('、', ',', $value[$v]);
$list[$key][$k] = str_replace('', ',', $list[$key][$k]);;
$list[$key][$k] = str_replace('', ',', $list[$key][$k]);
;
} else {
$list[$key][$k] = $value[$v];
}
@ -672,7 +692,7 @@ class UserController extends BaseController
if (isset($all['is_schoolmate'])) {
$data['is_schoolmate'] = $all['is_schoolmate'];
}
// if (isset($all['is_black'])) {
// if (isset($all['is_black'])) {
// $data['is_black'] = $all['is_black'];
// }
$this->model->whereIn('id', $idsArray)->update($data);

@ -58,52 +58,4 @@ class Company extends SoftDeletesModel
}
}
/**
* 上市公司(统计或列表)
* @param bool $retList 是否返回列表false返回数量true返回列表
* @return int|\Illuminate\Database\Eloquent\Collection
*/
public static function companyMarket($start_date, $end_date, $retList = false)
{
$courseSignByType = CourseSign::whereDate('created_at', '>=', $start_date)
->whereDate('created_at', '<=', $end_date)
->whereNotIn('status', [4, 5])
->get();
$list = Company::whereHas('users', function ($query) use ($courseSignByType) {
$query->whereIn('id', $courseSignByType->pluck('user_id'));
})->where('company_market', 1)->get();
if ($retList) {
// 返回列表
return $list;
} else {
// 返回统计数据
return $list->count();
}
}
/**
* 今年上市公司(统计或列表)
* @param int|null $year 年份,不传则使用当前年份
* @param bool $retList 是否返回列表false返回数量true返回列表
* @return int|\Illuminate\Database\Eloquent\Collection
*/
public static function companyMarketYear($start_date, $end_date, $course_ids, $retList = false)
{
$year = date('Y');
$courseSignByType = CourseSign::whereDate('created_at', '>=', $start_date)
->whereDate('created_at', '<=', $end_date)
->whereNotIn('status', [4, 5])
->get();
$list = Company::whereHas('users', function ($query) use ($courseSignByType) {
$query->whereIn('id', $courseSignByType->pluck('user_id'));
})->where('company_market', 1)->whereYear('stock_date', $year)->get();
if ($retList) {
// 返回列表
return $list;
} else {
// 返回统计数据
return $list->count();
}
}
}

@ -117,9 +117,9 @@ class CourseSign extends SoftDeletesModel
$query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]);
})->where(function ($query) {
$course_type_id = request('course_type_id', '');
$course_type_id = explode(',', $course_type_id);
$course_type_id = request('course_type_id');
if ($course_type_id) {
$course_type_id = explode(',', $course_type_id);
$query->whereIn('type', $course_type_id);
}
})->sum('course_type_signs_pass');
@ -148,9 +148,9 @@ class CourseSign extends SoftDeletesModel
$query->whereBetween('start_time', [$start_date, $end_date])
->orWhereBetween('end_time', [$start_date, $end_date]);
})->where(function ($query) {
$course_type_id = request('course_type_id', '');
$course_type_id = explode(',', $course_type_id);
$course_type_id = request('course_type_id');
if ($course_type_id) {
$course_type_id = explode(',', $course_type_id);
$query->whereIn('type', $course_type_id);
}
})->sum('course_type_signs_pass_unique');
@ -213,6 +213,109 @@ class CourseSign extends SoftDeletesModel
}
}
/**
* 今年被投企业统计(统计或列表)
* @param string|null $start_date 开始日期
* @param string|null $end_date 结束日期
* @param array|null $course_ids 课程ID数组不传则统计所有课程
* @param bool $retList 是否返回列表false返回数量true返回列表包含学员、课程信息
* @return int|array
*/
public static function companyInvestedYear($start_date = null, $end_date = null, $course_ids = null, $retList = false)
{
$courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids);
$courseSigns = $courseSignsQuery->with(['user.company', 'course.typeDetail'])->get();
// 获取所有被投企业的ID
$companyIds = $courseSigns->pluck('user.company.id')
->filter()
->unique()
->toArray();
$year = date('Y');
// 获取这些公司中标记为被投的公司
$allInvestedCompanies = Company::whereIn('id', $companyIds)
->where('is_yh_invested', 1)
->get();
// 筛选出被投时间在今年的企业
$companies = [];
foreach ($allInvestedCompanies as $company) {
$projectUsers = $company->project_users ?? [];
$hasInvestThisYear = false;
foreach ($projectUsers as $item) {
$investDate = $item['investDate'] ?? null;
if ($investDate) {
$investYear = date('Y', strtotime($investDate));
if ($investYear == $year) {
$hasInvestThisYear = true;
break;
}
}
}
if ($hasInvestThisYear) {
$companies[$company->id] = $company;
}
}
$companies = collect($companies);
if ($retList) {
// 返回详细列表:主表是公司,子数据是学员信息
$result = [];
foreach ($courseSigns as $courseSign) {
if (!$courseSign->user || !$courseSign->user->company) {
continue;
}
$companyId = $courseSign->user->company->id;
// 只处理今年被投企业的记录
if (!isset($companies[$companyId])) {
continue;
}
$company = $companies[$companyId];
// 如果公司还没有在结果中,初始化
if (!isset($result[$companyId])) {
$result[$companyId] = [
'company' => $company,
'users' => [],
];
}
// 按学员分组,收集每个学员的课程信息
$userId = $courseSign->user->id;
if (!isset($result[$companyId]['users'][$userId])) {
$result[$companyId]['users'][$userId] = [
'user' => $courseSign->user,
'user_name' => $courseSign->user->name ?? '',
'mobile' => $courseSign->user->mobile ?? '',
'courses' => [],
];
}
// 添加该学员的课程信息
$result[$companyId]['users'][$userId]['courses'][] = [
'course_name' => $courseSign->course->name ?? '',
'course_type' => $courseSign->course->typeDetail->name ?? '',
'course_sign' => $courseSign,
];
}
// 将 users 转换为数组(去掉 user_id 作为 key
foreach ($result as $companyId => $item) {
$result[$companyId]['users'] = array_values($item['users']);
}
// 转换为数组并返回
return array_values($result);
} else {
// 返回统计数据
return $companies->count();
}
}
/**
* 跟班学员(统计或列表)
* @param string $start_date 开始日期
@ -410,14 +513,17 @@ class CourseSign extends SoftDeletesModel
'常州团队',
'国企元禾'
];
$company = Company::where(function ($query) use ($companyNameKeyword) {
foreach ($companyNameKeyword as $item) {
$query->orWhere('company_name', 'like', '%' . $item . '%');
}
})->get();
// $company = Company::where(function ($query) use ($companyNameKeyword) {
// foreach ($companyNameKeyword as $item) {
// $query->orWhere('company_name', 'like', '%' . $item . '%');
// }
// })->get();
$list = User::whereIn('id', $courseSignByType->pluck('user_id'))
->whereIn('company_id', $company->pluck('id'))
->get();
->where(function ($query) use ($companyNameKeyword) {
foreach ($companyNameKeyword as $item) {
$query->orWhere('company_name', 'like', '%' . $item . '%');
}
})->get();
if ($retList) {
// 返回列表
@ -479,34 +585,206 @@ class CourseSign extends SoftDeletesModel
public static function rencai($start_date = null, $end_date = null, $course_ids = null, $retList = false)
{
$courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids);
$courseSigns = $courseSignsQuery->whereHas('course', function ($query) {
// 条件1人才培训课程类型的用户
$courseSigns1 = $courseSignsQuery->whereHas('course', function ($query) {
$query->whereHas('typeDetail', function ($q) {
$q->where('name', '人才培训');
});
})->get();
// 条件2data 字段中 name="个人荣誉" 且 value != "其他" 的用户
$courseSigns2 = $courseSignsQuery->get()->filter(function ($courseSign) {
if (empty($courseSign->data) || !is_array($courseSign->data)) {
return false;
}
foreach ($courseSign->data as $item) {
if (isset($item['key']) && $item['key'] === 'type') {
if (isset($item['value']) && $item['value'] !== '其他') {
return true;
}
}
}
return false;
});
// 合并两个条件的结果(或关系),并去重 user_id
$allUserIds = $courseSigns1->pluck('user_id')
->merge($courseSigns2->pluck('user_id'))
->unique()
->filter();
if ($retList) {
return User::whereIn('id', $courseSigns->pluck('user_id'))->get();
return User::whereIn('id', $allUserIds)->get();
} else {
return User::whereIn('id', $courseSigns->pluck('user_id'))->count();
return $allUserIds->count();
}
}
/**
* 重点上市公司
* 上市公司(统计或列表)
* @param string|null $start_date 开始日期
* @param string|null $end_date 结束日期
* @param array|null $course_ids 课程ID数组不传则统计所有课程
* @param bool $retList 是否返回列表false返回数量true返回列表包含学员、课程信息
* @return int|array
*/
public static function shangshi($start_date = null, $end_date = null, $course_ids = null, $retList = false)
{
$courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids);
$list = Company::whereHas('users', function ($query) use ($courseSignsQuery) {
$query->whereIn('id', $courseSignsQuery->get()->pluck('user_id'));
})->where('company_market', 1)->get();
$courseSigns = $courseSignsQuery->with(['user.company', 'course.typeDetail'])->get();
// 获取所有上市公司的ID
$companyIds = $courseSigns->pluck('user.company.id')
->filter()
->unique()
->toArray();
// 获取这些公司中标记为上市的公司
$companies = Company::whereIn('id', $companyIds)
->where('company_market', 1)
->get()
->keyBy('id');
if ($retList) {
return $list;
// 返回详细列表:主表是公司,子数据是学员信息
$result = [];
foreach ($courseSigns as $courseSign) {
if (!$courseSign->user || !$courseSign->user->company) {
continue;
}
$companyId = $courseSign->user->company->id;
// 只处理上市公司的记录
if (!isset($companies[$companyId])) {
continue;
}
$company = $companies[$companyId];
// 如果公司还没有在结果中,初始化
if (!isset($result[$companyId])) {
$result[$companyId] = [
'company' => $company,
'users' => [],
];
}
// 按学员分组,收集每个学员的课程信息
$userId = $courseSign->user->id;
if (!isset($result[$companyId]['users'][$userId])) {
$result[$companyId]['users'][$userId] = [
'user' => $courseSign->user,
'user_name' => $courseSign->user->name ?? '',
'mobile' => $courseSign->user->mobile ?? '',
'courses' => [],
];
}
// 添加该学员的课程信息
$result[$companyId]['users'][$userId]['courses'][] = [
'course_name' => $courseSign->course->name ?? '',
'course_type' => $courseSign->course->typeDetail->name ?? '',
'course_sign' => $courseSign,
];
}
// 将 users 转换为数组(去掉 user_id 作为 key
foreach ($result as $companyId => $item) {
$result[$companyId]['users'] = array_values($item['users']);
}
// 转换为数组并返回
return array_values($result);
} else {
return $list->count();
// 返回统计数据
return $companies->count();
}
}
/**
* 今年上市公司(统计或列表)
* @param string|null $start_date 开始日期
* @param string|null $end_date 结束日期
* @param array|null $course_ids 课程ID数组不传则统计所有课程
* @param bool $retList 是否返回列表false返回数量true返回列表包含学员、课程信息
* @return int|array
*/
public static function companyMarketYear($start_date = null, $end_date = null, $course_ids = null, $retList = false)
{
$courseSignsQuery = self::getStudentList($start_date, $end_date, 1, $course_ids);
$courseSigns = $courseSignsQuery->with(['user.company', 'course.typeDetail'])->get();
// 获取所有上市公司的ID
$companyIds = $courseSigns->pluck('user.company.id')
->filter()
->unique()
->toArray();
$year = date('Y');
// 获取这些公司中标记为上市的公司,且上市日期为今年
$companies = Company::whereIn('id', $companyIds)
->where('company_market', 1)
->whereYear('stock_date', $year)
->get()
->keyBy('id');
if ($retList) {
// 返回详细列表:主表是公司,子数据是学员信息
$result = [];
foreach ($courseSigns as $courseSign) {
if (!$courseSign->user || !$courseSign->user->company) {
continue;
}
$companyId = $courseSign->user->company->id;
// 只处理上市公司的记录
if (!isset($companies[$companyId])) {
continue;
}
$company = $companies[$companyId];
// 如果公司还没有在结果中,初始化
if (!isset($result[$companyId])) {
$result[$companyId] = [
'company' => $company,
'users' => [],
];
}
// 按学员分组,收集每个学员的课程信息
$userId = $courseSign->user->id;
if (!isset($result[$companyId]['users'][$userId])) {
$result[$companyId]['users'][$userId] = [
'user' => $courseSign->user,
'user_name' => $courseSign->user->name ?? '',
'mobile' => $courseSign->user->mobile ?? '',
'courses' => [],
];
}
// 添加该学员的课程信息
$result[$companyId]['users'][$userId]['courses'][] = [
'course_name' => $courseSign->course->name ?? '',
'course_type' => $courseSign->course->typeDetail->name ?? '',
'course_sign' => $courseSign,
];
}
// 将 users 转换为数组(去掉 user_id 作为 key
foreach ($result as $companyId => $item) {
$result[$companyId]['users'] = array_values($item['users']);
}
// 转换为数组并返回
return array_values($result);
} else {
// 返回统计数据
return $companies->count();
}
}
}

Binary file not shown.

@ -1,300 +0,0 @@
# 课程统计系统数据说明文档
## 🎯 一、基础统计数据
### 1. 报名人数course_signs_total
**简单理解**:就像学校统计有多少人报名了课程。
**统计方式**
- 系统会查看在您选择的时间范围内,所有提交了报名申请的人数
- 不管审核是否通过,只要提交了报名就算一个人
- 如果同一个人报名了多门课程会分别计算比如张三报名了3门课就算3个人次
**举个例子**
- 时间范围2024年1月1日 - 2024年12月31日
- 张三报名了"企业管理"课程 → 算1人
- 李四报名了"财务管理"和"市场营销"两门课程 → 算2人
- 总计3人次
---
### 2. 审核通过人数course_signs_pass
**简单理解**:报名后,经过审核被批准参加课程的人数。
**统计方式**
- 只统计审核状态为"审核通过"的报名记录
- 同样,如果一个人通过了多门课程的审核,会分别计算
**与报名人数的区别**
- 报名人数 = 所有提交申请的人(包括待审核、已通过、已拒绝)
- 审核通过人数 = 只有审核通过的人
**举个例子**
- 100人报名其中80人审核通过20人待审核或未通过
- 报名人数 = 100人
- 审核通过人数 = 80人
---
### 3. 审核通过人数去重course_signs_pass_unique
**简单理解**:这是"真实的人数"一个人不管报名了多少门课程只算1个人。
**统计方式**
- 系统会通过手机号来识别是否是同一个人
- 如果同一个手机号报名了多门课程只算1个人
- 这样可以知道真正有多少个不同的学员参加了培训
**举个例子**
- 张三用手机号13800138000报名了3门课程都审核通过了
- 李四用手机号13900139000报名了1门课程审核通过了
- 审核通过人数(不去重)= 4人次3+1
- 审核通过人数(去重)= 2人张三1人 + 李四1人
**为什么需要去重?**
- 不去重:可以知道课程的总参与人次,了解课程的受欢迎程度
- 去重:可以知道实际培养了多少个不同的学员,这是更准确的培养人数
---
### 4. 开课场次course_total
**简单理解**:在指定时间范围内,实际开了多少次课。
**统计方式**
- 系统会查看课程日历表,统计在您选择的时间范围内,有多少次课程安排
- 每次课程安排算1场次
- 比如一门课程在1月、2月、3月各开一次就算3场次
**举个例子**
- 时间范围2024年第一季度
- "企业管理"课程在1月15日、2月15日、3月15日各开一次 → 3场次
- "财务管理"课程在1月20日、2月20日各开一次 → 2场次
- 总计5场次
---
### 5. 开课天数course_day_total
**简单理解**:所有课程加起来,总共上了多少天课。
**统计方式**
- 系统会统计每场课程持续的天数
- 把所有场次的天数加起来
- 比如一门课程持续3天另一门持续2天总计就是5天
**与开课场次的区别**
- 开课场次 = 开了多少次课(不管每次上几天)
- 开课天数 = 总共上了多少天课
**举个例子**
- "企业管理"课程开了3次每次持续2天 → 6天
- "财务管理"课程开了2次每次持续1天 → 2天
- 总计8天
---
## 🏢 二、企业相关统计数据
### 6. 被投企业数course_signs_invested
**简单理解**:参加培训的学员中,有多少人所在的企业是被我们投资的企业。
**统计方式**
- 系统会查看每个学员所在的企业信息
- 如果企业的"是否被投"标记为"是"就算1家企业
- 如果多个学员来自同一家被投企业只算1家企业去重
**举个例子**
- 张三、李四、王五都来自"元禾控股"这家被投企业
- 虽然3个人都参加了培训但只算1家被投企业
- 如果还有赵六来自另一家被投企业"元禾原点"那就是2家被投企业
---
### 7. 上市公司数company_market_total
**简单理解**:参加培训的学员中,有多少人所在的企业是上市公司。
**统计方式**
- 系统会查看每个学员所在的企业信息
- 如果企业的"是否上市公司"标记为"是"就算1家上市公司
- 如果多个学员来自同一家上市公司只算1家企业去重
**举个例子**
- 张三、李四都来自"苏州某上市公司"
- 虽然2个人都参加了培训但只算1家上市公司
---
### 8. 今年上市公司数量company_market_year_total
**简单理解**:在参加培训的学员所在企业中,有多少家是在今年(当前年份)上市的。
**统计方式**
- 系统会查看每个学员所在的企业信息
- 如果企业是上市公司且上市日期stock_date在今年就算1家
- 如果多个学员来自同一家今年上市的公司只算1家企业去重
**举个例子**
- 时间范围2024年1月1日 - 2024年12月31日
- 张三来自"A公司"A公司在2024年3月上市 → 算1家
- 李四来自"B公司"B公司在2023年上市 → 不算(不是今年上市的)
- 总计1家今年上市公司
---
### 9. 入学后上市公司数量company_market_after_enrollment_total
**简单理解**:学员报名参加培训后,他所在的企业才上市的公司数量。
**统计方式**
- 系统会比较学员的报名时间和企业上市时间
- 如果企业上市时间 ≥ 学员报名时间,说明是"入学后上市"
- 如果多个学员来自同一家这样的公司只算1家企业去重
**举个例子**
- 张三在2024年1月报名参加培训
- 张三所在的企业在2024年6月上市
- 因为上市时间6月晚于报名时间1月所以算1家"入学后上市公司"
- 这体现了培训对企业发展的促进作用
---
### 10. 元和员工参与企业company_join_total
**简单理解**:参加培训的学员中,有多少人所在的企业名称中包含"元禾"相关关键词。
**统计方式**
- 系统会检查企业名称如果包含以下关键词之一就算1家企业
- 元禾控股、元禾原点、元禾厚望、元禾重元、元禾璞华、元禾谷风、元禾绿柳、元禾辰坤、元禾沙湖
- 禾裕集团、苏州科服、信诚管理咨询
- 集成电路公司、常州团队、国企元禾
- 如果多个学员来自同一家这样的企业只算1家企业去重
**举个例子**
- 张三来自"元禾控股有限公司"
- 李四来自"元禾原点投资公司"
- 虽然企业名称不同,但都包含"元禾"所以算2家企业
---
### 11. 全市干部参与企业company_ganbu_total
**简单理解**:参加培训的学员中,有多少人的来源标记为"跟班学员"(通常是干部)。
**统计方式**
- 系统会查看每个学员的"来源"字段
- 如果来源是"跟班学员"就算1个人
- 如果同一个人报名了多门课程只算1个人去重
**举个例子**
- 张三的来源是"跟班学员"报名了2门课程 → 算1人
- 李四的来源是"跟班学员"报名了1门课程 → 算1人
- 总计2人
---
### 12. 苏州头部企业cover_head_total
**简单理解**:参加培训的学员中,有多少人所在的企业是苏州的头部企业(通常是高新技术企业)。
**统计方式**
- 系统会查看企业信息中的"企业资质"字段
- 如果企业资质中包含"高新技术企业"就算1家企业
- 如果多个学员来自同一家这样的企业只算1家企业去重
**举个例子**
- 张三、李四都来自"苏州某高新技术企业"
- 虽然2个人都参加了培训但只算1家头部企业
---
### 13. 高层次人才cover_rencai_total
**简单理解**:参加培训的学员中,有多少人报名的是"人才培训"类型的课程。
**统计方式**
- 系统会查看学员报名的课程类型
- 如果课程类型是"人才培训"就算1个人
- 如果同一个人报名了多门"人才培训"课程只算1个人去重
**举个例子**
- 张三报名了"人才培训"类型的课程 → 算1人
- 李四报名了"企业管理"类型的课程 → 不算
- 总计1人
---
### 14. 重点上市公司cover_stock_total
**简单理解**:参加培训的学员中,有多少人所在的企业是重点上市公司。
**统计方式**
- 系统会查看企业信息中的"是否上市公司"字段
- 如果标记为"是"就算1家企业
- 如果多个学员来自同一家上市公司只算1家企业去重
**与"上市公司数"的区别**
- 这个统计可能有额外的筛选条件(具体看业务需求)
- 通常"重点上市公司"是"上市公司"的一个子集
---
## 📊 三、明细统计数据
### 15. 课程分类明细统计courseTypesSum
**简单理解**:按照不同的课程类型,分别统计每个类型和每门课程的培养人数。
**统计方式**
- 系统会按照课程类型分组统计
- 对于每个课程类型,会统计:
- 该类型所有课程的培养人数总和
- 该类型所有课程的培养人数(去重)
- 对于每门具体课程,会统计该课程的培养人数
**举个例子**
- 课程类型:"企业管理"
- 包含课程:"企业管理基础"、"企业管理进阶"
- 该类型培养人数100人两门课程加起来
- 该类型培养人数去重80人去除重复报名的人
- "企业管理基础"课程培养人数60人
- "企业管理进阶"课程培养人数40人
---
### 16. 区域明细统计areas
**简单理解**:按照不同的区域,统计每个区域有多少学员参加了培训。
**统计方式**
- 系统会按照学员所在企业的区域进行分组统计
- 对于苏州市内的企业,会按照具体的区域(比如"工业园区"、"高新区"等)统计
- 对于苏州市外的企业,统一归为"苏州市外"
- 每个区域会统计:
- 该区域的报名人数(不去重)
- 该区域的报名人数(去重,按手机号)
**举个例子**
- 工业园区50人报名去重后40人
- 高新区30人报名去重后25人
- 苏州市外20人报名去重后18人
---
## 🔍 四、统计的时间范围
所有统计数据都基于您选择的时间范围:
- **开始日期**:统计从这个日期开始的报名或开课
- **结束日期**:统计到这个日期为止的报名或开课
**重要说明**
- 对于报名人数:看的是学员的报名时间是否在这个范围内
- 对于开课场次:看的是课程的实际开课日期是否在这个范围内
- 对于企业统计:看的是学员的报名时间是否在这个范围内
Loading…
Cancel
Save