generated from liutk/owl-admin-base
清洁任务审批流程
parent
9b5184cbbf
commit
da9b11de12
|
|
@ -4,14 +4,15 @@ namespace App\Admin\Controllers\Plan;
|
|||
|
||||
use App\Admin\Controllers\AdminController;
|
||||
use App\Admin\Services\Plan\PlanService;
|
||||
use App\Enums\CheckStatus;
|
||||
use App\Enums\PlanStatus;
|
||||
use App\Enums\TaskHygieneStatus;
|
||||
use App\Enums\TaskLedgerStatus;
|
||||
use App\Enums\TaskPerformanceStatus;
|
||||
use App\Enums\TaskStatus;
|
||||
use App\Models\PlanHygiene;
|
||||
use App\Models\PlanLedger;
|
||||
use App\Models\PlanPerformance;
|
||||
use App\Models\TaskHygiene;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Slowlyo\OwlAdmin\Admin;
|
||||
|
|
@ -254,6 +255,8 @@ class PlanController extends AdminController
|
|||
amis()->TableColumn('completed_at', __('plan.task.completed_at')),
|
||||
amis()->TableColumn('created_at', __('plan.task.created_at')),
|
||||
$this->rowActions([
|
||||
$this->taskRowShowButton()
|
||||
->visible(Admin::user()->can('admin.plan.plans.task_view')),
|
||||
$this->taskRowDeleteButton()
|
||||
->visible(Admin::user()->can('admin.plan.plans.task_delete')),
|
||||
]),
|
||||
|
|
@ -381,17 +384,66 @@ class PlanController extends AdminController
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务 - 行查看按钮
|
||||
*/
|
||||
protected function taskRowShowButton(): DrawerAction
|
||||
{
|
||||
$taskDetailId = 'task-detail';
|
||||
$workflowLogListId = 'task-workflow-service';
|
||||
|
||||
$detail = $this->baseDetail()
|
||||
->id($taskDetailId)
|
||||
->initApi(admin_url('/plan/tasks/${id}?_action=getData'))
|
||||
->onEvent([
|
||||
'inited' => [
|
||||
'actions' => [
|
||||
['actionType' => 'reload', 'componentId' => $workflowLogListId],
|
||||
],
|
||||
],
|
||||
])
|
||||
->body([
|
||||
amis()->Property()->items([
|
||||
['label' => __('plan.task_hygiene.month'), 'content' => '${taskable.month}'],
|
||||
['label' => __('plan.task_hygiene.store'), 'content' => '${taskable.store.title}'],
|
||||
['label' => __('plan.task_hygiene.store_master'), 'content' => '${taskable.store_master.name}'],
|
||||
['label' => __('plan.task_hygiene.status'), 'content' => amis()->Mapping()->name('taskable.task_status')->map(TaskHygieneStatus::labelMap())],
|
||||
['label' => __('plan.task.completed_at'), 'content' => '${completed_at}'],
|
||||
['label' => __('plan.task.created_at'), 'content' => '${created_at}'],
|
||||
['label' => __('plan.task_hygiene.description'), 'content' => '${taskable.description}', 'span' => 3],
|
||||
['label' => __('plan.task_hygiene.photos'), 'content' => amis()->Images()->enlargeAble()->source('${taskable.photos}')->enlargeWithGallary(), 'span' => 3],
|
||||
['label' => __('workflow_log.check_status'), 'content' => amis()->Mapping()->name('taskable.workflow.check_status')->map(CheckStatus::labelMap())],
|
||||
['label' => __('workflow_log.checked_at'), 'content' => '${taskable.workflow.checked_at}'],
|
||||
['label' => __('workflow_log.remarks'), 'content' => '${taskable.workflow.check_remarks}'],
|
||||
]),
|
||||
|
||||
amis()->Divider(),
|
||||
|
||||
(new TaskController)->baseWorkflowLogList("{$taskDetailId},task-hygiene-table")
|
||||
->id($workflowLogListId)
|
||||
->api(admin_url('/api/workflow/logs?id=${taskable.workflow.id}'))
|
||||
->visibleOn('${taskable_type === "'.(new TaskHygiene())->getMorphClass().'"}'),
|
||||
]);
|
||||
|
||||
$drawer = Drawer::make()
|
||||
->title(__('admin.show'))
|
||||
->size('xl')
|
||||
->closeOnOutside()
|
||||
->body($detail);
|
||||
|
||||
return DrawerAction::make()
|
||||
->label(__('admin.show'))
|
||||
->icon('fa fa-eye')
|
||||
->level('link')
|
||||
->drawer($drawer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务 - 行删除按钮
|
||||
*/
|
||||
protected function taskRowDeleteButton(): AjaxAction
|
||||
{
|
||||
return amis()->AjaxAction()
|
||||
->label(__('admin.delete'))
|
||||
->icon('fa-regular fa-trash-can')
|
||||
->level('link')
|
||||
->confirmText(__('admin.confirm_delete'))
|
||||
->api('delete:'.admin_url('/plan/tasks/${id}'));
|
||||
return (new TaskController())->rowDeleteButton()->api('delete:'.admin_url('/plan/tasks/${id}'));
|
||||
}
|
||||
|
||||
protected function planableTypeOptions(): array
|
||||
|
|
|
|||
|
|
@ -5,20 +5,61 @@ namespace App\Admin\Controllers\Plan;
|
|||
use App\Admin\Controllers\AdminController;
|
||||
use App\Admin\Filters\TaskFilter;
|
||||
use App\Admin\Services\Plan\TaskService;
|
||||
use App\Enums\CheckStatus;
|
||||
use App\Enums\TaskHygieneStatus;
|
||||
use App\Models\Task;
|
||||
use App\Models\TaskHygiene;
|
||||
use App\Models\TaskLedger;
|
||||
use App\Models\TaskPerformance;
|
||||
use App\Traits\HasCheckActions;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Http\Request;
|
||||
use Slowlyo\OwlAdmin\Renderers\Form;
|
||||
|
||||
/**
|
||||
* @property TaskService $service
|
||||
*/
|
||||
class TaskController extends AdminController
|
||||
{
|
||||
use HasCheckActions;
|
||||
|
||||
protected string $serviceName = TaskService::class;
|
||||
|
||||
public function detail(): Form
|
||||
{
|
||||
$taskDetailId = 'task-detail';
|
||||
$workflowLogListId = 'task-workflow-service';
|
||||
|
||||
return $this->baseDetail()->id($taskDetailId)->title('')->onEvent([
|
||||
'inited' => [
|
||||
'actions' => [
|
||||
['actionType' => 'reload', 'componentId' => $workflowLogListId],
|
||||
],
|
||||
],
|
||||
])->body([
|
||||
amis()->Property()->items([
|
||||
['label' => __('plan.task_hygiene.month'), 'content' => '${taskable.month}'],
|
||||
['label' => __('plan.task_hygiene.store'), 'content' => '${taskable.store.title}'],
|
||||
['label' => __('plan.task_hygiene.store_master'), 'content' => '${taskable.store_master.name}'],
|
||||
['label' => __('plan.task_hygiene.status'), 'content' => amis()->Mapping()->name('taskable.task_status')->map(TaskHygieneStatus::labelMap())],
|
||||
['label' => __('plan.task.completed_at'), 'content' => '${completed_at}'],
|
||||
['label' => __('plan.task.created_at'), 'content' => '${created_at}'],
|
||||
['label' => __('plan.task_hygiene.description'), 'content' => '${taskable.description}', 'span' => 3],
|
||||
['label' => __('plan.task_hygiene.photos'), 'content' => amis()->Images()->enlargeAble()->source('${taskable.photos}')->enlargeWithGallary(), 'span' => 3],
|
||||
['label' => __('workflow_log.check_status'), 'content' => amis()->Mapping()->name('taskable.workflow.check_status')->map(CheckStatus::labelMap())],
|
||||
['label' => __('workflow_log.checked_at'), 'content' => '${taskable.workflow.checked_at}'],
|
||||
['label' => __('workflow_log.remarks'), 'content' => '${taskable.workflow.check_remarks}'],
|
||||
]),
|
||||
|
||||
amis()->Divider(),
|
||||
|
||||
$this->baseWorkflowLogList($taskDetailId)
|
||||
->id($workflowLogListId)
|
||||
->api(admin_url('/api/workflow/logs?id=${taskable.workflow.id}'))
|
||||
->visibleOn('${taskable_type === "'.(new TaskHygiene())->getMorphClass().'"}'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function shareList(Request $request)
|
||||
{
|
||||
$tasks = Task::filter($request->input(), TaskFilter::class)
|
||||
|
|
|
|||
|
|
@ -52,9 +52,7 @@ class PlanService extends BaseService
|
|||
],
|
||||
);
|
||||
|
||||
$planableType = Relation::getMorphedModel($data['planable_type']);
|
||||
|
||||
switch ($planableType) {
|
||||
switch (Relation::getMorphedModel($data['planable_type'])) {
|
||||
// 清洁卫生
|
||||
case PlanHygiene::class:
|
||||
$payload = $data['plan_hygiene'] ?? [];
|
||||
|
|
@ -69,7 +67,7 @@ class PlanService extends BaseService
|
|||
],
|
||||
);
|
||||
|
||||
$planable = PlanPerformance::create($payload);
|
||||
$planable = PlanHygiene::create($payload);
|
||||
|
||||
$planable->plan()->create([
|
||||
'name' => $data['name'],
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ use App\Models\PlanPerformance;
|
|||
use App\Models\Store;
|
||||
use App\Models\Task;
|
||||
use App\Models\TaskHygiene;
|
||||
use App\Models\TaskLedger;
|
||||
use App\Models\TaskPerformance;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
|
|
@ -27,6 +29,15 @@ class TaskService extends BaseService
|
|||
|
||||
protected string $modelFilterName = TaskFilter::class;
|
||||
|
||||
public function getDetail($id)
|
||||
{
|
||||
if ($task = parent::getDetail($id)) {
|
||||
$task->taskable->setRelation('task', $task->withoutRelations());
|
||||
}
|
||||
|
||||
return $task;
|
||||
}
|
||||
|
||||
public function store($data): bool
|
||||
{
|
||||
if (! isset($data['plan_id'])) {
|
||||
|
|
@ -194,4 +205,19 @@ class TaskService extends BaseService
|
|||
|
||||
$tasks->each(fn (Task $task) => $task->taskable()->delete());
|
||||
}
|
||||
|
||||
public function addRelations($query, string $scene = 'list')
|
||||
{
|
||||
if (in_array($scene, ['edit', 'detail'])) {
|
||||
$query->with([
|
||||
'taskable' => function (MorphTo $morphTo) {
|
||||
$morphTo->morphWith([
|
||||
TaskLedger::class => ['store', 'storeMaster'],
|
||||
TaskPerformance::class => ['store', 'storeMaster'],
|
||||
TaskHygiene::class => ['store', 'storeMaster', 'workflow'],
|
||||
]);
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class WorkFlowService extends BaseService
|
|||
*
|
||||
* @param WorkflowCheck $check 待审核记录
|
||||
* @param Employee $user 申请人
|
||||
*
|
||||
*
|
||||
* @return bool true: 成功, false: 失败, $this->getError(): 错误消息
|
||||
*/
|
||||
public function apply(WorkflowCheck $check, Employee $user)
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ Route::group([
|
|||
$router->resource('plans', PlanController::class);
|
||||
$router->post('/plans/{plan}/publish', [PlanController::class, 'publish'])->name('plans.publish');
|
||||
$router->post('/tasks', [TaskController::class, 'store'])->name('plans.task_create');
|
||||
$router->get('/tasks/{task}', [TaskController::class, 'show'])->name('plans.task_view');
|
||||
$router->put('/tasks/{task}', [TaskController::class, 'update'])->name('plans.task_update');
|
||||
$router->delete('/tasks/{task}', [TaskController::class, 'destroy'])->name('plans.task_delete');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ MySQL;
|
|||
throw tap($th, fn ($th) => report($th));
|
||||
}
|
||||
|
||||
return response()->json();
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
protected function handleTaskSubmit(Task $task, Request $request): void
|
||||
|
|
|
|||
|
|
@ -42,6 +42,11 @@ class TaskHygiene extends Model
|
|||
return $this->belongsTo(Employee::class, 'store_master_id');
|
||||
}
|
||||
|
||||
public function checkSuccess()
|
||||
{
|
||||
$this->task->markAsSuccess();
|
||||
}
|
||||
|
||||
protected function photos(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
|
|
@ -69,15 +74,15 @@ class TaskHygiene extends Model
|
|||
return TaskHygieneStatus::None;
|
||||
}
|
||||
|
||||
if ($this->task->isSuccess() || $this->checkSuccess()) {
|
||||
if ($this->task->isSuccess() || $this->isCheckSuccess()) {
|
||||
return TaskHygieneStatus::Success;
|
||||
}
|
||||
|
||||
if ($this->checkProcessing()) {
|
||||
if ($this->isCheckProcessing()) {
|
||||
return TaskHygieneStatus::Checking;
|
||||
}
|
||||
|
||||
if ($this->checkFail()) {
|
||||
if ($this->isCheckFail()) {
|
||||
return TaskHygieneStatus::Unpassed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,35 +35,55 @@ trait HasCheckable
|
|||
}
|
||||
|
||||
/**
|
||||
* 审核中
|
||||
* 审核通过
|
||||
*/
|
||||
public function checkProcessing(): bool
|
||||
public function checkApply()
|
||||
{
|
||||
return $this->workflow->check_status === CheckStatus::Processing;
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核通过
|
||||
*/
|
||||
public function checkSuccess(): bool
|
||||
public function checkSuccess()
|
||||
{
|
||||
return $this->workflow->check_status === CheckStatus::Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核未通过
|
||||
*/
|
||||
public function checkFail(): bool
|
||||
public function checkFail()
|
||||
{
|
||||
return $this->workflow->check_status === CheckStatus::Fail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消申请
|
||||
*/
|
||||
public function checkCancel(): bool
|
||||
public function checkCancel()
|
||||
{
|
||||
return $this->workflow->check_status === CheckStatus::Cancel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否审核中
|
||||
*/
|
||||
public function isCheckProcessing(): bool
|
||||
{
|
||||
return $this->workflow->check_status === CheckStatus::Processing;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否审核通过
|
||||
*/
|
||||
public function isCheckSuccess(): bool
|
||||
{
|
||||
return $this->workflow->check_status === CheckStatus::Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否审核未通过
|
||||
*/
|
||||
public function isCheckFail(): bool
|
||||
{
|
||||
return $this->workflow->check_status === CheckStatus::Fail;
|
||||
}
|
||||
|
||||
public function canUpdate(): bool
|
||||
|
|
|
|||
|
|
@ -182,18 +182,20 @@ class AdminPermissionSeeder extends Seeder
|
|||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'plan' => [
|
||||
'name' => '任务管理',
|
||||
'name' => '任务计划',
|
||||
'icon' => 'mingcute:send-plane-line',
|
||||
'uri' => '/plan',
|
||||
'order' => 4,
|
||||
'children' => [
|
||||
'plans' => [
|
||||
'name' => '任务列表',
|
||||
'name' => '任务计划',
|
||||
'icon' => 'tdesign:task',
|
||||
'uri' => '/plan/plans',
|
||||
'resource' => true,
|
||||
'children' => [
|
||||
'publish' => '发布',
|
||||
'task_create' => '创建任务',
|
||||
'task_view' => '查看任务',
|
||||
'task_update' => '编辑任务',
|
||||
'task_delete' => '删除任务',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -56,5 +56,7 @@ return [
|
|||
'store' => '门店',
|
||||
'store_master' => '店长',
|
||||
'status' => '状态',
|
||||
'description' => '清洁范围',
|
||||
'photos' => '清洁结果',
|
||||
],
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in New Issue