weizong song 2 months ago
parent 07ade32edc
commit 765eee5b2c

@ -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;
}
/**
* 获取动态列
*/

Loading…
Cancel
Save