diff --git a/app/Admin/Controllers/CockpitController.php b/app/Admin/Controllers/CockpitController.php index b2177d6..ae6da9e 100644 --- a/app/Admin/Controllers/CockpitController.php +++ b/app/Admin/Controllers/CockpitController.php @@ -2,6 +2,7 @@ namespace App\Admin\Controllers; +use App\Admin\Filters\StoreFilter; use App\Http\Controllers\Controller; use App\Models\Employee; use App\Models\Keyword; @@ -12,6 +13,7 @@ use App\Models\TaskPerformance; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Storage; use Illuminate\Validation\Rule; class CockpitController extends Controller @@ -317,4 +319,63 @@ class CockpitController extends Controller 'actual_performance' => trim_zeros($aggregates['actual_performance'] ?? 0), ]; } + + /** + * 门店数量分布 + */ + public function storeNumberDistribution(Request $request): array + { + /** @var array */ + $region = json_decode(Storage::disk('local')->get('region.json'), true); + + /** @var \Illuminate\Support\Collection */ + $numbers = Store::select(['region']) + ->filter($request->input(), StoreFilter::class) + ->onlyOpen() + ->get() + ->groupBy(fn ($store) => $store->region['provinceCode'] ?? 'other') + ->map(fn ($stores) => $stores->count()); + + return collect($region['province'])->map(function ($province) use ($numbers) { + return array_merge($province, [ + 'stores_count' => $numbers->get($province['code'], 0), + ]); + })->all(); + } + + /** + * 门店分布 + */ + public function storeDistribution(Request $request): array + { + $request->validate( + rules: [ + 'province_code' => ['required'], + ], + ); + + $provinceCode = $request->input('province_code'); + + /** @var array */ + $region = json_decode(Storage::disk('local')->get('region.json'), true); + + /** @var \Illuminate\Support\Collection */ + $stores = Store::filter($request->input(), StoreFilter::class) + ->onlyOpen() + ->get() + ->groupBy(fn ($store) => $store->region['cityCode'] ?? 'other'); + + return collect(data_get($region, "city.{$provinceCode}", []))->map(function ($city) use ($stores) { + return array_merge($city, [ + 'stores' => $stores->get($city['code'], collect())->map(function ($store) { + return [ + 'id' => $store->id, + 'title' => $store->title, + 'lon' => $store->lon, + 'lat' => $store->lat, + ]; + }), + ]); + })->all(); + } } diff --git a/app/Admin/routes.php b/app/Admin/routes.php index 316f880..bafb6dc 100644 --- a/app/Admin/routes.php +++ b/app/Admin/routes.php @@ -250,6 +250,10 @@ Route::group([ $router->get('cockpit/lottery-sales-trend', [CockpitController::class, 'lotterySalesTrend']); // 门店销量排名 $router->get('cockpit/store-sales-ranking', [CockpitController::class, 'storeSalesRanking']); + // 门店数量分布(按省份) + $router->get('cockpit/store-number-distribution', [CockpitController::class, 'storeNumberDistribution']); + // 门店分布(按城市) + $router->get('cockpit/store-distribution', [CockpitController::class, 'storeDistribution']); // 年度目标 $router->get('cockpit/yearly-goals', [CockpitController::class, 'yearlyGoals']); }); diff --git a/app/Http/Controllers/Api/TaskController.php b/app/Http/Controllers/Api/TaskController.php index 1d0bbd5..56072b0 100644 --- a/app/Http/Controllers/Api/TaskController.php +++ b/app/Http/Controllers/Api/TaskController.php @@ -34,8 +34,8 @@ MySQL; $tasks = Task::with([ 'taskable' => function (MorphTo $morphTo) { $morphTo->morphWith([ - TaskHygiene::class => ['task', 'workflow'], - TaskLedger::class => ['task'], + TaskHygiene::class => ['workflow'], + TaskLedger::class, ]); }, ]) @@ -60,7 +60,46 @@ MySQL; ->orderBy('end_at', 'ASC') ->simplePaginate($request->query('per_page', 20)); - return TaskResource::collection($tasks); + return TaskResource::collection( + $tasks->through(function ($task) { + $task->taskable->setRelation('task', $task->withoutRelations()); + return $task; + }) + ); + } + + public function show($id, Request $request) + { + /** @var \App\Models\Employee */ + $user = $request->user(); + + $task = Task::with([ + 'taskable' => function (MorphTo $morphTo) { + $morphTo->morphWith([ + TaskHygiene::class => ['workflow', 'store'], + TaskLedger::class => ['store'], + ]); + }, + ])->whereHasMorph( + 'taskable', + [TaskHygiene::class, TaskLedger::class], + function (Builder $query, string $type) use ($user) { + switch ($type) { + case TaskLedger::class: + case TaskHygiene::class: + if ($user->isStoreMaster()) { + $query->where('store_id', $user->store_id); + } else { + $query->whereRaw('1!=1'); + } + break; + } + } + )->findOrFail($id); + + $task->taskable->setRelation('task', $task->withoutRelations()); + + return TaskResource::make($task); } public function submit($id, Request $request) diff --git a/routes/api.php b/routes/api.php index 40cc011..a31dfd4 100644 --- a/routes/api.php +++ b/routes/api.php @@ -66,6 +66,7 @@ Route::group([ // 我的任务 - 任务列表 Route::get('tasks', [TaskController::class, 'index']); + Route::get('tasks/{task}', [TaskController::class, 'show']); // 我的任务 - 提交任务 Route::post('tasks/{task}/submit', [TaskController::class, 'submit']);