导入 AKSRT 主题开发源码

This commit is contained in:
Claude Code committed 2026-07-03 22:50:34 +08:00
1 parent 9681dd3d48
commit 1268a55dd0
595 files changed
+127705

No files matched your search

+68
View File
@@ -0,0 +1,68 @@
<?php
/**
* Template Name: AKSRT - Archives
* Template Post Type: page
*
* 文章归档页:按年月分组展示全站文章。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
global $wpdb;
?>
<main id="main-content" class="container page-content-default" tabindex="-1">
<header class="page-header">
<h1 class="entry-title"><?php esc_html_e('文章归档', 'aksrt'); ?></h1>
</header>
<div class="content-wrap">
<div class="content-layout content-layout--no-sidebar">
<div class="content-layout__primary">
<div class="aksrt-archives container">
<?php
$years = $wpdb->get_results(
"SELECT DISTINCT YEAR(post_date) AS year, MONTH(post_date) AS month, COUNT(*) AS count
FROM {$wpdb->posts}
WHERE post_type = 'post' AND post_status = 'publish'
GROUP BY YEAR(post_date), MONTH(post_date)
ORDER BY year DESC, month DESC"
); // phpcs:ignore WordPress.DB.DirectDatabaseQuery
$current_year = 0;
foreach ($years as $row) :
if ((int) $row->year !== $current_year) :
$current_year = (int) $row->year;
?>
<h2 class="aksrt-archives__year"><?php echo esc_html($current_year); ?></h2>
<?php endif; ?>
<h3 class="aksrt-archives__month">
<?php echo esc_html(sprintf('%d 月 (%d 篇)', (int) $row->month, (int) $row->count)); ?>
</h3>
<ul class="aksrt-archives__list">
<?php
$month_posts = get_posts([
'year' => (int) $row->year,
'monthnum' => (int) $row->month,
'posts_per_page' => -1,
'post_status' => 'publish',
]);
foreach ($month_posts as $mp) :
?>
<li class="aksrt-archives__item">
<span class="aksrt-archives__date"><?php echo esc_html(get_the_date('m-d', $mp)); ?></span>
<a href="<?php echo esc_url(get_permalink($mp->ID)); ?>" class="aksrt-archives__link"><?php echo esc_html($mp->post_title); ?></a>
</li>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
</div>
</div>
</div>
</main>
<?php
get_footer();
+139
View File
@@ -0,0 +1,139 @@
<?php
/**
* Template Name: AKSRT - Bind Account
* Template Post Type: page
*
* Theme auth route template: /bind-account/
*
* 第三方登录未匹配账号时的绑定页面
* 用户输入已有账号密码完成OAuth绑定
*
* @package AKSRT
*/
// ============================================
// 处理绑定请求(POST)
// ============================================
$bind_error = '';
$bind_verify_url = '';
$oauth_data = null;
$provider_name = '';
$obk = '';
if (isset($_GET['obk'])) {
$obk = sanitize_text_field($_GET['obk']);
$oauth_data = AKSRT_Auth_Service::get_oauth_bind_context($obk);
}
if (! $oauth_data || ! is_array($oauth_data)) {
// 无效或已过期的OAuth数据
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$bind_error = __('绑定会话已过期,请重新使用第三方登录', 'aksrt');
}
} else {
$provider_name = AKSRT_Auth_Service::get_oauth_provider_name($oauth_data['provider'] ?? '');
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['log'], $_POST['pwd']) && empty($bind_error)) {
if ($obk === '' && !empty($_POST['obk'])) {
$obk = sanitize_text_field($_POST['obk']);
}
if ($oauth_data === null && $obk !== '') {
$oauth_data = AKSRT_Auth_Service::get_oauth_bind_context($obk);
}
$result = AKSRT_Auth_Service::bind_oauth_account($_POST, $oauth_data);
if (empty($result['success'])) {
$bind_error = $result['error'] ?? __('绑定失败,请稍后重试', 'aksrt');
$bind_verify_url = $result['verify_url'] ?? '';
} else {
$user = $result['user'];
$provider = $result['provider'];
wp_safe_redirect(add_query_arg(['tab' => 'settings', 'oauth_bound' => $provider], aksrt_get_user_center_url()));
exit;
}
}
get_header();
?>
<main id="main-content" class="site-main" tabindex="-1">
<div class="auth-shell">
<div class="auth-card">
<?php if (! $oauth_data || ! is_array($oauth_data)) : ?>
<!-- 会话过期状态 -->
<div class="auth-card__expired">
<div class="auth-card__logo" aria-hidden="true">AK</div>
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
<p><?php echo esc_html(__('绑定会话已过期或无效', 'aksrt')); ?></p>
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>" class="btn-primary btn-lg auth-card__expired-action">
<?php esc_html_e('返回登录', 'aksrt'); ?>
</a>
</div>
<?php else : ?>
<!-- 正常绑定表单 -->
<div class="auth-card__logo" aria-hidden="true">AK</div>
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
<p class="auth-card__subtitle">
<?php printf(esc_html__('通过 %s 登录,请绑定你的已有账号', 'aksrt'), '<strong>' . esc_html($provider_name) . '</strong>'); ?>
</p>
<?php if (!empty($bind_error)) : ?>
<div class="alert alert--error" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
<span>
<?php echo esc_html($bind_error); ?>
<?php if (!empty($bind_verify_url)) : ?>
<a href="<?php echo esc_url($bind_verify_url); ?>"><?php esc_html_e('前往验证邮箱', 'aksrt'); ?></a>
<?php endif; ?>
</span>
</div>
<?php endif; ?>
<form class="auth-form" id="aksrt-bind-form" method="post" action="">
<?php wp_nonce_field('aksrt_bind', '_bind_nonce'); ?>
<input type="hidden" name="obk" value="<?php echo esc_attr($obk); ?>">
<div class="form-field">
<label for="bind_user_login"><?php esc_html_e('邮箱 / 用户名', 'aksrt'); ?></label>
<div class="input-wrap">
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
<input type="text" name="log" id="bind_user_login" autocomplete="username" required>
</div>
</div>
<div class="form-field form-field--pwd">
<label for="bind_user_pass"><?php esc_html_e('密码', 'aksrt'); ?></label>
<div class="input-wrap">
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>
<input type="password" name="pwd" id="bind_user_pass" autocomplete="current-password" required>
<button type="button" class="toggle-pwd" data-target="bind_user_pass" aria-label="<?php esc_attr_e('显示或隐藏密码', 'aksrt'); ?>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10 7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg></button>
</div>
</div>
<?php if (function_exists('aksrt_render_captcha')) : ?>
<?php aksrt_render_captcha('bind'); ?>
<?php endif; ?>
<button type="submit" name="wp-submit" class="btn-primary btn-lg" style="width:100%;margin-top:8px;">
<?php esc_html_e('绑定并登录', 'aksrt'); ?>
</button>
</form>
<?php if (get_option('users_can_register')) :
$register_url = aksrt_get_register_url();
$register_url = add_query_arg('obk', sanitize_text_field($_GET['obk']), $register_url);
?>
<p class="auth-footer-link">
<?php esc_html_e('还没有账号?', 'aksrt'); ?>
<a href="<?php echo esc_url($register_url); ?>"><?php esc_html_e('注册并绑定账号', 'aksrt'); ?></a>
</p>
<?php endif; ?>
<?php endif; ?><!-- end 正常绑定表单 -->
</div>
</div>
</main>
<?php
get_footer();
+281
View File
@@ -0,0 +1,281 @@
<?php
/**
* Template Name: AKSRT - Cart
* Template Post Type: page
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
if (!is_user_logged_in()) {
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
wp_safe_redirect($login_url);
exit;
}
$cart_view = function_exists('aksrt_get_cart_page_view')
? aksrt_get_cart_page_view(get_current_user_id())
: [
'payment_methods' => [],
'shipping_methods' => [],
'address_book' => [],
'coupon_enabled' => false,
'currency_symbol' => '¥',
'pending_orders' => [],
];
$pending_orders = is_array($cart_view['pending_orders'] ?? null) ? $cart_view['pending_orders'] : [];
$shipping_methods = is_array($cart_view['shipping_methods'] ?? null) ? array_values($cart_view['shipping_methods']) : [];
$payment_methods = is_array($cart_view['payment_methods'] ?? null) ? array_values($cart_view['payment_methods']) : [];
$address_book = is_array($cart_view['address_book'] ?? null) ? $cart_view['address_book'] : [];
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
<div
class="aksrt-cart-page container"
data-aksrt-cart-page
data-currency-symbol="<?php echo esc_attr((string) ($cart_view['currency_symbol'] ?? '¥')); ?>"
data-coupon-enabled="<?php echo !empty($cart_view['coupon_enabled']) ? '1' : '0'; ?>"
>
<div class="aksrt-cart-page__header">
<div>
<h1 class="aksrt-cart-page__title"><?php esc_html_e('购物车', 'aksrt'); ?></h1>
<p class="aksrt-cart-page__subtitle"><?php esc_html_e('在下单前确认地址、运费、优惠券和支付方式。', 'aksrt'); ?></p>
</div>
<?php if (!empty($pending_orders)) : ?>
<div class="aksrt-cart-page__pending">
<span class="aksrt-cart-page__pending-label"><?php esc_html_e('待支付订单', 'aksrt'); ?></span>
<div class="aksrt-cart-page__pending-list">
<?php foreach ($pending_orders as $pending_order) : ?>
<button
type="button"
class="aksrt-cart-page__pending-chip"
data-aksrt-resume-order="<?php echo esc_attr((string) ($pending_order['order_number'] ?? '')); ?>"
>
<?php echo esc_html((string) ($pending_order['order_number'] ?? '')); ?>
</button>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
</div>
<div class="aksrt-cart-page__layout">
<section class="aksrt-cart-page__main">
<div class="aksrt-cart-page__panel">
<div class="aksrt-cart-page__panel-head">
<h2><?php esc_html_e('商品清单', 'aksrt'); ?></h2>
<button type="button" class="btn-ghost btn-sm" data-aksrt-clear-cart><?php esc_html_e('清空购物车', 'aksrt'); ?></button>
</div>
<div class="aksrt-cart-page__items" data-aksrt-cart-items>
<div class="aksrt-cart-page__empty">
<i class="fas fa-shopping-cart" aria-hidden="true"></i>
<p><?php esc_html_e('购物车为空,去商品页添加想购买的内容。', 'aksrt'); ?></p>
<a href="<?php echo esc_url(home_url('/')); ?>" class="btn-outline btn-sm"><?php esc_html_e('继续浏览', 'aksrt'); ?></a>
</div>
</div>
</div>
<div class="aksrt-cart-page__grid">
<section class="aksrt-cart-page__panel">
<div class="aksrt-cart-page__panel-head">
<h2><?php esc_html_e('收货地址', 'aksrt'); ?></h2>
<button type="button" class="btn-ghost btn-sm" data-aksrt-address-add>
<i class="fas fa-plus" aria-hidden="true"></i> <?php esc_html_e('新增地址', 'aksrt'); ?>
</button>
</div>
<div class="aksrt-cart-page__option-list" data-aksrt-address-list>
<?php if (empty($address_book)) : ?>
<div class="aksrt-cart-page__address-empty" data-aksrt-address-empty>
<i class="fas fa-map-marker-alt" aria-hidden="true"></i>
<p><?php esc_html_e('暂无收货地址,请先新增。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<?php foreach ($address_book as $index => $address) : ?>
<div class="aksrt-cart-page__option-card aksrt-cart-page__address-card" data-aksrt-address-card="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>">
<label class="aksrt-cart-page__address-label">
<input
type="radio"
name="aksrt_cart_address"
value="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"
<?php checked($index === 0 || !empty($address['is_default'])); ?>
>
<span class="aksrt-cart-page__option-body">
<strong>
<?php echo esc_html((string) ($address['name'] ?? '')); ?>
<?php if (!empty($address['is_default'])) : ?>
<span class="aksrt-cart-page__default-tag"><?php esc_html_e('默认', 'aksrt'); ?></span>
<?php endif; ?>
</strong>
<span><?php echo esc_html((string) ($address['phone'] ?? '')); ?></span>
<span><?php echo esc_html((string) ($address['full_text'] ?? '')); ?></span>
</span>
</label>
<div class="aksrt-cart-page__address-actions">
<button type="button" class="btn-ghost btn-xs" data-aksrt-address-edit="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"><?php esc_html_e('编辑', 'aksrt'); ?></button>
<button type="button" class="btn-ghost btn-xs" data-aksrt-address-delete="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"><?php esc_html_e('删除', 'aksrt'); ?></button>
<?php if (empty($address['is_default'])) : ?>
<button type="button" class="btn-ghost btn-xs" data-aksrt-address-set-default="<?php echo esc_attr((string) ($address['id'] ?? 0)); ?>"><?php esc_html_e('设为默认', 'aksrt'); ?></button>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</section>
<!-- Address Editor Modal -->
<div class="aksrt-modal" data-aksrt-address-modal hidden>
<div class="aksrt-modal__overlay"></div>
<div class="aksrt-modal__dialog">
<div class="aksrt-modal__header">
<h3 data-aksrt-address-modal-title><?php esc_html_e('新增地址', 'aksrt'); ?></h3>
<button type="button" class="aksrt-modal__close" data-aksrt-address-modal-close>&times;</button>
</div>
<form class="aksrt-modal__body" data-aksrt-address-form>
<input type="hidden" name="address_id" value="">
<div class="aksrt-cart-page__field">
<label><?php esc_html_e('收货人', 'aksrt'); ?> *</label>
<input type="text" name="name" class="aksrt-cart-page__input" required maxlength="50">
</div>
<div class="aksrt-cart-page__field">
<label><?php esc_html_e('手机号', 'aksrt'); ?> *</label>
<input type="tel" name="phone" class="aksrt-cart-page__input" required maxlength="20">
</div>
<div class="aksrt-cart-page__field-row">
<div class="aksrt-cart-page__field">
<label><?php esc_html_e('省份', 'aksrt'); ?></label>
<input type="text" name="province" class="aksrt-cart-page__input" maxlength="50">
</div>
<div class="aksrt-cart-page__field">
<label><?php esc_html_e('城市', 'aksrt'); ?></label>
<input type="text" name="city" class="aksrt-cart-page__input" maxlength="50">
</div>
<div class="aksrt-cart-page__field">
<label><?php esc_html_e('区/县', 'aksrt'); ?></label>
<input type="text" name="district" class="aksrt-cart-page__input" maxlength="50">
</div>
</div>
<div class="aksrt-cart-page__field">
<label><?php esc_html_e('详细地址', 'aksrt'); ?> *</label>
<input type="text" name="address" class="aksrt-cart-page__input" required maxlength="200">
</div>
<label class="aksrt-cart-page__checkbox">
<input type="checkbox" name="is_default" value="1">
<span><?php esc_html_e('设为默认地址', 'aksrt'); ?></span>
</label>
<div class="aksrt-modal__footer">
<button type="button" class="btn-ghost" data-aksrt-address-modal-close><?php esc_html_e('取消', 'aksrt'); ?></button>
<button type="submit" class="btn-primary"><?php esc_html_e('保存地址', 'aksrt'); ?></button>
</div>
</form>
</div>
</div>
<section class="aksrt-cart-page__panel">
<div class="aksrt-cart-page__panel-head">
<h2><?php esc_html_e('配送与支付', 'aksrt'); ?></h2>
</div>
<div class="aksrt-cart-page__option-columns">
<div>
<h3 class="aksrt-cart-page__mini-title"><?php esc_html_e('配送方式', 'aksrt'); ?></h3>
<div class="aksrt-cart-page__option-list" data-aksrt-shipping-list>
<?php foreach ($shipping_methods as $index => $method) : ?>
<label class="aksrt-cart-page__option-card">
<input
type="radio"
name="aksrt_cart_shipping"
value="<?php echo esc_attr((string) ($method['value'] ?? '')); ?>"
<?php checked($index === 0); ?>
>
<span class="aksrt-cart-page__option-body">
<strong><?php echo esc_html((string) ($method['label'] ?? '')); ?></strong>
<span><?php echo esc_html((string) ($method['description'] ?? '')); ?></span>
</span>
</label>
<?php endforeach; ?>
</div>
</div>
<div>
<h3 class="aksrt-cart-page__mini-title"><?php esc_html_e('支付方式', 'aksrt'); ?></h3>
<div class="aksrt-cart-page__option-list" data-aksrt-payment-list>
<?php foreach ($payment_methods as $index => $method) : ?>
<label class="aksrt-cart-page__option-card">
<input
type="radio"
name="aksrt_cart_payment"
value="<?php echo esc_attr((string) ($method['value'] ?? '')); ?>"
<?php checked($index === 0); ?>
>
<span class="aksrt-cart-page__option-body">
<strong><?php echo esc_html((string) ($method['label'] ?? '')); ?></strong>
<span><?php echo esc_html((string) ($method['description'] ?? '')); ?></span>
</span>
</label>
<?php endforeach; ?>
</div>
</div>
</div>
</section>
<section class="aksrt-cart-page__panel">
<div class="aksrt-cart-page__panel-head">
<h2><?php esc_html_e('优惠与备注', 'aksrt'); ?></h2>
</div>
<div class="aksrt-cart-page__coupon-box">
<label class="aksrt-cart-page__field">
<span><?php esc_html_e('优惠券', 'aksrt'); ?></span>
<div class="aksrt-cart-page__coupon-row">
<input type="text" class="aksrt-cart-page__input" data-aksrt-coupon-code placeholder="<?php esc_attr_e('输入优惠码后试算', 'aksrt'); ?>">
<button type="button" class="btn-outline btn-sm" data-aksrt-preview-checkout><?php esc_html_e('应用并试算', 'aksrt'); ?></button>
</div>
</label>
<p class="aksrt-cart-page__hint" data-aksrt-preview-message><?php esc_html_e('试算后会展示优惠抵扣、运费和最终应付金额。', 'aksrt'); ?></p>
<label class="aksrt-cart-page__field">
<span><?php esc_html_e('订单备注', 'aksrt'); ?></span>
<textarea class="aksrt-cart-page__textarea" data-aksrt-customer-note rows="4" placeholder="<?php esc_attr_e('例如发票要求、发货备注等。', 'aksrt'); ?>"></textarea>
</label>
</div>
</section>
</div>
</section>
<aside class="aksrt-cart-page__sidebar">
<section class="aksrt-cart-page__panel aksrt-cart-page__summary">
<div class="aksrt-cart-page__panel-head">
<h2><?php esc_html_e('订单摘要', 'aksrt'); ?></h2>
</div>
<dl class="aksrt-cart-page__summary-list">
<div>
<dt><?php esc_html_e('商品小计', 'aksrt'); ?></dt>
<dd data-aksrt-summary-subtotal>¥0.00</dd>
</div>
<div>
<dt><?php esc_html_e('运费', 'aksrt'); ?></dt>
<dd data-aksrt-summary-shipping>¥0.00</dd>
</div>
<div>
<dt><?php esc_html_e('优惠抵扣', 'aksrt'); ?></dt>
<dd data-aksrt-summary-discount>-¥0.00</dd>
</div>
</dl>
<div class="aksrt-cart-page__summary-total">
<span><?php esc_html_e('应付总额', 'aksrt'); ?></span>
<strong data-aksrt-summary-total>¥0.00</strong>
</div>
<button type="button" class="btn-primary btn-lg aksrt-cart-page__submit" data-aksrt-create-order disabled>
<?php esc_html_e('创建订单', 'aksrt'); ?>
</button>
</section>
</aside>
</div>
</div>
</main>
<?php get_footer(); ?>
+130
View File
@@ -0,0 +1,130 @@
<?php
/**
* Template Name: AKSRT - Categories
* Template Post Type: page
*
* 分类汇总页面:列出全站所有分类。
*
* 用法:在后台新建一个 Page,标题任意(默认显示页面标题,否则用"分类目录"),
* 模板选择 "AKSRT - Categories";或将 slug 设为 "categories" 自动匹配。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
// ─── 数据准备 ─────────────────────────────────────────────
$all_terms = get_terms([
'taxonomy' => 'category',
'hide_empty' => false, // 全部展示,含 0 篇文章的分类
'orderby' => 'menu_order name',
'order' => 'ASC',
]);
if (is_wp_error($all_terms)) {
$all_terms = [];
}
$top_level = [];
$children_by_parent = [];
foreach ($all_terms as $term) {
if ((int) $term->parent === 0) {
$top_level[] = $term;
} else {
$children_by_parent[(int) $term->parent][] = $term;
}
}
$total_cats = count($all_terms);
$total_counts = wp_count_posts();
$total_posts = $total_counts && isset($total_counts->publish) ? (int) $total_counts->publish : 0;
$page_title = trim((string) get_the_title());
if ($page_title === '') {
$page_title = __('分类目录', 'aksrt');
}
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
<?php if (function_exists('aksrt_breadcrumbs')) {
aksrt_breadcrumbs();
} ?>
<header class="page-header aksrt-cats-header">
<h1 class="entry-title"><?php echo esc_html($page_title); ?></h1>
<p class="aksrt-cats-header__meta">
<?php
printf(
/* translators: 1: total category count, 2: total published post count */
esc_html__('共 %1$d 个分类 · 共 %2$d 篇文章', 'aksrt'),
$total_cats,
$total_posts
);
?>
</p>
</header>
<?php if (!empty($top_level)) : ?>
<section class="aksrt-cats-grid" aria-label="<?php esc_attr_e('分类列表', 'aksrt'); ?>">
<?php foreach ($top_level as $cat) :
$cat_id = (int) $cat->term_id;
$cat_link = get_category_link($cat_id);
$cover_url = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_category_cover_url($cat_id)
: (get_template_directory_uri() . '/assets/img/placeholder.svg');
$desc = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_category_recommend_desc($cat_id)
: (string) $cat->description;
$children = $children_by_parent[$cat_id] ?? [];
?>
<article class="aksrt-cat-card">
<a class="aksrt-cat-card__cover"
href="<?php echo esc_url($cat_link); ?>"
style="background-image: url('<?php echo esc_url($cover_url); ?>');"
aria-label="<?php echo esc_attr($cat->name); ?>">
<span class="aksrt-cat-card__count-badge">
<?php printf(esc_html__('%d 篇', 'aksrt'), (int) $cat->count); ?>
</span>
</a>
<div class="aksrt-cat-card__body">
<h2 class="aksrt-cat-card__title">
<a href="<?php echo esc_url($cat_link); ?>"><?php echo esc_html($cat->name); ?></a>
</h2>
<?php if ($desc !== '') : ?>
<p class="aksrt-cat-card__desc"><?php echo esc_html(wp_trim_words(wp_strip_all_tags($desc), 40, '…')); ?></p>
<?php endif; ?>
<?php if (!empty($children)) : ?>
<ul class="aksrt-cat-card__children" aria-label="<?php esc_attr_e('子分类', 'aksrt'); ?>">
<?php foreach ($children as $child) : ?>
<li>
<a href="<?php echo esc_url(get_category_link((int) $child->term_id)); ?>">
<span class="aksrt-cat-card__child-name"><?php echo esc_html($child->name); ?></span>
<span class="aksrt-cat-card__child-count"><?php echo (int) $child->count; ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
</article>
<?php endforeach; ?>
</section>
<?php else : ?>
<div class="no-results aksrt-cats-empty">
<p><?php esc_html_e('暂无分类。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<p class="aksrt-cats-footer">
<a class="btn-outline" href="<?php echo esc_url(home_url('/')); ?>">
<?php esc_html_e('返回首页', 'aksrt'); ?>
</a>
</p>
</main>
<?php
get_footer();
+167
View File
@@ -0,0 +1,167 @@
<?php
/**
* Template Name: AKSRT - Document Navigation
* Template Post Type: page
*
* 文档导航页:文档站式导航。
* 支持侧边章节树、当前章节高亮、索引卡片、最近更新列表、基础搜索。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
// Read doc mode settings
$doc_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_docs_mode_settings() : [];
$default_order = $doc_settings['default_order'] ?? 'menu_order';
$presenter = class_exists('AKSRT_Docs_Presenter') ? AKSRT_Docs_Presenter::get_instance() : null;
// Get root-level pages
$pages = $presenter
? $presenter->get_root_pages($default_order)
: get_pages([
'sort_column' => $default_order === 'title' ? 'post_title' : ($default_order === 'date' ? 'post_date' : 'menu_order, post_title'),
'sort_order' => 'ASC',
'parent' => 0,
'hierarchical' => 0,
'post_status' => 'publish',
]);
// Recent updates
$recent_pages = $presenter
? $presenter->get_recent_pages(8)
: get_pages([
'sort_column' => 'post_modified',
'sort_order' => 'DESC',
'number' => 8,
'post_status' => 'publish',
]);
$show_sidebar = !empty($doc_settings['toc_enabled']) || !empty($recent_pages);
?>
<main id="main-content" class="container page-content-default" tabindex="-1">
<header class="aksrt-doc-nav-header">
<h1 class="aksrt-doc-nav-header__title"><?php echo esc_html(get_the_title() ?: __('文档导航', 'aksrt')); ?></h1>
<?php $desc = get_the_excerpt(); if ($desc) : ?>
<p class="aksrt-doc-nav-header__desc"><?php echo esc_html($desc); ?></p>
<?php endif; ?>
</header>
<div class="aksrt-doc-nav container" data-aksrt-doc-page-id="<?php echo (int) get_the_ID(); ?>">
<div class="content-wrap">
<div class="content-layout<?php echo $show_sidebar && !empty($recent_pages) ? '' : ' content-layout--no-sidebar'; ?>">
<div class="content-layout__primary">
<!-- Quick search -->
<div class="aksrt-doc-nav__search">
<input type="text" class="aksrt-doc-nav__search-input" placeholder="<?php esc_attr_e('搜索文档...', 'aksrt'); ?>" id="aksrt-doc-search">
<i class="fas fa-search aksrt-doc-nav__search-icon"></i>
</div>
<div class="aksrt-doc-search__results" data-aksrt-doc-search-results hidden></div>
<?php if (!empty($pages)) : ?>
<!-- Toolbar: category chips -->
<div class="aksrt-doc-toolbar">
<div class="aksrt-doc-toolbar__chips">
<button type="button" class="aksrt-doc-toolbar__chip is-active" data-cat-id="0"><?php esc_html_e('全部', 'aksrt'); ?></button>
<?php foreach ($pages as $p) : ?>
<button type="button" class="aksrt-doc-toolbar__chip" data-cat-id="<?php echo (int) $p->ID; ?>"><?php echo esc_html($p->post_title); ?></button>
<?php endforeach; ?>
</div>
<span class="aksrt-doc-toolbar__meta"><?php printf(esc_html__('%d 篇文档', 'aksrt'), count($pages)); ?></span>
</div>
<?php endif; ?>
<div class="aksrt-doc-nav__layout">
<!-- Document index cards -->
<div class="aksrt-doc-nav__main">
<?php if (!empty($pages)) : ?>
<div class="aksrt-doc-nav__grid">
<?php foreach ($pages as $p) :
$children = $presenter
? $presenter->get_flat_tree($p->ID, 1)
: get_pages([
'child_of' => $p->ID,
'sort_column' => 'menu_order',
'sort_order' => 'ASC',
'parent' => $p->ID,
'post_status' => 'publish',
]);
$child_count = count($children);
$thumb = get_the_post_thumbnail_url($p->ID, 'medium');
$excerpt = wp_trim_words($p->post_excerpt, 30, '...');
?>
<a href="<?php echo esc_url(get_permalink($p->ID)); ?>" class="aksrt-doc-index-card" data-cat-id="<?php echo (int) $p->ID; ?>">
<?php if ($thumb) : ?>
<div class="aksrt-doc-index-card__thumb">
<img src="<?php echo esc_url($thumb); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
</div>
<?php else : ?>
<div class="aksrt-doc-index-card__icon">
<i class="fas fa-book-open"></i>
</div>
<?php endif; ?>
<div class="aksrt-doc-index-card__body">
<h3 class="aksrt-doc-index-card__title"><?php echo esc_html($p->post_title); ?></h3>
<?php if ($excerpt) : ?>
<p class="aksrt-doc-index-card__desc"><?php echo esc_html($excerpt); ?></p>
<?php endif; ?>
<div class="aksrt-doc-index-card__meta">
<?php if ($child_count > 0) : ?>
<span class="aksrt-doc-index-card__count">
<i class="fas fa-file-alt"></i>
<?php printf(esc_html__('%d 篇文章', 'aksrt'), $child_count); ?>
</span>
<?php endif; ?>
<span class="aksrt-doc-index-card__date">
<i class="fas fa-clock"></i>
<?php echo esc_html(get_the_date('', $p->ID)); ?>
</span>
</div>
</div>
<i class="fas fa-chevron-right aksrt-doc-index-card__arrow"></i>
</a>
<?php endforeach; ?>
</div>
<?php else : ?>
<div class="aksrt-doc-nav__empty">
<i class="fas fa-book-open"></i>
<p><?php esc_html_e('暂无文档页面。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
</div>
<!-- Sidebar: Recent updates -->
<?php if ($show_sidebar && !empty($recent_pages)) : ?>
<aside class="aksrt-doc-nav__sidebar sidebar">
<div class="aksrt-doc-nav__recent">
<h3 class="aksrt-doc-nav__recent-title">
<i class="fas fa-clock"></i>
<?php esc_html_e('最近更新', 'aksrt'); ?>
</h3>
<ul class="aksrt-doc-nav__recent-list">
<?php foreach ($recent_pages as $rp) : ?>
<li class="aksrt-doc-nav__recent-item">
<a href="<?php echo esc_url(get_permalink($rp->ID)); ?>">
<span class="aksrt-doc-nav__recent-name"><?php echo esc_html($rp->post_title); ?></span>
<time class="aksrt-doc-nav__recent-date"><?php echo esc_html(get_the_date('', $rp->ID)); ?></time>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</aside>
<?php endif; ?>
</div>
</div>
</div>
</main>
<?php
get_footer();
+220
View File
@@ -0,0 +1,220 @@
<?php
/**
* Template Name: AKSRT - Download Center
* Template Post Type: page
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$paged = max(1, (int) get_query_var('paged'));
$per_page = 12;
$type_filter = isset($_GET['resource_type']) ? sanitize_key((string) $_GET['resource_type']) : '';
$resource_type_labels = function_exists('aksrt_get_pay_types') ? aksrt_get_pay_types() : [];
unset($resource_type_labels[AKSRT_Domain_Model::PAY_TYPE_READING]);
if ($type_filter !== '' && !isset($resource_type_labels[$type_filter])) {
$type_filter = '';
}
$query_args = [
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $per_page,
'paged' => $paged,
'orderby' => 'date',
'order' => 'DESC',
'ignore_sticky_posts' => true,
'meta_query' => [
[
'key' => AKSRT_Domain_Model::RESOURCE_MARKER_KEY,
'value' => '1',
],
],
];
if ($type_filter !== '') {
$query_args['meta_query'][] = [
'key' => AKSRT_Domain_Model::PAY_TYPE_KEY,
'value' => $type_filter,
];
}
$resource_query = new WP_Query($query_args);
$is_logged_in = is_user_logged_in();
$user_credits = 0;
$user_download_count = 0;
if ($is_logged_in) {
$uid = get_current_user_id();
if (class_exists('AKSRT_Credits')) {
$user_credits = AKSRT_Credits::balance($uid);
}
$dl_meta = get_user_meta($uid, '_aksrt_downloaded_resources', true);
$user_download_count = is_array($dl_meta) ? count($dl_meta) : 0;
}
$currency_name = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_currency_name() : __('积分', 'aksrt');
$dl_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_cms_features() : [];
$dl_requires_login = !empty($dl_settings['download_requires_login']);
?>
<main id="main-content" class="site-main container" tabindex="-1">
<?php get_template_part('templates/parts/download/download-hero'); ?>
<div class="aksrt-download-center container">
<div class="content-wrap">
<div class="content-layout">
<div class="content-layout__primary">
<div class="aksrt-dl-status-bar">
<?php if ($is_logged_in) : ?>
<div class="aksrt-dl-status-bar__item">
<i class="fas fa-coins" aria-hidden="true"></i>
<span class="aksrt-dl-status-bar__label"><?php echo esc_html($currency_name); ?></span>
<span class="aksrt-dl-status-bar__value"><?php echo esc_html(number_format_i18n($user_credits)); ?></span>
</div>
<div class="aksrt-dl-status-bar__item">
<i class="fas fa-download" aria-hidden="true"></i>
<span class="aksrt-dl-status-bar__label"><?php esc_html_e('已下载', 'aksrt'); ?></span>
<span class="aksrt-dl-status-bar__value"><?php echo esc_html(number_format_i18n($user_download_count)); ?></span>
</div>
<div class="aksrt-dl-status-bar__item aksrt-dl-status-bar__item--hint">
<i class="fas fa-info-circle" aria-hidden="true"></i>
<span><?php esc_html_e('点击资源卡片查看详情和下载状态', 'aksrt'); ?></span>
</div>
<?php else : ?>
<div class="aksrt-dl-status-bar__item aksrt-dl-status-bar__item--hint">
<i class="fas fa-lock" aria-hidden="true"></i>
<span>
<?php if ($dl_requires_login) : ?>
<?php esc_html_e('登录后可查看下载状态和积分余额', 'aksrt'); ?>
<?php else : ?>
<?php esc_html_e('登录后可管理下载记录和积分余额', 'aksrt'); ?>
<?php endif; ?>
</span>
</div>
<div class="aksrt-dl-status-bar__actions">
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>" class="btn-outline btn-sm"><?php esc_html_e('登录', 'aksrt'); ?></a>
<?php if (get_option('users_can_register')) : ?>
<a href="<?php echo esc_url(aksrt_get_register_url()); ?>" class="btn-primary btn-sm"><?php esc_html_e('注册', 'aksrt'); ?></a>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<div class="aksrt-download-center__layout">
<div class="aksrt-download-center__main">
<?php if ($resource_query->have_posts()) : ?>
<div class="aksrt-download-center__grid">
<?php while ($resource_query->have_posts()) : $resource_query->the_post(); ?>
<article class="aksrt-download-card">
<?php if (has_post_thumbnail()) : ?>
<div class="aksrt-download-card__thumb">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('medium'); ?>
</a>
</div>
<?php endif; ?>
<div class="aksrt-download-card__body">
<h3 class="aksrt-download-card__title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<p class="aksrt-download-card__excerpt"><?php echo esc_html(wp_trim_words(get_the_excerpt(), 20)); ?></p>
<div class="aksrt-download-card__meta">
<span class="aksrt-download-card__date">
<i class="fas fa-clock"></i>
<?php echo esc_html(get_the_date()); ?>
</span>
<?php
$dl_count = (int) get_post_meta(get_the_ID(), AKSRT_Domain_Model::RESOURCE_DOWNLOAD_COUNT_KEY, true);
if ($dl_count > 0) :
?>
<span class="aksrt-download-card__downloads">
<i class="fas fa-download"></i>
<?php echo esc_html(number_format_i18n($dl_count)); ?>
</span>
<?php endif; ?>
</div>
<?php
$card_meta = function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta(get_the_ID()) : [];
$card_price = (float) ($card_meta['price'] ?? 0);
$price_label = function_exists('aksrt_resource_price_label')
? aksrt_resource_price_label($card_price)
: ['text' => __('免费', 'aksrt'), 'free' => true];
?>
<div class="aksrt-download-card__footer">
<span class="aksrt-download-card__price<?php echo $price_label['free'] ? ' is-free' : ' is-paid'; ?>">
<?php echo esc_html($price_label['text']); ?>
</span>
<a href="<?php the_permalink(); ?>" class="aksrt-download-card__action">
<?php esc_html_e('查看详情', 'aksrt'); ?>
<i class="fas fa-arrow-right" aria-hidden="true"></i>
</a>
</div>
</div>
</article>
<?php endwhile; ?>
</div>
<?php
if (function_exists('aksrt_render_pagination')) {
aksrt_render_pagination($resource_query);
}
wp_reset_postdata();
?>
<?php else : ?>
<div class="aksrt-download-center__empty">
<i class="fas fa-folder-open"></i>
<p><?php esc_html_e('暂无可下载资源。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
</div>
<aside class="aksrt-download-center__sidebar sidebar">
<?php get_template_part('templates/parts/download/download-permission-card'); ?>
<div class="aksrt-dl-sidebar-card">
<h3 class="aksrt-dl-sidebar-card__title">
<i class="fas fa-folder"></i>
<?php esc_html_e('资源类型', 'aksrt'); ?>
</h3>
<?php if (!empty($resource_type_labels)) : ?>
<ul class="aksrt-dl-sidebar-card__list">
<li class="<?php echo $type_filter === '' ? 'is-active' : ''; ?>">
<a href="<?php echo esc_url(get_permalink()); ?>">
<?php esc_html_e('全部资源', 'aksrt'); ?>
</a>
</li>
<?php foreach ($resource_type_labels as $type_key => $type_label) : ?>
<li class="<?php echo $type_filter === $type_key ? 'is-active' : ''; ?>">
<a href="<?php echo esc_url(add_query_arg('resource_type', $type_key, get_permalink())); ?>">
<?php echo esc_html($type_label); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
<div class="aksrt-dl-sidebar-card">
<h3 class="aksrt-dl-sidebar-card__title">
<i class="fas fa-lightbulb"></i>
<?php esc_html_e('下载须知', 'aksrt'); ?>
</h3>
<div class="aksrt-dl-sidebar-card__tips">
<p><i class="fas fa-shield-alt" aria-hidden="true"></i> <?php esc_html_e('所有资源均经过安全检测', 'aksrt'); ?></p>
<p><i class="fas fa-clock" aria-hidden="true"></i> <?php esc_html_e('下载链接 10 分钟内有效', 'aksrt'); ?></p>
<p><i class="fas fa-sync-alt" aria-hidden="true"></i> <?php esc_html_e('已下载资源可再次下载', 'aksrt'); ?></p>
</div>
</div>
</div>
</div>
</div>
</main>
<?php
get_footer();
+331
View File
@@ -0,0 +1,331 @@
<?php
/**
* Template Name: AKSRT - Forums
* Template Post Type: page
*
* §7.10 — Tab engine + quick post + plate grid + follow/synthesis/pending streams.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$forum = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
$current_user_id = get_current_user_id();
$view = $forum ? $forum->get_home_view($current_user_id) : [
'boards' => [],
'recent_topics' => [],
'hot_topics' => [],
'stats' => [],
'permissions' => ['can_compose' => false, 'can_manage' => false],
'applications' => [],
'home_tabs' => [],
'active_index' => 1,
'quick_posts' => true,
];
$boards = $view['boards'] ?? [];
$recent_topics = $view['recent_topics'] ?? [];
$hot_topics = $view['hot_topics'] ?? [];
$stats = $view['stats'] ?? [];
$permissions = $view['permissions'] ?? [];
$applications = $view['applications'] ?? [];
$compose_url = home_url('/compose/');
$forum_settings = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_forum_settings() : [];
$forum_names = $forum_settings['names'] ?? [];
$name_forum = $forum_names['forum'] ?? __('论坛', 'aksrt');
$name_plate = $forum_names['plate'] ?? __('版块', 'aksrt');
$name_topic = $forum_names['posts'] ?? __('主题', 'aksrt');
$name_reply = $forum_names['comment'] ?? __('回复', 'aksrt');
$admin_forum_url = admin_url('admin.php?page=aksrt-theme-admin#/forum');
$home_tabs = $view['home_tabs'] ?? [];
$active_index = max(0, min(count($home_tabs) - 1, (int) ($view['active_index'] ?? 1)));
$quick_posts = !empty($view['quick_posts']);
$nonce = wp_create_nonce('aksrt_public_nonce');
// Resolve active tab from query param or default
$active_tab_type = isset($_GET['forum_tab']) ? sanitize_key(wp_unslash($_GET['forum_tab'])) : '';
if ($active_tab_type === '' && isset($home_tabs[$active_index])) {
$active_tab_type = $home_tabs[$active_index]['type'] ?? 'synthesis';
}
if ($active_tab_type === '') {
$active_tab_type = 'synthesis';
}
?>
<main id="main-content" class="site-main container" tabindex="-1">
<header class="aksrt-forum-header">
<div class="aksrt-forum-header__content">
<h1 class="aksrt-forum-header__title"><?php echo esc_html(get_the_title() ?: __('社区论坛', 'aksrt')); ?></h1>
<?php if (get_the_excerpt()) : ?>
<p class="aksrt-forum-header__desc"><?php echo esc_html(get_the_excerpt()); ?></p>
<?php endif; ?>
<div class="aksrt-forum-header__actions">
<?php if (!empty($permissions['can_compose'])) : ?>
<a class="aksrt-forum-header__action aksrt-forum-header__action--primary" href="<?php echo esc_url($compose_url); ?>">
<i class="fas fa-pen"></i> <?php esc_html_e('发布主题', 'aksrt'); ?>
</a>
<?php else : ?>
<a class="aksrt-forum-header__action aksrt-forum-header__action--primary" href="<?php echo esc_url(wp_login_url(get_permalink())); ?>">
<i class="fas fa-sign-in-alt"></i> <?php esc_html_e('登录后发帖', 'aksrt'); ?>
</a>
<?php endif; ?>
<?php if (!empty($permissions['can_manage'])) : ?>
<a class="aksrt-forum-header__action" href="<?php echo esc_url($admin_forum_url); ?>">
<i class="fas fa-tools"></i> <?php esc_html_e('进入治理后台', 'aksrt'); ?>
</a>
<?php endif; ?>
</div>
</div>
<div class="aksrt-forum-header__stats">
<div class="aksrt-forum-header__stat">
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['board_count'] ?? 0))); ?></span>
<span class="aksrt-forum-header__stat-label"><?php echo esc_html($name_plate); ?></span>
</div>
<div class="aksrt-forum-header__stat">
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['topic_count'] ?? 0))); ?></span>
<span class="aksrt-forum-header__stat-label"><?php echo esc_html($name_topic); ?></span>
</div>
<div class="aksrt-forum-header__stat">
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['post_count'] ?? 0))); ?></span>
<span class="aksrt-forum-header__stat-label"><?php echo esc_html($name_reply); ?></span>
</div>
<div class="aksrt-forum-header__stat">
<span class="aksrt-forum-header__stat-num"><?php echo esc_html(number_format_i18n((int) ($stats['moderator_count'] ?? 0))); ?></span>
<span class="aksrt-forum-header__stat-label"><?php esc_html_e('版主', 'aksrt'); ?></span>
</div>
</div>
</header>
<?php if (isset($_GET['compose_status']) && $_GET['compose_status'] === 'pending') : ?>
<div class="aksrt-alert aksrt-alert--info" data-aksrt-flash-query="compose_status">
<?php esc_html_e('你的主题已提交审核,审核通过后会在版块中展示。', 'aksrt'); ?>
</div>
<?php endif; ?>
<div class="aksrt-forum container">
<div class="content-wrap">
<div class="content-layout content-layout--no-sidebar">
<div class="content-layout__primary">
<div class="aksrt-forum__layout">
<div class="aksrt-forum__main">
<?php if ($quick_posts && !empty($permissions['can_compose'])) : ?>
<div class="aksrt-forum-quick-post">
<a class="aksrt-forum-quick-post__input" href="<?php echo esc_url($compose_url); ?>">
<?php echo get_avatar($current_user_id, 32); ?>
<span><?php esc_html_e('分享你的想法…', 'aksrt'); ?></span>
</a>
</div>
<?php endif; ?>
<?php if (!empty($home_tabs)) : ?>
<nav class="aksrt-forum-home-tabs" id="aksrt-forum-home-tabs"
data-nonce="<?php echo esc_attr($nonce); ?>"
data-ajax-url="<?php echo esc_attr(admin_url('admin-ajax.php')); ?>">
<?php foreach ($home_tabs as $i => $tab) :
$tab_type = sanitize_key($tab['type'] ?? 'synthesis');
$tab_label = esc_html($tab['label'] ?? $tab_type);
$is_active = $tab_type === $active_tab_type;
if ($tab_type === 'pending' && empty($permissions['can_manage'])) continue;
?>
<button type="button"
class="aksrt-forum-home-tabs__btn<?php echo $is_active ? ' is-active' : ''; ?>"
data-tab-type="<?php echo esc_attr($tab_type); ?>">
<?php echo $tab_label; ?>
</button>
<?php endforeach; ?>
<?php if (!empty($permissions['can_manage'])) : ?>
<button type="button"
class="aksrt-forum-home-tabs__btn<?php echo $active_tab_type === 'pending' ? ' is-active' : ''; ?>"
data-tab-type="pending">
<?php esc_html_e('待审核', 'aksrt'); ?>
<?php if ((int) ($stats['pending_topic_count'] ?? 0) > 0) : ?>
<span class="aksrt-forum-home-tabs__badge"><?php echo esc_html((string) ($stats['pending_topic_count'] ?? 0)); ?></span>
<?php endif; ?>
</button>
<?php endif; ?>
</nav>
<?php endif; ?>
<div class="aksrt-forum-home-content" id="aksrt-forum-home-content">
<?php if ($active_tab_type === 'plate') : ?>
<?php if (!empty($boards)) : ?>
<div class="aksrt-forum-boards__grid">
<?php foreach ($boards as $board) :
$board_id = (int) ($board['id'] ?? 0);
?>
<article class="aksrt-forum-board-card">
<a class="aksrt-forum-board-card__link" href="<?php echo esc_url((string) ($board['url'] ?? '#')); ?>">
<div class="aksrt-forum-board-card__icon">
<?php if (!empty($board['thumbnail_url'])) : ?>
<img src="<?php echo esc_url((string) $board['thumbnail_url']); ?>" alt="" width="48" height="48">
<?php else : ?>
<i class="<?php echo esc_attr((string) ($board['icon'] ?: 'fas fa-comments')); ?>"></i>
<?php endif; ?>
</div>
<div class="aksrt-forum-board-card__body">
<div class="aksrt-forum-board-card__head">
<h3 class="aksrt-forum-board-card__title"><?php echo esc_html((string) ($board['name'] ?? '')); ?></h3>
</div>
<?php if (!empty($board['description'])) : ?>
<p class="aksrt-forum-board-card__desc"><?php echo esc_html((string) $board['description']); ?></p>
<?php endif; ?>
<div class="aksrt-forum-board-card__meta">
<span><i class="fas fa-file-alt"></i> <?php echo esc_html(number_format_i18n((int) ($board['topic_count'] ?? $board['post_count'] ?? 0))); ?></span>
<span><i class="fas fa-comment"></i> <?php echo esc_html(number_format_i18n((int) ($board['reply_count'] ?? 0))); ?></span>
<span><i class="fas fa-heart"></i> <?php echo esc_html(number_format_i18n((int) ($board['follow_count'] ?? 0))); ?></span>
</div>
</div>
</a>
</article>
<?php endforeach; ?>
</div>
<?php else : ?>
<div class="aksrt-forum__empty">
<i class="fas fa-comments"></i>
<p><?php esc_html_e('当前还没有论坛版块。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<?php elseif ($active_tab_type === 'follow') : ?>
<?php
$follow_data = $forum ? $forum->get_follow_stream($current_user_id) : ['items' => []];
if (!empty($follow_data['items'])) : ?>
<div class="aksrt-forum-topics__list js-aksrt-home-topic-list">
<?php foreach ($follow_data['items'] as $topic) { $forum->render_topic_row($topic); } ?>
</div>
<?php if ($follow_data['max_pages'] > 1) : ?>
<div class="aksrt-forum-home__load-more">
<button type="button" class="aksrt-forum-replies__more-btn js-aksrt-home-load-more"
data-page="1" data-max="<?php echo esc_attr((string) $follow_data['max_pages']); ?>"
data-tab="follow">
<i class="fas fa-chevron-down"></i> <?php esc_html_e('加载更多', 'aksrt'); ?>
</button>
</div>
<?php endif; ?>
<?php elseif ($current_user_id > 0) : ?>
<div class="aksrt-forum__empty">
<i class="far fa-heart"></i>
<p><?php esc_html_e('你还没有关注任何版块,去看看有哪些版块吧!', 'aksrt'); ?></p>
</div>
<?php else : ?>
<div class="aksrt-forum__empty">
<i class="fas fa-sign-in-alt"></i>
<p><?php esc_html_e('登录后即可看到你关注的版块内容。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<?php elseif ($active_tab_type === 'pending') : ?>
<?php
$pending_data = $forum ? $forum->get_pending_stream($current_user_id) : ['items' => []];
if (!empty($pending_data['items'])) : ?>
<div class="aksrt-forum-topics__list js-aksrt-home-topic-list">
<?php foreach ($pending_data['items'] as $topic) { $forum->render_topic_row($topic); } ?>
</div>
<?php else : ?>
<div class="aksrt-forum__empty">
<i class="fas fa-check-circle"></i>
<p><?php esc_html_e('没有待审核的主题。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<?php else : /* synthesis (default) */ ?>
<?php if (!empty($recent_topics)) : ?>
<div class="aksrt-forum-topics__list js-aksrt-home-topic-list">
<?php foreach ($recent_topics as $topic) {
if ($forum) { $forum->render_topic_row($topic); }
} ?>
</div>
<?php else : ?>
<div class="aksrt-forum__empty">
<i class="fas fa-feather-alt"></i>
<p><?php esc_html_e('还没有公开主题,欢迎创建第一个讨论。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
</div>
<aside class="aksrt-forum__sidebar">
<div class="aksrt-forum-sidebar-card">
<h3 class="aksrt-forum-sidebar-card__title">
<i class="fas fa-fire"></i>
<?php printf(esc_html__('热门%s', 'aksrt'), esc_html($name_topic)); ?>
</h3>
<?php if (!empty($hot_topics)) : ?>
<ul class="aksrt-forum-sidebar-card__list">
<?php foreach ($hot_topics as $index => $topic) : ?>
<li class="aksrt-forum-sidebar-card__item">
<span class="aksrt-forum-sidebar-card__rank"><?php echo esc_html((string) ($index + 1)); ?></span>
<a href="<?php echo esc_url((string) ($topic['permalink'] ?? '#')); ?>" class="aksrt-forum-sidebar-card__link">
<?php echo esc_html((string) ($topic['title'] ?? '')); ?>
</a>
<span class="aksrt-forum-sidebar-card__views"><?php echo esc_html(number_format_i18n((int) ($topic['views'] ?? 0))); ?></span>
</li>
<?php endforeach; ?>
</ul>
<?php else : ?>
<p class="aksrt-forum-sidebar-card__empty"><?php esc_html_e('暂无热门主题', 'aksrt'); ?></p>
<?php endif; ?>
</div>
<?php if (!empty($boards)) : ?>
<div class="aksrt-forum-sidebar-card">
<h3 class="aksrt-forum-sidebar-card__title">
<i class="fas fa-th-list"></i>
<?php echo esc_html($name_plate); ?>
</h3>
<ul class="aksrt-forum-sidebar-card__list">
<?php foreach (array_slice($boards, 0, 8) as $board) : ?>
<li class="aksrt-forum-sidebar-card__item">
<a href="<?php echo esc_url((string) ($board['url'] ?? '#')); ?>" class="aksrt-forum-sidebar-card__link">
<?php echo esc_html((string) ($board['name'] ?? '')); ?>
</a>
<span class="aksrt-forum-sidebar-card__views"><?php echo esc_html(number_format_i18n((int) ($board['topic_count'] ?? $board['post_count'] ?? 0))); ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php if (!empty($applications)) : ?>
<div class="aksrt-forum-sidebar-card">
<h3 class="aksrt-forum-sidebar-card__title">
<i class="fas fa-shield-alt"></i>
<?php esc_html_e('版主申请状态', 'aksrt'); ?>
</h3>
<ul class="aksrt-forum-sidebar-card__list aksrt-forum-sidebar-card__list--applications">
<?php foreach ($applications as $board_id => $application) :
if (!$application) continue;
$board_name = '';
foreach ($boards as $board) {
if ((int) ($board['id'] ?? 0) === (int) $board_id) {
$board_name = (string) ($board['name'] ?? '');
break;
}
}
?>
<li class="aksrt-forum-sidebar-card__item aksrt-forum-sidebar-card__item--stack">
<strong><?php echo esc_html($board_name); ?></strong>
<span><?php echo esc_html((string) ($application['status_label'] ?? '')); ?></span>
</li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
</aside>
</div>
</div>
</div>
</div>
</div>
</main>
<?php get_footer(); ?>
+61
View File
@@ -0,0 +1,61 @@
<?php
/**
* Template Name: 友情链接
* Template Post Type: page
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$links = function_exists('aksrt_get_friend_links') ? aksrt_get_friend_links() : [];
?>
<main id="main-content" class="container page-content-default" tabindex="-1">
<header class="page-header">
<h1 class="entry-title"><?php esc_html_e('友情链接', 'aksrt'); ?></h1>
<p><?php esc_html_e('与这些优秀的站点交换友链', 'aksrt'); ?></p>
</header>
<div class="content-wrap">
<div class="content-layout content-layout--no-sidebar">
<div class="content-layout__primary">
<?php if (! empty($links)) : ?>
<div class="friends-grid">
<?php foreach ($links as $link) : ?>
<a class="friend-card" href="<?php echo esc_url($link['url'] ?? '#'); ?>" target="_blank" rel="noopener noreferrer">
<?php
$logo = $link['logo'] ?? '';
if ($logo) {
echo '<img class="friend-card__avatar" src="' . esc_url($logo) . '" alt="">';
} else {
$initial = function_exists('mb_substr') ? mb_substr((string) ($link['name'] ?? 'A'), 0, 1, 'UTF-8') : substr((string) ($link['name'] ?? 'A'), 0, 1);
echo '<div class="friend-card__avatar" style="display:flex;align-items:center;justify-content:center;font-weight:800;color:var(--color-primary);font-family:var(--font-heading);">' . esc_html($initial) . '</div>';
}
?>
<div class="friend-card__info">
<h3 class="friend-card__name"><?php echo esc_html($link['name'] ?? ''); ?></h3>
<p class="friend-card__desc"><?php echo esc_html($link['description'] ?? ''); ?></p>
</div>
</a>
<?php endforeach; ?>
</div>
<?php else : ?>
<div class="no-results">
<p><?php esc_html_e('暂无友链,请在主题后台添加。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<p style="text-align:center;margin-top:32px;">
<a class="btn-outline" href="<?php echo esc_url(home_url('/')); ?>"><?php esc_html_e('返回首页', 'aksrt'); ?></a>
</p>
</div>
</div>
</div>
</main>
<?php
get_footer();
+11
View File
@@ -0,0 +1,11 @@
<?php
/**
* Template Name: AKSRT - Login
* Template Post Type: page
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
require AKSRT_DIR . '/templates/pages/page-sign.php';
+236
View File
@@ -0,0 +1,236 @@
<?php
/**
* Template Name: 消息中心
* Template Post Type: page
*
* 独立消息中心页面 — 两栏布局(左侧导航 + 右侧消息列表)
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
if ( ! is_user_logged_in() ) {
$login_url = function_exists( 'aksrt_get_login_url' ) ? aksrt_get_login_url() : wp_login_url( get_permalink() );
wp_safe_redirect( $login_url );
exit;
}
$user_id = get_current_user_id();
// 获取所有通知(持久化 + 即时状态)
$all_notifications = function_exists( 'aksrt_get_user_all_notifications' )
? aksrt_get_user_all_notifications( $user_id )
: [];
// 筛选类型
$current_type = isset( $_GET['msg_type'] ) ? sanitize_key( $_GET['msg_type'] ) : 'all';
// 按类型过滤
$filtered = $all_notifications;
if ( $current_type === 'unread' ) {
$filtered = array_filter( $filtered, static fn( $n ) => empty( $n['read'] ) );
} elseif ( $current_type !== 'all' ) {
$filtered = array_filter( $filtered, static fn( $n ) => ( $n['type'] ?? '' ) === $current_type );
}
$filtered = array_values( $filtered );
// 分页
$per_page = 20;
$current_page = max( 1, (int) ( $_GET['msg_page'] ?? 1 ) );
$total = count( $filtered );
$total_pages = max( 1, (int) ceil( $total / $per_page ) );
$offset = ( $current_page - 1 ) * $per_page;
$paged_items = array_slice( $filtered, $offset, $per_page );
// 统计各类型数量
$type_counts = [ 'all' => count( $all_notifications ), 'unread' => 0 ];
foreach ( $all_notifications as $n ) {
$t = $n['type'] ?? 'notice';
$type_counts[ $t ] = ( $type_counts[ $t ] ?? 0 ) + 1;
if ( empty( $n['read'] ) ) {
$type_counts['unread']++;
}
}
// 导航定义
$nav_items = [
'all' => __( '全部消息', 'aksrt' ),
'unread' => __( '未读', 'aksrt' ),
'conversation' => __( '私信', 'aksrt' ),
'comment_reply' => __( '评论回复', 'aksrt' ),
'comment_approved' => __( '评论审核', 'aksrt' ),
'credits_added' => __( '积分增加', 'aksrt' ),
'credits_deducted' => __( '积分扣减', 'aksrt' ),
'download_ready' => __( '下载就绪', 'aksrt' ),
'upload_moderation'=> __( '图片审核', 'aksrt' ),
'notice' => __( '系统通知', 'aksrt' ),
];
// 图标映射
$icon_map = [
'comment_reply' => 'fas fa-comment-dots',
'comment_approved' => 'fas fa-check-circle',
'credits_added' => 'fas fa-coins',
'credits_deducted' => 'fas fa-coins',
'download_ready' => 'fas fa-download',
'upload_moderation'=> 'fas fa-image',
'verify_email' => 'fas fa-envelope-open-text',
'pending_comments' => 'fas fa-clock',
'conversation' => 'fas fa-envelope',
'notice' => 'fas fa-bell',
];
?>
<div class="messages-center container">
<aside class="messages-center__nav">
<ul class="messages-nav__list">
<?php foreach ( $nav_items as $key => $label ) :
$count = (int) ( $type_counts[ $key ] ?? 0 );
if ( $key !== 'all' && $key !== 'unread' && $count < 1 ) continue;
$is_active = $current_type === $key;
?>
<li>
<a href="<?php echo esc_url( add_query_arg( [ 'msg_type' => $key, 'msg_page' => 1 ] ) ); ?>"
class="messages-nav__item<?php echo $is_active ? ' is-active' : ''; ?>"
data-type="<?php echo esc_attr( $key ); ?>">
<span><?php echo esc_html( $label ); ?></span>
<?php if ( $count > 0 ) : ?>
<span class="messages-nav__badge" data-type="<?php echo esc_attr( $key ); ?>" data-count="<?php echo esc_attr( (string) $count ); ?>"><?php echo esc_html( (string) $count ); ?></span>
<?php endif; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<div class="messages-nav__actions">
<button type="button" class="messages-nav__action-btn js-msg-mark-all-read"><?php esc_html_e( '全部已读', 'aksrt' ); ?></button>
<button type="button" class="messages-nav__action-btn js-msg-clear-read"><?php esc_html_e( '清除已读', 'aksrt' ); ?></button>
</div>
</aside>
<main class="messages-center__content">
<?php if ( $current_type === 'conversation' ) :
$pm = class_exists( 'AKSRT_Private_Message' ) ? AKSRT_Private_Message::get_instance() : null;
$conversations = $pm ? $pm->get_conversations( $user_id, 30 ) : [];
$pm_nonce = wp_create_nonce( 'aksrt_pm' );
?>
<div class="messages-conversations" id="aksrt-pm-conversations"
data-ajax="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>"
data-nonce="<?php echo esc_attr( $pm_nonce ); ?>">
<?php if ( ! empty( $conversations ) ) : ?>
<div class="aksrt-pm__list">
<?php foreach ( $conversations as $conv ) : ?>
<div class="aksrt-pm__item<?php echo $conv['unread'] > 0 ? ' is-unread' : ''; ?>"
data-conv-id="<?php echo esc_attr( (string) $conv['id'] ); ?>"
data-other-id="<?php echo esc_attr( (string) $conv['other_user_id'] ); ?>">
<img class="aksrt-pm__avatar" src="<?php echo esc_url( $conv['other_avatar'] ); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('avatar') : ' loading="lazy"'; ?> />
<div class="aksrt-pm__info">
<div class="aksrt-pm__name">
<?php echo esc_html( $conv['other_name'] ); ?>
<?php if ( $conv['unread'] > 0 ) : ?>
<span class="aksrt-pm__badge"><?php echo esc_html( (string) $conv['unread'] ); ?></span>
<?php endif; ?>
</div>
<div class="aksrt-pm__preview"><?php echo esc_html( mb_substr( $conv['last_message'], 0, 50 ) ); ?></div>
</div>
<div class="aksrt-pm__time"><?php echo esc_html( $conv['last_message_at'] ? mysql2date( 'm-d H:i', $conv['last_message_at'] ) : '' ); ?></div>
</div>
<?php endforeach; ?>
</div>
<?php else : ?>
<div class="messages-empty">
<span class="messages-empty__icon"><i class="fas fa-envelope"></i></span>
<p class="messages-empty__text"><?php esc_html_e( '暂无私信', 'aksrt' ); ?></p>
<p class="messages-empty__hint"><?php esc_html_e( '你可以在用户主页发起私信。', 'aksrt' ); ?></p>
</div>
<?php endif; ?>
</div>
<div class="aksrt-pm__thread" id="aksrt-pm-thread" style="display:none;">
<div class="aksrt-pm__thread-header">
<button type="button" class="aksrt-pm__back-btn" id="aksrt-pm-back"><i class="fas fa-arrow-left"></i> <?php esc_html_e( '返回', 'aksrt' ); ?></button>
<span class="aksrt-pm__thread-name" id="aksrt-pm-thread-name"></span>
</div>
<div class="aksrt-pm__messages" id="aksrt-pm-messages"></div>
<div class="aksrt-pm__compose">
<textarea id="aksrt-pm-input" rows="2" placeholder="<?php esc_attr_e( '输入消息...', 'aksrt' ); ?>"></textarea>
<button type="button" id="aksrt-pm-send" class="aksrt-pm__send-btn"><i class="fas fa-paper-plane"></i></button>
</div>
</div>
<?php /* conversation.js is enqueued via AKSRT_Scripts */ ?>
<?php elseif ( ! empty( $paged_items ) ) : ?>
<div class="messages-list">
<?php foreach ( $paged_items as $notice ) :
$n_type = (string) ( $notice['type'] ?? 'notice' );
$n_title = (string) ( $notice['title'] ?? '' );
$n_desc = (string) ( $notice['desc'] ?? '' );
$n_url = (string) ( $notice['url'] ?? '' );
$n_id = (string) ( $notice['id'] ?? '' );
$is_read = ! empty( $notice['read'] );
$is_state = ! empty( $notice['stateful'] );
$created = (string) ( $notice['created_at'] ?? '' );
$time_str = $is_state
? __( '状态提醒', 'aksrt' )
: ( $created !== '' ? get_date_from_gmt( $created, 'Y-m-d H:i' ) : '' );
$icon_cls = $icon_map[ $n_type ] ?? 'fas fa-bell';
?>
<div class="message-item<?php echo ! $is_read ? ' is-unread' : ''; ?>" data-notification-id="<?php echo esc_attr( $n_id ); ?>">
<span class="message-item__icon">
<i class="<?php echo esc_attr( $icon_cls ); ?>" aria-hidden="true"></i>
</span>
<div class="message-item__body">
<div class="message-item__title">
<?php echo esc_html( $n_title ); ?>
<?php if ( ! $is_read && ! $is_state ) : ?>
<span class="message-item__new-badge">NEW</span>
<?php endif; ?>
</div>
<?php if ( $n_desc !== '' ) : ?>
<div class="message-item__desc"><?php echo esc_html( $n_desc ); ?></div>
<?php endif; ?>
<?php if ( $time_str !== '' ) : ?>
<div class="message-item__time"><?php echo esc_html( $time_str ); ?></div>
<?php endif; ?>
</div>
<div class="message-item__actions">
<?php if ( $n_url !== '' ) : ?>
<a href="<?php echo esc_url( $n_url ); ?>" class="message-item__action-btn"><?php esc_html_e( '查看', 'aksrt' ); ?></a>
<?php endif; ?>
<?php if ( ! $is_state && ! $is_read ) : ?>
<button type="button" class="message-item__action-btn js-msg-mark-read" data-id="<?php echo esc_attr( $n_id ); ?>"><?php esc_html_e( '已读', 'aksrt' ); ?></button>
<?php endif; ?>
<?php if ( ! $is_state ) : ?>
<button type="button" class="message-item__action-btn message-item__action-btn--danger js-msg-delete" data-id="<?php echo esc_attr( $n_id ); ?>"><?php esc_html_e( '删除', 'aksrt' ); ?></button>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php if ( $total_pages > 1 ) : ?>
<div class="messages-pagination">
<?php for ( $i = 1; $i <= $total_pages; $i++ ) :
$page_url = add_query_arg( [ 'msg_type' => $current_type, 'msg_page' => $i ] );
?>
<?php if ( $i === $current_page ) : ?>
<span class="profile-status-chip is-active"><?php echo esc_html( (string) $i ); ?></span>
<?php else : ?>
<a href="<?php echo esc_url( $page_url ); ?>" class="profile-status-chip"><?php echo esc_html( (string) $i ); ?></a>
<?php endif; ?>
<?php endfor; ?>
</div>
<?php endif; ?>
<?php else : ?>
<div class="messages-empty">
<span class="messages-empty__icon"><i class="fas fa-bell-slash"></i></span>
<p class="messages-empty__text"><?php esc_html_e( '暂无消息', 'aksrt' ); ?></p>
</div>
<?php endif; ?>
</main>
</div>
<?php get_footer(); ?>
+67
View File
@@ -0,0 +1,67 @@
<?php
/**
* Template Name: AKSRT - New Posts
* Template Post Type: page
*
* 最新文章页:按时间倒序展示最新发布的文章。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$paged = max(1, (int) get_query_var('paged'));
$per_page = 20;
$query = new WP_Query([
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $per_page,
'paged' => $paged,
'orderby' => 'date',
'order' => 'DESC',
]);
?>
<main id="main-content" class="container page-content-default" tabindex="-1">
<header class="page-header">
<h1 class="entry-title"><?php echo esc_html(get_the_title() ?: __('最新文章', 'aksrt')); ?></h1>
</header>
<div class="content-wrap">
<div class="content-layout content-layout--no-sidebar">
<div class="content-layout__primary">
<div class="aksrt-newposts container">
<?php if ($query->have_posts()) : ?>
<div class="aksrt-newposts__list">
<?php while ($query->have_posts()) : $query->the_post(); ?>
<article class="aksrt-newposts__item">
<span class="aksrt-newposts__date"><?php echo esc_html(get_the_date()); ?></span>
<h3 class="aksrt-newposts__title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<p class="aksrt-newposts__excerpt"><?php echo esc_html(wp_trim_words(get_the_excerpt(), 30)); ?></p>
</article>
<?php endwhile; ?>
</div>
<?php
if (function_exists('aksrt_render_pagination')) {
aksrt_render_pagination($query);
} else {
echo '<div class="aksrt-pagination">' . paginate_links(['total' => $query->max_num_pages]) . '</div>';
}
?>
<?php wp_reset_postdata(); ?>
<?php else : ?>
<p class="aksrt-newposts__empty"><?php esc_html_e('暂无文章。', 'aksrt'); ?></p>
<?php endif; ?>
</div>
</div>
</div>
</div>
</main>
<?php
get_footer();
+253
View File
@@ -0,0 +1,253 @@
<?php
/**
* Template Name: AKSRT - Orders
* Template Post Type: page
*
* Enhanced: 5 tabs, logistics timeline, receipt confirm,
* review button, re-purchase, gift/discount details (§6.10).
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
if (!is_user_logged_in()) {
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
wp_safe_redirect($login_url);
exit;
}
$user_id = get_current_user_id();
$per_page = 20;
$paged = max(1, (int) ($_GET['order_page'] ?? 1));
$tab = sanitize_key((string) ($_GET['tab'] ?? ''));
$status = sanitize_key((string) ($_GET['order_status'] ?? ''));
$tab_status_map = [
'pending' => AKSRT_Order::STATUS_PENDING,
'shipped' => AKSRT_Order::STATUS_DELIVERED,
'received' => AKSRT_Order::STATUS_COMPLETED,
'review' => AKSRT_Order::STATUS_PENDING_REVIEW,
'after' => AKSRT_Order::STATUS_REFUNDING,
];
if ($tab !== '' && isset($tab_status_map[$tab])) {
$status = $tab_status_map[$tab];
}
$orders_view = function_exists('aksrt_get_orders_page_view')
? aksrt_get_orders_page_view($user_id, $paged, $per_page, $status)
: ['items' => [], 'total' => 0, 'total_pages' => 1, 'page' => 1];
$orders = (array) ($orders_view['items'] ?? []);
$total_pages = max(1, (int) ($orders_view['total_pages'] ?? 1));
$shop = class_exists('AKSRT_Shop') ? AKSRT_Shop::get_instance() : null;
$shipping = class_exists('AKSRT_Shipping') ? AKSRT_Shipping::get_instance() : null;
$tabs = [
'' => __('全部', 'aksrt'),
'pending' => __('待支付', 'aksrt'),
'shipped' => __('待收货', 'aksrt'),
'review' => __('待评价', 'aksrt'),
'after' => __('售后', 'aksrt'),
];
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
<div class="container aksrt-orders-page" data-aksrt-order-center>
<div class="aksrt-orders-page__header">
<h1><?php esc_html_e('我的订单', 'aksrt'); ?></h1>
</div>
<!-- 5-tab navigation -->
<div class="aksrt-orders-page__tabs">
<?php foreach ($tabs as $tab_key => $tab_label) :
$is_active = $tab === $tab_key;
$tab_url = $tab_key !== '' ? add_query_arg(['tab' => $tab_key, 'order_page' => 1]) : remove_query_arg(['tab', 'order_status', 'order_page']);
?>
<a href="<?php echo esc_url($tab_url); ?>" class="aksrt-orders-page__tab<?php echo $is_active ? ' is-active' : ''; ?>">
<?php echo esc_html($tab_label); ?>
</a>
<?php endforeach; ?>
</div>
<?php if (!empty($orders)) : ?>
<div class="aksrt-orders-page__list">
<?php foreach ($orders as $order) :
$on = (string) ($order['order_number'] ?? '');
$os = (string) ($order['status'] ?? '');
$items = $order['items'] ?? [];
?>
<article class="aksrt-orders-page__card" data-aksrt-order-card="<?php echo esc_attr($on); ?>">
<!-- Card header -->
<div class="aksrt-orders-page__card-head">
<span class="aksrt-orders-page__card-number"><?php echo esc_html($on); ?></span>
<time class="aksrt-orders-page__card-time"><?php echo esc_html((string) ($order['created_at'] ?? '')); ?></time>
<span class="aksrt-orders-page__card-status"><?php echo esc_html((string) ($order['status_label'] ?? '')); ?></span>
</div>
<!-- Order items -->
<div class="aksrt-orders-page__card-items">
<?php if (!empty($items)) : ?>
<?php foreach ($items as $item) : ?>
<div class="aksrt-orders-page__card-item">
<?php if (!empty($item['image'])) : ?>
<img src="<?php echo esc_url((string) $item['image']); ?>" alt="" class="aksrt-orders-page__card-img">
<?php endif; ?>
<div class="aksrt-orders-page__card-item-info">
<span class="aksrt-orders-page__card-item-title"><?php echo esc_html((string) ($item['product_title'] ?? '')); ?></span>
<?php if (!empty($item['options_label'])) : ?>
<small class="aksrt-orders-page__card-item-opts"><?php echo esc_html((string) $item['options_label']); ?></small>
<?php endif; ?>
</div>
<div class="aksrt-orders-page__card-item-price">
<strong>¥<?php echo esc_html(number_format((float) ($item['pay_price'] ?? $item['unit_price'] ?? 0), 2)); ?></strong>
<span>×<?php echo esc_html((string) ($item['quantity'] ?? 1)); ?></span>
</div>
</div>
<?php endforeach; ?>
<?php else : ?>
<div class="aksrt-orders-page__card-item">
<span class="aksrt-orders-page__card-item-title"><?php echo esc_html((string) ($order['product_name'] ?? __('商品订单', 'aksrt'))); ?></span>
<strong>¥<?php echo esc_html(number_format((float) ($order['amount'] ?? 0), 2)); ?></strong>
</div>
<?php endif; ?>
</div>
<!-- Price summary -->
<div class="aksrt-orders-page__card-summary">
<span><?php esc_html_e('合计', 'aksrt'); ?></span>
<strong>¥<?php echo esc_html(number_format((float) ($order['amount'] ?? 0), 2)); ?></strong>
<?php if ((float) ($order['discount'] ?? 0) > 0) : ?>
<small>(<?php printf(esc_html__('已优惠 ¥%s', 'aksrt'), number_format((float) $order['discount'], 2)); ?>)</small>
<?php endif; ?>
</div>
<!-- Logistics timeline (collapsed) -->
<?php if (!empty($order['shipping_records'])) : ?>
<div class="aksrt-orders-page__timeline" data-aksrt-timeline>
<h4 class="aksrt-orders-page__timeline-toggle" data-aksrt-toggle-timeline>
<i class="fas fa-truck"></i> <?php esc_html_e('物流信息', 'aksrt'); ?> <i class="fas fa-chevron-down"></i>
</h4>
<div class="aksrt-orders-page__timeline-body" hidden>
<?php foreach ((array) ($order['timeline'] ?? []) as $tl) : ?>
<div class="aksrt-orders-page__timeline-item">
<time><?php echo esc_html((string) ($tl['time'] ?? '')); ?></time>
<span><?php echo esc_html((string) ($tl['label'] ?? '')); ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
<!-- Actions -->
<div class="aksrt-orders-page__card-actions">
<?php if (!empty($order['actions']['can_pay'])) : ?>
<button type="button" class="btn-primary btn-sm" data-aksrt-order-pay="<?php echo esc_attr($on); ?>"><?php esc_html_e('去支付', 'aksrt'); ?></button>
<?php endif; ?>
<?php if (!empty($order['actions']['can_receipt'])) : ?>
<button type="button" class="btn-primary btn-sm" data-aksrt-order-receipt="<?php echo esc_attr($on); ?>"><?php esc_html_e('确认收货', 'aksrt'); ?></button>
<?php endif; ?>
<?php if ($os === AKSRT_Order::STATUS_PENDING_REVIEW) : ?>
<button type="button" class="btn-primary btn-sm" data-aksrt-order-review="<?php echo esc_attr($on); ?>"><?php esc_html_e('去评价', 'aksrt'); ?></button>
<?php endif; ?>
<?php if (!empty($order['actions']['can_cancel'])) : ?>
<button type="button" class="btn-ghost btn-sm" data-aksrt-order-cancel="<?php echo esc_attr($on); ?>"><?php esc_html_e('取消', 'aksrt'); ?></button>
<?php endif; ?>
<?php if (in_array($os, [AKSRT_Order::STATUS_COMPLETED, AKSRT_Order::STATUS_PENDING_REVIEW], true)) : ?>
<button type="button" class="btn-outline btn-sm" data-aksrt-order-rebuy="<?php echo esc_attr($on); ?>"><?php esc_html_e('再次购买', 'aksrt'); ?></button>
<?php endif; ?>
<?php if (!empty($order['actions']['can_after_sale'])) : ?>
<button type="button" class="btn-outline btn-sm" data-aksrt-order-after-sale="<?php echo esc_attr($on); ?>"><?php esc_html_e('售后', 'aksrt'); ?></button>
<?php endif; ?>
<?php if (!empty($order['time_left'])) : ?>
<span class="aksrt-orders-page__countdown" data-aksrt-order-countdown="<?php echo esc_attr((string) $order['time_left']); ?>">
<?php printf(esc_html__('%d秒后关闭', 'aksrt'), (int) $order['time_left']); ?>
</span>
<?php endif; ?>
</div>
</article>
<?php endforeach; ?>
</div>
<?php if ($total_pages > 1) : ?>
<div class="aksrt-orders-page__pagination">
<?php for ($i = 1; $i <= $total_pages; $i++) :
$page_url = add_query_arg(['order_page' => $i]);
?>
<?php if ($i === $paged) : ?>
<span class="aksrt-orders-page__page-chip is-active"><?php echo esc_html((string) $i); ?></span>
<?php else : ?>
<a href="<?php echo esc_url($page_url); ?>" class="aksrt-orders-page__page-chip"><?php echo esc_html((string) $i); ?></a>
<?php endif; ?>
<?php endfor; ?>
</div>
<?php endif; ?>
<?php else : ?>
<div class="aksrt-orders-page__empty">
<i class="fas fa-receipt" aria-hidden="true"></i>
<p><?php esc_html_e('暂无订单记录。', 'aksrt'); ?></p>
</div>
<?php endif; ?>
<!-- After-sale modal -->
<div class="aksrt-modal" data-aksrt-aftersale-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-aftersale-modal-close>&times;</button>
</div>
<form class="aksrt-modal__body" data-aksrt-aftersale-form>
<input type="hidden" name="order_number" value="">
<div class="aksrt-orders-page__field">
<label><?php esc_html_e('售后类型', 'aksrt'); ?></label>
<select name="type" class="aksrt-orders-page__select">
<?php foreach (AKSRT_After_Sale::get_valid_types() as $type_key => $type_label) : ?>
<option value="<?php echo esc_attr($type_key); ?>"><?php echo esc_html($type_label); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="aksrt-orders-page__field">
<label><?php esc_html_e('售后原因', 'aksrt'); ?> *</label>
<textarea name="reason" class="aksrt-orders-page__textarea" rows="4" required placeholder="<?php esc_attr_e('请描述问题', 'aksrt'); ?>"></textarea>
</div>
<div class="aksrt-modal__footer">
<button type="button" class="btn-ghost" data-aksrt-aftersale-modal-close><?php esc_html_e('取消', 'aksrt'); ?></button>
<button type="submit" class="btn-primary"><?php esc_html_e('提交', 'aksrt'); ?></button>
</div>
</form>
</div>
</div>
<!-- Favorites section -->
<?php
$fav_tab = sanitize_key((string) ($_GET['section'] ?? ''));
if ($fav_tab === 'favorites' && $shop) :
$fav_data = $shop->get_user_favorites($user_id);
?>
<section class="aksrt-orders-page__favorites">
<h2><?php esc_html_e('收藏商品', 'aksrt'); ?></h2>
<?php if (!empty($fav_data['items'])) : ?>
<div class="aksrt-orders-page__fav-grid">
<?php foreach ($fav_data['items'] as $fav) : ?>
<a href="<?php echo esc_url((string) ($fav['permalink'] ?? '#')); ?>" class="aksrt-orders-page__fav-card">
<?php if (!empty($fav['image'])) : ?>
<img src="<?php echo esc_url((string) $fav['image']); ?>" alt="" loading="lazy">
<?php endif; ?>
<h3><?php echo esc_html((string) ($fav['title'] ?? '')); ?></h3>
<strong>¥<?php echo esc_html(number_format((float) ($fav['price'] ?? 0), 2)); ?></strong>
</a>
<?php endforeach; ?>
</div>
<?php else : ?>
<p><?php esc_html_e('暂无收藏商品', 'aksrt'); ?></p>
<?php endif; ?>
</section>
<?php endif; ?>
</div>
</main>
<?php get_footer(); ?>
+59
View File
@@ -0,0 +1,59 @@
<?php
/**
* Template Name: AKSRT - Posts Navigation
* Template Post Type: page
*
* 文章导航页:分类+标签的导航聚合页。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$categories = get_categories(['hide_empty' => true, 'orderby' => 'count', 'order' => 'DESC', 'number' => 20]);
$tags = get_tags(['hide_empty' => true, 'orderby' => 'count', 'order' => 'DESC', 'number' => 40]);
?>
<main id="main-content" class="container page-content-default" tabindex="-1">
<header class="page-header">
<h1 class="entry-title"><?php echo esc_html(get_the_title() ?: __('文章导航', 'aksrt')); ?></h1>
</header>
<div class="content-wrap">
<div class="content-layout content-layout--no-sidebar">
<div class="content-layout__primary">
<div class="aksrt-posts-navs container">
<?php if (!empty($categories)) : ?>
<section class="aksrt-posts-navs__section">
<h2 class="aksrt-posts-navs__heading"><?php esc_html_e('热门分类', 'aksrt'); ?></h2>
<div class="aksrt-posts-navs__cats">
<?php foreach ($categories as $cat) : ?>
<a href="<?php echo esc_url(get_category_link($cat->term_id)); ?>" class="aksrt-posts-navs__cat-chip">
<span class="aksrt-posts-navs__cat-name"><?php echo esc_html($cat->name); ?></span>
<span class="aksrt-posts-navs__cat-count"><?php echo esc_html($cat->count); ?></span>
</a>
<?php endforeach; ?>
</div>
</section>
<?php endif; ?>
<?php if (!empty($tags)) : ?>
<section class="aksrt-posts-navs__section">
<h2 class="aksrt-posts-navs__heading"><?php esc_html_e('热门标签', 'aksrt'); ?></h2>
<div class="aksrt-posts-navs__tags">
<?php foreach ($tags as $tag) : ?>
<a href="<?php echo esc_url(get_tag_link($tag->term_id)); ?>" class="aksrt-posts-navs__tag"><?php echo esc_html($tag->name); ?></a>
<?php endforeach; ?>
</div>
</section>
<?php endif; ?>
</div>
</div>
</div>
</div>
</main>
<?php
get_footer();
+170
View File
@@ -0,0 +1,170 @@
<?php
/**
* Template Name: AKSRT - Product Edit
* Template Post Type: page
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
if (!is_user_logged_in()) {
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
wp_safe_redirect($login_url);
exit;
}
$product_id = (int) ($_GET['product_id'] ?? 0);
$edit_view = function_exists('aksrt_get_product_edit_page_view')
? aksrt_get_product_edit_page_view(get_current_user_id(), $product_id)
: ['allowed' => false, 'is_edit' => false, 'product' => [], 'taxonomy' => ['categories' => [], 'tags' => []], 'shipping_modes' => [], 'status_options' => []];
$product = (array) ($edit_view['product'] ?? []);
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
<div
class="aksrt-product-editor container"
data-aksrt-product-editor
data-product-id="<?php echo esc_attr((string) ($product['id'] ?? 0)); ?>"
data-is-edit="<?php echo !empty($edit_view['is_edit']) ? '1' : '0'; ?>"
>
<?php if (empty($edit_view['allowed'])) : ?>
<div class="aksrt-product-editor__empty">
<i class="fas fa-lock" aria-hidden="true"></i>
<p><?php esc_html_e('你没有权限编辑该商品。', 'aksrt'); ?></p>
</div>
<?php else : ?>
<div class="aksrt-product-editor__header">
<div>
<h1 class="aksrt-product-editor__title">
<?php echo !empty($edit_view['is_edit']) ? esc_html__('编辑商品', 'aksrt') : esc_html__('发布商品', 'aksrt'); ?>
</h1>
<p class="aksrt-product-editor__subtitle"><?php esc_html_e('管理主图、图集、分类标签、发货方式、运费和售后说明。', 'aksrt'); ?></p>
</div>
</div>
<form class="aksrt-product-editor__layout" data-aksrt-product-form>
<section class="aksrt-product-editor__main">
<div class="aksrt-product-editor__panel">
<h2><?php esc_html_e('基础信息', 'aksrt'); ?></h2>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('商品名称', 'aksrt'); ?></span>
<input type="text" name="title" class="aksrt-product-editor__input" value="<?php echo esc_attr((string) ($product['title'] ?? '')); ?>" required>
</label>
<div class="aksrt-product-editor__columns">
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('价格', 'aksrt'); ?></span>
<input type="number" name="price" class="aksrt-product-editor__input" min="0" step="0.01" value="<?php echo esc_attr((string) ($product['price'] ?? 0)); ?>" required>
</label>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('库存', 'aksrt'); ?></span>
<input type="number" name="stock" class="aksrt-product-editor__input" min="0" step="1" value="<?php echo esc_attr((string) ($product['stock'] ?? 0)); ?>" required>
</label>
</div>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('商品简介', 'aksrt'); ?></span>
<textarea name="excerpt" class="aksrt-product-editor__textarea" rows="4"><?php echo esc_textarea((string) ($product['excerpt'] ?? '')); ?></textarea>
</label>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('商品详情', 'aksrt'); ?></span>
<textarea name="content" class="aksrt-product-editor__textarea" rows="10"><?php echo esc_textarea((string) ($product['content'] ?? '')); ?></textarea>
</label>
</div>
<div class="aksrt-product-editor__panel">
<h2><?php esc_html_e('商品素材', 'aksrt'); ?></h2>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('主图 URL', 'aksrt'); ?></span>
<input type="url" name="image" class="aksrt-product-editor__input" value="<?php echo esc_attr((string) ($product['image'] ?? '')); ?>" placeholder="https://">
</label>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('图集 URL(每行一个)', 'aksrt'); ?></span>
<textarea name="gallery" class="aksrt-product-editor__textarea" rows="5"><?php echo esc_textarea(implode("\n", (array) ($product['gallery'] ?? []))); ?></textarea>
</label>
</div>
<div class="aksrt-product-editor__panel">
<h2><?php esc_html_e('发货与售后', 'aksrt'); ?></h2>
<div class="aksrt-product-editor__columns">
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('发货方式', 'aksrt'); ?></span>
<select name="shipping_mode" class="aksrt-product-editor__input">
<?php foreach ((array) ($edit_view['shipping_modes'] ?? []) as $mode) : ?>
<option value="<?php echo esc_attr((string) ($mode['value'] ?? '')); ?>" <?php selected((string) ($product['shipping_mode'] ?? ''), (string) ($mode['value'] ?? '')); ?>>
<?php echo esc_html((string) ($mode['label'] ?? '')); ?>
</option>
<?php endforeach; ?>
</select>
</label>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('额外运费', 'aksrt'); ?></span>
<input type="number" name="shipping_fee" class="aksrt-product-editor__input" min="0" step="0.01" value="<?php echo esc_attr((string) ($product['shipping_fee'] ?? 0)); ?>">
</label>
</div>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('售后说明', 'aksrt'); ?></span>
<textarea name="after_sale_policy" class="aksrt-product-editor__textarea" rows="4"><?php echo esc_textarea((string) ($product['after_sale_policy'] ?? '')); ?></textarea>
</label>
<label class="aksrt-product-editor__checkbox">
<input type="checkbox" name="support_refund" value="1" <?php checked(!empty($product['support_refund'])); ?>>
<span><?php esc_html_e('支持退款/售后入口', 'aksrt'); ?></span>
</label>
</div>
</section>
<aside class="aksrt-product-editor__sidebar">
<div class="aksrt-product-editor__panel">
<h2><?php esc_html_e('发布设置', 'aksrt'); ?></h2>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('状态', 'aksrt'); ?></span>
<select name="status" class="aksrt-product-editor__input">
<?php foreach ((array) ($edit_view['status_options'] ?? []) as $status_option) : ?>
<option value="<?php echo esc_attr((string) ($status_option['value'] ?? 'draft')); ?>" <?php selected((string) ($product['status'] ?? 'draft'), (string) ($status_option['value'] ?? 'draft')); ?>>
<?php echo esc_html((string) ($status_option['label'] ?? '')); ?>
</option>
<?php endforeach; ?>
</select>
</label>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('分类(按住 Ctrl 可多选)', 'aksrt'); ?></span>
<select name="categories[]" class="aksrt-product-editor__input" multiple size="6">
<?php foreach ((array) (($edit_view['taxonomy']['categories'] ?? [])) as $category) : ?>
<option value="<?php echo esc_attr((string) ($category['id'] ?? 0)); ?>" <?php echo in_array((int) ($category['id'] ?? 0), (array) ($product['categories'] ?? []), true) ? 'selected' : ''; ?>>
<?php echo esc_html((string) ($category['name'] ?? '')); ?>
</option>
<?php endforeach; ?>
</select>
</label>
<label class="aksrt-product-editor__field">
<span><?php esc_html_e('标签(英文逗号分隔)', 'aksrt'); ?></span>
<input type="text" name="tags" class="aksrt-product-editor__input" value="<?php echo esc_attr(implode(', ', (array) ($product['tags'] ?? []))); ?>">
</label>
</div>
<div class="aksrt-product-editor__panel">
<h2><?php esc_html_e('动作', 'aksrt'); ?></h2>
<div class="aksrt-product-editor__actions">
<button type="submit" class="btn-primary btn-lg"><?php echo !empty($edit_view['is_edit']) ? esc_html__('保存修改', 'aksrt') : esc_html__('发布商品', 'aksrt'); ?></button>
<a href="<?php echo esc_url(function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url() : home_url('/')); ?>" class="btn-ghost btn-lg"><?php esc_html_e('返回中心', 'aksrt'); ?></a>
</div>
<p class="aksrt-product-editor__hint" data-aksrt-product-editor-message><?php esc_html_e('保存后会回到用户中心,商品信息供订单页和商品详情页复用。', 'aksrt'); ?></p>
</div>
</aside>
</form>
<?php endif; ?>
</div>
</main>
<?php get_footer(); ?>
+413
View File
@@ -0,0 +1,413 @@
<?php
/**
* Template Name: AKSRT - Product Detail
* Template Post Type: page
*
* Enhanced: options selector, video gallery, params/services modal,
* review tab, favorites, related products, mobile tabbar (§6.10).
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$product_id = (int) ($_GET['product_id'] ?? 0);
if ($product_id <= 0) {
$product_id = (int) get_query_var('product_id', 0);
}
$shop = class_exists('AKSRT_Shop') ? AKSRT_Shop::get_instance() : null;
$product = function_exists('aksrt_get_product_page_view')
? aksrt_get_product_page_view($product_id)
: ($shop ? $shop->get_product_detail_view($product_id) : []);
$user_id = get_current_user_id();
$is_fav = $shop && $user_id > 0 ? $shop->is_favorite($user_id, $product_id) : false;
$options = $product['options'] ?? [];
$has_options = !empty($options);
$price_range = $product['price_range'] ?? [];
$params = $product['params'] ?? [];
$services = $product['services'] ?? [];
$pay_modo = $product['pay_modo'] ?? '0';
$scores = class_exists('AKSRT_Product_Review') ? AKSRT_Product_Review::get_instance()->get_product_scores($product_id) : [];
$reviews = class_exists('AKSRT_Product_Review') ? AKSRT_Product_Review::get_instance()->get_reviews($product_id, ['per_page' => 5]) : ['items' => [], 'total' => 0];
$author_id = (int) get_post_field('post_author', $product_id);
$author = $author_id > 0 ? get_userdata($author_id) : null;
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
<?php if (!empty($product)) : ?>
<div
class="aksrt-product-page container"
data-aksrt-product-page
data-product-id="<?php echo esc_attr((string) $product_id); ?>"
data-options='<?php echo esc_attr(wp_json_encode($options, JSON_UNESCAPED_UNICODE)); ?>'
>
<div class="aksrt-product-page__layout">
<!-- Gallery -->
<section class="aksrt-product-page__gallery">
<?php if (!empty($product['image'])) : ?>
<div class="aksrt-product-page__primary-image" data-aksrt-main-image>
<img src="<?php echo esc_url((string) $product['image']); ?>" alt="<?php echo esc_attr((string) ($product['title'] ?? '')); ?>" id="product-main-img">
</div>
<?php else : ?>
<div class="aksrt-product-page__placeholder">
<i class="fas fa-image" aria-hidden="true"></i>
</div>
<?php endif; ?>
<?php
$gallery_items = (array) ($product['gallery'] ?? []);
$cover_videos = (array) (get_post_meta($product_id, '_aksrt_cover_videos', true) ?: []);
?>
<?php if (!empty($gallery_items) || !empty($cover_videos)) : ?>
<div class="aksrt-product-page__thumbs">
<?php foreach ($cover_videos as $video_url) : ?>
<button type="button" class="aksrt-product-page__thumb aksrt-product-page__thumb--video" data-aksrt-product-video="<?php echo esc_url($video_url); ?>">
<i class="fas fa-play-circle"></i>
</button>
<?php endforeach; ?>
<?php foreach ($gallery_items as $gallery_image) : ?>
<button type="button" class="aksrt-product-page__thumb" data-aksrt-product-thumb="<?php echo esc_url($gallery_image); ?>">
<img src="<?php echo esc_url($gallery_image); ?>" alt="">
</button>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section>
<!-- Summary -->
<section class="aksrt-product-page__summary">
<div class="aksrt-product-page__badges">
<?php if ($pay_modo === 'points') : ?>
<span class="aksrt-product-page__badge aksrt-product-page__badge--points"><?php esc_html_e('积分商品', 'aksrt'); ?></span>
<?php endif; ?>
<?php if (!empty($product['marketing']['headline'])) : ?>
<span class="aksrt-product-page__badge aksrt-product-page__badge--promo"><?php echo esc_html((string) $product['marketing']['headline']); ?></span>
<?php endif; ?>
<?php if (!empty($product['after_sale']['support_refund'])) : ?>
<span class="aksrt-product-page__badge"><?php esc_html_e('支持售后', 'aksrt'); ?></span>
<?php endif; ?>
</div>
<h1 class="aksrt-product-page__title"><?php echo esc_html((string) ($product['title'] ?? '')); ?></h1>
<!-- Price row with range support -->
<div class="aksrt-product-page__price-row">
<?php if ($has_options && !empty($price_range) && $price_range['min'] !== $price_range['max']) : ?>
<strong class="aksrt-product-page__price" data-aksrt-dynamic-price>
<?php echo $pay_modo === 'points' ? '' : '¥'; ?><?php echo esc_html(number_format($price_range['min'], 2)); ?> - <?php echo $pay_modo === 'points' ? '' : '¥'; ?><?php echo esc_html(number_format($price_range['max'], 2)); ?>
<?php if ($pay_modo === 'points') : ?><small><?php esc_html_e('积分', 'aksrt'); ?></small><?php endif; ?>
</strong>
<?php else : ?>
<strong class="aksrt-product-page__price" data-aksrt-dynamic-price>
<?php echo $pay_modo === 'points' ? '' : '¥'; ?><?php echo esc_html(number_format((float) ($product['price'] ?? 0), 2)); ?>
<?php if ($pay_modo === 'points') : ?><small><?php esc_html_e('积分', 'aksrt'); ?></small><?php endif; ?>
</strong>
<?php endif; ?>
<span class="aksrt-product-page__sales"><?php printf(esc_html__('已售 %d', 'aksrt'), (int) ($product['sales'] ?? 0)); ?></span>
<?php if (!empty($scores['average'])) : ?>
<span class="aksrt-product-page__rating"><i class="fas fa-star"></i> <?php echo esc_html((string) $scores['average']); ?></span>
<?php endif; ?>
</div>
<?php if (!empty($product['excerpt'])) : ?>
<p class="aksrt-product-page__excerpt"><?php echo esc_html((string) $product['excerpt']); ?></p>
<?php endif; ?>
<!-- Product options selector -->
<?php if ($has_options) : ?>
<div class="aksrt-product-page__options" data-aksrt-options-selector>
<?php foreach ($options as $group_idx => $group) : ?>
<div class="aksrt-product-page__option-group" data-group-index="<?php echo esc_attr((string) $group_idx); ?>">
<span class="aksrt-product-page__option-label"><?php echo esc_html((string) ($group['name'] ?? '')); ?></span>
<div class="aksrt-product-page__option-values aksrt-product-page__option-values--<?php echo esc_attr($group['view_mode'] ?? 'list'); ?>">
<?php foreach ((array) ($group['values'] ?? []) as $val) : ?>
<button type="button"
class="aksrt-product-page__option-btn"
data-option-group="<?php echo esc_attr((string) $group_idx); ?>"
data-option-label="<?php echo esc_attr((string) ($val['label'] ?? '')); ?>"
data-price-change="<?php echo esc_attr((string) ($val['price_change'] ?? 0)); ?>"
<?php if (!empty($val['image'])) : ?>data-option-image="<?php echo esc_url($val['image']); ?>"<?php endif; ?>
>
<?php if (($group['view_mode'] ?? '') === 'img' && !empty($val['image'])) : ?>
<img src="<?php echo esc_url($val['image']); ?>" alt="<?php echo esc_attr($val['label']); ?>">
<?php endif; ?>
<span><?php echo esc_html((string) ($val['label'] ?? '')); ?></span>
<?php if ((float) ($val['price_change'] ?? 0) !== 0.0) : ?>
<em><?php echo (float) $val['price_change'] > 0 ? '+' : ''; ?><?php echo esc_html(number_format((float) $val['price_change'], 2)); ?></em>
<?php endif; ?>
</button>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
<div class="aksrt-product-page__option-result" data-aksrt-option-result hidden>
<span data-aksrt-selected-labels></span>
<strong data-aksrt-resolved-price></strong>
<span data-aksrt-resolved-stock></span>
</div>
</div>
<?php endif; ?>
<!-- Meta info -->
<dl class="aksrt-product-page__meta">
<div>
<dt><?php esc_html_e('库存', 'aksrt'); ?></dt>
<dd data-aksrt-stock-display><?php
$stock_val = (int) ($product['stock'] ?? 0);
echo $stock_val <= -1 ? esc_html__('充足', 'aksrt') : esc_html((string) $stock_val);
?></dd>
</div>
<div>
<dt><?php esc_html_e('配送', 'aksrt'); ?></dt>
<dd><?php echo esc_html((string) (($product['shipping']['delivery_note'] ?? '') ?: __('标准配送', 'aksrt'))); ?></dd>
</div>
<div>
<dt><?php esc_html_e('运费', 'aksrt'); ?></dt>
<dd><?php
$ship_fee = (float) ($product['shipping']['fee'] ?? 0);
echo $ship_fee > 0 ? '¥' . esc_html(number_format($ship_fee, 2)) : esc_html__('包邮', 'aksrt');
?></dd>
</div>
</dl>
<!-- Params & Services quick links -->
<?php if (!empty($params)) : ?>
<button type="button" class="aksrt-product-page__info-trigger" data-aksrt-show-params>
<i class="fas fa-list-ul"></i> <?php esc_html_e('商品参数', 'aksrt'); ?> <i class="fas fa-chevron-right"></i>
</button>
<?php endif; ?>
<?php if (!empty($services)) : ?>
<button type="button" class="aksrt-product-page__info-trigger" data-aksrt-show-services>
<i class="fas fa-shield-alt"></i> <?php esc_html_e('服务保障', 'aksrt'); ?> <i class="fas fa-chevron-right"></i>
</button>
<?php endif; ?>
<!-- Purchase box -->
<div class="aksrt-product-page__purchase-box">
<label class="aksrt-product-page__field">
<span><?php esc_html_e('购买数量', 'aksrt'); ?></span>
<div class="aksrt-product-page__quantity">
<button type="button" class="aksrt-product-page__qty-btn" data-aksrt-qty-action="dec">-</button>
<input type="number" min="1" max="<?php echo esc_attr((string) max(1, $stock_val > 0 ? $stock_val : 999)); ?>" value="1" class="aksrt-product-page__qty-input" data-aksrt-quantity>
<button type="button" class="aksrt-product-page__qty-btn" data-aksrt-qty-action="inc">+</button>
</div>
</label>
<div class="aksrt-product-page__actions">
<?php if (is_user_logged_in() && !empty($product['purchase_enabled'])) : ?>
<button type="button" class="btn-outline btn-lg" data-aksrt-add-cart><?php esc_html_e('加入购物车', 'aksrt'); ?></button>
<button type="button" class="btn-primary btn-lg" data-aksrt-buy-now>
<?php echo $pay_modo === 'points' ? esc_html__('积分兑换', 'aksrt') : esc_html__('立即下单', 'aksrt'); ?>
</button>
<?php elseif (!is_user_logged_in()) : ?>
<a href="<?php echo esc_url(function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink())); ?>" class="btn-primary btn-lg">
<?php esc_html_e('登录后购买', 'aksrt'); ?>
</a>
<?php else : ?>
<button type="button" class="btn-primary btn-lg" disabled><?php esc_html_e('暂不可购买', 'aksrt'); ?></button>
<?php endif; ?>
</div>
<!-- Auxiliary actions -->
<div class="aksrt-product-page__aux-actions">
<button type="button" class="aksrt-product-page__aux-btn<?php echo $is_fav ? ' is-active' : ''; ?>" data-aksrt-toggle-fav="<?php echo esc_attr((string) $product_id); ?>">
<i class="<?php echo $is_fav ? 'fas' : 'far'; ?> fa-heart"></i>
<?php esc_html_e('收藏', 'aksrt'); ?>
</button>
<button type="button" class="aksrt-product-page__aux-btn" data-aksrt-share>
<i class="fas fa-share-alt"></i> <?php esc_html_e('分享', 'aksrt'); ?>
</button>
</div>
</div>
<!-- Merchant info -->
<?php if ($author) : ?>
<div class="aksrt-product-page__merchant">
<img src="<?php echo esc_url(function_exists('aksrt_get_avatar_url') ? aksrt_get_avatar_url($author_id) : get_avatar_url($author_id)); ?>" alt="" class="aksrt-product-page__merchant-avatar">
<div>
<strong><?php echo esc_html($author->display_name); ?></strong>
<a href="<?php echo esc_url(get_author_posts_url($author_id)); ?>?tab=products" class="aksrt-product-page__merchant-link"><?php esc_html_e('进入店铺', 'aksrt'); ?></a>
</div>
</div>
<?php endif; ?>
</section>
</div>
<!-- Tabs: detail / reviews / custom -->
<div class="aksrt-product-page__tabs">
<nav class="aksrt-product-page__tab-nav">
<button class="aksrt-product-page__tab-btn is-active" data-aksrt-tab="detail"><?php esc_html_e('商品详情', 'aksrt'); ?></button>
<button class="aksrt-product-page__tab-btn" data-aksrt-tab="reviews">
<?php esc_html_e('评价', 'aksrt'); ?>
<?php if (($scores['total'] ?? 0) > 0) : ?>
<em>(<?php echo esc_html((string) $scores['total']); ?>)</em>
<?php endif; ?>
</button>
</nav>
<div class="aksrt-product-page__tab-panel is-active" data-aksrt-tab-panel="detail">
<div class="aksrt-product-page__content">
<?php echo wp_kses_post((string) ($product['content'] ?? '')); ?>
</div>
</div>
<div class="aksrt-product-page__tab-panel" data-aksrt-tab-panel="reviews">
<?php if (!empty($scores['total'])) : ?>
<div class="aksrt-product-page__review-summary">
<strong class="aksrt-product-page__review-avg"><?php echo esc_html((string) ($scores['average'] ?? '0')); ?></strong>
<span class="aksrt-product-page__review-level"><?php echo esc_html((string) ($scores['level'] ?? '')); ?></span>
<div class="aksrt-product-page__review-counts">
<span><?php printf(esc_html__('好评 %d', 'aksrt'), (int) ($scores['good'] ?? 0)); ?></span>
<span><?php printf(esc_html__('差评 %d', 'aksrt'), (int) ($scores['bad'] ?? 0)); ?></span>
<span><?php printf(esc_html__('有图 %d', 'aksrt'), (int) ($scores['has_image'] ?? 0)); ?></span>
</div>
</div>
<?php endif; ?>
<div class="aksrt-product-page__review-list" data-aksrt-review-list>
<?php foreach (($reviews['items'] ?? []) as $review) : ?>
<div class="aksrt-product-page__review-item">
<div class="aksrt-product-page__review-header">
<img src="<?php echo esc_url((string) ($review['user_avatar'] ?? '')); ?>" alt="" class="aksrt-product-page__review-avatar">
<span class="aksrt-product-page__review-name"><?php echo esc_html((string) ($review['user_name'] ?? '')); ?></span>
<span class="aksrt-product-page__review-date"><?php echo esc_html((string) ($review['date'] ?? '')); ?></span>
<span class="aksrt-product-page__review-stars">
<?php for ($s = 0; $s < 5; $s++) : ?>
<i class="<?php echo $s < (int) ($review['rating_average'] ?? 0) ? 'fas' : 'far'; ?> fa-star"></i>
<?php endfor; ?>
</span>
</div>
<p class="aksrt-product-page__review-text"><?php echo esc_html((string) ($review['content'] ?? '')); ?></p>
<?php if (!empty($review['images'])) : ?>
<div class="aksrt-product-page__review-images">
<?php foreach ((array) $review['images'] as $rimg) : ?>
<img src="<?php echo esc_url($rimg); ?>" alt="" class="aksrt-product-page__review-img">
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
<?php if (empty($reviews['items'])) : ?>
<p class="aksrt-product-page__review-empty"><?php esc_html_e('暂无评价', 'aksrt'); ?></p>
<?php endif; ?>
</div>
</div>
</div>
<!-- Related products -->
<?php
$related_query = new WP_Query([
'post_type' => 'aksrt_product',
'posts_per_page' => 6,
'post_status' => 'publish',
'post__not_in' => [$product_id],
'tax_query' => !empty($product['categories']) ? [[
'taxonomy' => 'aksrt_product_cat',
'field' => 'term_id',
'terms' => wp_list_pluck($product['categories'], 'term_id'),
]] : [],
'orderby' => 'rand',
]);
?>
<?php if ($related_query->have_posts()) : ?>
<section class="aksrt-product-page__related">
<h2><?php esc_html_e('相关推荐', 'aksrt'); ?></h2>
<div class="aksrt-product-page__related-grid">
<?php while ($related_query->have_posts()) : $related_query->the_post(); ?>
<a href="<?php echo esc_url(get_permalink()); ?>" class="aksrt-product-page__related-card">
<?php $thumb = $shop ? $shop->resolve_main_image(get_the_ID()) : get_the_post_thumbnail_url(get_the_ID(), 'medium'); ?>
<?php if ($thumb) : ?>
<img src="<?php echo esc_url($thumb); ?>" alt="<?php the_title_attribute(); ?>" loading="lazy">
<?php endif; ?>
<h3><?php the_title(); ?></h3>
<strong>¥<?php echo esc_html(number_format((float) get_post_meta(get_the_ID(), '_aksrt_price', true), 2)); ?></strong>
</a>
<?php endwhile; wp_reset_postdata(); ?>
</div>
</section>
<?php endif; ?>
</div>
<!-- Params modal -->
<?php if (!empty($params)) : ?>
<div class="aksrt-modal" data-aksrt-params-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-modal-close>&times;</button>
</div>
<div class="aksrt-modal__body">
<table class="aksrt-product-page__params-table">
<?php foreach ($params as $param) : ?>
<tr>
<th><?php echo esc_html((string) ($param['name'] ?? '')); ?></th>
<td><?php echo esc_html((string) ($param['value'] ?? '')); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
</div>
<?php endif; ?>
<!-- Services modal -->
<?php if (!empty($services)) : ?>
<div class="aksrt-modal" data-aksrt-services-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-modal-close>&times;</button>
</div>
<div class="aksrt-modal__body">
<?php foreach ($services as $service) : ?>
<div class="aksrt-product-page__service-item">
<?php if (!empty($service['icon'])) : ?>
<img src="<?php echo esc_url($service['icon']); ?>" alt="" class="aksrt-product-page__service-icon">
<?php else : ?>
<i class="fas fa-check-circle"></i>
<?php endif; ?>
<div>
<strong><?php echo esc_html((string) ($service['name'] ?? '')); ?></strong>
<?php if (!empty($service['desc'])) : ?>
<p><?php echo esc_html((string) $service['desc']); ?></p>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endif; ?>
<!-- Mobile purchase tabbar -->
<div class="aksrt-product-page__mobile-bar" data-aksrt-mobile-purchase>
<button type="button" class="aksrt-product-page__mobile-btn" data-aksrt-toggle-fav="<?php echo esc_attr((string) $product_id); ?>">
<i class="<?php echo $is_fav ? 'fas' : 'far'; ?> fa-heart"></i>
</button>
<button type="button" class="aksrt-product-page__mobile-btn" data-aksrt-add-cart>
<i class="fas fa-shopping-cart"></i>
</button>
<button type="button" class="aksrt-product-page__mobile-buy btn-primary" data-aksrt-buy-now>
<?php echo $pay_modo === 'points' ? esc_html__('积分兑换', 'aksrt') : esc_html__('立即购买', 'aksrt'); ?>
</button>
</div>
<?php else : ?>
<div class="aksrt-product-page container">
<div class="aksrt-product-page__empty">
<i class="fas fa-box-open" aria-hidden="true"></i>
<p><?php esc_html_e('商品不存在或已下架。', 'aksrt'); ?></p>
</div>
</div>
<?php endif; ?>
</main>
<?php get_footer(); ?>
File diff suppressed because it is too large. Load diff
+11
View File
@@ -0,0 +1,11 @@
<?php
/**
* Template Name: AKSRT - Register
* Template Post Type: page
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
require AKSRT_DIR . '/templates/pages/page-sign.php';
+172
View File
@@ -0,0 +1,172 @@
<?php
/**
* Template Name: AKSRT - Reset Password
* Template Post Type: page
*
* Theme auth route template: /reset-password/
*
* 统一处理:
* 1. 忘记密码(无 token 参数)— 输入邮箱/用户名请求重置
* 2. 设置密码(有 token+uid 参数)— 邮件链接进入后设置新密码
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
// ============================================
// 检测当前模式:设置密码 or 请求重置
// ============================================
$context = AKSRT_Auth_Service::get_reset_context($_GET);
$mode = $context['mode'];
$errors = [];
$success = '';
$token = $context['token'];
$user_id = $context['user_id'];
if (!empty($context['error'])) {
$errors[] = $context['error'];
}
// ============================================
// 处理表单提交
// ============================================
// 模式1:请求重置密码(忘记密码表单提交)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['aksrt_action']) && $_POST['aksrt_action'] === 'request_reset') {
$result = AKSRT_Auth_Service::request_password_reset($_POST);
if (!empty($result['success'])) {
$success = $result['message'] ?? __('如果该账号存在,重置邮件已发送到注册邮箱', 'aksrt');
} else {
$errors[] = $result['error'] ?? __('重置请求失败,请稍后重试', 'aksrt');
}
}
// 模式2:设置新密码(从邮件链接进入)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['aksrt_action']) && $_POST['aksrt_action'] === 'set_password') {
$result = AKSRT_Auth_Service::reset_password_with_token($_POST);
if (!empty($result['success'])) {
$mode = 'success';
$success = $result['message'] ?? __('密码已设置成功!', 'aksrt');
} else {
$errors[] = $result['error'] ?? __('重置密码失败,请稍后重试', 'aksrt');
$mode = $result['mode'] ?? 'invalid';
}
}
get_header();
?>
<main id="main-content" class="site-main" tabindex="-1">
<div class="auth-shell">
<div class="auth-card">
<div class="auth-card__logo" aria-hidden="true">AK</div>
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
<?php if ($mode === 'success') : ?>
<!-- 密码设置成功 -->
<p class="auth-card__subtitle"><?php esc_html_e('密码设置成功!', 'aksrt'); ?></p>
<div class="alert alert--success" role="alert">
<span><?php echo esc_html($success); ?></span>
</div>
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>" class="btn-primary btn-lg" style="width:100%;display:block;text-align:center;text-decoration:none;margin-top:16px;">
<?php esc_html_e('立即登录', 'aksrt'); ?>
</a>
<?php elseif ($mode === 'invalid') : ?>
<!-- 链接无效或已过期 -->
<p class="auth-card__subtitle"><?php esc_html_e('重置链接无效或已过期', 'aksrt'); ?></p>
<?php if (!empty($errors)) : ?>
<div class="alert alert--error" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
<span><?php echo esc_html($errors[0]); ?></span>
</div>
<?php endif; ?>
<a href="<?php echo esc_url(aksrt_get_reset_password_url()); ?>" class="btn-primary btn-lg" style="width:100%;display:block;text-align:center;text-decoration:none;margin-top:16px;">
<?php esc_html_e('重新申请重置密码', 'aksrt'); ?>
</a>
<?php elseif ($mode === 'reset') : ?>
<!-- 设置新密码表单 -->
<p class="auth-card__subtitle"><?php esc_html_e('请设置你的新密码', 'aksrt'); ?></p>
<?php if (!empty($errors)) : ?>
<div class="alert alert--error" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
<span><?php echo esc_html($errors[0]); ?></span>
</div>
<?php endif; ?>
<form class="auth-form" id="aksrt-set-password-form" method="post" action="">
<?php wp_nonce_field('aksrt_set_password', '_setpw_nonce'); ?>
<input type="hidden" name="aksrt_action" value="set_password">
<input type="hidden" name="reset_token" value="<?php echo esc_attr($token); ?>">
<input type="hidden" name="reset_uid" value="<?php echo esc_attr((string) $user_id); ?>">
<div class="form-field form-field--pwd">
<label for="pass1"><?php esc_html_e('新密码', 'aksrt'); ?></label>
<div class="input-wrap">
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>
<input type="password" name="pass1" id="pass1" autocomplete="new-password" required minlength="6">
<button type="button" class="toggle-pwd" data-target="pass1" aria-label="<?php esc_attr_e('显示或隐藏密码', 'aksrt'); ?>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg></button>
</div>
</div>
<div class="form-field form-field--pwd">
<label for="pass2"><?php esc_html_e('确认新密码', 'aksrt'); ?></label>
<div class="input-wrap">
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg></span>
<input type="password" name="pass2" id="pass2" autocomplete="new-password" required minlength="6">
<button type="button" class="toggle-pwd" data-target="pass2" aria-label="<?php esc_attr_e('显示或隐藏密码', 'aksrt'); ?>"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;"><path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/></svg></button>
</div>
</div>
<button type="submit" class="btn-primary btn-lg btn-block"><?php esc_html_e('设置新密码', 'aksrt'); ?></button>
</form>
<?php else : ?>
<!-- 请求重置密码表单(忘记密码) -->
<p class="auth-card__subtitle"><?php esc_html_e('输入邮箱或用户名,我们将发送重置链接', 'aksrt'); ?></p>
<?php if (!empty($errors)) : ?>
<div class="alert alert--error" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
<span><?php echo esc_html($errors[0]); ?></span>
</div>
<?php endif; ?>
<?php if (!empty($success)) : ?>
<div class="alert alert--success" role="alert">
<span><?php echo esc_html($success); ?></span>
</div>
<?php endif; ?>
<form class="auth-form" id="aksrt-request-reset-form" method="post" action="">
<?php wp_nonce_field('aksrt_reset_password', '_reset_nonce'); ?>
<input type="hidden" name="aksrt_action" value="request_reset">
<div class="form-field">
<label for="user_login"><?php esc_html_e('邮箱 / 用户名', 'aksrt'); ?></label>
<div class="input-wrap">
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
<input type="text" name="user_login" id="user_login" autocomplete="username" required>
</div>
</div>
<?php aksrt_render_captcha('lostpassword'); ?>
<button type="submit" class="btn-primary btn-lg btn-block"><?php esc_html_e('发送重置链接', 'aksrt'); ?></button>
</form>
<p class="auth-footer-link">
<?php esc_html_e('想起密码了?', 'aksrt'); ?>
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>"><?php esc_html_e('返回登录', 'aksrt'); ?></a>
</p>
<?php endif; ?>
</div>
</div>
</main>
<?php
get_footer();
+127
View File
@@ -0,0 +1,127 @@
<?php
/**
* Template Name: AKSRT - Revenue
* Template Post Type: page
*
* 创作者收益中心页面 — 显示收益概览、分成记录和提现入口
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
if (!is_user_logged_in()) {
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(get_permalink());
wp_safe_redirect($login_url);
exit;
}
$user_id = get_current_user_id();
// 通过 helper 获取收益视图模型
$revenue_view = function_exists('aksrt_get_revenue_page_view')
? aksrt_get_revenue_page_view($user_id)
: ['balance' => 0, 'total_earned' => 0, 'total_withdrawn' => 0, 'records' => []];
$balance = (float) ($revenue_view['balance'] ?? 0);
$total_earned = (float) ($revenue_view['total_earned'] ?? 0);
$total_withdrawn = (float) ($revenue_view['total_withdrawn'] ?? 0);
$records = $revenue_view['records'] ?? [];
$per_page = 20;
$paged = max(1, (int) ($_GET['rev_page'] ?? 1));
$total_records = count($records);
$total_pages = max(1, (int) ceil($total_records / $per_page));
$paged_records = array_slice($records, ($paged - 1) * $per_page, $per_page);
?>
<div class="container aksrt-revenue-page">
<div class="aksrt-revenue-page__header">
<h2><?php esc_html_e('创作收益', 'aksrt'); ?></h2>
</div>
<!-- 收益概览 -->
<div class="aksrt-revenue-page__stats">
<div class="aksrt-revenue-page__stat-card">
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-wallet"></i></div>
<div class="aksrt-revenue-page__stat-info">
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($balance, 2)); ?></span>
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('可提现余额', 'aksrt'); ?></span>
</div>
</div>
<div class="aksrt-revenue-page__stat-card">
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-chart-line"></i></div>
<div class="aksrt-revenue-page__stat-info">
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($total_earned, 2)); ?></span>
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('累计收益', 'aksrt'); ?></span>
</div>
</div>
<div class="aksrt-revenue-page__stat-card">
<div class="aksrt-revenue-page__stat-icon"><i class="fas fa-money-check-alt"></i></div>
<div class="aksrt-revenue-page__stat-info">
<span class="aksrt-revenue-page__stat-value">¥<?php echo esc_html(number_format($total_withdrawn, 2)); ?></span>
<span class="aksrt-revenue-page__stat-label"><?php esc_html_e('已提现', 'aksrt'); ?></span>
</div>
</div>
</div>
<!-- 提现按钮 -->
<?php if ($balance > 0) : ?>
<div class="aksrt-revenue-page__actions">
<a href="<?php echo esc_url(add_query_arg(['action' => 'withdraw'])); ?>" class="aksrt-revenue-page__withdraw-btn">
<i class="fas fa-hand-holding-usd"></i> <?php esc_html_e('申请提现', 'aksrt'); ?>
</a>
</div>
<?php endif; ?>
<!-- 分成记录 -->
<div class="aksrt-revenue-page__section">
<h3><?php esc_html_e('收益明细', 'aksrt'); ?></h3>
<?php if (!empty($paged_records)) : ?>
<div class="aksrt-revenue-page__list">
<?php foreach ($paged_records as $record) :
$r_type = (string) ($record['type'] ?? 'earning');
?>
<div class="aksrt-revenue-page__item">
<div class="aksrt-revenue-page__item-icon">
<i class="<?php echo $r_type === 'withdrawal' ? 'fas fa-arrow-up' : 'fas fa-arrow-down'; ?>"
style="color: <?php echo $r_type === 'withdrawal' ? '#f5222d' : '#52c41a'; ?>;"></i>
</div>
<div class="aksrt-revenue-page__item-info">
<span class="aksrt-revenue-page__item-title"><?php echo esc_html($record['title'] ?? ''); ?></span>
<span class="aksrt-revenue-page__item-time"><?php echo esc_html($record['created_at'] ?? ''); ?></span>
</div>
<div class="aksrt-revenue-page__item-amount" style="color: <?php echo $r_type === 'withdrawal' ? '#f5222d' : '#52c41a'; ?>;">
<?php echo $r_type === 'withdrawal' ? '-' : '+'; ?>¥<?php echo esc_html(number_format((float) ($record['amount'] ?? 0), 2)); ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php if ($total_pages > 1) : ?>
<div class="aksrt-revenue-page__pagination">
<?php for ($i = 1; $i <= $total_pages; $i++) :
$page_url = add_query_arg(['rev_page' => $i]);
?>
<?php if ($i === $paged) : ?>
<span class="aksrt-revenue-page__page-chip is-active"><?php echo esc_html((string) $i); ?></span>
<?php else : ?>
<a href="<?php echo esc_url($page_url); ?>" class="aksrt-revenue-page__page-chip"><?php echo esc_html((string) $i); ?></a>
<?php endif; ?>
<?php endfor; ?>
</div>
<?php endif; ?>
<?php else : ?>
<div class="aksrt-revenue-page__empty">
<i class="fas fa-chart-pie"></i>
<p><?php esc_html_e('暂无收益记录', 'aksrt'); ?></p>
</div>
<?php endif; ?>
</div>
</div>
<?php get_footer(); ?>
+345
View File
@@ -0,0 +1,345 @@
<?php
/**
* Template Name: AKSRT - 登录/注册
* Template Post Type: page
*
* @package AKSRT
*/
@session_start();
$route_tab = function_exists('aksrt_get_auth_tab') ? aksrt_get_auth_tab() : 'login';
$requested_tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash((string) $_GET['tab'])) : '';
$tab_aliases = [
'login' => 'signin',
'signin' => 'signin',
'register' => 'signup',
'signup' => 'signup',
];
$tab_source = $requested_tab !== '' ? $requested_tab : $route_tab;
$tab = $tab_aliases[$tab_source] ?? 'signin';
$redirect_to = !empty($_GET['redirect_to']) ? esc_url_raw(wp_unslash((string) $_GET['redirect_to'])) : home_url();
$registration_open = class_exists('AKSRT_Settings') && AKSRT_Settings::registration_enabled();
$titles = [
'signin' => __('用户登录', 'aksrt'),
'signup' => __('用户注册', 'aksrt'),
];
$page_title = ($titles[$tab] ?? __('登录 / 注册', 'aksrt')) . ' - ' . get_bloginfo('name');
$interim = isset($_REQUEST['interim-login']);
// 搂4.1 Defense-in-depth: redirect out when close_sign is active (backup of auth router gate)
if (class_exists('AKSRT_Settings') && AKSRT_Settings::close_sign() && !is_user_logged_in() && !$interim) {
wp_safe_redirect(home_url('/'), 302);
exit;
}
// §4.1 close_signin: password login disabled — force signin tab to show social-only message
$close_signin = class_exists('AKSRT_Settings') ? AKSRT_Settings::close_signin() : false;
if ($close_signin && $tab === 'signin') {
// Don't allow password form submission
$_SERVER['REQUEST_METHOD'] = 'GET';
}
$user_id = get_current_user_id();
if ($user_id) {
if ($interim && is_super_admin()) {
echo '<!DOCTYPE HTML><html><body class="login interim-login-success"><div style="padding:60px 0;text-align:center;color:#1a88fd;">' . esc_html__('登录成功', 'aksrt') . '</div></body></html>';
exit;
}
wp_safe_redirect($redirect_to);
exit;
}
if ($tab === 'signup' && !$registration_open) {
$tab = 'signin';
}
remove_action('wp_footer', 'aksrt_render_footer_tabbar', 20);
remove_action('wp_footer', 'aksrt_render_float_buttons', 30);
$background_html = '';
$sign_ui = class_exists('AKSRT_Settings') ? AKSRT_Settings::sign_page_ui() : [];
$card_position = $sign_ui['card_position'] ?? 'center';
$sign_show_logo = $sign_ui['show_logo'] ?? true;
$sign_show_header = $sign_ui['show_header'] ?? true;
$sign_theme_mode = $sign_ui['theme_mode'] ?? 'default';
if (class_exists('AKSRT_Settings')) {
$bg_ids = $sign_ui['background'] ?? [];
if (is_array($bg_ids) && !empty($bg_ids)) {
$bg_url = wp_get_attachment_url((int) $bg_ids[array_rand($bg_ids)]);
if ($bg_url) {
$background_html = '<div class="sign-bg" style="background-image:url(' . esc_url($bg_url) . ');"></div>';
}
} elseif (is_string($bg_ids) && $bg_ids !== '') {
// BC: comma-separated string from old storage
$ids = array_filter(array_map('absint', explode(',', $bg_ids)));
if (!empty($ids)) {
$bg_url = wp_get_attachment_url($ids[array_rand($ids)]);
if ($bg_url) {
$background_html = '<div class="sign-bg" style="background-image:url(' . esc_url($bg_url) . ');"></div>';
}
}
}
}
$login_error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['log'], $_POST['pwd']) && $tab === 'signin') {
if (class_exists('AKSRT_Auth_Service')) {
$result = AKSRT_Auth_Service::login_user($_POST, false);
if (empty($result['success'])) {
$login_error = $result['error'] ?? __('登录失败', 'aksrt');
} else {
wp_safe_redirect($result['redirect'] ?? home_url('/'));
exit;
}
}
}
$register_error = '';
$register_success = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['user_login'], $_POST['user_email']) && $tab === 'signup') {
if (class_exists('AKSRT_Auth_Service')) {
$result = AKSRT_Auth_Service::register_user($_POST, ['oauth_bind_data' => null, 'obk' => '']);
if (!empty($result['success'])) {
if (!empty($result['verification_required'])) {
$register_success = sprintf(
'%s <a href="%s">%s</a>',
esc_html($result['message'] ?? __('Registration successful. Please complete email verification.', 'aksrt')),
esc_url($result['verify_url'] ?? ''),
esc_html__('前往验证', 'aksrt')
);
} else {
$register_success = sprintf(
__('Registration successful. Please continue on the <a href="%s">login page</a>.', 'aksrt'),
esc_url(aksrt_get_login_url())
);
}
} else {
$register_error = $result['error'] ?? __('注册失败', 'aksrt');
}
}
}
$invite_prefill = '';
if (!empty($_GET['invite'])) {
$invite_prefill = sanitize_key(wp_unslash($_GET['invite']));
} elseif (!empty($_COOKIE['aksrt_invite'])) {
$invite_prefill = sanitize_key(wp_unslash($_COOKIE['aksrt_invite']));
}
?>
<!DOCTYPE html>
<html lang="<?php echo esc_attr(str_replace('_', '-', get_bloginfo('language'))); ?>">
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0">
<meta name="robots" content="noindex, nofollow">
<title><?php echo esc_html($page_title); ?></title>
<?php wp_head(); ?>
<style>
.sign-page{min-height:100vh;display:flex;align-items:center;justify-content:center;position:relative;padding:70px 16px 40px}
.sign-bg{position:fixed;inset:0;background-repeat:no-repeat;background-size:cover;background-position:center;z-index:0}
.sign-card{position:relative;z-index:1;width:100%;max-width:420px;background:var(--main-bg-color,#fff);border-radius:var(--main-radius,8px);box-shadow:0 0 10px var(--main-shadow,rgba(116,116,116,0.08));padding:30px 35px}
.sign-card--left{margin-right:auto}
.sign-card--right{margin-left:auto}
.sign-card--center{margin:0 auto}
.sign-logo{text-align:center;margin-bottom:20px}
.sign-logo img{height:36px}
.sign-logo__text{display:inline-flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:12px;background:var(--focus-color,#f04494);color:#fff;font-size:18px;font-weight:700;text-decoration:none}
.sign-tabs{display:flex;border-bottom:2px solid var(--main-border-color,rgba(50,50,50,0.06));margin-bottom:20px}
.sign-tab{flex:1;padding:10px 0;border:none;background:none;font-size:15px;cursor:pointer;color:var(--muted-color,#777);border-bottom:2px solid transparent;margin-bottom:-2px;transition:all .2s;text-align:center;font-weight:500}
.sign-tab.is-active{color:var(--focus-color,#f04494);border-bottom-color:var(--focus-color,#f04494);font-weight:600}
.sign-tab:hover{color:var(--focus-color,#f04494)}
.sign-panel{display:none}
.sign-panel.is-active{display:block}
.sign-error{background:rgba(239,68,68,0.08);border:1px solid rgba(239,68,68,0.2);border-radius:var(--main-radius,8px);padding:10px 14px;font-size:13px;color:#ef4444;margin-bottom:16px}
.sign-success{background:rgba(16,185,129,0.08);border:1px solid rgba(16,185,129,0.2);border-radius:var(--main-radius,8px);padding:10px 14px;font-size:13px;color:#10b981;margin-bottom:16px}
.sign-form{display:flex;flex-direction:column;gap:16px}
.sign-form .form-field{display:flex;flex-direction:column;gap:6px}
.sign-form label{font-size:14px;font-weight:500;color:var(--main-color,#4e5358)}
.sign-form .input-wrap{position:relative}
.sign-form .input-wrap input{width:100%;height:44px;padding:0 14px;border:1px solid transparent;background:var(--body-bg-color,#f5f6f7);border-radius:var(--main-radius,8px);font-size:14px;color:var(--key-color,#333);transition:border-color .15s}
.sign-form .input-wrap input:focus{outline:none;border-color:var(--focus-color,#f04494);box-shadow:0 0 2px 3px var(--focus-shadow-color,rgba(253,83,161,0.4))}
.sign-form .toggle-pwd{position:absolute;right:10px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;color:var(--muted-2-color,#999);padding:4px}
.sign-form .form-row-between{display:flex;align-items:center;justify-content:space-between;font-size:13px}
.sign-form .form-row-between a{color:var(--focus-color,#f04494)}
.sign-form .form-row-between label{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;color:var(--muted-color,#777)}
.sign-form .btn-submit{width:100%;height:44px;border:none;border-radius:var(--main-radius,8px);background:var(--focus-color,#f04494);color:#fff;font-size:15px;font-weight:600;cursor:pointer;transition:opacity .15s}
.sign-form .btn-submit:hover{opacity:.85}
.sign-form .btn-submit:disabled{opacity:.5;cursor:not-allowed}
.sign-hint{margin:0;font-size:13px;color:var(--muted-color,#777)}
.sign-terms{display:flex;align-items:flex-start;gap:8px;font-size:13px;cursor:pointer;color:var(--muted-color,#777)}
.sign-footer{text-align:center;margin-top:20px;font-size:14px;color:var(--muted-color,#777)}
.sign-footer a{color:var(--focus-color,#f04494)}
.sign-footer-bar{position:fixed;bottom:0;left:0;right:0;text-align:center;padding:10px;font-size:12px;color:var(--muted-2-color,#999);z-index:1}
@media(max-width:480px){.sign-card{padding:24px 20px}}
</style>
</head>
<body <?php body_class('page-template-user-sign' . ($sign_theme_mode !== 'default' ? ' sign-theme-' . esc_attr($sign_theme_mode) : '')); ?>>
<?php echo $background_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<main class="sign-page">
<div class="sign-card sign-card--<?php echo esc_attr($card_position); ?>">
<?php if ($sign_show_logo) : ?>
<div class="sign-logo">
<?php $logo_url = class_exists('AKSRT_Settings') ? AKSRT_Settings::user_logo_url() : ''; ?>
<?php if ($logo_url) : ?>
<a href="<?php echo esc_url(home_url('/')); ?>"><img src="<?php echo esc_url($logo_url); ?>" alt="<?php echo esc_attr(get_bloginfo('name')); ?>"></a>
<?php else : ?>
<a href="<?php echo esc_url(home_url('/')); ?>" class="sign-logo__text"><?php echo esc_html(mb_substr(get_bloginfo('name'), 0, 2)); ?></a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ($sign_show_header) : ?>
<div class="sign-tabs">
<button type="button" class="sign-tab<?php echo $tab === 'signin' ? ' is-active' : ''; ?>" data-sign-tab="signin"><?php esc_html_e('登录', 'aksrt'); ?></button>
<?php if ($registration_open) : ?>
<button type="button" class="sign-tab<?php echo $tab === 'signup' ? ' is-active' : ''; ?>" data-sign-tab="signup"><?php esc_html_e('注册', 'aksrt'); ?></button>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="sign-panel<?php echo $tab === 'signin' ? ' is-active' : ''; ?>" data-sign-panel="signin">
<?php if ($login_error) : ?><div class="sign-error"><?php echo esc_html($login_error); ?></div><?php endif; ?>
<?php if ($close_signin) : ?>
<div class="sign-notice" style="padding:16px;text-align:center;color:var(--muted-2-color,#666);">
<?php esc_html_e('This site currently supports third-party account sign-in only. Please use one of the social login buttons below.', 'aksrt'); ?>
</div>
<?php else : ?>
<form class="sign-form" id="sign-login-form" method="post" action="">
<?php wp_nonce_field('aksrt_login', '_login_nonce'); ?>
<div class="form-field">
<label for="sign-user-login"><?php esc_html_e('Email / Username', 'aksrt'); ?></label>
<div class="input-wrap"><input type="text" name="log" id="sign-user-login" autocomplete="username" required placeholder="<?php esc_attr_e('Please enter your email or username', 'aksrt'); ?>"></div>
</div>
<div class="form-field">
<label for="sign-user-pass"><?php esc_html_e('密码', 'aksrt'); ?></label>
<div class="input-wrap">
<input type="password" name="pwd" id="sign-user-pass" autocomplete="current-password" required>
<button type="button" class="toggle-pwd" data-target="sign-user-pass"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="form-row-between">
<label><input type="checkbox" name="rememberme" value="forever"> <?php esc_html_e('Remember me', 'aksrt'); ?></label>
<a href="<?php echo esc_url(aksrt_get_reset_password_url()); ?>"><?php esc_html_e('Forgot password?', 'aksrt'); ?></a>
</div>
<?php if (function_exists('aksrt_render_captcha')) aksrt_render_captcha('login'); ?>
<input type="hidden" name="redirect_to" value="<?php echo esc_url($redirect_to); ?>">
<button type="submit" class="btn-submit"><?php esc_html_e('登录', 'aksrt'); ?></button>
</form>
<?php endif; // close_signin gate ?>
<?php if (class_exists('AKSRT_OAuth')) : ?>
<?php $social = AKSRT_OAuth::get_instance()->render_social_buttons(); ?>
<?php if ($social) echo '<div style="margin-top:20px;">' . $social . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php endif; ?>
<?php if ($registration_open) : ?>
<div class="sign-footer"><?php esc_html_e('Don\'t have an account yet?', 'aksrt'); ?> <a href="#" data-sign-switch="signup"><?php esc_html_e('Register now', 'aksrt'); ?></a></div>
<?php endif; ?>
</div>
<?php if ($registration_open) : ?>
<div class="sign-panel<?php echo $tab === 'signup' ? ' is-active' : ''; ?>" data-sign-panel="signup">
<?php if ($register_error) : ?><div class="sign-error"><?php echo esc_html($register_error); ?></div><?php endif; ?>
<?php if ($register_success) : ?><div class="sign-success"><?php echo wp_kses($register_success, ['a' => ['href' => []]]); ?></div><?php endif; ?>
<form class="sign-form" id="sign-register-form" method="post" action="" novalidate>
<?php wp_nonce_field('aksrt_register', '_register_nonce'); ?>
<div class="form-field">
<label for="sign-reg-login"><?php esc_html_e('Username', 'aksrt'); ?></label>
<div class="input-wrap"><input type="text" name="user_login" id="sign-reg-login" autocomplete="username" required placeholder="<?php esc_attr_e('请输入用户名', 'aksrt'); ?>"></div>
</div>
<div class="form-field">
<label for="sign-reg-email"><?php esc_html_e('Email Address', 'aksrt'); ?></label>
<div class="input-wrap"><input type="email" name="user_email" id="sign-reg-email" autocomplete="email" required placeholder="<?php esc_attr_e('Please enter your email', 'aksrt'); ?>"></div>
</div>
<div class="form-field">
<label for="sign-reg-pass"><?php esc_html_e('登录密码', 'aksrt'); ?></label>
<div class="input-wrap">
<input type="password" name="user_pass" id="sign-reg-pass" autocomplete="new-password" required minlength="6">
<button type="button" class="toggle-pwd" data-target="sign-reg-pass"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="form-field">
<label for="sign-reg-pass2"><?php esc_html_e('确认密码', 'aksrt'); ?></label>
<div class="input-wrap">
<input type="password" name="user_pass_confirm" id="sign-reg-pass2" autocomplete="new-password" required minlength="6">
<button type="button" class="toggle-pwd" data-target="sign-reg-pass2"><i class="fas fa-eye"></i></button>
</div>
</div>
<?php
$invite_cfg = class_exists('AKSRT_Settings') ? AKSRT_Settings::get_invite_registration_config() : null;
if ($invite_cfg && ($invite_cfg['register_field'] ?? 'hidden') !== 'hidden') {
$mode = (string) $invite_cfg['register_field'];
$invit_hint = $mode === 'required'
? (string) ($invite_cfg['must_desc'] ?? '')
: (string) ($invite_cfg['open_desc'] ?? '');
?>
<div class="form-field">
<label for="sign-invite"><?php esc_html_e('邀请码', 'aksrt'); ?><?php echo $mode === 'optional' ? ' <small style="color:var(--muted-color);">(' . esc_html__('选填', 'aksrt') . ')</small>' : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></label>
<div class="input-wrap"><input type="text" name="invite_code" id="sign-invite" maxlength="32" autocomplete="off" value="<?php echo esc_attr($invite_prefill); ?>" <?php echo $mode === 'required' ? 'required' : ''; ?>></div>
<?php if ($invit_hint !== '') : ?>
<p class="sign-hint"><?php echo wp_kses_post($invit_hint); ?></p>
<?php endif; ?>
</div>
<?php } ?>
<label class="sign-terms">
<input type="checkbox" name="agree_terms" value="1" required>
<span><?php esc_html_e('I agree to the Terms of Service', 'aksrt'); ?></span>
</label>
<?php if (class_exists('AKSRT_Settings') && AKSRT_Settings::registration_requires_email_verification()) : ?>
<p class="sign-hint"><?php esc_html_e('Email verification is required after registration.', 'aksrt'); ?></p>
<?php endif; ?>
<?php if (function_exists('aksrt_render_captcha')) aksrt_render_captcha('register'); ?>
<button type="submit" class="btn-submit"><?php esc_html_e('注册', 'aksrt'); ?></button>
</form>
<div class="sign-footer"><?php esc_html_e('Already have an account?', 'aksrt'); ?> <a href="#" data-sign-switch="signin"><?php esc_html_e('Sign in now', 'aksrt'); ?></a></div>
</div>
<?php endif; ?>
</div>
</main>
<script>
(function(){
document.querySelectorAll('[data-sign-tab]').forEach(function(tab){
tab.addEventListener('click',function(){
var target=this.getAttribute('data-sign-tab');
this.parentElement.querySelectorAll('.sign-tab').forEach(function(t){t.classList.remove('is-active');});
this.classList.add('is-active');
var card=this.closest('.sign-card');
card.querySelectorAll('.sign-panel[data-sign-panel]').forEach(function(p){p.classList.remove('is-active');});
var panel=card.querySelector('[data-sign-panel="'+target+'"]');
if(panel)panel.classList.add('is-active');
});
});
document.querySelectorAll('[data-sign-switch]').forEach(function(link){
link.addEventListener('click',function(e){
e.preventDefault();
var target=this.getAttribute('data-sign-switch');
var btn=document.querySelector('[data-sign-tab="'+target+'"]');
if(btn)btn.click();
});
});
document.querySelectorAll('.toggle-pwd').forEach(function(btn){
btn.addEventListener('click',function(){
var input=document.getElementById(this.getAttribute('data-target'));
if(!input)return;
var isPw=input.type==='password';
input.type=isPw?'text':'password';
this.querySelector('i').className=isPw?'fas fa-eye-slash':'fas fa-eye';
});
});
})();
</script>
<?php if (!$interim) : ?>
<div class="sign-footer-bar">
<?php
$footer_text = $sign_ui['footer'] ?? '';
echo $footer_text ? wp_kses_post($footer_text) : '&copy; ' . date('Y') . ' ' . esc_html(get_bloginfo('name'));
?>
</div>
<?php endif; ?>
<?php wp_footer(); ?>
</body>
</html>
+148
View File
@@ -0,0 +1,148 @@
<?php
/**
* Template Name: AKSRT - Special Page
*
* 专题聚合页模板 — 用于内容专题、活动页、产品介绍页等。
* 读取 AKSRT_Settings 中的 page_display.special 配置,支持 per-page meta 覆盖。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$post_id = get_the_ID();
// 从门面 getter 读取专题页设置(validated & sanitized)
$special = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_special_page_settings()
: [];
$defaults = [
'cover_enabled' => true,
'summary_enabled' => true,
'summary_length' => 200,
'default_cover' => '',
'layout' => 'grid',
'columns' => 2,
'source_type' => 'category',
'source_ids' => '',
'subpage_display' => 'cards',
'subpage_count' => 6,
'sidebar' => true,
'pagination' => 'numeric',
'per_page' => 12,
'post_count' => false,
'orderby' => 'date',
];
$settings = array_merge($defaults, $special);
// Per-page meta override
$meta_layout = get_post_meta($post_id, '_aksrt_special_layout', true);
$meta_columns = get_post_meta($post_id, '_aksrt_special_columns', true);
$meta_source = get_post_meta($post_id, '_aksrt_special_source_type', true);
$meta_ids = get_post_meta($post_id, '_aksrt_special_source_ids', true);
if ($meta_layout) $settings['layout'] = sanitize_key($meta_layout);
if ($meta_columns) $settings['columns'] = max(1, min(4, (int) $meta_columns));
if ($meta_source) $settings['source_type'] = sanitize_key($meta_source);
if ($meta_ids !== '' && $meta_ids !== false) $settings['source_ids'] = $meta_ids;
$layout = in_array($settings['layout'], ['grid', 'list', 'masonry'], true) ? $settings['layout'] : 'grid';
$columns = max(1, min(4, (int) $settings['columns']));
$show_cover = !empty($settings['cover_enabled']);
$show_summary = !empty($settings['summary_enabled']);
$summary_len = max(50, min(500, (int) $settings['summary_length']));
$subpage_style = in_array($settings['subpage_display'], ['cards', 'list', 'timeline'], true) ? $settings['subpage_display'] : 'cards';
$per_page = max(4, min(48, (int) $settings['per_page']));
$orderby = in_array($settings['orderby'], ['date', 'modified', 'views', 'comments'], true) ? $settings['orderby'] : 'date';
// 聚合内容源
$source_type = sanitize_key($settings['source_type']);
$source_ids = array_filter(array_map('absint', explode(',', (string) $settings['source_ids'])));
$aggregated_posts = [];
if (!empty($source_ids)) {
$args = [
'posts_per_page' => $per_page,
'post_status' => 'publish',
'orderby' => ($orderby === 'modified') ? 'modified' : 'date',
'order' => 'DESC',
];
if ($source_type === 'category') {
$args['category__in'] = $source_ids;
} elseif ($source_type === 'tag') {
$args['tag__in'] = $source_ids;
}
$aggregated_query = new WP_Query($args);
$aggregated_posts = $aggregated_query->posts;
}
// 子页面列表
$children_per_page = max(1, min(20, (int) $settings['subpage_count']));
$children = get_pages([
'child_of' => $post_id,
'sort_column' => 'menu_order',
'sort_order' => 'ASC',
'parent' => $post_id,
'number' => $children_per_page,
]);
?>
<main id="main-content" class="site-main content-shell content-shell--page aksrt-special--<?php echo esc_attr($layout); ?>" tabindex="-1">
<?php if (function_exists('aksrt_breadcrumbs')) { aksrt_breadcrumbs(); } ?>
<?php if ($show_cover) :
$default_cover = $settings['default_cover'] ?? '';
$show_post_count = !empty($settings['post_count']);
include get_template_directory() . '/templates/parts/special/special-cover.php';
endif; ?>
<div class="aksrt-special-content container">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="aksrt-special-content__body">
<?php the_content(); ?>
</div>
<?php endwhile; endif; ?>
</div>
<?php if (!empty($aggregated_posts)) : ?>
<section class="aksrt-special-aggregated container">
<h2 class="aksrt-special-aggregated__title"><?php esc_html_e('相关内容', 'aksrt'); ?></h2>
<?php
// Use the special-grid part
$grid_posts = $aggregated_posts;
$show_dates = true;
include get_template_directory() . '/templates/parts/special/special-grid.php';
?>
</section>
<?php endif; ?>
<?php if (!empty($children)) : ?>
<section class="aksrt-special-children container">
<h2 class="aksrt-special-children__title"><?php esc_html_e('子页面', 'aksrt'); ?></h2>
<div class="aksrt-special-children__grid aksrt-special-children__grid--<?php echo esc_attr($subpage_style); ?>" style="--aksrt-cols:<?php echo esc_attr((string) $columns); ?>">
<?php foreach ($children as $child) :
$child_img = get_the_post_thumbnail_url($child->ID, 'medium');
?>
<a href="<?php echo esc_url(get_permalink($child->ID)); ?>" class="aksrt-special-child-card">
<?php if ($child_img) : ?>
<div class="aksrt-special-child-card__image">
<img src="<?php echo esc_url($child_img); ?>" alt=""<?php echo function_exists('aksrt_lazy_loading') ? aksrt_lazy_loading('other') : ' loading="lazy"'; ?>>
</div>
<?php endif; ?>
<div class="aksrt-special-child-card__body">
<h3 class="aksrt-special-child-card__title"><?php echo esc_html($child->post_title); ?></h3>
<?php if ($child->post_excerpt !== '') : ?>
<p class="aksrt-special-child-card__desc"><?php echo esc_html(wp_trim_words($child->post_excerpt, 30)); ?></p>
<?php endif; ?>
</div>
</a>
<?php endforeach; ?>
</div>
</section>
<?php endif; ?>
</main>
<?php
get_footer();
+292
View File
@@ -0,0 +1,292 @@
<?php
/**
* Template Name: AKSRT - Submit
*
* 前台投稿页面模板。
* 支持标题、摘要、分类、标签、正文、封面、草稿保存。
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!is_user_logged_in()) {
wp_redirect(aksrt_get_login_url(get_permalink()));
exit;
}
$user_id = get_current_user_id();
$can_submit = class_exists('AKSRT_Front_Submit') && AKSRT_Front_Submit::get_instance()->can_submit($user_id);
if (!$can_submit) {
wp_redirect(home_url('/'));
exit;
}
// Check if editing existing draft
$edit_id = isset($_GET['edit']) ? absint($_GET['edit']) : 0;
$edit_post = null;
if ($edit_id > 0) {
$edit_post = get_post($edit_id);
if (!$edit_post || (int) $edit_post->post_author !== $user_id || $edit_post->post_status !== 'draft') {
$edit_post = null;
$edit_id = 0;
}
}
get_header();
// Submit settings
$submit_settings = [];
if (class_exists('AKSRT_Settings')) {
$all = AKSRT_Settings::get_all();
$submit_settings = [
'enabled' => !empty($all['front_submit_enabled']),
'review_mode' => $all['front_submit_review_mode'] ?? 'pending',
'allow_cover' => !isset($all['front_submit_cover']) || !empty($all['front_submit_cover']),
'allow_excerpt' => !isset($all['front_submit_excerpt']) || !empty($all['front_submit_excerpt']),
'allow_category' => !isset($all['front_submit_category']) || !empty($all['front_submit_category']),
'allow_tags' => !isset($all['front_submit_tags']) || !empty($all['front_submit_tags']),
'max_images' => (int) ($all['front_submit_max_images'] ?? 5),
'allowed_cat_ids' => is_array($all['post_article_cat'] ?? null) ? array_map('intval', $all['post_article_cat']) : [],
'topics_s' => !empty($all['post_article_topics_s']),
'custom_filter_s' => !isset($all['post_article_custom_filter_s']) || !empty($all['post_article_custom_filter_s']),
];
}
// §3.7 topics: load topics taxonomy terms
$topics_terms = [];
if (!empty($submit_settings['topics_s']) && taxonomy_exists('topics')) {
$topics_terms = get_terms(['taxonomy' => 'topics', 'hide_empty' => false, 'orderby' => 'name', 'order' => 'ASC']);
if (is_wp_error($topics_terms)) $topics_terms = [];
}
$current_topics = [];
if ($edit_post && taxonomy_exists('topics')) {
$terms = wp_get_object_terms($edit_post->ID, 'topics', ['fields' => 'ids']);
if (!is_wp_error($terms)) $current_topics = $terms;
}
// §3.4 custom_filter: load dimension definitions for submit form
$custom_dimensions = [];
if (!empty($submit_settings['custom_filter_s']) && class_exists('AKSRT_Settings')) {
$filter_all = AKSRT_Settings::get_post_filter_settings();
$custom_dimensions = $filter_all['custom_filter'];
}
// §3.4 custom_filter: load current values for edit mode
$current_cf = [];
if ($edit_post && !empty($custom_dimensions)) {
foreach ($custom_dimensions as $dim) {
$current_cf[$dim['key']] = get_post_meta($edit_post->ID, '_aksrt_cf_' . $dim['key'], true);
}
}
// §3.7 post_article_cat: filter categories by allowed list
$cat_args = [
'taxonomy' => 'category',
'hide_empty' => false,
'orderby' => 'name',
'order' => 'ASC',
];
if (!empty($submit_settings['allowed_cat_ids'])) {
$cat_args['include'] = $submit_settings['allowed_cat_ids'];
}
$categories = get_categories($cat_args);
// Current values for edit mode
$current_title = $edit_post ? $edit_post->post_title : '';
$current_content = $edit_post ? $edit_post->post_content : '';
$current_excerpt = $edit_post ? $edit_post->post_excerpt : '';
$current_cats = $edit_post ? wp_get_post_categories($edit_post->ID) : [];
$current_tags = $edit_post ? implode(', ', wp_get_post_tags($edit_post->ID, ['fields' => 'names'])) : '';
$current_thumb = $edit_post ? get_the_post_thumbnail_url($edit_post->ID, 'large') : '';
?>
<main id="main-content" class="site-main content-shell content-shell--page" tabindex="-1">
<div class="aksrt-submit-page container">
<header class="aksrt-submit-page__header">
<h1 class="aksrt-submit-page__title">
<?php echo $edit_post ? esc_html__('编辑草稿', 'aksrt') : esc_html__('投稿', 'aksrt'); ?>
</h1>
<p class="aksrt-submit-page__desc">
<?php echo $edit_post
? esc_html__('继续编辑你的草稿,完成后提交审核。', 'aksrt')
: esc_html__('分享你的内容,提交后将进入审核流程。', 'aksrt'); ?>
</p>
</header>
<form class="aksrt-submit-form" id="aksrt-submit-form" data-aksrt-submit-form data-dirty="false">
<?php if ($edit_id > 0) : ?>
<input type="hidden" name="edit_id" value="<?php echo esc_attr((string) $edit_id); ?>">
<?php endif; ?>
<div class="aksrt-form-group">
<label for="submit-title"><?php esc_html_e('标题', 'aksrt'); ?> *</label>
<input type="text" id="submit-title" name="title" class="aksrt-form-input" required maxlength="200" placeholder="<?php esc_attr_e('请输入文章标题', 'aksrt'); ?>" value="<?php echo esc_attr($current_title); ?>">
</div>
<?php if (!empty($submit_settings['allow_excerpt'])) : ?>
<div class="aksrt-form-group">
<label for="submit-excerpt"><?php esc_html_e('摘要', 'aksrt'); ?></label>
<textarea id="submit-excerpt" name="excerpt" class="aksrt-form-input" rows="3" maxlength="300" placeholder="<?php esc_attr_e('可选:文章摘要', 'aksrt'); ?>"><?php echo esc_textarea($current_excerpt); ?></textarea>
</div>
<?php endif; ?>
<div class="aksrt-submit-form__row">
<?php if (!empty($submit_settings['allow_category'])) : ?>
<div class="aksrt-form-group aksrt-submit-form__col">
<label for="submit-category"><?php esc_html_e('分类', 'aksrt'); ?></label>
<select id="submit-category" name="category" class="aksrt-form-input">
<option value=""><?php esc_html_e('选择分类', 'aksrt'); ?></option>
<?php foreach ($categories as $cat) : ?>
<option value="<?php echo esc_attr((string) $cat->term_id); ?>" <?php selected(in_array($cat->term_id, $current_cats)); ?>><?php echo esc_html($cat->name); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
<?php if (!empty($submit_settings['allow_tags'])) : ?>
<div class="aksrt-form-group aksrt-submit-form__col">
<label for="submit-tags"><?php esc_html_e('标签', 'aksrt'); ?></label>
<input type="text" id="submit-tags" name="tags" class="aksrt-form-input" placeholder="<?php esc_attr_e('多个标签用逗号分隔', 'aksrt'); ?>" value="<?php echo esc_attr($current_tags); ?>">
</div>
<?php endif; ?>
</div>
<?php if (!empty($submit_settings['topics_s']) && !empty($topics_terms)) : ?>
<div class="aksrt-form-group">
<label for="submit-topics"><?php esc_html_e('专题', 'aksrt'); ?></label>
<select id="submit-topics" name="topics[]" class="aksrt-form-input" multiple>
<?php foreach ($topics_terms as $topic) : ?>
<option value="<?php echo esc_attr((string) $topic->term_id); ?>" <?php selected(in_array($topic->term_id, $current_topics)); ?>><?php echo esc_html($topic->name); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
<?php if (!empty($submit_settings['custom_filter_s']) && !empty($custom_dimensions)) : ?>
<?php foreach ($custom_dimensions as $dim) : ?>
<div class="aksrt-form-group">
<label for="submit-cf-<?php echo esc_attr($dim['key']); ?>"><?php echo esc_html($dim['name']); ?></label>
<select id="submit-cf-<?php echo esc_attr($dim['key']); ?>" name="cf_<?php echo esc_attr($dim['key']); ?>" class="aksrt-form-input">
<option value=""><?php printf(esc_html__('选择%s', 'aksrt'), esc_html($dim['name'])); ?></option>
<?php foreach ($dim['vals'] as $val) : ?>
<option value="<?php echo esc_attr($val['key']); ?>" <?php selected(!empty($current_cf[$dim['key']]) && $current_cf[$dim['key']] === $val['key']); ?>><?php echo esc_html($val['name']); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endforeach; ?>
<?php endif; ?>
<div class="aksrt-form-group">
<label for="submit-content"><?php esc_html_e('内容', 'aksrt'); ?> *</label>
<div class="aksrt-submit-form__editor-toolbar">
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="bold" title="<?php esc_attr_e('加粗', 'aksrt'); ?>"><i class="fas fa-bold"></i></button>
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="italic" title="<?php esc_attr_e('斜体', 'aksrt'); ?>"><i class="fas fa-italic"></i></button>
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="code" title="<?php esc_attr_e('代码', 'aksrt'); ?>"><i class="fas fa-code"></i></button>
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="link" title="<?php esc_attr_e('链接', 'aksrt'); ?>"><i class="fas fa-link"></i></button>
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="image" title="<?php esc_attr_e('图片', 'aksrt'); ?>"><i class="fas fa-image"></i></button>
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="quote" title="<?php esc_attr_e('引用', 'aksrt'); ?>"><i class="fas fa-quote-left"></i></button>
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="heading" title="<?php esc_attr_e('标题', 'aksrt'); ?>"><i class="fas fa-heading"></i></button>
<button type="button" class="aksrt-submit-form__toolbar-btn" data-action="list" title="<?php esc_attr_e('列表', 'aksrt'); ?>"><i class="fas fa-list-ul"></i></button>
</div>
<textarea id="submit-content" name="content" class="aksrt-form-input aksrt-submit-form__textarea" rows="16" required placeholder="<?php esc_attr_e('请输入文章内容(支持 HTML)', 'aksrt'); ?>"><?php echo esc_textarea($current_content); ?></textarea>
<div class="aksrt-submit-form__word-count" id="submit-word-count"></div>
</div>
<?php if (!empty($submit_settings['allow_cover'])) : ?>
<div class="aksrt-form-group">
<label for="submit-thumbnail"><?php esc_html_e('封面图', 'aksrt'); ?></label>
<div class="aksrt-submit-form__cover-input">
<input type="url" id="submit-thumbnail" name="thumbnail" class="aksrt-form-input" placeholder="<?php esc_attr_e('输入封面图地址', 'aksrt'); ?>" value="<?php echo esc_url($current_thumb); ?>">
<button type="button" class="aksrt-submit-form__cover-btn" id="aksrt-pick-cover">
<i class="fas fa-image"></i>
<?php esc_html_e('选择图片', 'aksrt'); ?>
</button>
</div>
<div class="aksrt-submit-form__cover-preview" id="cover-preview" <?php echo $current_thumb ? '' : 'style="display:none"'; ?>>
<img id="cover-preview-img" src="<?php echo esc_url($current_thumb); ?>" alt="">
<button type="button" class="aksrt-submit-form__cover-remove" id="cover-remove" title="<?php esc_attr_e('移除封面', 'aksrt'); ?>">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<?php endif; ?>
<div class="aksrt-submit-form__actions">
<button type="submit" class="aksrt-auth-submit" id="aksrt-submit-btn">
<i class="fas fa-paper-plane"></i>
<?php echo $edit_post ? esc_html__('更新投稿', 'aksrt') : esc_html__('提交投稿', 'aksrt'); ?>
</button>
<button type="button" class="btn-outline" id="aksrt-save-draft">
<i class="fas fa-save"></i>
<?php esc_html_e('保存草稿', 'aksrt'); ?>
</button>
</div>
<input type="hidden" name="_nonce" value="<?php echo esc_attr(wp_create_nonce('aksrt_submit')); ?>">
<input type="hidden" name="status" id="submit-status" value="pending">
</form>
<!-- Draft list -->
<?php
$user_drafts = get_posts([
'post_type' => 'post',
'post_status' => 'draft',
'author' => $user_id,
'numberposts' => 10,
'orderby' => 'modified',
'order' => 'DESC',
]);
if (!empty($user_drafts)) :
?>
<div class="aksrt-submit-drafts">
<h3 class="aksrt-submit-drafts__title">
<i class="fas fa-file-alt"></i>
<?php esc_html_e('我的草稿', 'aksrt'); ?>
</h3>
<div class="aksrt-submit-drafts__list">
<?php foreach ($user_drafts as $draft) : ?>
<div class="aksrt-submit-drafts__item">
<a href="<?php echo esc_url(add_query_arg('edit', $draft->ID, get_permalink())); ?>" class="aksrt-submit-drafts__link">
<span class="aksrt-submit-drafts__name"><?php echo esc_html($draft->post_title ?: __('无标题', 'aksrt')); ?></span>
<time class="aksrt-submit-drafts__date"><?php echo esc_html(get_the_date('Y-m-d H:i', $draft->ID)); ?></time>
</a>
<button type="button" class="aksrt-submit-drafts__delete" data-draft-id="<?php echo esc_attr((string) $draft->ID); ?>" title="<?php esc_attr_e('删除草稿', 'aksrt'); ?>">
<i class="fas fa-trash"></i>
</button>
</div>
<?php endforeach; ?>
</div>
</div>
<?php endif; ?>
</div>
</main>
<?php
// Enqueue the front-submit script
$front_submit_path = get_template_directory() . '/assets/js/front-submit.js';
if (file_exists($front_submit_path)) {
wp_enqueue_script(
'aksrt-front-submit',
get_template_directory_uri() . '/assets/js/front-submit.js',
['aksrt-script'],
(string) filemtime($front_submit_path),
true
);
wp_localize_script('aksrt-front-submit', 'aksrtSubmitData', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('aksrt_submit_nonce'),
'i18n' => [
'confirmLeave' => __('你有未保存的更改,确定要离开吗?', 'aksrt'),
'saving' => __('保存中...', 'aksrt'),
'saved' => __('草稿已保存', 'aksrt'),
'submitting' => __('提交中...', 'aksrt'),
'submitted' => __('投稿已提交', 'aksrt'),
'error' => __('操作失败,请重试', 'aksrt'),
'confirmDelete' => __('确定要删除这个草稿吗?', 'aksrt'),
],
]);
}
get_footer();
+556
View File
@@ -0,0 +1,556 @@
<?php
/**
* Public user homepage template.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
get_header();
$target_user_nicename = get_query_var('user_nicename');
$user = $target_user_nicename ? get_user_by('slug', $target_user_nicename) : null;
if (!$user) {
wp_safe_redirect(home_url('/'));
exit;
}
$user_id = (int) $user->ID;
// 数据聚合:复用共享 helper
$dashboard = function_exists('aksrt_get_user_dashboard_view')
? aksrt_get_user_dashboard_view($user_id, ['viewer_id' => get_current_user_id()])
: [];
$is_own_profile = !empty($dashboard['is_own_profile']);
$user_home_settings = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_user_home_settings()
: [
'tabs' => ['posts', 'comments', 'favorites'],
'sidebar' => true,
'cover' => true,
'follow' => true,
'posts_per_page' => 10,
];
$post_count = (int) ($dashboard['post_count'] ?? 0);
$comment_count = (int) ($dashboard['comment_count'] ?? 0);
$favorite_post_ids = $dashboard['favorite_post_ids'] ?? [];
$favorite_count = (int) ($dashboard['favorite_count'] ?? 0);
$user_contacts = $dashboard['user_contacts'] ?? [];
$user_center_settings = class_exists('AKSRT_Settings')
? AKSRT_Settings::get_user_center_settings()
: ['social_links' => true];
$per_page = (int) $user_home_settings['posts_per_page'];
$credits_enabled = !empty($dashboard['credits_enabled']);
$credit_balance = $dashboard['credit_balance'] ?? 0.0;
$currency_name = $dashboard['currency_name'] ?? __('积分', 'aksrt');
$user_home_manager = class_exists('AKSRT_User_Home') ? AKSRT_User_Home::get_instance() : null;
$visible_tabs = $user_home_manager ? $user_home_manager->get_visible_tabs($is_own_profile) : [];
$profile_signals = $dashboard['profile_signals'] ?? [];
$profile_notice = $dashboard['profile_notice'] ?? null;
$show_report_button = !empty($dashboard['show_report']);
$enabled_tabs = array_keys($visible_tabs);
if (empty($enabled_tabs)) {
$enabled_tabs = ['posts', 'comments', 'favorites'];
}
// Apply admin-configured display order
$_uh_order = $user_home_settings['tabs_order'] ?? [];
$_uh_ordered = [];
foreach ($_uh_order as $_t) {
if (in_array($_t, $enabled_tabs, true)) {
$_uh_ordered[] = $_t;
}
}
foreach ($enabled_tabs as $_t) {
if (!in_array($_t, $_uh_ordered, true)) {
$_uh_ordered[] = $_t;
}
}
$enabled_tabs = $_uh_ordered;
// Device visibility: build PC/mobile tab arrays
$_uh_pc_hide = $user_home_settings['tabs_pc_hide'] ?? [];
$_uh_mobile_hide = $user_home_settings['tabs_mobile_hide'] ?? [];
$enabled_tabs_pc = array_values(array_diff($enabled_tabs, $_uh_pc_hide));
$enabled_tabs_mobile = array_values(array_diff($enabled_tabs, $_uh_mobile_hide));
$_uh_is_mobile = function_exists('wp_is_mobile') && wp_is_mobile();
$display_tabs = $_uh_is_mobile ? $enabled_tabs_mobile : $enabled_tabs_pc;
$_uh_default_tab = !empty($display_tabs) ? $display_tabs[0] : $enabled_tabs[0];
$forum_instance = class_exists('AKSRT_Forum') ? AKSRT_Forum::get_instance() : null;
$forum_stats = $forum_instance ? $forum_instance->get_user_forum_stats($user_id) : [];
$forum_topic_count = (int) ($forum_stats['topic_count'] ?? 0);
$forum_followed_count = (int) ($forum_stats['followed_plate_count'] ?? 0);
$tab_counts = [
'posts' => $post_count,
'comments' => $comment_count,
'favorites' => $favorite_count,
'credits' => $credits_enabled && $is_own_profile ? (int) round($credit_balance) : 0,
'product' => 0,
'plate' => 0,
'forum' => $forum_topic_count,
'follow' => $forum_followed_count,
];
$tab_labels = [
'posts' => __('文章', 'aksrt'),
'comments' => __('评论', 'aksrt'),
'favorites' => __('收藏', 'aksrt'),
'credits' => sprintf(__('我的%s', 'aksrt'), $currency_name),
'product' => __('商品', 'aksrt'),
'plate' => __('圈子', 'aksrt'),
'forum' => __('论坛', 'aksrt'),
'follow' => __('关注', 'aksrt'),
];
foreach ($visible_tabs as $tab_key => $tab_config) {
if (!empty($tab_config['label'])) {
$tab_labels[$tab_key] = (string) $tab_config['label'];
}
}
$active_tab = isset($_GET['tab']) ? sanitize_key(wp_unslash($_GET['tab'])) : $_uh_default_tab;
if (!in_array($active_tab, $enabled_tabs, true)) {
$active_tab = $_uh_default_tab;
}
$posts_page = max(1, isset($_GET['posts_page']) ? (int) $_GET['posts_page'] : 1);
$comments_page = max(1, isset($_GET['comments_page']) ? (int) $_GET['comments_page'] : 1);
$favorites_page = max(1, isset($_GET['favorites_page']) ? (int) $_GET['favorites_page'] : 1);
require_once AKSRT_DIR . '/templates/parts/user-shared-helpers.php';
$svg_empty_post = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M9 13h6M9 17h6M9 9h1"/></svg>';
$svg_empty_comment = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>';
$svg_empty_favorite = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>';
$home_url = function_exists('aksrt_get_user_home_url') ? aksrt_get_user_home_url($user) : home_url('/');
?>
<main id="main-content" class="site-main content-shell" tabindex="-1">
<div class="content-layout<?php echo !empty($user_home_settings['sidebar']) ? '' : ' content-layout--no-sidebar'; ?> aksrt-user-home__layout">
<div class="content-layout__primary">
<?php
// 作者 Hero 区:共享 partial
set_query_var('user', $user);
set_query_var('dashboard', $dashboard);
set_query_var('user_home_settings', $user_home_settings);
set_query_var('is_author_page', false);
get_template_part('templates/parts/user/author-hero');
?>
<div class="dashboard dashboard--public" data-default-tab="<?php echo esc_attr($_uh_default_tab); ?>">
<div class="dashboard-tabs" role="tablist">
<?php foreach ($enabled_tabs as $tab_key) :
$_tab_class = $tab_key === $active_tab ? 'is-active' : '';
$_pc_hidden = in_array($tab_key, $_uh_pc_hide, true);
$_mobile_hidden = in_array($tab_key, $_uh_mobile_hide, true);
if ($_pc_hidden) $_tab_class .= ' tab-hide-pc';
if ($_mobile_hidden) $_tab_class .= ' tab-hide-mobile';
?>
<button type="button" class="<?php echo esc_attr(trim($_tab_class)); ?>" data-tab="<?php echo esc_attr($tab_key); ?>" role="tab">
<?php echo esc_html($tab_labels[$tab_key] ?? ucfirst($tab_key)); ?>
<span class="dashboard-tabs__count"><?php echo esc_html((string) ($tab_counts[$tab_key] ?? 0)); ?></span>
</button>
<?php endforeach; ?>
</div>
<?php if (in_array('posts', $enabled_tabs, true)) : ?>
<div id="panel-posts" class="dashboard-panel<?php echo $active_tab === 'posts' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'posts' ? ' hidden' : ''; ?>>
<?php
$author_posts = new WP_Query([
'author' => $user_id,
'posts_per_page' => $per_page,
'post_status' => 'publish',
'paged' => $posts_page,
'no_found_rows' => false,
'update_post_meta_cache' => false,
]);
if ($author_posts->have_posts()) :
?>
<div class="profile-list">
<?php while ($author_posts->have_posts()) : $author_posts->the_post(); ?>
<?php
set_query_var('aksrt_profile_item_action', [
'type' => 'view',
'url' => get_permalink(),
'label' => __('阅读', 'aksrt'),
]);
set_query_var('aksrt_profile_item_status', '');
get_template_part('templates/parts/content', 'profile-list-item');
?>
<?php endwhile; ?>
</div>
<?php
aksrt_render_profile_pagination((int) $author_posts->max_num_pages, $posts_page, 'posts_page');
wp_reset_postdata();
set_query_var('aksrt_profile_item_action', []);
else :
aksrt_render_profile_empty($svg_empty_post, __('TA 还没有发布文章', 'aksrt'));
endif;
?>
</div>
<?php endif; ?>
<?php if (in_array('comments', $enabled_tabs, true)) : ?>
<div id="panel-comments" class="dashboard-panel<?php echo $active_tab === 'comments' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'comments' ? ' hidden' : ''; ?>>
<?php
$user_comments = get_comments([
'user_id' => $user_id,
'status' => 'approve',
'number' => $per_page,
'offset' => ($comments_page - 1) * $per_page,
'type' => 'comment',
'update_comment_meta_cache' => false,
]);
if ($user_comments) :
?>
<div class="profile-comment-list">
<?php foreach ($user_comments as $c) : ?>
<?php
set_query_var('aksrt_profile_comment', $c);
get_template_part('templates/parts/content', 'profile-comment-item');
?>
<?php endforeach; ?>
<?php set_query_var('aksrt_profile_comment', null); ?>
</div>
<?php
$cm_total_pages = (int) ceil($comment_count / $per_page);
aksrt_render_profile_pagination($cm_total_pages, $comments_page, 'comments_page');
else :
aksrt_render_profile_empty($svg_empty_comment, __('TA 还没有发表评论', 'aksrt'));
endif;
?>
</div>
<?php endif; ?>
<?php if (in_array('favorites', $enabled_tabs, true)) : ?>
<div id="panel-favorites" class="dashboard-panel<?php echo $active_tab === 'favorites' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'favorites' ? ' hidden' : ''; ?>>
<?php if (!empty($favorite_post_ids)) : ?>
<?php
$favorites_query = new WP_Query([
'post_type' => 'post',
'post_status' => 'publish',
'post__in' => $favorite_post_ids,
'orderby' => 'post__in',
'posts_per_page' => $per_page,
'paged' => $favorites_page,
'ignore_sticky_posts' => true,
'no_found_rows' => false,
'update_post_meta_cache' => false,
]);
if ($favorites_query->have_posts()) :
?>
<div class="profile-list">
<?php while ($favorites_query->have_posts()) : $favorites_query->the_post(); ?>
<?php
set_query_var('aksrt_profile_item_action', [
'type' => 'view',
'url' => get_permalink(),
'label' => __('阅读', 'aksrt'),
]);
set_query_var('aksrt_profile_item_status', '');
get_template_part('templates/parts/content', 'profile-list-item');
?>
<?php endwhile; ?>
</div>
<?php
aksrt_render_profile_pagination((int) $favorites_query->max_num_pages, $favorites_page, 'favorites_page');
wp_reset_postdata();
set_query_var('aksrt_profile_item_action', []);
else :
aksrt_render_profile_empty($svg_empty_favorite, __('TA 还没有收藏文章', 'aksrt'));
endif;
?>
<?php else : ?>
<?php aksrt_render_profile_empty($svg_empty_favorite, __('TA 还没有收藏文章', 'aksrt')); ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (in_array('credits', $enabled_tabs, true) && $credits_enabled && $is_own_profile) : ?>
<div id="panel-credits" class="dashboard-panel<?php echo $active_tab === 'credits' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'credits' ? ' hidden' : ''; ?>>
<div class="user-home-balance-card">
<p class="user-home-balance-card__label"><?php echo esc_html(sprintf(__('当前%s余额', 'aksrt'), $currency_name)); ?></p>
<div class="user-home-balance-card__value"><?php echo esc_html(aksrt_format_credits($credit_balance)); ?></div>
<p class="user-home-balance-card__hint"><?php esc_html_e('完整账单和赚取/消费记录请在个人中心查看。', 'aksrt'); ?></p>
<a href="<?php echo esc_url(aksrt_get_user_center_url('credits')); ?>" class="btn-outline btn-sm"><?php esc_html_e('进入个人中心', 'aksrt'); ?></a>
</div>
</div>
<?php endif; ?>
<?php
// Placeholder panels for extended tabs (product, plate)
$_uh_extended_tabs = ['product', 'plate'];
$_uh_placeholder_msgs = [
'product' => __('暂无商品内容', 'aksrt'),
'plate' => __('暂无圈子内容', 'aksrt'),
];
foreach ($_uh_extended_tabs as $_uh_ext) :
if (!in_array($_uh_ext, $enabled_tabs, true)) continue;
?>
<div id="panel-<?php echo esc_attr($_uh_ext); ?>" class="dashboard-panel<?php echo $active_tab === $_uh_ext ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== $_uh_ext ? ' hidden' : ''; ?>>
<?php aksrt_render_profile_empty($svg_empty_post, $_uh_placeholder_msgs[$_uh_ext]); ?>
</div>
<?php endforeach; ?>
<?php if (in_array('forum', $enabled_tabs, true)) : ?>
<div id="panel-forum" class="dashboard-panel<?php echo $active_tab === 'forum' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'forum' ? ' hidden' : ''; ?>>
<?php
$forum_page = max(1, isset($_GET['forum_page']) ? (int) $_GET['forum_page'] : 1);
$forum_sub = isset($_GET['forum_sub']) ? sanitize_key(wp_unslash($_GET['forum_sub'])) : 'topics';
$forum_sub = in_array($forum_sub, ['topics', 'favorites', 'plates'], true) ? $forum_sub : 'topics';
?>
<div class="uh-forum__subtabs">
<a class="uh-forum__subtab<?php echo $forum_sub === 'topics' ? ' is-active' : ''; ?>"
href="<?php echo esc_url(add_query_arg(['tab' => 'forum', 'forum_sub' => 'topics', 'forum_page' => 1], $home_url)); ?>">
<i class="fas fa-file-alt"></i> <?php esc_html_e('帖子', 'aksrt'); ?>
<span class="uh-forum__subtab-count"><?php echo esc_html((string) $forum_topic_count); ?></span>
</a>
<a class="uh-forum__subtab<?php echo $forum_sub === 'favorites' ? ' is-active' : ''; ?>"
href="<?php echo esc_url(add_query_arg(['tab' => 'forum', 'forum_sub' => 'favorites', 'forum_page' => 1], $home_url)); ?>">
<i class="fas fa-star"></i> <?php esc_html_e('收藏帖子', 'aksrt'); ?>
<span class="uh-forum__subtab-count"><?php echo esc_html((string) ($forum_stats['favorite_count'] ?? 0)); ?></span>
</a>
<a class="uh-forum__subtab<?php echo $forum_sub === 'plates' ? ' is-active' : ''; ?>"
href="<?php echo esc_url(add_query_arg(['tab' => 'forum', 'forum_sub' => 'plates', 'forum_page' => 1], $home_url)); ?>">
<i class="fas fa-th-large"></i> <?php esc_html_e('版块', 'aksrt'); ?>
<span class="uh-forum__subtab-count"><?php echo esc_html((string) ($forum_stats['managed_plate_count'] ?? 0)); ?></span>
</a>
</div>
<?php if ($forum_sub === 'topics' && $forum_instance) :
$forum_topics = $forum_instance->get_user_forum_topics($user_id, ['page' => $forum_page, 'limit' => $per_page]);
if (!empty($forum_topics['items'])) : ?>
<div class="uh-forum__list">
<?php foreach ($forum_topics['items'] as $ft) : ?>
<div class="uh-forum__item">
<div class="uh-forum__item-body">
<a class="uh-forum__item-title" href="<?php echo esc_url(get_permalink((int) ($ft['id'] ?? 0))); ?>">
<?php echo esc_html((string) ($ft['title'] ?? '')); ?>
</a>
<div class="uh-forum__item-meta">
<span><i class="far fa-eye"></i> <?php echo esc_html((string) ($ft['views'] ?? 0)); ?></span>
<span><i class="far fa-comment"></i> <?php echo esc_html((string) ($ft['comment_count'] ?? 0)); ?></span>
<time><?php echo esc_html((string) ($ft['date'] ?? '')); ?></time>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php if ($forum_topics['max_pages'] > 1) : ?>
<div class="uh-forum__pagination">
<?php
echo paginate_links([
'base' => add_query_arg('forum_page', '%#%', $home_url),
'format' => '',
'current' => $forum_page,
'total' => $forum_topics['max_pages'],
'add_args' => ['tab' => 'forum', 'forum_sub' => 'topics'],
]);
?>
</div>
<?php endif; ?>
<?php else : ?>
<?php aksrt_render_profile_empty($svg_empty_post, __('暂无论坛帖子', 'aksrt')); ?>
<?php endif; ?>
<?php elseif ($forum_sub === 'favorites' && $forum_instance) :
$fav_topics = $forum_instance->get_user_favorite_topics($user_id, $forum_page, $per_page);
if (!empty($fav_topics['items'])) : ?>
<div class="uh-forum__list">
<?php foreach ($fav_topics['items'] as $ft) : ?>
<div class="uh-forum__item">
<div class="uh-forum__item-body">
<a class="uh-forum__item-title" href="<?php echo esc_url(get_permalink((int) ($ft['id'] ?? 0))); ?>">
<?php echo esc_html((string) ($ft['title'] ?? '')); ?>
</a>
<div class="uh-forum__item-meta">
<span><i class="far fa-eye"></i> <?php echo esc_html((string) ($ft['views'] ?? 0)); ?></span>
<span><i class="far fa-comment"></i> <?php echo esc_html((string) ($ft['comment_count'] ?? 0)); ?></span>
<time><?php echo esc_html((string) ($ft['date'] ?? '')); ?></time>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php if ($fav_topics['max_pages'] > 1) : ?>
<div class="uh-forum__pagination">
<?php
echo paginate_links([
'base' => add_query_arg('forum_page', '%#%', $home_url),
'format' => '',
'current' => $forum_page,
'total' => $fav_topics['max_pages'],
'add_args' => ['tab' => 'forum', 'forum_sub' => 'favorites'],
]);
?>
</div>
<?php endif; ?>
<?php else : ?>
<?php aksrt_render_profile_empty($svg_empty_favorite, __('暂无收藏帖子', 'aksrt')); ?>
<?php endif; ?>
<?php elseif ($forum_sub === 'plates' && $forum_instance) :
$managed_plates = $forum_instance->get_user_managed_plates($user_id);
$followed_plates = $forum_instance->get_user_followed_plates($user_id);
$has_plates = !empty($managed_plates['owned']) || !empty($managed_plates['moderating']) || !empty($followed_plates);
if ($has_plates) : ?>
<?php if (!empty($managed_plates['owned'])) : ?>
<h3 class="uh-forum__section-title"><i class="fas fa-crown"></i> <?php esc_html_e('创建的版块', 'aksrt'); ?></h3>
<div class="uh-forum__plate-grid">
<?php foreach ($managed_plates['owned'] as $plate) : ?>
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
<div class="uh-forum__plate-stats">
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
<span><?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($plate['follow_count'] ?? 0)); ?></span>
</div>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (!empty($managed_plates['moderating'])) : ?>
<h3 class="uh-forum__section-title"><i class="fas fa-shield-alt"></i> <?php esc_html_e('管理的版块', 'aksrt'); ?></h3>
<div class="uh-forum__plate-grid">
<?php foreach ($managed_plates['moderating'] as $plate) : ?>
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
<div class="uh-forum__plate-stats">
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
</div>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (!empty($followed_plates)) : ?>
<h3 class="uh-forum__section-title"><i class="fas fa-heart"></i> <?php esc_html_e('关注的版块', 'aksrt'); ?></h3>
<div class="uh-forum__plate-grid">
<?php foreach ($followed_plates as $plate) : ?>
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
<div class="uh-forum__plate-stats">
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
<span><?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($plate['follow_count'] ?? 0)); ?></span>
</div>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php else : ?>
<?php aksrt_render_profile_empty($svg_empty_post, __('暂无版块数据', 'aksrt')); ?>
<?php endif; ?>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if (in_array('follow', $enabled_tabs, true)) : ?>
<div id="panel-follow" class="dashboard-panel<?php echo $active_tab === 'follow' ? ' is-active' : ''; ?>" role="tabpanel"<?php echo $active_tab !== 'follow' ? ' hidden' : ''; ?>>
<?php
if ($forum_instance) :
$followed = $forum_instance->get_user_followed_plates($user_id);
if (!empty($followed)) : ?>
<div class="uh-forum__plate-grid">
<?php foreach ($followed as $plate) : ?>
<a class="uh-forum__plate-card" href="<?php echo esc_url(get_permalink((int) ($plate['id'] ?? 0))); ?>">
<div class="uh-forum__plate-name"><?php echo esc_html((string) ($plate['name'] ?? '')); ?></div>
<div class="uh-forum__plate-stats">
<span><?php printf(esc_html__('%d 帖子', 'aksrt'), (int) ($plate['topic_count'] ?? 0)); ?></span>
<span><?php printf(esc_html__('%d 关注', 'aksrt'), (int) ($plate['follow_count'] ?? 0)); ?></span>
</div>
</a>
<?php endforeach; ?>
</div>
<?php else : ?>
<?php aksrt_render_profile_empty($svg_empty_post, __('暂未关注任何版块', 'aksrt')); ?>
<?php endif;
else :
aksrt_render_profile_empty($svg_empty_post, __('暂无关注内容', 'aksrt'));
endif;
?>
</div>
<?php endif; ?>
</div>
</div>
<?php if (!empty($user_home_settings['sidebar'])) : ?>
<div class="sidebar uc-sidebar aksrt-user-home__aside" role="complementary" aria-label="<?php esc_attr_e('用户主页侧栏', 'aksrt'); ?>">
<div class="uc-sidebar__section">
<div class="uc-sidebar__title"><?php esc_html_e('主页概览', 'aksrt'); ?></div>
<div class="uc-stats">
<?php foreach ($enabled_tabs as $tab_key) : ?>
<a class="uc-stats__item" href="<?php echo esc_url(add_query_arg('tab', $tab_key, $home_url)); ?>">
<span class="uc-stats__value"><?php echo esc_html((string) ($tab_counts[$tab_key] ?? 0)); ?></span>
<span class="uc-stats__label"><?php echo esc_html($tab_labels[$tab_key] ?? ucfirst($tab_key)); ?></span>
</a>
<?php endforeach; ?>
</div>
</div>
<?php if (!empty($user_contacts) && !empty($user_center_settings['social_links'])) : ?>
<div class="uc-sidebar__section">
<div class="uc-sidebar__title"><?php esc_html_e('公开联系', 'aksrt'); ?></div>
<div class="aksrt-user-home__contacts">
<?php if (function_exists('aksrt_render_social_links')) : ?>
<?php aksrt_render_social_links($user_contacts); ?>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<div class="uc-sidebar__section">
<div class="uc-sidebar__title"><?php esc_html_e('快捷入口', 'aksrt'); ?></div>
<div class="uc-sidebar__buttons">
<a href="<?php echo esc_url($home_url); ?>" class="uc-sidebar__btn">
<i class="fas fa-user" aria-hidden="true"></i>
<span><?php esc_html_e('主页首页', 'aksrt'); ?></span>
</a>
<?php if ($is_own_profile) : ?>
<a href="<?php echo esc_url(aksrt_get_user_center_url()); ?>" class="uc-sidebar__btn">
<i class="fas fa-cog" aria-hidden="true"></i>
<span><?php esc_html_e('个人中心', 'aksrt'); ?></span>
</a>
<?php endif; ?>
</div>
</div>
<?php if ($is_own_profile) : ?>
<?php
$orders_url = function_exists('aksrt_get_orders_page_url') ? aksrt_get_orders_page_url() : '';
$show_vip = class_exists('AKSRT_Settings') && !empty(AKSRT_Settings::get_all()['payment_vip_enabled']);
$credits_enabled = class_exists('AKSRT_Settings') && AKSRT_Settings::credits_enabled();
?>
<?php if ($orders_url || $show_vip || $credits_enabled) : ?>
<div class="uc-sidebar__section">
<div class="uc-sidebar__title"><?php esc_html_e('交易服务', 'aksrt'); ?></div>
<div class="uc-sidebar__buttons">
<?php if ($orders_url) : ?>
<a href="<?php echo esc_url($orders_url); ?>" class="uc-sidebar__btn">
<i class="fas fa-receipt" aria-hidden="true"></i>
<span><?php esc_html_e('我的订单', 'aksrt'); ?></span>
</a>
<?php endif; ?>
<?php if ($show_vip) : ?>
<a href="<?php echo esc_url(aksrt_get_user_center_url()); ?>" class="uc-sidebar__btn">
<i class="fas fa-crown" aria-hidden="true"></i>
<span><?php esc_html_e('VIP 会员', 'aksrt'); ?></span>
</a>
<?php endif; ?>
<?php if ($credits_enabled) : ?>
<a href="<?php echo esc_url(aksrt_get_user_center_url()); ?>" class="uc-sidebar__btn">
<i class="fas fa-coins" aria-hidden="true"></i>
<span><?php echo esc_html(AKSRT_Settings::get_currency_name()); ?></span>
</a>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</aside>
<?php endif; ?>
</div>
</main>
<?php get_footer(); ?>
+149
View File
@@ -0,0 +1,149 @@
<?php
/**
* Template Name: AKSRT - Verify Email
* Template Post Type: page
*
* Theme auth route template: /verify-email/
*
* @package AKSRT
*/
$verify_error = '';
$verify_success = '';
$redirect_url = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['verify_email_resend'])) {
$result = AKSRT_Auth_Service::resend_email_verification($_POST);
if (!empty($result['success'])) {
$verify_success = $result['message'] ?? __('验证邮件已重新发送,请注意查收。', 'aksrt');
} else {
$verify_error = $result['error'] ?? __('验证邮件发送失败,请稍后重试。', 'aksrt');
}
} elseif (isset($_POST['verify_email_submit'])) {
$result = AKSRT_Auth_Service::verify_email_code_submission($_POST);
if (!empty($result['success'])) {
$verify_success = $result['message'] ?? __('邮箱验证成功,即将进入你的账号。', 'aksrt');
$redirect_url = $result['redirect'] ?? '';
} else {
$verify_error = $result['error'] ?? __('邮箱验证码错误或已过期。', 'aksrt');
}
}
}
$verify_context = AKSRT_Auth_Service::get_email_verification_context($_GET);
if ($verify_error === '' && !empty($verify_context['error'])) {
$verify_error = $verify_context['error'];
}
if ($verify_success === '' && !empty($verify_context['message'])) {
$verify_success = $verify_context['message'];
}
if ($redirect_url === '' && !empty($verify_context['redirect'])) {
$redirect_url = $verify_context['redirect'];
}
$verify_user = $verify_context['user'] ?? null;
$verify_uid = (int) ($verify_context['uid'] ?? 0);
$verify_email = (string) ($verify_context['email'] ?? '');
$verify_mode = (string) ($verify_context['mode'] ?? 'invalid');
$verify_method= (string) ($verify_context['method'] ?? '');
$verify_vk = (string) ($verify_context['access_key'] ?? '');
get_header();
?>
<main id="main-content" class="site-main" tabindex="-1">
<div class="auth-shell">
<div class="auth-card">
<div class="auth-card__logo" aria-hidden="true">AK</div>
<h1 class="auth-card__title"><?php bloginfo('name'); ?></h1>
<?php if ($verify_mode === 'completed' || $verify_mode === 'verified') : ?>
<p class="auth-card__subtitle"><?php esc_html_e('邮箱验证成功', 'aksrt'); ?></p>
<?php elseif ($verify_mode === 'code') : ?>
<p class="auth-card__subtitle"><?php esc_html_e('请输入邮箱验证码完成验证', 'aksrt'); ?></p>
<?php elseif ($verify_mode === 'pending') : ?>
<p class="auth-card__subtitle"><?php esc_html_e('验证邮件已经发出,请点击邮箱中的链接完成验证', 'aksrt'); ?></p>
<?php else : ?>
<p class="auth-card__subtitle"><?php esc_html_e('邮箱验证状态异常,请重新检查链接或重新发送验证邮件', 'aksrt'); ?></p>
<?php endif; ?>
<?php if ($verify_error !== '') : ?>
<div class="alert alert--error" role="alert">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/></svg>
<span><?php echo esc_html($verify_error); ?></span>
</div>
<?php endif; ?>
<?php if ($verify_success !== '') : ?>
<div class="alert alert--success" role="alert">
<span><?php echo esc_html($verify_success); ?></span>
</div>
<?php endif; ?>
<?php if (($verify_mode === 'completed' || $verify_mode === 'verified') && $redirect_url !== '') : ?>
<p class="auth-footer-link">
<a href="<?php echo esc_url($redirect_url); ?>"><?php esc_html_e('立即进入账号', 'aksrt'); ?></a>
</p>
<script>
setTimeout(function(){ window.location.href = <?php echo wp_json_encode($redirect_url); ?>; }, 1800);
</script>
<?php elseif ($verify_mode === 'code') : ?>
<form class="auth-form" method="post" action="">
<?php wp_nonce_field('aksrt_verify_email', '_verify_email_nonce'); ?>
<input type="hidden" name="verify_uid" value="<?php echo esc_attr((string) $verify_uid); ?>">
<input type="hidden" name="vk" value="<?php echo esc_attr($verify_vk); ?>">
<div class="form-field">
<label for="verify_email_code"><?php esc_html_e('邮箱验证码', 'aksrt'); ?></label>
<div class="input-wrap">
<span class="input-icon" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:18px;height:18px;"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg></span>
<input type="text" name="email_code" id="verify_email_code" inputmode="numeric" maxlength="6" pattern="[0-9]*" autocomplete="one-time-code" required>
</div>
</div>
<?php if ($verify_email !== '') : ?>
<p class="auth-card__subtitle" style="margin-top:-8px;"><?php echo esc_html(sprintf(__('验证码已发送到 %s', 'aksrt'), $verify_email)); ?></p>
<?php endif; ?>
<?php if (function_exists('aksrt_render_captcha')) : ?>
<?php aksrt_render_captcha('verify_email'); ?>
<?php endif; ?>
<button type="submit" name="verify_email_submit" class="btn-primary btn-lg btn-block"><?php esc_html_e('验证并登录', 'aksrt'); ?></button>
</form>
<form method="post" action="" style="margin-top:12px;">
<?php wp_nonce_field('aksrt_verify_email', '_verify_email_nonce'); ?>
<input type="hidden" name="verify_uid" value="<?php echo esc_attr((string) $verify_uid); ?>">
<input type="hidden" name="vk" value="<?php echo esc_attr($verify_vk); ?>">
<?php if (function_exists('aksrt_render_captcha')) : ?>
<?php aksrt_render_captcha('verify_email'); ?>
<?php endif; ?>
<button type="submit" name="verify_email_resend" class="btn-primary btn-lg" style="width:100%;background:transparent;color:var(--color-primary);border:1px solid var(--color-primary);"><?php esc_html_e('重新发送验证码', 'aksrt'); ?></button>
</form>
<?php elseif ($verify_mode === 'pending' && $verify_uid > 0 && $verify_vk !== '') : ?>
<?php
// method 缺失(历史账号 / meta 被外部清理)→ 回退到设置默认值
$resend_method = in_array($verify_method, ['link', 'code'], true)
? $verify_method
: (class_exists('AKSRT_Settings') ? AKSRT_Settings::registration_verification_method() : 'link');
?>
<?php if ($verify_email !== '') : ?>
<p class="auth-card__subtitle"><?php echo esc_html(sprintf(__('当前待验证邮箱:%s', 'aksrt'), $verify_email)); ?></p>
<?php endif; ?>
<form method="post" action="">
<?php wp_nonce_field('aksrt_verify_email', '_verify_email_nonce'); ?>
<input type="hidden" name="verify_uid" value="<?php echo esc_attr((string) $verify_uid); ?>">
<input type="hidden" name="vk" value="<?php echo esc_attr($verify_vk); ?>">
<?php if (function_exists('aksrt_render_captcha')) : ?>
<?php aksrt_render_captcha('verify_email'); ?>
<?php endif; ?>
<button type="submit" name="verify_email_resend" class="btn-primary btn-lg" style="width:100%;"><?php echo esc_html($resend_method === 'code' ? __('重新发送验证码', 'aksrt') : __('重新发送验证邮件', 'aksrt')); ?></button>
</form>
<?php endif; ?>
<p class="auth-footer-link">
<a href="<?php echo esc_url(aksrt_get_login_url()); ?>"><?php esc_html_e('返回登录', 'aksrt'); ?></a>
</p>
</div>
</div>
</main>
<?php
get_footer();