feat(admin): streamline ticket management with dialogs

Move on-behalf ticket creation into a header dialog and load ticket handling on demand. Reuse the admin REST write path, preserve drafts and filters, and cover dialog and server boundaries with regression tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-10-31 11:25:56 +08:00
1 parent b45fd161f0
commit 264015b7e9
16 files changed
+2178 -1048

No files matched your search

+18 -6
View File
@@ -324,13 +324,16 @@ final class TicketRestAdmin {
}
$attachment = TicketAttachment::sanitize($request->get_param('attachment'));
$order_number = TicketSettings::order_link_enabled()
? sanitize_text_field((string) $request->get_param('order_number'))
: '';
$id = TicketRepository::get_instance()->create([
'ticket_num' => TicketNumber::generate(),
'user_id' => $user_id,
'title' => $title,
'ticket_type_id' => $type_id,
'content' => $content,
'order_number' => sanitize_text_field((string) $request->get_param('order_number')),
'order_number' => $order_number,
'attachment' => TicketAttachment::encode($attachment),
'status' => TicketStatusService::KEY_ADMIN_REPLIED,
'post_admin_id' => get_current_user_id(),
@@ -394,19 +397,28 @@ final class TicketRestAdmin {
}
$fields = ['status' => $to];
$type_id = absint($request->get_param('ticket_type_id'));
if ($type_id > 0 && TicketTypeService::exists($type_id)) {
if ($request->has_param('ticket_type_id')) {
$type_id = absint($request->get_param('ticket_type_id'));
if ($type_id <= 0 || !TicketTypeService::exists($type_id)) {
return new \WP_Error('aksrt_ticket_type', __('请选择有效的工单部门', 'aksrt'), ['status' => 400]);
}
$fields['ticket_type_id'] = $type_id;
}
$admin_id = absint($request->get_param('admin_id'));
if ($admin_id > 0 && get_userdata($admin_id)) {
if ($request->has_param('admin_id')) {
$admin_id = absint($request->get_param('admin_id'));
if ($admin_id > 0 && $admin_id !== (int) ($ticket['admin_id'] ?? 0)
&& (!get_userdata($admin_id) || !user_can($admin_id, 'manage_options'))) {
return new \WP_Error('aksrt_ticket_admin', __('请选择有效的管理员', 'aksrt'), ['status' => 400]);
}
$fields['admin_id'] = $admin_id;
}
$fields['updated_at'] = current_time('mysql');
if (!$repo->update_fields($id, $fields)) {
return new \WP_Error('aksrt_ticket_db', __('工单状态保存失败', 'aksrt'), ['status' => 500]);
}
$was_closed = TicketStatusService::is_closed((string) $ticket['status']);
$ticket = array_merge($ticket, $fields);
if ($to === TicketStatusService::KEY_CLOSED) {
if ($to === TicketStatusService::KEY_CLOSED && !$was_closed) {
TicketNotifier::closed($ticket, 'admin');
}
return rest_ensure_response(['success' => true, 'data' => $repo->find($id)]);