fix(user-center): embed official certification panel
This commit is contained in:
@@ -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']);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user