From 765eee5b2c6298d63ec72dc0adca987434c28c18 Mon Sep 17 00:00:00 2001 From: weizong song Date: Mon, 16 Feb 2026 09:24:32 +0800 Subject: [PATCH] up --- .../Admin/StatisticsController.php | 104 +++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index 4d1218f..c40604f 100755 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -28,6 +28,7 @@ use App\Models\Refund; use App\Scopes\AdminProjectScope; use Carbon\Carbon; use Illuminate\Http\Request; +use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use PhpOffice\PhpSpreadsheet\Spreadsheet; @@ -466,14 +467,36 @@ class StatisticsController extends CommonController } })->where('admin_id', $user->id)->pluck('building_id'); } - $data = Area::where('project_id', $project_id)->with('project', 'building')->where(function ($query) use ($areaId, $buildingId) { + $allAreas = Area::where('project_id', $project_id)->with('project', 'building')->where(function ($query) use ($areaId, $buildingId) { if ($areaId) { $query->whereIn('id', $areaId); } if ($buildingId) { $query->whereIn('building_id', $buildingId); } - })->paginate(40); + })->get(); + + // 病区智能排序:1.数字开头按数字升序 2.中文数字开头转阿拉伯数字后升序 3.其他按myindex+id + $sortedAreas = $allAreas->sort(function ($a, $b) { + $keyA = $this->_getAreaNameSortKey($a->name ?? '', $a->myindex ?? 0, $a->id); + $keyB = $this->_getAreaNameSortKey($b->name ?? '', $b->myindex ?? 0, $b->id); + if ($keyA[0] !== $keyB[0]) { + return $keyA[0] <=> $keyB[0]; + } + if ($keyA[1] !== $keyB[1]) { + return $keyA[1] <=> $keyB[1]; + } + return $keyA[2] <=> $keyB[2]; + })->values(); + + $perPage = 40; + $currentPage = (int) $request->get('page', 1); + $currentPage = max(1, $currentPage); + $items = $sortedAreas->forPage($currentPage, $perPage)->values(); + $data = new LengthAwarePaginator($items, $sortedAreas->count(), $perPage, $currentPage, [ + 'path' => $request->url(), + 'query' => $request->query(), + ]); $data->appends($request->all())->render(); // ===== 重构:先从 OrderItems 获取真实价格数据,生成列,然后再统计每个病区的数据 ===== @@ -556,6 +579,83 @@ class StatisticsController extends CommonController return view($this->bladePath . ".huli", compact("sumOrderTotal", "data", "month", "lie", "projects", "project_id")); } + /** + * 获取病区名称的排序键,用于智能排序 + * 规则:1.数字开头->按数字升序 2.中文数字开头->转阿拉伯数字后升序 3.其他->按myindex+id + * + * @return array [tier, primary_sort, secondary_sort] tier=0有数字 tier=1无数字 + */ + private function _getAreaNameSortKey($name, $myindex, $id) + { + $name = trim((string) $name); + $myindex = (int) $myindex; + $id = (int) $id; + + // 1. 以阿拉伯数字开头:提取数字 + if (preg_match('/^(\d+)/', $name, $m)) { + return [0, (int) $m[1], 0]; + } + + // 2. 以中文数字开头:解析并转换 + $cnNum = $this->_parseChineseNumber($name); + if ($cnNum !== null) { + return [0, $cnNum, 0]; + } + + // 3. 都不满足:按 myindex、id + return [1, $myindex, $id]; + } + + /** + * 解析病区名称开头的连续中文数字,转为阿拉伯数字 + * + * @return int|null 解析到的数字,若无则 null + */ + private function _parseChineseNumber($str) + { + static $digits = [ + '〇' => 0, '零' => 0, '一' => 1, '二' => 2, '两' => 2, '三' => 3, '四' => 4, + '五' => 5, '六' => 6, '七' => 7, '八' => 8, '九' => 9, + '十' => 10, '百' => 100, '千' => 1000, '万' => 10000, + ]; + + $s = preg_replace('/\s+/', '', $str); + if ($s === '') { + return null; + } + + $len = mb_strlen($s); + $i = 0; + $result = 0; + $temp = 0; // 用于「十」「百」前的累积 + + while ($i < $len) { + $ch = mb_substr($s, $i, 1); + if (!isset($digits[$ch])) { + break; + } + $val = $digits[$ch]; + + if ($val >= 10) { + // 十、百、千、万:乘数 + if ($temp === 0) { + $temp = 1; + } + $result += $temp * $val; + $temp = 0; + } else { + $temp = $val; + } + $i++; + } + $result += $temp; + + if ($i === 0) { + return null; + } + return $result; + } + /** * 获取动态列 */