feat(ux): after-sale multi-step, ban appeal, message types, coupon wallet
Orders center gains after-sale tickets (return ship/cancel/timeline), coupon wallet list, ban-appeal page, and expanded message center tabs.
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
/**
|
||||
* Frontend ban appeal (zibll user_ban_appeal parity) on Restriction meta.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
namespace AKSRT\User;
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
class BanAppeal {
|
||||
|
||||
public const META_STATUS = 'aksrt_ban_appeal_status'; // pending|approved|rejected|''
|
||||
public const META_PAYLOAD = 'aksrt_ban_appeal_payload';
|
||||
public const META_HISTORY = 'aksrt_ban_appeal_history';
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public static function get_instance(): self {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function init(): void {
|
||||
add_action('wp_ajax_aksrt_ban_appeal_submit', [$this, 'ajax_submit']);
|
||||
add_action('wp_ajax_aksrt_ban_appeal_status', [$this, 'ajax_status']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{enabled:bool,desc:string,keys:string[]}
|
||||
*/
|
||||
public static function settings(): array {
|
||||
$all = class_exists('\AKSRT\Settings\Settings') ? (array) \AKSRT\Settings\Settings::get_all() : [];
|
||||
$keys_raw = (string) ($all['ban_appeal_keys'] ?? '');
|
||||
$keys = array_values(array_filter(array_map('trim', preg_split('/[,,\n]/', $keys_raw) ?: [])));
|
||||
return [
|
||||
'enabled' => !isset($all['user_report_enabled']) || !empty($all['user_report_enabled']),
|
||||
'desc' => (string) ($all['ban_appeal_desc'] ?? ''),
|
||||
'keys' => $keys,
|
||||
];
|
||||
}
|
||||
|
||||
public static function get_status(int $user_id): string {
|
||||
return sanitize_key((string) get_user_meta($user_id, self::META_STATUS, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public static function get_payload(int $user_id): array {
|
||||
$p = get_user_meta($user_id, self::META_PAYLOAD, true);
|
||||
return is_array($p) ? $p : [];
|
||||
}
|
||||
|
||||
public function ajax_status(): void {
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('请先登录', 'aksrt')]);
|
||||
}
|
||||
$user_id = get_current_user_id();
|
||||
$ban = class_exists('\AKSRT\User\Restriction')
|
||||
? \AKSRT\User\Restriction::get_instance()->get_active_ban($user_id)
|
||||
: null;
|
||||
wp_send_json([
|
||||
'error' => 0,
|
||||
'banned' => (bool) $ban,
|
||||
'ban' => $ban,
|
||||
'status' => self::get_status($user_id),
|
||||
'payload'=> self::get_payload($user_id),
|
||||
]);
|
||||
}
|
||||
|
||||
public function ajax_submit(): void {
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('请先登录', 'aksrt')]);
|
||||
}
|
||||
if (!check_ajax_referer('aksrt_ban_appeal', '_wpnonce', false)) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('安全校验失败', 'aksrt')]);
|
||||
}
|
||||
$user_id = get_current_user_id();
|
||||
$s = self::settings();
|
||||
if (!$s['enabled']) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('申诉功能未开启', 'aksrt')]);
|
||||
}
|
||||
|
||||
$banned = class_exists('\AKSRT\User\Restriction')
|
||||
&& \AKSRT\User\Restriction::get_instance()->is_banned($user_id);
|
||||
if (!$banned) {
|
||||
wp_send_json(['error' => 1, 'msg' => __('当前账号未处于禁封状态', 'aksrt')]);
|
||||
}
|
||||
if (self::get_status($user_id) === 'pending') {
|
||||
wp_send_json(['error' => 1, 'msg' => __('申诉正在处理中,请勿重复提交', 'aksrt')]);
|
||||
}
|
||||
|
||||
$reason_key = isset($_POST['reason_key']) ? sanitize_text_field(wp_unslash((string) $_POST['reason_key'])) : '';
|
||||
$reason = isset($_POST['reason']) ? sanitize_textarea_field(wp_unslash((string) $_POST['reason'])) : '';
|
||||
if ($reason === '') {
|
||||
wp_send_json(['error' => 1, 'msg' => __('请填写申诉说明', 'aksrt')]);
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'reason_key' => $reason_key,
|
||||
'reason' => $reason,
|
||||
'time' => current_time('Y-m-d H:i'),
|
||||
];
|
||||
update_user_meta($user_id, self::META_PAYLOAD, $payload);
|
||||
update_user_meta($user_id, self::META_STATUS, 'pending');
|
||||
|
||||
$history = get_user_meta($user_id, self::META_HISTORY, true);
|
||||
$history = is_array($history) ? $history : [];
|
||||
$history[] = $payload;
|
||||
update_user_meta($user_id, self::META_HISTORY, array_slice($history, -20));
|
||||
|
||||
// Notify admins via site message table if available.
|
||||
if (class_exists('\AKSRT\Messages\Message')) {
|
||||
$admins = get_users(['role' => 'administrator', 'fields' => 'ID', 'number' => 20]);
|
||||
$summary = sprintf(
|
||||
/* translators: 1: user login 2: reason */
|
||||
__('用户 %1$s 提交禁封申诉:%2$s', 'aksrt'),
|
||||
wp_get_current_user()->user_login,
|
||||
mb_substr($reason, 0, 80)
|
||||
);
|
||||
foreach ($admins as $admin_id) {
|
||||
\AKSRT\Messages\Message::get_instance()->send(
|
||||
(int) $admin_id,
|
||||
'ban_appeal',
|
||||
$summary,
|
||||
[
|
||||
'title' => __('禁封申诉', 'aksrt'),
|
||||
'target_url' => admin_url('users.php?page=aksrt_user_ban&tab=appeals'),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $user_id
|
||||
* @param array $payload
|
||||
*/
|
||||
do_action('aksrt_ban_appeal_submitted', $user_id, $payload);
|
||||
|
||||
wp_send_json([
|
||||
'error' => 0,
|
||||
'msg' => __('申诉已提交,请等待管理员处理', 'aksrt'),
|
||||
'reload' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user