Merge pull request 'fix(user-center): embed official certification panel' (#319) from worktree-user-center-sidebar-wallet-redesign into main

Reviewed-on: CYL/wordpress-theme-aksrt#319
This commit is contained in:
2026-07-28 15:26:04 +08:00
22 changed files with 415 additions and 461 deletions
@@ -14,6 +14,21 @@
<n-descriptions-item label="最近处理">{{ detail.request.reviewed_at || '-' }}</n-descriptions-item>
</n-descriptions>
<div class="aksrt-verify-drawer__section">
<div class="aksrt-verify-drawer__title">申请资料</div>
<n-descriptions bordered :column="1" size="small" label-placement="left">
<n-descriptions-item label="认证类型">{{ detail.request.application?.type || '-' }}</n-descriptions-item>
<n-descriptions-item label="认证身份">{{ detail.request.application?.name || '-' }}</n-descriptions-item>
<n-descriptions-item label="身份简介">{{ detail.request.application?.desc || '-' }}</n-descriptions-item>
<n-descriptions-item label="申请说明">{{ detail.request.application?.msg || '-' }}</n-descriptions-item>
</n-descriptions>
<div v-if="detail.request.application?.img?.length" class="aksrt-verify-drawer__proofs">
<a v-for="image in detail.request.application.img" :key="image" :href="image" target="_blank" rel="noopener noreferrer">
<img :src="image" alt="认证证明材料" />
</a>
</div>
</div>
<div class="aksrt-verify-drawer__section">
<div class="aksrt-verify-drawer__title">当前备注</div>
<n-alert type="info" :show-icon="false">
@@ -149,6 +164,21 @@ async function handleSubmit() {
color: #1f2937;
}
.aksrt-verify-drawer__proofs {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 12px;
}
.aksrt-verify-drawer__proofs img {
display: block;
width: 92px;
height: 92px;
border-radius: 10px;
object-fit: cover;
}
.aksrt-verify-drawer__timeline {
display: grid;
gap: 12px;
@@ -4,7 +4,7 @@ export const featuresSchema = {
icon: 'fas fa-user-cog',
description: '配置用户中心和个人主页的功能模块。',
defaults: {
user_center_tabs: 'profile,posts,comments,favorites,vip,credits',
user_center_tabs: 'profile,posts,comments,favorites,vip,credits,auth',
user_avatar_upload: true,
user_cover_upload: true,
user_social_links: true,
@@ -26,7 +26,7 @@ export const featuresSchema = {
title: '用户中心',
icon: 'fas fa-user-shield',
fields: [
{ key: 'user_center_tabs', label: '用户中心 Tab', type: 'input', default: 'profile,posts,comments,favorites,vip,credits', help: '逗号分隔。vip=我的会员(会员功能开启时也会自动注入)' },
{ key: 'user_center_tabs', label: '用户中心 Tab', type: 'input', default: 'profile,posts,comments,favorites,vip,credits,auth', help: '逗号分隔。auth=官方认证;vip、订单和认证会按功能开关自动注入' },
{ key: 'user_avatar_upload', label: '头像上传', type: 'switch', default: true },
{ key: 'user_cover_upload', label: '封面上传', type: 'switch', default: true },
{ key: 'user_social_links', label: '社交链接', type: 'switch', default: true },
-80
View File
@@ -1,80 +0,0 @@
/**
* User identity auth page styles (zibll user-auth).
*
* @package AKSRT
*/
.aksrt-user-auth-panel {
overflow: hidden;
margin-top: 20px;
}
.aksrt-user-auth-panel .colorful-bg.c-blue {
background: linear-gradient(135deg, #4e9bff 0%, #2f6df6 100%);
color: #fff;
}
.aksrt-user-auth-panel .muted-2-color {
color: var(--muted-2-color, #888);
}
.aksrt-user-auth-panel .form-control {
width: 100%;
padding: 8px 10px;
border: 1px solid var(--main-border-color, #ddd);
border-radius: 6px;
box-sizing: border-box;
}
.aksrt-user-auth-panel .mb20 {
margin-bottom: 20px;
}
.aksrt-user-auth-panel .mb6 {
margin-bottom: 6px;
}
.aksrt-user-auth-panel .but.c-blue,
.aksrt-user-auth-panel button.but {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
background: var(--focus-color, #2f6df6);
color: #fff;
border: 0;
border-radius: 6px;
padding: 10px 18px;
cursor: pointer;
}
.aksrt-user-auth-panel .btn-block {
width: 100%;
}
.aksrt-user-auth-panel__imgs {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.aksrt-user-auth-panel__imgs .preview-item {
width: 96px;
height: 96px;
border-radius: 6px;
overflow: hidden;
border: 1px solid var(--main-border-color, #eee);
}
.aksrt-user-auth-panel__imgs img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.aksrt-user-auth-panel .c-red {
color: #e74c3c;
}
/* Dual-column geometry owned by layout.css site-layout float rules (Zibll). */
@@ -359,3 +359,79 @@
margin-right: 8px;
margin-top: 4px;
}
/* ==================== 官方认证面板 ==================== */
.uc-auth-panel { overflow: hidden; }
.uc-auth-card {
display: grid;
grid-template-columns: 128px minmax(0, 1fr);
min-height: 210px;
overflow: hidden;
border-radius: 14px;
background: linear-gradient(135deg, rgba(59, 130, 246, 0.13), rgba(124, 92, 220, 0.08));
}
.uc-auth-card__art {
display: grid;
place-items: center;
background: linear-gradient(150deg, #3988f4, #7567de);
color: #fff;
font-size: 46px;
}
.uc-auth-card__content {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
padding: 28px;
}
.uc-auth-card__content small { color: var(--color-primary); font-weight: 700; }
.uc-auth-card__content h2 { margin: 5px 0 9px; font-size: 24px; }
.uc-auth-card__content p,
.uc-auth-card__content time { margin: 0; color: var(--color-ink-4); font-size: 13px; line-height: 1.7; }
.uc-auth-card__notice { margin-top: 14px; color: var(--color-error, #dc2626); font-size: 13px; }
.uc-auth-apply-open { margin-top: 18px; min-width: 112px; }
.uc-auth-card--verified { background: linear-gradient(135deg, rgba(16, 185, 129, 0.12), rgba(59, 130, 246, 0.08)); }
.uc-auth-card--verified .uc-auth-card__art { background: linear-gradient(150deg, #20a77d, #3287df); }
.uc-auth-modal { z-index: 620; }
.uc-auth-modal .aksrt-modal__dialog { width: min(620px, calc(100vw - 28px)); max-height: min(760px, calc(100vh - 40px)); overflow: auto; }
.uc-auth-modal__header > div { display: flex; align-items: center; gap: 10px; }
.uc-auth-modal__header > div > span { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 11px; background: var(--color-primary-soft); color: var(--color-primary); }
.uc-auth-modal__body { padding: 22px; }
.uc-auth-form { display: grid; gap: 17px; }
.uc-auth-form > label { display: grid; gap: 7px; color: var(--color-ink-2); font-size: 13px; font-weight: 600; }
.uc-auth-form .form-control { width: 100%; min-height: 42px; padding: 9px 11px; border: 1px solid var(--color-line-soft, rgba(15, 23, 42, 0.1)); border-radius: 9px; background: var(--surface-1); color: var(--color-ink); font: inherit; font-weight: 400; box-sizing: border-box; }
.uc-auth-form textarea.form-control { resize: vertical; }
.uc-auth-upload small { color: var(--color-ink-4); font-weight: 400; }
.uc-auth-submit { display: inline-flex; align-items: center; justify-content: center; gap: 7px; min-height: 44px; }
.uc-auth-form__message { min-height: 18px; color: var(--color-error, #dc2626); font-size: 12px; text-align: center; }
.uc-auth-upload__previews { display: flex; flex-wrap: wrap; gap: 8px; }
.uc-auth-upload__previews img,
.uc-auth-proof-list .preview-item { width: 82px; height: 82px; border-radius: 8px; overflow: hidden; object-fit: cover; }
.uc-auth-proof-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.uc-auth-proof-list img { width: 100%; height: 100%; object-fit: cover; }
.uc-auth-pending { text-align: center; padding: 4px 0 18px; }
.uc-auth-pending > span { display: grid; place-items: center; width: 58px; height: 58px; margin: 0 auto 12px; border-radius: 18px; background: rgba(245, 158, 11, 0.14); color: #a66e0b; font-size: 24px; }
.uc-auth-pending h3 { margin: 0 0 7px; }
.uc-auth-pending p { margin: 0; color: var(--color-ink-4); font-size: 13px; }
.uc-auth-apply-detail { display: grid; gap: 0; border-top: 1px solid var(--color-line-soft); }
.uc-auth-apply-detail dl { display: grid; grid-template-columns: 90px minmax(0, 1fr); gap: 12px; margin: 0; padding: 12px 0; border-bottom: 1px solid var(--color-line-soft); font-size: 13px; }
.uc-auth-apply-detail dt { color: var(--color-ink-4); }
.uc-auth-apply-detail dd { margin: 0; color: var(--color-ink-2); }
.uc-auth-modal__confirm { width: 100%; margin-top: 20px; }
@media (max-width: 640px) {
.uc-auth-card { grid-template-columns: 92px minmax(0, 1fr); min-height: 180px; }
.uc-auth-card__art { font-size: 34px; }
.uc-auth-card__content { padding: 20px 17px; }
.uc-auth-card__content h2 { font-size: 20px; }
.uc-auth-modal .aksrt-modal__dialog { position: fixed; inset: auto 0 0; width: 100%; max-height: 88vh; margin: 0; border-radius: 18px 18px 0 0; }
}
+6 -1
View File
@@ -631,10 +631,15 @@ body.aksrt-user-center .uc-content,
.uc-service-grid__item--profile .uc-service-grid__icon { color: #6550c7; background: rgba(124, 92, 220, 0.12); }
.uc-service-grid__item--security .uc-service-grid__icon { color: #16816c; background: rgba(16, 185, 129, 0.12); }
.uc-service-grid__item:hover {
.uc-service-grid__item:hover,
.uc-service-grid__item.is-active {
color: var(--color-primary);
}
.uc-service-grid__item.is-active .uc-service-grid__icon {
box-shadow: 0 0 0 2px var(--color-primary-soft), 0 5px 14px rgba(15, 23, 42, 0.08);
}
@media (prefers-reduced-motion: reduce) {
.uc-order-grid__icon { transition: none; }
}
+89 -1
View File
@@ -27,7 +27,7 @@
if (!tabContainer) return;
var tabs = tabContainer.querySelectorAll('[data-tab]');
var sidebarBtns = document.querySelectorAll('.uc-sidebar__btn[data-tab]');
var sidebarBtns = document.querySelectorAll('.uc-sidebar__btn[data-tab], .uc-service-grid__item[data-tab]');
var panels = {};
var defaultTab = cfg.defaultTab || 'profile';
var drawerTrigger = document.getElementById('uc-drawer-trigger');
@@ -193,6 +193,92 @@
});
}
function initAuthForm() {
var modal = document.getElementById('uc-auth-modal');
if (!modal || modal.dataset.authModalBound === '1') return;
modal.dataset.authModalBound = '1';
function openModal() {
modal.classList.add('is-open');
modal.setAttribute('aria-hidden', 'false');
document.body.style.overflow = 'hidden';
var first = modal.querySelector('input:not([type="hidden"]), select, textarea, button');
if (first) window.setTimeout(function() { first.focus(); }, 80);
}
function closeModal() {
modal.classList.remove('is-open');
modal.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
}
document.querySelectorAll('[data-auth-modal-open]').forEach(function(button) {
button.addEventListener('click', openModal);
});
modal.querySelectorAll('[data-auth-modal-close]').forEach(function(button) {
button.addEventListener('click', closeModal);
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.classList.contains('is-open')) closeModal();
});
var fileInput = modal.querySelector('[data-auth-files]');
var previews = modal.querySelector('[data-auth-previews]');
if (fileInput && previews) {
fileInput.addEventListener('change', function() {
previews.innerHTML = '';
var files = Array.prototype.slice.call(fileInput.files || []);
if (files.length > 3) {
showToast('证明材料最多上传 3 张');
fileInput.value = '';
return;
}
for (var index = 0; index < files.length; index++) {
if (files[index].size > 2 * 1024 * 1024) {
showToast('单张图片不能超过 2MB');
fileInput.value = '';
previews.innerHTML = '';
return;
}
var image = document.createElement('img');
image.src = URL.createObjectURL(files[index]);
image.alt = '';
image.onload = function() { URL.revokeObjectURL(this.src); };
previews.appendChild(image);
}
});
}
var form = modal.querySelector('.aksrt-user-auth-form');
if (!form) return;
form.addEventListener('submit', function(e) {
e.preventDefault();
var button = form.querySelector('[type="submit"]');
var message = form.querySelector('[data-auth-message]');
var original = button ? button.textContent : '';
if (button) {
button.disabled = true;
button.textContent = i18n.submitting || '提交中…';
}
if (message) message.textContent = '';
fetch(ajaxUrl, { method: 'POST', body: new FormData(form), credentials: 'same-origin' })
.then(function(response) { return response.json(); })
.then(function(response) {
if (!response || response.error) throw new Error((response && response.msg) || '提交失败');
showToast(response.msg || '提交成功');
window.setTimeout(function() { window.location.assign(tabUrls.auth || '?tab=auth'); }, 500);
})
.catch(function(error) {
if (message) message.textContent = error.message || '提交失败';
showToast(error.message || '提交失败');
if (button) {
button.disabled = false;
button.textContent = original;
}
});
});
}
/* ==================== 列表内取消收藏 ==================== */
function initUnfavorite() {
var list = document.querySelector('.profile-list[data-list="favorites"]');
@@ -678,6 +764,7 @@
document.addEventListener('DOMContentLoaded', function() {
initDashboardNavigation();
initProfileForm();
initAuthForm();
initUnfavorite();
initNotifications();
initSettings();
@@ -685,6 +772,7 @@
} else {
initDashboardNavigation();
initProfileForm();
initAuthForm();
initUnfavorite();
initNotifications();
initSettings();
-64
View File
@@ -1,64 +0,0 @@
/**
* User auth apply form AJAX.
*
* @package AKSRT
*/
(function () {
'use strict';
function ajaxUrl() {
if (window.aksrtData && window.aksrtData.ajaxUrl) return window.aksrtData.ajaxUrl;
return '/wp-admin/admin-ajax.php';
}
function toast(msg, type) {
if (window.aksrt && typeof window.aksrt.toast === 'function') {
window.aksrt.toast(msg, type || 'info');
return;
}
// eslint-disable-next-line no-alert
window.alert(msg);
}
function init() {
var form = document.querySelector('.aksrt-user-auth-form');
if (!form) return;
form.addEventListener('submit', function (e) {
e.preventDefault();
var btn = form.querySelector('button[type="submit"]');
if (btn) btn.disabled = true;
var fd = new FormData(form);
if (!fd.get('action')) fd.set('action', 'aksrt_user_auth_apply');
fetch(ajaxUrl(), {
method: 'POST',
body: fd,
credentials: 'same-origin',
})
.then(function (r) { return r.json(); })
.then(function (data) {
if (!data || data.error) {
toast((data && data.msg) || '提交失败', 'danger');
return;
}
toast(data.msg || '提交成功', 'success');
if (data.reload) {
window.setTimeout(function () { window.location.reload(); }, 500);
}
})
.catch(function () {
toast('网络错误', 'danger');
})
.finally(function () {
if (btn) btn.disabled = false;
});
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
+2 -1
View File
@@ -148,6 +148,7 @@ if (!function_exists('aksrt_capture_user_center_view')) {
'credits' => 'credits',
'vip' => 'vip',
'orders' => 'orders',
'auth' => 'auth',
'settings' => 'settings',
'header' => 'header',
'sidebar' => 'sidebar',
@@ -172,7 +173,7 @@ if (!function_exists('aksrt_capture_user_center_panel')) {
* Capture a built-in or registered user-center panel body.
*/
function aksrt_capture_user_center_panel(string $tab_key, array $tab, array $context): string {
$built_in_tabs = ['profile', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'settings'];
$built_in_tabs = ['profile', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'settings'];
if (in_array($tab_key, $built_in_tabs, true)) {
return aksrt_capture_user_center_view($tab_key, $context);
}
@@ -0,0 +1,108 @@
<?php
/**
* User center panel: official certification.
*
* Zibll parity: compact center card + in-place application modal.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
use AKSRT\User\AuthApply;
$context = is_array($args['context'] ?? null) ? $args['context'] : [];
$user_id = (int) ($context['user_id'] ?? get_current_user_id());
$settings = class_exists(AuthApply::class) ? AuthApply::settings() : ['enabled' => false, 'allow_apply' => false];
$status = $user_id > 0 && class_exists(AuthApply::class) ? AuthApply::get_status($user_id) : '';
$info = $user_id > 0 && class_exists(AuthApply::class) ? AuthApply::get_auth_info($user_id) : [];
$apply = $user_id > 0 && class_exists(AuthApply::class) ? AuthApply::get_apply_payload($user_id) : [];
$type_labels = [];
foreach ((array) ($settings['types'] ?? []) as $type) {
$type_labels[(string) ($type['slug'] ?? '')] = (string) ($type['label'] ?? '');
}
$apply_type = sanitize_key((string) ($apply['type'] ?? ''));
$limit = (int) ($settings['limit_level'] ?? 0);
$current_level = class_exists('\AKSRT\User\Level') ? (int) \AKSRT\User\Level::get_level($user_id) : 0;
$blocked_level = $limit > 0 && $current_level < $limit;
$can_apply = !empty($settings['enabled']) && !empty($settings['allow_apply']) && !$blocked_level && $status !== 'verified';
?>
<div class="aksrt-user-auth-panel uc-auth-panel">
<?php if ($status === 'verified') :
$name = (string) ($info['name'] ?? $apply['name'] ?? __('官方认证', 'aksrt'));
$desc = (string) ($info['desc'] ?? $apply['desc'] ?? '');
$time = (string) ($info['time'] ?? get_user_meta($user_id, 'aksrt_user_verify_reviewed_at', true));
?>
<div class="uc-auth-card uc-auth-card--verified">
<span class="uc-auth-card__art"><i class="fas fa-check-circle" aria-hidden="true"></i></span>
<div class="uc-auth-card__content">
<small><?php esc_html_e('已通过官方认证', 'aksrt'); ?></small>
<h2><?php echo esc_html($name); ?></h2>
<?php if ($desc !== '') : ?><p><?php echo esc_html($desc); ?></p><?php endif; ?>
<?php if ($time !== '') : ?><time><?php printf(esc_html__('认证时间:%s', 'aksrt'), esc_html($time)); ?></time><?php endif; ?>
</div>
</div>
<?php else : ?>
<div class="uc-auth-card">
<span class="uc-auth-card__art"><i class="fas fa-id-badge" aria-hidden="true"></i></span>
<div class="uc-auth-card__content">
<small><?php esc_html_e('身份权益', 'aksrt'); ?></small>
<h2><?php esc_html_e('官方认证', 'aksrt'); ?></h2>
<p><?php echo esc_html((string) ($settings['desc'] ?? __('认证后将展示官方身份标识。', 'aksrt'))); ?></p>
<?php if (empty($settings['allow_apply'])) : ?>
<div class="uc-auth-card__notice"><?php echo wp_kses_post(nl2br(esc_html((string) ($settings['disable_desc'] ?? __('暂时不能申请身份认证', 'aksrt'))))); ?></div>
<?php elseif ($blocked_level) : ?>
<div class="uc-auth-card__notice"><?php printf(esc_html__('达到 LV.%d 后即可申请', 'aksrt'), $limit); ?></div>
<?php elseif ($can_apply) : ?>
<button type="button" class="btn-primary uc-auth-apply-open" data-auth-modal-open>
<?php echo $status === 'pending' ? esc_html__('查看申请进度', 'aksrt') : esc_html__('申请认证', 'aksrt'); ?>
</button>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php if ($can_apply) : ?>
<div class="aksrt-modal uc-auth-modal" id="uc-auth-modal" aria-hidden="true">
<div class="aksrt-modal__backdrop" data-auth-modal-close></div>
<div class="aksrt-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="uc-auth-modal-title">
<div class="aksrt-modal__header uc-auth-modal__header">
<div><span><i class="fas fa-id-badge" aria-hidden="true"></i></span><strong id="uc-auth-modal-title"><?php esc_html_e('申请身份认证', 'aksrt'); ?></strong></div>
<button type="button" class="aksrt-modal__close" data-auth-modal-close aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fas fa-times" aria-hidden="true"></i></button>
</div>
<div class="aksrt-modal__body uc-auth-modal__body">
<?php if ($status === 'pending') : ?>
<div class="uc-auth-pending">
<span><i class="fas fa-hourglass-half" aria-hidden="true"></i></span>
<h3><?php esc_html_e('您的申请正在审核中', 'aksrt'); ?></h3>
<p><?php esc_html_e('请耐心等待,审核结果会通过消息中心通知。', 'aksrt'); ?></p>
</div>
<div class="uc-auth-apply-detail">
<dl><dt><?php esc_html_e('认证身份', 'aksrt'); ?></dt><dd><?php echo esc_html((string) ($apply['name'] ?? '')); ?></dd></dl>
<?php if ($apply_type !== '') : ?><dl><dt><?php esc_html_e('认证类型', 'aksrt'); ?></dt><dd><?php echo esc_html($type_labels[$apply_type] ?? $apply_type); ?></dd></dl><?php endif; ?>
<?php if (!empty($apply['desc'])) : ?><dl><dt><?php esc_html_e('身份简介', 'aksrt'); ?></dt><dd><?php echo esc_html((string) $apply['desc']); ?></dd></dl><?php endif; ?>
<?php if (!empty($apply['msg'])) : ?><dl><dt><?php esc_html_e('申请说明', 'aksrt'); ?></dt><dd><?php echo esc_html((string) $apply['msg']); ?></dd></dl><?php endif; ?>
<?php if (!empty($apply['time'])) : ?><dl><dt><?php esc_html_e('申请时间', 'aksrt'); ?></dt><dd><?php echo esc_html((string) $apply['time']); ?></dd></dl><?php endif; ?>
</div>
<?php if (!empty($apply['img'])) : ?>
<div class="aksrt-user-auth-panel__imgs uc-auth-proof-list"><?php foreach ((array) $apply['img'] as $img_url) : ?><div class="preview-item"><img src="<?php echo esc_attr(AuthApply::evidence_src((string) $img_url)); ?>" alt="" loading="lazy"></div><?php endforeach; ?></div>
<?php endif; ?>
<button type="button" class="btn-primary uc-auth-modal__confirm" data-auth-modal-close><?php esc_html_e('确定', 'aksrt'); ?></button>
<?php else : ?>
<form class="aksrt-user-auth-form uc-auth-form" enctype="multipart/form-data">
<label><span><?php esc_html_e('认证类型', 'aksrt'); ?></span><select class="form-control" name="type" required><?php foreach ((array) ($settings['types'] ?? []) as $type) : ?><option value="<?php echo esc_attr((string) $type['slug']); ?>"><?php echo esc_html((string) $type['label']); ?></option><?php endforeach; ?></select></label>
<label><span><?php esc_html_e('认证身份', 'aksrt'); ?></span><input type="text" class="form-control" name="name" required minlength="4" maxlength="16" placeholder="<?php esc_attr_e('请输入 4-16 个字符', 'aksrt'); ?>"></label>
<label><span><?php esc_html_e('身份简介', 'aksrt'); ?></span><textarea class="form-control" name="desc" rows="3" maxlength="300" placeholder="<?php esc_attr_e('认证通过后公开展示的身份说明', 'aksrt'); ?>"></textarea></label>
<label><span><?php esc_html_e('申请说明', 'aksrt'); ?></span><textarea class="form-control" name="msg" rows="3" maxlength="500" placeholder="<?php esc_attr_e('说明申请缘由,便于管理员审核', 'aksrt'); ?>"></textarea></label>
<label class="uc-auth-upload"><span><?php esc_html_e('证明材料', 'aksrt'); ?></span><input type="file" name="image[]" accept="image/jpeg,image/png,image/gif,image/webp" multiple data-auth-files><small><?php esc_html_e('最多上传 3 张图片,单张不超过 2MB(可选)。', 'aksrt'); ?></small><div class="uc-auth-upload__previews" data-auth-previews></div></label>
<?php wp_nonce_field('aksrt_user_auth_apply', '_wpnonce', false); ?>
<input type="hidden" name="action" value="aksrt_user_auth_apply">
<button type="submit" class="btn-primary uc-auth-submit"><i class="fas fa-check" aria-hidden="true"></i><?php esc_html_e('确认提交', 'aksrt'); ?></button>
<div class="uc-auth-form__message" data-auth-message role="status"></div>
</form>
<?php endif; ?>
</div>
</div>
</div>
<?php endif; ?>
</div>
@@ -11,10 +11,7 @@ $cart_url = function_exists('aksrt_get_cart_page_url') ? aksrt_get_cart_page_url
$level_url = isset($dashboard_tabs['credits'])
? add_query_arg('asset_tab', 'points', aksrt_get_user_center_tab_url('credits'))
: '';
$auth_settings = class_exists('\AKSRT\User\AuthApply') ? \AKSRT\User\AuthApply::settings() : [];
$auth_url = !empty($auth_settings['enabled']) && function_exists('aksrt_get_user_auth_page_url')
? aksrt_get_user_auth_page_url()
: '';
$auth_url = isset($dashboard_tabs['auth']) ? aksrt_get_user_center_tab_url('auth') : '';
$services = array_values(array_filter([
[
@@ -34,6 +31,7 @@ $services = array_values(array_filter([
'icon' => 'id-badge',
'tone' => 'auth',
'url' => $auth_url,
'tab' => 'auth',
],
], static fn(array $item): bool => (string) $item['url'] !== ''));
@@ -63,7 +61,7 @@ $render_grid = static function (array $items): void {
?>
<div class="uc-service-grid">
<?php foreach ($items as $item) : ?>
<a class="uc-service-grid__item uc-service-grid__item--<?php echo esc_attr((string) $item['tone']); ?>" href="<?php echo esc_url((string) $item['url']); ?>">
<a class="uc-service-grid__item uc-service-grid__item--<?php echo esc_attr((string) $item['tone']); ?><?php echo !empty($item['tab']) && ($active_tab ?? '') === $item['tab'] ? ' is-active' : ''; ?>" href="<?php echo esc_url((string) $item['url']); ?>"<?php if (!empty($item['tab'])) : ?> data-tab="<?php echo esc_attr((string) $item['tab']); ?>"<?php endif; ?>>
<span class="uc-service-grid__icon">
<i class="fas fa-<?php echo esc_attr((string) $item['icon']); ?>" aria-hidden="true"></i>
<?php if (!empty($item['count'])) : ?><small><?php echo esc_html((string) $item['count']); ?></small><?php endif; ?>
+1 -7
View File
@@ -18,7 +18,6 @@ add_filter('query_vars', function ($vars) {
$vars[] = 'aksrt_orders';
$vars[] = 'aksrt_cart';
$vars[] = 'aksrt_revenue';
$vars[] = 'aksrt_user_auth';
return $vars;
});
@@ -43,14 +42,12 @@ add_action('init', function () {
add_rewrite_tag('%aksrt_orders%', '([0-1])');
add_rewrite_tag('%aksrt_cart%', '([0-1])');
add_rewrite_tag('%aksrt_revenue%', '([0-1])');
add_rewrite_tag('%aksrt_user_auth%', '([0-1])');
add_rewrite_rule('^profile/?$', 'index.php?aksrt_user_center=1', 'top');
add_rewrite_rule('^user/([^/]+)/?$', 'index.php?user_nicename=$matches[1]', 'top');
// Commerce center aliases (work even before WP page is assigned).
add_rewrite_rule('^orders/?$', 'index.php?aksrt_orders=1', 'top');
add_rewrite_rule('^cart/?$', 'index.php?aksrt_cart=1', 'top');
add_rewrite_rule('^revenue/?$', 'index.php?aksrt_revenue=1', 'top');
add_rewrite_rule('^user-auth/?$', 'index.php?aksrt_user_auth=1', 'top');
});
// --- 3b. 统一模板拦截器(核心)---
@@ -169,7 +166,7 @@ add_action('init', function () {
}
// 统一 flush 检查 — bump when user-home rewrite / author override changes
$rewrite_version = AKSRT_VERSION . ':user-home-profile-routing-v4';
$rewrite_version = AKSRT_VERSION . ':user-home-profile-routing-v5';
$flushed = get_option('aksrt_user_rules_flushed');
$rules = get_option('rewrite_rules');
$need_flush = ($flushed !== $rewrite_version)
@@ -218,9 +215,6 @@ add_filter('request', function ($query_vars) {
if (empty($query_vars['aksrt_user_center']) && isset($_GET['aksrt_user_center'])) {
$query_vars['aksrt_user_center'] = '1';
}
if (empty($query_vars['aksrt_user_auth']) && isset($_GET['aksrt_user_auth'])) {
$query_vars['aksrt_user_auth'] = '1';
}
return $query_vars;
});
@@ -131,12 +131,6 @@ $_aksrt_special_templates = [
'title' => '消息中心',
'fallback' => '/messages/',
],
'user-auth' => [
'file' => 'templates/pages/page-user-auth.php',
'slug' => 'user-auth',
'title' => '官方认证',
'fallback' => '/user-auth/',
],
'submit' => [
'file' => 'templates/pages/page-submit.php',
'slug' => 'submit',
@@ -282,7 +276,6 @@ function aksrt_resolve_page_template_file(string $template_file = '', string $po
'categories' => 'templates/pages/page-categories.php',
'friends' => 'templates/pages/page-friends.php',
'profile' => 'templates/pages/page-profile.php',
'user-auth' => 'templates/pages/page-user-auth.php',
];
if (!empty($slug_map[$post_slug]) && aksrt_locate_template_file($slug_map[$post_slug])) {
@@ -444,11 +437,6 @@ function aksrt_get_current_special_template_path(): string {
return $revenue_template ?: '';
}
if (get_query_var('aksrt_user_auth')) {
$auth_template = aksrt_locate_template_file('templates/pages/page-user-auth.php');
return $auth_template ?: '';
}
if (get_query_var('aksrt_sign')) {
$auth_template = aksrt_get_auth_template_file((string) get_query_var('aksrt_auth_tab'), true);
$auth_template_path = aksrt_locate_template_file($auth_template);
-15
View File
@@ -106,21 +106,6 @@ function aksrt_get_revenue_page_url(): string {
}
endif;
if (!function_exists('aksrt_get_user_auth_page_url')) :
/**
* 官方认证页面 URL。
*/
function aksrt_get_user_auth_page_url(): string {
if (function_exists('aksrt_get_template_url')) {
return aksrt_get_template_url('user-auth');
}
if (get_option('permalink_structure')) {
return home_url('/user-auth/');
}
return add_query_arg('aksrt_user_auth', '1', home_url('/'));
}
endif;
if (!function_exists('aksrt_get_messages_page_url')) :
/**
* 消息中心页面 URL(模板 templates/pages/page-messages.php)。
+22 -2
View File
@@ -547,7 +547,8 @@ class UsersMenus {
echo '<div class="description">' . esc_html((string) $apply['msg']) . '</div>';
}
foreach ((array) ($apply['img'] ?? []) as $image_url) {
echo '<a href="' . esc_url((string) $image_url) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_url((string) $image_url) . '" alt="" style="width:56px;height:56px;object-fit:cover;margin:6px 6px 0 0;border-radius:4px;" /></a>';
$evidence_src = class_exists('\AKSRT\User\AuthApply') ? \AKSRT\User\AuthApply::evidence_src((string) $image_url) : '';
echo '<a href="' . esc_attr($evidence_src) . '" target="_blank" rel="noopener noreferrer"><img src="' . esc_attr($evidence_src) . '" alt="" style="width:56px;height:56px;object-fit:cover;margin:6px 6px 0 0;border-radius:4px;" /></a>';
}
}
if (!empty($row['verify_reason'])) {
@@ -588,7 +589,17 @@ class UsersMenus {
check_admin_referer('aksrt_users_review_verify_' . $user_id);
$ok = false;
if ($user_id > 0 && in_array($status, ['verified', 'rejected'], true) && get_userdata($user_id)) {
$current_status = sanitize_key((string) get_user_meta($user_id, 'aksrt_user_verify_status', true));
$application = get_user_meta($user_id, 'aksrt_user_verify_apply', true);
if (
$user_id > 0
&& in_array($status, ['verified', 'rejected'], true)
&& get_userdata($user_id)
&& $current_status === 'pending'
&& is_array($application)
&& !empty($application['name'])
&& !empty($application['type'])
) {
update_user_meta($user_id, 'aksrt_user_verify_status', $status);
update_user_meta($user_id, 'aksrt_user_verify_reviewed_at', current_time('mysql'));
update_user_meta($user_id, 'aksrt_user_verify_reviewer', get_current_user_id());
@@ -619,6 +630,15 @@ class UsersMenus {
'time' => current_time('mysql'),
];
update_option('aksrt_verify_review_log', array_slice($log, -500), false);
if (class_exists('\AKSRT\Messages\Message')) {
$message = $status === 'verified'
? __('您的官方认证申请已通过审核', 'aksrt')
: sprintf(__('您的官方认证申请未通过:%s', 'aksrt'), $note !== '' ? $note : __('请修改资料后重新申请', 'aksrt'));
\AKSRT\Messages\Message::get_instance()->send($user_id, 'auth_apply_reply', $message, [
'title' => __('官方认证审核结果', 'aksrt'),
'target_url' => aksrt_get_user_center_tab_url('auth'),
]);
}
$ok = true;
}
$this->redirect('aksrt_user_auth', $ok ? 'verify_updated' : 'verify_failed', ['status' => 'pending']);
+1 -1
View File
@@ -515,7 +515,7 @@ class SchemaUsers {
'option_key' => 'aksrt_settings',
'groups' => [
['key' => 'center', 'title' => '用户中心', 'fields' => [
['key' => 'user_center_tabs', 'label' => '用户中心 Tab', 'type' => 'input', 'default' => 'profile,posts,comments,favorites,vip,credits', 'help' => '逗号分隔。vip=我的会员(会员功能开启时也会自动注入)'],
['key' => 'user_center_tabs', 'label' => '用户中心 Tab', 'type' => 'input', 'default' => 'profile,posts,comments,favorites,vip,credits,auth', 'help' => '逗号分隔。auth=官方认证;vip、订单和认证会按功能开关自动注入'],
['key' => 'user_avatar_upload', 'label' => '头像上传', 'type' => 'switch', 'default' => true],
['key' => 'user_cover_upload', 'label' => '封面上传', 'type' => 'switch', 'default' => true],
['key' => 'user_social_links', 'label' => '社交链接', 'type' => 'switch', 'default' => true],
@@ -179,6 +179,11 @@ trait UserControllerVerifyIntegrations {
if (!$user) {
return $this->error(__('用户不存在', 'aksrt'), 404);
}
$current_status = sanitize_key((string) get_user_meta($user_id, 'aksrt_user_verify_status', true));
$application = get_user_meta($user_id, 'aksrt_user_verify_apply', true);
if ($current_status !== 'pending' || !is_array($application) || empty($application['name']) || empty($application['type'])) {
return $this->error(__('该用户没有可审核的认证申请', 'aksrt'), 409);
}
update_user_meta($user_id, 'aksrt_user_verify_status', $status);
update_user_meta($user_id, 'aksrt_user_verify_reviewed_at', current_time('mysql'));
@@ -216,6 +221,15 @@ trait UserControllerVerifyIntegrations {
$log = array_slice($log, -500);
}
update_option('aksrt_verify_review_log', $log, false);
if (class_exists('\AKSRT\Messages\Message')) {
$message = $status === 'verified'
? __('您的官方认证申请已通过审核', 'aksrt')
: sprintf(__('您的官方认证申请未通过:%s', 'aksrt'), $note !== '' ? $note : __('请修改资料后重新申请', 'aksrt'));
\AKSRT\Messages\Message::get_instance()->send($user_id, 'auth_apply_reply', $message, [
'title' => __('官方认证审核结果', 'aksrt'),
'target_url' => aksrt_get_user_center_tab_url('auth'),
]);
}
return $this->success([
'message' => $status === 'verified'
@@ -239,7 +253,7 @@ trait UserControllerVerifyIntegrations {
'email' => (string) ($row['user_email'] ?? ''),
'status' => $status,
'reason' => (string) ($row['verify_reason'] ?? ''),
'requested_at' => (string) ($row['user_registered'] ?? ''),
'requested_at' => (string) ($application['time'] ?? $row['user_registered'] ?? ''),
'reviewed_at' => (string) ($row['reviewed_at'] ?? ''),
'email_verified' => $email_verified,
'application' => $application,
+3 -33
View File
@@ -448,7 +448,9 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
'aksrt-route-user-center',
$base_uri . '/assets/js/routes/user-center.js',
['aksrt-script'],
$version,
file_exists(get_template_directory() . '/assets/js/routes/user-center.js')
? (string) filemtime(get_template_directory() . '/assets/js/routes/user-center.js')
: $version,
true
);
// 绑定手机短信发送按钮依赖 sign-register 的 data-aksrt-sms-trigger 契约
@@ -623,38 +625,6 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
}
}
// 用户身份认证页(zibll user-auth.php)
$is_user_auth_page = (bool) get_query_var('aksrt_user_auth')
|| is_page_template('templates/pages/page-user-auth.php')
|| (
is_page()
&& (
(string) get_post_field('post_name', get_queried_object_id()) === 'user-auth'
|| (string) get_post_meta(get_queried_object_id(), '_wp_page_template', true) === 'templates/pages/page-user-auth.php'
)
);
if ($is_user_auth_page) {
$ua_css = get_template_directory() . '/assets/css/routes/user-auth.css';
if (file_exists($ua_css)) {
wp_enqueue_style(
'aksrt-route-user-auth',
$base_uri . '/assets/css/routes/user-auth.css',
['aksrt-tokens'],
(string) filemtime($ua_css)
);
}
$ua_js = get_template_directory() . '/assets/js/user-auth-page.js';
if (file_exists($ua_js)) {
wp_enqueue_script(
'aksrt-user-auth-page',
$base_uri . '/assets/js/user-auth-page.js',
[],
(string) filemtime($ua_js),
true
);
}
}
// 交易中心共享壳层(购物车 / 订单 / 收益)
// Virtual rewrite routes (aksrt_orders / aksrt_cart / aksrt_revenue) also count.
$is_commerce_center = is_page_template('templates/pages/page-orders.php')
-1
View File
@@ -48,7 +48,6 @@ class Templates {
'templates/pages/page-posts-navs.php' => __('AKSRT - 文章导航', 'aksrt'),
'templates/pages/page-friends.php' => __('AKSRT - 友情链接', 'aksrt'),
'templates/pages/page-links.php' => __('AKSRT - 网址导航', 'aksrt'),
'templates/pages/page-user-auth.php' => __('AKSRT - 用户身份认证', 'aksrt'),
'templates/pages/page-ban-appeal.php' => __('AKSRT - 禁封申诉', 'aksrt'),
'templates/pages/page-orders.php' => __('AKSRT - 订单中心', 'aksrt'),
'templates/pages/page-revenue.php' => __('AKSRT - 收益中心', 'aksrt'),
+2 -2
View File
@@ -83,14 +83,14 @@ class UserRuntime {
*/
public static function get_user_center_settings(): array {
$settings = Settings::get_all();
$raw_tabs = $settings['user_center_tabs'] ?? 'profile,posts,comments,credits,favorites';
$raw_tabs = $settings['user_center_tabs'] ?? 'profile,posts,comments,credits,favorites,auth';
$tabs = is_array($raw_tabs)
? $raw_tabs
: preg_split('/[\s,]+/', (string) $raw_tabs, -1, PREG_SPLIT_NO_EMPTY);
// Built-in switchable panels. VIP is always auto-injected when enabled
// by AKSRT\User\Center — keep it allowed for explicit config too.
$allowed_tabs = ['profile', 'posts', 'comments', 'favorites', 'credits', 'vip', 'settings'];
$allowed_tabs = ['profile', 'posts', 'comments', 'favorites', 'credits', 'vip', 'orders', 'auth', 'settings'];
$normalized_tabs = ['profile'];
foreach ((array) $tabs as $tab) {
+41 -30
View File
@@ -56,6 +56,12 @@ class AuthApply {
}
$types[] = ['slug' => $slug, 'label' => (string) $label];
}
if ($types === []) {
$types = [
['slug' => 'real_name', 'label' => __('实名认证', 'aksrt')],
['slug' => 'organization', 'label' => __('企业认证', 'aksrt')],
];
}
return [
'enabled' => $enabled,
'allow_apply' => !isset($all['user_verify_allow_apply']) || !empty($all['user_verify_allow_apply']),
@@ -95,6 +101,13 @@ class AuthApply {
return is_array($apply) ? $apply : [];
}
public static function evidence_src(string $value): string {
if (preg_match('#^data:image/(?:jpeg|png|gif|webp);base64,[A-Za-z0-9+/=]+$#', $value)) {
return $value;
}
return esc_url_raw($value);
}
public function ajax_apply(): void {
if (!is_user_logged_in()) {
wp_send_json(['error' => 1, 'msg' => __('请先登录', 'aksrt')]);
@@ -133,8 +146,9 @@ class AuthApply {
$msg = isset($_POST['msg']) ? sanitize_textarea_field(wp_unslash((string) $_POST['msg'])) : '';
$type = isset($_POST['type']) ? sanitize_key((string) wp_unslash($_POST['type'])) : '';
$allowed_types = array_column((array) $s['types'], 'slug');
if ($name === '') {
wp_send_json(['error' => 1, 'msg' => __('请填写认证身份名称', 'aksrt')]);
$name_length = function_exists('mb_strlen') ? mb_strlen($name) : strlen($name);
if ($name_length < 4 || $name_length > 16) {
wp_send_json(['error' => 1, 'msg' => __('认证身份长度需在 4-16 个字符之间', 'aksrt')]);
}
if ($type === '' || !in_array($type, $allowed_types, true)) {
wp_send_json(['error' => 1, 'msg' => __('请选择有效的认证类型', 'aksrt')]);
@@ -142,46 +156,43 @@ class AuthApply {
$images = [];
if (!empty($_FILES['image']['name'])) {
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$files = $_FILES['image'];
// Normalize multi-file upload.
$names = $files['name'];
if (!is_array($names)) {
$names = [$names];
$tmp = [
$names = is_array($files['name']) ? $files['name'] : [$files['name']];
if (!is_array($files['name'])) {
$files = [
'name' => $names,
'type' => [$files['type']],
'tmp_name' => [$files['tmp_name']],
'error' => [$files['error']],
'size' => [$files['size']],
];
$files = $tmp;
}
$count = min(3, count($files['name']));
for ($i = 0; $i < $count; $i++) {
if (empty($files['name'][$i]) || (int) $files['error'][$i] !== UPLOAD_ERR_OK) {
if (count($files['name']) > 3) {
wp_send_json(['error' => 1, 'msg' => __('证明材料最多上传 3 张', 'aksrt')]);
}
foreach ($files['name'] as $index => $filename) {
if ($filename === '') {
continue;
}
$file = [
'name' => $files['name'][$i],
'type' => $files['type'][$i],
'tmp_name' => $files['tmp_name'][$i],
'error' => $files['error'][$i],
'size' => $files['size'][$i],
];
$_FILES['aksrt_auth_img'] = $file;
$aid = media_handle_upload('aksrt_auth_img', 0);
if (!is_wp_error($aid)) {
$url = wp_get_attachment_url((int) $aid);
if ($url) {
$images[] = $url;
}
if ((int) ($files['error'][$index] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
wp_send_json(['error' => 1, 'msg' => __('证明材料上传失败,请重新选择', 'aksrt')]);
}
$size = (int) ($files['size'][$index] ?? 0);
$tmp_name = (string) ($files['tmp_name'][$index] ?? '');
if ($size <= 0 || $size > 2 * MB_IN_BYTES || !is_uploaded_file($tmp_name)) {
wp_send_json(['error' => 1, 'msg' => __('单张证明图片不能超过 2MB', 'aksrt')]);
}
$file_check = wp_check_filetype_and_ext($tmp_name, (string) $filename);
$mime = (string) ($file_check['type'] ?? '');
if (!in_array($mime, ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], true)) {
wp_send_json(['error' => 1, 'msg' => __('证明材料仅支持 JPG、PNG、GIF 或 WebP 图片', 'aksrt')]);
}
$bytes = file_get_contents($tmp_name);
if (!is_string($bytes) || $bytes === '') {
wp_send_json(['error' => 1, 'msg' => __('证明材料读取失败', 'aksrt')]);
}
$images[] = 'data:' . $mime . ';base64,' . base64_encode($bytes);
}
unset($_FILES['aksrt_auth_img']);
}
$payload = [
+14
View File
@@ -91,6 +91,12 @@ class Center {
'priority' => 60,
'type' => 'link',
],
'auth' => [
'label' => __('官方认证', 'aksrt'),
'icon' => 'id-badge',
'priority' => 65,
'type' => 'panel',
],
'settings' => [
'label' => __('账号设置', 'aksrt'),
'icon' => 'cog',
@@ -144,6 +150,11 @@ class Center {
if (($credits_on || $balance_on) && !in_array('credits', $order, true)) {
$order[] = 'credits';
}
$auth_on = class_exists('\AKSRT\User\AuthApply')
&& !empty(\AKSRT\User\AuthApply::settings()['enabled']);
if ($auth_on && !in_array('auth', $order, true)) {
$order[] = 'auth';
}
if (!in_array('settings', $order, true)) {
$order[] = 'settings';
}
@@ -161,6 +172,9 @@ class Center {
if ($key === 'orders' && !$orders_on) {
continue;
}
if ($key === 'auth' && !$auth_on) {
continue;
}
$panel = $definitions[$key];
if ($key === 'credits' && $balance_on) {
$panel['label'] = __('我的资产', 'aksrt');
-203
View File
@@ -1,203 +0,0 @@
<?php
/**
* Template Name: AKSRT - 用户身份认证
* Template Post Type: page
*
* Zibll pages/user-auth.php 1:1 shell on aksrt_user_verify_* storage.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
use AKSRT\User\AuthApply;
$settings = class_exists(AuthApply::class) ? AuthApply::settings() : ['enabled' => true, 'allow_apply' => true];
$user_id = get_current_user_id();
$status = $user_id && class_exists(AuthApply::class) ? AuthApply::get_status($user_id) : '';
$info = $user_id && class_exists(AuthApply::class) ? AuthApply::get_auth_info($user_id) : [];
$apply = $user_id && class_exists(AuthApply::class) ? AuthApply::get_apply_payload($user_id) : [];
$login_url = function_exists('aksrt_get_login_url') ? aksrt_get_login_url(aksrt_get_user_auth_page_url()) : wp_login_url(aksrt_get_user_auth_page_url());
get_header();
?>
<main class="container page-template-user-auth">
<div class="content-wrap">
<div class="content-layout">
<?php while (have_posts()) : the_post(); ?>
<div class="nopw-sm box-body theme-box radius8 main-bg main-shadow">
<article class="article wp-posts-content">
<?php
the_content();
wp_link_pages([
'before' => '<p class="text-center post-nav-links radius8 padding-6">',
'after' => '</p>',
]);
?>
</article>
</div>
<?php endwhile; ?>
<div class="theme-box radius8 main-bg main-shadow relative-h aksrt-user-auth-panel">
<?php if (empty($settings['enabled'])) : ?>
<div class="colorful-bg c-blue flex jc" style="min-height:120px;align-items:center;justify-content:center;">
<div class="text-center">
<div class="em2x"><i class="fa fa-id-badge" aria-hidden="true"></i></div>
<div class="mt10 em12"><?php esc_html_e('身份认证功能未启用', 'aksrt'); ?></div>
</div>
</div>
<?php elseif ($status === 'verified') : ?>
<?php
$name = (string) ($info['name'] ?? ($apply['name'] ?? __('官方认证', 'aksrt')));
$desc = (string) ($info['desc'] ?? ($apply['desc'] ?? ''));
$time = (string) ($info['time'] ?? get_user_meta($user_id, 'aksrt_user_verify_reviewed_at', true));
?>
<div class="colorful-bg c-blue flex ac jse aksrt-user-auth-panel__verified" style="padding:30px 16px;gap:20px;flex-wrap:wrap;">
<div class="text-center flex0">
<div class="em3x"><i class="fa fa-id-badge" aria-hidden="true"></i></div>
<div class="mt10 padding-w10"><?php esc_html_e('我的认证信息', 'aksrt'); ?></div>
</div>
<div class="box-body">
<div><i class="fa fa-check-circle" aria-hidden="true"></i> <b class="ml3"><?php echo esc_html($name); ?></b></div>
<?php if ($desc !== '') : ?>
<div class="muted-2-color mt10"><?php echo esc_html($desc); ?></div>
<?php endif; ?>
<?php if ($time !== '') : ?>
<div class="muted-2-color mt10"><?php echo esc_html(sprintf(__('认证时间:%s', 'aksrt'), $time)); ?></div>
<?php endif; ?>
</div>
</div>
<?php elseif (!$user_id) : ?>
<div class="colorful-bg c-blue flex jc" style="min-height:120px;align-items:center;justify-content:center;padding:24px;">
<div class="text-center">
<div class="em2x"><i class="fa fa-id-badge" aria-hidden="true"></i></div>
<div class="em12 padding-w10 mt10"><?php esc_html_e('申请身份认证', 'aksrt'); ?></div>
<p class="mt20">
<a class="but c-blue padding-lg signin-loader" href="<?php echo esc_url($login_url); ?>">
<i class="fa fa-sign-in mr6" aria-hidden="true"></i><?php esc_html_e('登录后申请', 'aksrt'); ?>
</a>
</p>
</div>
</div>
<?php elseif ($status === 'pending') : ?>
<div class="box-body" style="padding:24px;">
<div class="c-red mb10"><?php esc_html_e('您的申请正在审核中,请耐心等待', 'aksrt'); ?></div>
<div><i class="fa fa-id-badge" aria-hidden="true"></i> <b class="ml3"><?php echo esc_html((string) ($apply['name'] ?? '')); ?></b></div>
<?php if (!empty($apply['desc'])) : ?>
<div class="muted-2-color mt10"><?php echo esc_html((string) $apply['desc']); ?></div>
<?php endif; ?>
<?php if (!empty($apply['msg'])) : ?>
<div class="muted-2-color mt10"><?php echo esc_html(sprintf(__('申请说明:%s', 'aksrt'), (string) $apply['msg'])); ?></div>
<?php endif; ?>
<?php if (!empty($apply['time'])) : ?>
<div class="muted-2-color mt10"><?php echo esc_html(sprintf(__('申请时间:%s', 'aksrt'), (string) $apply['time'])); ?></div>
<?php endif; ?>
<?php if (!empty($apply['img']) && is_array($apply['img'])) : ?>
<div class="mt20 aksrt-user-auth-panel__imgs">
<?php foreach ($apply['img'] as $img_url) : ?>
<div class="preview-item"><img src="<?php echo esc_url((string) $img_url); ?>" alt=""></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php elseif (empty($settings['allow_apply'])) : ?>
<div class="box-body" style="padding:24px;">
<div class="c-red"><i class="fa mr6 fa-info-circle" aria-hidden="true"></i><?php esc_html_e('抱歉!暂时不能申请身份认证', 'aksrt'); ?></div>
<?php if (!empty($settings['disable_desc'])) : ?>
<div class="muted-color mt20"><?php echo wp_kses_post(nl2br(esc_html((string) $settings['disable_desc']))); ?></div>
<?php endif; ?>
</div>
<?php else : ?>
<?php
$blocked_level = false;
$limit = (int) ($settings['limit_level'] ?? 0);
if ($limit > 0 && class_exists('\AKSRT\User\Level')) {
$lv = (int) \AKSRT\User\Level::get_level($user_id);
if ($lv < $limit) {
$blocked_level = true;
}
}
?>
<?php if ($blocked_level) : ?>
<div class="box-body" style="padding:24px;">
<div class="c-red"><i class="fa mr6 fa-info-circle" aria-hidden="true"></i><?php esc_html_e('抱歉!您暂时不能申请身份认证', 'aksrt'); ?></div>
<div class="muted-color mt20">
<?php
printf(
/* translators: %d level */
esc_html__('由于您的等级过低,请升级到 LV.%d 后再来申请', 'aksrt'),
$limit
);
?>
</div>
</div>
<?php else : ?>
<div class="colorful-bg c-blue flex ac" style="height:100px;justify-content:center;gap:10px;">
<div class="em2x"><i class="fa fa-id-badge" aria-hidden="true"></i></div>
<div class="em12 padding-w10"><?php esc_html_e('申请身份认证', 'aksrt'); ?></div>
</div>
<div class="box-body" style="padding:20px;">
<?php if ($status === 'rejected') : ?>
<div class="c-red mb15">
<?php esc_html_e('上次申请未通过,可修改资料后重新提交。', 'aksrt'); ?>
<?php
$reason = (string) get_user_meta($user_id, AuthApply::REASON_META, true);
if ($reason !== '') {
echo '<div class="muted-2-color mt6">' . esc_html(sprintf(__('原因:%s', 'aksrt'), $reason)) . '</div>';
}
?>
</div>
<?php endif; ?>
<?php if (!empty($settings['desc'])) : ?>
<div class="muted-color mb20"><?php echo wp_kses_post(nl2br(esc_html((string) $settings['desc']))); ?></div>
<?php endif; ?>
<form class="aksrt-user-auth-form form-upload" enctype="multipart/form-data">
<?php if (!empty($settings['types'])) : ?>
<div class="mb20">
<div class="em09 muted-2-color mb6"><?php esc_html_e('认证类型', 'aksrt'); ?></div>
<select class="form-control" name="type">
<?php foreach ($settings['types'] as $t) : ?>
<option value="<?php echo esc_attr($t['slug']); ?>"><?php echo esc_html($t['label']); ?></option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
<div class="mb20">
<div class="em09 muted-2-color mb6"><?php esc_html_e('认证身份', 'aksrt'); ?></div>
<input type="text" class="form-control" name="name" required placeholder="<?php esc_attr_e('请输入身份名称', 'aksrt'); ?>" value="<?php echo esc_attr((string) ($apply['name'] ?? '')); ?>">
</div>
<div class="mb20">
<div class="em09 muted-2-color mb6"><?php esc_html_e('身份简介', 'aksrt'); ?></div>
<textarea class="form-control" name="desc" rows="2" placeholder="<?php esc_attr_e('请输入申请的身份简介', 'aksrt'); ?>"><?php echo esc_textarea((string) ($apply['desc'] ?? '')); ?></textarea>
</div>
<div class="mb20">
<div class="em09 muted-2-color mb6"><?php esc_html_e('申请说明', 'aksrt'); ?></div>
<textarea class="form-control" name="msg" rows="2" placeholder="<?php esc_attr_e('请输入申请缘由及说明', 'aksrt'); ?>"><?php echo esc_textarea((string) ($apply['msg'] ?? '')); ?></textarea>
</div>
<div class="mb20">
<div class="em09 muted-2-color mb6"><?php esc_html_e('证明材料', 'aksrt'); ?></div>
<input type="file" name="image[]" accept="image/gif,image/jpeg,image/jpg,image/png" multiple>
<div class="px12 muted-2-color mt6"><?php esc_html_e('最多 3 张图片', 'aksrt'); ?></div>
</div>
<?php wp_nonce_field('aksrt_user_auth_apply', '_wpnonce', false); ?>
<input type="hidden" name="action" value="aksrt_user_auth_apply">
<button type="submit" class="but c-blue padding-lg btn-block">
<i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e('确认提交', 'aksrt'); ?>
</button>
</form>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php
if (comments_open() || get_comments_number()) {
comments_template();
}
?>
</div>
</div>
<?php get_sidebar(); ?>
</main>
<?php
get_footer();