From 9ffd5d942ae7c606ccf08e7e05a8df9548c9c16e Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Sat, 18 May 2024 14:53:30 +0800 Subject: [PATCH] task basic --- .../Resources/System/ExamResource.php | 18 ++++++++++ .../User/UserResource/Pages/UserProfile.php | 1 + app/Models/Exam.php | 20 ++++++++++- app/Repositories/ExamRepository.php | 35 ++++++++++++------- ...5_033436_add_field_type_to_exams_table.php | 34 ++++++++++++++++++ resources/lang/en/admin.php | 2 +- resources/lang/en/exam.php | 10 +++++- resources/lang/zh_CN/admin.php | 2 +- resources/lang/zh_CN/exam.php | 11 +++++- resources/lang/zh_TW/admin.php | 2 +- resources/lang/zh_TW/exam.php | 10 +++++- 11 files changed, 125 insertions(+), 20 deletions(-) create mode 100644 database/migrations/2024_05_15_033436_add_field_type_to_exams_table.php diff --git a/app/Filament/Resources/System/ExamResource.php b/app/Filament/Resources/System/ExamResource.php index c0d53b51..cb806c00 100644 --- a/app/Filament/Resources/System/ExamResource.php +++ b/app/Filament/Resources/System/ExamResource.php @@ -48,6 +48,22 @@ class ExamResource extends Resource ->schema([ Forms\Components\Section::make(__('label.exam.section_base_info'))->schema([ Forms\Components\TextInput::make('name')->required()->columnSpan(['sm' => 2])->label(__('label.name')), + Forms\Components\Select::make('type') + ->required()->columnSpan(['sm' => 2]) + ->label(__('exam.type')) + ->options(Exam::listTypeOptions()) + ->helperText(__('exam.type_help')) + ->reactive() + , + Forms\Components\TextInput::make('success_reward_bonus') + ->label(__('exam.success_reward_bonus')) + ->hidden(fn (\Closure $get) => $get('type') != Exam::TYPE_TASK) + , + Forms\Components\TextInput::make('fail_deduct_bonus') + ->label(__('exam.fail_deduct_bonus')) + ->hidden(fn (\Closure $get) => $get('type') != Exam::TYPE_TASK) + , + Forms\Components\Repeater::make('indexes')->schema([ Forms\Components\Select::make('index') ->options(Exam::listIndex(true)) @@ -124,6 +140,7 @@ class ExamResource extends Resource ->columns([ Tables\Columns\TextColumn::make('id')->sortable(), Tables\Columns\TextColumn::make('name')->searchable()->label(__('label.name')), + Tables\Columns\TextColumn::make('typeText')->label(__('exam.type')), Tables\Columns\TextColumn::make('indexFormatted')->label(__('label.exam.index_formatted'))->html(), Tables\Columns\TextColumn::make('begin')->label(__('label.begin')), Tables\Columns\TextColumn::make('end')->label(__('label.end')), @@ -136,6 +153,7 @@ class ExamResource extends Resource ]) ->defaultSort('id', 'desc') ->filters([ + Tables\Filters\SelectFilter::make('type')->options(Exam::listTypeOptions())->label(__("exam.type")), Tables\Filters\SelectFilter::make('is_discovered')->options(self::IS_DISCOVERED_OPTIONS)->label(__("label.exam.is_discovered")), Tables\Filters\SelectFilter::make('status')->options(self::getEnableDisableOptions())->label(__("label.status")), ]) diff --git a/app/Filament/Resources/User/UserResource/Pages/UserProfile.php b/app/Filament/Resources/User/UserResource/Pages/UserProfile.php index 4258ba32..c6b4107b 100644 --- a/app/Filament/Resources/User/UserResource/Pages/UserProfile.php +++ b/app/Filament/Resources/User/UserResource/Pages/UserProfile.php @@ -4,6 +4,7 @@ namespace App\Filament\Resources\User\UserResource\Pages; use App\Filament\OptionsTrait; use App\Filament\Resources\User\UserResource; +use App\Models\Exam; use App\Models\Invite; use App\Models\Medal; use App\Models\User; diff --git a/app/Models/Exam.php b/app/Models/Exam.php index c8e57b13..e5dd3147 100644 --- a/app/Models/Exam.php +++ b/app/Models/Exam.php @@ -11,7 +11,7 @@ class Exam extends NexusModel { protected $fillable = [ 'name', 'description', 'begin', 'end', 'duration', 'status', 'is_discovered', 'filters', 'indexes', 'priority', - 'recurring', + 'recurring', 'type', 'success_reward_bonus', 'fail_deduct_bonus' ]; public $timestamps = true; @@ -69,6 +69,9 @@ class Exam extends NexusModel const RECURRING_WEEKLY = "Weekly"; const RECURRING_MONTHLY = "Monthly"; + const TYPE_EXAM = 1; + const TYPE_TASK = 2; + protected static function booted() { static::saving(function (Model $model) { @@ -99,6 +102,21 @@ class Exam extends NexusModel self::RECURRING_MONTHLY => nexus_trans("exam.recurring_monthly"), ]; } + + public static function listTypeOptions(): array + { + return [ + self::TYPE_EXAM => nexus_trans("exam.type_exam"), + self::TYPE_TASK => nexus_trans("exam.type_task"), + ]; + } + + public function getTypeTextAttribute() + { + return self::listTypeOptions()[$this->type] ?? ""; + } + + protected function getRecurringTextAttribute(): string { $options = self::listRecurringOptions(); diff --git a/app/Repositories/ExamRepository.php b/app/Repositories/ExamRepository.php index 3f6b9768..a2fd842a 100644 --- a/app/Repositories/ExamRepository.php +++ b/app/Repositories/ExamRepository.php @@ -241,7 +241,7 @@ class ExamRepository extends BaseRepository * @param null $excludeId * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection */ - public function listValid($excludeId = null, $isDiscovered = null) + public function listValid($excludeId = null, $isDiscovered = null, $type = null) { $now = Carbon::now(); $query = Exam::query() @@ -255,6 +255,9 @@ class ExamRepository extends BaseRepository if (!is_null($isDiscovered)) { $query->where('is_discovered', $isDiscovered); } + if (!is_null($type)) { + $query->where("type", $type); + } return $query->orderBy('priority', 'desc')->orderBy('id', 'asc')->get(); } @@ -266,19 +269,25 @@ class ExamRepository extends BaseRepository */ public function listMatchExam($uid) { - $logPrefix = "uid: $uid"; - $exams = $this->listValid(); - if ($exams->isEmpty()) { - do_log("$logPrefix, no valid exam."); - return $exams; - } - $matched = $exams->filter(function (Exam $exam) use ($uid, $logPrefix) { - return $this->isExamMatchUser($exam, $uid); - }); - - return $matched; + $exams = $this->listValid(null, null, Exam::TYPE_EXAM); + return $this->filterForUser($exams, $uid); } + public function listMatchTask($uid) + { + $exams = $this->listValid(null, null, Exam::TYPE_TASK); + return $this->filterForUser($exams, $uid); + } + + private function filterForUser(Collection $exams, $uid): Collection + { + $userInfo = User::query()->findOrFail($uid, User::$commonFields); + return $exams->filter(function (Exam $exam) use ($userInfo) { + return $this->isExamMatchUser($exam, $userInfo); + }); + } + + private function isExamMatchUser(Exam $exam, $user): bool { if (!$user instanceof User) { @@ -917,7 +926,7 @@ class ExamRepository extends BaseRepository public function cronjonAssign() { - $exams = $this->listValid(null, Exam::DISCOVERED_YES); + $exams = $this->listValid(null, Exam::DISCOVERED_YES, Exam::TYPE_EXAM); if ($exams->isEmpty()) { do_log("No valid and discovered exam."); return false; diff --git a/database/migrations/2024_05_15_033436_add_field_type_to_exams_table.php b/database/migrations/2024_05_15_033436_add_field_type_to_exams_table.php new file mode 100644 index 00000000..cf170106 --- /dev/null +++ b/database/migrations/2024_05_15_033436_add_field_type_to_exams_table.php @@ -0,0 +1,34 @@ +integer("type")->default(\App\Models\Exam::TYPE_EXAM); + $table->integer("success_reward_bonus")->default(0); + $table->integer("fail_deduct_bonus")->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('exams', function (Blueprint $table) { + $table->dropColumn(["type", "success_reward_bonus", "fail_deduct_bonus"]); + }); + } +}; diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index 02c0d5e0..3ecb402d 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -8,7 +8,7 @@ return [ 'tags_list' => 'Tags', 'agent_allows' => 'Agent Allows', 'agent_denies' => 'Agent Denies', - 'exams_list' => 'Exams', + 'exams_list' => 'Exams & Tasks', 'medals_list' => 'Medals', 'settings' => 'Settings', 'users_medals' => 'User medals', diff --git a/resources/lang/en/exam.php b/resources/lang/en/exam.php index c4956d1c..9a963f5b 100644 --- a/resources/lang/en/exam.php +++ b/resources/lang/en/exam.php @@ -37,7 +37,15 @@ return [ 'recurring_daily' => 'once a day', 'recurring_weekly' => 'once a week', 'recurring_monthly' => 'once a month', - 'recurring_help' => 'If specified as periodic, the appraisal start time is the start time of the current cycle, and the end time is the end time of the current cycle, which is said to be the natural week/month. At the end of each cycle, if the user still meets the screening criteria, the user will be automatically assigned to the next cycle.' , + 'recurring_help' => 'If specified as periodic, the start time of the exam is the start time of the current cycle, and the end time is the end time of the current cycle, which are all natural days/weeks/months as stated here. If type is exam, at the end of each cycle, if the user still meets the screening criteria, the user will be automatically assigned an exam for the next cycle.' , 'time_condition_invalid' => 'The time parameter does not make sense, there are and only one of three items: start time + end time / duration / recurring', + + 'type_exam' => 'Exam', + 'type_task' => 'Task', + 'type' => 'Type', + 'type_help' => 'Exam are regular exam and failing them will result in account banning. Tasks can be set to reward bonus or deduct bonus depending on whether they are completed or not', + + 'fail_deduct_bonus' => 'Deduct bonus for task failure', + 'success_reward_bonus' => 'Reward bonus for task completion', ]; diff --git a/resources/lang/zh_CN/admin.php b/resources/lang/zh_CN/admin.php index 7d4f9b83..610581c6 100644 --- a/resources/lang/zh_CN/admin.php +++ b/resources/lang/zh_CN/admin.php @@ -8,7 +8,7 @@ return [ 'tags_list' => '标签', 'agent_allows' => '允许客户端', 'agent_denies' => '拒绝客户端', - 'exams_list' => '考核', + 'exams_list' => '考核 & 任务', 'medals_list' => '勋章', 'settings' => '设置', 'users_medals' => '用户勋章', diff --git a/resources/lang/zh_CN/exam.php b/resources/lang/zh_CN/exam.php index cf10cb34..07bf8098 100644 --- a/resources/lang/zh_CN/exam.php +++ b/resources/lang/zh_CN/exam.php @@ -37,7 +37,16 @@ return [ 'recurring_daily' => '每天一次', 'recurring_weekly' => '每周一次', 'recurring_monthly' => '每月一次', - 'recurring_help' => '如果指定为周期性,考核开始时间为当前周期的开始时间,结束时间为当前周期的结束时间,这里说的都是自然周/月。每个周期结束后,如果用户仍然满足筛选条件,会自动为用户分配下个周期的任务。', + 'recurring_help' => '如果指定为周期性,考核开始时间为当前周期的开始时间,结束时间为当前周期的结束时间,这里说的都是自然日/周/月。对于类型为考核的,每个周期结束后,如果用户仍然满足筛选条件,会自动为用户分配下个周期的考核。', 'time_condition_invalid' => '时间参数不合理,有且只有三项之一:开始时间+结束时间/时长/周期性', + + 'type_exam' => '考核', + 'type_task' => '任务', + 'type' => '类型', + 'type_help' => '考核是常规的考核,不通过会被封禁账号。任务可根据完成与否设置奖励魔力或扣除魔力', + + 'fail_deduct_bonus' => '任务失败扣除魔力', + 'success_reward_bonus' => '任务完成奖励魔力', + ]; diff --git a/resources/lang/zh_TW/admin.php b/resources/lang/zh_TW/admin.php index 3d67d0cb..c0c2ef37 100644 --- a/resources/lang/zh_TW/admin.php +++ b/resources/lang/zh_TW/admin.php @@ -8,7 +8,7 @@ return [ 'tags_list' => '標簽', 'agent_allows' => '允許客戶端', 'agent_denies' => '拒絕客戶端', - 'exams_list' => '考核', + 'exams_list' => '考核 & 任務', 'medals_list' => '勛章', 'settings' => '設置', 'users_medals' => '用戶勛章', diff --git a/resources/lang/zh_TW/exam.php b/resources/lang/zh_TW/exam.php index 5edfd152..c8ad4ec3 100644 --- a/resources/lang/zh_TW/exam.php +++ b/resources/lang/zh_TW/exam.php @@ -37,7 +37,15 @@ return [ 'recurring_daily' => '每天一次', 'recurring_weekly' => '每周一次', 'recurring_monthly' => '每月一次', - 'recurring_help' => '如果指定為周期性,考核開始時間為當前周期的開始時間,結束時間為當前周期的結束時間,這裏說的都是自然周/月。每個周期結束後,如果用戶仍然滿足篩選條件,會自動為用戶分配下個周期的任務。', + 'recurring_help' => '如果指定為周期性,考核開始時間為當前周期的開始時間,結束時間為當前周期的結束時間,這裏說的都是自然日/周/月。對於類型為考核的,每個周期結束後,如果用戶仍然滿足篩選條件,會自動為用戶分配下個周期的考核。', 'time_condition_invalid' => '時間參數不合理,有且只有三項之一:開始時間+結束時間/時長/周期性', + + 'type_exam' => '考核', + 'type_task' => '任务', + 'type' => '类型', + 'type_help' => '考核是常规的考核,不通过会被封禁账号。任务可根据完成与否设置奖励魔力或扣除魔力', + + 'fail_deduct_bonus' => '任务失败扣除魔力', + 'success_reward_bonus' => '任务完成奖励魔力', ];