修复了一些一些已知问题

This commit is contained in:
2026-08-21 12:35:55 +08:00
parent d69334b37d
commit 3e6af7863d
7 changed files with 178 additions and 38 deletions
+124
View File
@@ -5,6 +5,130 @@
* owns AKSRT-specific account content such as check-in, wallet and VIP rows.
*/
/* The desktop action cluster owns one horizontal alignment context. */
.navbar-top .aksrt-navbar-actions {
display: flex;
align-items: center;
gap: 10px;
min-height: 50px;
margin-top: 0;
margin-bottom: 0;
padding: 0;
}
.navbar-top .aksrt-navbar-actions > *,
.navbar-top .aksrt-navbar-account,
.navbar-top .aksrt-navbar-account > li {
display: inline-flex;
align-items: center;
flex: 0 0 auto;
}
.navbar-top .aksrt-navbar-account {
gap: 4px;
min-height: 50px;
margin: 0;
}
.navbar-top .aksrt-navbar-account.navbar-text {
float: none;
}
.navbar-top .aksrt-navbar-actions .navbar-cta {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 4px;
min-height: 29px;
margin: 0;
padding: .3em 1em !important;
border-radius: var(--radius-btn, 4px);
font-size: .8em;
line-height: 1.44;
}
.navbar-top .aksrt-navbar-actions .navbar-cta.radius {
border-radius: 50px;
}
.navbar-top .aksrt-nav-icon,
.navbar-top .aksrt-nav-avatar {
display: inline-flex !important;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
padding: 0 !important;
overflow: visible !important;
border: 0 !important;
border-radius: 0;
background: transparent !important;
box-shadow: none !important;
}
.navbar-top .aksrt-nav-icon .icon {
width: 1.2em;
height: 1.2em;
}
.navbar-top .aksrt-nav-avatar {
margin-top: 0;
}
.navbar-top .aksrt-nav-avatar .avatar {
display: block;
width: 29px;
height: 29px;
border-radius: 50%;
object-fit: cover;
}
.navbar-top .aksrt-navbar-actions .toggle-radius {
flex: 0 0 29px;
margin: 0;
vertical-align: middle;
}
.navbar-top .aksrt-navbar-language {
margin: 0;
}
/* The full search surface must sit above a fixed header (z-index: 999). */
.navbar-search {
z-index: 1001;
height: 100%;
overflow: hidden;
}
.navbar-search > .container {
position: relative;
height: 100%;
max-height: 100%;
padding-bottom: 76px;
overflow-y: auto;
}
.navbar-search .search-close-box {
position: fixed;
right: max(30px, calc((100vw - var(--container, 1200px)) / 2 + 30px));
bottom: 24px;
z-index: 2;
width: auto;
max-width: none;
margin: 0;
}
.navbar-search .search-close-box > .but {
float: none;
}
@media (max-width: 767.98px) {
.navbar-search .search-close-box {
right: 15px;
bottom: calc(15px + env(safe-area-inset-bottom, 0px));
}
}
.aksrt-header-userbox {
width: 260px;
color: var(--color-ink-2);
@@ -103,9 +103,9 @@ if (!function_exists('aksrt_footer_navbar_search')) :
echo '<div mini-touch="nav_search" touch-direction="top" class="main-search fixed-body main-bg box-body navbar-search nopw-sm">';
echo '<div class="container">';
echo '<div class="mb20 search-close-box"><button type="button" class="but cir" data-toggle-class data-target=".navbar-search" aria-label="'
. esc_attr__('关闭搜索', 'aksrt') . '"><svg class="ic-close" aria-hidden="true"><use xlink:href="#icon-close"></use></svg></button></div>';
echo $remote; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<div class="search-close-box"><button type="button" class="but cir" data-toggle-class data-target=".navbar-search" aria-label="'
. esc_attr__('关闭搜索', 'aksrt') . '"><svg class="ic-close" aria-hidden="true"><use xlink:href="#icon-close"></use></svg></button></div>';
echo '</div></div>';
}
endif;
+17 -31
View File
@@ -197,14 +197,10 @@ if (!function_exists('aksrt_header_user_box_html')) :
}
if (!empty($ctx['can_publish'])) {
$pub_text = (string) ($ctx['settings']['nav_user_newposts_btn_text'] ?? '');
if ($pub_text === '') {
$pub_text = __('发布内容', 'aksrt');
}
$pub_url = (string) $ctx['publish_url'];
$href .= '<a rel="nofollow" href="' . esc_url($pub_url) . '">';
$href .= '<div class="badg mb6 toggle-radius c-green"><i class="fa fas fa-edit" aria-hidden="true"></i></div>';
$href .= '<div class="c-green">' . esc_html($pub_text) . '</div></a>';
$href .= '<div class="c-green">' . esc_html__('发布内容', 'aksrt') . '</div></a>';
}
$href .= '<a href="javascript:;" data-toggle="modal" data-target="#modal_signout">';
@@ -289,29 +285,23 @@ if (!function_exists('aksrt_menu_button')) :
function aksrt_menu_button(array $ctx): void {
$layout = (string) ($ctx['layout'] ?? '1');
$user_id = (int) ($ctx['user_id'] ?? 0);
$button = '';
$actions = '';
// Publish and membership actions.
if (function_exists('aksrt_render_header_menu_buttons')) {
$action_buttons = aksrt_render_header_menu_buttons();
if ($action_buttons !== '') {
$button .= '<div class="navbar-form navbar-right navbar-but">' . $action_buttons . '</div>';
}
$actions = aksrt_render_header_menu_buttons();
}
// Theme toggle.
$radius_but = '';
$utility_buttons = '';
if (in_array('pc_nav', (array) ($ctx['theme_positions'] ?? []), true)) {
$radius_but .= '<a href="javascript:;" class="toggle-theme toggle-radius" id="theme-toggle-desktop" title="'
$utility_buttons .= '<a href="javascript:;" class="toggle-theme toggle-radius" id="theme-toggle-desktop" title="'
. esc_attr__('切换亮暗色', 'aksrt') . '">';
$radius_but .= '<i class="fa fas fa-toggle-theme" aria-hidden="true"></i>';
$radius_but .= '</a>';
$utility_buttons .= '<i class="fa fas fa-toggle-theme" aria-hidden="true"></i>';
$utility_buttons .= '</a>';
}
if (function_exists('aksrt_get_translate_language_btn')) {
$radius_but .= aksrt_get_translate_language_btn('ml10 pull-right');
}
if ($radius_but !== '') {
$button .= '<div class="navbar-form navbar-right flex ac">' . $radius_but . '</div>';
$utility_buttons .= aksrt_get_translate_language_btn('aksrt-navbar-language');
}
// User + search.
@@ -320,7 +310,7 @@ if (!function_exists('aksrt_menu_button')) :
if ('2' === $layout) {
if ($user_id > 0) {
$avatar = aksrt_get_avatar_html($user_id, 36, ['class' => 'avatar']);
$sign_but = '<li><a href="javascript:;" class="navbar-avatar">' . $avatar . '</a><ul class="sub-menu">'
$sign_but = '<li><a href="javascript:;" class="navbar-avatar aksrt-nav-avatar">' . $avatar . '</a><ul class="sub-menu">'
. $user_sub . '</ul></li>';
} else {
$sign_but = '<li><a href="javascript:;" class="signin-loader">' . esc_html__('登录', 'aksrt') . '</a></li>';
@@ -329,7 +319,7 @@ if (!function_exists('aksrt_menu_button')) :
}
}
} else {
$cls = 'btn' . ($user_id > 0 ? '' : ' signin-loader');
$cls = 'aksrt-nav-icon' . ($user_id > 0 ? '' : ' signin-loader');
$sign_but = '<li><a href="javascript:;" class="' . esc_attr($cls) . '">'
. '<svg class="icon" aria-hidden="true"><use xlink:href="#icon-user"></use></svg></a>'
. '<ul class="sub-menu">' . $user_sub . '</ul></li>';
@@ -337,25 +327,21 @@ if (!function_exists('aksrt_menu_button')) :
$search_but = '';
if ('2' !== $layout) {
$search_but = '<li class="relative"><a href="javascript:;" class="btn nav-search-btn main-search-btn" aria-label="'
$search_but = '<li class="relative"><a href="javascript:;" class="aksrt-nav-icon nav-search-btn main-search-btn" aria-label="'
. esc_attr__('打开搜索', 'aksrt') . '"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-search"></use></svg></a></li>';
}
$right_but = '<div class="navbar-form navbar-right'
. ($user_id <= 0 && '2' === $layout ? ' navbar-text' : '') . '">';
$right_but .= '<ul class="list-inline splitters relative">'
. $sign_but . $search_but . '</ul></div>';
$account = '<ul class="list-inline splitters relative aksrt-navbar-account'
. ($user_id <= 0 && '2' === $layout ? ' navbar-text' : '') . '">'
. $sign_but . $search_but . '</ul>';
$button = '<div class="aksrt-navbar-actions navbar-form navbar-right">'
. $actions . $utility_buttons . $account . '</div>';
$fold = '<div class="navbar-form navbar-right hide show-nav-but" style="margin-right:-10px;">'
. '<a data-toggle-class data-target=".nav.navbar-nav" href="javascript:;" class="but" aria-label="'
. esc_attr__('展开菜单', 'aksrt') . '"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-menu_2"></use></svg></a></div>';
$html = $fold;
if ('3' === $layout) {
$html .= $right_but . $button;
} else {
$html .= $button . $right_but;
}
$html = $fold . $button;
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
-2
View File
@@ -54,8 +54,6 @@ class SchemaPageDisplay {
self::field('nav_newposts_radius', '按钮圆角', 'switcher', true, ['dependsOn' => self::enabled('nav_newposts')]),
self::field('nav_newposts_class', '按钮颜色', 'palette', 'jb-blue', ['dependsOn' => self::enabled('nav_newposts'), 'options' => self::zib_palette()]),
self::field('nav_newposts_text', '按钮文案', 'textarea', '<i class="fa fa-fw fa-pencil"></i>发布', ['dependsOn' => self::enabled('nav_newposts'), 'sanitize_type' => 'html', 'rows' => 1]),
self::field('nav_user_newposts_btn', '导航栏用户卡片发布按钮', 'select', 'post', ['options' => self::options(['post' => '文章'])]),
self::field('nav_user_newposts_btn_text', '按钮文字', 'text', '发布文章'),
]);
}
+1 -1
View File
@@ -24,7 +24,7 @@ final class FrontendRenderer {
AssetManager::enqueue_for($definition);
$classes = ['aksrt-widget', 'zib-widget-wrap', 'aksrt-widget--' . $definition->slug(), 'aksrt-widget--' . $definition->size()];
if ($definition->size() === 'sidebar') {
if ($definition->size() === 'sidebar' && $definition->slug() !== 'user_card') {
$classes[] = 'zib-widget';
}
$device_class = WidgetVisibility::device_class($instance);
+1 -1
View File
@@ -58,7 +58,7 @@ final class UserRenderer {
if (!empty($i['show_cover'])) {
$html .= '<div class="aksrt-user-card__cover"' . ($cover ? ' style="background-image:url(' . esc_url($cover) . ')"' : '') . '></div>';
}
$html .= '<div class="aksrt-user-card__body"><a class="aksrt-user-card__avatar" href="' . esc_url($home) . '">' . (function_exists('aksrt_get_avatar_html') ? aksrt_get_avatar_html($user_id, 96) : get_avatar($user_id, 96)) . '</a><h3><a href="' . esc_url($home) . '">' . esc_html($user->display_name) . '</a>' . (function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($user_id) : '') . '</h3>';
$html .= '<div class="aksrt-user-card__body"><a class="aksrt-user-card__avatar" href="' . esc_url($home) . '">' . (function_exists('aksrt_get_avatar_html') ? aksrt_get_avatar_html($user_id, 96) : get_avatar($user_id, 96)) . '</a><h3><a href="' . esc_url($home) . '">' . esc_html($user->display_name) . '</a></h3>';
if (function_exists('aksrt_render_user_identity_chips')) {
$html .= '<div class="aksrt-user-card__identity">' . aksrt_render_user_identity_chips($user_id, 'widget') . '</div>';
}
@@ -16,6 +16,11 @@ const scriptsPart1c = read('src/Core/ScriptsPart1c.php')
const footerCss = read('assets/css/frontend/footer/zibll-shell.css')
const frontendBaseCss = read('assets/css/frontend/base.css')
const headerMenuButtons = read('inc/helpers/aksrt-header-menu-buttons.php')
const frontendRenderer = read('src/WidgetSystem/FrontendRenderer.php')
const userRenderer = read('src/WidgetSystem/Renderers/UserRenderer.php')
const headerNavbar = read('inc/helpers/header/aksrt-header-navbar.php')
const headerSearch = read('inc/helpers/header/aksrt-header-menu-search.php')
const headerCss = read('assets/css/frontend/header-userbox.css')
function activeRepositorySource() {
const roots = ['assets/admin/src', 'assets/js', 'inc', 'src', 'templates']
@@ -57,7 +62,6 @@ test('top-level field IDs match the Zibll V9.0 eight-page contract', () => {
'header_theme_custom', 'header_theme_bg_custom', 'header_theme_bg', 'header_theme_color_custom',
'header_layout', 'mobile_header_layout', 'mobile_navbar_align', 'nav_fixed', 'nav_scroll_down_hide',
'nav_newposts', 'nav_newposts_radius', 'nav_newposts_class', 'nav_newposts_text',
'nav_user_newposts_btn', 'nav_user_newposts_btn_text',
])
assert.deepEqual(topLevelFieldIds('header_components'), [
'header_slider_show', 'header_slider_show_type', 'header_slider_nav_color', 'header_slider',
@@ -201,6 +205,34 @@ test('header multifunction search keeps focus and submit alignment route-indepen
)
})
test('user profile widget owns its only card surface and keeps membership below the name', () => {
assert.match(frontendRenderer, /size\(\) === 'sidebar' && \$definition->slug\(\) !== 'user_card'/)
assert.match(userRenderer, /display_name\) \. '<\/a><\/h3>'/)
assert.match(userRenderer, /aksrt-user-card__identity.*aksrt_render_user_identity_chips\(\$user_id, 'widget'\)/s)
assert.doesNotMatch(userRenderer, /display_name\) \. '<\/a>' \. \(function_exists\('aksrt_render_vip_badge'/)
})
test('desktop header actions share one row without generic button masks', () => {
assert.match(headerNavbar, /aksrt-navbar-actions navbar-form navbar-right/)
assert.match(headerNavbar, /class="aksrt-nav-icon nav-search-btn main-search-btn"/)
assert.doesNotMatch(headerNavbar, /class="btn nav-search-btn main-search-btn"/)
assert.match(headerCss, /\.navbar-top \.aksrt-navbar-actions\s*\{[^}]*display:\s*flex;[^}]*align-items:\s*center;/s)
assert.match(headerCss, /\.navbar-top \.aksrt-nav-icon,[\s\S]*?background:\s*transparent !important;/)
assert.match(headerCss, /\.navbar-top \.aksrt-navbar-actions \.navbar-cta\.radius\s*\{[^}]*border-radius:\s*50px;/s)
})
test('search surface clears the fixed header and closes from the lower-right corner', () => {
assert.match(headerCss, /\.navbar-search\s*\{[^}]*z-index:\s*1001;[^}]*height:\s*100%;[^}]*overflow:\s*hidden;/s)
assert.match(headerCss, /\.navbar-search \.search-close-box\s*\{[^}]*position:\s*fixed;[^}]*right:[^;]+;[^}]*bottom:/s)
assert.ok(headerSearch.indexOf('echo $remote') < headerSearch.indexOf('search-close-box'))
})
test('header user-card publish controls are removed from configuration and runtime', () => {
assert.doesNotMatch(schema, /nav_user_newposts_btn/)
assert.doesNotMatch(headerNavbar, /nav_user_newposts_btn/)
assert.match(headerNavbar, /esc_html__\('发布内容', 'aksrt'\)/)
})
test('save contract rejects invalid input and round-trips canonical nested values', () => {
const result = spawnSync(process.env.PHP_BINARY || 'php', [path.join(__dirname, 'page-display-save-harness.php')], {
cwd: root,