From 05fb848fc53254e3f79ce6a1dd9a04dfd03ff6cf Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Thu, 6 May 2021 01:49:05 +0800 Subject: [PATCH] exam add duration --- admin/src/views/exam/form.vue | 8 ++++ admin/src/views/exam/index.vue | 5 +++ app/Console/Commands/Test.php | 2 + app/Http/Controllers/ExamController.php | 1 + app/Http/Resources/ExamResource.php | 2 + app/Models/Exam.php | 7 ++- app/Models/ExamUser.php | 45 +++++++++++++++++-- app/Repositories/ExamRepository.php | 38 ++++++---------- .../2021_04_19_061650_create_exams_table.php | 1 + 9 files changed, 80 insertions(+), 29 deletions(-) diff --git a/admin/src/views/exam/form.vue b/admin/src/views/exam/form.vue index 8b33b555..d8eb1ab0 100644 --- a/admin/src/views/exam/form.vue +++ b/admin/src/views/exam/form.vue @@ -54,6 +54,12 @@ placeholder="Select End Time"> + + + +
Unit: days. When assign to user, begin and end are used if they are specified. Otherwise begin time is the time at assignment, and the end time is the time at assignment plus the duration.
+
+ {{item}} @@ -109,6 +115,7 @@ export default { description: '', begin: '', end: '', + duration: '', indexes: [], filters: { classes: [], @@ -141,6 +148,7 @@ export default { state.formData.description = res.data.description state.formData.begin = res.data.begin state.formData.end = res.data.end + state.formData.duration = res.data.duration state.formData.indexes = res.data.indexes state.formData.filters = res.data.filters state.formData.status = res.data.status diff --git a/admin/src/views/exam/index.vue b/admin/src/views/exam/index.vue index 87b01a3f..a6e9abf8 100644 --- a/admin/src/views/exam/index.vue +++ b/admin/src/views/exam/index.vue @@ -50,6 +50,11 @@ > + + cronjobCheckout(); $r = DB::select(DB::raw('select version() as info'))[0]->info; dd($r); + Carbon::now()->toDateTimeString(); } } diff --git a/app/Http/Controllers/ExamController.php b/app/Http/Controllers/ExamController.php index 974bbbf2..cb291fbc 100644 --- a/app/Http/Controllers/ExamController.php +++ b/app/Http/Controllers/ExamController.php @@ -44,6 +44,7 @@ class ExamController extends Controller 'name' => 'required|string', 'indexes' => 'required|array|min:1', 'status' => 'required|in:0,1', + 'duration' => 'numeric' ]; $request->validate($rules); $result = $this->repository->store($request->all()); diff --git a/app/Http/Resources/ExamResource.php b/app/Http/Resources/ExamResource.php index 9ed278ac..18263afb 100644 --- a/app/Http/Resources/ExamResource.php +++ b/app/Http/Resources/ExamResource.php @@ -23,6 +23,8 @@ class ExamResource extends JsonResource 'description' => $this->description, 'begin' => $this->begin, 'end' => $this->end, + 'duration' => $this->duration, + 'duration_text' => $this->duration_text, 'filters' => $this->filters, 'filters_formatted' => $this->formatFilters($this->resource), 'indexes' => $this->indexes, diff --git a/app/Models/Exam.php b/app/Models/Exam.php index c520abee..b8d307c1 100644 --- a/app/Models/Exam.php +++ b/app/Models/Exam.php @@ -4,7 +4,7 @@ namespace App\Models; class Exam extends NexusModel { - protected $fillable = ['name', 'description', 'begin', 'end', 'status', 'is_discovered', 'filters', 'indexes']; + protected $fillable = ['name', 'description', 'begin', 'end', 'duration', 'status', 'is_discovered', 'filters', 'indexes']; public $timestamps = true; @@ -59,4 +59,9 @@ class Exam extends NexusModel return self::$discovers[$this->is_discovered]['text'] ?? ''; } + public function getDurationTextAttribute(): string + { + return $this->duration . ' Days'; + } + } diff --git a/app/Models/ExamUser.php b/app/Models/ExamUser.php index 031ee86b..31bacdcb 100644 --- a/app/Models/ExamUser.php +++ b/app/Models/ExamUser.php @@ -24,19 +24,58 @@ class ExamUser extends NexusModel 'progress' => 'json' ]; - public function getStatusTextAttribute() + public function getStatusTextAttribute(): string { return self::$status[$this->status]['text'] ?? ''; } public function getBeginAttribute() { - return $this->begin ?? $this->exam->begin; + $begin = $this->getRawOriginal('begin'); + $end = $this->getRawOriginal('end'); + if ($begin && $end) { + do_log(sprintf('examUser: %s, begin from self', $this->id)); + return $begin; + } + + $exam = $this->exam; + $begin = $exam->getRawOriginal('begin'); + $end = $exam->getRawOriginal('end'); + if ($begin && $end) { + do_log(sprintf('examUser: %s, begin from exam: %s', $this->id, $exam->id)); + return $begin; + } + + if ($exam->duration > 0) { + do_log(sprintf('examUser: %s, begin from self created_at', $this->id)); + return $this->created_at->toDateTimeString(); + } + return null; } public function getEndAttribute() { - return $this->end ?? $this->exam->end; + $begin = $this->getRawOriginal('begin'); + $end = $this->getRawOriginal('end'); + if ($begin && $end) { + do_log(sprintf('examUser: %s, end from self', $this->id)); + return $end; + } + + $exam = $this->exam; + $begin = $exam->getRawOriginal('begin'); + $end = $exam->getRawOriginal('end'); + if ($begin && $end) { + do_log(sprintf('examUser: %s, end from exam: %s', $this->id, $exam->id)); + return $end; + } + + $duration = $exam->duration; + if ($duration > 0) { + do_log(sprintf('examUser: %s, end from self created_at + exam: %s %s days', $this->id, $exam->id, $duration)); + return $this->created_at->addDays($duration)->toDateTimeString(); + } + return null; } diff --git a/app/Repositories/ExamRepository.php b/app/Repositories/ExamRepository.php index 5415ef24..8cf616ef 100644 --- a/app/Repositories/ExamRepository.php +++ b/app/Repositories/ExamRepository.php @@ -103,9 +103,8 @@ class ExamRepository extends BaseRepository { $now = Carbon::now(); $query = Exam::query() - ->where('begin', '<=', $now) - ->where('end', '>=', $now) ->where('status', Exam::STATUS_ENABLED) + ->whereRaw("if(begin is not null and end is not null, begin <= '$now' and end >= '$now', duration > 0)") ->orderBy('id', 'desc'); if (!is_null($excludeId)) { $query->whereNotIn('id', Arr::wrap($excludeId)); @@ -130,7 +129,6 @@ class ExamRepository extends BaseRepository do_log("$logPrefix, no valid exam."); return $exams; } - $matched = $exams->filter(function (Exam $exam) use ($uid, $logPrefix) { return $this->isExamMatchUser($exam, $uid); }); @@ -253,8 +251,12 @@ class ExamRepository extends BaseRepository if (!$exam) { throw new NexusException("exam: {$examUser->exam_id} not exists."); } - $begin = $examUser->begin ?? $exam->begin; - $end = $examUser->end ?? $exam->end; + $begin = $examUser->begin; + $end = $examUser->end; + if (!$begin || !$end) { + do_log(sprintf("no begin or end, examUser: %s", $examUser->toJson())); + return false; + } if ($now < $begin || $now > $end) { do_log(sprintf("now: %s, not in exam time range: %s ~ %s", $now, $begin, $end)); return false; @@ -331,10 +333,6 @@ class ExamRepository extends BaseRepository } $examUser = $examUsers->first(); $exam = $examUser->exam; - if (empty($examUser->begin) || empty($examUser->end)) { - $examUser->begin = $exam->begin; - $examUser->end = $exam->end; - } $progress = $this->calculateProgress($examUser); do_log("$logPrefix, progress: " . nexus_json_encode($progress)); $examUser->progress = $progress; @@ -344,25 +342,14 @@ class ExamRepository extends BaseRepository private function calculateProgress(ExamUser $examUser) { - $exam = $examUser->exam; $logPrefix = "examUser: " . $examUser->id; - if ($examUser->begin) { - $logPrefix .= ", begin from examUser: " . $examUser->id; - $begin = $examUser->begin; - } elseif ($exam->begin) { - $logPrefix .= ", begin from exam: " . $exam->id; - $begin = $exam->begin; - } else { + $begin = $examUser->begin; + $end = $examUser->end; + if (!$begin) { do_log("$logPrefix, no begin"); return null; } - if ($examUser->end) { - $logPrefix .= ", end from examUser: " . $examUser->id; - $end = $examUser->end; - } elseif ($exam->end) { - $logPrefix .= ", end from exam: " . $exam->id; - $end = $exam->end; - } else { + if (!$end) { do_log("$logPrefix, no end"); return null; } @@ -507,7 +494,8 @@ class ExamRepository extends BaseRepository ->with(['exam', 'user', 'user.language']) ->orderBy("$examUserTable.id", "asc"); if (!$ignoreTimeRange) { - $baseQuery->whereRaw("if($examUserTable.end is not null, $examUserTable.end < '$now', $examTable.end < '$now')"); +// $baseQuery->whereRaw("if($examUserTable.end is not null, $examUserTable.end < '$now', $examTable.end < '$now')"); + $baseQuery->whereRaw("case when $examUserTable.end is not null then $examUserTable.end < '$now' case when $examTable.end is not null then $examTable.end < '$now' case when $examTable.duration > 0 then date_add($examUserTable.created_at, interval $examTable.duration day) < '$now' else true end"); } $size = 100; diff --git a/database/migrations/2021_04_19_061650_create_exams_table.php b/database/migrations/2021_04_19_061650_create_exams_table.php index 17fab1cb..09ae6026 100644 --- a/database/migrations/2021_04_19_061650_create_exams_table.php +++ b/database/migrations/2021_04_19_061650_create_exams_table.php @@ -19,6 +19,7 @@ class CreateExamsTable extends Migration $table->text('description')->nullable(); $table->dateTime('begin')->nullable(); $table->dateTime('end')->nullable(); + $table->integer('duration')->default(0); $table->text('filters')->nullable(); $table->text('indexes'); $table->tinyInteger('status')->default(0);