feat(admin): 售后操作列改为 WP 文章列表式 row-actions 悬停快捷操作(JS POST 提交,拒绝时 prompt 填备注)

This commit is contained in:
2026-10-07 08:42:07 +00:00
parent 01cd734989
commit 80fb4068d1
+34 -6
View File
@@ -437,15 +437,28 @@ class PayOrders {
} }
$images_cell = $thumbs ? implode('', $thumbs) : '—'; $images_cell = $thumbs ? implode('', $thumbs) : '—';
echo '<tr><td>' . esc_html((string) $id) . '<br><small>' . esc_html((string) ($item['created_at'] ?? '')) . '</small></td><td><a href="' . esc_url($this->page_url(self::PAGE_SLUG, ['order' => $number])) . '"><code>' . esc_html($number) . '</code></a><br><span class="description">' . esc_html($type_label) . ($order ? ' · ' . esc_html(\AKSRT\Payment\UserOrders::get_instance()->decorate_order_view($order, false)['product_name'] ?? '') : '') . '</span></td><td>' . esc_html($user ? $user->display_name . ' (#' . $uid . ')' : '#' . $uid) . '</td><td>' . $reason_cell . '</td><td>' . $materials_cell . '</td><td>' . $desc_cell . '</td><td>' . $images_cell . '</td><td>' . esc_html($refund_amount) . '</td><td>' . esc_html($status_labels[(string) $item['status']] ?? (string) $item['status']) . '</td><td>'; echo '<tr><td>' . esc_html((string) $id) . '<br><small>' . esc_html((string) ($item['created_at'] ?? '')) . '</small></td><td><a href="' . esc_url($this->page_url(self::PAGE_SLUG, ['order' => $number])) . '"><code>' . esc_html($number) . '</code></a><br><span class="description">' . esc_html($type_label) . ($order ? ' · ' . esc_html(\AKSRT\Payment\UserOrders::get_instance()->decorate_order_view($order, false)['product_name'] ?? '') : '') . '</span></td><td>' . esc_html($user ? $user->display_name . ' (#' . $uid . ')' : '#' . $uid) . '</td><td>' . $reason_cell . '</td><td>' . $materials_cell . '</td><td>' . $desc_cell . '</td><td>' . $images_cell . '</td><td>' . esc_html($refund_amount) . '</td><td>' . esc_html($status_labels[(string) $item['status']] ?? (string) $item['status']) . '</td><td>';
if ((string) $item['status'] === 'pending') foreach (['approve' => '通过', 'reject' => '拒绝'] as $decision => $label) { // 快捷操作:仿 WP 文章列表 row-actions(悬停显示),点击经 JS 以 POST 提交
echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" style="display:inline-block;vertical-align:top;margin-right:4px;"><input type="hidden" name="action" value="aksrt_after_sale_review" /><input type="hidden" name="after_sale_id" value="' . esc_attr((string) $id) . '" /><input type="hidden" name="decision" value="' . esc_attr($decision) . '" />'; wp_nonce_field('aksrt_after_sale_review_' . $id); echo '<textarea name="admin_note" rows="2" placeholder="' . esc_attr__('管理员备注', 'aksrt') . '"></textarea><br><button class="button button-small" type="submit">' . esc_html($label) . '</button></form>'; $quick_actions = [];
} if ((string) $item['status'] === 'pending') {
if ((string) $item['status'] === 'processing') { $quick_actions = ['approve' => __('通过', 'aksrt'), 'reject' => __('拒绝', 'aksrt')];
} elseif ((string) $item['status'] === 'processing') {
$gateway_result = json_decode((string) ($item['gateway_result'] ?? ''), true); $gateway_result = json_decode((string) ($item['gateway_result'] ?? ''), true);
$manual_refund = is_array($gateway_result) && sanitize_key((string) ($gateway_result['status'] ?? '')) === 'manual'; $manual_refund = is_array($gateway_result) && sanitize_key((string) ($gateway_result['status'] ?? '')) === 'manual';
foreach (($manual_refund ? ['complete' => '确认线下退款完成', 'reject' => '确认未退款并拒绝'] : ['approve' => '同步退款状态']) as $decision => $label) { $quick_actions = $manual_refund
echo '<form method="post" action="' . esc_url(admin_url('admin-post.php')) . '" style="display:inline-block;margin-right:4px;"><input type="hidden" name="action" value="aksrt_after_sale_review" /><input type="hidden" name="after_sale_id" value="' . esc_attr((string) $id) . '" /><input type="hidden" name="decision" value="' . esc_attr($decision) . '" />'; wp_nonce_field('aksrt_after_sale_review_' . $id); echo '<button class="button button-small" type="submit">' . esc_html__($label, 'aksrt') . '</button></form>'; ? ['complete' => __('确认线下退款完成', 'aksrt'), 'reject' => __('确认未退款并拒绝', 'aksrt')]
: ['approve' => __('同步退款状态', 'aksrt')];
}
if ($quick_actions) {
$links = [];
foreach ($quick_actions as $decision => $label) {
$links[] = '<span class="' . esc_attr($decision) . '"><a href="#" class="aksrt-after-sale-quick-action"'
. ' data-id="' . esc_attr((string) $id) . '"'
. ' data-decision="' . esc_attr($decision) . '"'
. ' data-label="' . esc_attr($label) . '"'
. ' data-nonce="' . esc_attr(wp_create_nonce('aksrt_after_sale_review_' . $id)) . '"'
. '>' . esc_html($label) . '</a></span>';
} }
echo '<div class="row-actions">' . implode(' | ', $links) . '</div>';
} }
if (!empty($item['admin_note'])) echo '<small>' . esc_html__('备注:', 'aksrt') . esc_html((string) $item['admin_note']) . '</small><br>'; if (!empty($item['admin_note'])) echo '<small>' . esc_html__('备注:', 'aksrt') . esc_html((string) $item['admin_note']) . '</small><br>';
if (!empty($item['gateway_result'])) { if (!empty($item['gateway_result'])) {
@@ -456,6 +469,21 @@ class PayOrders {
echo '</td></tr>'; echo '</td></tr>';
} }
echo '</tbody></table>'; echo '</tbody></table>';
echo '<script>(function(){'
. 'var postUrl=' . wp_json_encode(esc_url_raw(admin_url('admin-post.php'))) . ';'
. 'var tReject=' . wp_json_encode(__('请填写原因(将记为管理员备注,可留空):', 'aksrt')) . ';'
. 'var tConfirmA=' . wp_json_encode(__('确认执行', 'aksrt')) . ';'
. 'var tConfirmB=' . wp_json_encode(__('吗?', 'aksrt')) . ';'
. 'document.querySelectorAll(".aksrt-after-sale-quick-action").forEach(function(a){'
. 'a.addEventListener("click",function(e){e.preventDefault();'
. 'var decision=a.getAttribute("data-decision"),label=a.getAttribute("data-label"),note="";'
. 'if(decision==="reject"){note=prompt(tReject,"");if(note===null)return;}'
. 'else if(!confirm(tConfirmA+"「"+label+"」"+tConfirmB))return;'
. 'var f=document.createElement("form");f.method="post";f.action=postUrl;'
. 'var fields={action:"aksrt_after_sale_review",after_sale_id:a.getAttribute("data-id"),decision:decision,_wpnonce:a.getAttribute("data-nonce"),admin_note:note||""};'
. 'Object.keys(fields).forEach(function(k){var i=document.createElement("input");i.type="hidden";i.name=k;i.value=fields[k];f.appendChild(i);});'
. 'document.body.appendChild(f);f.submit();'
. '});});})();</script>';
} }
public function handle_after_sale_review(): void { public function handle_after_sale_review(): void {