info("开始将课程关联到calendars日历表..."); $this->info("总共需要处理 " . count($this->courseList) . " 个课程"); $linkedCount = 0; $notFoundCourses = []; $alreadyLinkedCourses = []; DB::beginTransaction(); try { foreach ($this->courseList as $courseName) { $this->info("正在处理课程: {$courseName}"); // 查找匹配的课程 $course = $this->findCourse($courseName); if (!$course) { $this->warn("✗ 未找到匹配的课程: {$courseName}"); $notFoundCourses[] = $courseName; continue; } $this->info("✓ 找到匹配课程: {$course->name} (ID: {$course->id})"); // 检查是否已经存在日历记录 $existingCalendar = Calendar::where('course_id', $course->id) ->where('type', 1) // 类型1为课程 ->first(); if ($existingCalendar) { $this->warn("⚠ 课程已存在日历记录: {$course->name}"); $alreadyLinkedCourses[] = $course->name; continue; } // 创建日历记录 $calendarData = $this->createCalendarData($course); $calendar = Calendar::create($calendarData); $this->info("✓ 成功创建日历记录 (ID: {$calendar->id}) 关联课程: {$course->name}"); $linkedCount++; } DB::commit(); $this->info("\n" . str_repeat('=', 60)); $this->info("处理完成!"); $this->info("成功关联课程数量: {$linkedCount}"); $this->info("已存在日历记录: " . count($alreadyLinkedCourses)); $this->info("未找到匹配课程: " . count($notFoundCourses)); // 显示未找到的课程 if (!empty($notFoundCourses)) { $this->warn("\n未找到匹配的课程列表:"); foreach ($notFoundCourses as $course) { $this->warn(" - {$course}"); } } // 显示已存在日历记录的课程 if (!empty($alreadyLinkedCourses)) { $this->warn("\n已存在日历记录的课程列表:"); foreach ($alreadyLinkedCourses as $course) { $this->warn(" - {$course}"); } } } catch (\Exception $e) { DB::rollback(); $this->error("处理过程中发生错误: " . $e->getMessage()); $this->error("已回滚所有更改"); return; } $this->info("\n所有操作已完成!"); } /** * 查找匹配的课程 */ private function findCourse($courseName) { // 1. 精确匹配 $course = Course::where('name', $courseName) ->whereNull('deleted_at') ->first(); if ($course) { return $course; } // 2. 模糊匹配 $course = Course::where('name', 'like', "%{$courseName}%") ->whereNull('deleted_at') ->first(); if ($course) { $this->info("通过模糊匹配找到课程: '{$course->name}'"); return $course; } // 3. 相似度匹配 $courses = Course::whereNull('deleted_at') ->whereNotNull('name') ->where('name', '!=', '') ->get(); $bestMatch = null; $highestSimilarity = 0; foreach ($courses as $course) { $similarity = $this->calculateSimilarity($courseName, $course->name); if ($similarity > $highestSimilarity) { $highestSimilarity = $similarity; $bestMatch = $course; } } if ($bestMatch && $highestSimilarity > 0.3) { // 设置最低相似度阈值 $this->info("通过相似度匹配找到课程 (相似度: " . round($highestSimilarity * 100, 2) . "%): '{$bestMatch->name}'"); return $bestMatch; } return null; } /** * 创建日历数据 */ private function createCalendarData($course) { return [ 'type' => 1, // 类型1为课程 'course_id' => $course->id, 'date' => $course->start_date ?? now()->format('Y-m-d'), 'title' => $course->name, 'content' => $course->content ?? '', 'start_time' => $course->start_date ? $course->start_date . ' 09:00:00' : null, 'end_time' => $course->end_date ? $course->end_date . ' 17:00:00' : null, 'url' => $course->url ?? '', 'created_at' => now(), 'updated_at' => now(), ]; } /** * 计算字符串相似度 */ private function calculateSimilarity($str1, $str2) { // 移除空格并转换为小写 $str1 = strtolower(preg_replace('/\s+/', '', $str1)); $str2 = strtolower(preg_replace('/\s+/', '', $str2)); if ($str1 === $str2) { return 1.0; } if (empty($str1) || empty($str2)) { return 0.0; } // 使用Levenshtein距离计算相似度 $maxLen = max(strlen($str1), strlen($str2)); if ($maxLen == 0) { return 1.0; } $distance = levenshtein($str1, $str2); $similarity = 1 - ($distance / $maxLen); // 如果其中一个字符串包含另一个,提高相似度 if (strpos($str1, $str2) !== false || strpos($str2, $str1) !== false) { $containsSimilarity = min(strlen($str1), strlen($str2)) / $maxLen; $similarity = max($similarity, $containsSimilarity); } return max(0, $similarity); } }