ticket_page_url()); // 状态 subsubsub(完结态单独放最后,默认视图不显示已关闭工单) echo ''; // 筛选 + 搜索 echo '
'; echo ''; echo ' '; echo ' '; echo ' '; submit_button(__('筛选', 'aksrt'), 'primary', '', false); echo '
'; // 新建工单入口 printf( '

', esc_html__('代客提交工单', 'aksrt') ); $repo = \AKSRT\Ticket\TicketRepository::get_instance(); $result = $repo->paginate([ 'status' => $status === '' ? [] : [$status], 'ticket_type_id' => $type_id, 'keywords' => $s, 'limit' => self::TICKET_PER_PAGE, 'offset' => ($paged - 1) * self::TICKET_PER_PAGE, ], true); $items = $result['items']; $total = $result['total']; $open_id = isset($_GET['id']) ? absint($_GET['id']) : 0; echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; if ($items === []) { echo ''; } foreach ($items as $ticket) { $is_open = $open_id === (int) $ticket['id']; printf( '' . '' . '', esc_attr((string) $ticket['status_color']), esc_html((string) $ticket['status_label']), esc_html((string) $ticket['ticket_num']), esc_url(add_query_arg('id', (int) $ticket['id'], $base_url)), esc_html((string) $ticket['title']), esc_html((string) $ticket['ticket_type_name']), esc_html((string) $ticket['user_name']), esc_html((string) $ticket['admin_name'] !== '' ? (string) $ticket['admin_name'] : '—'), esc_html((string) $ticket['post_time']), esc_html((string) $ticket['last_reply_time'] !== '' ? (string) $ticket['last_reply_time'] : '—') ); if ($is_open) { echo ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } echo '
' . esc_html__('状态', 'aksrt') . '' . esc_html__('工单号', 'aksrt') . '' . esc_html__('标题', 'aksrt') . '' . esc_html__('部门', 'aksrt') . '' . esc_html__('用户', 'aksrt') . '' . esc_html__('跟进人', 'aksrt') . '' . esc_html__('提交时间', 'aksrt') . '' . esc_html__('最后回复', 'aksrt') . '
' . esc_html__('暂无工单', 'aksrt') . '
%s%s%s%s%s%s%s%s
' . $this->render_ticket_detail_panel($ticket) . '
'; \AKSRT\Admin\Native\AdminListPagination::render( self::TICKET_PAGE_SLUG, $total, $paged, self::TICKET_PER_PAGE, array_filter([ 'status' => $status, 'ticket_type_id' => $type_id, 's' => $s, ], static fn($value): bool => $value !== '' && $value !== 0) ); } /** * 行内展开的工单详情:沟通记录 + 回复框 + 状态迁移 + 后台备注。 * * @param array $ticket */ private function render_ticket_detail_panel(array $ticket): string { $id = (int) $ticket['id']; $repo = \AKSRT\Ticket\TicketRepository::get_instance(); $replies = $repo->replies($id); $notes = \AKSRT\Ticket\TicketNoteService::for_ticket($id); $html = '
'; // 工单正文 $html .= '
'; $html .= '

' . esc_html__('工单号', 'aksrt') . ':' . esc_html((string) $ticket['ticket_num']) . '

'; $html .= '

' . esc_html__('提交用户', 'aksrt') . ':' . esc_html((string) $ticket['user_name']) . ' (#' . esc_html((string) $ticket['user_id']) . ')

'; if ((string) $ticket['order_number'] !== '') { $html .= '

' . esc_html__('关联订单', 'aksrt') . ':' . esc_html((string) $ticket['order_number']) . '

'; } $html .= '

' . esc_html__('问题描述', 'aksrt') . ':

'; $html .= '
' . nl2br(esc_html((string) $ticket['content'])) . '
'; $html .= '
'; // 沟通记录 $html .= '

' . esc_html__('沟通记录', 'aksrt') . '

'; if ($replies === []) { $html .= '

' . esc_html__('暂无沟通记录', 'aksrt') . '

'; } $html .= '
    '; foreach ($replies as $reply) { $who = (string) $reply['author_type'] === 'admin' ? sprintf( /* translators: %s admin name */ __('管理员 %s', 'aksrt'), (string) $reply['author_name'] ) : (string) $reply['author_name']; $html .= '
  1. '; $html .= '
    ' . esc_html($who) . '' . '
    '; if (is_array($reply['quote'] ?? null)) { $quote = $reply['quote']; $html .= '
    ' . esc_html(!empty($quote['is_deleted']) ? __('原回复已删除', 'aksrt') : (string) $quote['content']) . '
    '; } $html .= '
    ' . nl2br(esc_html((string) $reply['content'])) . '
    '; $html .= '
  2. '; } $html .= '
'; // 管理员回复:已完结工单不再给回复框,只提示已关闭。 if (!empty($ticket['is_closed'])) { $html .= '

' . esc_html__('工单已关闭,无法继续回复。', 'aksrt') . '

'; } else { $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= wp_nonce_field('aksrt_ticket_reply_' . $id, '_wpnonce', true, false); $html .= '

'; $html .= '

'; $html .= '
'; } // 状态迁移 / 部门 / 跟进人 $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= wp_nonce_field('aksrt_ticket_status_' . $id, '_wpnonce', true, false); $html .= '

'; $html .= ' '; $html .= ' '; $html .= '

'; $html .= '
'; // 后台备注 $html .= '

' . esc_html__('后台备注', 'aksrt') . '

'; if ($notes === []) { $html .= '

' . esc_html__('暂无备注', 'aksrt') . '

'; } $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= ''; $html .= wp_nonce_field('aksrt_ticket_note_' . $id, '_wpnonce', true, false); $html .= '

' . '

'; $html .= '
'; $html .= '
'; return $html; } }