攀峰班 > 初创班) * * @var array */ protected $courseTypePriority = ['高研班', '攀峰班', '初创班']; /** * 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() { // 获取高研班、攀峰班、初创班三个课程体系下的课程 ID $courseTypeIds = CourseType::whereIn('name', $this->courseTypePriority)->pluck('id')->toArray(); if (empty($courseTypeIds)) { return $this->error('未找到高研班/攀峰班/初创班课程类型'); } $courseIds = Course::whereIn('type', $courseTypeIds)->pluck('id')->toArray(); if (empty($courseIds)) { return $this->error('三个课程体系下没有课程'); } // 获取这三个体系下所有有报名数据(data 不为空)的报名记录,再取去重用户 $userIds = CourseSign::whereIn('course_id', $courseIds) ->whereNotNull('user_id') ->whereNotNull('data') ->pluck('user_id') ->unique() ->values() ->toArray(); if (empty($userIds)) { return $this->error('没有找到符合条件的报名用户'); } $users = User::whereIn('id', $userIds)->get(); $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, $courseIds); $successCount++; } catch (\Exception $e) { $this->error("处理用户 {$user->name} 时出错:" . $e->getMessage()); $failCount++; } } $this->newLine(); return $this->info("全部处理完成!成功:{$successCount},失败:{$failCount}"); } /** * 处理单个用户 * 按优先级(高研班 > 攀峰班 > 初创班)选定课程体系,取该体系下最新一条报名数据覆盖用户 * * @param \App\Models\User $user * @param array $courseIds 高研班/攀峰班/初创班下的课程 ID 列表 */ private function processUser($user, array $courseIds) { $user_id = $user->id; // 仅获取该用户在三个体系下的报名记录(携带课程及课程类型),按 created_at 倒序 $courseSigns = CourseSign::with('course.typeDetail') ->where('user_id', $user_id) ->whereIn('course_id', $courseIds) ->whereNotNull('data') ->orderByDesc('created_at') ->get(); if ($courseSigns->isEmpty()) { $this->info('该用户在此三个体系下没有报名记录或报名记录中没有数据'); return; } // 统计用户报名的课程体系 $userCourseTypes = $courseSigns->map(function ($sign) { return $sign->course->typeDetail->name ?? ''; })->filter()->unique()->values()->toArray(); $this->info('用户报名的课程体系:' . implode('、', $userCourseTypes)); // 按优先级确定使用的课程体系:有高研班用高研班,否则攀峰班,否则初创班 $selectedTypeName = null; foreach ($this->courseTypePriority as $typeName) { $hasSign = $courseSigns->contains(function ($sign) use ($typeName) { $name = $sign->course->typeDetail->name ?? ''; return $name === $typeName; }); if ($hasSign) { $selectedTypeName = $typeName; $this->info("检测到用户报名了【{$typeName}】,优先使用该体系的数据"); break; } } if ($selectedTypeName === null) { $this->info('未匹配到高研班/攀峰班/初创班课程类型,跳过'); return; } // 只保留该体系下的报名,且已按 created_at 倒序,取最新一条 $targetSigns = $courseSigns->filter(function ($sign) use ($selectedTypeName) { $name = $sign->course->typeDetail->name ?? ''; return $name === $selectedTypeName; }); $latestSign = $targetSigns->first(); $this->info("使用课程体系【{$selectedTypeName}】下最新报名(course_sign_id: {$latestSign->id})覆盖用户数据"); // 从单条最新报名中提取用户字段 $userData = []; $hasCompanyName = false; if (empty($latestSign->data) || !is_array($latestSign->data)) { $this->info('该条报名 data 为空,无法更新用户'); return; } $courseForms = CourseForm::where('course_id', $latestSign->course_id) ->where('belong_user', 1) ->whereNotNull('belong_user_table') ->where('belong_user_table', '!=', '') ->get(['field', 'belong_user_table']); if ($courseForms->isEmpty()) { $this->info('该课程无 belong_user 表单配置,跳过'); return; } $fieldMapping = []; foreach ($courseForms as $form) { $fieldMapping[$form->field] = $form->belong_user_table; } $dataArray = []; foreach ($latestSign->data as $item) { if (isset($item['field'], $item['value'])) { $dataArray[$item['field']] = $item['value']; } } foreach ($fieldMapping as $field => $userTableField) { if (isset($dataArray[$field]) && $dataArray[$field] !== null && $dataArray[$field] !== '') { $userData[$userTableField] = $dataArray[$field]; if ($userTableField === 'company_name') { $hasCompanyName = true; } } } if (empty($userData)) { $this->info('未解析出可更新的用户字段'); return; } // 如果用户已有 company_id 且存在对应的 company 数据,则不更新公司名字 if ($user->company_id) { $hasCompany = Company::where('id', $user->company_id)->exists(); if ($hasCompany) { // 有关联的 company 数据,移除 company_name 字段,不更新 if (isset($userData['company_name'])) { unset($userData['company_name']); $hasCompanyName = false; $this->info('用户已有关联的 company 数据(company_id: ' . $user->company_id . '),跳过公司名字更新'); } } } 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('用户信息更新成功'); 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('用户更新完成'); } }