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)>
arrow_downward
-
+ @if ($canDeleteTodos)
+
+ @endif
@@ -1022,7 +1024,9 @@
@@ -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();
|