我的任务

main
Jing Li 2024-04-20 20:29:57 +08:00
parent cecce29485
commit c9bccd7123
14 changed files with 204 additions and 35 deletions

View File

@ -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([

View File

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

View File

@ -0,0 +1,42 @@
<?php
namespace App\Enums;
enum TaskHygieneStatus: int
{
case None = 1; // 未开始
case Pending = 2; // 待完成
case Checking = 3; // 审核中
case Unpassed = 4; // 未通过
case Success = 5; // 已完成
case Failed = 6; // 未完成
public function text(): string
{
return self::options()[$this->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 => '<span class="label bg-gray-500">'.self::None->text().'</span>',
self::Pending->value => '<span class="label label-primary">'.self::Pending->text().'</span>',
self::Checking->value => '<span class="label bg-danger">'.self::Checking->text().'</span>',
self::Unpassed->value => '<span class="label label-warning">'.self::Unpassed->text().'</span>',
self::Success->value => '<span class="label label-success">'.self::Success->text().'</span>',
self::Failed->value => '<span class="label label-danger">'.self::Failed->text().'</span>',
];
}
}

View File

@ -27,7 +27,7 @@ enum TaskLedgerStatus: int
public static function labelMap(): array
{
return [
self::None->value => '<span class="label bg-purple-500">'.self::None->text().'</span>',
self::None->value => '<span class="label bg-gray-500">'.self::None->text().'</span>',
self::Pending->value => '<span class="label label-primary">'.self::Pending->text().'</span>',
self::Success->value => '<span class="label label-success">'.self::Success->text().'</span>',
self::Failed->value => '<span class="label label-danger">'.self::Failed->text().'</span>',

View File

@ -27,7 +27,7 @@ enum TaskPerformanceStatus: int
public static function labelMap(): array
{
return [
self::None->value => '<span class="label bg-purple-500">'.self::None->text().'</span>',
self::None->value => '<span class="label bg-gray-500">'.self::None->text().'</span>',
self::Pending->value => '<span class="label label-primary">'.self::Pending->text().'</span>',
self::Success->value => '<span class="label label-success">'.self::Success->text().'</span>',
self::Failed->value => '<span class="label label-danger">'.self::Failed->text().'</span>',

View File

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

View File

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

View File

@ -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;
},
);
}
}

View File

@ -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;
},
);
}

View File

@ -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;
},
);
}

View File

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

View File

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

View File

@ -32,7 +32,7 @@ return [
'name' => '任务名称',
'status' => '状态',
'completed_at' => '完成时间',
'created_at' => '创建时间',
'created_at' => '发布时间',
],
'task_ledger' => [

View File

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