diff --git a/assets/css/routes/sign.css b/assets/css/routes/sign.css index ee51c7f9..5bfd96eb 100644 --- a/assets/css/routes/sign.css +++ b/assets/css/routes/sign.css @@ -38,6 +38,8 @@ object-fit: cover; } +/* The shared sheet leaves the modal close button in normal flow, so it would + * push the card content down. */ #u_sign .sign > .close { position: absolute; top: 10px; @@ -46,6 +48,12 @@ font-size: 18px; } +/* .fa sets display:inline-block, which outranks the UA [hidden] rule, so every + * hidden glyph (spinner, password eye) stayed visible without this. */ +.sign [hidden] { + display: none !important; +} + body.auth-modal-open { overflow: hidden; } @@ -90,6 +98,7 @@ body.auth-modal-open { z-index: 2; } +/* ---- card internals ---- */ .sign .sign-passw { border: 0; background: none; @@ -124,25 +133,10 @@ body.auth-modal-open { color: #ff5473; } -@media (max-width: 991px) { - #u_sign .modal-dialog, - #u_sign.has-sign-img .modal-dialog { - width: auto; - margin: 30px; - } -} - -@media (max-width: 767px) { - .sign-page { - padding-top: 20px; - } - - .sign-row { - min-height: calc(100vh - 110px); - } - - .sign-page .sign { - width: 340px; - max-width: 100%; +/* Between the 992px split and the 640px collapse the shared sheet still offsets + * the card by 55%, but the dialog has already shrunk — give the card the room. */ +@media (max-width: 991px) and (min-width: 641px) { + #u_sign .sign-img + .sign { + margin-left: 45%; } } diff --git a/inc/helpers/homepage/header-components.php b/inc/helpers/homepage/header-components.php index a59e85c6..8d309556 100644 --- a/inc/helpers/homepage/header-components.php +++ b/inc/helpers/homepage/header-components.php @@ -53,6 +53,12 @@ if (!function_exists('jio_header_slide_current_page_type')) { * opt out entirely, like the excluded templates. */ function jio_header_slide_current_page_type(): string { + // The /sign/ route is `index.php?jio_sign=1`, which WordPress reports as + // home — the auth surface must never inherit the home component scope. + // (Pages using the sign template are already excluded further down.) + if ((string) get_query_var('jio_sign') !== '') { + return ''; + } if ((string) get_query_var('jio_go_redirect') !== '') { return ''; } diff --git a/templates/parts/auth-content.php b/templates/parts/auth-content.php index 2689a674..9efe71cc 100644 --- a/templates/parts/auth-content.php +++ b/templates/parts/auth-content.php @@ -63,14 +63,16 @@ $oauth_bind_pass = $oauth_intent === 'bind' : ''; $initial_tab = $auth_tab; -if ($initial_tab === 'signin' && $close_signin && $registration_open) { - $initial_tab = 'signup'; +if ($initial_tab === 'signin' && $close_signin) { + // Account login is off: land on registration when it is open, otherwise on + // the social/QR pane so the modal never opens on an empty sign-in panel. + $initial_tab = $registration_open ? 'signup' : ($wechat_qr ? 'oauth' : 'signin'); } if ($initial_tab === 'signup' && !$registration_open) { $initial_tab = 'signin'; } if ($initial_tab === 'oauth' && !$wechat_qr) { - $initial_tab = 'signin'; + $initial_tab = $close_signin && $registration_open ? 'signup' : 'signin'; } if ($initial_tab === 'bind' && !$is_oauth_bind) { $initial_tab = 'signin'; @@ -81,7 +83,7 @@ $show_pas = !$passwordless || $passwordless_mode !== 'only_nopas'; $nopas_active = $show_nopas && $passwordless_mode !== 'pas'; $signin_user_hint = ($passwordless || $signin_phone) ? __('用户名/手机号/邮箱', 'jio') : __('用户名或邮箱', 'jio'); $social_html = ''; -if (!$is_oauth_bind && !$close_signin && !empty($oauth_providers) && class_exists('\Jio\Auth\OAuth')) { +if (!$is_oauth_bind && !empty($oauth_providers) && class_exists('\Jio\Auth\OAuth')) { $social_html = \Jio\Auth\OAuth::get_instance()->render_social_buttons(__('社交账号登录', 'jio')); } $ref_tooltip = $ref_hint !== '' ? wp_strip_all_tags($ref_hint) : ''; @@ -96,7 +98,24 @@ $invite_tooltip = ($invite_mode === 'optional' && $invite_hint !== '') ? wp_stri
- + +
+
+
+
+
+
+ +
> +
+
+ +
+
+ +
+
+
>
diff --git a/tests/widget-system/auth-source-contract.test.cjs b/tests/widget-system/auth-source-contract.test.cjs index 44fb29cb..36b83a38 100644 --- a/tests/widget-system/auth-source-contract.test.cjs +++ b/tests/widget-system/auth-source-contract.test.cjs @@ -41,7 +41,8 @@ test('authentication shell reuses the shared sign-card CSS contract', () => { assert.match(mainCss, /\.signin-qrcode-img\s*\{[\s\S]*?width:\s*180px/); assert.match(mainCss, /#u_sign \.modal-dialog\s*\{\s*width:\s*800px;/); assert.match(signCss, /\.sign-page \.sign\s*\{\s*width:\s*350px/); - assert.match(signCss, /@media \(max-width:\s*767px\)[\s\S]*?\.sign-page \.sign\s*\{[\s\S]*?width:\s*340px/); + // Hidden glyphs must stay hidden even though .fa forces display:inline-block. + assert.match(signCss, /\.sign \[hidden\]\s*\{\s*display:\s*none !important;/); }); test('authentication settings use reference defaults and canonical keys', () => { diff --git a/tests/widget-system/header-multifunction-render-harness.php b/tests/widget-system/header-multifunction-render-harness.php index e9f8f622..876446c6 100644 --- a/tests/widget-system/header-multifunction-render-harness.php +++ b/tests/widget-system/header-multifunction-render-harness.php @@ -34,7 +34,8 @@ namespace { function is_search(): bool { return false; } function is_page(): bool { return false; } function is_home(): bool { return false; } - function get_query_var(string $key) { return ''; } + $GLOBALS['jio_query_vars'] = []; + function get_query_var(string $key) { return $GLOBALS['jio_query_vars'][$key] ?? ''; } function sanitize_key($value): string { return preg_replace('/[^a-z0-9_-]/', '', strtolower((string) $value)); } function sanitize_html_class($value): string { return preg_replace('/[^a-zA-Z0-9_-]/', '', (string) $value); } function wp_parse_args($args, array $defaults = []): array { return array_merge($defaults, is_array($args) ? $args : []); } @@ -111,6 +112,16 @@ namespace { 'button' => true, ]); + // /sign/ is `index.php?jio_sign=1`, so is_front_page() stays true. The auth + // surface must not inherit the home scope. + $GLOBALS['jio_query_vars']['jio_sign'] = '1'; + $auth_page_show = jio_header_slide_is_show(); + $auth_page_type = jio_header_slide_current_page_type(); + ob_start(); + jio_header_slide(); + $auth_page_markup = (string) ob_get_clean(); + $GLOBALS['jio_query_vars']['jio_sign'] = ''; + require_once dirname(__DIR__, 2) . '/src/Admin/PageConfigMetaBox.php'; $sanitize_cards = new \ReflectionMethod('Jio\\Admin\\PageConfigMetaBox', 'sanitize_card_options'); $page_config_save = $sanitize_cards->invoke(null, ['show_widget_bg' => true, 'cards' => []]); @@ -122,5 +133,8 @@ namespace { 'lazy_disabled' => $lazy_disabled, 'single_slide' => $single_slide, 'page_config_save' => $page_config_save, + 'auth_page_show' => $auth_page_show, + 'auth_page_type' => $auth_page_type, + 'auth_page_markup' => $auth_page_markup, ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } diff --git a/tests/widget-system/header-multifunction-render.test.cjs b/tests/widget-system/header-multifunction-render.test.cjs index aed31fd4..826a1225 100644 --- a/tests/widget-system/header-multifunction-render.test.cjs +++ b/tests/widget-system/header-multifunction-render.test.cjs @@ -42,6 +42,13 @@ test('header multifunction renders reference slide, search, and card contracts o assert.match(moduleBackground, /
Card one<\/div>/); assert.equal(JSON.parse(rendered.stdout).page_config_save.show_widget_bg, true); + // /sign/ resolves to index.php?jio_sign=1, so WordPress still reports it as + // home; the component must stay off even when "首页" is in its scope list. + const { auth_page_show: authShow, auth_page_type: authType, auth_page_markup: authMarkup } = JSON.parse(rendered.stdout); + assert.equal(authShow, false); + assert.equal(authType, ''); + assert.equal(authMarkup, ''); + const { lazy_disabled: eager, single_slide: single } = JSON.parse(rendered.stdout); assert.match(eager, /