修复了一些一些已知问题
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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', '发布文章'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user