['bail', 'required', 'max:255'], 'planable_type' => [ 'bail', 'required', Rule::in([ (new PlanHygiene())->getMorphClass(), (new PlanPerformance())->getMorphClass(), ]), ], ], attributes: [ 'name' => __('plan.plan.name'), 'planable_type' => __('plan.plan.type'), ], ); switch (Relation::getMorphedModel($data['planable_type'])) { // 清洁卫生 case PlanHygiene::class: $payload = $data['plan_hygiene'] ?? []; Validator::validate( data: $payload, rules: [ 'month' => ['bail', 'required', 'date_format:Y-m'], ], attributes: [ 'month' => __('plan.plan_hygiene.month'), ], ); $planable = PlanHygiene::create($payload); $planable->plan()->create([ 'name' => $data['name'], 'plan_status' => PlanStatus::Pending, ]); break; // 业绩指标 case PlanPerformance::class: $payload = $data['plan_performance'] ?? []; Validator::validate( data: $payload, rules: [ 'month' => ['bail', 'required', 'date_format:Y-m'], 'store_category_id' => ['bail', 'required', Rule::exists(Keyword::class, 'key')], 'store_level_id' => ['bail', 'nullable', Rule::exists(Keyword::class, 'key')], 'performance' => ['bail', 'required', 'numeric', 'min:0'], ], attributes: [ 'month' => __('plan.plan_performance.month'), 'store_category_id' => __('plan.plan_performance.store_category_id'), 'store_level_id' => __('plan.plan_performance.store_level_id'), 'performance' => __('plan.plan_performance.performance'), ], ); $planable = PlanPerformance::create($payload); $planable->plan()->create([ 'name' => $data['name'], 'plan_status' => PlanStatus::Pending, ]); break; } return true; } public function update($primaryKey, $data): bool { /** @var \App\Models\Plan|null */ $plan = Plan::findOrFail($primaryKey); if ($plan->isPublished()) { admin_abort('任务计划已发布'); } $planableType = Relation::getMorphedModel($plan->planable_type); $rules = array_merge( ['name' => ['filled', 'max:255']], match ($planableType) { PlanHygiene::class => [ 'plan_hygiene.month' => ['bail', 'required', 'date_format:Y-m'], ], PlanPerformance::class => [ 'plan_performance.month' => ['bail', 'required', 'date_format:Y-m'], 'plan_performance.store_category_id' => ['bail', 'required', Rule::exists(Keyword::class, 'key')], 'plan_performance.store_level_id' => ['bail', 'nullable', Rule::exists(Keyword::class, 'key')], 'plan_performance.performance' => ['bail', 'required', 'numeric', 'min:0'], ], }, ); Validator::validate( data: $data, rules: $rules, attributes: [ 'name' => __('plan.plan.name'), 'plan_performance.month' => __('plan.plan_performance.month'), 'plan_performance.store_category_id' => __('plan.plan_performance.store_category_id'), 'plan_performance.store_level_id' => __('plan.plan_performance.store_level_id'), 'plan_performance.performance' => __('plan.plan_performance.performance'), 'plan_hygiene.month' => __('plan.plan_hygiene.month'), ], ); if (array_key_exists('name', $data)) { $plan->name = $data['name']; } $plan->save(); switch ($planableType) { case PlanPerformance::class: $plan->planable->update($data['plan_performance']); break; case PlanHygiene::class: $plan->planable->update($data['plan_hygiene']); break; } return true; } public function publish($id) { /** @var \App\Models\Plan */ $plan = Plan::findOrFail($id); if ($plan->isPublished()) { admin_abort('任务计划已发布'); } switch (Relation::getMorphedModel($plan->planable_type)) { // 清洁卫生 case PlanHygiene::class: // 任务开始时间 $startAt = Carbon::createFromFormat('Y-m-d H:i:s', "{$plan->planable->month}-01 00:00:00"); // 任务结束时间 $endAt = $startAt->copy()->endOfMonth(); /** @var \Illuminate\Database\Eloquent\Collection */ $stores = Store::findMany($plan->planable->store_ids); foreach ($stores as $store) { $taskable = TaskHygiene::create([ 'month' => $plan->planable->month, 'store_id' => $store->id, 'store_master_id' => $store->master_id, ]); $taskable->task()->create([ 'plan_id' => $plan->id, 'name' => '清洁任务', 'start_at' => $startAt, 'end_at' => $endAt, 'task_status' => TaskStatus::Pending, ]); } break; // 业绩指标 case PlanPerformance::class: // 任务开始时间 $startAt = Carbon::createFromFormat('Y-m-d H:i:s', "{$plan->planable->month}-01 00:00:00"); // 任务结束时间 $endAt = $startAt->copy()->endOfMonth(); $input = [ 'category_id' => $plan->planable->store_category_id, 'level_id' => $plan->planable->store_level_id, ]; /** @var \Illuminate\Database\Eloquent\Collection */ $stores = Store::filter($input, StoreFilter::class)->get(['id', 'master_id']); foreach ($stores as $store) { $taskable = TaskPerformance::create([ 'month' => $plan->planable->month, 'store_id' => $store->id, 'store_master_id' => $store->master_id, 'expected_performance' => $plan->planable->performance, 'actual_performance' => 0, ]); $taskable->task()->create([ 'plan_id' => $plan->id, 'name' => '业绩指标', 'start_at' => $startAt, 'end_at' => $endAt, 'task_status' => TaskStatus::Pending, ]); } break; default: admin_abort('未知计划类型'); break; } $plan->update([ 'plan_status' => PlanStatus::Published, ]); } public function getDetail($id) { if ($plan = parent::getDetail($id)) { if ($plan->planable instanceof PlanHygiene) { $plan->planable->setAttribute( 'stores', Store::findMany($plan->planable->store_ids) ); } } return $plan; } public function preDelete(array $ids): void { /** @var \Illuminate\Database\Eloquent\Collection */ $plans = Plan::findMany($ids); if ($plans->contains(fn (Plan $plan) => $plan->isPublished())) { admin_abort('不能删除已发布的任务计划'); } $plans->each(fn (Plan $plan) => $plan->planable()->delete()); } public function addRelations($query, string $scene = 'list') { if (in_array($scene, ['edit', 'detail'])) { $query->with([ 'planable' => function (MorphTo $morphTo) { $morphTo->morphWith([ PlanPerformance::class => ['storeCategory', 'storeLevel'], ]); }, ]); } } }