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

master
lion 6 months ago
commit e8750a145c

@ -0,0 +1,411 @@
<?php
namespace App\Console\Commands;
use App\Models\CourseForm;
use App\Models\CourseSign;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
class UpdateUserFromCourseSign extends Command
{
/**
* 限定的手机号列表
*
* @var array
*/
protected $allowedMobiles = [
'13858193624',
'18168183607',
'13771868287',
'18549832553',
'18817298535',
'15273825050',
'18501595925',
'15962590786',
'15320620860',
'13914062017',
'18845143850',
'13917783425',
'13003277587',
'13361107842',
'15241804640',
'13372167314',
'18911127892',
'13997379909',
'15962509586',
'13476809761',
'18906228428',
'13962193806',
'13401443377',
'15962258750',
'17356073468',
'15810534434',
'18662580218',
'13914082740',
'15850525270',
'18739970513',
'15951188321',
'13774360353',
'13913655117',
'13626235977',
'18913283047',
'13013780812',
'18706135861',
'18896939233',
'13598863511',
'15061626527',
'13671824049',
'18762554317',
'15295604750',
'13901541065',
'15995554646',
'13607695075',
'18120148214',
'18626276559',
'13390883999',
'15144140738',
'18906223828',
'18012609856',
'18521596109',
'13009135328',
'13914075750',
'13675755980',
'15651822712',
'18967310128',
'18626295150',
'17712684658',
'18362590815',
'15021008622',
'17303651730',
'17706139033',
'15851476110',
'18601100026',
'13310030818',
'18017665072',
'18912617316',
'13509081568',
'18153524752',
'15995415268',
'17558865852',
'13080603559',
'18964136910',
'13572101550',
'19517891657',
'17805246873',
'13018069212',
'18810901685',
'18616829901',
'13516009851',
'13621553499',
'18986133721',
'13402687760',
'13616211556',
'18505126656',
'13914067620',
'13817301718',
'17710782443',
'13914070504',
'13301575752',
'18994390903',
'18118152163',
'18913553211',
'18550011669',
'15895987328',
'13521086590',
'16601137982',
'18101546975',
'15150558910',
'15962175908',
'18913516806',
'13306136908',
'13720114794',
'13915590667',
'18818589103',
'15850298560',
'13621738712',
'15502129786',
'13862044718',
'13699289293',
'13776041671',
'13811803477',
'18606274785',
'13962124936',
'13504329035',
'18115687371',
'18662158968',
'18662338056',
'13913682588',
'18294402490',
'13270460314',
'18118133321',
'18616795057',
'18912640962',
'18014012006',
'15162647653',
'13466327309',
'15995818235',
'15026822942',
'15652776292',
'15995845671',
'15711294528',
'13656245273',
'13732612069',
'13912729192',
'13771714603',
'13818243299',
'13488771282',
'13584853248',
'15506142175',
'13205193071',
'13962331061',
'15501521761',
'13731218215',
'13812787096',
'15527157619',
'15506218920',
'18858085416',
'18915500725',
'13162792917',
'18911085890',
'15250177879',
'13962113299',
'13681023055',
'17621680840',
'18126448678',
'13776090472',
'18550233721',
'15862493869',
'13298612196',
'13771914071',
'13501238055',
'18913226262',
'18051731616',
'13552627464',
'13669830249',
'19951220702',
'13511594468',
'13942027696',
'15952970972',
'18606270513',
'18627127978',
'13614175299',
'17751459927',
'18994467326',
'18012603353',
'18626178698',
'18811760936',
'13776243855',
'15862467695',
'13913584479',
'15021956508',
'18362120000',
'13076748281',
'18962233636',
'13913101360',
'13812685231',
'13862064335',
'15506266777',
'13812869876',
'13771855571',
'13906132266',
'13701570032',
'15298877317',
'15150106699',
'13506139373',
'13812770216',
'13862019986',
'18662118000',
'18626261221',
'13806216733',
'15306209021',
'13656225381',
'15250974754',
'13451736589',
'13901544538',
'13776091313',
'13812605725',
'17746389584',
'13813662822',
];
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'update_user_from_course_sign';
/**
* The console command description.
*
* @var string
*/
protected $description = '从报名表获取用户填写的信息填充到user数据表按手机号匹配';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
// 根据限定手机号列表查找所有用户
$users = User::whereIn('mobile', $this->allowedMobiles)->get();
if ($users->isEmpty()) {
return $this->error('没有找到符合条件的用户');
}
$this->info("找到 {$users->count()} 个用户需要处理");
$successCount = 0;
$failCount = 0;
foreach ($users as $user) {
$this->newLine();
$this->info("========== 处理用户:{$user->name} (手机号: {$user->mobile}, ID: {$user->id}) ==========");
try {
$this->processUser($user);
$successCount++;
} catch (\Exception $e) {
$this->error("处理用户 {$user->name} 时出错:" . $e->getMessage());
$failCount++;
}
}
$this->newLine();
return $this->info("全部处理完成!成功:{$successCount},失败:{$failCount}");
}
/**
* 处理单个用户
*/
private function processUser($user)
{
$user_id = $user->id;
// 获取该用户的所有报名记录
$courseSigns = CourseSign::where('user_id', $user_id)
->whereNotNull('data')
->get();
if ($courseSigns->isEmpty()) {
$this->info('该用户没有报名记录或报名记录中没有数据');
return;
}
$this->info("找到 {$courseSigns->count()} 条报名记录");
// 收集所有需要更新的用户字段
$userData = [];
$hasCompanyName = false;
foreach ($courseSigns as $courseSign) {
if (empty($courseSign->data) || !is_array($courseSign->data)) {
continue;
}
// 获取该课程的表单字段配置,建立 field -> belong_user_table 的映射关系
$courseForms = CourseForm::where('course_id', $courseSign->course_id)
->where('belong_user', 1) // 只获取属于用户信息的字段
->whereNotNull('belong_user_table') // 必须有对应的用户表字段
->where('belong_user_table', '!=', '') // 用户表字段不能为空
->get(['field', 'belong_user_table']);
if ($courseForms->isEmpty()) {
continue;
}
// 建立 field -> belong_user_table 的映射关系
$fieldMapping = [];
foreach ($courseForms as $form) {
$fieldMapping[$form->field] = $form->belong_user_table;
}
// 将 data 数组转换为以 field 为 key 的关联数组
$dataArray = [];
foreach ($courseSign->data as $item) {
if (isset($item['field']) && isset($item['value'])) {
$dataArray[$item['field']] = $item['value'];
}
}
// 提取属于用户信息的字段,使用 belong_user_table 作为用户表的字段名
foreach ($fieldMapping as $field => $userTableField) {
if (isset($dataArray[$field]) && $dataArray[$field] !== null && $dataArray[$field] !== '') {
// 如果字段已经在 $userData 中,且新值不为空,则更新(优先使用非空值)
if (!isset($userData[$userTableField]) || empty($userData[$userTableField])) {
$userData[$userTableField] = $dataArray[$field];
}
// 检查是否是公司名字
if ($userTableField === 'company_name') {
$hasCompanyName = true;
}
}
}
}
if (empty($userData)) {
$this->info('没有找到需要更新的用户信息');
return;
}
$this->info('准备更新以下字段:' . implode(', ', array_keys($userData)));
// 更新用户信息
// 根据 User::$coverFields 判断是否需要覆盖更新
foreach ($userData as $key => $value) {
if (!in_array($key, User::$coverFields)) {
// 追加更新(对于非覆盖字段)
$currentValue = $user->$key ?? '';
if (!empty($currentValue)) {
$tempArray = explode(',', $currentValue . ',' . $value);
$tempArray = array_unique(array_filter($tempArray));
$userData[$key] = implode(',', $tempArray);
}
}
}
// 检查公司名字是否发生变化
$oldCompanyName = $user->company_name;
$newCompanyName = $userData['company_name'] ?? null;
// 如果公司名字从无到有,或者发生变化,都需要更新
$companyNameChanged = $hasCompanyName && isset($newCompanyName) &&
(empty($oldCompanyName) || $oldCompanyName != $newCompanyName);
$user->fill($userData);
$user->save();
$this->info('用户信息更新成功');
// 如果公司名字发生变化或新增,调用 UpdateCompany 脚本
if ($companyNameChanged) {
if (empty($oldCompanyName)) {
$this->info("检测到新增公司名字({$newCompanyName}),开始调用 UpdateCompany 脚本更新公司信息...");
} else {
$this->info("检测到公司名字发生变化({$oldCompanyName} -> {$newCompanyName}),开始调用 UpdateCompany 脚本更新公司信息...");
}
Artisan::call("update_company --user_id={$user_id}");
$this->info('公司信息更新完成');
} elseif ($hasCompanyName && isset($newCompanyName)) {
$this->info("公司名字未发生变化({$newCompanyName}),跳过公司信息更新");
}
$this->info('用户更新完成');
}
}

@ -104,7 +104,7 @@ class UpdateUserNo extends Command
$tag = '元禾同事';
// 获取元和员工用户列表
$users = CourseSign::companyJoin(null, null, null, true);
$users = CourseSign::companyJoin(null, null, null, true, false);
$count = 0;
foreach ($users as $user) {

@ -396,10 +396,18 @@ class CommonExport implements FromCollection, WithStyles, WithColumnWidths, With
$header = array_values($this->fields);
$moreFileds = [];
if (empty($clear)) {
if (isset($this->data[0]['data']) && is_array($this->data[0]['data'])) {
$moreHeader = array_column($this->data[0]['data'], 'name');
// 容错,取数据不是空的数组
foreach ($this->data as $value) {
if (!empty($value['data'])) {
$otherData = $value['data'];
break;
}
}
if (isset($otherData) && is_array($otherData)) {
$moreHeader = array_column($otherData, 'name');
$header = array_merge($header, $moreHeader);
$moreFileds = array_column($this->data[0]['data'], 'field');
$moreFileds = array_column($otherData, 'field');
}
}
$newList[] = $header;

@ -122,6 +122,11 @@ class OtherController extends CommonController
*/
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();
// 今年新增校友数
@ -140,12 +145,16 @@ class OtherController extends CommonController
$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(null, null, 1);
$list['course_signs_pass'] = CourseSign::courseSignsTotal($start_date, $end_date, 1);
// 培养人数
$list['course_signs_pass_unique'] = CourseSign::courseSignsTotalByUnique(null, null, 1, null, null);
$list['course_signs_pass_unique'] = CourseSign::courseSignsTotalByUnique($start_date, $end_date, 1, null, null);
// 跟班学员数
$list['genban_total'] = CourseSign::genban();
$list['genban_total'] = CourseSign::genban($start_date, $end_date);
// 本月课程
$monthCourses = Calendar::with('course.teacher')
->where('start_time', 'like', '%' . date('Y-m') . '%')
@ -154,10 +163,7 @@ class OtherController extends CommonController
$courseTypes = CourseType::where('is_chart', 1)
->orderBy('sort', 'asc')
->where('is_history', 0)->get();
// 默认开始时间
$start_date = CourseType::START_DATE;
// 默认结束日期一年以后
$end_date = date('Y-m-d', strtotime('+10 year'));
foreach ($courseTypes as $courseType) {
// 历史已开设期数
@ -284,7 +290,7 @@ class OtherController extends CommonController
$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);
$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);
// 苏州头部企业
@ -322,7 +328,7 @@ class OtherController extends CommonController
// 被投企业数
'yh_invested_total' => CourseSign::yhInvested($start_date, $end_date, [$course->id]),
// 元禾同事数
'company_join_total' => CourseSign::companyJoin($start_date, $end_date, [$course->id]),
'company_join_total' => CourseSign::companyJoin($start_date, $end_date, [$course->id], false, false, false),
];
}
}
@ -551,7 +557,7 @@ class OtherController extends CommonController
'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]),
'company_join_total' => CourseSign::companyJoin($start_date, $end_date, [$course->id], false, false),
];
}
}
@ -1039,7 +1045,7 @@ class OtherController extends CommonController
case 'company_join_total':
// 元和员工参与人员明细 - 使用模型方法(现在返回的是用户列表)
$users = CourseSign::companyJoin($start_date, $end_date, $course_ids, true);
$users = CourseSign::companyJoin($start_date, $end_date, $course_ids, true, false);
// 加载关联关系
$users->load('company');
foreach ($users as $user) {

@ -16,6 +16,7 @@ use App\Models\CourseContent;
use App\Models\CourseContentCheck;
use App\Models\CourseContentEvaluation;
use App\Models\CourseContentEvaluationForm;
use App\Models\CourseForm;
use App\Models\CourseSign;
use App\Models\CourseType;
use App\Models\Notice;
@ -110,13 +111,23 @@ class CourseController extends CommonController
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$detail = Course::with(['qunImage', 'typeDetail', 'courseForms', 'teacher', 'courseContentEvaluation' => function ($query) {
$query->with(['courseContentEvaluationAsks' => function ($q) {
$q->orderBy('sort', 'asc');
}]);
}])->withCount(['courseSigns as my_user' => function ($query) {
$query->where('user_id', $this->getUserId());
}])->find($all['course_id']);
$detail = Course::with([
'qunImage',
'typeDetail',
'courseForms',
'teacher',
'courseContentEvaluation' => function ($query) {
$query->with([
'courseContentEvaluationAsks' => function ($q) {
$q->orderBy('sort', 'asc');
}
]);
}
])->withCount([
'courseSigns as my_user' => function ($query) {
$query->where('user_id', $this->getUserId());
}
])->find($all['course_id']);
return $this->success($detail);
}
@ -144,9 +155,11 @@ class CourseController extends CommonController
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$detail = CourseContentEvaluation::with(['courseContentEvaluationAsks' => function ($q) {
$q->with('courseContent.teacher')->orderBy('sort', 'asc');
}])->find($all['course_content_evaluation_id']);
$detail = CourseContentEvaluation::with([
'courseContentEvaluationAsks' => function ($q) {
$q->with('courseContent.teacher')->orderBy('sort', 'asc');
}
])->find($all['course_content_evaluation_id']);
return $this->success($detail);
}
@ -224,6 +237,33 @@ class CourseController extends CommonController
return $this->fail([ResponseCode::ERROR_BUSINESS, '报名已结束']);
}
}
// 检测必填字段
$requiredFields = CourseForm::where('course_id', $all['course_id'])
->where('rule', 'like', '%required%')
->get(['field', 'name']);
if ($requiredFields->count() > 0) {
// 将 data 数组转换为以 field 为 key 的关联数组
$dataArray = [];
if (isset($all['data']) && is_array($all['data'])) {
foreach ($all['data'] as $item) {
if (isset($item['field'])) {
$dataArray[$item['field']] = $item['value'] ?? null;
}
}
}
// 检查必填字段
$missingFields = [];
foreach ($requiredFields as $field) {
$fieldValue = $dataArray[$field->field] ?? null;
// 检查字段是否存在且值不为空null、空字符串视为空0是有效值
if ($fieldValue === null || $fieldValue === '') {
$missingFields[] = $field->name;
}
}
if (!empty($missingFields)) {
return $this->fail([ResponseCode::ERROR_PARAMETER, '以下字段为必填项:' . implode('、', $missingFields)]);
}
}
$result = CourseSign::create([
'is_change' => $all['is_change'] ?? 0,
'course_id' => $all['course_id'],
@ -258,9 +298,11 @@ class CourseController extends CommonController
*/
public function myCourse()
{
$list = Course::with('typeDetail', 'courseContentEvaluation')->with(['courseSigns' => function ($query) {
$query->where('user_id', $this->getUserId());
}])->whereHas('courseSigns', function ($query) {
$list = Course::with('typeDetail', 'courseContentEvaluation')->with([
'courseSigns' => function ($query) {
$query->where('user_id', $this->getUserId());
}
])->whereHas('courseSigns', function ($query) {
$query->where('user_id', $this->getUserId());
})->where('is_virtual', 0)->orderBy('id', 'desc')->paginate($all['page_size'] ?? 20);
return $this->success(compact('list'));
@ -325,11 +367,18 @@ class CourseController extends CommonController
if ($validator->fails()) {
return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]);
}
$detail = CourseContent::with(['course', 'teacher', 'courseKeeps', 'courseContentEvaluation' => function ($query) {
$query->with(['courseContentEvaluationAsks' => function ($q) {
$q->orderBy('sort');
}]);
}])->find($all['course_content_id']);
$detail = CourseContent::with([
'course',
'teacher',
'courseKeeps',
'courseContentEvaluation' => function ($query) {
$query->with([
'courseContentEvaluationAsks' => function ($q) {
$q->orderBy('sort');
}
]);
}
])->find($all['course_content_id']);
return $this->success($detail);
}
@ -569,7 +618,7 @@ class CourseController extends CommonController
// 获取打卡范围,千米
// $content_check_range = Config::getValueByKey('content_check_range');
$courseContent = CourseContent::find($all['course_content_id']);
// $distance = getDistance($courseContent->longitude, $courseContent->latitude, $all['longitude'], $all['latitude']);
// $distance = getDistance($courseContent->longitude, $courseContent->latitude, $all['longitude'], $all['latitude']);
// if ($distance > $content_check_range) {
// return $this->fail([ResponseCode::ERROR_BUSINESS, '超出打卡范围']);
// }
@ -654,7 +703,7 @@ class CourseController extends CommonController
// 获取打卡范围,千米
$content_check_range = Config::getValueByKey('content_check_range');
$course = Course::find($all['course_id']);
// if (empty($course->longitude) || empty($course->latitude)) {
// if (empty($course->longitude) || empty($course->latitude)) {
// return $this->fail([ResponseCode::ERROR_BUSINESS, '请先设置课程经纬度']);
// }
// $distance = getDistance($course->longitude, $course->latitude, $all['longitude'], $all['latitude']);
@ -751,53 +800,55 @@ class CourseController extends CommonController
if ($all['type'] == 2) {
$query->where('status', 1);
}
})->with(['courseSigns' => function ($query) use ($all) {
$query->where('status', 1)->whereHas('course', function ($q) {
$q->where('is_fee', 1);
})->with('course.teacher', 'course.typeDetail')
->orderByRaw("FIELD(fee_status, 1, 0, 2,3)");
if (isset($all['course_id'])) {
$query->where('course_id', $all['course_id']);
}
}])->where(function ($query) use ($all) {
if ($all['type'] == 1) {
$query->where('is_schoolmate', 1);
}
if (isset($all['name'])) {
$query->where('name', 'like', '%' . $all['name'] . '%');
}
if (isset($all['company_business'])) {
$query->where('company_business', 'like', '%' . $all['company_business'] . '%');
}
if (isset($all['company_name'])) {
$query->where('company_name', 'like', '%' . $all['company_name'] . '%');
}
if (isset($all['company_position'])) {
$query->where('company_position', $all['company_position']);
}
if (isset($all['company_area'])) {
$query->where('company_area', 'like', '%' . $all['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]);
})->with([
'courseSigns' => function ($query) use ($all) {
$query->where('status', 1)->whereHas('course', function ($q) {
$q->where('is_fee', 1);
})->with('course.teacher', 'course.typeDetail')
->orderByRaw("FIELD(fee_status, 1, 0, 2,3)");
if (isset($all['course_id'])) {
$query->where('course_id', $all['course_id']);
}
}
});
}
if (isset($all['company_industry'])) {
$company_industry = explode(',', $all['company_industry']);
$query->where(function ($q) use ($company_industry) {
foreach ($company_industry as $v) {
$q->orWhereRaw('FIND_IN_SET(?, company_industry)', [$v]);
])->where(function ($query) use ($all) {
if ($all['type'] == 1) {
$query->where('is_schoolmate', 1);
}
if (isset($all['name'])) {
$query->where('name', 'like', '%' . $all['name'] . '%');
}
if (isset($all['company_business'])) {
$query->where('company_business', 'like', '%' . $all['company_business'] . '%');
}
if (isset($all['company_name'])) {
$query->where('company_name', 'like', '%' . $all['company_name'] . '%');
}
if (isset($all['company_position'])) {
$query->where('company_position', $all['company_position']);
}
if (isset($all['company_area'])) {
$query->where('company_area', 'like', '%' . $all['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) {
foreach ($company_industry as $v) {
$q->orWhereRaw('FIND_IN_SET(?, company_industry)', [$v]);
}
});
}
if (isset($all['letter'])) {
$query->where('letter', $all['letter']);
}
});
}
if (isset($all['letter'])) {
$query->where('letter', $all['letter']);
}
});
if (isset($all['type']) && $all['type'] == 2) {
$list = $list->orderBy('letter')->paginate(10);
} else {

@ -584,7 +584,7 @@ class CourseSign extends SoftDeletesModel
/**
* 元和员工参人员
*/
public static function companyJoin($start_date = null, $end_date = null, $course_ids = null, $retList = false)
public static function companyJoin($start_date = null, $end_date = null, $course_ids = null, $retList = false, $needHistory = true)
{
$courseSignsQuery = self::getStudentList($start_date, $end_date, null, $course_ids);
$courseSignByType = $courseSignsQuery->get();
@ -620,14 +620,17 @@ class CourseSign extends SoftDeletesModel
} else {
// 基础数据
$baseCount = $list->count();
// 额外数据
$employeeParticipations = EmployeeParticipation::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('type', 1)->sum('total');
$employeeParticipations = 0;
if ($needHistory) {
// 额外数据
$employeeParticipations = EmployeeParticipation::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('type', 1)->sum('total');
}
// 返回统计数据
return $baseCount + $employeeParticipations;
}

Loading…
Cancel
Save