diff --git a/inc/helpers/aksrt-avatar.php b/inc/helpers/aksrt-avatar.php
index 7f58255b..ce89327c 100644
--- a/inc/helpers/aksrt-avatar.php
+++ b/inc/helpers/aksrt-avatar.php
@@ -281,7 +281,7 @@ if (!function_exists('aksrt_render_admin_avatar_field')) {
|
- ID, 96, ['loading' => 'eager']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
+ ID, 96, '', $user->display_name, ['loading' => 'eager']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
ID, 96) !== '') : ?>
diff --git a/src/Admin/Native/UsersMenusVerify.php b/src/Admin/Native/UsersMenusVerify.php
index 05c9a178..22d8ecca 100644
--- a/src/Admin/Native/UsersMenusVerify.php
+++ b/src/Admin/Native/UsersMenusVerify.php
@@ -195,7 +195,7 @@ trait UsersMenusVerify {
$application = (new \AKSRT\Identity\ApplicationRepository())->find_by_uuid($uuid);
$result = (!$application || (int) $application['user_id'] !== $user_id || (string) $application['status'] !== $expected)
? new \WP_Error('aksrt_verify_conflict', __('认证状态已变化,请刷新后重试', 'aksrt'))
- : \AKSRT\User\AuthApply::review($user_id, $status, $note, get_current_user_id());
+ : \AKSRT\User\AuthApply::review($user_id, $uuid, $status, $note, get_current_user_id(), []);
$extra = ['status' => $status === 'cancelled' ? 'cancelled' : 'pending'];
if (is_wp_error($result)) $extra['aksrt_verify_error'] = $result->get_error_message();
$this->redirect('aksrt_user_auth', is_wp_error($result) ? 'verify_failed' : 'verify_updated', $extra);
diff --git a/src/Identity/TransitionService.php b/src/Identity/TransitionService.php
index f9f76849..bff1be68 100644
--- a/src/Identity/TransitionService.php
+++ b/src/Identity/TransitionService.php
@@ -76,6 +76,11 @@ final class TransitionService {
return $updated;
}
+ /** @return array */
+ public static function allowed_targets(string $status): array {
+ return self::ALLOWED[sanitize_key($status)] ?? [];
+ }
+
/**
* Apply an identity transition inside an already-owned database transaction.
* The caller must lock the application row before invoking this method.
diff --git a/src/User/AuthApply.php b/src/User/AuthApply.php
index 59883b3d..53fe586f 100644
--- a/src/User/AuthApply.php
+++ b/src/User/AuthApply.php
@@ -29,6 +29,9 @@ class AuthApply {
add_filter('manage_users_custom_column', [$this, 'render_admin_user_column'], 10, 3);
add_action('show_user_profile', [$this, 'render_admin_profile_status']);
add_action('edit_user_profile', [$this, 'render_admin_profile_status']);
+ add_action('personal_options_update', [$this, 'handle_admin_profile_update']);
+ add_action('edit_user_profile_update', [$this, 'handle_admin_profile_update']);
+ add_action('admin_notices', [$this, 'render_admin_profile_notice']);
}
}
@@ -243,10 +246,12 @@ class AuthApply {
return $history;
}
- public static function review(int $user_id, string $status, string $note, int $reviewer_id) {
+ /** @param array $profile_fields */
+ public static function review(int $user_id, string $application_uuid, string $status, string $note, int $reviewer_id, array $profile_fields) {
$repo = new ApplicationRepository();
- $application = $repo->latest_for_user($user_id);
- if (!$application) {
+ $application_uuid = sanitize_text_field($application_uuid);
+ $application = wp_is_uuid($application_uuid) ? $repo->find_by_uuid($application_uuid) : null;
+ if (!$application || (int) $application['user_id'] !== $user_id) {
return new \WP_Error('aksrt_verify_missing', __('认证申请不存在', 'aksrt'));
}
$status = sanitize_key($status);
@@ -257,10 +262,19 @@ class AuthApply {
if (in_array($status, ['rejected', 'cancelled'], true) && $note === '') {
return new \WP_Error('aksrt_verify_note', __('请填写处理原因', 'aksrt'));
}
- $result = (new TransitionService($repo))->transition($application, $status, [
- 'review_note' => $note,
- 'reviewer_id' => $reviewer_id,
- ], ['source' => 'admin', 'event_type' => 'manual_review', 'actor_user_id' => $reviewer_id]);
+ $fields = [];
+ foreach (['public_name', 'public_desc'] as $key) {
+ if (array_key_exists($key, $profile_fields)) {
+ $fields[$key] = (string) $profile_fields[$key];
+ }
+ }
+ $fields['review_note'] = $note;
+ $fields['reviewer_id'] = $reviewer_id;
+ $result = (new TransitionService($repo))->transition($application, $status, $fields, [
+ 'source' => 'admin',
+ 'event_type' => 'manual_review',
+ 'actor_user_id' => $reviewer_id,
+ ]);
return is_wp_error($result) ? $result : ['status' => $status, 'reviewed_at' => (string) $result['completed_at']];
}
@@ -279,14 +293,170 @@ class AuthApply {
}
public function render_admin_profile_status(\WP_User $user): void {
- $status = self::get_status((int) $user->ID);
- $info = self::get_auth_info((int) $user->ID);
+ $user_id = (int) $user->ID;
+ $snapshot = self::snapshot($user_id);
+ $application = is_array($snapshot['verified'] ?? null)
+ ? $snapshot['verified']
+ : (is_array($snapshot['latest'] ?? null) ? $snapshot['latest'] : null);
+ $raw_status = (string) ($application['status'] ?? '');
+ $can_manage = $application !== null
+ && current_user_can('aksrt_review_identity')
+ && current_user_can('edit_user', $user_id);
+ $allowed_actions = array_values(array_intersect(
+ TransitionService::allowed_targets($raw_status),
+ ['verified', 'rejected', 'cancelled']
+ ));
+ $public_name = (string) ($application['public_name'] ?? '');
+ $public_desc = (string) ($application['public_desc'] ?? '');
?>
snapshot_for_user($user_id);
+ $application = is_array($snapshot['verified'] ?? null)
+ ? $snapshot['verified']
+ : (is_array($snapshot['latest'] ?? null) ? $snapshot['latest'] : null);
+ if ($application === null) {
+ return;
+ }
+ $application_uuid = sanitize_text_field((string) wp_unslash($_POST['aksrt_identity_application_uuid'] ?? ''));
+ if ($application_uuid === '' || !hash_equals((string) $application['application_uuid'], $application_uuid)) {
+ $this->set_admin_profile_notice('error', __('身份认证记录已变化,请刷新后重试。', 'aksrt'));
+ return;
+ }
+
+ $public_name = wp_html_excerpt(sanitize_text_field((string) wp_unslash($_POST['aksrt_identity_public_name'] ?? '')), 64, '');
+ $public_desc = wp_html_excerpt(sanitize_textarea_field((string) wp_unslash($_POST['aksrt_identity_public_desc'] ?? '')), 300, '');
+ $action = sanitize_key((string) wp_unslash($_POST['aksrt_identity_action'] ?? ''));
+ $note = sanitize_textarea_field((string) wp_unslash($_POST['aksrt_identity_review_note'] ?? ''));
+ $fields = [
+ 'public_name' => $public_name,
+ 'public_desc' => $public_desc,
+ ];
+
+ if ($action === '') {
+ $updated = $repo->update((int) $application['id'], $fields);
+ $this->set_admin_profile_notice($updated ? 'success' : 'error', $updated ? __('身份认证资料已更新。', 'aksrt') : __('身份认证资料更新失败。', 'aksrt'));
+ return;
+ }
+
+ $allowed = TransitionService::allowed_targets((string) $application['status']);
+ if (!in_array($action, $allowed, true) || !in_array($action, ['verified', 'rejected', 'cancelled'], true)) {
+ $this->set_admin_profile_notice('error', __('当前认证状态不能执行该操作。', 'aksrt'));
+ return;
+ }
+ if ($action === 'verified' && $public_name === '') {
+ $this->set_admin_profile_notice('error', __('通过认证时请填写认证身份。', 'aksrt'));
+ return;
+ }
+ if (in_array($action, ['rejected', 'cancelled'], true) && $note === '') {
+ $this->set_admin_profile_notice('error', __('驳回或取消认证时请填写处理说明。', 'aksrt'));
+ return;
+ }
+
+ $result = self::review($user_id, $application_uuid, $action, $note, get_current_user_id(), $fields);
+ $this->set_admin_profile_notice(
+ is_wp_error($result) ? 'error' : 'success',
+ is_wp_error($result) ? $result->get_error_message() : __('身份认证已更新。', 'aksrt')
+ );
+ }
+
+ public function render_admin_profile_notice(): void {
+ $key = 'aksrt_identity_profile_notice_' . get_current_user_id();
+ $notice = get_transient($key);
+ if (!is_array($notice) || empty($notice['message'])) {
+ return;
+ }
+ delete_transient($key);
+ $type = ($notice['type'] ?? '') === 'success' ? 'success' : 'error';
+ echo '' . esc_html((string) $notice['message']) . ' ';
+ }
+
+ private function set_admin_profile_notice(string $type, string $message): void {
+ set_transient('aksrt_identity_profile_notice_' . get_current_user_id(), [
+ 'type' => $type,
+ 'message' => $message,
+ ], 60);
+ }
+
+ private static function admin_status_label(string $status): string {
+ $labels = [
+ 'created' => __('已创建', 'aksrt'),
+ 'provider_pending' => __('等待核身', 'aksrt'),
+ 'provider_processing' => __('云端处理中', 'aksrt'),
+ 'provider_failed' => __('云认证失败', 'aksrt'),
+ 'provider_unsupported' => __('云端不支持', 'aksrt'),
+ 'provider_expired' => __('会话已过期', 'aksrt'),
+ 'manual_pending' => __('人工待审', 'aksrt'),
+ 'verified' => __('已认证', 'aksrt'),
+ 'rejected' => __('已驳回', 'aksrt'),
+ 'cancelled' => __('已取消', 'aksrt'),
+ ];
+ return $labels[$status] ?? $status;
+ }
+
+ private static function admin_action_label(string $action): string {
+ $labels = [
+ 'verified' => __('通过认证', 'aksrt'),
+ 'rejected' => __('驳回申请', 'aksrt'),
+ 'cancelled' => __('取消认证', 'aksrt'),
+ ];
+ return $labels[$action] ?? $action;
+ }
}
diff --git a/src/User/BalanceAdmin.php b/src/User/BalanceAdmin.php
index c669c31d..f464221a 100644
--- a/src/User/BalanceAdmin.php
+++ b/src/User/BalanceAdmin.php
@@ -80,7 +80,6 @@ class BalanceAdmin {
}
$balance_minor = \AKSRT\Ledger\LedgerService::get_instance()->balance((int) $user->ID, \AKSRT\Ledger\AssetType::BALANCE);
$can = $this->can_manage();
- $log = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['user_id' => (int) $user->ID, 'asset' => 'balance', 'page' => 1, 'per_page' => 8]);
?>
@@ -105,28 +104,6 @@ class BalanceAdmin {
|
-