master
lion 3 weeks ago
parent 464e5d68d2
commit 98bd3303bb

@ -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();

@ -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;
}

@ -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]);

Loading…
Cancel
Save