Merge pull request 'feat(shell): header multifunc + window._win + float cart/VIP' (#216) from worktree-header-runtime-float-1to1 into main

Reviewed-on: CYL/wordpress-theme-aksrt#216
This commit is contained in:
2026-07-18 22:18:52 +08:00
9 changed files with 994 additions and 441 deletions
@@ -0,0 +1,114 @@
/**
* Header multi-function publish cluster + VIP CTA.
*
* @package AKSRT
*/
.navbar-but-cluster {
display: flex;
align-items: center;
gap: 8px;
}
.navbar-but-cluster .navbar-but,
.navbar-but-cluster .navbar-vip {
display: inline-flex;
align-items: center;
}
.navbar-but-cluster .btn-primary,
.navbar-but-cluster .but.btn-primary,
.navbar-but-cluster .navbar-newposts.but,
.navbar-but-cluster a.but {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
border-radius: 20px;
background: var(--color-primary, #2f6df6);
color: #fff;
text-decoration: none;
border: 0;
font-size: 13px;
line-height: 1.4;
white-space: nowrap;
}
.navbar-but-cluster .payvip-icon.but {
background: linear-gradient(90deg, #ff6b6b, #f04494);
color: #fff;
padding: 6px 12px;
border-radius: 20px;
text-decoration: none;
font-size: 13px;
}
.newadd-btns.hover-show {
position: relative;
display: inline-block;
}
.newadd-btns .drop-newadd,
.newadd-btns .hover-show-con {
display: none;
position: absolute;
top: calc(100% + 6px);
right: 0;
min-width: 140px;
background: var(--main-bg-color, #fff);
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
padding: 6px 0;
z-index: 50;
}
.newadd-btns.hover-show:hover .drop-newadd,
.newadd-btns.hover-show:hover .hover-show-con,
.newadd-btns.hover-show:focus-within .drop-newadd {
display: block;
}
.newadd-btns__item {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 14px;
color: inherit;
text-decoration: none;
white-space: nowrap;
}
.newadd-btns__item:hover {
background: var(--surface-2, rgba(0, 0, 0, 0.04));
color: var(--focus-color, var(--color-primary));
}
/* float commerce */
.float-btn-shop-cart {
position: relative;
}
.float-btn-shop-cart badge,
.float-btn-shop-cart [cart-count] {
position: absolute;
top: -4px;
right: -4px;
min-width: 16px;
height: 16px;
padding: 0 4px;
border-radius: 10px;
background: #e74c3c;
color: #fff;
font-size: 11px;
line-height: 16px;
text-align: center;
}
.float-btn-shop-cart badge:empty,
.float-btn-shop-cart [cart-count=""] {
display: none;
}
.float-btn.pay-vip {
color: #f5a623;
}
+24 -1
View File
@@ -112,6 +112,16 @@
var MAX_ZOOM_DESKTOP = 2;
var MAX_ZOOM_MOBILE = 3;
function lightboxFlag(key, fallback) {
var w = window._win || (window.aksrtData && window.aksrtData.imgbox) || {};
if (w[key] === undefined || w[key] === null || w[key] === '') return fallback;
return w[key] === true || w[key] === 1 || w[key] === '1';
}
function lightboxEnabled() {
return lightboxFlag('imgbox', true);
}
function resolveFullUrl(img) {
var full = img.getAttribute('data-full-url') || img.getAttribute('data-src') || '';
if (full) return full;
@@ -134,6 +144,7 @@
}
function createLightbox() {
if (!lightboxEnabled()) return;
if (lightboxEl) return;
lightboxEl = document.createElement('div');
@@ -161,6 +172,18 @@
lightboxCounter = lightboxEl.querySelector('.aksrt-lightbox__counter');
lightboxThumbsWrap = lightboxEl.querySelector('.aksrt-lightbox__thumbs');
// Apply window._win imgbox feature flags
var zoomBtn = lightboxEl.querySelector('.toggle-zoom');
var thumbsBtn = lightboxEl.querySelector('.toggle-thumbs');
var playBtn = lightboxEl.querySelector('.toggle-play');
var fullBtn = lightboxEl.querySelector('.toggle-full');
var downBtn = lightboxEl.querySelector('.aksrt-lightbox__download');
if (zoomBtn) zoomBtn.hidden = !lightboxFlag('imgbox_zoom', true);
if (thumbsBtn) thumbsBtn.hidden = !lightboxFlag('imgbox_thumbs', true);
if (playBtn) playBtn.hidden = !lightboxFlag('imgbox_play', false);
if (fullBtn) fullBtn.hidden = !lightboxFlag('imgbox_full', true);
if (downBtn) downBtn.hidden = !lightboxFlag('imgbox_down', false);
// Close
lightboxEl.querySelector('.aksrt-lightbox__close').addEventListener('click', function (e) { e.stopPropagation(); closeLightbox(); });
lightboxEl.addEventListener('click', function (e) { if (e.target === lightboxEl || e.target.classList.contains('aksrt-lightbox__stage')) closeLightbox(); });
@@ -435,7 +458,7 @@
var img = e.target.closest(TRIGGER_SEL);
if (!img) return;
if (img.width < 100 || img.height < 100) return;
if (isNoLightbox(img)) return;
if (!lightboxEnabled() || isNoLightbox(img)) return;
e.preventDefault();
+23 -1
View File
@@ -396,6 +396,18 @@ if ($floating_enabled) :
<i class="fas fa-sun float-btn__icon-sun" aria-hidden="true"></i>
<i class="fas fa-moon float-btn__icon-moon" aria-hidden="true"></i>
</a>
<?php elseif ($item_type === 'shop_cart') :
$cart_html = function_exists('aksrt_get_float_shop_cart_html') ? aksrt_get_float_shop_cart_html($item) : '';
if ($cart_html !== '') {
echo $cart_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
<?php elseif ($item_type === 'pay_vip') :
$vip_html = function_exists('aksrt_get_float_pay_vip_html') ? aksrt_get_float_pay_vip_html($item) : '';
if ($vip_html !== '') {
echo $vip_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
<?php elseif ($item_type === 'service_wechat') :
$item_class .= ' service-wechat';
$wechat_img = $item['wechat_img'] ?? ($item['qrcode_img'] ?? '');
@@ -471,7 +483,17 @@ if ($floating_enabled) :
<?php endif; ?>
</a>
<?php endif; ?>
<?php endforeach; ?>
<?php
// Commerce floats when admin list omits them.
$float_types = array_column($floating_items, 'type');
if (!in_array('shop_cart', $float_types, true) && function_exists('aksrt_get_float_shop_cart_html')) {
echo aksrt_get_float_shop_cart_html(['icon' => 'fas fa-shopping-cart']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
if (!in_array('pay_vip', $float_types, true) && function_exists('aksrt_get_float_pay_vip_html')) {
echo aksrt_get_float_pay_vip_html(['icon' => 'fa fa-diamond']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
<?php endforeach; ?>
</div>
<?php endif; ?>
+19 -13
View File
@@ -261,20 +261,26 @@ if (!empty($aksrt_bg_styles)) {
</form>
<?php endif; ?>
<div class="nav-actions__cta">
<?php if ($aksrt_can_publish) : ?>
<a class="btn-primary" href="<?php echo esc_url($aksrt_publish_url); ?>">
<i class="fas fa-pen-nib" aria-hidden="true"></i>
<span><?php esc_html_e('发布', 'aksrt'); ?></span>
</a>
<?php endif; ?>
<div class="nav-actions__cta navbar-but-cluster">
<?php
if (function_exists('aksrt_render_header_menu_buttons')) {
echo aksrt_render_header_menu_buttons(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} elseif (!empty($aksrt_can_publish)) {
?>
<a class="btn-primary" href="<?php echo esc_url($aksrt_publish_url); ?>">
<i class="fas fa-pen-nib" aria-hidden="true"></i>
<span><?php esc_html_e('发布', 'aksrt'); ?></span>
</a>
<?php
}
?>
<?php if (in_array('pc_nav', $aksrt_theme_toggle_positions, true)) : ?>
<button type="button" class="btn-outline theme-toggle-desktop" id="theme-toggle-desktop" title="<?php esc_attr_e('切换亮暗色', 'aksrt'); ?>">
<i class="fas fa-adjust" aria-hidden="true"></i>
</button>
<?php endif; ?>
</div>
<?php if (in_array('pc_nav', $aksrt_theme_toggle_positions, true)) : ?>
<button type="button" class="btn-outline theme-toggle-desktop" id="theme-toggle-desktop" title="<?php esc_attr_e('切换亮暗色', 'aksrt'); ?>">
<i class="fas fa-adjust" aria-hidden="true"></i>
</button>
<?php endif; ?>
</div>
<?php if ($aksrt_show_user_entry) : ?>
<?php if (is_user_logged_in()) : ?>
+2
View File
@@ -45,6 +45,8 @@ require_once AKSRT_DIR . '/inc/helpers/aksrt-null.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-ajax-list.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-links.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-header-userbox.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-header-menu-buttons.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-runtime-win.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-identity.php';
require_once AKSRT_DIR . '/inc/helpers/aksrt-rewards.php';
require_once AKSRT_DIR . '/inc/helpers/menu-decoration.php';
+433 -426
View File
@@ -1,426 +1,433 @@
<?php
defined('ABSPATH') || exit;
// 前端隐藏 WordPress Admin Bar
// ============================================================
add_filter('show_admin_bar', '__return_false');
// ============================================================
// WordPress 链接管理(网址导航 / 书签)
// zibll enables link_manager; AKSRT keeps it for page-links.
// ============================================================
add_filter('pre_option_link_manager_enabled', '__return_true');
// ============================================================
// Gravatar 头像源替换(4层拦截:get_avatar_url / pre_get_avatar_data / avatar_defaults / ob_start 兜底)
// ============================================================
function aksrt_get_gravatar_source() {
if (class_exists('\AKSRT\Settings\Settings')) {
return \AKSRT\Settings\Settings::avatar_source();
}
$source = aksrt_get_setting('avatar_source', 'cn.cravatar.com');
$allowed = array('cn.cravatar.com', 'cn.gravatar.com', 'gravatar.com');
return in_array($source, $allowed, true) ? $source : 'cn.cravatar.com';
}
function aksrt_replace_gravatar_domain($url) {
$source = aksrt_get_gravatar_source();
if ($source === 'gravatar.com') return $url;
return preg_replace('#^https?://([0-9]+\.)?(secure\.)?gravatar\.com#i', 'https://' . $source, $url);
}
add_filter('get_avatar_url', function ($url) {
return aksrt_replace_gravatar_domain($url);
});
add_filter('pre_get_avatar_data', function ($args) {
if (!empty($args['url'])) {
$args['url'] = aksrt_replace_gravatar_domain($args['url']);
}
return $args;
}, 10, 1);
add_filter('avatar_defaults', function ($defaults) {
foreach ($defaults as &$url) {
$url = aksrt_replace_gravatar_domain($url);
}
unset($url);
return $defaults;
});
// 全局输出缓冲兜底(覆盖 JS/API 直接请求的 URL)
add_action('init', function () {
if (is_admin()) ob_start(function ($html) {
return preg_replace_callback(
'#https?://([0-9]+\.)?(secure\.)?gravatar\.com#i',
function () { return 'https://' . aksrt_get_gravatar_source(); },
$html
);
});
});
// ============================================================
// SMTP 邮件配置注入
// ============================================================
add_action('phpmailer_init', function ($phpmailer) {
$mail = get_option('aksrt_mail_smtp', array());
if (empty($mail['enabled']) || empty($mail['host'])) return;
$phpmailer->isSMTP();
$phpmailer->Host = $mail['host'];
$phpmailer->Port = (int) (isset($mail['port']) ? $mail['port'] : 465);
$phpmailer->SMTPAuth = !empty($mail['username']);
$phpmailer->Username = $mail['username'];
$phpmailer->Password = $mail['password'];
$phpmailer->SMTPSecure = isset($mail['encryption']) ? $mail['encryption'] : 'ssl';
// 性能优化:超时 + 连接保持
$phpmailer->Timeout = 10; // 连接/读取超时 10 秒
$phpmailer->Timelimit = 15; // 总执行上限 15 秒
if (!empty($mail['from_address'])) {
$from_name = isset($mail['from_name']) ? $mail['from_name'] : '';
// mail_showname 覆盖 from_name
if (class_exists('\AKSRT\Settings\Settings')) {
$branding = \AKSRT\Settings\Settings::get_mail_branding();
if ($branding['showname'] !== '') {
$from_name = $branding['showname'];
}
}
$phpmailer->setFrom($mail['from_address'], $from_name);
}
if (!empty($mail['from_name'])) {
$phpmailer->FromName = $mail['from_name'];
}
// mail_showname 全局覆盖 FromName
if (class_exists('\AKSRT\Settings\Settings')) {
$branding = \AKSRT\Settings\Settings::get_mail_branding();
if ($branding['showname'] !== '') {
$phpmailer->FromName = $branding['showname'];
}
}
});
// mail_title_prefix:为所有邮件主题添加前缀
add_filter('wp_mail', function ($atts) {
if (!class_exists('\AKSRT\Settings\Settings') || empty($atts['subject'])) return $atts;
$branding = \AKSRT\Settings\Settings::get_mail_branding();
if ($branding['title_prefix'] !== '' && strpos($atts['subject'], $branding['title_prefix']) !== 0) {
$atts['subject'] = $branding['title_prefix'] . ' ' . $atts['subject'];
}
return $atts;
});
// ============================================================
// 分类 Term Meta 字段(封面图 + 推荐描述)
// ============================================================
/**
* 编辑分类页面 - 显示自定义字段
*/
function aksrt_category_meta_fields($term) {
$cover_id = (int) get_term_meta($term->term_id, 'aksrt_category_cover_id', true);
$cover_url = $cover_id > 0 ? wp_get_attachment_url($cover_id) : '';
$recommend_desc = (string) get_term_meta($term->term_id, 'aksrt_category_recommend_desc', true);
?>
<tr class="form-field">
<th scope="row"><label for="aksrt_category_cover_id"><?php esc_html_e('分类封面图', 'aksrt'); ?></label></th>
<td>
<div id="aksrt-cover-preview" style="margin-bottom:8px;">
<?php if ($cover_url) : ?>
<img src="<?php echo esc_url($cover_url); ?>" style="max-width:200px;height:auto;border-radius:6px;" alt="">
<?php endif; ?>
</div>
<input type="hidden" id="aksrt_category_cover_id" name="aksrt_category_cover_id" value="<?php echo esc_attr((string) $cover_id); ?>">
<button type="button" class="button" id="aksrt-pick-cover"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
<button type="button" class="button" id="aksrt-remove-cover" <?php echo $cover_id > 0 ? '' : 'style="display:none;"'; ?>><?php esc_html_e('移除', 'aksrt'); ?></button>
<p class="description"><?php esc_html_e('分类推荐模块的封面图片。', 'aksrt'); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row"><label for="aksrt_category_recommend_desc"><?php esc_html_e('推荐描述', 'aksrt'); ?></label></th>
<td>
<textarea id="aksrt_category_recommend_desc" name="aksrt_category_recommend_desc" rows="3" class="large-text"><?php echo esc_textarea($recommend_desc); ?></textarea>
<p class="description"><?php esc_html_e('分类推荐模块中显示的描述文字。留空则使用分类默认描述。', 'aksrt'); ?></p>
</td>
</tr>
<?php
}
/**
* 新增分类页面 - 显示自定义字段
*/
function aksrt_category_meta_fields_add() {
?>
<div class="form-field">
<label for="aksrt_category_cover_id"><?php esc_html_e('分类封面图', 'aksrt'); ?></label>
<div id="aksrt-cover-preview" style="margin-bottom:8px;"></div>
<input type="hidden" id="aksrt_category_cover_id" name="aksrt_category_cover_id" value="">
<button type="button" class="button" id="aksrt-pick-cover"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
<button type="button" class="button" id="aksrt-remove-cover" style="display:none;"><?php esc_html_e('移除', 'aksrt'); ?></button>
<p class="description"><?php esc_html_e('分类推荐模块的封面图片。', 'aksrt'); ?></p>
</div>
<div class="form-field">
<label for="aksrt_category_recommend_desc"><?php esc_html_e('推荐描述', 'aksrt'); ?></label>
<textarea id="aksrt_category_recommend_desc" name="aksrt_category_recommend_desc" rows="3"></textarea>
<p class="description"><?php esc_html_e('分类推荐模块中显示的描述文字。留空则使用分类默认描述。', 'aksrt'); ?></p>
</div>
<?php
}
add_action('category_edit_form_fields', 'aksrt_category_meta_fields', 10, 1);
add_action('category_add_form_fields', 'aksrt_category_meta_fields_add', 10, 1);
/**
* 保存分类 term meta
*/
function aksrt_save_category_meta(int $term_id) {
if (!current_user_can('manage_categories')) return;
$cover_id = isset($_POST['aksrt_category_cover_id']) ? absint($_POST['aksrt_category_cover_id']) : 0;
$recommend_desc = isset($_POST['aksrt_category_recommend_desc']) ? sanitize_textarea_field(wp_unslash($_POST['aksrt_category_recommend_desc'])) : '';
if ($cover_id > 0) {
update_term_meta($term_id, 'aksrt_category_cover_id', $cover_id);
} else {
delete_term_meta($term_id, 'aksrt_category_cover_id');
}
if ($recommend_desc !== '') {
update_term_meta($term_id, 'aksrt_category_recommend_desc', $recommend_desc);
} else {
delete_term_meta($term_id, 'aksrt_category_recommend_desc');
}
if (class_exists('\AKSRT\Settings\Settings')) {
\AKSRT\Settings\Settings::flush_category_recommend_cache();
}
}
add_action('edited_category', 'aksrt_save_category_meta', 10, 1);
add_action('created_category', 'aksrt_save_category_meta', 10, 1);
/**
* 分类编辑页加载媒体库脚本(wp_enqueue_media 仅在 AKSRT 面板加载,此处补上)
*/
add_action('admin_enqueue_scripts', function (string $hook_suffix) {
if ($hook_suffix === 'edit-tags.php' || $hook_suffix === 'term.php') {
wp_enqueue_media();
}
});
/**
* 分类编辑页内联 JS - 媒体选择器
*/
function aksrt_category_meta_admin_js() {
$screen = get_current_screen();
if (!$screen || $screen->taxonomy !== 'category') return;
?>
<script>
jQuery(function($) {
var frame;
$(document).on('click', '#aksrt-pick-cover', function(e) {
e.preventDefault();
if (typeof wp === 'undefined' || !wp.media) return;
if (frame) { frame.open(); return; }
frame = wp.media({
title: '<?php echo esc_js(__('选择分类封面图', 'aksrt')); ?>',
button: { text: '<?php echo esc_js(__('使用此图片', 'aksrt')); ?>' },
multiple: false
});
frame.on('select', function() {
var attachment = frame.state().get('selection').first().toJSON();
$('#aksrt_category_cover_id').val(attachment.id);
$('#aksrt-cover-preview').html('<img src="' + attachment.url + '" style="max-width:200px;height:auto;border-radius:6px;" alt="">');
$('#aksrt-remove-cover').show();
});
frame.open();
});
$(document).on('click', '#aksrt-remove-cover', function(e) {
e.preventDefault();
$('#aksrt_category_cover_id').val('');
$('#aksrt-cover-preview').html('');
$(this).hide();
});
});
</script>
<?php
}
add_action('admin_footer', 'aksrt_category_meta_admin_js');
// ============================================================
// 资源列表:/resources 虚拟归档(post + _aksrt_is_resource)
// ============================================================
add_action('init', function () {
add_rewrite_rule('^resources/?$', 'index.php?aksrt_is_resource_archive=1', 'top');
add_rewrite_rule('^resources/page/([0-9]+)/?$', 'index.php?aksrt_is_resource_archive=1&paged=$matches[1]', 'top');
// 旧单篇路径 /resource/{slug} → 301 到 post 永久链接
add_rewrite_rule('^resource/([^/]+)/?$', 'index.php?aksrt_legacy_resource=$matches[1]', 'top');
});
add_filter('query_vars', function ($vars) {
$vars[] = 'aksrt_is_resource_archive';
$vars[] = 'aksrt_legacy_resource';
$vars[] = 'aksrt_search_type';
return $vars;
});
add_action('template_redirect', function () {
$slug = get_query_var('aksrt_legacy_resource');
if (!$slug) {
return;
}
$page = get_page_by_path((string) $slug, OBJECT, 'post');
if ($page) {
wp_redirect(get_permalink($page->ID), 301);
exit;
}
});
add_action('pre_get_posts', function ($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ((bool) $query->get('aksrt_is_resource_archive')) {
$query->set('post_type', 'post');
$query->set('post_status', 'publish');
$orderby = isset($_GET['orderby']) ? sanitize_key((string) $_GET['orderby']) : 'date';
if ($orderby === 'downloads') {
$query->set('meta_key', \AKSRT\Core\DomainModel::RESOURCE_DOWNLOAD_COUNT_KEY);
$query->set('orderby', 'meta_value_num');
$query->set('order', 'DESC');
} elseif ($orderby === 'views') {
$query->set('meta_key', \AKSRT\Core\DomainModel::RESOURCE_VIEW_COUNT_KEY);
$query->set('orderby', 'meta_value_num');
$query->set('order', 'DESC');
}
$price_filter = isset($_GET['price']) ? sanitize_key((string) $_GET['price']) : '';
$price_min = isset($_GET['price_min']) && $_GET['price_min'] !== '' ? (float) $_GET['price_min'] : null;
$price_max = isset($_GET['price_max']) && $_GET['price_max'] !== '' ? (float) $_GET['price_max'] : null;
$meta_query = [
'relation' => 'AND',
[
'key' => \AKSRT\Core\DomainModel::RESOURCE_MARKER_KEY,
'value' => '1',
'compare' => '=',
],
];
if ($price_filter === 'free') {
$meta_query[] = [
'relation' => 'OR',
[
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => 0,
'compare' => '=',
'type' => 'NUMERIC',
],
[
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'compare' => 'NOT EXISTS',
],
];
} elseif ($price_filter === 'paid') {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => 0,
'compare' => '>',
'type' => 'NUMERIC',
];
}
if ($price_min !== null || $price_max !== null) {
if ($price_min !== null && $price_max !== null) {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => [$price_min, $price_max],
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
];
} elseif ($price_min !== null) {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => $price_min,
'compare' => '>=',
'type' => 'NUMERIC',
];
} else {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => $price_max,
'compare' => '<=',
'type' => 'NUMERIC',
];
}
}
$existing = $query->get('meta_query');
if (!is_array($existing)) {
$existing = [];
}
$query->set('meta_query', array_merge($existing, $meta_query));
$query->set('cat', 0);
$query->set('tag', '');
}
// 站内搜索:分类/标签名搜索(内容类型始终为 post)
if ($query->is_search() && empty($query->get('post_type'))) {
$search_type = sanitize_key((string) $query->get('aksrt_search_type'));
if (in_array($search_type, ['category', 'tag'], true)) {
$taxonomy = $search_type === 'category' ? 'category' : 'post_tag';
$term_ids = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
'fields' => 'ids',
'number' => 20,
'search' => (string) $query->get('s'),
]);
$query->set('s', '');
if (is_wp_error($term_ids) || empty($term_ids)) {
$query->set('post__in', [0]);
} else {
$query->set('tax_query', [[
'taxonomy' => $taxonomy,
'field' => 'term_id',
'terms' => array_map('absint', $term_ids),
]]);
}
}
}
});
add_filter('template_include', function ($template) {
if (!get_query_var('aksrt_is_resource_archive')) {
return $template;
}
$candidate = locate_template(['archive-resources.php']);
return $candidate ?: $template;
});
add_filter('document_title_parts', function ($parts) {
if (get_query_var('aksrt_is_resource_archive')) {
$parts['title'] = __('资源', 'aksrt');
}
return $parts;
});
// ============================================================␍
<?php
defined('ABSPATH') || exit;
// window._win runtime bridge (zibll zib_win_var)
add_action('wp_head', static function () {
if (function_exists('aksrt_print_win_var')) {
aksrt_print_win_var();
}
}, 1);
// 前端隐藏 WordPress Admin Bar
// ============================================================
add_filter('show_admin_bar', '__return_false');
// ============================================================
// WordPress 链接管理(网址导航 / 书签)
// zibll enables link_manager; AKSRT keeps it for page-links.
// ============================================================
add_filter('pre_option_link_manager_enabled', '__return_true');
// ============================================================
// Gravatar 头像源替换(4层拦截:get_avatar_url / pre_get_avatar_data / avatar_defaults / ob_start 兜底)
// ============================================================
function aksrt_get_gravatar_source() {
if (class_exists('\AKSRT\Settings\Settings')) {
return \AKSRT\Settings\Settings::avatar_source();
}
$source = aksrt_get_setting('avatar_source', 'cn.cravatar.com');
$allowed = array('cn.cravatar.com', 'cn.gravatar.com', 'gravatar.com');
return in_array($source, $allowed, true) ? $source : 'cn.cravatar.com';
}
function aksrt_replace_gravatar_domain($url) {
$source = aksrt_get_gravatar_source();
if ($source === 'gravatar.com') return $url;
return preg_replace('#^https?://([0-9]+\.)?(secure\.)?gravatar\.com#i', 'https://' . $source, $url);
}
add_filter('get_avatar_url', function ($url) {
return aksrt_replace_gravatar_domain($url);
});
add_filter('pre_get_avatar_data', function ($args) {
if (!empty($args['url'])) {
$args['url'] = aksrt_replace_gravatar_domain($args['url']);
}
return $args;
}, 10, 1);
add_filter('avatar_defaults', function ($defaults) {
foreach ($defaults as &$url) {
$url = aksrt_replace_gravatar_domain($url);
}
unset($url);
return $defaults;
});
// 全局输出缓冲兜底(覆盖 JS/API 直接请求的 URL)
add_action('init', function () {
if (is_admin()) ob_start(function ($html) {
return preg_replace_callback(
'#https?://([0-9]+\.)?(secure\.)?gravatar\.com#i',
function () { return 'https://' . aksrt_get_gravatar_source(); },
$html
);
});
});
// ============================================================
// SMTP 邮件配置注入
// ============================================================
add_action('phpmailer_init', function ($phpmailer) {
$mail = get_option('aksrt_mail_smtp', array());
if (empty($mail['enabled']) || empty($mail['host'])) return;
$phpmailer->isSMTP();
$phpmailer->Host = $mail['host'];
$phpmailer->Port = (int) (isset($mail['port']) ? $mail['port'] : 465);
$phpmailer->SMTPAuth = !empty($mail['username']);
$phpmailer->Username = $mail['username'];
$phpmailer->Password = $mail['password'];
$phpmailer->SMTPSecure = isset($mail['encryption']) ? $mail['encryption'] : 'ssl';
// 性能优化:超时 + 连接保持
$phpmailer->Timeout = 10; // 连接/读取超时 10 秒
$phpmailer->Timelimit = 15; // 总执行上限 15 秒
if (!empty($mail['from_address'])) {
$from_name = isset($mail['from_name']) ? $mail['from_name'] : '';
// mail_showname 覆盖 from_name
if (class_exists('\AKSRT\Settings\Settings')) {
$branding = \AKSRT\Settings\Settings::get_mail_branding();
if ($branding['showname'] !== '') {
$from_name = $branding['showname'];
}
}
$phpmailer->setFrom($mail['from_address'], $from_name);
}
if (!empty($mail['from_name'])) {
$phpmailer->FromName = $mail['from_name'];
}
// mail_showname 全局覆盖 FromName
if (class_exists('\AKSRT\Settings\Settings')) {
$branding = \AKSRT\Settings\Settings::get_mail_branding();
if ($branding['showname'] !== '') {
$phpmailer->FromName = $branding['showname'];
}
}
});
// mail_title_prefix:为所有邮件主题添加前缀
add_filter('wp_mail', function ($atts) {
if (!class_exists('\AKSRT\Settings\Settings') || empty($atts['subject'])) return $atts;
$branding = \AKSRT\Settings\Settings::get_mail_branding();
if ($branding['title_prefix'] !== '' && strpos($atts['subject'], $branding['title_prefix']) !== 0) {
$atts['subject'] = $branding['title_prefix'] . ' ' . $atts['subject'];
}
return $atts;
});
// ============================================================
// 分类 Term Meta 字段(封面图 + 推荐描述)
// ============================================================
/**
* 编辑分类页面 - 显示自定义字段
*/
function aksrt_category_meta_fields($term) {
$cover_id = (int) get_term_meta($term->term_id, 'aksrt_category_cover_id', true);
$cover_url = $cover_id > 0 ? wp_get_attachment_url($cover_id) : '';
$recommend_desc = (string) get_term_meta($term->term_id, 'aksrt_category_recommend_desc', true);
?>
<tr class="form-field">
<th scope="row"><label for="aksrt_category_cover_id"><?php esc_html_e('分类封面图', 'aksrt'); ?></label></th>
<td>
<div id="aksrt-cover-preview" style="margin-bottom:8px;">
<?php if ($cover_url) : ?>
<img src="<?php echo esc_url($cover_url); ?>" style="max-width:200px;height:auto;border-radius:6px;" alt="">
<?php endif; ?>
</div>
<input type="hidden" id="aksrt_category_cover_id" name="aksrt_category_cover_id" value="<?php echo esc_attr((string) $cover_id); ?>">
<button type="button" class="button" id="aksrt-pick-cover"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
<button type="button" class="button" id="aksrt-remove-cover" <?php echo $cover_id > 0 ? '' : 'style="display:none;"'; ?>><?php esc_html_e('移除', 'aksrt'); ?></button>
<p class="description"><?php esc_html_e('分类推荐模块的封面图片。', 'aksrt'); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row"><label for="aksrt_category_recommend_desc"><?php esc_html_e('推荐描述', 'aksrt'); ?></label></th>
<td>
<textarea id="aksrt_category_recommend_desc" name="aksrt_category_recommend_desc" rows="3" class="large-text"><?php echo esc_textarea($recommend_desc); ?></textarea>
<p class="description"><?php esc_html_e('分类推荐模块中显示的描述文字。留空则使用分类默认描述。', 'aksrt'); ?></p>
</td>
</tr>
<?php
}
/**
* 新增分类页面 - 显示自定义字段
*/
function aksrt_category_meta_fields_add() {
?>
<div class="form-field">
<label for="aksrt_category_cover_id"><?php esc_html_e('分类封面图', 'aksrt'); ?></label>
<div id="aksrt-cover-preview" style="margin-bottom:8px;"></div>
<input type="hidden" id="aksrt_category_cover_id" name="aksrt_category_cover_id" value="">
<button type="button" class="button" id="aksrt-pick-cover"><?php esc_html_e('选择图片', 'aksrt'); ?></button>
<button type="button" class="button" id="aksrt-remove-cover" style="display:none;"><?php esc_html_e('移除', 'aksrt'); ?></button>
<p class="description"><?php esc_html_e('分类推荐模块的封面图片。', 'aksrt'); ?></p>
</div>
<div class="form-field">
<label for="aksrt_category_recommend_desc"><?php esc_html_e('推荐描述', 'aksrt'); ?></label>
<textarea id="aksrt_category_recommend_desc" name="aksrt_category_recommend_desc" rows="3"></textarea>
<p class="description"><?php esc_html_e('分类推荐模块中显示的描述文字。留空则使用分类默认描述。', 'aksrt'); ?></p>
</div>
<?php
}
add_action('category_edit_form_fields', 'aksrt_category_meta_fields', 10, 1);
add_action('category_add_form_fields', 'aksrt_category_meta_fields_add', 10, 1);
/**
* 保存分类 term meta
*/
function aksrt_save_category_meta(int $term_id) {
if (!current_user_can('manage_categories')) return;
$cover_id = isset($_POST['aksrt_category_cover_id']) ? absint($_POST['aksrt_category_cover_id']) : 0;
$recommend_desc = isset($_POST['aksrt_category_recommend_desc']) ? sanitize_textarea_field(wp_unslash($_POST['aksrt_category_recommend_desc'])) : '';
if ($cover_id > 0) {
update_term_meta($term_id, 'aksrt_category_cover_id', $cover_id);
} else {
delete_term_meta($term_id, 'aksrt_category_cover_id');
}
if ($recommend_desc !== '') {
update_term_meta($term_id, 'aksrt_category_recommend_desc', $recommend_desc);
} else {
delete_term_meta($term_id, 'aksrt_category_recommend_desc');
}
if (class_exists('\AKSRT\Settings\Settings')) {
\AKSRT\Settings\Settings::flush_category_recommend_cache();
}
}
add_action('edited_category', 'aksrt_save_category_meta', 10, 1);
add_action('created_category', 'aksrt_save_category_meta', 10, 1);
/**
* 分类编辑页加载媒体库脚本(wp_enqueue_media 仅在 AKSRT 面板加载,此处补上)
*/
add_action('admin_enqueue_scripts', function (string $hook_suffix) {
if ($hook_suffix === 'edit-tags.php' || $hook_suffix === 'term.php') {
wp_enqueue_media();
}
});
/**
* 分类编辑页内联 JS - 媒体选择器
*/
function aksrt_category_meta_admin_js() {
$screen = get_current_screen();
if (!$screen || $screen->taxonomy !== 'category') return;
?>
<script>
jQuery(function($) {
var frame;
$(document).on('click', '#aksrt-pick-cover', function(e) {
e.preventDefault();
if (typeof wp === 'undefined' || !wp.media) return;
if (frame) { frame.open(); return; }
frame = wp.media({
title: '<?php echo esc_js(__('选择分类封面图', 'aksrt')); ?>',
button: { text: '<?php echo esc_js(__('使用此图片', 'aksrt')); ?>' },
multiple: false
});
frame.on('select', function() {
var attachment = frame.state().get('selection').first().toJSON();
$('#aksrt_category_cover_id').val(attachment.id);
$('#aksrt-cover-preview').html('<img src="' + attachment.url + '" style="max-width:200px;height:auto;border-radius:6px;" alt="">');
$('#aksrt-remove-cover').show();
});
frame.open();
});
$(document).on('click', '#aksrt-remove-cover', function(e) {
e.preventDefault();
$('#aksrt_category_cover_id').val('');
$('#aksrt-cover-preview').html('');
$(this).hide();
});
});
</script>
<?php
}
add_action('admin_footer', 'aksrt_category_meta_admin_js');
// ============================================================
// 资源列表:/resources 虚拟归档(post + _aksrt_is_resource)
// ============================================================
add_action('init', function () {
add_rewrite_rule('^resources/?$', 'index.php?aksrt_is_resource_archive=1', 'top');
add_rewrite_rule('^resources/page/([0-9]+)/?$', 'index.php?aksrt_is_resource_archive=1&paged=$matches[1]', 'top');
// 旧单篇路径 /resource/{slug} → 301 到 post 永久链接
add_rewrite_rule('^resource/([^/]+)/?$', 'index.php?aksrt_legacy_resource=$matches[1]', 'top');
});
add_filter('query_vars', function ($vars) {
$vars[] = 'aksrt_is_resource_archive';
$vars[] = 'aksrt_legacy_resource';
$vars[] = 'aksrt_search_type';
return $vars;
});
add_action('template_redirect', function () {
$slug = get_query_var('aksrt_legacy_resource');
if (!$slug) {
return;
}
$page = get_page_by_path((string) $slug, OBJECT, 'post');
if ($page) {
wp_redirect(get_permalink($page->ID), 301);
exit;
}
});
add_action('pre_get_posts', function ($query) {
if (is_admin() || !$query->is_main_query()) {
return;
}
if ((bool) $query->get('aksrt_is_resource_archive')) {
$query->set('post_type', 'post');
$query->set('post_status', 'publish');
$orderby = isset($_GET['orderby']) ? sanitize_key((string) $_GET['orderby']) : 'date';
if ($orderby === 'downloads') {
$query->set('meta_key', \AKSRT\Core\DomainModel::RESOURCE_DOWNLOAD_COUNT_KEY);
$query->set('orderby', 'meta_value_num');
$query->set('order', 'DESC');
} elseif ($orderby === 'views') {
$query->set('meta_key', \AKSRT\Core\DomainModel::RESOURCE_VIEW_COUNT_KEY);
$query->set('orderby', 'meta_value_num');
$query->set('order', 'DESC');
}
$price_filter = isset($_GET['price']) ? sanitize_key((string) $_GET['price']) : '';
$price_min = isset($_GET['price_min']) && $_GET['price_min'] !== '' ? (float) $_GET['price_min'] : null;
$price_max = isset($_GET['price_max']) && $_GET['price_max'] !== '' ? (float) $_GET['price_max'] : null;
$meta_query = [
'relation' => 'AND',
[
'key' => \AKSRT\Core\DomainModel::RESOURCE_MARKER_KEY,
'value' => '1',
'compare' => '=',
],
];
if ($price_filter === 'free') {
$meta_query[] = [
'relation' => 'OR',
[
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => 0,
'compare' => '=',
'type' => 'NUMERIC',
],
[
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'compare' => 'NOT EXISTS',
],
];
} elseif ($price_filter === 'paid') {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => 0,
'compare' => '>',
'type' => 'NUMERIC',
];
}
if ($price_min !== null || $price_max !== null) {
if ($price_min !== null && $price_max !== null) {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => [$price_min, $price_max],
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
];
} elseif ($price_min !== null) {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => $price_min,
'compare' => '>=',
'type' => 'NUMERIC',
];
} else {
$meta_query[] = [
'key' => \AKSRT\Core\DomainModel::PAY_PRICE_KEY,
'value' => $price_max,
'compare' => '<=',
'type' => 'NUMERIC',
];
}
}
$existing = $query->get('meta_query');
if (!is_array($existing)) {
$existing = [];
}
$query->set('meta_query', array_merge($existing, $meta_query));
$query->set('cat', 0);
$query->set('tag', '');
}
// 站内搜索:分类/标签名搜索(内容类型始终为 post)
if ($query->is_search() && empty($query->get('post_type'))) {
$search_type = sanitize_key((string) $query->get('aksrt_search_type'));
if (in_array($search_type, ['category', 'tag'], true)) {
$taxonomy = $search_type === 'category' ? 'category' : 'post_tag';
$term_ids = get_terms([
'taxonomy' => $taxonomy,
'hide_empty' => false,
'fields' => 'ids',
'number' => 20,
'search' => (string) $query->get('s'),
]);
$query->set('s', '');
if (is_wp_error($term_ids) || empty($term_ids)) {
$query->set('post__in', [0]);
} else {
$query->set('tax_query', [[
'taxonomy' => $taxonomy,
'field' => 'term_id',
'terms' => array_map('absint', $term_ids),
]]);
}
}
}
});
add_filter('template_include', function ($template) {
if (!get_query_var('aksrt_is_resource_archive')) {
return $template;
}
$candidate = locate_template(['archive-resources.php']);
return $candidate ?: $template;
});
add_filter('document_title_parts', function ($parts) {
if (get_query_var('aksrt_is_resource_archive')) {
$parts['title'] = __('资源', 'aksrt');
}
return $parts;
});
// ============================================================
+188
View File
@@ -0,0 +1,188 @@
<?php
/**
* Header multi-function cluster (zibll zib_menu_button publish/VIP subset).
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_get_header_newposts_config')) :
/**
* @return array{enabled:bool,text:string,radius:int,class:string,types:string[]}
*/
function aksrt_get_header_newposts_config(): array {
$cfg = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_header_newposts_config()
: ['enabled' => true, 'text' => __('发布', 'aksrt'), 'radius' => 20, 'class' => ''];
$all = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
// Prefer publish_btn from header nav when newposts not explicitly set.
$nav = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_header_nav_settings()
: ['publish_btn' => true];
if (empty($cfg['enabled']) && !empty($nav['publish_btn'])) {
$cfg['enabled'] = true;
}
$types = [];
if (!empty($all['header_newposts_types']) && is_array($all['header_newposts_types'])) {
$types = array_values(array_filter(array_map('sanitize_key', $all['header_newposts_types'])));
}
if (!$types) {
$types = ['post'];
if (class_exists('\AKSRT\Settings\Settings')) {
$forum = \AKSRT\Settings\Settings::get_forum_settings();
$shop = \AKSRT\Settings\Settings::get_shop_settings();
if (!empty($forum['enabled'])) {
$types[] = 'topic';
}
if (!empty($shop['enabled'])) {
$types[] = 'product';
}
}
}
$cfg['types'] = $types;
return $cfg;
}
endif;
if (!function_exists('aksrt_get_new_add_actions')) :
/**
* Build multi-type publish actions.
*
* @param string[] $types post|topic|product
* @return list<array{type:string,url:string,label:string,icon:string}>
*/
function aksrt_get_new_add_actions(array $types = ['post']): array {
$out = [];
foreach ($types as $type) {
$type = sanitize_key((string) $type);
if ($type === 'post') {
$url = function_exists('aksrt_get_new_post_url') ? aksrt_get_new_post_url() : admin_url('post-new.php');
if ($url === '') {
continue;
}
$out[] = [
'type' => 'post',
'url' => $url,
'label' => __('写文章', 'aksrt'),
'icon' => 'fa fa-file-text-o',
];
} elseif ($type === 'topic') {
$url = function_exists('aksrt_get_forum_compose_url') ? aksrt_get_forum_compose_url() : '';
if ($url === '') {
continue;
}
$out[] = [
'type' => 'topic',
'url' => $url,
'label' => __('发帖', 'aksrt'),
'icon' => 'fa fa-comments-o',
];
} elseif ($type === 'product') {
// Prefer front product edit page when registered.
$url = '';
if (function_exists('aksrt_get_product_edit_url')) {
$url = (string) aksrt_get_product_edit_url();
}
if ($url === '') {
// Fallback: product-edit page template lookup is optional.
$url = home_url('/?page_id=0');
// Use admin product CPT if available.
$url = admin_url('post-new.php?post_type=aksrt_product');
}
$out[] = [
'type' => 'product',
'url' => $url,
'label' => __('发布商品', 'aksrt'),
'icon' => 'fa fa-shopping-bag',
];
}
}
return $out;
}
endif;
if (!function_exists('aksrt_render_new_add_btns')) :
/**
* Multi-type publish button (zibll newadd-btns).
*
* @param string[] $types
*/
function aksrt_render_new_add_btns(array $types, string $class = '', string $label = ''): string {
$actions = aksrt_get_new_add_actions($types);
if (!$actions) {
return '';
}
if ($label === '') {
$label = __('发布', 'aksrt');
}
$class = trim('newadd-btns ' . $class);
if (count($actions) === 1) {
$a = $actions[0];
return '<a rel="nofollow" class="' . esc_attr(trim($class . ' but')) . '" href="' . esc_url($a['url']) . '">'
. '<i class="' . esc_attr($a['icon']) . '" aria-hidden="true"></i> '
. wp_kses_post($label)
. '</a>';
}
$html = '<span class="' . esc_attr($class) . ' hover-show">';
$html .= '<a href="javascript:;" class="but newadd-btns__toggle" rel="nofollow">' . wp_kses_post($label) . ' <i class="fa fa-caret-down" aria-hidden="true"></i></a>';
$html .= '<div class="hover-show-con dropdown-menu drop-newadd">';
foreach ($actions as $a) {
$html .= '<a rel="nofollow" class="newadd-btns__item" href="' . esc_url($a['url']) . '">';
$html .= '<i class="' . esc_attr($a['icon']) . '" aria-hidden="true"></i> ' . esc_html($a['label']);
$html .= '</a>';
}
$html .= '</div></span>';
return $html;
}
endif;
if (!function_exists('aksrt_render_header_menu_buttons')) :
/**
* Publish + optional VIP open button for header CTA.
*/
function aksrt_render_header_menu_buttons(): string {
$cfg = aksrt_get_header_newposts_config();
$html = '';
if (!empty($cfg['enabled'])) {
$class = 'btn-primary navbar-newposts';
if (!empty($cfg['class'])) {
$class .= ' ' . $cfg['class'];
}
$radius = (int) ($cfg['radius'] ?? 20);
$style = $radius > 0 ? ' style="border-radius:' . $radius . 'px"' : '';
$label = (string) ($cfg['text'] ?? __('发布', 'aksrt'));
// Strip outer <i> if present in settings HTML text — keep simple.
$btn = aksrt_render_new_add_btns($cfg['types'] ?? ['post'], $class, $label);
if ($btn !== '') {
$html .= '<div class="navbar-form navbar-right navbar-but"' . $style . '>' . $btn . '</div>';
}
}
// VIP open CTA for guests / non-VIP.
$user_id = get_current_user_id();
$vip_url = function_exists('aksrt_get_vip_purchase_url') ? aksrt_get_vip_purchase_url() : (function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url('vip') : '#');
$show_vip = true;
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_vip_settings')) {
$vs = \AKSRT\Settings\Settings::get_vip_settings();
$show_vip = !empty($vs['enabled']) || !empty($vs['vip1_enabled']) || !empty($vs['vip2_enabled']);
}
if ($show_vip) {
$is_vip = false;
if ($user_id > 0 && function_exists('aksrt_get_user_vip_level')) {
$is_vip = (int) aksrt_get_user_vip_level($user_id) > 0;
}
if (!$is_vip) {
$cls = $user_id ? 'pay-vip' : 'signin-loader';
$html .= '<div class="navbar-form navbar-right navbar-vip hover-show inline-block">';
$html .= '<a class="but jb-red radius payvip-icon ml10 ' . esc_attr($cls) . '" href="' . ($user_id ? esc_url($vip_url) : 'javascript:;') . '">';
$html .= '<i class="fa fa-diamond em12 mr3" aria-hidden="true"></i>' . esc_html__('开通会员', 'aksrt');
$html .= '</a></div>';
}
}
return $html;
}
endif;
+179
View File
@@ -0,0 +1,179 @@
<?php
/**
* Float button commerce types + runtime window._win bridge (zibll parity).
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (!function_exists('aksrt_get_float_shop_cart_html')) :
/**
* Floating shop cart button with badge.
*/
function aksrt_get_float_shop_cart_html(array $item = []): string {
if (!is_user_logged_in()) {
return '';
}
$shop_on = true;
if (class_exists('\AKSRT\Settings\Settings')) {
$shop = \AKSRT\Settings\Settings::get_shop_settings();
$shop_on = !empty($shop['enabled']);
}
if (!$shop_on) {
return '';
}
// Skip on cart page.
if (function_exists('is_page_template') && is_page_template('templates/pages/page-cart.php')) {
return '';
}
$url = function_exists('aksrt_get_cart_page_url') ? aksrt_get_cart_page_url() : '';
if ($url === '') {
return '';
}
$count = 0;
if (class_exists('\AKSRT\Shop\Shop')) {
$count = (int) \AKSRT\Shop\Shop::get_instance()->get_cart_count(get_current_user_id());
}
$icon = !empty($item['icon']) ? (string) $item['icon'] : 'fas fa-shopping-cart';
$style = [];
if (!empty($item['color'])) {
$style[] = '--this-color:' . esc_attr((string) $item['color']);
}
if (!empty($item['bg'])) {
$style[] = '--this-bg:' . esc_attr((string) $item['bg']);
}
$style_attr = $style ? ' style="' . implode(';', $style) . '"' : '';
$badge = $count > 0 ? (string) min(99, $count) : '';
return '<a class="float-btn float-btn-shop-cart nowave" href="' . esc_url($url) . '" title="' . esc_attr__('购物车', 'aksrt') . '"' . $style_attr . '>'
. '<i class="' . esc_attr($icon) . '" aria-hidden="true"></i>'
. '<badge cart-count="' . esc_attr($badge) . '">' . esc_html($badge) . '</badge>'
. '</a>';
}
endif;
if (!function_exists('aksrt_get_float_pay_vip_html')) :
/**
* Floating VIP open button.
*/
function aksrt_get_float_pay_vip_html(array $item = []): string {
$show_vip = true;
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_vip_settings')) {
$vs = \AKSRT\Settings\Settings::get_vip_settings();
$show_vip = !empty($vs['enabled']) || !empty($vs['vip1_enabled']) || !empty($vs['vip2_enabled']);
}
if (!$show_vip) {
return '';
}
$user_id = get_current_user_id();
$level = 0;
if ($user_id > 0 && function_exists('aksrt_get_user_vip_level')) {
$level = (int) aksrt_get_user_vip_level($user_id);
}
// Hide for max VIP if we only have 2 tiers and already VIP.
if ($level >= 2) {
return '';
}
$vip_url = function_exists('aksrt_get_vip_purchase_url')
? aksrt_get_vip_purchase_url()
: (function_exists('aksrt_get_user_center_url') ? aksrt_get_user_center_url('vip') : '#');
$title = $level === 1 ? __('升级会员', 'aksrt') : __('开通会员', 'aksrt');
$icon = !empty($item['icon']) ? (string) $item['icon'] : 'fa fa-diamond';
$cls = $user_id > 0 ? 'float-btn pay-vip' : 'float-btn signin-loader';
$href = $user_id > 0 ? $vip_url : 'javascript:;';
$style = [];
if (!empty($item['color'])) {
$style[] = '--this-color:' . esc_attr((string) $item['color']);
}
if (!empty($item['bg'])) {
$style[] = '--this-bg:' . esc_attr((string) $item['bg']);
}
$style_attr = $style ? ' style="' . implode(';', $style) . '"' : '';
return '<a class="' . esc_attr($cls) . '" href="' . esc_url($href) . '" title="' . esc_attr($title) . '"' . $style_attr . '>'
. '<i class="' . esc_attr($icon) . '" aria-hidden="true"></i>'
. '</a>';
}
endif;
if (!function_exists('aksrt_get_win_runtime_config')) :
/**
* Build window._win payload (zibll zib_win_var subset).
*
* @return array<string,mixed>
*/
function aksrt_get_win_runtime_config(): array {
$post_display = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_post_page_settings()
: [];
$is_mobile = wp_is_mobile();
$list_style = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_post_list_style_settings()
: [];
$signin = function_exists('aksrt_get_login_url')
? aksrt_get_login_url(function_exists('aksrt_get_current_url') ? aksrt_get_current_url() : home_url('/'))
: wp_login_url();
$signup = function_exists('aksrt_get_register_url')
? aksrt_get_register_url()
: wp_registration_url();
$views = 0;
if (is_singular()) {
$views = (int) get_queried_object_id();
}
return [
'views' => $views,
'www' => home_url('/'),
'uri' => get_template_directory_uri(),
'ver' => defined('AKSRT_VERSION') ? AKSRT_VERSION : '3.4.0-dev',
'imgbox' => !isset($post_display['lightbox']) || !empty($post_display['lightbox']) ? '1' : '',
'imgbox_type' => 'group',
'imgbox_thumbs' => !isset($post_display['lightbox_thumbs']) || !empty($post_display['lightbox_thumbs']) ? '1' : '',
'imgbox_zoom' => !isset($post_display['lightbox_zoom']) || !empty($post_display['lightbox_zoom']) ? '1' : '',
'imgbox_full' => !isset($post_display['lightbox_full']) || !empty($post_display['lightbox_full']) ? '1' : '',
'imgbox_play' => !empty($post_display['lightbox_play']) ? '1' : '',
'imgbox_down' => !empty($post_display['lightbox_down']) ? '1' : '',
'sign_type' => class_exists('\AKSRT\Settings\Settings')
? (string) (\AKSRT\Settings\Settings::get_all()['user_sign_type'] ?? 'page')
: 'page',
'signin_url' => $signin,
'signup_url' => $signup,
'ajax_url' => admin_url('admin-ajax.php'),
'ajaxpager' => '1',
'ajax_trigger' => (string) ($list_style['ajax_trigger_text'] ?? __('加载更多', 'aksrt')),
'ajax_nomore' => (string) ($list_style['ajax_nomore_text'] ?? __('没有更多了', 'aksrt')),
'qj_loading' => __('加载中...', 'aksrt'),
'is_mobile' => $is_mobile ? '1' : '',
'is_logged_in' => is_user_logged_in() ? '1' : '',
'user_id' => get_current_user_id(),
'rest_url' => esc_url_raw(rest_url('aksrt/v1')),
'rest_nonce' => wp_create_nonce('wp_rest'),
'nonce' => wp_create_nonce('aksrt_public_nonce'),
];
}
endif;
if (!function_exists('aksrt_print_win_var')) :
/**
* Echo window._win + alias window.aksrtData bridge.
*/
function aksrt_print_win_var(): void {
static $done = false;
if ($done) {
return;
}
$done = true;
$cfg = aksrt_get_win_runtime_config();
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<script type="text/javascript">window._win=' . wp_json_encode($cfg, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . ';'
. 'window.aksrtData=window.aksrtData||{};'
. 'window.aksrtData.ajaxUrl=window.aksrtData.ajaxUrl||window._win.ajax_url;'
. 'window.aksrtData.siteUrl=window.aksrtData.siteUrl||window._win.www;'
. 'window.aksrtData.themeUri=window.aksrtData.themeUri||window._win.uri;'
. 'window.aksrtData.restUrl=window.aksrtData.restUrl||window._win.rest_url;'
. 'window.aksrtData.restNonce=window.aksrtData.restNonce||window._win.rest_nonce;'
. 'window.aksrtData.nonce=window.aksrtData.nonce||window._win.nonce;'
. 'window.aksrtData.imgbox=window._win;'
. '</script>' . "\n";
}
endif;
+12
View File
@@ -150,6 +150,18 @@ trait ScriptsPart1b {
);
}
// Header multi-function publish/VIP cluster
$hmb_css = get_template_directory() . '/assets/css/frontend/nav/header-menu-buttons.css';
if (file_exists($hmb_css)) {
wp_enqueue_style(
'aksrt-header-menu-buttons',
$base_uri . '/assets/css/frontend/nav/header-menu-buttons.css',
[$core_dep],
(string) filemtime($hmb_css)
);
}
// Print stylesheet — only load on singular pages
if (is_singular()) {
wp_enqueue_style(