mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-24 03:57:22 +08:00
exam add duration
This commit is contained in:
@@ -54,6 +54,12 @@
|
|||||||
placeholder="Select End Time">
|
placeholder="Select End Time">
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="Duration" prop="duration">
|
||||||
|
<el-input v-model="formData.duration" type="number" placeholder=""></el-input>
|
||||||
|
<div style="color: #aaa">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.</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="Target User Class" prop="filters.classes">
|
<el-form-item label="Target User Class" prop="filters.classes">
|
||||||
<el-checkbox-group v-model="formData.filters.classes">
|
<el-checkbox-group v-model="formData.filters.classes">
|
||||||
<el-checkbox v-for="(item, index) in allClasses" :label="index" :key="index">{{item}}</el-checkbox>
|
<el-checkbox v-for="(item, index) in allClasses" :label="index" :key="index">{{item}}</el-checkbox>
|
||||||
@@ -109,6 +115,7 @@ export default {
|
|||||||
description: '',
|
description: '',
|
||||||
begin: '',
|
begin: '',
|
||||||
end: '',
|
end: '',
|
||||||
|
duration: '',
|
||||||
indexes: [],
|
indexes: [],
|
||||||
filters: {
|
filters: {
|
||||||
classes: [],
|
classes: [],
|
||||||
@@ -141,6 +148,7 @@ export default {
|
|||||||
state.formData.description = res.data.description
|
state.formData.description = res.data.description
|
||||||
state.formData.begin = res.data.begin
|
state.formData.begin = res.data.begin
|
||||||
state.formData.end = res.data.end
|
state.formData.end = res.data.end
|
||||||
|
state.formData.duration = res.data.duration
|
||||||
state.formData.indexes = res.data.indexes
|
state.formData.indexes = res.data.indexes
|
||||||
state.formData.filters = res.data.filters
|
state.formData.filters = res.data.filters
|
||||||
state.formData.status = res.data.status
|
state.formData.status = res.data.status
|
||||||
|
|||||||
@@ -50,6 +50,11 @@
|
|||||||
>
|
>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
prop="duration_text"
|
||||||
|
label="Duration"
|
||||||
|
></el-table-column>
|
||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="Target users"
|
label="Target users"
|
||||||
width="350px"
|
width="350px"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Models\ExamProgress;
|
|||||||
use App\Models\ExamUser;
|
use App\Models\ExamUser;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Repositories\ExamRepository;
|
use App\Repositories\ExamRepository;
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
@@ -57,6 +58,7 @@ class Test extends Command
|
|||||||
// $rep->cronjobCheckout();
|
// $rep->cronjobCheckout();
|
||||||
$r = DB::select(DB::raw('select version() as info'))[0]->info;
|
$r = DB::select(DB::raw('select version() as info'))[0]->info;
|
||||||
dd($r);
|
dd($r);
|
||||||
|
Carbon::now()->toDateTimeString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class ExamController extends Controller
|
|||||||
'name' => 'required|string',
|
'name' => 'required|string',
|
||||||
'indexes' => 'required|array|min:1',
|
'indexes' => 'required|array|min:1',
|
||||||
'status' => 'required|in:0,1',
|
'status' => 'required|in:0,1',
|
||||||
|
'duration' => 'numeric'
|
||||||
];
|
];
|
||||||
$request->validate($rules);
|
$request->validate($rules);
|
||||||
$result = $this->repository->store($request->all());
|
$result = $this->repository->store($request->all());
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ class ExamResource extends JsonResource
|
|||||||
'description' => $this->description,
|
'description' => $this->description,
|
||||||
'begin' => $this->begin,
|
'begin' => $this->begin,
|
||||||
'end' => $this->end,
|
'end' => $this->end,
|
||||||
|
'duration' => $this->duration,
|
||||||
|
'duration_text' => $this->duration_text,
|
||||||
'filters' => $this->filters,
|
'filters' => $this->filters,
|
||||||
'filters_formatted' => $this->formatFilters($this->resource),
|
'filters_formatted' => $this->formatFilters($this->resource),
|
||||||
'indexes' => $this->indexes,
|
'indexes' => $this->indexes,
|
||||||
|
|||||||
+6
-1
@@ -4,7 +4,7 @@ namespace App\Models;
|
|||||||
|
|
||||||
class Exam extends NexusModel
|
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;
|
public $timestamps = true;
|
||||||
|
|
||||||
@@ -59,4 +59,9 @@ class Exam extends NexusModel
|
|||||||
return self::$discovers[$this->is_discovered]['text'] ?? '';
|
return self::$discovers[$this->is_discovered]['text'] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDurationTextAttribute(): string
|
||||||
|
{
|
||||||
|
return $this->duration . ' Days';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-3
@@ -24,19 +24,58 @@ class ExamUser extends NexusModel
|
|||||||
'progress' => 'json'
|
'progress' => 'json'
|
||||||
];
|
];
|
||||||
|
|
||||||
public function getStatusTextAttribute()
|
public function getStatusTextAttribute(): string
|
||||||
{
|
{
|
||||||
return self::$status[$this->status]['text'] ?? '';
|
return self::$status[$this->status]['text'] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBeginAttribute()
|
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()
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -103,9 +103,8 @@ class ExamRepository extends BaseRepository
|
|||||||
{
|
{
|
||||||
$now = Carbon::now();
|
$now = Carbon::now();
|
||||||
$query = Exam::query()
|
$query = Exam::query()
|
||||||
->where('begin', '<=', $now)
|
|
||||||
->where('end', '>=', $now)
|
|
||||||
->where('status', Exam::STATUS_ENABLED)
|
->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');
|
->orderBy('id', 'desc');
|
||||||
if (!is_null($excludeId)) {
|
if (!is_null($excludeId)) {
|
||||||
$query->whereNotIn('id', Arr::wrap($excludeId));
|
$query->whereNotIn('id', Arr::wrap($excludeId));
|
||||||
@@ -130,7 +129,6 @@ class ExamRepository extends BaseRepository
|
|||||||
do_log("$logPrefix, no valid exam.");
|
do_log("$logPrefix, no valid exam.");
|
||||||
return $exams;
|
return $exams;
|
||||||
}
|
}
|
||||||
|
|
||||||
$matched = $exams->filter(function (Exam $exam) use ($uid, $logPrefix) {
|
$matched = $exams->filter(function (Exam $exam) use ($uid, $logPrefix) {
|
||||||
return $this->isExamMatchUser($exam, $uid);
|
return $this->isExamMatchUser($exam, $uid);
|
||||||
});
|
});
|
||||||
@@ -253,8 +251,12 @@ class ExamRepository extends BaseRepository
|
|||||||
if (!$exam) {
|
if (!$exam) {
|
||||||
throw new NexusException("exam: {$examUser->exam_id} not exists.");
|
throw new NexusException("exam: {$examUser->exam_id} not exists.");
|
||||||
}
|
}
|
||||||
$begin = $examUser->begin ?? $exam->begin;
|
$begin = $examUser->begin;
|
||||||
$end = $examUser->end ?? $exam->end;
|
$end = $examUser->end;
|
||||||
|
if (!$begin || !$end) {
|
||||||
|
do_log(sprintf("no begin or end, examUser: %s", $examUser->toJson()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($now < $begin || $now > $end) {
|
if ($now < $begin || $now > $end) {
|
||||||
do_log(sprintf("now: %s, not in exam time range: %s ~ %s", $now, $begin, $end));
|
do_log(sprintf("now: %s, not in exam time range: %s ~ %s", $now, $begin, $end));
|
||||||
return false;
|
return false;
|
||||||
@@ -331,10 +333,6 @@ class ExamRepository extends BaseRepository
|
|||||||
}
|
}
|
||||||
$examUser = $examUsers->first();
|
$examUser = $examUsers->first();
|
||||||
$exam = $examUser->exam;
|
$exam = $examUser->exam;
|
||||||
if (empty($examUser->begin) || empty($examUser->end)) {
|
|
||||||
$examUser->begin = $exam->begin;
|
|
||||||
$examUser->end = $exam->end;
|
|
||||||
}
|
|
||||||
$progress = $this->calculateProgress($examUser);
|
$progress = $this->calculateProgress($examUser);
|
||||||
do_log("$logPrefix, progress: " . nexus_json_encode($progress));
|
do_log("$logPrefix, progress: " . nexus_json_encode($progress));
|
||||||
$examUser->progress = $progress;
|
$examUser->progress = $progress;
|
||||||
@@ -344,25 +342,14 @@ class ExamRepository extends BaseRepository
|
|||||||
|
|
||||||
private function calculateProgress(ExamUser $examUser)
|
private function calculateProgress(ExamUser $examUser)
|
||||||
{
|
{
|
||||||
$exam = $examUser->exam;
|
|
||||||
$logPrefix = "examUser: " . $examUser->id;
|
$logPrefix = "examUser: " . $examUser->id;
|
||||||
if ($examUser->begin) {
|
$begin = $examUser->begin;
|
||||||
$logPrefix .= ", begin from examUser: " . $examUser->id;
|
$end = $examUser->end;
|
||||||
$begin = $examUser->begin;
|
if (!$begin) {
|
||||||
} elseif ($exam->begin) {
|
|
||||||
$logPrefix .= ", begin from exam: " . $exam->id;
|
|
||||||
$begin = $exam->begin;
|
|
||||||
} else {
|
|
||||||
do_log("$logPrefix, no begin");
|
do_log("$logPrefix, no begin");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ($examUser->end) {
|
if (!$end) {
|
||||||
$logPrefix .= ", end from examUser: " . $examUser->id;
|
|
||||||
$end = $examUser->end;
|
|
||||||
} elseif ($exam->end) {
|
|
||||||
$logPrefix .= ", end from exam: " . $exam->id;
|
|
||||||
$end = $exam->end;
|
|
||||||
} else {
|
|
||||||
do_log("$logPrefix, no end");
|
do_log("$logPrefix, no end");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -507,7 +494,8 @@ class ExamRepository extends BaseRepository
|
|||||||
->with(['exam', 'user', 'user.language'])
|
->with(['exam', 'user', 'user.language'])
|
||||||
->orderBy("$examUserTable.id", "asc");
|
->orderBy("$examUserTable.id", "asc");
|
||||||
if (!$ignoreTimeRange) {
|
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;
|
$size = 100;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class CreateExamsTable extends Migration
|
|||||||
$table->text('description')->nullable();
|
$table->text('description')->nullable();
|
||||||
$table->dateTime('begin')->nullable();
|
$table->dateTime('begin')->nullable();
|
||||||
$table->dateTime('end')->nullable();
|
$table->dateTime('end')->nullable();
|
||||||
|
$table->integer('duration')->default(0);
|
||||||
$table->text('filters')->nullable();
|
$table->text('filters')->nullable();
|
||||||
$table->text('indexes');
|
$table->text('indexes');
|
||||||
$table->tinyInteger('status')->default(0);
|
$table->tinyInteger('status')->default(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user