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,91 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: AKSRT - 禁封申诉
|
||||
* Template Post Type: page
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
use AKSRT\User\BanAppeal;
|
||||
use AKSRT\User\Restriction;
|
||||
|
||||
get_header();
|
||||
|
||||
if (!is_user_logged_in()) {
|
||||
$login = function_exists('aksrt_get_login_url') ? aksrt_get_login_url(get_permalink()) : wp_login_url(get_permalink());
|
||||
wp_safe_redirect($login);
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = get_current_user_id();
|
||||
$settings = class_exists(BanAppeal::class) ? BanAppeal::settings() : ['enabled' => true, 'desc' => '', 'keys' => []];
|
||||
$ban = class_exists(Restriction::class) ? Restriction::get_instance()->get_active_ban($user_id) : null;
|
||||
$status = class_exists(BanAppeal::class) ? BanAppeal::get_status($user_id) : '';
|
||||
$payload = class_exists(BanAppeal::class) ? BanAppeal::get_payload($user_id) : [];
|
||||
?>
|
||||
<main class="container page-template-ban-appeal">
|
||||
<div class="content-wrap">
|
||||
<div class="content-layout content-layout--no-sidebar">
|
||||
<div class="theme-box radius8 main-bg main-shadow box-body mb20">
|
||||
<h1 class="article-title"><?php echo esc_html(get_the_title() ?: __('禁封申诉', 'aksrt')); ?></h1>
|
||||
</div>
|
||||
|
||||
<div class="theme-box radius8 main-bg main-shadow box-body aksrt-ban-appeal">
|
||||
<?php if (!$ban) : ?>
|
||||
<div class="muted-2-color text-center" style="padding:40px 0;">
|
||||
<i class="fa fa-check-circle em2x" aria-hidden="true"></i>
|
||||
<p class="mt10"><?php esc_html_e('当前账号未处于禁封状态。', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php elseif (empty($settings['enabled'])) : ?>
|
||||
<div class="c-red"><i class="fa fa-info-circle mr6" aria-hidden="true"></i><?php esc_html_e('申诉功能暂未开启', 'aksrt'); ?></div>
|
||||
<?php elseif ($status === 'pending') : ?>
|
||||
<div class="c-red mb10"><?php esc_html_e('您的申诉正在审核中,请耐心等待。', 'aksrt'); ?></div>
|
||||
<?php if (!empty($payload['reason'])) : ?>
|
||||
<div class="muted-2-color"><?php echo esc_html(sprintf(__('申诉内容:%s', 'aksrt'), (string) $payload['reason'])); ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($payload['time'])) : ?>
|
||||
<div class="muted-2-color mt6"><?php echo esc_html(sprintf(__('提交时间:%s', 'aksrt'), (string) $payload['time'])); ?></div>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<?php if (!empty($ban['reason'])) : ?>
|
||||
<div class="muted-box mb20">
|
||||
<strong><?php esc_html_e('禁封原因', 'aksrt'); ?>:</strong>
|
||||
<?php echo esc_html((string) $ban['reason']); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($settings['desc'])) : ?>
|
||||
<div class="muted-color mb20"><?php echo wp_kses_post(nl2br(esc_html((string) $settings['desc']))); ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($status === 'rejected') : ?>
|
||||
<div class="c-red mb15"><?php esc_html_e('上次申诉未通过,可修改后重新提交。', 'aksrt'); ?></div>
|
||||
<?php endif; ?>
|
||||
<form class="aksrt-ban-appeal-form">
|
||||
<?php if (!empty($settings['keys'])) : ?>
|
||||
<div class="mb15">
|
||||
<label class="em09 muted-2-color"><?php esc_html_e('申诉类型', 'aksrt'); ?></label>
|
||||
<select name="reason_key" class="form-control">
|
||||
<?php foreach ($settings['keys'] as $key) : ?>
|
||||
<option value="<?php echo esc_attr($key); ?>"><?php echo esc_html($key); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="mb15">
|
||||
<label class="em09 muted-2-color"><?php esc_html_e('申诉说明', 'aksrt'); ?> *</label>
|
||||
<textarea name="reason" class="form-control" rows="5" required placeholder="<?php esc_attr_e('请说明误封原因或补充材料说明', 'aksrt'); ?>"><?php echo esc_textarea((string) ($payload['reason'] ?? '')); ?></textarea>
|
||||
</div>
|
||||
<?php wp_nonce_field('aksrt_ban_appeal', '_wpnonce', false); ?>
|
||||
<input type="hidden" name="action" value="aksrt_ban_appeal_submit">
|
||||
<button type="submit" class="but c-blue padding-lg">
|
||||
<i class="fa fa-paper-plane" aria-hidden="true"></i> <?php esc_html_e('提交申诉', 'aksrt'); ?>
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -53,7 +53,11 @@ $type_groups = [
|
||||
'all' => null, // special: all
|
||||
'comment' => ['comment_reply', 'comment_approved', 'pending_comments'],
|
||||
'credits' => ['credits_added', 'credits_deducted'],
|
||||
'system' => ['notice', 'download_ready', 'upload_moderation', 'verify_email'],
|
||||
'pay' => ['pay', 'order_paid', 'order_refund', 'shop_order', 'after_sale'],
|
||||
'vip' => ['vip', 'pay_vip', 'vip_expire', 'vip_upgrade'],
|
||||
'medal' => ['medal', 'badge', 'level_up'],
|
||||
'ban_appeal' => ['ban_appeal', 'user_ban', 'restriction'],
|
||||
'system' => ['notice', 'download_ready', 'upload_moderation', 'verify_email', 'auth_apply', 'auth_apply_reply'],
|
||||
'conversation' => ['conversation'],
|
||||
];
|
||||
|
||||
@@ -94,27 +98,31 @@ $offset = ($current_page - 1) * $per_page;
|
||||
$paged_items = array_slice($filtered, $offset, $per_page);
|
||||
|
||||
// 统计
|
||||
$type_counts = [
|
||||
'all' => count($all_notifications),
|
||||
'unread' => 0,
|
||||
'comment'=> 0,
|
||||
'credits'=> 0,
|
||||
'system' => 0,
|
||||
'conversation' => 0,
|
||||
];
|
||||
foreach ($all_notifications as $n) {
|
||||
$t = (string) ($n['type'] ?? 'notice');
|
||||
if (empty($n['read'])) {
|
||||
$type_counts['unread']++;
|
||||
}
|
||||
foreach (['comment', 'credits', 'system', 'conversation'] as $group) {
|
||||
if (in_array($t, $type_groups[$group], true)) {
|
||||
$type_counts[$group]++;
|
||||
$type_counts = [
|
||||
'all' => count($all_notifications),
|
||||
'unread' => 0,
|
||||
'comment' => 0,
|
||||
'credits' => 0,
|
||||
'pay' => 0,
|
||||
'vip' => 0,
|
||||
'medal' => 0,
|
||||
'ban_appeal' => 0,
|
||||
'system' => 0,
|
||||
'conversation' => 0,
|
||||
];
|
||||
foreach ($all_notifications as $n) {
|
||||
$t = (string) ($n['type'] ?? 'notice');
|
||||
if (empty($n['read'])) {
|
||||
$type_counts['unread']++;
|
||||
}
|
||||
foreach (['comment', 'credits', 'pay', 'vip', 'medal', 'ban_appeal', 'system', 'conversation'] as $group) {
|
||||
if (!empty($type_groups[$group]) && is_array($type_groups[$group]) && in_array($t, $type_groups[$group], true)) {
|
||||
$type_counts[$group]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($pm_enabled && class_exists('\AKSRT\Messages\PrivateMessage')) {
|
||||
if ($pm_enabled && class_exists('\AKSRT\Messages\PrivateMessage')) {
|
||||
// conversation count prefers live PM conversations when available
|
||||
$pm_tmp = \AKSRT\Messages\PrivateMessage::get_instance();
|
||||
if (method_exists($pm_tmp, 'get_conversations')) {
|
||||
@@ -126,17 +134,21 @@ if ($pm_enabled && class_exists('\AKSRT\Messages\PrivateMessage')) {
|
||||
}
|
||||
|
||||
$nav_items = [
|
||||
'unread' => __('未读消息', 'aksrt'),
|
||||
'all' => __('全部消息', 'aksrt'),
|
||||
'comment' => __('评论互动', 'aksrt'),
|
||||
'credits' => __('积分动态', 'aksrt'),
|
||||
'system' => __('系统通知', 'aksrt'),
|
||||
];
|
||||
if ($pm_enabled) {
|
||||
$nav_items['conversation'] = __('私信消息', 'aksrt');
|
||||
}
|
||||
'unread' => __('未读消息', 'aksrt'),
|
||||
'all' => __('全部消息', 'aksrt'),
|
||||
'comment' => __('评论互动', 'aksrt'),
|
||||
'credits' => __('积分动态', 'aksrt'),
|
||||
'pay' => __('交易通知', 'aksrt'),
|
||||
'vip' => __('会员动态', 'aksrt'),
|
||||
'medal' => __('徽章等级', 'aksrt'),
|
||||
'ban_appeal' => __('禁封申诉', 'aksrt'),
|
||||
'system' => __('系统通知', 'aksrt'),
|
||||
];
|
||||
if ($pm_enabled) {
|
||||
$nav_items['conversation'] = __('私信消息', 'aksrt');
|
||||
}
|
||||
|
||||
$icon_map = [
|
||||
$icon_map = [
|
||||
'comment_reply' => 'fas fa-comment-dots',
|
||||
'comment_approved' => 'fas fa-check-circle',
|
||||
'credits_added' => 'fas fa-coins',
|
||||
@@ -146,6 +158,18 @@ $icon_map = [
|
||||
'verify_email' => 'fas fa-envelope-open-text',
|
||||
'pending_comments' => 'fas fa-clock',
|
||||
'conversation' => 'fas fa-envelope',
|
||||
'pay' => 'fas fa-receipt',
|
||||
'order_paid' => 'fas fa-receipt',
|
||||
'order_refund' => 'fas fa-undo',
|
||||
'after_sale' => 'fas fa-undo-alt',
|
||||
'vip' => 'fas fa-crown',
|
||||
'pay_vip' => 'fas fa-crown',
|
||||
'medal' => 'fas fa-medal',
|
||||
'badge' => 'fas fa-certificate',
|
||||
'ban_appeal' => 'fas fa-gavel',
|
||||
'user_ban' => 'fas fa-ban',
|
||||
'auth_apply' => 'fas fa-id-badge',
|
||||
'auth_apply_reply' => 'fas fa-id-badge',
|
||||
'notice' => 'fas fa-bell',
|
||||
];
|
||||
|
||||
|
||||
@@ -71,6 +71,12 @@ $tabs = [
|
||||
?>
|
||||
|
||||
<!-- 5-tab navigation -->
|
||||
<div class="aksrt-orders-page__extra-nav" data-aksrt-orders-extra-nav>
|
||||
<a href="<?php echo esc_url(add_query_arg(['section' => 'after-sale'])); ?>" class="aksrt-orders-page__extra-link<?php echo (sanitize_key((string) ($_GET['section'] ?? '')) === 'after-sale') ? ' is-active' : ''; ?>"><?php esc_html_e('售后工单', 'aksrt'); ?></a>
|
||||
<a href="<?php echo esc_url(add_query_arg(['section' => 'coupons'])); ?>" class="aksrt-orders-page__extra-link<?php echo (sanitize_key((string) ($_GET['section'] ?? '')) === 'coupons') ? ' is-active' : ''; ?>"><?php esc_html_e('优惠券', 'aksrt'); ?></a>
|
||||
<a href="<?php echo esc_url(add_query_arg(['section' => 'favorites'])); ?>" class="aksrt-orders-page__extra-link<?php echo (sanitize_key((string) ($_GET['section'] ?? '')) === 'favorites') ? ' is-active' : ''; ?>"><?php esc_html_e('收藏', 'aksrt'); ?></a>
|
||||
</div>
|
||||
|
||||
<div class="aksrt-orders-page__tabs">
|
||||
<?php foreach ($tabs as $tab_key => $tab_label) :
|
||||
$is_active = $tab === $tab_key;
|
||||
@@ -231,6 +237,110 @@ $tabs = [
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Return shipping modal -->
|
||||
<div class="aksrt-modal" data-aksrt-return-ship-modal hidden>
|
||||
<div class="aksrt-modal__overlay"></div>
|
||||
<div class="aksrt-modal__dialog">
|
||||
<div class="aksrt-modal__header">
|
||||
<h3><?php esc_html_e('填写退货物流', 'aksrt'); ?></h3>
|
||||
<button type="button" class="aksrt-modal__close" data-aksrt-return-ship-close>×</button>
|
||||
</div>
|
||||
<form class="aksrt-modal__body" data-aksrt-return-ship-form>
|
||||
<input type="hidden" name="ticket_id" value="">
|
||||
<div class="aksrt-orders-page__field">
|
||||
<label><?php esc_html_e('快递公司', 'aksrt'); ?> *</label>
|
||||
<input type="text" name="carrier" class="aksrt-orders-page__input" required placeholder="<?php esc_attr_e('如:顺丰速运', 'aksrt'); ?>">
|
||||
</div>
|
||||
<div class="aksrt-orders-page__field">
|
||||
<label><?php esc_html_e('运单号', 'aksrt'); ?> *</label>
|
||||
<input type="text" name="tracking_no" class="aksrt-orders-page__input" required placeholder="<?php esc_attr_e('快递单号', 'aksrt'); ?>">
|
||||
</div>
|
||||
<div class="aksrt-modal__footer">
|
||||
<button type="button" class="btn-ghost" data-aksrt-return-ship-close><?php esc_html_e('取消', 'aksrt'); ?></button>
|
||||
<button type="submit" class="btn-primary"><?php esc_html_e('提交物流', 'aksrt'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- After-sale tickets panel -->
|
||||
<?php
|
||||
$as_section = sanitize_key((string) ($_GET['section'] ?? ''));
|
||||
if ($as_section === 'after-sale' && class_exists('\AKSRT\Payment\AfterSale')) :
|
||||
$tickets = \AKSRT\Payment\AfterSale::get_instance()->get_user_tickets($user_id, 50);
|
||||
?>
|
||||
<section class="aksrt-orders-page__aftersale" data-aksrt-aftersale-list>
|
||||
<h2><?php esc_html_e('我的售后', 'aksrt'); ?></h2>
|
||||
<?php if (!empty($tickets)) : ?>
|
||||
<div class="aksrt-as-list">
|
||||
<?php foreach ($tickets as $t) :
|
||||
$tid = (int) ($t['id'] ?? 0);
|
||||
$events = is_array($t['events'] ?? null) ? $t['events'] : [];
|
||||
$actions = is_array($t['actions'] ?? null) ? $t['actions'] : [];
|
||||
?>
|
||||
<article class="aksrt-as-card" data-aksrt-as-ticket="<?php echo esc_attr((string) $tid); ?>">
|
||||
<div class="aksrt-as-card__head">
|
||||
<strong>#<?php echo esc_html((string) $tid); ?></strong>
|
||||
<span class="aksrt-as-card__order"><?php echo esc_html((string) ($t['order_number'] ?? '')); ?></span>
|
||||
<span class="aksrt-as-card__status"><?php echo esc_html((string) ($t['status_label'] ?? $t['status'] ?? '')); ?></span>
|
||||
</div>
|
||||
<div class="aksrt-as-card__meta muted-2-color">
|
||||
<?php echo esc_html((string) ($t['type_label'] ?? $t['type'] ?? '')); ?>
|
||||
· <?php echo esc_html((string) ($t['created_at'] ?? '')); ?>
|
||||
<?php if (!empty($t['progress_label'])) : ?>
|
||||
· <?php echo esc_html((string) $t['progress_label']); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="aksrt-as-card__reason"><?php echo esc_html((string) ($t['reason'] ?? '')); ?></div>
|
||||
<?php if (!empty($t['return_shipping']['tracking_no'])) : ?>
|
||||
<div class="aksrt-as-card__ship muted-2-color">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1 carrier 2 tracking */
|
||||
esc_html__('退货物流:%1$s %2$s', 'aksrt'),
|
||||
esc_html((string) ($t['return_shipping']['carrier'] ?? '')),
|
||||
esc_html((string) $t['return_shipping']['tracking_no'])
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($events) : ?>
|
||||
<ol class="aksrt-as-timeline">
|
||||
<?php foreach (array_reverse($events) as $ev) : ?>
|
||||
<li>
|
||||
<time><?php echo esc_html((string) ($ev['time'] ?? '')); ?></time>
|
||||
<span><?php echo esc_html((string) ($ev['label'] ?? '')); ?></span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ol>
|
||||
<?php endif; ?>
|
||||
<div class="aksrt-as-card__actions">
|
||||
<?php if (!empty($actions['can_return_ship'])) : ?>
|
||||
<button type="button" class="btn-primary btn-sm" data-aksrt-return-ship="<?php echo esc_attr((string) $tid); ?>"><?php esc_html_e('填写退货物流', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($actions['can_cancel'])) : ?>
|
||||
<button type="button" class="btn-ghost btn-sm" data-aksrt-as-cancel="<?php echo esc_attr((string) $tid); ?>"><?php esc_html_e('取消售后', 'aksrt'); ?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<p class="muted-2-color"><?php esc_html_e('暂无售后记录', 'aksrt'); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Coupon wallet -->
|
||||
<?php if ($as_section === 'coupons') : ?>
|
||||
<section class="aksrt-orders-page__coupons" data-aksrt-coupon-wallet>
|
||||
<h2><?php esc_html_e('优惠券', 'aksrt'); ?></h2>
|
||||
<div class="aksrt-coupon-wallet" data-aksrt-coupon-wallet-list>
|
||||
<p class="muted-2-color"><?php esc_html_e('加载中…', 'aksrt'); ?></p>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Favorites section -->
|
||||
<?php
|
||||
$fav_tab = sanitize_key((string) ($_GET['section'] ?? ''));
|
||||
|
||||
Reference in New Issue
Block a user