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 .= '' . $btn . '
';
+ }
+ }
+
+ // 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(