task basic

This commit is contained in:
xiaomlove
2024-05-18 14:53:30 +08:00
parent fc2aaf802b
commit 9ffd5d942a
11 changed files with 125 additions and 20 deletions

View File

@@ -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")),
])

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('exams', function (Blueprint $table) {
$table->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"]);
});
}
};

View File

@@ -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',

View File

@@ -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',
];

View File

@@ -8,7 +8,7 @@ return [
'tags_list' => '标签',
'agent_allows' => '允许客户端',
'agent_denies' => '拒绝客户端',
'exams_list' => '考核',
'exams_list' => '考核 & 任务',
'medals_list' => '勋章',
'settings' => '设置',
'users_medals' => '用户勋章',

View File

@@ -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' => '任务完成奖励魔力',
];

View File

@@ -8,7 +8,7 @@ return [
'tags_list' => '標簽',
'agent_allows' => '允許客戶端',
'agent_denies' => '拒絕客戶端',
'exams_list' => '考核',
'exams_list' => '考核 & 任務',
'medals_list' => '勛章',
'settings' => '設置',
'users_medals' => '用戶勛章',

View File

@@ -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' => '任务完成奖励魔力',
];