diff --git a/app/Http/Controllers/Business/SystemizationTodos.php b/app/Http/Controllers/Business/SystemizationTodos.php index 8f8d7563..631dfd1f 100644 --- a/app/Http/Controllers/Business/SystemizationTodos.php +++ b/app/Http/Controllers/Business/SystemizationTodos.php @@ -45,6 +45,7 @@ class SystemizationTodos extends Controller '秋香', '待定', ]; + private const TODO_DELETE_ACCOUNTS = ['江陵', 'jiangling']; private const COLUMN_WIDTHS_SETTING = 'business.systemization_todos.column_widths'; private const COLUMN_WIDTH_KEYS = [ 'type', @@ -156,6 +157,7 @@ class SystemizationTodos extends Controller )), 'todoColumnWidths' => $this->columnWidths(), 'todoSummary' => $summary, + 'canDeleteTodos' => $this->canDeleteTodos(), 'todoRoutes' => [ 'store' => route('business.systemization-todos.store'), 'update' => route('business.systemization-todos.update', ['todo' => '__TODO__']), @@ -800,6 +802,8 @@ class SystemizationTodos extends Controller public function destroy(SystemizationTodo $todo): RedirectResponse { + abort_unless($this->canDeleteTodos(), 403, '只有江陵可以删除待办事项。'); + DB::transaction(function () use ($todo): void { $before = $this->audit->snapshot($todo, true); $todo->update(['updated_by' => user_id()]); @@ -819,6 +823,13 @@ class SystemizationTodos extends Controller return $this->backToPage('待办事项已删除。'); } + private function canDeleteTodos(): bool + { + $accountName = mb_strtolower(trim((string) (user()?->name ?? ''))); + + return in_array($accountName, self::TODO_DELETE_ACCOUNTS, true); + } + public function batchUpdateCells(Request $request): JsonResponse { $data = $request->validate([ diff --git a/resources/views/business/pages/systemization-todos.blade.php b/resources/views/business/pages/systemization-todos.blade.php index d4aa5a88..189bb053 100644 --- a/resources/views/business/pages/systemization-todos.blade.php +++ b/resources/views/business/pages/systemization-todos.blade.php @@ -728,14 +728,16 @@ @disabled((int) $item->item_sequence >= (int) $item->content_count)> - + @if ($canDeleteTodos) + + @endif @@ -1022,7 +1024,9 @@
- + @if ($canDeleteTodos) + + @endif
@@ -2032,7 +2036,7 @@ title.textContent = currentTodoId ? '编辑待办' : (payload && payload.afterSequence ? '在第 ' + payload.afterSequence + ' 条后新增待办' : '新增待办'); - deleteButton.hidden = !currentTodoId; + if (deleteButton) deleteButton.hidden = !currentTodoId; if (!currentTodoId) { payload = Object.assign({}, payload || {}); if (!payload.owner && activeTodoFilters.owners.length) { diff --git a/tests/Feature/Business/SystemizationTodosTest.php b/tests/Feature/Business/SystemizationTodosTest.php index 952fa200..95241abc 100644 --- a/tests/Feature/Business/SystemizationTodosTest.php +++ b/tests/Feature/Business/SystemizationTodosTest.php @@ -18,6 +18,7 @@ class SystemizationTodosTest extends FeatureTestCase { Storage::fake('uploads'); + $this->loginAsSystemizationTodoDeleter(); $pageResponse = $this->loginAs() ->get(route('business.pages.show', [ 'section' => 'other', @@ -1965,6 +1966,7 @@ class SystemizationTodosTest extends FeatureTestCase public function test_manual_changes_are_listed_in_operation_history_and_csv(): void { + $this->loginAsSystemizationTodoDeleter(); $this->loginAs(); $this->post(route('business.systemization-todos.store'), [ @@ -2014,6 +2016,45 @@ class SystemizationTodosTest extends FeatureTestCase $this->assertStringNotContainsString('新增:', $csv); } + public function test_only_jiangling_can_see_or_use_todo_delete_entry_points(): void + { + $this->loginAs(); + $todo = $this->createTodo('收入', '删除权限测试', '普通账号不得删除', '2026-11-30', 1); + + $this->get(route('business.pages.show', [ + 'section' => 'other', + 'page' => 'systemization-todos', + ]))->assertOk() + ->assertDontSee('data-sys-todo-grid-delete-url="', false) + ->assertDontSee('data-sys-todo-open-delete hidden', false); + + $this->withExceptionHandling() + ->delete(route('business.systemization-todos.destroy', ['todo' => $todo->id])) + ->assertForbidden(); + + $this->assertNotSoftDeleted('business_systemization_todos', ['id' => $todo->id]); + } + + public function test_jiangling_can_delete_todos(): void + { + $this->user->update(['name' => '江陵']); + $this->user->refresh(); + $this->loginAs(); + $todo = $this->createTodo('收入', '删除权限测试', '江陵可以删除', '2026-11-30', 1); + + $this->get(route('business.pages.show', [ + 'section' => 'other', + 'page' => 'systemization-todos', + ]))->assertOk() + ->assertSee('data-sys-todo-grid-delete-url="', false) + ->assertSee('data-sys-todo-open-delete hidden', false); + + $this->delete(route('business.systemization-todos.destroy', ['todo' => $todo->id])) + ->assertRedirect(); + + $this->assertSoftDeleted('business_systemization_todos', ['id' => $todo->id]); + } + public function test_operation_history_starts_from_today(): void { $this->loginAs(); @@ -2280,6 +2321,12 @@ class SystemizationTodosTest extends FeatureTestCase ]); } + private function loginAsSystemizationTodoDeleter(): void + { + $this->user->update(['name' => '江陵']); + $this->user->refresh(); + } + private function writeWorkbook(string $path, array $rows): void { $spreadsheet = new Spreadsheet();