diff --git a/app/Http/Controllers/Business/SystemizationTodos.php b/app/Http/Controllers/Business/SystemizationTodos.php index 650b4c21..3e4437f2 100644 --- a/app/Http/Controllers/Business/SystemizationTodos.php +++ b/app/Http/Controllers/Business/SystemizationTodos.php @@ -195,9 +195,9 @@ class SystemizationTodos extends Controller $section = $this->hierarchyLabel($todo->section); return [ - 'category_key' => $category === '' ? "\0" : $category, + 'category_key' => $this->hierarchyGroupKey($category), 'category_label' => $category, - 'section_key' => $section === '' ? "\0" : $section, + 'section_key' => $this->hierarchyGroupKey($section), 'section_label' => $section, 'sort_order' => (int) $todo->sort_order, 'id' => (int) $todo->id, @@ -216,12 +216,12 @@ class SystemizationTodos extends Controller $categoryOrder[$categoryKey] ?? PHP_INT_MAX, $row['sort_order'], ); - $categoryLabels[$categoryKey] = $row['category_label']; + $categoryLabels[$categoryKey] ??= $row['category_label']; $sectionOrder[$categoryKey][$sectionKey] = min( $sectionOrder[$categoryKey][$sectionKey] ?? PHP_INT_MAX, $row['sort_order'], ); - $sectionLabels[$categoryKey][$sectionKey] = $row['section_label']; + $sectionLabels[$categoryKey][$sectionKey] ??= $row['section_label']; $groupedRows[$categoryKey][$sectionKey][] = $row; } @@ -299,6 +299,18 @@ class SystemizationTodos extends Controller )); } + private function hierarchyGroupKey(string $label): string + { + $normalized = preg_replace( + '/[\s\p{Z}\x{200B}\x{FEFF}]+/u', + '', + $label, + ); + $normalized = (string) $normalized; + + return $normalized === '' ? "\0" : mb_strtolower($normalized); + } + public function store(Request $request): RedirectResponse { $data = $this->validated($request); diff --git a/tests/Feature/Business/SystemizationTodosTest.php b/tests/Feature/Business/SystemizationTodosTest.php index 1fb00a51..f8b310bc 100644 --- a/tests/Feature/Business/SystemizationTodosTest.php +++ b/tests/Feature/Business/SystemizationTodosTest.php @@ -307,13 +307,15 @@ class SystemizationTodosTest extends FeatureTestCase { $this->loginAs(); - $pending = $this->createTodo('收入', '钉钉流程', '待办事项 A', '2026-10-30', 1); - $completed = $this->createTodo('收入', '钉钉流程', '待办事项 B', '2026-10-10', 2); + $mergedSection = '钉钉流程,纳税人 3、盘点'; + $mergedSectionVariant = '钉钉流程,纳税人3、盘点'; + $pending = $this->createTodo('收入', $mergedSection, '待办事项 A', '2026-10-30', 1); + $completed = $this->createTodo('收入', $mergedSectionVariant, '待办事项 B', '2026-10-10', 2); $completed->update([ 'status' => SystemizationTodo::STATUS_COMPLETED, 'completed_at' => '2026-10-10', ]); - $inProgress = $this->createTodo('收入', '钉钉流程', '待办事项 C', '2026-10-20', 3); + $inProgress = $this->createTodo('收入', $mergedSection, '待办事项 C', '2026-10-20', 3); $inProgress->update(['status' => SystemizationTodo::STATUS_IN_PROGRESS]); $secondContent = $this->createTodo('收入', '报销流程', '待办事项 D', '2026-11-01', 4); $cost = $this->createTodo('成本', '成本核对', '待办事项 E', '2026-11-02', 5); @@ -354,12 +356,16 @@ class SystemizationTodosTest extends FeatureTestCase $this->assertSame( [$completed->id, $inProgress->id], $items - ->where('section', '钉钉流程') + ->where('type_sequence', 1) + ->where('content_sequence', 1) ->whereIn('status', [SystemizationTodo::STATUS_COMPLETED, SystemizationTodo::STATUS_IN_PROGRESS]) ->pluck('id') ->all(), ); - $this->assertSame(1, substr_count((string) $response->getContent(), '>钉钉流程<')); + $this->assertSame( + 1, + substr_count((string) $response->getContent(), '>' . $mergedSection . '<'), + ); } public function test_page_renders_all_todos_on_one_continuous_list(): void