From c9bccd7123fcd6fc1e7f14edf84ea708216f406b Mon Sep 17 00:00:00 2001 From: Jing Li Date: Sat, 20 Apr 2024 20:29:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=88=91=E7=9A=84=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Admin/Controllers/Plan/PlanController.php | 5 +- app/Admin/Controllers/Plan/TaskController.php | 2 +- app/Enums/TaskHygieneStatus.php | 42 ++++++++++ app/Enums/TaskLedgerStatus.php | 2 +- app/Enums/TaskPerformanceStatus.php | 2 +- app/Http/Controllers/Api/TaskController.php | 77 ++++++++++++++++++- app/Http/Resources/TaskHygieneResource.php | 1 + app/Models/TaskHygiene.php | 39 ++++++++++ app/Models/TaskLedger.php | 22 +++--- app/Models/TaskPerformance.php | 20 ++--- app/Traits/HasCheckable.php | 20 +++-- database/seeders/WorkflowSeeder.php | 1 + lang/zh_CN/plan.php | 2 +- routes/api.php | 4 +- 14 files changed, 204 insertions(+), 35 deletions(-) create mode 100644 app/Enums/TaskHygieneStatus.php diff --git a/app/Admin/Controllers/Plan/PlanController.php b/app/Admin/Controllers/Plan/PlanController.php index 02f10a4..7314f26 100644 --- a/app/Admin/Controllers/Plan/PlanController.php +++ b/app/Admin/Controllers/Plan/PlanController.php @@ -5,6 +5,7 @@ namespace App\Admin\Controllers\Plan; use App\Admin\Controllers\AdminController; use App\Admin\Services\Plan\PlanService; use App\Enums\PlanStatus; +use App\Enums\TaskHygieneStatus; use App\Enums\TaskLedgerStatus; use App\Enums\TaskPerformanceStatus; use App\Enums\TaskStatus; @@ -246,12 +247,10 @@ class PlanController extends AdminController amis('reload')->align('right'), ]) ->columns([ - // amis()->TableColumn('id', __('plan.task.id')), - // amis()->TableColumn('name', __('plan.task.name')), amis()->TableColumn('taskable.month', __('plan.task_hygiene.month')), amis()->TableColumn('taskable.store.title', __('plan.task_hygiene.store')), amis()->TableColumn('taskable.store_master.name', __('plan.task_hygiene.store_master')), - amis()->TableColumn('task_status', __('plan.task.status'))->type('mapping')->map(TaskStatus::labelMap()), + amis()->TableColumn('taskable.task_status', __('plan.task_hygiene.status'))->type('mapping')->map(TaskHygieneStatus::labelMap()), amis()->TableColumn('completed_at', __('plan.task.completed_at')), amis()->TableColumn('created_at', __('plan.task.created_at')), $this->rowActions([ diff --git a/app/Admin/Controllers/Plan/TaskController.php b/app/Admin/Controllers/Plan/TaskController.php index d089015..799da74 100644 --- a/app/Admin/Controllers/Plan/TaskController.php +++ b/app/Admin/Controllers/Plan/TaskController.php @@ -27,7 +27,7 @@ class TaskController extends AdminController $morphTo->morphWith([ TaskLedger::class => ['store', 'storeMaster'], TaskPerformance::class => ['store', 'storeMaster'], - TaskHygiene::class => ['store', 'storeMaster'], + TaskHygiene::class => ['store', 'storeMaster', 'workflow'], ]); }, ]) diff --git a/app/Enums/TaskHygieneStatus.php b/app/Enums/TaskHygieneStatus.php new file mode 100644 index 0000000..f044a2d --- /dev/null +++ b/app/Enums/TaskHygieneStatus.php @@ -0,0 +1,42 @@ +value]; + } + + public static function options(): array + { + return [ + self::None->value => '未开始', + self::Pending->value => '待完成', + self::Checking->value => '审核中', + self::Unpassed->value => '未通过', + self::Success->value => '已完成', + self::Failed->value => '未完成', + ]; + } + + public static function labelMap(): array + { + return [ + self::None->value => ''.self::None->text().'', + self::Pending->value => ''.self::Pending->text().'', + self::Checking->value => ''.self::Checking->text().'', + self::Unpassed->value => ''.self::Unpassed->text().'', + self::Success->value => ''.self::Success->text().'', + self::Failed->value => ''.self::Failed->text().'', + ]; + } +} diff --git a/app/Enums/TaskLedgerStatus.php b/app/Enums/TaskLedgerStatus.php index 3bc9abe..3b3da0b 100644 --- a/app/Enums/TaskLedgerStatus.php +++ b/app/Enums/TaskLedgerStatus.php @@ -27,7 +27,7 @@ enum TaskLedgerStatus: int public static function labelMap(): array { return [ - self::None->value => ''.self::None->text().'', + self::None->value => ''.self::None->text().'', self::Pending->value => ''.self::Pending->text().'', self::Success->value => ''.self::Success->text().'', self::Failed->value => ''.self::Failed->text().'', diff --git a/app/Enums/TaskPerformanceStatus.php b/app/Enums/TaskPerformanceStatus.php index ca6b218..e819028 100644 --- a/app/Enums/TaskPerformanceStatus.php +++ b/app/Enums/TaskPerformanceStatus.php @@ -27,7 +27,7 @@ enum TaskPerformanceStatus: int public static function labelMap(): array { return [ - self::None->value => ''.self::None->text().'', + self::None->value => ''.self::None->text().'', self::Pending->value => ''.self::Pending->text().'', self::Success->value => ''.self::Success->text().'', self::Failed->value => ''.self::Failed->text().'', diff --git a/app/Http/Controllers/Api/TaskController.php b/app/Http/Controllers/Api/TaskController.php index 46a20e6..67117d9 100644 --- a/app/Http/Controllers/Api/TaskController.php +++ b/app/Http/Controllers/Api/TaskController.php @@ -2,13 +2,19 @@ namespace App\Http\Controllers\Api; +use App\Admin\Services\WorkFlowService; +use App\Enums\TaskHygieneStatus; +use App\Exceptions\RuntimeException; use App\Http\Resources\TaskResource; use App\Models\Task; use App\Models\TaskHygiene; use App\Models\TaskLedger; use Illuminate\Contracts\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\MorphTo; +use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use Throwable; class TaskController extends Controller { @@ -25,7 +31,14 @@ class TaskController extends Controller MySQL; /** @var \Illuminate\Database\Eloquent\Collection */ - $tasks = Task::with(['taskable']) + $tasks = Task::with([ + 'taskable' => function (MorphTo $morphTo) { + $morphTo->morphWith([ + TaskHygiene::class => ['task', 'workflow'], + TaskLedger::class => ['task'], + ]); + }, + ]) ->whereHasMorph( 'taskable', [TaskHygiene::class, TaskLedger::class], @@ -49,4 +62,66 @@ MySQL; return TaskResource::collection($tasks); } + + public function submit($id, Request $request) + { + $task = Task::findOrFail($id); + + try { + DB::beginTransaction(); + + $this->handleTaskSubmit($task, $request); + + DB::commit(); + } catch (Throwable $th) { + DB::rollBack(); + throw tap($th, fn ($th) => report($th)); + } + + return response()->json(); + } + + protected function handleTaskSubmit(Task $task, Request $request): void + { + /** @var \App\Models\Employee */ + $user = $request->user(); + + switch (Relation::getMorphedModel($task->taskable_type)) { + case TaskHygiene::class: + $request->validate( + rules: [ + 'task_hygiene.description' => ['bail', 'required', 'max:255'], + 'task_hygiene.photos' => ['bail', 'required', 'array'], + ], + attributes: [ + 'task_hygiene.description' => '清洁范围', + 'task_hygiene.photos' => '清洁结果', + ], + ); + + switch ($task->taskable->task_status) { + case TaskHygieneStatus::None: + throw new RuntimeException('任务未开始'); + break; + + case TaskHygieneStatus::Checking: + throw new RuntimeException('任务审核中'); + break; + + case TaskHygieneStatus::Success: + throw new RuntimeException('任务已完成'); + break; + } + + $task->taskable->update($request->input('task_hygiene')); + + (new WorkFlowService())->apply($task->taskable->workflow, $user); + + break; + + default: + throw new RuntimeException('任务不可提交'); + break; + } + } } diff --git a/app/Http/Resources/TaskHygieneResource.php b/app/Http/Resources/TaskHygieneResource.php index dd69d58..1d7c8a0 100644 --- a/app/Http/Resources/TaskHygieneResource.php +++ b/app/Http/Resources/TaskHygieneResource.php @@ -20,6 +20,7 @@ class TaskHygieneResource extends JsonResource 'store' => StoreResource::make($this->whenLoaded('store')), 'description' => $this->resource->description, 'photos' => $this->resource->photos, + 'status' => $this->resource->task_status, 'created_at' => $this->resource->created_at->timestamp, ]; } diff --git a/app/Models/TaskHygiene.php b/app/Models/TaskHygiene.php index b76213d..3864cf9 100644 --- a/app/Models/TaskHygiene.php +++ b/app/Models/TaskHygiene.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enums\TaskHygieneStatus; use App\Traits\HasCheckable; use App\Traits\HasDateTimeFormatter; use Illuminate\Database\Eloquent\Casts\Attribute; @@ -14,6 +15,10 @@ class TaskHygiene extends Model { use HasCheckable, HasFactory, HasDateTimeFormatter; + protected $appends = [ + 'task_status', + ]; + protected $fillable = [ 'month', 'store_id', @@ -50,4 +55,38 @@ class TaskHygiene extends Model set: fn (mixed $value) => json_encode(is_array($value) ? $value : []), ); } + + /** + * 任务状态 + */ + protected function taskStatus(): Attribute + { + return Attribute::make( + get: function (mixed $value) { + $datetime = now(); + + if ($datetime->lt($this->task->start_at)) { + return TaskHygieneStatus::None; + } + + if ($this->task->isSuccess() || $this->checkSuccess()) { + return TaskHygieneStatus::Success; + } + + if ($this->checkProcessing()) { + return TaskHygieneStatus::Checking; + } + + if ($this->checkFail()) { + return TaskHygieneStatus::Unpassed; + } + + if ($datetime->lt($this->task->end_at)) { + return TaskHygieneStatus::Pending; + } + + return TaskHygieneStatus::Failed; + }, + ); + } } diff --git a/app/Models/TaskLedger.php b/app/Models/TaskLedger.php index 4fcc565..358ff31 100644 --- a/app/Models/TaskLedger.php +++ b/app/Models/TaskLedger.php @@ -45,22 +45,22 @@ class TaskLedger extends Model protected function taskStatus(): Attribute { return Attribute::make( - get: function (mixed $value, array $attributes) { - /** @var \App\Models\Task */ - $task = $this->task; + get: function (mixed $value) { + $datetime = now(); - if ($task->isSuccess()) { + if ($datetime->lt($this->task->start_at)) { + return TaskLedgerStatus::None; + } + + if ($this->task->isSuccess()) { return TaskLedgerStatus::Success; } - $datetime = now(); - - if ($datetime->lt($task->start_at)) { - return TaskLedgerStatus::None; - } elseif ($datetime->gte($task->end_at)) { - return TaskLedgerStatus::Failed; + if ($datetime->lt($this->task->end_at)) { + return TaskLedgerStatus::Pending; } - return TaskLedgerStatus::Pending; + + return TaskLedgerStatus::Failed; }, ); } diff --git a/app/Models/TaskPerformance.php b/app/Models/TaskPerformance.php index 1a7b6a9..d0becad 100644 --- a/app/Models/TaskPerformance.php +++ b/app/Models/TaskPerformance.php @@ -55,20 +55,22 @@ class TaskPerformance extends Model protected function taskStatus(): Attribute { return Attribute::make( - get: function (mixed $value, array $attributes) { - if ($this->isSuccess()) { - return TaskPerformanceStatus::Success; - } - - // 当前时间 + get: function (mixed $value) { $datetime = now(); if ($datetime->lt($this->task->start_at)) { return TaskPerformanceStatus::None; - } elseif ($datetime->gte($this->task->end_at)) { - return TaskPerformanceStatus::Failed; } - return TaskPerformanceStatus::Pending; + + if ($this->isSuccess()) { + return TaskPerformanceStatus::Success; + } + + if ($datetime->lt($this->task->end_at)) { + return TaskPerformanceStatus::Pending; + } + + return TaskPerformanceStatus::Failed; }, ); } diff --git a/app/Traits/HasCheckable.php b/app/Traits/HasCheckable.php index 51f7c69..2bd9cc4 100644 --- a/app/Traits/HasCheckable.php +++ b/app/Traits/HasCheckable.php @@ -34,28 +34,36 @@ trait HasCheckable return Str::snake(class_basename(__CLASS__)); } + /** + * 审核中 + */ + public function checkProcessing(): bool + { + return $this->workflow->check_status === CheckStatus::Processing; + } + /** * 审核通过 */ - public function checkSuccess() + public function checkSuccess(): bool { - + return $this->workflow->check_status === CheckStatus::Success; } /** * 审核未通过 */ - public function checkFail() + public function checkFail(): bool { - + return $this->workflow->check_status === CheckStatus::Fail; } /** * 取消申请 */ - public function checkCancel() + public function checkCancel(): bool { - + return $this->workflow->check_status === CheckStatus::Cancel; } public function canUpdate(): bool diff --git a/database/seeders/WorkflowSeeder.php b/database/seeders/WorkflowSeeder.php index 4a5cb3f..527259e 100644 --- a/database/seeders/WorkflowSeeder.php +++ b/database/seeders/WorkflowSeeder.php @@ -27,6 +27,7 @@ class WorkflowSeeder extends Seeder ['key' => 'store_master_commission', 'name' => '店长提成', 'config' => $config, 'created_at' => now(), 'updated_at' => now()], ['key' => 'employee_promotion', 'name' => '升职申请', 'config' => $config, 'created_at' => now(), 'updated_at' => now()], ['key' => 'agreement', 'name' => '合同审核', 'config' => $config, 'created_at' => now(), 'updated_at' => now()], + ['key' => 'task_hygiene', 'name' => '清洁卫生', 'config' => $config, 'created_at' => now(), 'updated_at' => now()], ]); } } diff --git a/lang/zh_CN/plan.php b/lang/zh_CN/plan.php index 8fc94ab..46b6ea6 100644 --- a/lang/zh_CN/plan.php +++ b/lang/zh_CN/plan.php @@ -32,7 +32,7 @@ return [ 'name' => '任务名称', 'status' => '状态', 'completed_at' => '完成时间', - 'created_at' => '创建时间', + 'created_at' => '发布时间', ], 'task_ledger' => [ diff --git a/routes/api.php b/routes/api.php index 938c6cf..afd0fb6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -55,8 +55,10 @@ Route::group([ // 数据上报 Route::apiResource('/ledgers', LedgerController::class)->only(['store', 'show']); - // 任务列表 + // 我的任务 - 任务列表 Route::get('tasks', [TaskController::class, 'index']); + // 我的任务 - 提交任务 + Route::post('tasks/{task}/submit', [TaskController::class, 'submit']); // 举报投诉 Route::post('complaints', [ComplaintController::class, 'store']);