+ */
+function aksrt_captcha_sanitize_scene_list($raw): array {
+ $list = is_array($raw) ? $raw : [];
+ $clean = [];
+ foreach ($list as $scene) {
+ $scene = sanitize_key((string) $scene);
+ if ($scene !== '' && array_key_exists($scene, aksrt_captcha_scenes()) && !in_array($scene, $clean, true)) {
+ $clean[] = $scene;
+ }
+ }
+ return array_values($clean);
+}
+
/**
* 获取人机验证完整配置(规范化,不合并历史脏键)。
*
@@ -68,20 +90,26 @@ function aksrt_get_captcha_config(): array {
$cfg = [];
}
- $default = aksrt_captcha_default_config();
+ $all_scenes = array_keys(aksrt_captcha_scenes());
$provider = isset($cfg['active_provider']) ? sanitize_key((string) $cfg['active_provider']) : '';
if (!in_array($provider, aksrt_captcha_providers(), true)) {
$provider = '';
}
- $disabled = isset($cfg['disabled_scenarios']) ? (array) $cfg['disabled_scenarios'] : [];
- $disabled = array_values(array_filter(array_map('sanitize_key', $disabled), function ($s) {
- return array_key_exists($s, aksrt_captcha_scenes());
- }));
+ if (array_key_exists('enabled_scenarios', $cfg)) {
+ // Explicit positive list (may be empty = no scenes).
+ $enabled = aksrt_captcha_sanitize_scene_list($cfg['enabled_scenarios']);
+ } else {
+ // Legacy: only disabled list stored → all minus disabled.
+ $disabled_legacy = aksrt_captcha_sanitize_scene_list($cfg['disabled_scenarios'] ?? []);
+ $enabled = array_values(array_diff($all_scenes, $disabled_legacy));
+ }
+ $disabled = array_values(array_diff($all_scenes, $enabled));
$result = [
'enabled' => !empty($cfg['enabled']),
'active_provider' => $provider,
+ 'enabled_scenarios' => $enabled,
'disabled_scenarios' => $disabled,
];
foreach (aksrt_captcha_providers() as $p) {
@@ -146,7 +174,11 @@ function aksrt_is_captcha_enabled_for($scene): bool {
return false;
}
- return !in_array($scene, $cfg['disabled_scenarios'], true);
+ $enabled = isset($cfg['enabled_scenarios']) && is_array($cfg['enabled_scenarios'])
+ ? $cfg['enabled_scenarios']
+ : array_values(array_diff(array_keys(aksrt_captcha_scenes()), (array) ($cfg['disabled_scenarios'] ?? [])));
+
+ return in_array($scene, $enabled, true);
}
/**
@@ -546,7 +578,7 @@ function aksrt_render_captcha($scene = 'comment') {
echo '';
echo esc_html(sprintf(
/* translators: %s: captcha provider key */
- __('人机验证服务商「%s」已启用但凭据未配齐,前台已跳过渲染。请到「功能&权限 → 登录权限」补全配置。', 'aksrt'),
+ __('人机验证服务商「%s」已启用但凭据未配齐,前台已跳过渲染。请到「功能&权限 → 人机验证」补全配置。', 'aksrt'),
$provider
));
echo '
';
@@ -701,7 +733,7 @@ function submitForm(){
verified=true; hField.value='1';
if(C.scene==='download') syncDownloadSiblings(true);
if(typeof pendingAction==='function'){
- var action=pendingAction; pendingAction=null; action(); return;
+ finishPending(true); return;
}
setTimeout(resetVerificationState, 3000);
submitNativeForm();
@@ -717,18 +749,24 @@ function showTip(msg, color){
function showLoading(){ box.innerHTML='验证码加载中...
'; }
function clearLoading(){ box.innerHTML=''; }
-root.scenes[C.scene]={
+function finishPending(ok){
+ var action=pendingAction; pendingAction=null;
+ if(typeof action==='function'){ action(!!ok); }
+ }
+
+ function cancelPending(msg){
+ if(msg) showTip(msg, '#e67e22');
+ finishPending(false);
+ }
+
+ root.scenes[C.scene]={
verify:function(callback){
- var retry=0;
- function run(){
- if(verified || hField.value==='1'){
- if(typeof callback==='function') callback();
- return;
- }
- pendingAction=(typeof callback==='function')?callback:null;
- triggerCaptcha();
+ if(verified || hField.value==='1'){
+ if(typeof callback==='function') callback(true);
+ return;
}
- run();
+ pendingAction=(typeof callback==='function')?function(ok){ callback(ok!==false); }:null;
+ triggerCaptcha();
},
reset:resetVerificationState
};
@@ -744,7 +782,7 @@ function loadTencent(){
triggerCaptcha=function(){
if(!capIns){
capIns=new TencentCaptcha(C.tc.app_id, function(res){
- if(res.ret===2) return;
+ if(res.ret===2){ cancelPending('已取消验证'); return; }
if(res.ret===0 && res.ticket){
if(res.ticket.indexOf('trerror_')===0){
showTip('验证码服务异常,请刷新页面重试', '#e67e22'); return;
@@ -803,7 +841,7 @@ function loadCloudflare(){
'';
document.body.appendChild(cfModal);
- var cancelFn=function(){ cfVerifying=false; closeModal(); showTip('验证码已取消', '#e67e22'); };
+ var cancelFn=function(){ cfVerifying=false; closeModal(); cancelPending('已取消验证'); };
cfModal.querySelector('.aksrt-captcha-modal-backdrop').addEventListener('click', cancelFn);
cfModal.querySelector('.aksrt-captcha-modal-close').addEventListener('click', cancelFn);
renderWidget();
@@ -828,7 +866,7 @@ function loadGeetest(){
var product=(C.gt && C.gt.product) ? String(C.gt.product) : 'bind';
if(!captchaId){
clearLoading();
- showTip('极验 Captcha ID 未配置,请到后台「功能&权限 → 登录权限」填写并保存', '#e74c3c');
+ showTip('极验 Captcha ID 未配置,请到后台「功能&权限 → 人机验证」填写并保存', '#e74c3c');
return;
}
function render(){