diff --git a/app/Console/Commands/CheckBirthday.php b/app/Console/Commands/CheckBirthday.php index 26a6839..a87d5c8 100755 --- a/app/Console/Commands/CheckBirthday.php +++ b/app/Console/Commands/CheckBirthday.php @@ -44,7 +44,8 @@ class CheckBirthday extends Command */ public function handle() { - $users = User::where('is_schoolmate', 1)->where('birthday', date('Y-m-d'))->get(); + $day = date('Y-m'); + $users = User::where('is_schoolmate', 1)->where('birthday', 'like', '%' . $day . '%')->get(); foreach ($users as $user) { Notification::send($user, new BirthdayNotify(['user_id' => $user->id])); } diff --git a/app/Console/Commands/LinkCoursesToCalendar.php b/app/Console/Commands/LinkCoursesToCalendar.php deleted file mode 100644 index e661984..0000000 --- a/app/Console/Commands/LinkCoursesToCalendar.php +++ /dev/null @@ -1,302 +0,0 @@ -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); - } -} diff --git a/app/Console/Commands/UpdateCourseUrls.php b/app/Console/Commands/UpdateCourseUrls.php index 1c276a7..80363c8 100644 --- a/app/Console/Commands/UpdateCourseUrls.php +++ b/app/Console/Commands/UpdateCourseUrls.php @@ -2,6 +2,7 @@ namespace App\Console\Commands; +use App\Models\Calendar; use App\Models\Course; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; @@ -22,7 +23,7 @@ class UpdateCourseUrls extends Command * * @var string */ - protected $description = '从Excel文件读取课程信息,匹配phome_ecms_news表的titleurl并更新courses表的url字段'; + protected $description = '从Excel文件读取课程信息,匹配courses表,获取新闻链接,并创建calendar记录'; /** * Create a new command instance. @@ -58,7 +59,9 @@ class UpdateCourseUrls extends Command $this->info("Excel文件包含 {$sheetCount} 个工作表"); - $totalUpdated = 0; + $totalCreated = 0; + $failedCourses = []; + $failedNews = []; // 处理每个工作表 for ($sheetIndex = 0; $sheetIndex < $sheetCount; $sheetIndex++) { @@ -67,11 +70,29 @@ class UpdateCourseUrls extends Command $this->info("正在处理工作表: {$sheetName}"); - $updated = $this->processWorksheet($worksheet, $sheetName); - $totalUpdated += $updated; + list($created, $sheetFailedCourses, $sheetFailedNews) = $this->processWorksheet($worksheet, $sheetName); + $totalCreated += $created; + $failedCourses = array_merge($failedCourses, $sheetFailedCourses); + $failedNews = array_merge($failedNews, $sheetFailedNews); } - $this->info("处理完成,总共更新了 {$totalUpdated} 条记录"); + $this->info("处理完成,总共创建了 {$totalCreated} 条日历记录"); + + // 显示匹配失败的课程 + if (!empty($failedCourses)) { + $this->warn("匹配失败的课程:"); + foreach (array_unique($failedCourses) as $failedCourse) { + $this->warn(" - {$failedCourse}"); + } + } + + // 显示匹配失败的新闻 + if (!empty($failedNews)) { + $this->warn("匹配失败的新闻:"); + foreach (array_unique($failedNews) as $failedNewsItem) { + $this->warn(" - {$failedNewsItem}"); + } + } } catch (\Exception $e) { $this->error("处理Excel文件时发生错误: " . $e->getMessage()); @@ -98,70 +119,150 @@ class UpdateCourseUrls extends Command $headers[$col] = trim($cellValue); } - $this->info("表头: " . implode(', ', $headers)); - - // 找到"课程"和"跳转链接"列的位置 + // 找到"课程"、"开始时间"、"结束时间"、"跳转链接"列的位置 $courseColumn = null; + $startTimeColumn = null; + $endTimeColumn = null; $linkColumn = null; foreach ($headers as $colIndex => $header) { if (strpos($header, '课程') !== false) { $courseColumn = $colIndex; } + if (strpos($header, '开始时间') !== false) { + $startTimeColumn = $colIndex; + } + if (strpos($header, '结束时间') !== false) { + $endTimeColumn = $colIndex; + } if (strpos($header, '跳转链接') !== false) { $linkColumn = $colIndex; } } - if (!$courseColumn || !$linkColumn) { - $this->warn("工作表 {$sheetName} 中未找到'课程'或'跳转链接'列"); - return 0; + if (!$courseColumn || !$startTimeColumn || !$endTimeColumn || !$linkColumn) { + $this->warn("工作表 {$sheetName} 中未找到必要的列(课程、开始时间、结束时间、跳转链接)"); + return [0, [], []]; } - $this->info("找到课程列: {$courseColumn},跳转链接列: {$linkColumn}"); - - $updated = 0; + $this->info("找到课程列: {$courseColumn},开始时间列: {$startTimeColumn},结束时间列: {$endTimeColumn},跳转链接列: {$linkColumn}"); + $created = 0; $failedCourses = []; + $failedNews = []; // 处理数据行 for ($row = 2; $row <= $highestRow; $row++) { $courseName = trim($worksheet->getCellByColumnAndRow($courseColumn, $row)->getCalculatedValue()); + + // 获取开始时间和结束时间的原始值,避免格式化问题 + $startTimeCell = $worksheet->getCellByColumnAndRow($startTimeColumn, $row); + $endTimeCell = $worksheet->getCellByColumnAndRow($endTimeColumn, $row); + + // 优先使用原始值,如果没有则使用计算值 + $startTime = $startTimeCell->getValue(); + if ($startTime === null) { + $startTime = trim($startTimeCell->getCalculatedValue()); + } + + $endTime = $endTimeCell->getValue(); + if ($endTime === null) { + $endTime = trim($endTimeCell->getCalculatedValue()); + } + $jumpLink = trim($worksheet->getCellByColumnAndRow($linkColumn, $row)->getCalculatedValue()); - if (empty($courseName) || empty($jumpLink)) { + if (empty($courseName) || empty($startTime) || empty($endTime)) { continue; } - $this->info("处理行 {$row}: 课程='{$courseName}', 跳转链接='{$jumpLink}'"); - - // 从phome_ecms_news表获取titleurl - list($title, $titleUrl) = $this->getTitleUrlFromNews($jumpLink); + $this->info("处理行 {$row}: 课程='{$courseName}', 开始时间='{$startTime}' (类型: " . gettype($startTime) . "), 结束时间='{$endTime}' (类型: " . gettype($endTime) . "), 跳转链接='{$jumpLink}'"); - if ($titleUrl) { - // 更新courses表 - $updateCount = $this->updateCourseUrl($courseName, $titleUrl, $title); - $updated += $updateCount; + // 1. 匹配courses表 + $courseId = $this->matchCourse($courseName); + if (!$courseId) { + $this->warn("✗ 未找到匹配的课程: '{$courseName}'"); + $failedCourses[] = $courseName; + continue; + } - if ($updateCount > 0) { - $this->info("✓ 成功更新课程 '{$courseName}' 的URL为: {$titleUrl}"); - } else { - $this->warn("✗ 未找到匹配的课程: '{$courseName}'"); - $failedCourses[] = $courseName; + // 2. 匹配phome_ecms_news表获取url和title + $url = null; + $title = null; + if (!empty($jumpLink)) { + list($title, $url) = $this->getTitleUrlFromNews($jumpLink); + if (!$url) { + $this->warn("✗ 未找到匹配的新闻标题: '{$jumpLink}'"); + $failedNews[] = $jumpLink; } + } + + // 3. 更新courses表的url字段 + if ($url && $title) { + $this->updateCourseUrl($courseId, $url, $title); + } + + // 4. 创建calendar记录 + $calendarCreated = $this->createCalendarRecord($courseId, $courseName, $startTime, $endTime, $url, $title, $courseName); + if ($calendarCreated) { + $created++; + $this->info("✓ 成功创建日历记录: '{$courseName}'"); } else { - $this->warn("✗ 未找到匹配的新闻标题: '{$jumpLink}'"); + $this->warn("✗ 创建日历记录失败: '{$courseName}'"); } } - // 显示匹配失败的课程 - if (!empty($failedCourses)) { - $this->warn("工作表 {$sheetName} 中匹配失败的课程:"); - foreach ($failedCourses as $failedCourse) { - $this->warn(" - {$failedCourse}"); + return [$created, $failedCourses, $failedNews]; + } + + /** + * 匹配courses表 + */ + private function matchCourse($courseName) + { + try { + // 直接匹配 + $course = Course::where('name', $courseName)->first(); + + if ($course) { + $this->info("通过直接匹配找到课程: '{$course->name}' (ID: {$course->id})"); + return $course->id; + } + + // 模糊匹配 + $course = Course::where('name', 'like', "%{$courseName}%") + ->whereNull('deleted_at') + ->first(); + + if ($course) { + $this->info("通过模糊匹配找到课程: '{$course->name}' (ID: {$course->id})"); + return $course->id; + } + + // 使用相似度匹配 + $courses = Course::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}' (ID: {$bestMatch->id})"); + return $bestMatch->id; } + + } catch (\Exception $e) { + $this->error("查询courses表时发生错误: " . $e->getMessage()); } - return $updated; + return null; } /** @@ -208,8 +309,9 @@ class UpdateCourseUrls extends Command } } - if ($bestMatch && $highestSimilarity > 0) { - $this->info("通过相似度匹配找到 (相似度: " . round($highestSimilarity * 100, 2) . "%): '{$bestMatch->title}' -> '{$bestMatch->titleurl}'"); + // 取相似度最高的作为结果,不设置阈值限制 + if ($bestMatch && $highestSimilarity > 0.3) { + $this->info("通过相似度匹配找到新闻 (相似度: " . round($highestSimilarity * 100, 2) . "%): '{$bestMatch->title}' -> '{$bestMatch->titleurl}'"); return [$bestMatch->title, $bestMatch->titleurl]; } @@ -223,58 +325,130 @@ class UpdateCourseUrls extends Command /** * 更新courses表的url字段 */ - private function updateCourseUrl($courseName, $titleUrl, $title) + private function updateCourseUrl($courseId, $titleUrl, $title) { try { - // 直接匹配 - $updateCount = Course::where('name', $courseName) - ->whereNull('deleted_at') - ->update(['url' => $titleUrl, 'url_title' => $title]); + $course = Course::find($courseId); + if ($course) { + $course->url = $titleUrl; + $course->url_title = $title; + $course->save(); + $this->info("✓ 成功更新课程URL: '{$course->name}' -> '{$titleUrl}'"); + return true; + } + } catch (\Exception $e) { + $this->error("更新courses表时发生错误: " . $e->getMessage()); + } + + return false; + } + + /** + * 创建calendar记录 + */ + private function createCalendarRecord($courseId, $courseName, $startTime, $endTime, $url = null, $title = null, $calendarTitle = null) + { + try { + // 转换时间格式 + $startDateTime = $this->parseDateTime($startTime); + $endDateTime = $this->parseDateTime($endTime); - if ($updateCount > 0) { - return $updateCount; + if (!$startDateTime || !$endDateTime) { + $this->warn("时间格式解析失败: 开始时间='{$startTime}', 结束时间='{$endTime}'"); + return false; } - // 模糊匹配 - $updateCount = Course::where('name', 'like', "%{$courseName}%") - ->whereNull('deleted_at') - ->update(['url' => $titleUrl, 'url_title' => $title]); + // 检查是否已存在相同的日历记录 + $existingCalendar = Calendar::where('course_id', $courseId) + ->where('start_time', $startDateTime) + ->where('end_time', $endDateTime) + ->first(); - if ($updateCount > 0) { - $this->info("通过模糊匹配更新了课程"); - return $updateCount; + if ($existingCalendar) { + $this->info("日历记录已存在,跳过创建: '{$courseName}'"); + return true; } - // 使用相似度匹配 - $courses = Course::whereNull('deleted_at') - ->whereNotNull('name') - ->where('name', '!=', '') - ->get(); + // 创建新的日历记录 + $calendar = new Calendar(); + $calendar->type = 1; // 课程类型 + $calendar->course_id = $courseId; + $calendar->title = $calendarTitle ?: $courseName; // 使用Excel中的课程名字作为title + $calendar->start_time = $startDateTime; + $calendar->end_time = $endDateTime; + $calendar->date = $startDateTime->format('Y-m-d'); + $calendar->url = $url; + $calendar->is_publish = 1; // 默认发布 + $calendar->save(); - $bestMatch = null; - $highestSimilarity = 0; + return true; - foreach ($courses as $course) { - $similarity = $this->calculateSimilarity($courseName, $course->name); - if ($similarity > $highestSimilarity) { - $highestSimilarity = $similarity; - $bestMatch = $course; + } catch (\Exception $e) { + $this->error("创建calendar记录时发生错误: " . $e->getMessage()); + } + + return false; + } + + /** + * 解析日期时间格式 + */ + private function parseDateTime($dateTimeString) + { + try { + // 处理Excel数字格式的日期时间 + if (is_numeric($dateTimeString)) { + $excelDate = (float) $dateTimeString; + + // Excel日期从1900年1月1日开始计算天数 + // 需要减去2是因为Excel错误地认为1900年是闰年 + $unixTimestamp = ($excelDate - 25569) * 86400; + + $dateTime = new \DateTime(); + $dateTime->setTimestamp($unixTimestamp); + + $this->info("Excel数字日期转换: {$dateTimeString} -> " . $dateTime->format('Y-m-d H:i:s')); + return $dateTime; + } + + // 尝试多种日期时间格式 + $formats = [ + 'Y-m-d H:i:s', + 'Y-m-d H:i', + 'Y/m/d H:i:s', + 'Y/m/d H:i', + 'Y-m-d', + 'Y/m/d', + 'd/m/Y H:i:s', + 'd/m/Y H:i', + 'd-m-Y H:i:s', + 'd-m-Y H:i' + ]; + + foreach ($formats as $format) { + $dateTime = \DateTime::createFromFormat($format, $dateTimeString); + if ($dateTime !== false) { + // 如果只有日期没有时间,设置默认时间 + if (strpos($format, 'H:i') === false) { + $dateTime->setTime(9, 0, 0); // 默认上午9点 + } + return $dateTime; } } - if ($bestMatch && $highestSimilarity > 0) { - $bestMatch->url = $titleUrl; - $bestMatch->url_title = $title; - $bestMatch->save(); - $this->info("通过相似度匹配更新了课程 (相似度: " . round($highestSimilarity * 100, 2) . "%): '{$bestMatch->name}'"); - return 1; + // 尝试使用strtotime + $timestamp = strtotime($dateTimeString); + if ($timestamp !== false) { + $dateTime = new \DateTime(); + $dateTime->setTimestamp($timestamp); + return $dateTime; } } catch (\Exception $e) { - $this->error("更新courses表时发生错误: " . $e->getMessage()); + $this->error("解析日期时间时发生错误: " . $e->getMessage()); } - return 0; + return null; } /** diff --git a/app/Http/Controllers/Admin/OtherController.php b/app/Http/Controllers/Admin/OtherController.php index d2c045c..7912f9e 100755 --- a/app/Http/Controllers/Admin/OtherController.php +++ b/app/Http/Controllers/Admin/OtherController.php @@ -6,6 +6,7 @@ use App\Helpers\ResponseCode; use App\Models\Admin; use App\Models\Appointment; use App\Models\AppointmentConfig; +use App\Models\Calendar; use App\Models\CarparkLog; use App\Models\Company; use App\Models\CourseSign; @@ -121,32 +122,28 @@ class OtherController extends CommonController // 报名人数 $list['course_signs_total'] = CourseSign::whereDate('created_at', '>=', $start_date) ->whereDate('created_at', '<=', $end_date) + ->whereNotIn('status', [4, 5]) ->where(function ($query) use ($courses) { $query->whereIn('course_id', $courses->pluck('id')); })->count(); // 审核通过人数 - $list['course_signs_pass'] = CourseSign::where('status', 1) + $courseSign = CourseSign::where('status', 1) ->whereDate('created_at', '>=', $start_date) ->whereDate('created_at', '<=', $end_date) + ->whereNotIn('status', [4, 5]) ->where(function ($query) use ($courses) { $query->whereIn('course_id', $courses->pluck('id')); - }) - ->count(); + })->get(); + $list['course_signs_pass'] = $courseSign->count(); // 审核通过人数去重 - $list['course_signs_pass_unique'] = CourseSign::where('status', 1) - ->whereDate('created_at', '>=', $start_date) - ->whereDate('created_at', '<=', $end_date) - ->where(function ($query) use ($courses) { - $query->whereIn('course_id', $courses->pluck('id')); - })->select('user_id') - ->distinct() - ->count(); + $list['course_signs_pass_unique'] = User::whereIn('id', $courseSign->pluck('user_id'))->distinct('mobile')->count(); // 开课场次 - $list['course_total'] = $courses->count(); + $calendar = Calendar::whereIn('course_id', $courses->pluck('id'))->whereBetween('date', [$start_date, $end_date])->get(); + $list['course_total'] = $calendar->count(); // 开课天数 - $list['course_day_total'] = $courses->sum(function ($course) { - $start = Carbon::parse($course->start_date); - $end = Carbon::parse($course->end_date); + $list['course_day_total'] = $calendar->sum(function ($course) { + $start = Carbon::parse($course->start_time); + $end = Carbon::parse($course->end_time); return $end->diffInDays($start) + 1; // 包含起始和结束日期 }); // 返回所有sql语句 @@ -160,20 +157,16 @@ class OtherController extends CommonController ->where('start_date', '<=', $end_date) ->where('type', $courseType->id) ->get(); - // 培养人数 - $courseTypeSignsPass = CourseSign::where('status', 1) + $courseSignByType = CourseSign::where('status', 1) ->whereIn('course_id', $courses2->pluck('id')) + ->whereNotIn('status', [4, 5]) ->whereDate('created_at', '>=', $start_date) ->whereDate('created_at', '<=', $end_date) - ->count(); + ->get(); + // 培养人数 + $courseTypeSignsPass = $courseSignByType->count(); // 去重培养人数 - $courseTypeSignsPassUnique = CourseSign::where('status', 1) - ->whereIn('course_id', $courses2->pluck('id')) - ->whereDate('created_at', '>=', $start_date) - ->whereDate('created_at', '<=', $end_date) - ->select('user_id') - ->distinct() - ->count(); + $courseTypeSignsPassUnique = User::whereIn('id', $courseSignByType->pluck('user_id'))->distinct('mobile')->count(); foreach ($courses2 as $course) { $courseTypesSum[] = [ 'course_type' => $courseType->name, @@ -192,20 +185,14 @@ class OtherController extends CommonController // 区域明细统计 $areas = ParameterDetail::where('parameter_id', 5)->get(); foreach ($areas as $area) { - $area->course_signs_pass = CourseSign::where('status', 1) + $courseSignByArea = CourseSign::where('status', 1) ->whereHas('user', function ($query) use ($area) { $query->where('company_area', $area->value); })->whereDate('created_at', '>=', $start_date) ->whereDate('created_at', '<=', $end_date) - ->count(); - $area->course_signs_pass_unique = CourseSign::where('status', 1) - ->whereHas('user', function ($query) use ($area) { - $query->where('company_area', $area->value); - })->whereDate('created_at', '>=', $start_date) - ->whereDate('created_at', '<=', $end_date) - ->select('user_id') - ->distinct() - ->count(); + ->get(); + $area->course_signs_pass = $courseSignByArea->count(); + $area->course_signs_pass_unique = User::whereIn('id', $courseSignByArea->pluck('user_id'))->distinct('mobile')->count(); } return $this->success(compact('list', 'courseTypesSum', 'areas', 'sql')); } diff --git a/app/Http/Controllers/Admin/SupplyDemandController.php b/app/Http/Controllers/Admin/SupplyDemandController.php index 3e40c56..1bfeb9a 100755 --- a/app/Http/Controllers/Admin/SupplyDemandController.php +++ b/app/Http/Controllers/Admin/SupplyDemandController.php @@ -270,15 +270,16 @@ class SupplyDemandController extends BaseController $interactionGrowthRate = $this->calculateGrowthRate($interactionCount, $prevInteractionCount); // 当期供需发布分页 - $list = SupplyDemand::with(['user', 'messages' => function ($query) { - $query->with('user', 'toUser')->limit(2)->orderBy('created_at', 'desc'); + $list = SupplyDemand::with(['user', 'dialogues' => function ($query) { + $query->with(['user', 'toUser', 'messages' => function ($q) { + $q->orderBy('created_at', 'desc')->limit(10); + }])->limit(2)->orderBy('created_at', 'desc'); }])->where(function ($query) use ($type) { if ($type) { $query->where('type', $type); } })->whereBetween('created_at', [$startDate, $endDate]) ->paginate($all['page_size'] ?? 20); - return $this->success([ 'list' => $list, 'supply_demand_count' => $supplyDemandCount, diff --git a/app/Http/Controllers/Admin/TeacherController.php b/app/Http/Controllers/Admin/TeacherController.php index 7e83616..f2e547d 100755 --- a/app/Http/Controllers/Admin/TeacherController.php +++ b/app/Http/Controllers/Admin/TeacherController.php @@ -3,8 +3,12 @@ namespace App\Http\Controllers\Admin; use App\Exports\BaseExport; +use App\Helpers\ResponseCode; use App\Models\CustomForm; +use App\Models\CustomFormField; use App\Models\Teacher; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Validator; use Maatwebsite\Excel\Facades\Excel; class TeacherController extends BaseController @@ -44,7 +48,7 @@ class TeacherController extends BaseController public function index() { $all = request()->all(); - $list = $this->model->with('courseContents.course','courseContents.directionDetail')->where(function ($query) use ($all) { + $list = $this->model->with('courseContents.course', 'courseContents.directionDetail')->where(function ($query) use ($all) { if (isset($all['filter']) && !empty($all['filter'])) { foreach ($all['filter'] as $condition) { $key = $condition['key'] ?? null; @@ -224,7 +228,38 @@ class TeacherController extends BaseController */ public function import() { - return parent::import(); + $all = \request()->all(); + $messages = [ + 'data.required' => '数据必填', + ]; + $validator = Validator::make($all, [ + 'data' => 'required', + ], $messages); + if ($validator->fails()) { + return $this->fail([ResponseCode::ERROR_PARAMETER, implode(',', $validator->errors()->all())]); + } + $records = $all['data']; + DB::beginTransaction(); + try { + // 获取数据表的所有字段 + // 分段导入 + foreach ($records as $item) { + $where = ['name' => $item['name']]; + $data = [ + 'name' => $item['name'], + 'sex' => $item['sex'] ?? '', + 'remark' => $item['remark'] ?? '', + 'introduce' => $item['introduce'] ?? '', + 'mobile' => $item['mobile'] ?? '', + ]; + $this->model->updateOrCreate($where, $data); + } + DB::commit(); + return $this->success(['total' => count($records), 'filter_total' => count($records)]); + } catch (\Exception $exception) { + DB::rollBack(); + return $this->fail([$exception->getCode(), $exception->getMessage()]); + } } diff --git a/app/Http/Controllers/Mobile/UserController.php b/app/Http/Controllers/Mobile/UserController.php index 4b58cd3..96353cb 100755 --- a/app/Http/Controllers/Mobile/UserController.php +++ b/app/Http/Controllers/Mobile/UserController.php @@ -254,7 +254,7 @@ class UserController extends CommonController })->where('id', $this->getUserId())->count(); // 是否生日 $is_birthday = 0; - if (isset($user->birthday) && $user->birthday == date('Y-m-d')) { + if (isset($user->birthday) && date('m-d', strtotime($user->birthday)) == date('m-d')) { $is_birthday = 1; } return $this->success(compact('user', 'door_appointments', 'course_signs', 'enter_schoolmate', 'is_birthday')); diff --git a/app/Models/Dialogue.php b/app/Models/Dialogue.php index 19b3fd0..671b3ce 100644 --- a/app/Models/Dialogue.php +++ b/app/Models/Dialogue.php @@ -15,8 +15,14 @@ class Dialogue extends SoftDeletesModel return $this->hasOne(User::class, 'id', 'to_user_id'); } - public function supplyDemand(){ + public function supplyDemand() + { return $this->hasOne(SupplyDemand::class, 'id', 'supply_demand_id'); } + public function messages() + { + return $this->hasMany(Message::class, 'dialogue_id', 'id'); + } + } diff --git a/app/Models/SupplyDemand.php b/app/Models/SupplyDemand.php index b9c0860..9fb41cd 100755 --- a/app/Models/SupplyDemand.php +++ b/app/Models/SupplyDemand.php @@ -34,5 +34,10 @@ class SupplyDemand extends SoftDeletesModel return $this->hasMany(Message::class, 'supply_demand_id', 'id'); } + public function dialogues() + { + return $this->hasMany(Dialogue::class, 'supply_demand_id', 'id'); + } + } diff --git a/app/Services/TestData/CourseContentEvaluationTestDataGenerator.php b/app/Services/TestData/CourseContentEvaluationTestDataGenerator.php index ac613c8..ddcfe07 100644 --- a/app/Services/TestData/CourseContentEvaluationTestDataGenerator.php +++ b/app/Services/TestData/CourseContentEvaluationTestDataGenerator.php @@ -60,33 +60,46 @@ class CourseContentEvaluationTestDataGenerator } // 3) 生成评价问卷主数据 - for ($i = 0; $i < $evaluationCount; $i++) { - $courseContent = $allCourseContents->random(); - $course = $courses->where('id', $courseContent->course_id)->first(); - - if (!$course) { - // 如果找不到课程,跳过这个课程内容 - continue; + // 按课程分组,每个课程生成一个问卷,包含该课程的所有内容 + $coursesWithContents = $courses->map(function ($course) use ($allCourseContents) { + $courseContents = $allCourseContents->where('course_id', $course->id); + return [ + 'course' => $course, + 'contents' => $courseContents + ]; + })->filter(function ($item) { + return $item['contents']->count() > 0; + }); + + $selectedCourses = $coursesWithContents->random(min($evaluationCount, $coursesWithContents->count())); + + foreach ($selectedCourses as $courseData) { + $course = $courseData['course']; + $courseContents = $courseData['contents']; + + // 为每个课程创建一个评价问卷 + $evaluation = $this->createEvaluation($courseContents->first(), $course, $faker); + + // 4) 为每个问卷生成问题字段(包含该课程的所有内容) + $allAsks = []; + foreach ($courseContents as $courseContent) { + $asks = $this->createEvaluationAsks($evaluation, $courseContent, $course, 0, $faker); + $allAsks = array_merge($allAsks, $asks); } - - $evaluation = $this->createEvaluation($courseContent, $course, $faker); - - // 4) 为每个问卷生成问题字段 - $askCount = $faker->numberBetween(5, 15); - $asks = $this->createEvaluationAsks($evaluation, $courseContent, $course, $askCount, $faker); - + // 5) 生成用户提交的表单数据 $formCount = $faker->numberBetween(10, min(40, $allUsers->count())); $submittedUsers = $allUsers->random($formCount); - + foreach ($submittedUsers as $user) { - $this->createEvaluationForm($evaluation, $user, $asks, $faker); + $this->createEvaluationForm($evaluation, $user, $allAsks, $faker); } - $log(sprintf('评价问卷#%d "%s" 已生成:%d个问题字段,%d份用户提交', + $log(sprintf( + '评价问卷#%d "%s" 已生成:%d个问题字段,%d份用户提交', $evaluation->id, $evaluation->title, - $askCount, + count($allAsks), $formCount )); } @@ -104,11 +117,11 @@ class CourseContentEvaluationTestDataGenerator $evaluation->title = $this->generateEvaluationTitle($course, $courseContent, $faker); $evaluation->desc = $this->generateEvaluationDesc($faker); $evaluation->type_id = $faker->numberBetween(1, 5); // 问卷类型ID - + // 时间设置:开始时间在课程内容时间前后,截止时间在开始时间之后 $startTime = $faker->dateTimeBetween('-30 days', '+7 days'); $endTime = $faker->dateTimeBetween($startTime, $startTime->format('Y-m-d H:i:s') . ' +30 days'); - + $evaluation->start_time = $startTime->format('Y-m-d H:i:s'); $evaluation->end_time = $endTime->format('Y-m-d H:i:s'); $evaluation->status = $faker->randomElement([0, 1]); // 0未发布, 1已发布 @@ -124,10 +137,74 @@ class CourseContentEvaluationTestDataGenerator { $asks = []; $fieldTemplates = $this->getEvaluationFieldTemplates(); - - for ($i = 0; $i < $count; $i++) { - $template = $faker->randomElement($fieldTemplates); - + + // 为每个课程内容生成4个评价维度的问题(课程必要性、理论丰富程度、实践指导意义、讲授能力) + $evaluationDimensions = [ + '课程必要性', + '理论丰富程度', + '实践指导意义', + '讲授能力' + ]; + + $sort = 1; + + // 为每个评价维度创建问题,每个维度都包含课程内容标题 + foreach ($evaluationDimensions as $dimension) { + $ask = new CourseContentEvaluationAsk(); + $ask->admin_id = $faker->numberBetween(1, 10); + $ask->department_id = $faker->numberBetween(1, 5); + $ask->course_id = $course->id; + $ask->course_content_id = $courseContent->id; + $ask->course_content_evaluation_id = $evaluation->id; + $ask->name = $courseContent->theme . '——' . $dimension; + $ask->field = strtolower(str_replace(' ', '_', $dimension)) . '_' . $courseContent->id; + $ask->edit_input = 'radio'; + $ask->rule = 'required'; + $ask->sort = $sort++; + $ask->help = "请评价《{$courseContent->theme}》的{$dimension}"; + $ask->select_item = ['很不满意', '不满意', '一般', '满意', '很满意']; + $ask->need_fill = true; + $ask->belong_user = false; + $ask->allow_input = false; + $ask->save(); + + $asks[] = $ask; + } + + // 添加建议类问题 + $suggestionTemplates = array_filter($fieldTemplates, function ($template) { + return $template['edit_input'] === 'textarea'; + }); + + foreach ($suggestionTemplates as $template) { + $ask = new CourseContentEvaluationAsk(); + $ask->admin_id = $faker->numberBetween(1, 10); + $ask->department_id = $faker->numberBetween(1, 5); + $ask->course_id = $course->id; + $ask->course_content_id = $courseContent->id; + $ask->course_content_evaluation_id = $evaluation->id; + $ask->name = $template['name']; + $ask->field = $template['field']; + $ask->edit_input = $template['edit_input']; + $ask->rule = $template['rule']; + $ask->sort = $sort++; + $ask->help = $template['help']; + $ask->select_item = $template['select_item']; + $ask->need_fill = $template['need_fill']; + $ask->belong_user = $template['belong_user']; + $ask->allow_input = $template['allow_input']; + $ask->save(); + + $asks[] = $ask; + } + + // 添加姓名字段 + $nameTemplate = array_filter($fieldTemplates, function ($template) { + return $template['field'] === 'student_name'; + }); + + if (!empty($nameTemplate)) { + $template = reset($nameTemplate); $ask = new CourseContentEvaluationAsk(); $ask->admin_id = $faker->numberBetween(1, 10); $ask->department_id = $faker->numberBetween(1, 5); @@ -135,20 +212,20 @@ class CourseContentEvaluationTestDataGenerator $ask->course_content_id = $courseContent->id; $ask->course_content_evaluation_id = $evaluation->id; $ask->name = $template['name']; - $ask->field = $template['field'] . '_' . ($i + 1); + $ask->field = $template['field']; $ask->edit_input = $template['edit_input']; $ask->rule = $template['rule']; - $ask->sort = $i + 1; + $ask->sort = $sort++; $ask->help = $template['help']; $ask->select_item = $template['select_item']; $ask->need_fill = $template['need_fill']; $ask->belong_user = $template['belong_user']; $ask->allow_input = $template['allow_input']; $ask->save(); - + $asks[] = $ask; } - + return $asks; } @@ -158,11 +235,11 @@ class CourseContentEvaluationTestDataGenerator private function createEvaluationForm(CourseContentEvaluation $evaluation, User $user, array $asks, $faker): void { $formData = []; - + foreach ($asks as $ask) { $formData[$ask->field] = $this->generateFieldValue($ask, $faker); } - + $form = new CourseContentEvaluationForm(); $form->course_content_evaluation_id = $evaluation->id; $form->user_id = $user->id; @@ -178,17 +255,20 @@ class CourseContentEvaluationTestDataGenerator private function generateEvaluationTitle(Course $course, CourseContent $courseContent, $faker): string { $templates = [ - '《%s》课程满意度调查', - '%s 教学效果评价', - '%s 学习体验反馈', - '关于 %s 的教学质量评估', - '%s 课程内容评价问卷', - '%s 授课情况调研', - '%s 学员反馈调查' + '首期%s课程满意度调查', + '%s(%s班)第一次课课程满意度调查', + '%s研修班课程满意度调查', + '%s培训课程满意度调查', + '%s课程满意度调查问卷', + '%s课程评价调查', + '%s学习效果评价调查' ]; - - $courseName = $course->title ?? '课程'; - return sprintf($faker->randomElement($templates), $courseName); + + $courseName = $course->name ?? '课程'; + $classNames = ['攀峰班', '精英班', '进阶班', '基础班', '高级班']; + $className = $faker->randomElement($classNames); + + return sprintf($faker->randomElement($templates), $courseName, $className); } /** @@ -197,13 +277,13 @@ class CourseContentEvaluationTestDataGenerator private function generateEvaluationDesc($faker): string { $descriptions = [ - '为了提升教学质量,改进课程内容,请您根据实际学习体验,客观填写本次评价问卷。您的宝贵意见将帮助我们持续优化课程设计。', - '此次评价旨在了解您对本课程的学习感受和建议。问卷采用匿名形式,请放心填写真实想法,感谢您的配合!', - '请根据您的实际学习情况,对本次课程的各个方面进行客观评价。您的反馈对我们改进教学方法具有重要意义。', - '为持续提升课程品质,特设立本次学员满意度调查。请您花费几分钟时间,帮助我们了解课程的优点与不足。', - '感谢您参与本次课程学习!为了给后续学员提供更好的学习体验,恳请您如实填写这份评价问卷。' + '为了提升研修班教学质量,改进课程内容,请您根据实际学习体验,客观填写本次评价问卷。您的宝贵意见将帮助我们持续优化课程设计。', + '此次评价旨在了解您对本研修班课程的学习感受和建议。问卷采用匿名形式,请放心填写真实想法,感谢您的配合!', + '请根据您的实际学习情况,对本次研修班课程的各个方面进行客观评价。您的反馈对我们改进教学方法具有重要意义。', + '为持续提升研修班课程品质,特设立本次学员满意度调查。请您花费几分钟时间,帮助我们了解课程的优点与不足。', + '感谢您参与本次研修班课程学习!为了给后续学员提供更好的学习体验,恳请您如实填写这份评价问卷。' ]; - + return $faker->randomElement($descriptions); } @@ -214,114 +294,92 @@ class CourseContentEvaluationTestDataGenerator { return [ [ - 'name' => '课程内容满意度', - 'field' => 'content_satisfaction', + 'name' => '课程必要性', + 'field' => 'course_necessity', 'edit_input' => 'radio', 'rule' => 'required', - 'help' => '请选择您对课程内容的满意程度', - 'select_item' => ['非常满意', '满意', '一般', '不满意', '非常不满意'], + 'help' => '请评价该课程的必要性', + 'select_item' => ['很不满意', '不满意', '一般', '满意', '很满意'], 'need_fill' => true, 'belong_user' => false, 'allow_input' => false ], [ - 'name' => '授课方式评价', - 'field' => 'teaching_method', + 'name' => '理论丰富程度', + 'field' => 'theory_richness', 'edit_input' => 'radio', 'rule' => 'required', - 'help' => '请评价老师的授课方式', - 'select_item' => ['很好', '好', '一般', '较差', '很差'], + 'help' => '请评价课程理论的丰富程度', + 'select_item' => ['很不满意', '不满意', '一般', '满意', '很满意'], 'need_fill' => true, 'belong_user' => false, 'allow_input' => false ], [ - 'name' => '课程难度评价', - 'field' => 'difficulty_level', + 'name' => '实践指导意义', + 'field' => 'practical_guidance', 'edit_input' => 'radio', 'rule' => 'required', - 'help' => '您认为课程难度如何', - 'select_item' => ['太简单', '偏简单', '适中', '偏难', '太难'], + 'help' => '请评价课程的实践指导意义', + 'select_item' => ['很不满意', '不满意', '一般', '满意', '很满意'], 'need_fill' => true, 'belong_user' => false, 'allow_input' => false ], [ - 'name' => '学习收获评价', - 'field' => 'learning_gain', - 'edit_input' => 'checkbox', - 'rule' => '', - 'help' => '您在本次学习中获得了哪些收获(可多选)', - 'select_item' => ['理论知识', '实践技能', '思维方法', '行业认知', '人际交往', '其他'], - 'need_fill' => false, - 'belong_user' => false, - 'allow_input' => true - ], - [ - 'name' => '课程推荐度', - 'field' => 'recommendation', + 'name' => '讲授能力', + 'field' => 'teaching_ability', 'edit_input' => 'radio', 'rule' => 'required', - 'help' => '您是否愿意向他人推荐此课程', - 'select_item' => ['非常愿意', '愿意', '无所谓', '不愿意', '绝对不会'], + 'help' => '请评价老师的讲授能力', + 'select_item' => ['很不满意', '不满意', '一般', '满意', '很满意'], 'need_fill' => true, 'belong_user' => false, 'allow_input' => false ], [ - 'name' => '整体评分', - 'field' => 'overall_rating', - 'edit_input' => 'select', - 'rule' => 'required', - 'help' => '请为本次课程打分(10分制)', - 'select_item' => ['10分', '9分', '8分', '7分', '6分', '5分', '4分', '3分', '2分', '1分'], - 'need_fill' => true, + 'name' => '您对本次培训的课程及老师的资料、专业性等方面有哪些建议?', + 'field' => 'course_teacher_suggestions', + 'edit_input' => 'textarea', + 'rule' => '', + 'help' => '请提出您对课程和老师的建议', + 'select_item' => null, + 'need_fill' => false, 'belong_user' => false, - 'allow_input' => false + 'allow_input' => true ], [ - 'name' => '意见建议', - 'field' => 'suggestions', + 'name' => '您对培训专题、课程内容、授课师资及形式等方面有哪些建议?', + 'field' => 'training_suggestions', 'edit_input' => 'textarea', 'rule' => '', - 'help' => '请提出您的宝贵意见和建议', + 'help' => '请提出您对培训各方面的建议', 'select_item' => null, 'need_fill' => false, 'belong_user' => false, 'allow_input' => true ], [ - 'name' => '您的姓名', - 'field' => 'student_name', - 'edit_input' => 'text', + 'name' => '其他建议', + 'field' => 'other_suggestions', + 'edit_input' => 'textarea', 'rule' => '', - 'help' => '请填写您的真实姓名(可选)', + 'help' => '请提出其他建议', 'select_item' => null, 'need_fill' => false, - 'belong_user' => true, - 'allow_input' => false + 'belong_user' => false, + 'allow_input' => true ], [ - 'name' => '联系方式', - 'field' => 'contact_info', + 'name' => '如果您愿意,请留下您的姓名(选填)', + 'field' => 'student_name', 'edit_input' => 'text', 'rule' => '', - 'help' => '如需回访,请留下联系方式', + 'help' => '这将帮助我们更好地整理反馈并与您沟通', 'select_item' => null, 'need_fill' => false, 'belong_user' => true, 'allow_input' => false - ], - [ - 'name' => '课堂互动评价', - 'field' => 'interaction_rating', - 'edit_input' => 'radio', - 'rule' => '', - 'help' => '您对课堂互动环节的评价', - 'select_item' => ['很活跃', '较活跃', '一般', '较沉闷', '很沉闷'], - 'need_fill' => false, - 'belong_user' => false, - 'allow_input' => false ] ]; } @@ -335,33 +393,42 @@ class CourseContentEvaluationTestDataGenerator case 'radio': case 'select': return $faker->randomElement($ask->select_item ?? []); - + case 'checkbox': $options = $ask->select_item ?? []; $selected = $faker->randomElements($options, $faker->numberBetween(1, min(3, count($options)))); return implode(',', $selected); - + case 'textarea': $suggestions = [ - '希望增加更多实践环节', - '课程进度可以适当放慢', - '案例分析很有帮助,建议增加', - '老师讲解很清晰,受益良多', - '课程资料很丰富,感谢分享', - '希望提供更多课后练习', - '建议增加小组讨论时间', - '整体非常满意,期待后续课程' + '希望增加更多实践环节和案例分析', + '课程进度可以适当放慢,便于消化吸收', + '案例分析很有帮助,建议增加更多实际案例', + '老师讲解很清晰,理论联系实际,受益良多', + '课程资料很丰富,感谢分享,希望提供更多参考资料', + '希望提供更多课后练习和讨论机会', + '建议增加小组讨论时间和互动环节', + '整体非常满意,期待后续课程,希望继续深入学习', + '课程内容很实用,对工作有很大帮助', + '老师专业水平很高,讲解深入浅出', + '希望增加更多行业前沿信息分享', + '课程安排合理,时间控制得当', + '建议增加更多实战演练环节', + '课程质量很高,值得推荐给同事', + '希望提供更多学习资源和交流平台' ]; return $faker->optional(0.7)->randomElement($suggestions) ?: ''; - + case 'text': if ($ask->field === 'student_name') { return $faker->optional(0.4)->name ?: ''; + } elseif ($ask->field === 'course_content_title') { + return $ask->name; // 返回课程内容标题 } elseif ($ask->field === 'contact_info') { return $faker->optional(0.3)->phoneNumber ?: ''; } return $faker->optional(0.5)->words(3, true) ?: ''; - + default: return ''; } @@ -373,18 +440,62 @@ class CourseContentEvaluationTestDataGenerator private function createSampleCoursesAndContents($faker): void { $courseData = [ - ['title' => 'Python 程序设计基础', 'contents' => ['Python 语言概述', '数据类型与变量', '控制结构', '函数与模块', '面向对象编程']], - ['title' => '数据库原理与应用', 'contents' => ['数据库基础概念', 'SQL 语言基础', '数据库设计', '事务处理', '性能优化']], - ['title' => '项目管理实务', 'contents' => ['项目管理概述', '项目计划制定', '风险管理', '团队管理', '项目收尾']], - ['title' => '市场营销学', 'contents' => ['市场营销概论', '消费者行为分析', '产品策略', '价格策略', '推广策略']], - ['title' => 'Web 前端开发', 'contents' => ['HTML 基础', 'CSS 样式设计', 'JavaScript 编程', 'Vue.js 框架', '项目实战']] + [ + 'title' => '苏州市科技企业资本运作研修班', + 'contents' => [ + '《资本市场深化改革背景下,私募股权基金的专业化发展路径与企业家资本战略选择》——王建平老师', + '《科技创新产业现状与未来趋势(深圳创新实践案例)》——梁永生老师', + '《IPO流程与估值——沙盘演练》——郭圣宇老师', + '《IPO流程与估值——沙盘演练》——张剑波老师', + '《IPO企业常见涉税问题——专题授课》——肖鑫老师', + '《IPO企业财务管理——沙盘演练》——王晓苗老师' + ] + ], + [ + 'title' => '企业数字化转型研修班', + 'contents' => [ + '《数字化转型战略规划》——李明老师', + '《人工智能在企业中的应用》——张华老师', + '《大数据分析与决策支持》——王强老师', + '《云计算与云原生架构》——刘伟老师' + ] + ], + [ + 'title' => '创新创业管理研修班', + 'contents' => [ + '《创业机会识别与商业模式设计》——陈刚老师', + '《创业团队建设与管理》——赵敏老师', + '《融资策略与风险投资》——孙涛老师', + '《知识产权保护与运用》——周琳老师' + ] + ], + [ + 'title' => '供应链管理研修班', + 'contents' => [ + '《供应链战略规划》——吴斌老师', + '《采购管理与供应商关系》——郑红老师', + '《物流配送优化》——马超老师', + '《供应链风险管理》——徐静老师' + ] + ], + [ + 'title' => '人力资源管理研修班', + 'contents' => [ + '《人力资源战略规划》——黄磊老师', + '《招聘与人才发展》——韩雪老师', + '《绩效管理与激励机制》——杨帆老师', + '《企业文化与组织发展》——林峰老师' + ] + ] ]; foreach ($courseData as $data) { $course = Course::create([ - 'title' => $data['title'], - 'description' => $data['title'] . '课程', + 'name' => $data['title'], + 'content' => $data['title'] . '课程', 'status' => 1, + 'course_status' => 10, // 进行中 + 'sign_status' => 10, // 进行中 'created_at' => now(), 'updated_at' => now() ]); @@ -392,10 +503,8 @@ class CourseContentEvaluationTestDataGenerator foreach ($data['contents'] as $index => $contentTitle) { CourseContent::create([ 'course_id' => $course->id, - 'title' => $contentTitle, - 'description' => $contentTitle . '相关内容', - 'sort' => $index + 1, - 'status' => 1, + 'theme' => $contentTitle, + 'period' => '第' . ($index + 1) . '期', 'created_at' => now(), 'updated_at' => now() ]); diff --git a/课程台账.xlsx b/课程台账.xlsx index 3bc5dde..4a2659a 100644 Binary files a/课程台账.xlsx and b/课程台账.xlsx differ