From 98bd3303bb0c9d0c32614b8b8db50a74c2f5f7bf Mon Sep 17 00:00:00 2001 From: lion <120344285@qq.com> Date: Thu, 22 Oct 2026 21:12:32 +0800 Subject: [PATCH] =?UTF-8?q?=E9=97=AE=E5=8D=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Mobile/CourseController.php | 4 +- app/Models/CourseContentEvaluation.php | 18 +++++++- tests/Feature/SurveyWorkflowTest.php | 42 +++++++++++++++++-- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Mobile/CourseController.php b/app/Http/Controllers/Mobile/CourseController.php index 4d0b91b..f9cca22 100755 --- a/app/Http/Controllers/Mobile/CourseController.php +++ b/app/Http/Controllers/Mobile/CourseController.php @@ -187,6 +187,7 @@ class CourseController extends CommonController } ])->find($all['course_content_evaluation_id']); if (!$detail) return $this->fail([ResponseCode::ERROR_BUSINESS, '问卷不存在']); + if ($error = $detail->availabilityError()) return $this->success(['id' => $detail->id] + $error); if ($message = $detail->participationError($this->getUserId())) return $this->success(['id' => $detail->id, 'access_error' => $message]); $detail->schema_hash = SurveySchema::hash($detail->courseContentEvaluationAsks->toArray()); $reply = $detail->courseContentEvaluationForms()->where('user_id', $this->getUserId())->first(); @@ -485,9 +486,8 @@ class CourseController extends CommonController $model = DB::transaction(function () use ($all) { $survey = CourseContentEvaluation::whereKey($all['course_content_evaluation_id'])->lockForUpdate()->first(); if (!$survey) throw new \InvalidArgumentException('问卷不存在'); + if ($error = $survey->availabilityError()) return ['id' => $survey->id] + $error; if ($message = $survey->participationError($this->getUserId())) return ['access_error' => $message]; - if ((int) $survey->status !== 1) throw new \InvalidArgumentException('问卷未发布'); - if ($survey->start_time && strtotime($survey->start_time) > time()) throw new \InvalidArgumentException('评价时间未开始'); if (trim((string) auth('mobile')->user()->mobile) === '') throw new \InvalidArgumentException('请先绑定或注册'); $reply = $survey->courseContentEvaluationForms()->where('user_id', $this->getUserId())->first(); $questions = $survey->courseContentEvaluationAsks()->with('courseContent.teacher')->orderBy('sort')->orderBy('id')->get()->toArray(); diff --git a/app/Models/CourseContentEvaluation.php b/app/Models/CourseContentEvaluation.php index 8c4b514..7691714 100644 --- a/app/Models/CourseContentEvaluation.php +++ b/app/Models/CourseContentEvaluation.php @@ -6,9 +6,25 @@ class CourseContentEvaluation extends SoftDeletesModel { protected $casts = ['audience_course_ids' => 'array']; + public function availabilityError(): ?array + { + $now = \Illuminate\Support\Carbon::now(); + if ($this->start_time) { + $start = \Illuminate\Support\Carbon::parse($this->start_time); + if ($start->greaterThan($now)) { + $formatted = $start->format($start->format('H:i:s') === '00:00:00' ? 'Y年m月d日' : 'Y年m月d日 H:i:s'); + return ['access_state' => 'not_started', 'access_error' => '该问卷尚未开始,请于'.$formatted.'后扫码打开该问卷。']; + } + } + if ((int) $this->status !== 1) return ['access_state' => 'draft', 'access_error' => '该问卷还未开始。']; + if ($this->end_time && \Illuminate\Support\Carbon::parse($this->end_time)->lessThanOrEqualTo($now)) { + return ['access_state' => 'ended', 'access_error' => '该问卷已结束。']; + } + return null; + } + public function participationError($userId): ?string { - if ($this->end_time && strtotime($this->end_time) <= time()) return '当前问卷已截止'; if ($this->audience_course_ids && !CourseSign::where('user_id', $userId)->whereIn('course_id', $this->audience_course_ids)->where('status', 1)->exists()) return '您还未报名相关课程'; return null; } diff --git a/tests/Feature/SurveyWorkflowTest.php b/tests/Feature/SurveyWorkflowTest.php index 599d04e..5c90eca 100644 --- a/tests/Feature/SurveyWorkflowTest.php +++ b/tests/Feature/SurveyWorkflowTest.php @@ -279,6 +279,40 @@ class SurveyWorkflowTest extends TestCase $this->assertSame(1, DB::table('course_content_evaluation_forms')->count()); } + public function testUnavailableSurveysHideContentAndBlockSubmissionIncludingExistingReplies(): void + { + \Illuminate\Support\Carbon::setTestNow(\Illuminate\Support\Carbon::parse('2026-10-22 12:00:00')); + try { + $id = $this->createQuestion(); + $detail = '/api/mobile/course/evaluation-detail?course_content_evaluation_id=10'; + $submit = '/api/mobile/course/course-content-form'; + $payload = ['course_content_evaluation_id' => 10, 'answer_version' => 2, 'data' => [['id' => $id, 'value' => ['count' => 0, 'follow' => 'no']]]]; + $replyId = $this->postJson($submit, $payload)->assertOk()->json('id'); + $original = DB::table('course_content_evaluation_forms')->where('id', $replyId)->value('data'); + foreach ([ + [1, '2026-10-23 00:00:00', null, 'not_started', '该问卷尚未开始,请于2026年10月23日后扫码打开该问卷。'], + [1, '2026-10-23 09:30:15', null, 'not_started', '该问卷尚未开始,请于2026年10月23日 09:30:15后扫码打开该问卷。'], + [1, null, '2026-10-22 12:00:00', 'ended', '该问卷已结束。'], + [0, null, null, 'draft', '该问卷还未开始。'], + [0, '2026-10-26 00:00:00', null, 'not_started', '该问卷尚未开始,请于2026年10月26日后扫码打开该问卷。'], + [0, '2026-10-26 09:30:15', null, 'not_started', '该问卷尚未开始,请于2026年10月26日 09:30:15后扫码打开该问卷。'], + [0, '2026-10-21 00:00:00', null, 'draft', '该问卷还未开始。'], + [0, null, '2020-01-01 00:00:00', 'draft', '该问卷还未开始。'], + ] as [$status, $start, $end, $state, $message]) { + DB::table('course_content_evaluations')->where('id', 10)->update(['status' => $status, 'start_time' => $start, 'end_time' => $end]); + $this->getJson($detail)->assertExactJson(['id' => 10, 'access_state' => $state, 'access_error' => $message]); + $this->postJson($submit, $payload)->assertJsonPath('access_state', $state)->assertJsonPath('access_error', $message); + $this->assertSame($original, DB::table('course_content_evaluation_forms')->where('id', $replyId)->value('data')); + $this->assertSame(1, DB::table('course_content_evaluation_forms')->count()); + } + DB::table('course_content_evaluations')->where('id', 10)->update(['status' => 1, 'start_time' => '2026-10-22 12:00:00', 'end_time' => null]); + $this->getJson($detail)->assertJsonPath('my_response.questions.0.id', $id); + $this->postJson($submit, $payload)->assertJsonPath('id', $replyId); + } finally { + \Illuminate\Support\Carbon::setTestNow(); + } + } + public function testAudienceAndDeadlineProtectEntryAndSubmission(): void { Schema::create('courses', function (Blueprint $table) { $table->id(); $table->softDeletes(); }); @@ -302,8 +336,8 @@ class SurveyWorkflowTest extends TestCase $replyId = $this->postJson($submit, $payload)->assertOk()->json('id'); $this->assertNotNull($replyId); DB::table('course_content_evaluations')->where('id', 10)->update(['end_time' => '2000-01-01 00:00:00']); - $this->getJson($detail)->assertJsonPath('access_error', '当前问卷已截止'); - $this->postJson($submit, $payload)->assertJsonPath('access_error', '当前问卷已截止'); + $this->getJson($detail)->assertJsonPath('access_state', 'ended')->assertJsonPath('access_error', '该问卷已结束。'); + $this->postJson($submit, $payload)->assertJsonPath('access_state', 'ended')->assertJsonPath('access_error', '该问卷已结束。'); $this->assertSame(1, DB::table('course_content_evaluation_forms')->count()); DB::table('course_content_evaluations')->where('id', 10)->update(['end_time' => null]); $this->postJson('/api/admin/course-content-evaluations/save', ['id' => 10, 'audience_course_ids' => []])->assertJsonPath('audience_course_ids', []); @@ -392,6 +426,8 @@ class SurveyWorkflowTest extends TestCase ])->assertOk(); DB::table('course_content_evaluations')->where('id', 10)->update(['title' => '新标题', 'status' => 0]); DB::table('course_content_evaluation_asks')->where('id', $id)->update(['name' => '新题目']); + $this->getJson($url)->assertExactJson(['id' => 10, 'access_state' => 'draft', 'access_error' => '该问卷还未开始。']); + DB::table('course_content_evaluations')->where('id', 10)->update(['status' => 1]); $this->getJson($url)->assertJsonPath('my_response.title', '培训问卷') ->assertJsonPath('my_response.questions.0.name', '融资对接') ->assertJsonPath('my_response.questions.0.value.count', 0) @@ -415,7 +451,7 @@ class SurveyWorkflowTest extends TestCase $this->postJson('/api/mobile/course/course-content-form', $payload)->assertJsonPath('errcode', 10001); $this->getJson('/api/mobile/course/evaluation-detail?course_content_evaluation_id=10')->assertJsonPath('my_response.questions.0.value.count', 8); DB::table('course_content_evaluations')->where('id', 10)->update(['end_time' => '2020-01-01 00:00:00']); - $this->postJson('/api/mobile/course/course-content-form', $payload)->assertJsonPath('access_error', '当前问卷已截止'); + $this->postJson('/api/mobile/course/course-content-form', $payload)->assertJsonPath('access_error', '该问卷已结束。'); DB::table('course_content_evaluations')->where('id', 10)->update(['end_time' => null]); $guest = new User(); $guest->forceFill(['id' => 201]);