From 0a7b33a35a7723293b53e87cb760bc965212fbbd Mon Sep 17 00:00:00 2001 From: yueyang <2495544247@qq.com> Date: Mon, 26 Oct 2026 18:29:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=B3=BB=E7=BB=9F=E5=8C=96=E5=BE=85?= =?UTF-8?q?=E5=8A=9E=E5=BA=8F=E5=8F=B7=E6=94=AF=E6=8C=81=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E7=A7=BB=E9=99=A4=E5=BA=8F=E5=8F=B7=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Business/SystemizationTodos.php | 86 +++++++++++++------ .../pages/systemization-todos.blade.php | 46 +++++----- .../Business/SystemizationTodosTest.php | 64 +++++++------- 3 files changed, 118 insertions(+), 78 deletions(-) diff --git a/app/Http/Controllers/Business/SystemizationTodos.php b/app/Http/Controllers/Business/SystemizationTodos.php index 1420c6aa..e1538461 100644 --- a/app/Http/Controllers/Business/SystemizationTodos.php +++ b/app/Http/Controllers/Business/SystemizationTodos.php @@ -106,27 +106,6 @@ class SystemizationTodos extends Controller }); $items = $items->sortBy('hierarchy_order')->values(); $positionGroups = $this->positionGroups($sequenceMap); - if ($filters['type_sequence'] > 0) { - $items = $items - ->filter(static fn (SystemizationTodo $todo): bool => - (int) $todo->type_sequence === $filters['type_sequence'] - ) - ->values(); - } - if ($filters['content_sequence'] > 0) { - $items = $items - ->filter(static fn (SystemizationTodo $todo): bool => - (int) $todo->content_sequence === $filters['content_sequence'] - ) - ->values(); - } - if ($filters['item_sequence'] > 0) { - $items = $items - ->filter(static fn (SystemizationTodo $todo): bool => - (int) $todo->item_sequence === $filters['item_sequence'] - ) - ->values(); - } $base = SystemizationTodo::query(); $categories = SystemizationTodo::query() @@ -428,7 +407,11 @@ class SystemizationTodos extends Controller ); } - private function contentSiblings(?string $category, ?string $section): Collection + private function contentSiblings( + ?string $category, + ?string $section, + ?int $excludeId = null, + ): Collection { $categoryKey = $this->hierarchyGroupKey($this->hierarchyLabel($category)); $sectionKey = $this->hierarchyGroupKey($this->hierarchyLabel($section)); @@ -439,12 +422,54 @@ class SystemizationTodos extends Controller ->lockForUpdate() ->get() ->filter(fn (SystemizationTodo $todo): bool => - $this->hierarchyGroupKey($this->hierarchyLabel($todo->category)) === $categoryKey + (int) $todo->id !== (int) $excludeId + && $this->hierarchyGroupKey($this->hierarchyLabel($todo->category)) === $categoryKey && $this->hierarchyGroupKey($this->hierarchyLabel($todo->section)) === $sectionKey ) ->values(); } + private function positionForUpdate( + SystemizationTodo $todo, + int $targetPosition, + array &$data, + ): void { + $currentCategoryKey = $this->hierarchyGroupKey($this->hierarchyLabel($todo->category)); + $currentSectionKey = $this->hierarchyGroupKey($this->hierarchyLabel($todo->section)); + $targetCategoryKey = $this->hierarchyGroupKey($this->hierarchyLabel($data['category'] ?? null)); + $targetSectionKey = $this->hierarchyGroupKey($this->hierarchyLabel($data['section'] ?? null)); + $sameGroup = $currentCategoryKey === $targetCategoryKey + && $currentSectionKey === $targetSectionKey; + + if ($sameGroup) { + $currentSiblings = $this->contentSiblings($todo->category, $todo->section); + $currentIndex = $currentSiblings->search( + static fn (SystemizationTodo $item): bool => (int) $item->id === (int) $todo->id + ); + if ($currentIndex !== false && $targetPosition === ((int) $currentIndex + 1)) { + return; + } + } + + $siblings = $this->contentSiblings( + $data['category'] ?? null, + $data['section'] ?? null, + (int) $todo->id, + ); + if ($siblings->isEmpty()) { + $insertOrder = (int) SystemizationTodo::query()->max('sort_order') + 1; + } elseif ($targetPosition <= $siblings->count()) { + $insertOrder = (int) $siblings[$targetPosition - 1]->sort_order; + } else { + $insertOrder = (int) $siblings->max('sort_order') + 1; + } + + SystemizationTodo::query() + ->where('sort_order', '>=', $insertOrder) + ->increment('sort_order'); + $data['sort_order'] = $insertOrder; + } + private function groupTodoIds(SystemizationTodo $todo, bool $includeSection): array { $categoryKey = $this->hierarchyGroupKey($this->hierarchyLabel($todo->category)); @@ -480,6 +505,7 @@ class SystemizationTodos extends Controller public function update(Request $request, SystemizationTodo $todo): RedirectResponse { $data = $this->validated($request); + $targetPosition = max(0, (int) ($data['position'] ?? 0)); unset($data['position']); $data['updated_by'] = user_id(); $this->normalizeCompletionDates($data); @@ -500,7 +526,16 @@ class SystemizationTodos extends Controller } } - $todo->update($data); + DB::transaction(function () use ($todo, $data, $targetPosition): void { + $lockedTodo = SystemizationTodo::query() + ->lockForUpdate() + ->findOrFail($todo->id); + if ($targetPosition > 0) { + $this->positionForUpdate($lockedTodo, $targetPosition, $data); + } + $lockedTodo->update($data); + $todo->setRawAttributes($lockedTodo->getAttributes(), true); + }); $this->storeAttachments($request, $todo); return $this->backToPage('待办事项已更新并定位。', 'success', $todo); @@ -572,9 +607,6 @@ class SystemizationTodos extends Controller 'assignees' => $this->peopleFilter('assignee'), 'start_date' => $this->normalizeDateFilter(request('start_date')), 'due_date' => $this->normalizeDateFilter(request('due_date')), - 'type_sequence' => max(0, (int) request('type_sequence', 0)), - 'content_sequence' => max(0, (int) request('content_sequence', 0)), - 'item_sequence' => max(0, (int) request('item_sequence', 0)), 'keyword' => trim((string) request('keyword', '')), ]; } diff --git a/resources/views/business/pages/systemization-todos.blade.php b/resources/views/business/pages/systemization-todos.blade.php index 2c555b77..380637b1 100644 --- a/resources/views/business/pages/systemization-todos.blade.php +++ b/resources/views/business/pages/systemization-todos.blade.php @@ -215,9 +215,6 @@ @endforeach - - - @php $selectedOwners = $todoOwners->filter( static fn (string $owner): bool => in_array($owner, $todoFilters['owners'], true) @@ -345,7 +342,7 @@ - + @@ -363,6 +360,7 @@ }; $todoPayload = [ 'id' => $item->id, + 'position' => (int) $item->item_sequence, 'category' => $item->category ?? '', 'section' => $sectionLabels[$loop->index] ?? '', 'title' => $titleLabels[$loop->index] ?? '', @@ -489,7 +487,7 @@ - ', false) + ->assertSee('', false) ->assertSee('sys-todo-table__type', false) ->assertSee('title="类型序号">1', false) ->assertSee('title="内容序号">1', false) @@ -320,22 +350,6 @@ class SystemizationTodosTest extends FeatureTestCase ->all(), ); - $sequenceResponse = $this->get(route('business.pages.show', [ - 'section' => 'other', - 'page' => 'systemization-todos', - 'category' => '收入', - 'item_sequence' => 2, - ]))->assertOk(); - $sequenceContent = $sequenceResponse->viewData('content'); - $this->assertSame(['2、收入事项 B'], $sequenceContent['items']->pluck('title')->all()); - - $typeSequenceContent = $this->get(route('business.pages.show', [ - 'section' => 'other', - 'page' => 'systemization-todos', - 'type_sequence' => 2, - ]))->assertOk()->viewData('content'); - $this->assertSame(['3、成本事项'], $typeSequenceContent['items']->pluck('title')->all()); - $highlightedTodo = $pageItems->firstWhere('title', '2、收入事项 B'); $this->get(route('business.pages.show', [ 'section' => 'other', @@ -430,16 +444,6 @@ class SystemizationTodosTest extends FeatureTestCase ->values() ->all(), ); - $contentResponse = $this->get(route('business.pages.show', [ - 'section' => 'other', - 'page' => 'systemization-todos', - 'type_sequence' => 1, - 'content_sequence' => 2, - ]))->assertOk(); - $this->assertSame( - [$secondContent->id], - $contentResponse->viewData('content')['items']->pluck('id')->all(), - ); $this->assertSame( [$completed->id, $inProgress->id], $items -- 2.47.2
类型内容待办序号待办事项总负责人责任人类型内容待办事项序号待办事项总负责人责任人 开始时间完成时间状态完成情况完成截图备注
内容待办序号待办事项内容待办事项序号待办事项