增加序号筛选并定位刚修改待办 (#586)

This commit is contained in:
yueyang 2026-10-26 13:43:22 +08:00
parent 141c518da3
commit 4cc4589d8d
3 changed files with 60 additions and 13 deletions

View File

@ -102,6 +102,13 @@ class SystemizationTodos extends Controller
->orderBy('sort_order')
->orderBy('id')
->get();
if ($filters['sequence'] > 0) {
$items = $items
->filter(static fn (SystemizationTodo $todo): bool =>
(int) $todo->category_sequence === $filters['sequence']
)
->values();
}
$base = SystemizationTodo::query();
$categories = SystemizationTodo::query()
@ -176,7 +183,7 @@ class SystemizationTodos extends Controller
$todo = SystemizationTodo::query()->create($data);
$this->storeAttachments($request, $todo);
return $this->backToPage('待办事项已新增。');
return $this->backToPage('待办事项已新增并定位。', 'success', $todo);
}
public function update(Request $request, SystemizationTodo $todo): RedirectResponse
@ -204,7 +211,7 @@ class SystemizationTodos extends Controller
$todo->update($data);
$this->storeAttachments($request, $todo);
return $this->backToPage('待办事项已更新。');
return $this->backToPage('待办事项已更新并定位。', 'success', $todo);
}
public function destroy(SystemizationTodo $todo): RedirectResponse
@ -273,6 +280,7 @@ class SystemizationTodos extends Controller
'assignees' => $this->peopleFilter('assignee'),
'start_date' => $this->normalizeDateFilter(request('start_date')),
'due_date' => $this->normalizeDateFilter(request('due_date')),
'sequence' => max(0, (int) request('sequence', 0)),
'keyword' => trim((string) request('keyword', '')),
];
}
@ -371,13 +379,22 @@ class SystemizationTodos extends Controller
}
}
private function backToPage(string $message, string $type = 'success'): RedirectResponse
private function backToPage(
string $message,
string $type = 'success',
?SystemizationTodo $focus = null,
): RedirectResponse
{
$parameters = [
'section' => 'other',
'page' => 'systemization-todos',
];
if ($focus) {
$parameters['highlight'] = $focus->id;
}
return redirect()
->route('business.pages.show', [
'section' => 'other',
'page' => 'systemization-todos',
])
->route('business.pages.show', $parameters)
->with($type === 'success' ? 'success' : 'error', $message);
}
}

View File

@ -44,6 +44,7 @@
.sys-todo-table td { padding:.72rem .6rem; border-bottom:1px solid #eee7da; background:#fff; color:#2f2a23; line-height:1.6; vertical-align:top; }
.sys-todo-table tbody tr { cursor:pointer; }
.sys-todo-table tbody tr:hover td { background:#fdfbf6; }
.sys-todo-table tbody tr.is-highlighted td { background:#fff4cf !important; }
.sys-todo-table tbody tr:focus-visible { outline:2px solid var(--sys-gold); outline-offset:-2px; }
.sys-todo-table__index-cell { width:3.6rem; min-width:3.6rem; text-align:center; }
.sys-todo-table__index { color:#6d5630; font-weight:600; font-variant-numeric:tabular-nums; white-space:nowrap; }
@ -198,6 +199,7 @@
<option value="{{ $category }}" @selected($todoFilters['category'] === $category)>{{ $category }}</option>
@endforeach
</select></label>
<label>类型内序号<input type="number" name="sequence" min="1" step="1" value="{{ $todoFilters['sequence'] ?: '' }}" placeholder="如:5"></label>
@php
$selectedOwners = $todoOwners->filter(
static fn (string $owner): bool => in_array($owner, $todoFilters['owners'], true)
@ -309,6 +311,7 @@
}
$lastItem = $items->last();
$lastSectionLabel = $items->isNotEmpty() ? ($sectionLabels[$items->count() - 1] ?? '') : '';
$highlightId = max(0, (int) request('highlight', 0));
@endphp
<div class="sys-todo-table__add">
@ -366,7 +369,7 @@
$categorySpan = $groupRowspans['category'][$loop->index] ?? 1;
$sectionSpan = $groupRowspans['section'][$loop->index] ?? 1;
@endphp
<tr tabindex="0" data-sys-todo-row-edit="{{ $todoPayloadEncoded }}" title="点击整行直接编辑">
<tr id="sys-todo-row-{{ $item->id }}" class="{{ $highlightId === (int) $item->id ? 'is-highlighted' : '' }}" tabindex="0" data-sys-todo-row-edit="{{ $todoPayloadEncoded }}" title="点击整行直接编辑">
@if ($categorySpan !== 0)
<td class="sys-todo-table__group sys-todo-table__type" @if ($categorySpan > 1) rowspan="{{ $categorySpan }}" @endif>{{ $item->category ?: '—' }}</td>
@endif
@ -899,6 +902,13 @@
new ResizeObserver(scheduleScrollRailSync).observe(tableWrap);
}
scheduleScrollRailSync();
var highlightedRow = document.querySelector('.sys-todo-table tbody tr.is-highlighted');
if (highlightedRow) {
window.setTimeout(function () {
highlightedRow.scrollIntoView({ behavior: 'smooth', block: 'center' });
highlightedRow.focus({ preventScroll: true });
}, 120);
}
screenshotInput.addEventListener('change', function () {
if (screenshotInput.files.length) {
uploadNote.textContent = '已选择 ' + screenshotInput.files.length + ' 张:' + selectedFilesLabel() + '。保存后上传。';

View File

@ -28,6 +28,7 @@ class SystemizationTodosTest extends FeatureTestCase
->assertSeeText('从 Excel 同步待办')
->assertSeeText('总负责人')
->assertSeeText('责任人')
->assertSeeText('类型内序号')
->assertSeeText('已逾期')
->assertSeeText('开始时间')
->assertSeeText('完成时间')
@ -49,7 +50,7 @@ class SystemizationTodosTest extends FeatureTestCase
->assertDontSeeText('下一页')
->assertSee('id="sysTodoImageViewer"', false);
$this->post(route('business.systemization-todos.store'), [
$storeResponse = $this->post(route('business.systemization-todos.store'), [
'category' => '收入',
'section' => '平台收入核对',
'title' => '核对淘系收入与平台账单差异',
@ -64,12 +65,13 @@ class SystemizationTodosTest extends FeatureTestCase
$this->pngUpload('first.png'),
$this->pngUpload('existing.png'),
],
])->assertRedirect(route('business.pages.show', [
'section' => 'other',
'page' => 'systemization-todos',
]));
]);
$storeResponse->assertRedirect();
$todo = SystemizationTodo::query()->firstOrFail();
$location = (string) $storeResponse->headers->get('Location');
parse_str((string) parse_url($location, PHP_URL_QUERY), $redirectQuery);
$this->assertSame((string) $todo->id, $redirectQuery['highlight'] ?? null);
$this->assertSame('收入', $todo->category);
$this->assertSame('晨曦、人参', $todo->owner);
$this->assertSame(SystemizationTodo::STATUS_IN_PROGRESS, $todo->status);
@ -220,6 +222,24 @@ class SystemizationTodosTest extends FeatureTestCase
->all(),
);
$sequenceResponse = $this->get(route('business.pages.show', [
'section' => 'other',
'page' => 'systemization-todos',
'category' => '收入',
'sequence' => 2,
]))->assertOk();
$sequenceContent = $sequenceResponse->viewData('content');
$this->assertSame(['2、收入事项 B'], $sequenceContent['items']->pluck('title')->all());
$highlightedTodo = $pageItems->firstWhere('title', '2、收入事项 B');
$this->get(route('business.pages.show', [
'section' => 'other',
'page' => 'systemization-todos',
'highlight' => $highlightedTodo->id,
]))
->assertOk()
->assertSee('id="sys-todo-row-' . $highlightedTodo->id . '" class="is-highlighted"', false);
$response = $this->get(route('business.pages.show', [
'section' => 'other',
'page' => 'systemization-todos',