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.

397 lines
16 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\Models;
use EasyWeChat\Factory;
use Illuminate\Filesystem\Filesystem;
class Course extends SoftDeletesModel
{
protected $appends = [
'date_status',
'publicize',
'sign_date_status',
'qrcode',
'teacher_detail',
'status_text',
'is_fee_text',
'is_arrange_text',
'show_txl_text',
'show_mobile_text',
'auto_schoolmate_text',
'is_virtual_text'
];
protected $casts = ['publicize_ids' => 'json'];
public function getStatusTextAttribute()
{
$array = [0 => '待发布', 1 => '已发布'];
return $array[$this->attributes['status']];
}
public function getIsFeeTextAttribute()
{
$array = [0 => '免费', 1 => '收费'];
return $array[$this->attributes['is_fee']];
}
public function getIsArrangeTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['is_arrange']];
}
public function getShowTxlTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['show_txl']];
}
public function getShowMobileTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['show_mobile']];
}
public function getAutoSchoolmateTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['auto_schoolmate']];
}
public function getIsVirtualTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['is_virtual']];
}
public function getQrcodeAttribute($value)
{
return $this->getCourseQrcode($this->attributes['id']);
}
public function getTeacherDetailAttribute($value)
{
$teacherIds = explode(',', $this->teacher_id);
return Teacher::whereIn('id', $teacherIds)->get();
}
public function getPublicizeAttribute($value)
{
if (empty($this->publicize_ids))
return [];
return Upload::whereIn('id', $this->publicize_ids)->get();
}
public function getDateStatusAttribute()
{
$text = '课程未开始';
if ($this->course_status == 10) {
$text = '课程进行中';
}
if ($this->course_status == 40) {
$text = '课程已结束';
}
return $text;
}
public function getSignDateStatusAttribute()
{
$text = '未开始';
if ($this->sign_status == 10) {
$text = '进行中';
}
if ($this->sign_status == 40) {
$text = '已结束';
}
return $text;
}
public function typeDetail()
{
return $this->hasOne(CourseType::class, 'id', 'type');
}
public function courseForms()
{
return $this->hasMany(CourseForm::class, 'course_id', 'id');
}
public function teacher()
{
return $this->hasOne(Teacher::class, 'id', 'teacher_id');
}
public function courseSettings()
{
return $this->hasMany(CourseSetting::class, 'course_id', 'id');
}
public function coursePeriods()
{
return $this->hasMany(CoursePeriod::class, 'course_id', 'id');
}
public function courseSigns()
{
return $this->hasMany(CourseSign::class, 'course_id', 'id');
}
public function image()
{
return $this->hasOne(Upload::class, 'id', 'image_id');
}
public function qunImage()
{
return $this->hasOne(Upload::class, 'id', 'qun_image_id');
}
public function courseContents()
{
return $this->hasMany(CourseContent::class, 'course_id', 'id');
}
public function courseContentEvaluation()
{
return $this->hasMany(CourseContentEvaluation::class, 'course_id', 'id');
}
/**
* 更新课程报名状态
*/
public static function updateSignStatus($courseId)
{
// 进行中-未开始-已结束
$now = date('Y-m-d');
$course = Course::find($courseId);
// 默认未开始
$sign_status = 30;
if ($course->sign_start_date && $now < $course->sign_start_date) {
// 未开始
$sign_status = 20;
}
if ($course->sign_start_date && $now >= $course->sign_start_date) {
// 进行中
$sign_status = 10;
}
if ($course->sign_end_date && $now > $course->sign_end_date) {
// 已结束
$sign_status = 40;
}
$course->sign_status = $sign_status;
$course->save();
return $course;
}
/**
* 更新课程状态
*/
public static function updateStatus($courseId)
{
// 进行中-未开始-已结束
$now = date('Y-m-d');
$course = Course::find($courseId);
// 默认待定
$course_status = 30;
if ($course->start_date && $now < $course->start_date) {
// 未开始
$course_status = 20;
}
if ($course->start_date && $now >= $course->start_date) {
// 进行中
$course_status = 10;
}
if ($course->end_date && $now > $course->end_date) {
// 已结束
$course_status = 40;
}
$course->course_status = $course_status;
$course->save();
return $course;
}
/**
* 获取课程详情小程序码
*/
public function getCourseQrcode($courseId)
{
$course = Course::find($courseId);
$path = config('filesystems.disks.public.root') . '/course_qrcode/' . $course->id . '.png';
$url = config('filesystems.disks.public.url') . '/course_qrcode/' . $course->id . '.png';
$fileSys = new Filesystem();
if ($fileSys->exists($path)) {
return $url;
}
$config = [
'app_id' => \config('app.applet_appid'),
'secret' => \config('app.applet_secret')
];
$app = Factory::miniProgram($config);
$tmp = $app->app_code->get('packages/course/detail?' . 'id=' . $courseId, [
'env_version' => "release" // 正式版
// 'env_version' => "trial" // 体验版
]);
$dir = dirname($path);
$fileSys->ensureDirectoryExists($dir, 0755, true);
$fileSys->put($path, $tmp);
return $url;
}
/**
* 获取课程报名小程序码
*/
public function getCourseCheckQrcode($courseId)
{
$course = Course::find($courseId);
$path = config('filesystems.disks.public.root') . '/course_check_qrcode/' . $course->id . '.png';
$url = config('filesystems.disks.public.url') . '/course_check_qrcode/' . $course->id . '.png';
$fileSys = new Filesystem();
if ($fileSys->exists($path)) {
return $url;
}
$config = [
'app_id' => \config('app.applet_appid'),
'secret' => \config('app.applet_secret')
];
$app = Factory::miniProgram($config);
$tmp = $app->app_code->get('packages/sign/course?course_id=' . $courseId, [
'env_version' => "release" // 正式版
]);
$dir = dirname($path);
$fileSys->ensureDirectoryExists($dir, 0755, true);
$fileSys->put($path, $tmp);
return $url;
}
/**
* 获取问卷小程序码
*/
public function getEvaluationQrcode($id)
{
$courseContentEvaluation = CourseContentEvaluation::find($id);
$path = config('filesystems.disks.public.root') . '/course_evaluation_qrcode/' . $courseContentEvaluation->id . '.png';
$url = config('filesystems.disks.public.url') . '/course_evaluation_qrcode/' . $courseContentEvaluation->id . '.png';
$fileSys = new Filesystem();
if ($fileSys->exists($path)) {
return $url;
}
$config = [
'app_id' => \config('app.applet_appid'),
'secret' => \config('app.applet_secret')
];
$app = Factory::miniProgram($config);
$tmp = $app->app_code->get('packages/surveyFill/index?id=' . $id, [
// todo:: 版本切换
'env_version' => "release" // 正式版
// 'env_version' => "trial" // 体验版
]);
$dir = dirname($path);
$fileSys->ensureDirectoryExists($dir, 0755, true);
$fileSys->put($path, $tmp);
return $url;
}
/**
* 获取课程统计项元数据
* 返回每个统计项的计算逻辑和验证方法说明
* @return array
*/
public static function getStatisticsMetadata()
{
return [
'course_signs_total' => [
'name' => '报名人数',
'from' => '统计在指定时间范围内、指定课程范围内的所有报名记录数量。包括所有状态的报名(待审核、已通过、已拒绝等),同时会加上历史课程数据中的人数统计。一个学员报名多个课程会计算多次。',
'verify' => ''
],
'course_signs_pass' => [
'name' => '审核通过人数',
'from' => '统计在指定时间范围内、指定课程范围内审核通过的报名记录数量。只统计状态为"已通过"的报名,不包括待审核、已拒绝等其他状态。同时会加上历史课程数据中已通过的人数统计。一个学员报名多个课程会计算多次。',
'verify' => ''
],
'course_signs_pass_unique' => [
'name' => '审核通过人数去重',
'from' => '统计在指定时间范围内、指定课程范围内审核通过的学员人数(按学员去重)。与"审核通过人数"的区别是:如果同一个学员报名了多个课程,这里只计算一次。通过学员的手机号进行去重,确保每个学员只统计一次。同时会加上历史课程数据中去重后的人数统计。',
'verify' => ''
],
'course_total' => [
'name' => '开课场次',
'from' => '统计在指定时间范围内、指定课程体系范围内的开课场次数。一个课程可能有多个场次(比如分多天上课),这里统计的是场次数,不是课程数。只要场次的开始时间或结束时间在指定时间范围内,就会被统计。',
'verify' => ''
],
'course_day_total' => [
'name' => '开课天数',
'from' => '统计在指定时间范围内、指定课程体系范围内的开课天数总和。只统计标记为"需要统计天数"的场次每个场次可能有不同的天数比如3天、5天等将所有场次的天数相加得到总天数。',
'verify' => ''
],
'company_market_total' => [
'name' => '上市公司数',
'from' => '统计在指定时间范围内、指定课程范围内报名的学员中,所在公司为上市公司的公司数量。通过学员关联到其所在公司,筛选出已上市的公司,然后按公司去重统计。如果同一公司有多个学员报名,只计算一次。',
'verify' => ''
],
'ganbu_total' => [
'name' => '跟班学员数',
'from' => '统计在指定时间范围内、指定课程范围内的跟班学员人数。筛选条件1)学员的"来源"字段包含"跟班学员"2)课程类型标记为"需要统计跟班学员"。同时会加上员工参与表中的额外数据。按学员去重,同一学员只计算一次。',
'verify' => ''
],
'company_market_year_total' => [
'name' => '今年上市公司数量',
'from' => '统计所有在今年(当前年份)上市的公司数量。直接从上市公司表中查询,统计上市日期在今年内的公司。这个统计不依赖学员报名记录,统计的是所有在今年上市的公司,不管是否有学员报名。',
'verify' => ''
],
'company_market_after_enrollment_total' => [
'name' => '入学后上市公司数量',
'from' => '统计所有标记为"入学后上市"的公司数量。直接从上市公司表中查询,统计标记为"入学后上市"的公司。这个统计不依赖学员报名记录,统计的是所有在学员入学后才上市的公司。',
'verify' => ''
],
'course_signs_invested' => [
'name' => '累计被投企业数',
'from' => '统计从课程开始日期到结束日期,在指定课程范围内报名的学员中,所在公司为被投企业的公司数量。通过学员关联到其所在公司,筛选出标记为"被投企业"的公司,检查公司的被投时间是否在截止日期之前(或没有记录被投时间),然后按公司去重统计。同一公司多个学员只计算一次。',
'verify' => ''
],
'company_invested_after_enrollment_total' => [
'name' => '入学后被投企业数量',
'from' => '统计在指定时间范围内报名的学员中,所在公司在学员入学后被投的公司数量。以学员报名的课程开课时间作为"入学时间",筛选出公司的被投时间晚于入学时间的公司,然后按公司去重统计。同一公司多个学员只计算一次。',
'verify' => ''
],
'company_invested_year_total' => [
'name' => '今年被投企业数',
'from' => '统计在指定时间范围内报名的学员中,所在公司在指定年份范围内被投的公司数量。从开始日期和结束日期中提取年份范围,筛选出公司的被投时间在指定年份范围内的公司,然后按公司去重统计。同一公司多个学员只计算一次。',
'verify' => ''
],
'company_join_total' => [
'name' => '元和员工参与人数',
'from' => '统计在指定时间范围内、指定课程范围内报名的学员中,所在公司为元和投资公司的学员人数。通过学员关联到其所在公司,筛选出元和投资的公司,然后按学员去重统计。同一学员报名多个课程只计算一次。',
'verify' => ''
],
'company_ganbu_total' => [
'name' => '全市干部参与企业',
'from' => '统计在指定时间范围内、指定课程范围内报名的学员中,来源为"跟班学员"且课程类型标记为"需要统计跟班学员"的学员人数。与"跟班学员数"的统计逻辑相同,同时会加上员工参与表中的额外数据。按学员去重,同一学员只计算一次。',
'verify' => ''
],
'cover_head_total' => [
'name' => '苏州头部企业',
'from' => '统计在指定时间范围内、指定课程范围内报名的学员中,所在公司为苏州头部企业的公司数量。通过学员关联到其所在公司,筛选出标记为"苏州头部企业"的公司,然后按公司去重统计。同一公司多个学员只计算一次。',
'verify' => ''
],
'cover_rencai_total' => [
'name' => '高层次人才',
'from' => '统计在指定时间范围内、指定课程范围内报名的学员中,标记为"高层次人才"的学员人数。通过学员的个人信息(如学历等)判断是否为高层次人才,然后按学员去重统计。同一学员报名多个课程只计算一次。',
'verify' => ''
],
'cover_stock_total' => [
'name' => '重点上市公司',
'from' => '统计在指定时间范围内、指定课程范围内报名的学员中,所在公司为重点上市公司的公司数量。通过学员关联到其所在公司,筛选出重点上市公司,然后按公司去重统计。与"上市公司数"的统计逻辑相同,但筛选的是重点上市公司。同一公司多个学员只计算一次。',
'verify' => ''
],
];
}
}