diff --git a/assets/admin/src/pages/extensions/ExtensionSecurity.vue b/assets/admin/src/pages/extensions/ExtensionSecurity.vue index d6206433..2b148ab5 100644 --- a/assets/admin/src/pages/extensions/ExtensionSecurity.vue +++ b/assets/admin/src/pages/extensions/ExtensionSecurity.vue @@ -235,10 +235,16 @@ async function handleTestIp() { async function handleTestAudit() { auditTest.value.loading = true + auditTest.value.result = '' try { - const res = await api.testContentAudit(auditTest.value.text) - auditTest.value.result = JSON.stringify(res?.data || {}, null, 2) - message.success('内容审核测试完成') + const res = await api.testContentAudit(String(auditTest.value.text || '').trim()) + const data = res?.data || {} + auditTest.value.result = JSON.stringify(data, null, 2) + if (data.ok) { + message.success(data.message || '内容审核测试完成') + } else { + message.warning(data.message || '内容审核未通过或配置异常') + } } catch (err) { message.error(err?.message || '内容审核测试失败') } finally { diff --git a/inc/classes/admin/class-aksrt-admin-extension-controller.php b/inc/classes/admin/class-aksrt-admin-extension-controller.php index 206450e6..588c8218 100644 --- a/inc/classes/admin/class-aksrt-admin-extension-controller.php +++ b/inc/classes/admin/class-aksrt-admin-extension-controller.php @@ -346,6 +346,9 @@ class AKSRT_Admin_Extension_Controller extends AKSRT_Admin_Controller_Base { /** * POST /extensions/audit-test — test text content against current audit provider. + * + * Admin tests force a live provider call (skip enable gates + failure allow policy) + * so operators can verify credentials before flipping runtime switches. */ public function test_content_audit(WP_REST_Request $request): WP_REST_Response { $params = $this->get_json_params($request); @@ -359,12 +362,72 @@ class AKSRT_Admin_Extension_Controller extends AKSRT_Admin_Controller_Base { return $this->error(__('内容审核服务不可用', 'aksrt'), 500); } - $result = AKSRT_Content_Audit::get_instance()->audit_text($text); + $audit = AKSRT_Content_Audit::get_instance(); + $status = $audit->get_status(); + $result = $audit->audit_text($text, true); + + $reason = (string) ($result['reason'] ?? ''); + $message = ''; + $ok = !empty($result['passed']); + + // config/api 错误时 passed=false 且 reason 是机器码,需要可读提示 + $error_reasons = ['config_missing', 'api_error', 'file_error', 'disabled']; + $is_error = in_array($reason, $error_reasons, true) + || (str_starts_with($reason, 'config_') && $reason !== ''); + + if ($is_error || (!$ok && $reason !== '')) { + switch ($reason) { + case 'config_missing': + if (!empty($status['missing_fields'])) { + $message = sprintf( + /* translators: %s: missing config field keys */ + __('当前审核服务商凭据不完整(缺少:%s),请先在「扩展 → 内容审核」补全配置。', 'aksrt'), + implode(', ', (array) $status['missing_fields']) + ); + } else { + $message = __('审核服务商凭据缺失,请先补全 API Key / Secret。', 'aksrt'); + } + $ok = false; + break; + case 'api_error': + $message = __('调用审核接口失败,请检查凭据、网络出口或服务商状态。', 'aksrt'); + $ok = false; + break; + case 'disabled': + $message = __('内容审核功能未启用。', 'aksrt'); + $ok = false; + break; + case 'non_compliant': + $message = __('审核结论:不合规(已拦截)。', 'aksrt'); + break; + case 'suspected': + $message = __('审核结论:疑似违规。', 'aksrt'); + break; + case 'review_failed': + $message = __('审核结论:服务商审核失败。', 'aksrt'); + break; + default: + if (!$ok) { + $message = $reason !== '' + ? sprintf(/* translators: %s: provider reason */ __('审核未通过:%s', 'aksrt'), $reason) + : __('审核未通过。', 'aksrt'); + } + } + } elseif ($ok) { + if ($reason === 'passthrough' || $reason === '') { + $message = __('审核通过。', 'aksrt'); + } else { + $message = sprintf(/* translators: %s: provider reason */ __('审核通过(%s)。', 'aksrt'), $reason); + } + } return $this->success([ 'data' => [ - 'text' => $text, - 'result' => $result, + 'text' => $text, + 'ok' => $ok, + 'message' => $message, + 'status' => $status, + 'result' => $result, ], ]); } diff --git a/inc/classes/class-aksrt-content-audit.php b/inc/classes/class-aksrt-content-audit.php index 29e796bf..2bcc24c3 100644 --- a/inc/classes/class-aksrt-content-audit.php +++ b/inc/classes/class-aksrt-content-audit.php @@ -24,23 +24,34 @@ class AKSRT_Content_Audit { /** * 审核文本内容 * + * @param string $text 待审文本 + * @param bool $force 管理端测试用:跳过启用开关与失败放行策略,直接打服务商 * @return array{passed: bool, reason: string, labels: array, raw: array} */ - public function audit_text(string $text): array { + public function audit_text(string $text, bool $force = false): array { $config = $this->get_config(); - if (empty($config['content_audit_enabled']) || empty($config['content_audit_text_enabled'])) { + if ( + !$force + && (empty($config['content_audit_enabled']) || empty($config['content_audit_text_enabled'])) + ) { return $this->ok('disabled'); } $provider = sanitize_key((string) ($config['content_audit_provider'] ?? 'baidu')); $result = $this->call_text_api($provider, $text, $config); - if (!empty($config['content_audit_log_enabled'])) { + // 管理端强制测试不写生产日志,避免污染审计流水 + if (!$force && !empty($config['content_audit_log_enabled'])) { $this->log_audit('text', $text, $result); } - if (!$result['passed'] && ($config['content_audit_on_failure'] ?? 'allow') === 'allow') { + // 管理端强制测试保留服务商原始结论,不套用 on_failure=allow + if ( + !$force + && !$result['passed'] + && ($config['content_audit_on_failure'] ?? 'allow') === 'allow' + ) { $result['passed'] = true; $result['reason'] .= ' (failure_policy: allow)'; }