feat(admin): open ticket creation in a dialog on the list page

Move "代客提交工单" back into a native <dialog> on the ticket list while
the ticket workspace stays a full page. Closing asks before discarding
input, ignores backdrop clicks, resets the form and returns focus; an
uncertain create result keeps the form locked behind "重新加载".

Remove the ?view=new create page route and its styles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Fable 5 committed 2026-10-31 14:57:35 +08:00
1 parent d86a85e6a6
commit 54cc5301c3
9 files changed
+169 -65

No files matched your search

@@ -28,16 +28,22 @@ test('ticket native page registers no AJAX read; writes reuse REST', () => {
assert.match(menus, /TicketSettings::enabled\(\)/);
});
test('list, workspace and create are page views, never dialogs', () => {
test('list and workspace are page views; only creation is a dialog on the list page', () => {
assert.match(center, /use UsersMenusTicketsCreate;/);
assert.doesNotMatch(center, /UsersMenusTicketsDialogs/);
assert.ok(!fs.existsSync(path.join(root, 'src/Admin/Native/UsersMenusTicketsDialogs.php')));
assert.match(center, /render_ticket_detail_page\(\$id,/);
assert.match(center, /\$view === 'new'/);
assert.match(list, /'url' => \$this->ticket_page_url\(\['view' => 'new'\]/);
assert.doesNotMatch(center + list + js, /view=new|'view' => 'new'|\$view === 'new'|render_ticket_create_page/);
assert.match(list, /'dialog' => self::TICKET_CREATE_DIALOG/);
assert.match(list, /\$this->render_ticket_create_dialog\(\);/);
assert.match(list, /ticket_page_url\(\['id' => \$id\] \+ \$context\)/);
assert.match(create, /<dialog id="' \. esc_attr\(self::TICKET_CREATE_DIALOG\)/);
assert.match(create, /ticket_form_open\('create', 0,/);
assert.doesNotMatch(center + list + detail + create + js + css, /<dialog|showModal|data-aksrt-dialog|aksrt-ticket-dialog|aksrt-ticket-modal-open/);
assert.match(js, /dialog\.showModal\(\)/);
assert.match(js, /window\.confirm\(strings\.discard\)/);
// 处理工作区不得回到弹窗。
assert.doesNotMatch(detail, /<dialog|data-aksrt-dialog/);
assert.doesNotMatch(js + css, /aksrt-ticket-detail-dialog|aksrt-ticket-modal-open|data-aksrt-ticket-panel/);
});
test('detail lookup is independent of the filtered list; paging clamps and preserves filters', () => {
@@ -78,7 +84,7 @@ test('page safety: unsaved-change guard, drafts survive the post-save reload, un
assert.match(css, /:focus-visible/);
assert.match(css, /@media \(prefers-reduced-motion: reduce\)/);
assert.match(css, /@media \(max-width: 600px\)/);
assert.doesNotMatch(css, /detail-row|row\.is-open|::backdrop/);
assert.doesNotMatch(css, /detail-row|row\.is-open/);
});
test('configuration remains in the SPA; native ops has no old config tabs', () => {