From a99b3ede0fba5ba45ae1ab5a0dfaecd6d77ce736 Mon Sep 17 00:00:00 2001 From: weizong song Date: Sat, 9 Aug 2025 16:26:32 +0800 Subject: [PATCH] up --- .gitignore | 1 + .../Commands/SeedCourseContentEvaluations.php | 58 +++ app/Models/Course.php | 5 + ...urseContentEvaluationTestDataGenerator.php | 405 ++++++++++++++++++ 4 files changed, 469 insertions(+) create mode 100644 app/Console/Commands/SeedCourseContentEvaluations.php create mode 100644 app/Services/TestData/CourseContentEvaluationTestDataGenerator.php diff --git a/.gitignore b/.gitignore index 4cd4b9a..f521362 100755 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ npm-debug.log yarn-error.log /.idea /.vscode +/.snapshots diff --git a/app/Console/Commands/SeedCourseContentEvaluations.php b/app/Console/Commands/SeedCourseContentEvaluations.php new file mode 100644 index 0000000..b96d42e --- /dev/null +++ b/app/Console/Commands/SeedCourseContentEvaluations.php @@ -0,0 +1,58 @@ +option('evaluations'); + $minUsers = (int) $this->option('users'); + + $this->info("开始生成课程内容评价测试数据..."); + $this->info("计划生成 {$evaluationCount} 个评价问卷,确保至少 {$minUsers} 个用户"); + + $generator = new CourseContentEvaluationTestDataGenerator(); + + $startTime = microtime(true); + + try { + $generator->generate($evaluationCount, $minUsers, function (string $message) { + $this->line(" → {$message}"); + }); + + $duration = round(microtime(true) - $startTime, 2); + $this->info("✅ 数据生成完成!耗时 {$duration} 秒"); + + return Command::SUCCESS; + + } catch (\Exception $e) { + $this->error("❌ 数据生成失败:" . $e->getMessage()); + return Command::FAILURE; + } + } +} diff --git a/app/Models/Course.php b/app/Models/Course.php index f7a94db..7fd70be 100755 --- a/app/Models/Course.php +++ b/app/Models/Course.php @@ -94,6 +94,11 @@ class Course extends SoftDeletesModel return $this->hasOne(Upload::class, 'id', 'qun_image_id'); } + public function courseContents() + { + return $this->hasMany(CourseContent::class, 'course_id', 'id'); + } + /** * 更新课程报名状态 */ diff --git a/app/Services/TestData/CourseContentEvaluationTestDataGenerator.php b/app/Services/TestData/CourseContentEvaluationTestDataGenerator.php new file mode 100644 index 0000000..ac613c8 --- /dev/null +++ b/app/Services/TestData/CourseContentEvaluationTestDataGenerator.php @@ -0,0 +1,405 @@ +create(); + } + + $allUsers = User::all(); + if ($allUsers->count() < 5) { + throw new \RuntimeException('生成评价数据至少需要5个用户'); + } + + // 2) 确保课程和课程内容存在 + $courses = Course::with('courseContents')->get(); + if ($courses->isEmpty()) { + $log("创建示例课程数据"); + $this->createSampleCoursesAndContents($faker); + $courses = Course::with('courseContents')->get(); + } + + $allCourseContents = CourseContent::all(); + if ($allCourseContents->isEmpty()) { + throw new \RuntimeException('无课程内容数据,无法生成评价'); + } + + // 3) 生成评价问卷主数据 + for ($i = 0; $i < $evaluationCount; $i++) { + $courseContent = $allCourseContents->random(); + $course = $courses->where('id', $courseContent->course_id)->first(); + + if (!$course) { + // 如果找不到课程,跳过这个课程内容 + continue; + } + + $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); + } + + $log(sprintf('评价问卷#%d "%s" 已生成:%d个问题字段,%d份用户提交', + $evaluation->id, + $evaluation->title, + $askCount, + $formCount + )); + } + }); + } + + /** + * 创建评价问卷主数据 + */ + private function createEvaluation(CourseContent $courseContent, Course $course, $faker): CourseContentEvaluation + { + $evaluation = new CourseContentEvaluation(); + $evaluation->course_id = $course->id; + $evaluation->course_content_id = $courseContent->id; + $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已发布 + $evaluation->save(); + + return $evaluation; + } + + /** + * 创建评价问题字段 + */ + private function createEvaluationAsks(CourseContentEvaluation $evaluation, CourseContent $courseContent, Course $course, int $count, $faker): array + { + $asks = []; + $fieldTemplates = $this->getEvaluationFieldTemplates(); + + for ($i = 0; $i < $count; $i++) { + $template = $faker->randomElement($fieldTemplates); + + $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'] . '_' . ($i + 1); + $ask->edit_input = $template['edit_input']; + $ask->rule = $template['rule']; + $ask->sort = $i + 1; + $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; + } + + /** + * 创建用户提交的评价表单 + */ + 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; + $form->time_total = $faker->numberBetween(180, 1800); // 3分钟到30分钟 + $form->data = $formData; + $form->created_at = $faker->dateTimeBetween($evaluation->start_time, $evaluation->end_time ?: 'now'); + $form->save(); + } + + /** + * 生成评价标题 + */ + private function generateEvaluationTitle(Course $course, CourseContent $courseContent, $faker): string + { + $templates = [ + '《%s》课程满意度调查', + '%s 教学效果评价', + '%s 学习体验反馈', + '关于 %s 的教学质量评估', + '%s 课程内容评价问卷', + '%s 授课情况调研', + '%s 学员反馈调查' + ]; + + $courseName = $course->title ?? '课程'; + return sprintf($faker->randomElement($templates), $courseName); + } + + /** + * 生成评价描述 + */ + private function generateEvaluationDesc($faker): string + { + $descriptions = [ + '为了提升教学质量,改进课程内容,请您根据实际学习体验,客观填写本次评价问卷。您的宝贵意见将帮助我们持续优化课程设计。', + '此次评价旨在了解您对本课程的学习感受和建议。问卷采用匿名形式,请放心填写真实想法,感谢您的配合!', + '请根据您的实际学习情况,对本次课程的各个方面进行客观评价。您的反馈对我们改进教学方法具有重要意义。', + '为持续提升课程品质,特设立本次学员满意度调查。请您花费几分钟时间,帮助我们了解课程的优点与不足。', + '感谢您参与本次课程学习!为了给后续学员提供更好的学习体验,恳请您如实填写这份评价问卷。' + ]; + + return $faker->randomElement($descriptions); + } + + /** + * 获取评价字段模板 + */ + private function getEvaluationFieldTemplates(): array + { + return [ + [ + 'name' => '课程内容满意度', + 'field' => 'content_satisfaction', + 'edit_input' => 'radio', + 'rule' => 'required', + 'help' => '请选择您对课程内容的满意程度', + 'select_item' => ['非常满意', '满意', '一般', '不满意', '非常不满意'], + 'need_fill' => true, + 'belong_user' => false, + 'allow_input' => false + ], + [ + 'name' => '授课方式评价', + 'field' => 'teaching_method', + 'edit_input' => 'radio', + 'rule' => 'required', + 'help' => '请评价老师的授课方式', + 'select_item' => ['很好', '好', '一般', '较差', '很差'], + 'need_fill' => true, + 'belong_user' => false, + 'allow_input' => false + ], + [ + 'name' => '课程难度评价', + 'field' => 'difficulty_level', + 'edit_input' => 'radio', + 'rule' => 'required', + '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', + 'edit_input' => 'radio', + 'rule' => 'required', + '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, + 'belong_user' => false, + 'allow_input' => false + ], + [ + 'name' => '意见建议', + 'field' => 'suggestions', + 'edit_input' => 'textarea', + 'rule' => '', + 'help' => '请提出您的宝贵意见和建议', + 'select_item' => null, + 'need_fill' => false, + 'belong_user' => false, + 'allow_input' => true + ], + [ + 'name' => '您的姓名', + 'field' => 'student_name', + 'edit_input' => 'text', + 'rule' => '', + 'help' => '请填写您的真实姓名(可选)', + 'select_item' => null, + 'need_fill' => false, + 'belong_user' => true, + 'allow_input' => false + ], + [ + 'name' => '联系方式', + 'field' => 'contact_info', + 'edit_input' => 'text', + 'rule' => '', + '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 + ] + ]; + } + + /** + * 根据字段类型生成对应的值 + */ + private function generateFieldValue(CourseContentEvaluationAsk $ask, $faker) + { + switch ($ask->edit_input) { + 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 === 'contact_info') { + return $faker->optional(0.3)->phoneNumber ?: ''; + } + return $faker->optional(0.5)->words(3, true) ?: ''; + + default: + return ''; + } + } + + /** + * 创建示例课程和课程内容数据(如果不存在) + */ + 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 框架', '项目实战']] + ]; + + foreach ($courseData as $data) { + $course = Course::create([ + 'title' => $data['title'], + 'description' => $data['title'] . '课程', + 'status' => 1, + 'created_at' => now(), + 'updated_at' => now() + ]); + + foreach ($data['contents'] as $index => $contentTitle) { + CourseContent::create([ + 'course_id' => $course->id, + 'title' => $contentTitle, + 'description' => $contentTitle . '相关内容', + 'sort' => $index + 1, + 'status' => 1, + 'created_at' => now(), + 'updated_at' => now() + ]); + } + } + } +} \ No newline at end of file