diff --git a/app/Http/Controllers/Business/SystemizationTodos.php b/app/Http/Controllers/Business/SystemizationTodos.php index 4905f40d..dbe64d81 100644 --- a/app/Http/Controllers/Business/SystemizationTodos.php +++ b/app/Http/Controllers/Business/SystemizationTodos.php @@ -645,9 +645,9 @@ class SystemizationTodos extends Controller ->where('section', '<>', '') ->get(['category', 'section']); foreach ($todos as $todo) { - $category = trim((string) ($todo->category ?? '')); + $category = $this->hierarchyLabel($todo->category); $section = $this->hierarchyLabel($todo->section); - if ($section !== '') { + if ($category !== '' && $section !== '') { $options[$category][$section] = true; } } diff --git a/resources/views/business/pages/systemization-todos.blade.php b/resources/views/business/pages/systemization-todos.blade.php index 106ae6a7..9ce1b6d1 100644 --- a/resources/views/business/pages/systemization-todos.blade.php +++ b/resources/views/business/pages/systemization-todos.blade.php @@ -707,8 +707,8 @@ var end = document.createElement('option'); end.value = String(count + 1); end.textContent = count > 0 - ? '添加到末尾(第 ' + (count + 1) + ' 条)' - : '新增为第 1 条'; + ? '+ 新增第 ' + (count + 1) + ' 条(添加到末尾)' + : '+ 新增为第 1 条'; positionSelect.appendChild(end); positionSelect.value = String(count + 1); } @@ -812,15 +812,15 @@ } function availableSectionLabels() { - var category = categoryValue.value; - if (category !== '' && Array.isArray(contentOptions[category])) { - return contentOptions[category].slice(); - } + var category = normalizedGroupText(categoryValue.value); + if (category === '') return []; - var labels = Object.values(contentOptions || {}).flat(); - return Array.from(new Set(labels)).sort(function (left, right) { - return String(left).localeCompare(String(right), 'zh-CN'); + var matchingKey = Object.keys(contentOptions || {}).find(function (key) { + return normalizedGroupText(key) === category; }); + return matchingKey && Array.isArray(contentOptions[matchingKey]) + ? contentOptions[matchingKey].slice() + : []; } function setSectionSelection(value) { @@ -881,6 +881,12 @@ : sectionSelect.value; } + function refreshSectionForCategory() { + var labels = availableSectionLabels(); + refreshSectionOptions(labels.length ? labels[0] : ''); + populatePositionOptions(); + } + function appendScreenshotFiles(files) { var images = Array.prototype.slice.call(files || []).filter(function (file) { return /^image\/(jpeg|png|webp)$/.test(file.type) @@ -1104,14 +1110,12 @@ }); categorySelect.addEventListener('change', function () { syncCategoryValue(); - refreshSectionOptions(sectionValue.value); - populatePositionOptions(); + refreshSectionForCategory(); }); newCategoryInput.addEventListener('input', function () { if (categorySelect.value === '__new__') { syncCategoryValue(); - refreshSectionOptions(sectionValue.value); - populatePositionOptions(); + refreshSectionForCategory(); } }); sectionSelect.addEventListener('change', function () { diff --git a/tests/Feature/Business/SystemizationTodosTest.php b/tests/Feature/Business/SystemizationTodosTest.php index 4ac24d5c..91461e94 100644 --- a/tests/Feature/Business/SystemizationTodosTest.php +++ b/tests/Feature/Business/SystemizationTodosTest.php @@ -219,6 +219,52 @@ class SystemizationTodosTest extends FeatureTestCase ], $reordered->pluck('title')->all()); } + public function test_can_add_a_new_sequence_after_the_last_todo(): void + { + $this->loginAs(); + + foreach (range(1, 7) as $index) { + $this->createTodo( + '收入', + '平台收入核对', + '原待办 ' . $index, + '2026-11-30', + $index, + ); + } + + $this->post(route('business.systemization-todos.store'), [ + 'category' => '收入', + 'section' => '平台收入核对', + 'position' => 8, + 'title' => '新增待办 8', + 'owner' => '晨曦', + 'assignee' => '栎阳', + 'status' => SystemizationTodo::STATUS_PENDING, + ])->assertRedirect() + ->assertSessionHas('success', '待办事项已新增为当前内容第 8 条并定位。'); + + $group = $this->get(route('business.pages.show', [ + 'section' => 'other', + 'page' => 'systemization-todos', + ]))->assertOk()->viewData('content')['items'] + ->where('category', '收入') + ->where('section', '平台收入核对') + ->values(); + + $this->assertSame([ + '原待办 1', + '原待办 2', + '原待办 3', + '原待办 4', + '原待办 5', + '原待办 6', + '原待办 7', + '新增待办 8', + ], $group->pluck('title')->all()); + $this->assertSame(8, (int) $group->last()->item_sequence); + } + public function test_type_and_content_cells_can_be_edited_for_the_whole_group(): void { $this->loginAs(); @@ -299,7 +345,7 @@ class SystemizationTodosTest extends FeatureTestCase { $this->loginAs(); - $this->createTodo('收入', '1、平台收入核对', '1、收入事项 A', '2026-10-26', 1, '晨曦', '栎阳、秋香'); + $this->createTodo('1、收入', '1、平台收入核对', '1、收入事项 A', '2026-10-26', 1, '晨曦', '栎阳、秋香'); $this->createTodo('收入', '平台收入核对', '2、收入事项 B', '2026-10-27', 2); $this->createTodo('成本', '3、退款核销', '3、成本事项', '2026-10-26', 3, '常仪', '山时'); $this->createTodo('费用', '4、逾期核对', '4、逾期事项', '2026-10-20', 4, '人参', '玉兔'); @@ -324,6 +370,7 @@ class SystemizationTodosTest extends FeatureTestCase ->assertSee('收入事项 B'); $pageContent = $pageResponse->viewData('content'); $this->assertContains('平台收入核对', $pageContent['todoContentOptions']['收入']); + $this->assertArrayNotHasKey('1、收入', $pageContent['todoContentOptions']); $this->assertSame( ['__overdue__', '待办'], array_column($pageContent['todoStatusOptions']->all(), 'value'), @@ -331,7 +378,7 @@ class SystemizationTodosTest extends FeatureTestCase $pageItems = $pageContent['items']; $this->assertSame( [1, 1], - $pageItems->where('category', '收入') + $pageItems->where('category_display', '收入') ->pluck('type_sequence') ->map(static fn (mixed $value): int => (int) $value) ->values() @@ -339,7 +386,7 @@ class SystemizationTodosTest extends FeatureTestCase ); $this->assertSame( [1, 2], - $pageItems->where('category', '收入') + $pageItems->where('category_display', '收入') ->pluck('item_sequence') ->map(static fn (mixed $value): int => (int) $value) ->values()