updateUserNo(); // 2. 给元和同事打标签 $this->tagYuanheColleague(); return $this->info('更新完成'); } /** * 批量更新学号 */ protected function updateUserNo() { $this->info('开始更新学号...'); $today = date('Y-m-d'); // 获取所有已开始且有学号前缀的课程 $courses = Course::with([ 'courseSigns' => function ($query) { $query->where('status', 1); } ])->whereNotNull('start_date') ->where('start_date', '<=', $today) ->whereNotNull('student_prefix') ->orderBy('start_date') ->get(); $totalUpdated = 0; foreach ($courses as $course) { $i = 1; // 编号前缀 foreach ($course->courseSigns as $sign) { $user = User::find($sign->user_id); // 只要用户没有学号(包括 null 和空字符串),都需要更新 if ($user->no) { continue; } // 生成学号,如果已存在则顺位+1继续尝试 $baseNo = $course->student_prefix . str_pad($i, 3, '0', STR_PAD_LEFT); $no = $baseNo; $attempt = 0; $maxAttempts = 1000; // 防止无限循环 $saved = false; // 尝试保存学号,如果遇到唯一性冲突则重新生成 while (!$saved && $attempt < $maxAttempts) { // 检查学号是否已存在,如果存在则顺位+1继续尝试 if (User::where('no', $no)->where('id', '!=', $user->id)->exists()) { $i++; $no = $course->student_prefix . str_pad($i, 3, '0', STR_PAD_LEFT); $attempt++; continue; } // 尝试更新用户编号 try { $user->no = $no; $user->save(); $saved = true; } catch (\Illuminate\Database\QueryException $e) { // 捕获唯一性约束冲突异常 if ($e->getCode() == 23000 && strpos($e->getMessage(), 'Duplicate entry') !== false) { // 学号已被其他用户占用,重新生成 $i++; $no = $course->student_prefix . str_pad($i, 3, '0', STR_PAD_LEFT); $attempt++; continue; } // 其他异常直接抛出 throw $e; } } if (!$saved) { $this->warn('课程: ' . ($course->name ?? $course->id) . ', 用户: ' . ($user->name ?? $user->id) . ' 无法生成唯一学号,跳过'); continue; } if ($no != $baseNo) { $this->info('课程: ' . ($course->name ?? $course->id) . ', 原学号: ' . $baseNo . ' 已存在,使用: ' . $no . ', 用户: ' . ($user->name ?? $user->id)); } else { $this->info('课程: ' . ($course->name ?? $course->id) . ', 学号: ' . $no . ', 用户: ' . ($user->name ?? $user->id)); } $i++; $totalUpdated++; } } $this->info('学号更新完成,共更新 ' . $totalUpdated . ' 个学号'); } /** * 给元和同事打标签:检查所有有公司名称的用户,若公司名匹配元和员工则追加 from 标签 */ protected function tagYuanheColleague() { $this->info('开始给元和同事打标签...'); $tag = User::FROM_TAG_YUANHE_COLLEAGUE; // 从 config 获取元和公司名称关键词(用于判断是否元和员工) $companyNameKeyword = []; $configValue = Config::getValueByKey('yuanhe_company'); if ($configValue) { $configData = json_decode($configValue, true); if (is_array($configData)) { foreach ($configData as $item) { if (!empty($item['company_name'])) { $companyNameKeyword[] = $item['company_name']; } if (!empty($item['short_company_name'])) { $companyNameKeyword[] = $item['short_company_name']; } } $companyNameKeyword = array_values(array_unique($companyNameKeyword)); } } if (empty($companyNameKeyword)) { $this->warn('config(yuanhe_company) 无数据,跳过元和同事打标签'); return; } // 所有有公司名称、且 from 中尚无「元禾同事」的用户(有该标签的不再追加) $users = User::whereNotNull('company_name') ->where('company_name', '!=', '') ->where(function ($q) use ($tag) { $q->whereNull('from') ->orWhere('from', 'not like', '%' . $tag . '%'); }) ->get(); $count = 0; foreach ($users as $user) { $companyName = (string) ($user->company_name ?? ''); // 检查是否元和员工:公司名包含任一关键词 $isYuanhe = false; foreach ($companyNameKeyword as $keyword) { $keyword = (string) $keyword; if ($keyword !== '' && mb_strpos($companyName, $keyword) !== false) { $isYuanhe = true; break; } } if (!$isYuanhe) { continue; } // 再次确认 from 未有该标签,避免重复 $from = $user->from ?? ''; $fromArray = array_filter(array_map('trim', explode(',', $from))); if (in_array($tag, $fromArray)) { continue; } // 追加标签并去重后写回 $fromArray[] = $tag; $fromArray = array_values(array_unique($fromArray)); $user->from = implode(',', $fromArray); $user->save(); $this->info('已为用户 ' . $user->name . '(' . $user->mobile . ') 添加标签: ' . $tag . ',公司: ' . $companyName); $count++; } $this->info('元和同事标签更新完成,共更新 ' . $count . ' 人'); } }