diff --git a/assets/css/frontend/nav/header-menu-buttons.css b/assets/css/frontend/nav/header-menu-buttons.css new file mode 100644 index 00000000..39cc6f15 --- /dev/null +++ b/assets/css/frontend/nav/header-menu-buttons.css @@ -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; +} diff --git a/assets/js/enhancements.js b/assets/js/enhancements.js index c5314919..28e1d60a 100644 --- a/assets/js/enhancements.js +++ b/assets/js/enhancements.js @@ -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(); diff --git a/footer.php b/footer.php index c04f81fc..4b427406 100644 --- a/footer.php +++ b/footer.php @@ -396,6 +396,18 @@ if ($floating_enabled) : + + - + '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 + } + ?> + diff --git a/header.php b/header.php index 628799c9..e80f6e78 100644 --- a/header.php +++ b/header.php @@ -261,20 +261,26 @@ if (!empty($aksrt_bg_styles)) { - diff --git a/inc/bootstrap.php b/inc/bootstrap.php index 2996a21e..cc8d656e 100644 --- a/inc/bootstrap.php +++ b/inc/bootstrap.php @@ -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'; diff --git a/inc/core-hooks/part-2.php b/inc/core-hooks/part-2.php index 9664fed8..f86f6bc4 100644 --- a/inc/core-hooks/part-2.php +++ b/inc/core-hooks/part-2.php @@ -1,426 +1,433 @@ -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); - ?> - - - -
- - - -
- - - -

- - - - - - -

- - - -
- -
- - - -

-
-
- - -

-
- 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; - ?> - - 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; -}); - -// ============================================================ \ No newline at end of file +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); + ?> + + + +
+ + + +
+ + + +

+ + + + + + +

+ + + +
+ +
+ + + +

+
+
+ + +

+
+ 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; + ?> + + 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; +}); + +// ============================================================ diff --git a/inc/helpers/aksrt-header-menu-buttons.php b/inc/helpers/aksrt-header-menu-buttons.php new file mode 100644 index 00000000..87686a16 --- /dev/null +++ b/inc/helpers/aksrt-header-menu-buttons.php @@ -0,0 +1,188 @@ + 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 + */ + 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 '' + . ' ' + . wp_kses_post($label) + . ''; + } + + $html = ''; + $html .= '' . wp_kses_post($label) . ' '; + $html .= ''; + 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 if present in settings HTML text — keep simple. + $btn = aksrt_render_new_add_btns($cfg['types'] ?? ['post'], $class, $label); + if ($btn !== '') { + $html .= ''; + } + } + + // 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 .= ''; + } + } + + return $html; + } +endif; diff --git a/inc/helpers/aksrt-runtime-win.php b/inc/helpers/aksrt-runtime-win.php new file mode 100644 index 00000000..354c2e0d --- /dev/null +++ b/inc/helpers/aksrt-runtime-win.php @@ -0,0 +1,179 @@ +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 '' + . '' + . '' . esc_html($badge) . '' + . ''; + } +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 '' + . '' + . ''; + } +endif; + +if (!function_exists('aksrt_get_win_runtime_config')) : + /** + * Build window._win payload (zibll zib_win_var subset). + * + * @return array + */ + 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 '' . "\n"; + } +endif; diff --git a/src/AKSRT/Core/ScriptsPart1b.php b/src/AKSRT/Core/ScriptsPart1b.php index e711029a..1b0d75a7 100644 --- a/src/AKSRT/Core/ScriptsPart1b.php +++ b/src/AKSRT/Core/ScriptsPart1b.php @@ -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(