feat(navigation): hard-switch to Zibll navigation and Font Awesome 5

This commit is contained in:
kate522 committed 2026-08-18 20:46:21 +08:00
1 parent 3c3ddac8be
commit a0b84977a2
630 files changed
+101647 -11293

No files matched your search

+3 -3
View File
@@ -110,10 +110,10 @@ class Admin {
}
}
// Match frontend FA5 pack so FaIcon / menu glyphs render in the SPA.
// Use the same local FA5 pack as the public stack.
wp_enqueue_style(
'aksrt-font-awesome-5',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css',
'aksrt-font-awesome',
get_template_directory_uri() . '/assets/vendor/fontawesome5/css/all.min.css',
[],
'5.15.4'
);
+7 -8
View File
@@ -56,7 +56,7 @@ trait GlobalControllerPart1 {
if (!empty($item['add_items']) && is_array($item['add_items'])) {
foreach ($item['add_items'] as $sub_item) {
$label = sanitize_text_field($sub_item['label'] ?? '');
$icon = sanitize_text_field($sub_item['icon'] ?? 'fas fa-pen');
$icon = sanitize_text_field($sub_item['icon'] ?? 'fa fas fa-pen');
$url = esc_url_raw($sub_item['url'] ?? '');
if ($label === '') {
continue;
@@ -237,7 +237,7 @@ trait GlobalControllerPart1 {
$icon_dark = sanitize_text_field($item['icon_dark'] ?? '');
$icon_light = sanitize_text_field($item['icon_light'] ?? '');
if ($type === 'theme_mode') {
$icon = 'fas fa-sun';
$icon = 'fa fas fa-sun';
$icon_dark = '';
$icon_light = '';
}
@@ -247,13 +247,12 @@ trait GlobalControllerPart1 {
if ($type === 'pay_vip') {
$link = '';
$hover = '';
if ($icon === '' || str_contains($icon, 'fa-diamond') || $icon === 'fa fa-diamond') {
$icon = 'fas fa-gem';
}
// Ensure FA5 prefix when bare fa-* is stored.
if ($icon !== '' && !preg_match('/\b(fas|far|fab|fal|fad)\b/', $icon)) {
$icon = 'fas ' . ltrim(preg_replace('/^fa\s+/', '', $icon) ?? $icon);
if ($icon === '' || str_contains($icon, 'fa-gem') || $icon === 'fa fas fa-gem') {
$icon = 'fa fas fa-gem';
}
if (!preg_match('/^fa\s+(?:fas|far|fab)\s+fa-[a-z0-9-]+(?:\s+fa-[a-z0-9-]+)*$/i', $icon)) {
$icon = 'fa fas fa-gem';
}
}
return [
+16 -4
View File
@@ -37,22 +37,34 @@ trait GlobalControllerPart2 {
}
public function rest_get_categories(\WP_REST_Request $request): \WP_REST_Response {
$categories = get_categories([
$requested = array_filter(array_map('sanitize_key', explode(',', (string) $request->get_param('taxonomy'))));
$taxonomies = array_values(array_filter($requested ?: ['category'], 'taxonomy_exists'));
if ($taxonomies === []) {
return rest_ensure_response(['code' => 'success', 'data' => []]);
}
$categories = get_terms([
'taxonomy' => $taxonomies,
'orderby' => 'count',
'order' => 'DESC',
'hide_empty' => false,
]);
if (is_wp_error($categories)) {
return rest_ensure_response(['code' => 'success', 'data' => []]);
}
$data = array_map(function ($cat) {
$is_category = $cat->taxonomy === 'category';
return [
'term_id' => (int) $cat->term_id,
'name' => $cat->name,
'slug' => $cat->slug,
'taxonomy' => $cat->taxonomy,
'count' => (int) $cat->count,
'description' => $cat->description,
'cover_id' => (int) get_term_meta($cat->term_id, 'aksrt_category_cover_id', true),
'cover_url' => \AKSRT\Settings\Settings::get_category_cover_url((int) $cat->term_id),
'recommend_desc' => (string) get_term_meta($cat->term_id, 'aksrt_category_recommend_desc', true),
'cover_id' => $is_category ? (int) get_term_meta($cat->term_id, 'aksrt_category_cover_id', true) : 0,
'cover_url' => $is_category ? \AKSRT\Settings\Settings::get_category_cover_url((int) $cat->term_id) : '',
'recommend_desc' => $is_category ? (string) get_term_meta($cat->term_id, 'aksrt_category_recommend_desc', true) : '',
];
}, $categories);
-3
View File
@@ -80,9 +80,6 @@ trait HomepageSettingsRest {
if (isset($params['homepage_tab_limit'])) {
$settings['homepage_tab_limit'] = max(1, min(12, (int) $params['homepage_tab_limit']));
}
if (array_key_exists('homepage_module_hero_enabled', $params)) {
$settings['homepage_module_hero_enabled'] = !empty($params['homepage_module_hero_enabled']);
}
if (array_key_exists('homepage_module_banner_enabled', $params)) {
$settings['homepage_module_banner_enabled'] = !empty($params['homepage_module_banner_enabled']);
}
+14 -14
View File
@@ -1,6 +1,6 @@
<?php
/**
* Native WP nav-menu item options (aksrt_menu_options) with senior submenu JSON.
* Native WP nav-menu item options using Zibll's zib_menu_options meta contract.
*
* @package AKSRT
*/
@@ -41,7 +41,7 @@ class NavMenuOptions {
*/
public static function render_fields($item_id, $item): void {
$item_id = (int) $item_id;
$opts = get_post_meta($item_id, 'aksrt_menu_options', true);
$opts = get_post_meta($item_id, 'zib_menu_options', true);
$opts = is_array($opts) ? $opts : [];
$icon = (string) ($opts['icon'] ?? '');
$badge = (string) ($opts['badge'] ?? '');
@@ -57,9 +57,9 @@ class NavMenuOptions {
?>
<p class="field-aksrt-icon description description-wide">
<label for="edit-menu-item-aksrt-icon-<?php echo esc_attr((string) $item_id); ?>">
<?php esc_html_e('图标 class(如 fas fa-home)', 'aksrt'); ?><br>
<?php esc_html_e('图标 class(如 fa fas fa-home)', 'aksrt'); ?><br>
<input type="text" id="edit-menu-item-aksrt-icon-<?php echo esc_attr((string) $item_id); ?>"
class="widefat" name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][icon]"
class="widefat" name="zib_menu_options[<?php echo esc_attr((string) $item_id); ?>][icon]"
value="<?php echo esc_attr($icon); ?>">
</label>
</p>
@@ -67,7 +67,7 @@ class NavMenuOptions {
<label for="edit-menu-item-aksrt-badge-<?php echo esc_attr((string) $item_id); ?>">
<?php esc_html_e('徽章文字', 'aksrt'); ?><br>
<input type="text" id="edit-menu-item-aksrt-badge-<?php echo esc_attr((string) $item_id); ?>"
class="widefat" name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][badge]"
class="widefat" name="zib_menu_options[<?php echo esc_attr((string) $item_id); ?>][badge]"
value="<?php echo esc_attr($badge); ?>">
</label>
</p>
@@ -75,13 +75,13 @@ class NavMenuOptions {
<label for="edit-menu-item-aksrt-badge-class-<?php echo esc_attr((string) $item_id); ?>">
<?php esc_html_e('徽章 class', 'aksrt'); ?><br>
<input type="text" id="edit-menu-item-aksrt-badge-class-<?php echo esc_attr((string) $item_id); ?>"
class="widefat" name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][badge_class]"
class="widefat" name="zib_menu_options[<?php echo esc_attr((string) $item_id); ?>][badge_class]"
value="<?php echo esc_attr($badge_class); ?>">
</label>
</p>
<p class="field-aksrt-submenu description description-wide">
<label>
<input type="checkbox" name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][submenu_s]" value="1" <?php checked($submenu_s); ?>>
<input type="checkbox" name="zib_menu_options[<?php echo esc_attr((string) $item_id); ?>][submenu_s]" value="1" <?php checked($submenu_s); ?>>
<?php esc_html_e('启用高级子菜单(仅一级菜单)', 'aksrt'); ?>
</label>
</p>
@@ -89,7 +89,7 @@ class NavMenuOptions {
<label for="edit-menu-item-aksrt-submenu-type-<?php echo esc_attr((string) $item_id); ?>">
<?php esc_html_e('高级子菜单类型', 'aksrt'); ?><br>
<select id="edit-menu-item-aksrt-submenu-type-<?php echo esc_attr((string) $item_id); ?>"
name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][submenu_type]">
name="zib_menu_options[<?php echo esc_attr((string) $item_id); ?>][submenu_type]">
<option value="" <?php selected($submenu_type, ''); ?>><?php esc_html_e('无', 'aksrt'); ?></option>
<option value="graphic_card" <?php selected($submenu_type, 'graphic_card'); ?>><?php esc_html_e('图文卡片', 'aksrt'); ?></option>
<option value="multi_column_links" <?php selected($submenu_type, 'multi_column_links'); ?>><?php esc_html_e('多列链接', 'aksrt'); ?></option>
@@ -100,14 +100,14 @@ class NavMenuOptions {
<label for="edit-menu-item-aksrt-graphic-<?php echo esc_attr((string) $item_id); ?>">
<?php esc_html_e('图文卡片 JSON(type=graphic_card)', 'aksrt'); ?><br>
<textarea rows="8" class="widefat code" id="edit-menu-item-aksrt-graphic-<?php echo esc_attr((string) $item_id); ?>"
name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][graphic_card_opts_json]"><?php echo esc_textarea((string) $graphic_json); ?></textarea>
name="zib_menu_options[<?php echo esc_attr((string) $item_id); ?>][graphic_card_opts_json]"><?php echo esc_textarea((string) $graphic_json); ?></textarea>
</label>
</p>
<p class="field-aksrt-multi description description-wide">
<label for="edit-menu-item-aksrt-multi-<?php echo esc_attr((string) $item_id); ?>">
<?php esc_html_e('多列链接 JSON(type=multi_column_links)', 'aksrt'); ?><br>
<textarea rows="8" class="widefat code" id="edit-menu-item-aksrt-multi-<?php echo esc_attr((string) $item_id); ?>"
name="aksrt_menu_options[<?php echo esc_attr((string) $item_id); ?>][multi_column_links_opts_json]"><?php echo esc_textarea((string) $multi_json); ?></textarea>
name="zib_menu_options[<?php echo esc_attr((string) $item_id); ?>][multi_column_links_opts_json]"><?php echo esc_textarea((string) $multi_json); ?></textarea>
</label>
</p>
<?php
@@ -120,11 +120,11 @@ class NavMenuOptions {
public static function save($menu_id, $menu_item_db_id): void {
$menu_item_db_id = (int) $menu_item_db_id;
// phpcs:ignore WordPress.Security.NonceVerification.Missing
if (empty($_POST['aksrt_menu_options'][ $menu_item_db_id ]) || !is_array($_POST['aksrt_menu_options'][ $menu_item_db_id ])) {
if (empty($_POST['zib_menu_options'][ $menu_item_db_id ]) || !is_array($_POST['zib_menu_options'][ $menu_item_db_id ])) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$raw = wp_unslash($_POST['aksrt_menu_options'][ $menu_item_db_id ]);
$raw = wp_unslash($_POST['zib_menu_options'][ $menu_item_db_id ]);
$clean = [
'icon' => sanitize_text_field((string) ($raw['icon'] ?? '')),
@@ -143,7 +143,7 @@ class NavMenuOptions {
$clean['multi_column_links_opts'] = self::sanitize_multi_opts($multi);
}
update_post_meta($menu_item_db_id, 'aksrt_menu_options', $clean);
update_post_meta($menu_item_db_id, 'zib_menu_options', $clean);
}
/**
@@ -257,7 +257,7 @@ class NavMenuOptions {
'columns' => [
[
'title' => '栏目一',
'icon' => 'fas fa-folder',
'icon' => 'fa fas fa-folder',
'link' => ['url' => '', 'text' => '', 'target' => ''],
'items' => [
['title' => '链接 A', 'icon' => '', 'link' => ['url' => home_url('/'), 'text' => '', 'target' => '']],
+300
View File
@@ -0,0 +1,300 @@
<?php
/**
* Per-page Zibll header slider configuration.
*
* @package AKSRT
*/
namespace AKSRT\Admin;
defined('ABSPATH') || exit;
final class PageConfigMetaBox {
private const META_KEY = 'page_config';
private const NONCE_ACTION = 'aksrt_page_config_save';
private const NONCE_NAME = 'aksrt_page_config_nonce';
public static function init(): void {
add_action('add_meta_boxes_page', [self::class, 'register']);
add_action('save_post_page', [self::class, 'save']);
}
public static function register(): void {
add_meta_box(
'aksrt-page-config',
__('页面配置', 'aksrt'),
[self::class, 'render'],
'page',
'normal',
'high'
);
}
/** @param \WP_Post $post */
public static function render($post): void {
$config = get_post_meta((int) $post->ID, self::META_KEY, true);
$config = is_array($config) ? $config : [];
wp_nonce_field(self::NONCE_ACTION, self::NONCE_NAME);
$show_type = (string) ($config['header_slider_show_type'] ?? '');
$devices = [
'header_slider_search_s' => (array) ($config['header_slider_search_s'] ?? []),
'header_slider_card_s' => (array) ($config['header_slider_card_s'] ?? []),
];
?>
<style>
.aksrt-page-config-grid{display:grid;grid-template-columns:220px minmax(0,1fr);gap:14px 20px;align-items:start}
.aksrt-page-config-grid>label{font-weight:600;padding-top:7px}.aksrt-page-config-grid textarea{width:100%;font-family:Consolas,monospace}
.aksrt-page-config-grid .description{margin:4px 0 0}.aksrt-page-config-wide{grid-column:1/-1}
@media(max-width:782px){.aksrt-page-config-grid{grid-template-columns:1fr}.aksrt-page-config-wide{grid-column:auto}}
</style>
<div class="aksrt-page-config-grid">
<label for="aksrt-header-slider-show"><?php esc_html_e('启用顶部多功能组件', 'aksrt'); ?></label>
<div><label><input id="aksrt-header-slider-show" type="checkbox" name="page_config[header_slider_show]" value="1" <?php checked(!empty($config['header_slider_show'])); ?>> <?php esc_html_e('为当前页面使用独立配置', 'aksrt'); ?></label></div>
<label><?php esc_html_e('显示规则', 'aksrt'); ?></label>
<div>
<?php foreach (['' => __('全部显示', 'aksrt'), 'only_pc' => __('仅在 PC 端显示', 'aksrt'), 'only_sm' => __('仅在移动端显示', 'aksrt')] as $value => $label) : ?>
<label style="margin-right:16px"><input type="radio" name="page_config[header_slider_show_type]" value="<?php echo esc_attr($value); ?>" <?php checked($show_type, $value); ?>> <?php echo esc_html($label); ?></label>
<?php endforeach; ?>
</div>
<label for="aksrt-header-slider-nav-color"><?php esc_html_e('导航栏文字颜色', 'aksrt'); ?></label>
<div><input id="aksrt-header-slider-nav-color" type="color" name="page_config[header_slider_nav_color]" value="<?php echo esc_attr((string) ($config['header_slider_nav_color'] ?? '#ffffff')); ?>"></div>
<?php self::render_json_field('header_slider', __('背景内容', 'aksrt'), $config['header_slider'] ?? self::slide_defaults(), 16); ?>
<?php self::render_json_field('header_slider_option', __('背景显示设置', 'aksrt'), $config['header_slider_option'] ?? self::slider_defaults(), 12); ?>
<label><?php esc_html_e('叠加搜索组件', 'aksrt'); ?></label>
<div><?php self::render_devices('header_slider_search_s', $devices['header_slider_search_s']); ?></div>
<?php self::render_json_field('header_slider_search_option', __('搜索组件设置', 'aksrt'), $config['header_slider_search_option'] ?? self::search_defaults(), 12); ?>
<label><?php esc_html_e('叠加封面卡片组件', 'aksrt'); ?></label>
<div><?php self::render_devices('header_slider_card_s', $devices['header_slider_card_s']); ?></div>
<?php self::render_json_field('header_slider_card_option', __('图标卡片设置', 'aksrt'), $config['header_slider_card_option'] ?? self::card_defaults(), 16); ?>
</div>
<p class="description"><?php esc_html_e('复杂字段使用参考主题原始数组结构的 JSON;保存后统一写入 page_config 序列化元数据,不读取任何旧字段。', 'aksrt'); ?></p>
<?php
}
/** @param mixed $value */
private static function render_json_field(string $key, string $label, $value, int $rows): void {
$json = wp_json_encode(is_array($value) ? $value : [], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
?>
<label for="aksrt-<?php echo esc_attr($key); ?>"><?php echo esc_html($label); ?></label>
<div><textarea id="aksrt-<?php echo esc_attr($key); ?>" name="page_config[<?php echo esc_attr($key); ?>]" rows="<?php echo (int) $rows; ?>"><?php echo esc_textarea((string) $json); ?></textarea></div>
<?php
}
/** @param list<string> $selected */
private static function render_devices(string $key, array $selected): void {
foreach (['pc_s' => __('PC 端显示', 'aksrt'), 'm_s' => __('移动端显示', 'aksrt')] as $value => $label) {
printf(
'<label style="margin-right:16px"><input type="checkbox" name="page_config[%1$s][]" value="%2$s" %3$s> %4$s</label>',
esc_attr($key),
esc_attr($value),
checked(in_array($value, $selected, true), true, false),
esc_html($label)
);
}
}
public static function save(int $post_id): void {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!current_user_can('edit_page', $post_id)) {
return;
}
if (!isset($_POST[self::NONCE_NAME]) || !wp_verify_nonce(sanitize_text_field(wp_unslash((string) $_POST[self::NONCE_NAME])), self::NONCE_ACTION)) {
return;
}
if (!isset($_POST['page_config']) || !is_array($_POST['page_config'])) {
delete_post_meta($post_id, self::META_KEY);
return;
}
$raw = wp_unslash($_POST['page_config']);
$config = [
'header_slider_show' => !empty($raw['header_slider_show']),
'header_slider_show_type' => self::enum((string) ($raw['header_slider_show_type'] ?? ''), ['', 'only_pc', 'only_sm']),
'header_slider_nav_color' => sanitize_hex_color((string) ($raw['header_slider_nav_color'] ?? '')) ?: '#ffffff',
'header_slider' => self::sanitize_slides(self::decode_json($raw['header_slider'] ?? '')),
'header_slider_option' => self::sanitize_slider_options(self::decode_json($raw['header_slider_option'] ?? '')),
'header_slider_search_s' => self::sanitize_devices($raw['header_slider_search_s'] ?? []),
'header_slider_search_option' => self::sanitize_search_options(self::decode_json($raw['header_slider_search_option'] ?? '')),
'header_slider_card_s' => self::sanitize_devices($raw['header_slider_card_s'] ?? []),
'header_slider_card_option' => self::sanitize_card_options(self::decode_json($raw['header_slider_card_option'] ?? '')),
];
update_post_meta($post_id, self::META_KEY, $config);
}
/** @param mixed $value @return array<mixed> */
private static function decode_json($value): array {
if (is_array($value)) {
return $value;
}
$decoded = json_decode((string) $value, true);
return is_array($decoded) ? $decoded : [];
}
/** @param mixed $value @return list<string> */
private static function sanitize_devices($value): array {
return array_values(array_intersect(array_map('sanitize_key', (array) $value), ['pc_s', 'm_s']));
}
/** @param list<string> $allowed */
private static function enum(string $value, array $allowed): string {
return in_array($value, $allowed, true) ? $value : $allowed[0];
}
/** @param array<mixed> $slides @return list<array<string,mixed>> */
private static function sanitize_slides(array $slides): array {
$clean = [];
foreach ($slides as $slide) {
if (!is_array($slide)) {
continue;
}
$layers = [];
foreach ((array) ($slide['image_layer'] ?? []) as $layer) {
if (!is_array($layer)) {
continue;
}
$layers[] = [
'image' => esc_url_raw((string) ($layer['image'] ?? '')),
'free_size' => !empty($layer['free_size']),
'align' => self::enum(sanitize_key((string) ($layer['align'] ?? 'center')), ['left', 'center', 'right']),
'parallax' => max(-200, min(200, (int) ($layer['parallax'] ?? 0))),
'parallax_scale' => max(1, min(200, (int) ($layer['parallax_scale'] ?? 100))),
'parallax_opacity' => max(1, min(100, (int) ($layer['parallax_opacity'] ?? 100))),
];
}
$text = is_array($slide['text'] ?? null) ? $slide['text'] : [];
$link = is_array($slide['link'] ?? null) ? $slide['link'] : [];
$clean[] = [
'background' => esc_url_raw((string) ($slide['background'] ?? '')),
'background_video' => esc_url_raw((string) ($slide['background_video'] ?? '')),
'video' => esc_url_raw((string) ($slide['video'] ?? '')),
'hide' => self::enum(sanitize_key((string) ($slide['hide'] ?? '')), ['', 'pc', 'm']),
'link' => [
'url' => esc_url_raw((string) ($link['url'] ?? '')),
'target' => !empty($link['target']) ? '_blank' : '',
'text' => sanitize_text_field((string) ($link['text'] ?? '')),
],
'image_layer' => $layers,
'text' => [
'title' => wp_kses_post((string) ($text['title'] ?? '')),
'desc' => wp_kses_post((string) ($text['desc'] ?? '')),
'text_align' => sanitize_html_class((string) ($text['text_align'] ?? 'left-bottom')),
'text_size_pc' => max(12, min(50, (int) ($text['text_size_pc'] ?? 30))),
'text_size_m' => max(12, min(50, (int) ($text['text_size_m'] ?? 20))),
'parallax' => max(-200, min(200, (int) ($text['parallax'] ?? 40))),
],
];
}
return $clean;
}
/** @param array<mixed> $value @return array<string,mixed> */
private static function sanitize_slider_options(array $value): array {
$defaults = array_merge(self::slider_defaults(), ['scale' => 40, 'max_height' => 500, 'min_height' => 180]);
$value = wp_parse_args($value, $defaults);
return [
'direction' => self::enum(sanitize_key((string) $value['direction']), ['horizontal', 'vertical']),
'loop' => !empty($value['loop']),
'button' => !empty($value['button']),
'pagination' => !empty($value['pagination']),
'effect' => self::enum(sanitize_key((string) $value['effect']), ['slide', 'fade', 'cube', 'coverflow', 'flip']),
'scale_height' => !empty($value['scale_height']),
'scale' => max(10, min(300, (int) $value['scale'])),
'auto_height' => !empty($value['auto_height']),
'max_height' => max(120, min(800, (int) $value['max_height'])),
'min_height' => max(100, min(500, (int) $value['min_height'])),
'pc_height' => max(120, min(800, (int) $value['pc_height'])),
'm_height' => max(100, min(500, (int) $value['m_height'])),
'spacebetween' => max(0, min(500, (int) $value['spacebetween'])),
'speed' => max(0, min(3000, (int) $value['speed'])),
'autoplay' => !empty($value['autoplay']),
'interval' => max(0, min(20, (int) $value['interval'])),
];
}
/** @param array<mixed> $value @return array<string,mixed> */
private static function sanitize_search_options(array $value): array {
$value = wp_parse_args($value, self::search_defaults());
return [
'show_keywords' => !empty($value['show_keywords']),
'popular_limit' => max(2, min(50, (int) $value['popular_limit'])),
'show_input_cat' => !empty($value['show_input_cat']),
'in_cat' => absint($value['in_cat']),
'more_cats' => array_values(array_filter(array_map('absint', (array) $value['more_cats']))),
'show_type' => !empty($value['show_type']),
'in_type' => sanitize_key((string) $value['in_type']),
'before_html' => wp_kses_post((string) $value['before_html']),
'after_html' => wp_kses_post((string) $value['after_html']),
];
}
/** @param array<mixed> $value @return array<string,mixed> */
private static function sanitize_card_options(array $value): array {
$value = wp_parse_args($value, self::card_defaults());
$cards = [];
foreach ((array) $value['cards'] as $card) {
if (!is_array($card)) {
continue;
}
$link = is_array($card['link'] ?? null) ? $card['link'] : [];
$cards[] = [
'title' => wp_kses_post((string) ($card['title'] ?? '')),
'desc' => wp_kses_post((string) ($card['desc'] ?? '')),
'icon' => sanitize_text_field((string) ($card['icon'] ?? '')),
'customize_icon' => wp_kses_post((string) ($card['customize_icon'] ?? '')),
'icon_class' => sanitize_text_field((string) ($card['icon_class'] ?? '')),
'link' => [
'url' => esc_url_raw((string) ($link['url'] ?? '')),
'target' => !empty($link['target']) ? '_blank' : '',
'text' => sanitize_text_field((string) ($link['text'] ?? '')),
],
];
}
return ['show_widget_bg' => !empty($value['show_widget_bg']), 'icon_radius4' => !empty($value['icon_radius4']), 'cards' => $cards];
}
/** @return array<string,mixed> */
private static function slider_defaults(): array {
return ['direction' => 'horizontal', 'loop' => true, 'button' => true, 'pagination' => true, 'effect' => 'slide', 'scale_height' => false, 'auto_height' => false, 'pc_height' => 550, 'm_height' => 280, 'spacebetween' => 0, 'speed' => 0, 'autoplay' => true, 'interval' => 6];
}
/** @return list<array<string,mixed>> */
private static function slide_defaults(): array {
$base = defined('AKSRT_URI') ? trailingslashit(AKSRT_URI) . 'assets/vendor/zibll/img/' : '';
$slides = [];
foreach (['slider-bg.jpg', 'user_t.jpg'] as $image) {
$slides[] = [
'background' => $base . $image,
'link' => ['url' => 'https://www.zibll.com/', 'target' => '_blank'],
'text' => ['desc' => '', 'title' => ''],
'text_align' => 'left-bottom', 'text_parallax' => 30,
'text_size_m' => 20, 'text_size_pc' => 30,
];
}
return $slides;
}
/** @return array<string,mixed> */
private static function search_defaults(): array {
return ['show_keywords' => true, 'popular_limit' => 6, 'show_input_cat' => false, 'in_cat' => 0, 'more_cats' => [], 'show_type' => false, 'in_type' => 'post', 'before_html' => '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div><div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>', 'after_html' => ''];
}
/** @return array<string,mixed> */
private static function card_defaults(): array {
return ['show_widget_bg' => false, 'icon_radius4' => false, 'cards' => [
['icon' => 'zibsvg-vip_1', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'],
['icon' => 'zibsvg-vip_2', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'],
['icon' => 'zibsvg-hot', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'],
['icon' => 'fa fas fa-ioxhost', 'customize_icon' => '', 'icon_class' => 'jb-cyan', 'link' => [], 'title' => '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fas fa-angle-right em12"></span></badge>', 'desc' => '这是一个图标卡片示例'],
]];
}
}
+8 -30
View File
@@ -22,7 +22,7 @@ class PageDisplayController extends ControllerBase {
}
public function register_routes(): void {
// Banners (generic CRUD — hero, banner kinds)
// Homepage content-stream banners.
register_rest_route(self::API_NAMESPACE, '/banners', [
'methods' => 'GET',
'callback' => [$this, 'rest_get_banners'],
@@ -40,42 +40,23 @@ class PageDisplayController extends ControllerBase {
]);
}
private function normalize_banner_kind($kind): string {
return in_array($kind, ['hero', 'banner'], true) ? $kind : 'hero';
}
private function get_banner_kind_query(string $kind): array {
if ('banner' === $kind) {
return [
[
'key' => '_aksrt_kind',
'value' => 'banner',
],
];
}
private function get_banner_kind_query(): array {
return [
'relation' => 'OR',
[
'key' => '_aksrt_kind',
'value' => 'hero',
],
[
'key' => '_aksrt_kind',
'compare' => 'NOT EXISTS',
'value' => 'banner',
],
];
}
public function rest_get_banners(\WP_REST_Request $request): \WP_REST_Response {
$kind = $this->normalize_banner_kind($request->get_param('kind') ?: 'hero');
$args = [
'post_type' => 'aksrt_banner',
'posts_per_page' => 100,
'post_status' => 'any',
'orderby' => 'menu_order',
'order' => 'ASC',
'meta_query' => $this->get_banner_kind_query($kind),
'meta_query' => $this->get_banner_kind_query(),
];
$posts = get_posts($args);
$banners = array_map(function ($post) {
@@ -95,7 +76,6 @@ class PageDisplayController extends ControllerBase {
'enabled' => get_post_meta($post->ID, '_enabled', true) !== '0',
'show_text' => get_post_meta($post->ID, '_show_text', true) !== '0',
'show_meta' => get_post_meta($post->ID, '_show_meta', true) === '1',
'kind' => get_post_meta($post->ID, '_aksrt_kind', true) ?: 'hero',
'sort_order' => $post->menu_order,
'text_size_pc' => get_post_meta($post->ID, '_text_size_pc', true) ?: '',
'text_size_m' => get_post_meta($post->ID, '_text_size_m', true) ?: '',
@@ -108,11 +88,10 @@ class PageDisplayController extends ControllerBase {
public function rest_create_banner(\WP_REST_Request $request): \WP_REST_Response {
$params = $this->get_json_params($request);
$kind = $this->normalize_banner_kind($params['kind'] ?? 'hero');
$title = sanitize_text_field($params['title'] ?? '');
$post_id = wp_insert_post([
// Title is optional in admin UI; keep a non-empty WP title for list readability.
'post_title' => '' !== $title ? $title : ('banner' === $kind ? 'Banner Slide' : 'Hero Slide'),
'post_title' => '' !== $title ? $title : 'Banner Slide',
'post_type' => 'aksrt_banner',
'post_status' => 'publish',
'menu_order' => (int) ($params['sort_order'] ?? 0),
@@ -133,7 +112,7 @@ class PageDisplayController extends ControllerBase {
update_post_meta($post_id, '_enabled', !array_key_exists('enabled', $params) || !empty($params['enabled']) ? '1' : '0');
update_post_meta($post_id, '_show_text', !array_key_exists('show_text', $params) || !empty($params['show_text']) ? '1' : '0');
update_post_meta($post_id, '_show_meta', !empty($params['show_meta']) ? '1' : '0');
update_post_meta($post_id, '_aksrt_kind', $kind);
update_post_meta($post_id, '_aksrt_kind', 'banner');
update_post_meta($post_id, '_text_size_pc', sanitize_text_field($params['text_size_pc'] ?? ''));
update_post_meta($post_id, '_text_size_m', sanitize_text_field($params['text_size_m'] ?? ''));
update_post_meta($post_id, '_text_parallax', !empty($params['text_parallax']) ? '1' : '0');
@@ -146,7 +125,7 @@ class PageDisplayController extends ControllerBase {
public function rest_handle_banner_item(\WP_REST_Request $request): \WP_REST_Response {
$id = absint($request['id']);
if (!$id || get_post_type($id) !== 'aksrt_banner') {
if (!$id || get_post_type($id) !== 'aksrt_banner' || 'banner' !== get_post_meta($id, '_aksrt_kind', true)) {
return new \WP_REST_Response(['code' => 'not_found', 'message' => __('幻灯片不存在', 'aksrt')], 404);
}
@@ -156,7 +135,6 @@ class PageDisplayController extends ControllerBase {
}
$params = $this->get_json_params($request);
$kind = $this->normalize_banner_kind($params['kind'] ?? get_post_meta($id, '_aksrt_kind', true) ?: 'hero');
// Optional title: empty is allowed (UI shows “未命名”); do not 422.
$title = sanitize_text_field($params['title'] ?? '');
@@ -165,7 +143,7 @@ class PageDisplayController extends ControllerBase {
'post_title' => $title,
]);
update_post_meta($id, '_aksrt_kind', $kind);
update_post_meta($id, '_aksrt_kind', 'banner');
update_post_meta($id, '_subtitle', sanitize_text_field($params['subtitle'] ?? ''));
update_post_meta($id, '_description', sanitize_textarea_field($params['description'] ?? ''));
update_post_meta($id, '_image_url', esc_url_raw($params['image_url'] ?? ''));
+52 -42
View File
@@ -315,58 +315,68 @@ class GlobalSchema {
'version' => '2.0.0',
'option_key' => 'aksrt_settings',
'groups' => [
['key' => 'basic', 'title' => '搜索基础', 'fields' => [
['key' => 'search_mode', 'label' => '搜索模式', 'type' => 'radio', 'default' => 'default', 'options' => [
['label' => '默认搜索', 'value' => 'default'],
['label' => 'AJAX 实时搜索', 'value' => 'ajax'],
['label' => '跳转搜索', 'value' => 'redirect'],
]],
['key' => 'search_placeholder', 'label' => '搜索框提示文字', 'type' => 'input', 'default' => '开启精彩搜索'],
]],
['key' => 'content-types', 'title' => '搜索内容类型', 'fields' => [
['key' => 'search_type_post', 'label' => '文章', 'type' => 'switch', 'default' => true],
['key' => 'search_type_user', 'label' => '用户', 'type' => 'switch', 'default' => false],
['key' => 'search_type_category', 'label' => '分类', 'type' => 'switch', 'default' => true],
['key' => 'search_type_tag', 'label' => '标签', 'type' => 'switch', 'default' => true],
['key' => 'search_type_product', 'label' => '商品', 'type' => 'switch', 'default' => false],
['key' => 'search_default_type', 'label' => '默认类型', 'type' => 'select', 'default' => 'post', 'options' => [
['label' => '文章', 'value' => 'post'],
['label' => '用户', 'value' => 'user'],
['label' => '分类', 'value' => 'category'],
['label' => '标签', 'value' => 'tag'],
['label' => '商品', 'value' => 'product'],
]],
]],
['key' => 'features', 'title' => '搜索功能', 'fields' => [
['key' => 'search_history_enabled', 'label' => '搜索历史', 'type' => 'switch', 'default' => true],
['key' => 'hot_search_enabled', 'label' => '热门搜索', 'type' => 'switch', 'default' => true],
['key' => 'hot_search_keywords', 'label' => '热门搜索关键词', 'type' => 'textarea', 'default' => ''],
['key' => 'search_suggestions_enabled', 'label' => '搜索建议', 'type' => 'switch', 'default' => false],
['key' => 'basic', 'title' => '搜索基础', 'fields' => [
['key' => 'search_placeholder', 'label' => '搜索框提示文字', 'type' => 'input', 'default' => '开启精彩搜索'],
]],
['key' => 'content-types', 'title' => '搜索内容类型', 'fields' => [
['key' => 'search_type', 'label' => '显示切换搜索类型按钮', 'type' => 'switch', 'default' => true],
['key' => 'search_type_in', 'label' => '默认搜索类型', 'type' => 'radio', 'default' => 'post', 'options' => [
['label' => '文章', 'value' => 'post'],
['label' => '用户', 'value' => 'user'],
]],
]],
['key' => 'features', 'title' => '搜索功能', 'fields' => [
['key' => 'search_history', 'label' => '搜索历史', 'type' => 'switch', 'default' => true],
['key' => 'search_popular_key', 'label' => '热门搜索', 'type' => 'switch', 'default' => true],
['key' => '404_search_s', 'label' => '在 404 页面显示搜索功能', 'type' => 'switch', 'default' => true],
['key' => 'search_posts', 'label' => '搜索框热门文章', 'type' => 'switch', 'default' => true, 'help' => '在搜索面板中显示热门文章列表'],
['key' => 'search_no_page', 'label' => '排除页面', 'type' => 'switch', 'default' => true, 'help' => '搜索结果中排除页面(仅显示文章)'],
['key' => 'search_exclude_cats', 'label' => '排除分类', 'type' => 'textarea', 'default' => '', 'help' => '搜索结果中排除的分类 ID(逗号分隔)'],
['key' => 'search_exclude_cats', 'label' => '排除分类', 'type' => 'taxonomy_select', 'taxonomy' => ['category', 'shop_cat'], 'multiple' => true, 'default' => [], 'help' => '搜索结果中排除的文章或商品分类'],
['key' => 'search_custom_key_s', 'label' => '自定义匹配范围', 'type' => 'switch', 'default' => true, 'help' => '启用后可配置搜索匹配字段范围(标题/内容/分类/标签等)'],
['key' => 'search_custom_key', 'label' => '匹配字段', 'type' => 'textarea', 'default' => 'title,content', 'help' => '搜索匹配的字段范围(逗号分隔:title/content/excerpt/category/tag/author)'],
['key' => 'search_facets', 'label' => '搜索结果筛选', 'type' => 'switch', 'default' => false, 'help' => '启用搜索结果 taxonomy 筛选面板'],
['key' => 'search_facets_order', 'label' => '筛选排序', 'type' => 'textarea', 'default' => "category\ntag", 'help' => '筛选 fieldset 显示顺序(每行一个 taxonomy slug)'],
['key' => 'search_custom_key', 'label' => '匹配字段', 'type' => 'checkbox', 'default' => ['title', 'content', 'excerpt', 'post_tag', 'forum_topic', 'shop_cat', 'shop_discount'], 'options' => [
['label' => '标题', 'value' => 'title'], ['label' => '内容', 'value' => 'content'], ['label' => '简介', 'value' => 'excerpt'],
['label' => '分类', 'value' => 'category'], ['label' => '标签', 'value' => 'post_tag'], ['label' => '专题', 'value' => 'topics'],
['label' => '评论', 'value' => 'coment'], ['label' => '作者昵称', 'value' => 'user'],
['label' => '[帖子]话题', 'value' => 'forum_topic'], ['label' => '[帖子]标签', 'value' => 'forum_tag'],
['label' => '[商品]分类', 'value' => 'shop_cat'], ['label' => '[商品]特色标签', 'value' => 'shop_tag'], ['label' => '[商品]优惠活动', 'value' => 'shop_discount'],
]],
['key' => 'search_facets', 'label' => '搜索筛选', 'type' => 'fieldset', 'sanitize_type' => 'array', 'default' => [], 'dependsOn' => ['key' => 'search_ms_s', 'value' => false], 'help' => '搜索结果中显示的筛选列表;启用 Meilisearch 后由搜索引擎生成关联筛选。', 'fields' => [
['key' => 'category', 'label' => '[文章] 分类', 'type' => 'taxonomy_select', 'taxonomy' => 'category', 'multiple' => true, 'default' => []],
['key' => 'topics', 'label' => '[文章] 专题', 'type' => 'taxonomy_select', 'taxonomy' => 'topics', 'multiple' => true, 'default' => []],
['key' => 'post_tag', 'label' => '[文章] 标签', 'type' => 'taxonomy_select', 'taxonomy' => 'post_tag', 'multiple' => true, 'default' => []],
['key' => 'plate_id', 'label' => '[论坛帖子] 板块 ID', 'type' => 'input', 'default' => ''],
['key' => 'forum_topic', 'label' => '[论坛帖子] 话题', 'type' => 'taxonomy_select', 'taxonomy' => 'forum_topic', 'multiple' => true, 'default' => []],
['key' => 'forum_tag', 'label' => '[论坛帖子] 标签', 'type' => 'taxonomy_select', 'taxonomy' => 'forum_tag', 'multiple' => true, 'default' => []],
['key' => 'shop_cat', 'label' => '[商品] 分类', 'type' => 'taxonomy_select', 'taxonomy' => 'shop_cat', 'multiple' => true, 'default' => []],
['key' => 'shop_discount', 'label' => '[商品] 优惠活动', 'type' => 'taxonomy_select', 'taxonomy' => 'shop_discount', 'multiple' => true, 'default' => []],
['key' => 'shop_tag', 'label' => '[商品] 特色标签', 'type' => 'taxonomy_select', 'taxonomy' => 'shop_tag', 'multiple' => true, 'default' => []],
]],
]],
['key' => 'category-search', 'title' => '分类搜索', 'fields' => [
['key' => 'search_cat', 'label' => '启用分类搜索', 'type' => 'switch', 'default' => true, 'help' => '在搜索框旁显示分类选择器'],
['key' => 'search_cat_in', 'label' => '默认分类', 'type' => 'input', 'default' => '', 'help' => '默认搜索的分类 ID(留空为全部分类)'],
['key' => 'search_more_cat_obj', 'label' => '显示更多分类', 'type' => 'switch', 'default' => true, 'help' => '展开显示全部分类列表'],
['key' => 'search_cat_in', 'label' => '默认分类', 'type' => 'taxonomy_select', 'taxonomy' => 'category', 'multiple' => false, 'default' => '', 'help' => '留空为全部分类'],
['key' => 'search_more_cat_obj', 'label' => '允许选择的更多分类', 'type' => 'taxonomy_select', 'taxonomy' => 'category', 'multiple' => true, 'default' => []],
]],
['key' => 'popular', 'title' => '热门搜索', 'fields' => [
['key' => 'search_popular_title', 'label' => '标题', 'type' => 'input', 'default' => '热门搜索'],
['key' => 'search_popular_key_num', 'label' => '显示数量', 'type' => 'number', 'default' => 20, 'min' => 1, 'max' => 50],
['key' => 'search_popular_sticky', 'label' => '置顶词(每行一个)', 'type' => 'textarea', 'default' => ''],
]],
['key' => 'meilisearch', 'title' => 'Meilisearch 集成', 'fields' => [
['key' => 'search_ms_enabled', 'label' => '启用 Meilisearch', 'type' => 'switch', 'default' => false, 'help' => '启用后搜索请求将发送至 Meilisearch 服务器'],
['key' => 'search_ms_api_url', 'label' => 'API 地址', 'type' => 'input', 'default' => '', 'help' => 'Meilisearch 服务器 URL'],
['key' => 'search_ms_api_key', 'label' => 'API Key', 'type' => 'input', 'default' => '', 'help' => 'Meilisearch Search API Key(只读密钥)'],
['key' => 'search_ms_index_prefix', 'label' => '索引前缀', 'type' => 'input', 'default' => 'aksrt', 'help' => '索引名称前缀'],
['key' => 'search_ms_synonyms', 'label' => '同义词(JSON)', 'type' => 'textarea', 'default' => '', 'help' => 'Meilisearch 同义词配置 JSON'],
['key' => 'search_popular_key_num', 'label' => '显示数量', 'type' => 'number', 'default' => 20, 'min' => 10, 'max' => 50, 'step' => 2],
['key' => 'search_popular_sticky', 'label' => '置顶关键词', 'type' => 'input', 'default' => '', 'help' => '使用逗号分隔;可追加 &type=user 指定搜索类型'],
]],
['key' => 'meilisearch', 'title' => 'Meilisearch 智能搜索', 'fields' => [
['key' => 'search_ms_s', 'label' => '启用 Meilisearch', 'type' => 'switch', 'default' => false],
['key' => 'search_ms_opt', 'label' => 'Meilisearch 参数', 'type' => 'fieldset', 'sanitize_type' => 'array', 'default' => [
'api_url' => 'http://127.0.0.1:7700', 'api_key' => '', 'index_prefix' => 'aksrt',
'synonyms' => [['key' => 'wordpress', 'val' => 'wp,wordp,wordpre']],
], 'dependsOn' => ['key' => 'search_ms_s', 'value' => true], 'fields' => [
['key' => 'api_url', 'label' => 'API 地址', 'type' => 'input', 'default' => 'http://127.0.0.1:7700'],
['key' => 'api_key', 'label' => 'API 密钥', 'type' => 'input', 'default' => ''],
['key' => 'index_prefix', 'label' => '索引前缀', 'type' => 'input', 'default' => 'aksrt'],
['key' => 'synonyms', 'label' => '同义词', 'type' => 'repeater', 'default' => [['key' => 'wordpress', 'val' => 'wp,wordp,wordpre']], 'addText' => '添加同义词', 'fields' => [
['key' => 'key', 'label' => '关键词', 'type' => 'input', 'default' => ''],
['key' => 'val', 'label' => '同义词', 'type' => 'textarea', 'default' => ''],
]],
]],
]],
],
],
'email' => [
@@ -119,7 +119,7 @@ class SchemaPostListList {
]],
['key' => 'paging_ajax_ias_s', 'label' => 'AJAX 自动加载', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'paging_ajax_s', 'value' => '1']],
['key' => 'ias_max', 'label' => '自动加载页数', 'type' => 'number', 'default' => 3, 'min' => 0, 'max' => 10, 'dependsOn' => ['key' => 'paging_ajax_s', 'value' => '1']],
['key' => 'ajax_trigger', 'label' => '翻页按钮文字', 'type' => 'textarea', 'sanitize_type' => 'html', 'default' => '<i class="fa fa-angle-right"></i>加载更多'],
['key' => 'ajax_trigger', 'label' => '翻页按钮文字', 'type' => 'textarea', 'sanitize_type' => 'html', 'default' => '<i class="fa fas fa-angle-right"></i>加载更多'],
['key' => 'ajax_nomore', 'label' => '列表全部加载完毕文案', 'type' => 'textarea', 'sanitize_type' => 'html', 'default' => '没有更多内容了'],
],
],
+152 -153
View File
@@ -20,16 +20,10 @@ class SchemaPageDisplay {
'version' => '1.1.0',
'option_key' => 'aksrt_settings',
'groups' => [
['key' => 'layout', 'title' => '导航栏布局', 'fields' => [
['key' => 'header_fixed', 'label' => '固定导航栏', 'type' => 'switch', 'default' => true],
['key' => 'header_nav_style', 'label' => '导航栏风格', 'type' => 'radio', 'default' => 'default', 'options' => [
['label' => '默认', 'value' => 'default'],
['label' => '透明', 'value' => 'transparent'],
['label' => '毛玻璃', 'value' => 'blur'],
]],
['key' => 'header_max_width', 'label' => '导航栏最大宽度', 'type' => 'number', 'default' => 1200, 'min' => 0, 'max' => 1600],
['key' => 'header_scroll_down_hide', 'label' => '下滑隐藏导航栏', 'type' => 'switch', 'default' => true],
]],
['key' => 'layout', 'title' => '导航栏布局', 'fields' => [
['key' => 'nav_fixed', 'label' => '导航栏一直固定在顶部', 'type' => 'switch', 'default' => true],
['key' => 'nav_scroll_down_hide', 'label' => '下滚动隐藏,上滚动显示', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'nav_fixed', 'value' => true]],
]],
['key' => 'layout-type', 'title' => '布局类型', 'fields' => [
['key' => 'header_layout', 'label' => '桌面端布局', 'type' => 'image_select', 'default' => '1', 'options' => self::header_layout_options()],
['key' => 'mobile_header_layout', 'label' => '移动端布局', 'type' => 'image_select', 'default' => 'center', 'options' => self::mobile_header_layout_options()],
@@ -39,18 +33,15 @@ class SchemaPageDisplay {
['label' => '右侧滑出', 'value' => 'right'],
]],
]],
['key' => 'components', 'title' => '导航组件', 'fields' => [
['key' => 'header_search_enabled', 'label' => '搜索入口', 'type' => 'switch', 'default' => true],
['key' => 'header_user_menu', 'label' => '用户菜单', 'type' => 'switch', 'default' => true],
['key' => 'header_mobile_drawer', 'label' => '移动端抽屉导航', 'type' => 'switch', 'default' => true],
['key' => 'header_nav_pay_vip', 'label' => '导航栏开通会员按钮', 'type' => 'switch', 'default' => true],
['key' => 'header_nav_user_pay_vip', 'label' => '用户框开通会员按钮', 'type' => 'switch', 'default' => true],
]],
['key' => 'newposts', 'title' => '发布按钮', 'fields' => [
['key' => 'header_newposts_enabled', 'label' => '启用发布按钮', 'type' => 'switch', 'default' => true],
['key' => 'header_newposts_text', 'label' => '按钮文案', 'type' => 'input', 'default' => '<i class="fa fa-pencil"></i> 发布'],
['key' => 'header_newposts_radius', 'label' => '按钮圆角(胶囊)', 'type' => 'switch', 'default' => true],
['key' => 'header_newposts_class', 'label' => '按钮颜色', 'type' => 'select', 'default' => 'jb-blue', 'options' => [
['key' => 'components', 'title' => '导航组件', 'fields' => [
['key' => 'nav_pay_vip', 'label' => '导航栏开通会员按钮', 'type' => 'switch', 'default' => true],
['key' => 'nav_user_pay_vip', 'label' => '用户框开通会员按钮', 'type' => 'switch', 'default' => true],
]],
['key' => 'newposts', 'title' => '发布按钮', 'fields' => [
['key' => 'nav_newposts', 'label' => '启用发布按钮', 'type' => 'switch', 'default' => true],
['key' => 'nav_newposts_text', 'label' => '按钮文案', 'type' => 'input', 'default' => '<i class="fa fas fa-fw fa-pen"></i>发布', 'dependsOn' => ['key' => 'nav_newposts', 'value' => true]],
['key' => 'nav_newposts_radius', 'label' => '按钮圆角(胶囊)', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'nav_newposts', 'value' => true]],
['key' => 'nav_newposts_class', 'label' => '按钮颜色', 'type' => 'select', 'default' => 'jb-blue', 'dependsOn' => ['key' => 'nav_newposts', 'value' => true], 'options' => [
['label' => '蓝色', 'value' => 'jb-blue'],
['label' => '红色', 'value' => 'jb-red'],
['label' => '绿色', 'value' => 'jb-green'],
@@ -58,13 +49,16 @@ class SchemaPageDisplay {
['label' => '紫色', 'value' => 'jb-purple'],
['label' => '粉色', 'value' => 'jb-pink'],
]],
['key' => 'header_newposts_types', 'label' => '发布类型', 'type' => 'checkbox', 'default' => ['post'], 'options' => [
['label' => '文章', 'value' => 'post'],
]],
['key' => 'header_user_newposts_btn', 'label' => '用户卡发布类型', 'type' => 'select', 'default' => 'post', 'options' => [
['label' => '文章', 'value' => 'post'],
]],
['key' => 'header_user_newposts_text', 'label' => '用户卡发布文案', 'type' => 'input', 'default' => '发布内容'],
['key' => 'nav_newposts_btns', 'label' => '需显示的按钮', 'type' => 'checkbox', 'default' => ['post', 'bbs_topic', 'bbs_plate', 'bbs_posts'], 'dependsOn' => ['key' => 'nav_newposts', 'value' => true], 'options' => [
['label' => '文章', 'value' => 'post'],
['label' => '论坛话题', 'value' => 'bbs_topic'],
['label' => '论坛版块', 'value' => 'bbs_plate'],
['label' => '论坛帖子', 'value' => 'bbs_posts'],
]],
['key' => 'nav_user_newposts_btn', 'label' => '用户卡发布类型', 'type' => 'select', 'default' => 'post', 'options' => [
['label' => '文章', 'value' => 'post'],
]],
['key' => 'nav_user_newposts_btn_text', 'label' => '用户卡发布文案', 'type' => 'input', 'default' => '发布文章'],
]],
['key' => 'color', 'title' => '颜色设置', 'fields' => [
['key' => 'header_theme_custom', 'label' => '自定义导航栏颜色', 'type' => 'switch', 'default' => false],
@@ -74,91 +68,59 @@ class SchemaPageDisplay {
]],
],
],
'header-components' => [
'key' => 'header-components',
'title' => '顶部多功能组件',
'description' => '配置顶部组件的显示范围、设备规则、轮播参数、搜索覆盖层与图标卡片。幻灯片图片/文案内容请到「Hero 轮播」「Banner 轮播」管理。',
'version' => '1.1.0',
'option_key' => 'aksrt_settings',
'groups' => [
['key' => 'visibility', 'title' => '显示规则', 'fields' => [
['key' => 'header_components_search_enabled', 'label' => '启用搜索覆盖层', 'type' => 'switch', 'default' => true],
['key' => 'header_components_cards_enabled', 'label' => '启用图标卡片', 'type' => 'switch', 'default' => false],
['key' => 'header_components_show_on', 'label' => '按页面类型启用', 'type' => 'checkbox', 'default' => ['home'], 'options' => [
['label' => '首页', 'value' => 'home'],
['label' => '分类页', 'value' => 'category'],
['label' => '标签页', 'value' => 'tag'],
['label' => '用户页', 'value' => 'author'],
['label' => '文章页', 'value' => 'single'],
['label' => '搜索页', 'value' => 'search'],
['label' => '其它页面', 'value' => 'page'],
]],
['key' => 'header_components_device_visibility', 'label' => '设备显示规则', 'type' => 'radio', 'default' => '', 'options' => [
['label' => '全部', 'value' => ''],
['label' => '仅电脑', 'value' => 'only_pc'],
['label' => '仅移动', 'value' => 'only_sm'],
]],
]],
['key' => 'nav-color', 'title' => '导航栏配色', 'fields' => [
['key' => 'header_components_nav_color', 'label' => '导航栏文字颜色', 'type' => 'color', 'default' => '#ffffff'],
]],
['key' => 'slider-config', 'title' => '幻灯片配置', 'fields' => [
['key' => 'slider_config_direction', 'label' => '滑动方向', 'type' => 'radio', 'default' => 'horizontal', 'dependsOn' => ['key' => 'header_components_show_on', 'not' => []], 'options' => [
['label' => '水平', 'value' => 'horizontal'],
['label' => '垂直', 'value' => 'vertical'],
]],
['key' => 'slider_config_speed', 'label' => '切换速度(ms)', 'type' => 'number', 'default' => 300, 'min' => 100, 'max' => 3000, 'dependsOn' => ['key' => 'header_components_show_on', 'not' => []]],
['key' => 'slider_config_button', 'label' => '显示前进后退按钮', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'header_components_show_on', 'not' => []]],
['key' => 'slider_config_scale_height', 'label' => '缩放高度', 'type' => 'switch', 'default' => false, 'dependsOn' => ['key' => 'header_components_show_on', 'not' => []]],
['key' => 'slider_config_scale', 'label' => '缩放效果', 'type' => 'switch', 'default' => false, 'dependsOn' => ['key' => 'header_components_show_on', 'not' => []]],
['key' => 'slider_config_max_height', 'label' => '最大高度', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'header_components_show_on', 'not' => []]],
['key' => 'slider_config_min_height', 'label' => '最小高度', 'type' => 'input', 'default' => '', 'dependsOn' => ['key' => 'header_components_show_on', 'not' => []]],
]],
['key' => 'search', 'title' => '搜索组件', 'fields' => [
['key' => 'header_components_search_pc', 'label' => 'PC 端显示搜索', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'header_components_search_enabled', 'value' => true]],
['key' => 'header_components_search_mobile', 'label' => '移动端显示搜索', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'header_components_search_enabled', 'value' => true]],
['key' => 'header_components_search_show_keywords', 'label' => '热门搜索', 'type' => 'switch', 'default' => true, 'dependsOn' => ['key' => 'header_components_search_enabled', 'value' => true]],
['key' => 'header_components_search_popular_limit', 'label' => '关键词最多显示', 'type' => 'number', 'default' => 6, 'min' => 2, 'max' => 50, 'dependsOn' => ['key' => 'header_components_search_show_keywords', 'value' => true]],
['key' => 'header_components_search_show_input_cat', 'label' => '显示分类搜索', 'type' => 'switch', 'default' => false, 'dependsOn' => ['key' => 'header_components_search_enabled', 'value' => true]],
['key' => 'header_components_search_show_type', 'label' => '显示类型切换', 'type' => 'switch', 'default' => false, 'dependsOn' => ['key' => 'header_components_search_enabled', 'value' => true]],
[
'key' => 'header_components_search_before_html',
'label' => '搜索上方额外内容',
'type' => 'textarea',
'sanitize_type' => 'html',
'default' => '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div>
<div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>',
'dependsOn' => ['key' => 'header_components_search_enabled', 'value' => true],
'help' => 'Hero 主标题/副标题写在这里(支持 HTML)。勿依赖幻灯片文案,以免与搜索重叠;请注意组件总高度。',
],
[
'key' => 'header_components_search_after_html',
'label' => '搜索下方额外内容',
'type' => 'textarea',
'sanitize_type' => 'html',
'default' => '',
'dependsOn' => ['key' => 'header_components_search_enabled', 'value' => true],
'help' => '支持 HTML;请注意组件总高度。',
],
]],
['key' => 'cards', 'title' => '图标卡片样式', 'fields' => [
['key' => 'header_components_filter_blur_devices', 'label' => '组件高斯模糊特效', 'type' => 'checkbox', 'default' => ['pc', 'mobile'], 'options' => [
['label' => 'PC', 'value' => 'pc'],
['label' => '移动端', 'value' => 'mobile'],
]],
['key' => 'header_components_card_show_devices', 'label' => '卡片显示设备', 'type' => 'checkbox', 'default' => ['pc', 'mobile'], 'dependsOn' => ['key' => 'header_components_cards_enabled', 'value' => true], 'options' => [
['label' => 'PC', 'value' => 'pc'],
['label' => '移动端', 'value' => 'mobile'],
]],
['key' => 'header_components_card_shared_bg', 'label' => '共享卡片背景', 'type' => 'switch', 'default' => false, 'dependsOn' => ['key' => 'header_components_cards_enabled', 'value' => true]],
['key' => 'header_components_card_icon_shape', 'label' => '图标形状', 'type' => 'radio', 'default' => 'circle', 'dependsOn' => ['key' => 'header_components_cards_enabled', 'value' => true], 'options' => [
['label' => '圆形', 'value' => 'circle'],
['label' => '方形', 'value' => 'square'],
]],
]],
['key' => 'icon-cards', 'title' => '图标卡片列表', 'fields' => [
['key' => 'header_components_icon_cards', 'label' => '图标卡片', 'type' => 'repeater', 'sanitize_type' => 'array', 'default' => [], 'dependsOn' => ['key' => 'header_components_cards_enabled', 'value' => true]],
]],
'header-components' => [
'key' => 'header-components',
'title' => '顶部多功能组件',
'description' => 'Zibll 顶部幻灯、搜索覆盖层与图标卡片的原始字段契约。',
'version' => '2.0.0',
'option_key' => 'aksrt_settings',
'groups' => [
['key' => 'visibility', 'title' => '显示规则', 'fields' => [
['key' => 'header_slider_show', 'label' => '启用顶部多功能组件的页面', 'type' => 'checkbox', 'default' => [], 'options' => [
['label' => '首页', 'value' => 'home'],
['label' => '分类页', 'value' => 'category'],
['label' => '标签页', 'value' => 'tag'],
['label' => '用户页', 'value' => 'author'],
['label' => '文章页', 'value' => 'single'],
['label' => '搜索页', 'value' => 'search'],
['label' => '其它页面', 'value' => 'page'],
['label' => '专题页', 'value' => 'topics'],
['label' => '论坛首页', 'value' => 'forum_home'],
['label' => '论坛版块', 'value' => 'forum_plate'],
['label' => '论坛帖子', 'value' => 'forum_post'],
]],
['key' => 'header_slider_show_type', 'label' => '显示规则', 'type' => 'radio', 'default' => '', 'dependsOn' => ['key' => 'header_slider_show', 'not' => []], 'options' => [
['label' => '全部', 'value' => ''],
['label' => '仅电脑', 'value' => 'only_pc'],
['label' => '仅移动', 'value' => 'only_sm'],
]],
['key' => 'header_slider_nav_color', 'label' => '导航栏文字颜色', 'type' => 'color', 'default' => '#ffffff', 'dependsOn' => ['key' => 'header_slider_show', 'not' => []]],
]],
['key' => 'slides', 'title' => '幻灯片', 'fields' => [
['key' => 'header_slider', 'label' => '幻灯片项目', 'type' => 'repeater', 'sanitize_type' => 'array', 'default' => self::header_slider_defaults(), 'addText' => '添加幻灯片', 'fields' => [
['key' => 'background', 'label' => '背景图片', 'type' => 'media', 'default' => ''],
['key' => 'background_video', 'label' => '视频背景', 'type' => 'media', 'default' => '', 'help' => 'PC 端视频优先;移动端仅显示背景图片。'],
['key' => 'video', 'label' => '视频内容', 'type' => 'input', 'default' => ''],
['key' => 'hide', 'label' => '隐藏设备', 'type' => 'radio', 'default' => '', 'options' => [
['label' => '不隐藏', 'value' => ''],
['label' => 'PC 端不显示', 'value' => 'pc'],
['label' => '移动端不显示', 'value' => 'm'],
]],
['key' => 'link', 'label' => '跳转链接', 'type' => 'json', 'sanitize_type' => 'array', 'default' => ['url' => '', 'target' => '', 'text' => '']],
['key' => 'image_layer', 'label' => '叠加图层', 'type' => 'json', 'sanitize_type' => 'array', 'default' => [], 'help' => '每层支持 image、free_size、align、parallax、parallax_scale、parallax_opacity。'],
['key' => 'text', 'label' => '叠加文案', 'type' => 'json', 'sanitize_type' => 'array', 'default' => ['title' => '', 'desc' => '', 'text_align' => 'left-bottom', 'text_size_pc' => 30, 'text_size_m' => 20, 'parallax' => 40]],
]],
['key' => 'header_slider_option', 'label' => '幻灯片参数', 'type' => 'json', 'sanitize_type' => 'array', 'default' => self::header_slider_option_defaults()],
]],
['key' => 'search', 'title' => '搜索组件', 'fields' => [
['key' => 'header_slider_search_s', 'label' => '显示搜索组件', 'type' => 'checkbox', 'default' => ['pc_s', 'm_s'], 'options' => self::device_options()],
['key' => 'header_slider_search_option', 'label' => '搜索组件参数', 'type' => 'json', 'sanitize_type' => 'array', 'default' => self::header_slider_search_defaults()],
]],
['key' => 'cards', 'title' => '图标卡片组件', 'fields' => [
['key' => 'header_slider_card_s', 'label' => '显示图标卡片', 'type' => 'checkbox', 'default' => ['pc_s', 'm_s'], 'options' => self::device_options()],
['key' => 'header_slider_card_option', 'label' => '图标卡片参数', 'type' => 'json', 'sanitize_type' => 'array', 'default' => self::header_slider_card_defaults()],
['key' => 'header_slider_filter_blur', 'label' => '组件高斯模糊特效', 'type' => 'checkbox', 'default' => ['pc_s', 'm_s'], 'options' => self::device_options()],
]],
],
],
'category' => [
@@ -341,43 +303,6 @@ class SchemaPageDisplay {
]],
],
],
'menu-decoration' => [
'key' => 'menu-decoration',
'title' => '菜单装饰',
'version' => '1.0.0',
'option_key' => 'aksrt_settings',
'groups' => [
['key' => 'icon', 'title' => '菜单图标', 'fields' => [
['key' => 'menu_icon_enabled', 'label' => '显示菜单图标', 'type' => 'switch', 'default' => true],
['key' => 'menu_badge_enabled', 'label' => '显示菜单徽章', 'type' => 'switch', 'default' => true],
]],
['key' => 'submenu', 'title' => '下拉子菜单', 'fields' => [
['key' => 'menu_submenu_style', 'label' => '子菜单样式', 'type' => 'radio', 'default' => 'dropdown', 'options' => [
['label' => '普通下拉', 'value' => 'dropdown'],
['label' => '多列下拉', 'value' => 'mega'],
['label' => '图文卡片', 'value' => 'cards'],
]],
['key' => 'menu_submenu_columns', 'label' => '多列列数', 'type' => 'number', 'default' => 1, 'min' => 1, 'max' => 5],
['key' => 'menu_submenu_width', 'label' => '子菜单宽度 (px)', 'type' => 'number', 'default' => 220, 'min' => 160, 'max' => 800],
]],
['key' => 'effect', 'title' => '交互效果', 'fields' => [
['key' => 'menu_hover_effect', 'label' => 'Hover 效果', 'type' => 'radio', 'default' => 'underline', 'options' => [
['label' => '下划线', 'value' => 'underline'],
['label' => '背景色', 'value' => 'background'],
['label' => '文字变色', 'value' => 'color'],
['label' => '无效果', 'value' => 'none'],
]],
['key' => 'menu_item_padding', 'label' => '菜单项内边距 (px)', 'type' => 'number', 'default' => 12, 'min' => 4, 'max' => 32],
]],
['key' => 'mobile', 'title' => '移动端菜单', 'fields' => [
['key' => 'menu_mobile_style', 'label' => '移动端菜单样式', 'type' => 'radio', 'default' => 'drawer', 'options' => [
['label' => '抽屉', 'value' => 'drawer'],
['label' => '全屏', 'value' => 'fullscreen'],
['label' => '下拉', 'value' => 'dropdown'],
]],
]],
],
],
'footer' => [
'key' => 'footer',
'title' => '底部页脚',
@@ -465,8 +390,82 @@ class SchemaPageDisplay {
];
}
/** @return list<array{label:string,value:string,image:string}> */
private static function header_layout_options(): array {
/** @return list<array{label:string,value:string}> */
private static function device_options(): array {
return [
['label' => '电脑端', 'value' => 'pc_s'],
['label' => '移动端', 'value' => 'm_s'],
];
}
/** @return list<array<string,mixed>> */
private static function header_slider_defaults(): array {
$base = defined('AKSRT_URI') ? trailingslashit(AKSRT_URI) . 'assets/vendor/zibll/img/' : '';
$slides = [];
foreach (['slider-bg.jpg', 'user_t.jpg'] as $image) {
$slides[] = [
'background' => $base . $image,
'link' => ['url' => 'https://www.zibll.com/', 'target' => '_blank'],
'text' => ['desc' => '', 'title' => ''],
'text_align' => 'left-bottom',
'text_parallax' => 30,
'text_size_m' => 20,
'text_size_pc' => 30,
];
}
return $slides;
}
/** @return array<string,mixed> */
private static function header_slider_option_defaults(): array {
return [
'direction' => 'horizontal',
'loop' => true,
'button' => true,
'pagination' => true,
'effect' => 'slide',
'scale_height' => false,
'auto_height' => false,
'pc_height' => 550,
'm_height' => 280,
'spacebetween' => 0,
'speed' => 0,
'autoplay' => true,
'interval' => 6,
];
}
/** @return array<string,mixed> */
private static function header_slider_search_defaults(): array {
return [
'show_keywords' => true,
'popular_limit' => 6,
'show_input_cat' => false,
'in_cat' => '',
'more_cats' => [],
'show_type' => false,
'in_type' => 'post',
'before_html' => '<div class="em16 font-bold mb10">更优雅的WordPress主题</div><div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>',
'after_html' => '',
];
}
/** @return array<string,mixed> */
private static function header_slider_card_defaults(): array {
return [
'show_widget_bg' => false,
'icon_radius4' => false,
'cards' => [
['icon' => 'zibsvg-vip_1', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'],
['icon' => 'zibsvg-vip_2', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'],
['icon' => 'zibsvg-hot', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'],
['icon' => 'fa fas fa-ioxhost', 'customize_icon' => '', 'icon_class' => 'jb-cyan', 'link' => [], 'title' => '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fas fa-angle-right em12"></span></badge>', 'desc' => '这是一个图标卡片示例'],
],
];
}
/** @return list<array{label:string,value:string,image:string}> */
private static function header_layout_options(): array {
$base = defined('AKSRT_URI') ? trailingslashit(AKSRT_URI) . 'assets/images/header-layout/' : '';
return [
['label' => '布局 1(经典)', 'value' => '1', 'image' => $base . 'header_layout_1.png'],
+1 -1
View File
@@ -128,7 +128,7 @@ class WeixinGzh {
'user_id' => 0,
]);
$html = '<img class="signin-qrcode-img" src="' . esc_url($img) . '" alt="" style="width:160px;height:160px;" />';
$html .= '<p class="text-center mt10 em09 muted-2-color"><i class="fab fa-weixin c-green"></i> ' . esc_html__('微信扫码登录', 'aksrt') . '</p>';
$html .= '<p class="text-center mt10 em09 muted-2-color"><i class="fa fab fa-weixin c-green"></i> ' . esc_html__('微信扫码登录', 'aksrt') . '</p>';
return new \WP_REST_Response([
'success' => true,
'data' => [
+2 -2
View File
@@ -165,7 +165,7 @@ trait VipServiceModal {
$icon_url = esc_url((string) ($levels[$level]['img_icon'] ?? ''));
$icon = $icon_url !== ''
? '<img' . aksrt_get_lazy_attr('lazy_other', $icon_url, 'aksrt-vip-level-icon') . ' alt="" decoding="async">'
: '<i class="fas fa-gem" aria-hidden="true"></i>';
: '<i class="fa fas fa-gem" aria-hidden="true"></i>';
$html = '<div class="vip-card pointer level-' . $level . ' vip-theme' . $level . $cls . '" vip-level="' . $level . '">';
$html .= '<div class="vip-baicon" aria-hidden="true">' . $icon . '</div>';
$html .= '<div class="vip-img abs-right">' . $icon . '</div>';
@@ -177,7 +177,7 @@ trait VipServiceModal {
$html .= $equity_html;
$html .= '<a class="but jb-blue radius payvip-button" href="javascript:;">'
. esc_html(sprintf(__('开通%s', 'aksrt'), $name))
. '<span class="ml6"><i class="fas fa-chevron-circle-right" aria-hidden="true"></i></span></a>';
. '<span class="ml6"><i class="fa fas fa-chevron-circle-right" aria-hidden="true"></i></span></a>';
$html .= '</div></div>';
return $html;
}
+1 -1
View File
@@ -324,7 +324,7 @@ class Visibility {
$wrapper_class = 'aksrt-hidden-content aksrt-hidden-content--locked aksrt-hidden-content--' . esc_attr($mode);
$html = '<div class="' . $wrapper_class . '" data-aksrt-visibility-mode="' . esc_attr($mode) . '" data-aksrt-visibility-pid="' . esc_attr((string) $pid) . '">';
$html .= '<div class="aksrt-hidden-content__message">';
$html .= '<i class="fas fa-lock" aria-hidden="true"></i> ';
$html .= '<i class="fa fas fa-lock" aria-hidden="true"></i> ';
$html .= '<span>' . esc_html($message) . '</span>';
$html .= '</div>';
+2 -4
View File
@@ -108,7 +108,7 @@ class HomeModules {
* 全屏模块类型(不受侧栏约束)。
*/
public static function fullbleed_types(): array {
return ['hero'];
return [];
}
/**
@@ -177,7 +177,7 @@ class HomeModules {
public static function allowed_types(): array {
return [
'hero', 'banner', 'category', 'tabs', 'ranking',
'banner', 'category', 'tabs', 'ranking',
'recent', 'tag_cloud', 'friend_links', 'html', 'hotspot',
'category_recommend_cards',
// Phase 5: 运营型模块
@@ -203,7 +203,6 @@ class HomeModules {
case 'mixed':
return [
['type' => 'hero', 'config' => []],
['type' => 'recent', 'config' => ['count' => 6, 'layout' => 'card']],
['type' => 'category', 'config' => ['count' => 6, 'columns' => 3]],
['type' => 'category', 'config' => ['count' => 6, 'columns' => 3]],
@@ -212,7 +211,6 @@ class HomeModules {
case 'resource_standard':
default:
return [
['type' => 'hero', 'config' => []],
['type' => 'tabs', 'config' => ['count' => 8]],
['type' => 'recent', 'config' => ['count' => 8, 'layout' => 'card']],
['type' => 'ranking', 'config' => ['metric' => 'downloads', 'count' => 6]],
+1 -24
View File
@@ -34,32 +34,9 @@ class Scripts {
add_action('wp_footer', [$this, 'output_custom_footer_codes'], 99);
add_action('wp_ajax_aksrt_frontend_debug', [$this, 'handle_frontend_debug']);
add_action('wp_ajax_nopriv_aksrt_frontend_debug', [$this, 'handle_frontend_debug']);
add_action('wp_ajax_aksrt_search_history', [$this, 'handle_search_history']);
add_action('wp_ajax_aksrt_search_suggestions', [$this, 'handle_search_suggestions']);
add_action('wp_ajax_nopriv_aksrt_search_suggestions', [$this, 'handle_search_suggestions']);
add_filter('body_class', [$this, 'body_classes']);
add_filter('wp_resource_hints', [$this, 'resource_hints'], 10, 2);
}
/**
* 字体 CDN 的 preconnect 提示(提前 DNS + TLS 握手,加速首屏字体加载)
*/
public function resource_hints(array $hints, string $relation): array {
if ('preconnect' === $relation) {
$hints[] = [
'href' => 'https://fonts.googleapis.com',
'crossorigin',
];
$hints[] = [
'href' => 'https://fonts.gstatic.com',
'crossorigin',
];
$hints[] = [
'href' => 'https://cdn.jsdelivr.net',
'crossorigin',
];
}
return $hints;
}
}
}
+45 -154
View File
@@ -13,7 +13,19 @@ trait ScriptsPart1b {
$base_uri = get_template_directory_uri();
$version = AKSRT_VERSION;
wp_enqueue_script('jquery');
$zibll_uri = $base_uri . '/assets/vendor/zibll';
$fa5_uri = $base_uri . '/assets/vendor/fontawesome5';
// Zibll's frontend runtime is the single public dependency stack.
wp_deregister_script('jquery');
wp_register_script(
'jquery',
$zibll_uri . '/js/libs/jquery.min.js',
[],
'1.9.1',
false
);
wp_enqueue_script('jquery');
wp_enqueue_script(
'aksrt-passive-events',
@@ -23,22 +35,12 @@ trait ScriptsPart1b {
false
);
wp_enqueue_style(
'bootstrap5',
'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css',
[],
'5.3.3'
);
wp_enqueue_style('_bootstrap', $zibll_uri . '/css/bootstrap.min.css', [], '3.4.1');
wp_enqueue_style('_fontawesome', $fa5_uri . '/css/all.min.css', [], '5.15.4');
wp_enqueue_style('_main', $zibll_uri . '/css/main.min.css', ['_bootstrap', '_fontawesome'], $version);
wp_enqueue_script('bootstrap', $zibll_uri . '/js/libs/bootstrap.min.js', ['jquery'], '3.4.1', true);
wp_enqueue_script(
'bootstrap5',
'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js',
['jquery'],
'5.3.3',
true
);
wp_enqueue_style('aksrt-style', get_stylesheet_uri(), ['bootstrap5'], $version);
wp_enqueue_style('aksrt-style', get_stylesheet_uri(), ['_main'], $version);
$lazy_animation = class_exists('\AKSRT\Settings\Settings')
? (string) \AKSRT\Settings\Settings::get_value('lazy_animation', 'blur')
: 'blur';
@@ -101,41 +103,16 @@ trait ScriptsPart1b {
);
};
// 4a. 全站必加 — 优先使用合并文件
$frontend_bundle = get_template_directory() . '/assets/css/build/frontend-base.min.css';
if (file_exists($frontend_bundle)) {
wp_enqueue_style(
'aksrt-frontend-bundle',
$base_uri . '/assets/css/build/frontend-base.min.css',
[$core_dep],
filemtime($frontend_bundle) ?: $version
);
// Keep shell-level source overrides live during the refactor.
foreach (['base', 'nav', 'footer'] as $shell_slug) {
$shell_css_path = get_template_directory() . '/assets/css/frontend/' . $shell_slug . '.css';
if (file_exists($shell_css_path)) {
wp_enqueue_style(
'aksrt-shell-' . $shell_slug,
$base_uri . '/assets/css/frontend/' . $shell_slug . '.css',
['aksrt-frontend-bundle'],
filemtime($shell_css_path) ?: $version
);
}
}
} else {
$enqueue_module('base');
$enqueue_module('zibll-compat-vars');
$enqueue_module('card-primitives');
$enqueue_module('overlay-primitives');
$enqueue_module('nav');
$enqueue_module('layout');
$enqueue_module('footer');
$enqueue_module('floating-buttons');
$enqueue_module('theme-background');
$enqueue_module('menu-decorations');
$enqueue_module('enhancements');
}
// AKSRT domain styles load after Zibll main.css. The old aggregate is
// intentionally not used because it contains the removed navigation CSS.
$enqueue_module('base');
$enqueue_module('card-primitives');
$enqueue_module('overlay-primitives');
$enqueue_module('layout');
$enqueue_module('footer');
$enqueue_module('floating-buttons');
$enqueue_module('theme-background');
$enqueue_module('enhancements');
// 4a-b. 全局补充样式(骨架屏、空状态、分页、加载指示器)
foreach (['skeleton', 'empty-state', 'pagination', 'ajax-spinner', 'modal-runtime'] as $slug) {
@@ -150,73 +127,6 @@ trait ScriptsPart1b {
}
}
// Header user-box density (check-in / wallet / signout modal)
$hub_css = get_template_directory() . '/assets/css/frontend/nav/header-userbox.css';
if (file_exists($hub_css)) {
wp_enqueue_style(
'aksrt-header-userbox',
$base_uri . '/assets/css/frontend/nav/header-userbox.css',
[$core_dep],
(string) filemtime($hub_css)
);
}
$hub_js = get_template_directory() . '/assets/js/header-userbox.js';
if (file_exists($hub_js)) {
wp_enqueue_script(
'aksrt-header-userbox',
$base_uri . '/assets/js/header-userbox.js',
['aksrt-notyf'],
(string) filemtime($hub_js),
true
);
}
// 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)
);
}
// Final nav alignment overrides AFTER header-menu-buttons (zibll text/icon baseline).
// Re-enqueue shell nav.css last so inline critical rules win the cascade.
$nav_css = get_template_directory() . '/assets/css/frontend/nav.css';
if (file_exists($nav_css)) {
wp_enqueue_style(
'aksrt-nav-align',
$base_uri . '/assets/css/frontend/nav.css',
['aksrt-header-menu-buttons'],
(string) filemtime($nav_css)
);
}
$inline_search_js = get_template_directory() . '/assets/js/header-inline-search.js';
if (file_exists($inline_search_js)) {
wp_enqueue_script(
'aksrt-header-inline-search',
$base_uri . '/assets/js/header-inline-search.js',
[],
(string) filemtime($inline_search_js),
true
);
}
$hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
if (file_exists($hmb_js)) {
wp_enqueue_script(
'aksrt-header-newadd',
$base_uri . '/assets/js/header-newadd.js',
[],
(string) filemtime($hmb_js),
true
);
}
// Shared VIP purchase/poll coordinator for modal and credits surfaces.
$vip_on = class_exists('\AKSRT\Settings\Settings')
&& !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']);
@@ -256,7 +166,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-pay-vip',
$base_uri . '/assets/js/pay-vip.js',
['aksrt-script', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
['loader_js', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
(string) filemtime($vip_js),
true
);
@@ -325,21 +235,6 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
$enqueue_module('breadcrumb');
}
// 顶部多功能组件:按 page-type 启用结果入队(对齐 zibll,不绑死首页)
if (function_exists('aksrt_header_slide_is_show') && aksrt_header_slide_is_show()) {
// flex/gutters used by icon cards (same helpers single-post loads via zibll-utilities)
$zu_path = get_template_directory() . '/assets/css/frontend/zibll-utilities.css';
if (file_exists($zu_path)) {
wp_enqueue_style(
'aksrt-zibll-utilities',
$base_uri . '/assets/css/frontend/zibll-utilities.css',
is_string($deps[0] ?? null) ? [$deps[0]] : (array) $deps,
filemtime($zu_path) ?: $version
);
}
$enqueue_module('header-components');
}
// 单篇文章:所有 single 相关样式
if ($is_single_post) {
// Prefer discrete enqueues over CSS @import (cache-bust + parallel load).
@@ -433,7 +328,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-author',
$base_uri . '/assets/js/author.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($author_js_path),
true
);
@@ -493,7 +388,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-order-center',
$base_uri . '/assets/js/order-center.js',
['aksrt-script', 'aksrt-rehydrate', 'aksrt-core-request', 'aksrt-core-modal-runtime'],
['loader_js', 'aksrt-rehydrate', 'aksrt-core-request', 'aksrt-core-modal-runtime'],
(string) filemtime($order_center_js),
true
);
@@ -505,14 +400,14 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-route-user-center-auth',
$base_uri . '/assets/js/routes/user-center-auth.js',
['aksrt-script', 'aksrt-core-request', 'aksrt-core-modal-runtime'],
['loader_js', 'aksrt-core-request', 'aksrt-core-modal-runtime'],
(string) filemtime($identity_js),
true
);
}
$user_center_deps = file_exists($identity_js)
? ['aksrt-script', 'aksrt-route-user-center-auth', 'aksrt-notyf']
: ['aksrt-script', 'aksrt-notyf'];
? ['loader_js', 'aksrt-route-user-center-auth', 'aksrt-notyf']
: ['loader_js', 'aksrt-notyf'];
if ($has_orders_panel && wp_script_is('aksrt-order-center', 'registered')) {
$user_center_deps[] = 'aksrt-order-center';
}
@@ -668,7 +563,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-messages',
$base_uri . '/assets/js/messages.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($messages_js),
true
);
@@ -678,7 +573,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-conversation',
$base_uri . '/assets/js/conversation.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($conversation_js),
true
);
@@ -693,7 +588,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-share-data',
$base_uri . '/assets/js/share-data-builder.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($share_data_js),
true
);
@@ -707,7 +602,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-poster-share',
$base_uri . '/assets/js/poster-share.js',
['aksrt-script', 'aksrt-share-data'],
['loader_js', 'aksrt-share-data'],
(string) filemtime($poster_js),
true
);
@@ -742,7 +637,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-sign-register',
$base_uri . '/assets/js/sign-register.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($sign_js_path),
true
);
@@ -780,7 +675,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-cms-download',
$base_uri . '/assets/js/cms-download.js',
['aksrt-script', 'aksrt-runtime'],
['loader_js', 'aksrt-runtime'],
file_exists($cms_download_js_path) ? (string) filemtime($cms_download_js_path) : $version,
true
);
@@ -794,23 +689,19 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
if ($is_cms_home || $is_preview) {
$enqueue_module('home-modules');
$enqueue_module('post-card'); // 模块内复用
$enqueue_module('header-components'); // header components 模块依赖
wp_enqueue_script(
'aksrt-cms-home-modules',
$base_uri . '/assets/js/cms-home-modules.js',
['aksrt-script'],
['loader_js'],
$version,
true
);
}
if ($is_fixed_homepage) {
$enqueue_module('header-components'); // header-slider / hero
$enqueue_module('post-card');
$homepage_style_deps = file_exists($frontend_bundle)
? ['aksrt-frontend-bundle', 'aksrt-header-components', 'aksrt-post-card']
: ['aksrt-zibll-compat-vars', 'aksrt-layout', 'aksrt-header-components', 'aksrt-post-card'];
$homepage_style_deps = ['_main', 'aksrt-layout', 'aksrt-post-card'];
$homepage_style_deps = array_values(array_filter(
$homepage_style_deps,
static fn(string $handle): bool => wp_style_is($handle, 'registered')
@@ -855,7 +746,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-credits',
$base_uri . '/assets/js/credits.js',
['aksrt-script', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
['loader_js', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
file_exists($credits_js_path) ? (string) filemtime($credits_js_path) : $version,
true
);
@@ -865,7 +756,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-user-badges',
$base_uri . '/assets/js/user-badges.js',
['aksrt-script', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-core-modal-triggers'],
['loader_js', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-core-modal-triggers'],
(string) filemtime($badges_js_path),
true
);
@@ -886,7 +777,7 @@ $hmb_js = get_template_directory() . '/assets/js/header-newadd.js';
wp_enqueue_script(
'aksrt-user-badges',
$base_uri . '/assets/js/user-badges.js',
['aksrt-script', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-core-modal-triggers'],
['loader_js', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-core-modal-triggers'],
(string) filemtime($badges_js_path_global),
true
);
+89 -181
View File
@@ -20,100 +20,86 @@ trait ScriptsPart1c {
* Fonts / FA / global JS stack / aksrtData (split from enqueue_public).
*/
private function enqueue_public_fonts_js_and_data($base_uri, $core_dep, $deps, $is_fixed_homepage, $is_home_or_archive, $is_single_post, $is_single_resource, $version): void {
// ===== 5. 字体 =====
// 5a. 拉丁字体 - Inter (UI) + Source Serif 4 (正文)
wp_enqueue_style(
'aksrt-fonts',
'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,500;0,8..60,600;0,8..60,700;1,8..60,400&display=swap',
[],
null
);
// 5b. 中文字体 - jsDelivr CDN (思源黑体 / 思源宋体)
// 仅 regular 字重,避免拖慢首屏;其它字重通过 system fallback (PingFang/微软雅黑)
// Fontsource v5 已按 unicode-range 自动分包,浏览器只会下载用到的简中子集
wp_enqueue_style(
'aksrt-fonts-cn',
'https://cdn.jsdelivr.net/npm/@fontsource/noto-sans-sc@5.2.9/400.css',
[],
null
);
wp_enqueue_style(
'aksrt-fonts-cn-serif',
'https://cdn.jsdelivr.net/npm/@fontsource/noto-serif-sc@5.2.9/400.css',
[],
null
);
// ===== 6. 图标系统 =====
// Font Awesome 5 全站加载(评论回复、单篇互动栏、profile 联系方式等
// 多处模板使用 fa-* 类名,作为全主题图标包统一使用)
wp_enqueue_style(
'aksrt-font-awesome-5',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css',
[],
'5.15.4'
);
// FA4 class aliases (fa-diamond, fa-file-text-o, ...) used by zibll-style markup.
wp_enqueue_style(
'aksrt-font-awesome-5-v4-shims',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/v4-shims.min.css',
['aksrt-font-awesome-5'],
'5.15.4'
);
$notyf_css = get_template_directory() . '/assets/css/frontend/notyf.css';
wp_enqueue_style(
'aksrt-notyf',
$base_uri . '/assets/css/frontend/notyf.css',
[$core_dep, 'aksrt-font-awesome-5-v4-shims'],
file_exists($notyf_css) ? (string) filemtime($notyf_css) : $version
);
$notyf_css = get_template_directory() . '/assets/css/frontend/notyf.css';
wp_enqueue_style(
'aksrt-notyf',
$base_uri . '/assets/css/frontend/notyf.css',
[$core_dep, '_fontawesome'],
file_exists($notyf_css) ? (string) filemtime($notyf_css) : $version
);
// ===== 7. JS =====
// Swiper.js(文章列表媒体及单篇资源页加载)
$needs_post_list_media = wp_style_is('aksrt-post-card', 'enqueued');
$needs_swiper = $needs_post_list_media || $is_home_or_archive || $is_single_post || $is_single_resource;
if ($needs_swiper) {
wp_enqueue_style(
'aksrt-swiper',
$base_uri . '/assets/css/frontend/swiper-bundle.min.css',
[],
'11.2.10'
);
wp_enqueue_script(
'aksrt-swiper',
$base_uri . '/assets/js/swiper-bundle.min.js',
[],
'11.2.10',
true
);
}
wp_enqueue_script(
'aksrt-qrcode',
'https://cdn.jsdelivr.net/npm/kjua@0.9.0/dist/kjua.min.js',
[],
'0.9.0',
true
);
$zibll_uri = $base_uri . '/assets/vendor/zibll';
wp_enqueue_script(
'loader_js',
$zibll_uri . '/js/loader.js',
['jquery', 'bootstrap'],
$version,
true
);
wp_localize_script(
'loader_js',
'_win',
[
'views' => '',
'www' => home_url('/'),
'uri' => $zibll_uri,
'ver' => $version,
'pay_mark' => '¥',
'pay_currency_unit' => __('元', 'aksrt'),
'imgbox' => false,
'imgbox_type' => 'group',
'imgbox_thumbs' => false,
'imgbox_zoom' => false,
'imgbox_full' => false,
'imgbox_play' => false,
'imgbox_down' => false,
'sign_type' => 'page',
'signin_url' => wp_login_url(home_url('/' . ltrim((string) ($GLOBALS['wp']->request ?? ''), '/'))),
'signup_url' => wp_registration_url(),
'ajax_url' => admin_url('admin-ajax.php'),
'ajaxpager' => '',
'ajax_trigger' => __('加载更多', 'aksrt'),
'ajax_nomore' => __('没有更多了', 'aksrt'),
'qj_loading' => __('加载中...', 'aksrt'),
'highlight_kg' => false,
'highlight_hh' => false,
'highlight_btn' => false,
'highlight_zt' => 'enlighter',
'highlight_white_zt' => 'enlighter',
'highlight_dark_zt' => 'dracula',
'upload_img_size' => 3,
'img_upload_multiple' => 6,
'upload_video_size' => 30,
'upload_file_size' => 30,
'upload_ext' => implode('|', array_keys(get_allowed_mime_types())),
'user_upload_nonce' => wp_create_nonce('user_upload'),
'post_action_nonce' => wp_create_nonce('post_action'),
'is_split_upload' => false,
'split_minimum_size' => 10,
'comment_upload_img' => false,
'translate_config' => [],
'qrcode_signin' => ['url' => false, 'state' => false],
'i18n' => [
'load_more' => __('加载更多', 'aksrt'),
'processing' => __('处理中...', 'aksrt'),
'please_wait' => __('请稍候', 'aksrt'),
'done' => __('操作完成', 'aksrt'),
'confirm_clear_search' => __('确认清空搜索记录?', 'aksrt'),
'search_loading' => __('搜索中...', 'aksrt'),
'search_min_chars' => __('至少输入 %s 个字符', 'aksrt'),
],
]
);
// Zibll lazySizes is the only media lazy-loading runtime.
$lazysizes_js = get_template_directory() . '/assets/js/lazysizes.js';
wp_enqueue_script(
'aksrt-lazysizes',
$base_uri . '/assets/js/lazysizes.js',
[],
file_exists($lazysizes_js) ? (string) filemtime($lazysizes_js) : $version,
true
);
// Rehydrate system — must load before aksrt-script so AksrtFrontend is available
wp_enqueue_script(
'aksrt-rehydrate',
$base_uri . '/assets/js/rehydrate.js',
['aksrt-lazysizes'],
// AKSRT-only modules register after the Zibll loader; navigation is owned by main.min.js.
wp_enqueue_script(
'aksrt-rehydrate',
$base_uri . '/assets/js/rehydrate.js',
['loader_js'],
file_exists(get_template_directory() . '/assets/js/rehydrate.js')
? (string) filemtime(get_template_directory() . '/assets/js/rehydrate.js')
: $version,
@@ -153,13 +139,7 @@ trait ScriptsPart1c {
}
// Core modules (split from main.js) — register with AksrtFrontend
$core_modules = [
'aksrt-core-theme' => 'theme.js',
'aksrt-core-nav' => 'nav.js',
'aksrt-core-search' => 'search.js',
'aksrt-core-dropdown' => 'dropdown.js',
'aksrt-core-scroll' => 'scroll.js',
'aksrt-core-slider' => 'slider.js',
$core_modules = [
'aksrt-core-article' => 'article.js',
'aksrt-core-comments' => 'comments.js',
'aksrt-core-comment-fixed' => 'comment-fixed-input.js',
@@ -183,9 +163,7 @@ trait ScriptsPart1c {
if (file_exists($path)) {
// Depend on aksrt-runtime so window.aksrtData (localized below) is available.
$deps = ['aksrt-rehydrate', 'aksrt-runtime'];
if ($handle === 'aksrt-core-slider') {
$deps = array_merge($deps, $needs_swiper ? ['aksrt-swiper'] : []);
} elseif ($handle === 'aksrt-core-misc' && $needs_post_list_media) {
if ($handle === 'aksrt-core-misc' && $needs_post_list_media) {
$deps[] = 'aksrt-grade';
} elseif ($handle === 'aksrt-core-modal-runtime') {
$deps = array_merge($deps, [
@@ -208,54 +186,6 @@ trait ScriptsPart1c {
}
}
wp_enqueue_script(
'aksrt-script',
$base_uri . '/assets/js/main.js',
array_merge(
['jquery', 'bootstrap5', 'aksrt-rehydrate', 'aksrt-runtime'],
$core_handles
),
file_exists(get_template_directory() . '/assets/js/main.js')
? (string) filemtime(get_template_directory() . '/assets/js/main.js')
: $version,
true
);
// SVG icon data + helper (must load before other scripts that use icons)
$svg_icon_js = get_template_directory() . '/assets/js/svg-icon.js';
if (file_exists($svg_icon_js)) {
wp_enqueue_script(
'aksrt-svg-icon',
$base_uri . '/assets/js/svg-icon.js',
['jquery'],
(string) filemtime($svg_icon_js),
true // load after <body> exists
);
}
$svg_helper_js = get_template_directory() . '/assets/js/svg-icon-helper.js';
if (file_exists($svg_helper_js)) {
wp_enqueue_script(
'aksrt-svg-icon-helper',
$base_uri . '/assets/js/svg-icon-helper.js',
['aksrt-svg-icon'],
(string) filemtime($svg_helper_js),
true
);
}
// Page loading indicator (top progress bar)
$loader_js = get_template_directory() . '/assets/js/loader.js';
if (file_exists($loader_js)) {
wp_enqueue_script(
'aksrt-loader',
$base_uri . '/assets/js/loader.js',
[],
(string) filemtime($loader_js),
true
);
}
// Code block enhancements (copy button + language label)
$precode_js = get_template_directory() . '/assets/js/precode.js';
if (file_exists($precode_js)) {
@@ -292,18 +222,6 @@ trait ScriptsPart1c {
);
}
// Touch gesture support (swipe, pull-to-dismiss)
$mini_touch_js = get_template_directory() . '/assets/js/mini-touch.js';
if (file_exists($mini_touch_js)) {
wp_enqueue_script(
'aksrt-mini-touch',
$base_uri . '/assets/js/mini-touch.js',
[],
(string) filemtime($mini_touch_js),
true
);
}
// Section navs: article TOC / scrollspy
$section_navs_js = get_template_directory() . '/assets/js/section-navs.js';
if (file_exists($section_navs_js)) {
@@ -356,7 +274,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-enhancements',
$base_uri . '/assets/js/enhancements.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($enhancements_js),
true
);
@@ -367,7 +285,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-enhancements2',
$base_uri . '/assets/js/enhancements2.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($enhancements2_js),
true
);
@@ -379,7 +297,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-reward',
$base_uri . '/assets/js/reward.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($reward_js),
true
);
@@ -391,7 +309,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-effects',
$base_uri . '/assets/js/effects.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($effects_js),
true
);
@@ -450,7 +368,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-modal-auth',
$base_uri . '/assets/js/modal-auth.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($modal_auth_js),
true
);
@@ -462,7 +380,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-homepage-fixed',
$base_uri . '/assets/js/homepage-fixed.js',
['aksrt-script'],
['loader_js'],
file_exists($homepage_js_path) ? (string) filemtime($homepage_js_path) : $version,
true
);
@@ -476,7 +394,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-comment-tools',
$base_uri . '/assets/js/comment-tools.js',
['aksrt-script', 'aksrt-core-comment-fixed', 'aksrt-core-comment-move'],
['loader_js', 'aksrt-core-comment-fixed', 'aksrt-core-comment-move'],
file_exists($comment_tools_path) ? (string) filemtime($comment_tools_path) : $version,
true
);
@@ -499,7 +417,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-comment-ajax',
$base_uri . '/assets/js/comment-ajax.js',
['aksrt-script', 'aksrt-core-comments'],
['loader_js', 'aksrt-core-comments'],
(string) filemtime($comment_ajax_path),
true
);
@@ -512,7 +430,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-page-template',
$base_uri . '/assets/js/page-template.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($page_template_path),
true
);
@@ -526,7 +444,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-weixin-share',
$base_uri . '/assets/js/weixin-share.js',
['aksrt-script'],
['loader_js'],
(string) filemtime($weixin_share_path),
true
);
@@ -537,7 +455,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-post-share',
$base_uri . '/assets/js/post-share.js',
['aksrt-script', 'aksrt-weixin-share', 'aksrt-share-data'],
['loader_js', 'aksrt-weixin-share', 'aksrt-share-data'],
(string) filemtime($post_share_path),
true
);
@@ -557,7 +475,7 @@ trait ScriptsPart1c {
// exist before pagination/search/article handlers run.
$aksrt_data_handle = wp_script_is('aksrt-runtime', 'registered') || wp_script_is('aksrt-runtime', 'enqueued')
? 'aksrt-runtime'
: 'aksrt-script';
: 'loader_js';
wp_localize_script($aksrt_data_handle, 'aksrtData', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('aksrt_public_nonce'),
@@ -578,7 +496,7 @@ trait ScriptsPart1c {
'homeListSortEnabled' => !class_exists('\AKSRT\Settings\Settings') || \AKSRT\Settings\Settings::home_list_sort_enabled(),
'homeListSortDropdown' => class_exists('\AKSRT\Settings\Settings') && \AKSRT\Settings\Settings::home_list_sort_dropdown(),
// AJAX 翻页文案
'ajaxTrigger' => (class_exists('\AKSRT\Settings\Settings') && ($t = \AKSRT\Settings\Settings::get_post_list_style_settings()['ajax_trigger'] ?? '') !== '') ? $t : '<i class="fa fa-angle-right"></i>加载更多',
'ajaxTrigger' => (class_exists('\AKSRT\Settings\Settings') && ($t = \AKSRT\Settings\Settings::get_post_list_style_settings()['ajax_trigger'] ?? '') !== '') ? $t : '<i class="fa fas fa-angle-right"></i>加载更多',
'ajaxNomore' => (class_exists('\AKSRT\Settings\Settings') && ($n = \AKSRT\Settings\Settings::get_post_list_style_settings()['ajax_nomore'] ?? '') !== '') ? $n : __('没有更多内容了', 'aksrt'),
'ajaxLoading' => __('正在加载...', 'aksrt'),
'iasMax' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_post_list_style_settings()['ias_max'] : 3,
@@ -602,16 +520,6 @@ trait ScriptsPart1c {
'stickyPages' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_post_list_style_settings()['sticky_s'] : ['home', 'cat'],
'badgeShow' => class_exists('\AKSRT\Settings\Settings') ? !empty(\AKSRT\Settings\Settings::get_post_list_style_settings()['list_badge_show']) : true,
'badgeTypes' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_post_list_style_settings()['list_badge_show'] : ['pay', 'tag', 'cat'],
'search' => [
'mode' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::search_mode() : 'default',
'placeholder' => function_exists('aksrt_get_search_placeholder') ? aksrt_get_search_placeholder() : __('开启精彩搜索...', 'aksrt'),
'historyEnabled' => function_exists('aksrt_search_history_enabled') ? aksrt_search_history_enabled() : true,
'suggestionsEnabled' => function_exists('aksrt_search_suggestions_enabled') ? aksrt_search_suggestions_enabled() : false,
'hotKeywords' => function_exists('aksrt_get_search_hot_keywords') ? aksrt_get_search_hot_keywords() : [],
'popularTitle' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::search_popular_title() : __('热门搜索', 'aksrt'),
'contentTypes' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_search_content_types()['types'] : ['post', 'category', 'tag'],
'defaultType' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_search_content_types()['default'] : 'post',
],
// 用户状态
'isLoggedIn' => is_user_logged_in(),
'userId' => get_current_user_id(),
+3 -3
View File
@@ -83,7 +83,7 @@ class Shortcodes {
$message = $atts['message'] ?: __('此内容仅 VIP 用户可见', 'aksrt');
$html = '<div class="aksrt-hidden-content aksrt-hidden-content--locked aksrt-hidden-content--vip">';
$html .= '<div class="aksrt-hidden-content__message">';
$html .= '<i class="fas fa-crown" aria-hidden="true"></i> ';
$html .= '<i class="fa fas fa-certificate" aria-hidden="true"></i> ';
$html .= '<span>' . esc_html($message) . '</span>';
$html .= '</div>';
if ($uid <= 0) {
@@ -133,7 +133,7 @@ class Shortcodes {
}
return '<div class="aksrt-hidden-content aksrt-hidden-content--locked aksrt-hidden-content--payshow">'
. '<div class="aksrt-hidden-content__message"><i class="fas fa-lock" aria-hidden="true"></i><span>'
. '<div class="aksrt-hidden-content__message"><i class="fa fas fa-lock" aria-hidden="true"></i><span>'
. esc_html($message)
. '</span></div></div>';
}
@@ -241,7 +241,7 @@ class Shortcodes {
$message = $atts['message'] ?: ($default_msgs[$type] ?? __('此内容已隐藏', 'aksrt'));
$html = '<div class="aksrt-hidden-content aksrt-hidden-content--locked aksrt-hidden-content--role">';
$html .= '<div class="aksrt-hidden-content__message">';
$html .= '<i class="fas fa-eye-slash" aria-hidden="true"></i> ';
$html .= '<i class="fa fas fa-eye-slash" aria-hidden="true"></i> ';
$html .= '<span>' . esc_html($message) . '</span>';
$html .= '</div>';
$html .= '</div>';
+3 -3
View File
@@ -274,7 +274,7 @@ class Signin {
$html = '<div class="aksrt-checkin-modal">';
$html .= '<div class="aksrt-checkin-modal__head">';
$html .= '<i class="fa fa-calendar-check-o" aria-hidden="true"></i>';
$html .= '<i class="fa fas fa-calendar-check" aria-hidden="true"></i>';
$html .= '<strong>' . esc_html__('签到领奖励', 'aksrt') . '</strong>';
$html .= '<button type="button" class="aksrt-modal-runtime__close" data-aksrt-modal-close aria-label="' . esc_attr__('关闭', 'aksrt') . '">&times;</button>';
$html .= '</div>';
@@ -294,11 +294,11 @@ class Signin {
$html .= '<div class="aksrt-checkin-modal__card">';
$html .= '<div class="aksrt-checkin-modal__card-main">';
$html .= '<div class="aksrt-checkin-modal__card-title"><i class="fas fa-gift" aria-hidden="true"></i> ' . esc_html__('每日签到奖励', 'aksrt') . '</div>';
$html .= '<div class="aksrt-checkin-modal__card-title"><i class="fa fas fa-gift" aria-hidden="true"></i> ' . esc_html__('每日签到奖励', 'aksrt') . '</div>';
$html .= '<div class="aksrt-checkin-modal__badge">' . esc_html($currency) . ' +' . esc_html((string) $base) . '</div>';
$html .= '</div>';
if ($rec) {
$html .= '<div class="aksrt-checkin-modal__done"><i class="fa fa-calendar-check-o" aria-hidden="true"></i> ' . esc_html__('今日已签到', 'aksrt');
$html .= '<div class="aksrt-checkin-modal__done"><i class="fa fas fa-calendar-check" aria-hidden="true"></i> ' . esc_html__('今日已签到', 'aksrt');
$html .= '<div class="em09">+' . esc_html((string) (int) ($rec['reward'] ?? 0)) . '</div></div>';
} else {
$html .= '<button type="button" class="but c-blue aksrt-checkin-modal__btn" data-aksrt-checkin="1">' . esc_html__('立即签到', 'aksrt') . '</button>';
+6 -6
View File
@@ -47,9 +47,8 @@ class MeiliSearch {
*/
public function is_configured(): bool {
if (!class_exists('\AKSRT\Settings\Settings')) return false;
$host = \AKSRT\Settings\Settings::get_value('meilisearch_host', '');
$key = \AKSRT\Settings\Settings::get_value('meilisearch_api_key', '');
return !empty($host) && !empty($key);
$config = \AKSRT\Settings\ThemeSearch::get_meilisearch_config();
return !empty($config['enabled']) && !empty($config['api_url']) && !empty($config['api_key']);
}
/**
@@ -69,10 +68,11 @@ class MeiliSearch {
* Get MeiliSearch config
*/
private function get_config(): array {
$config = \AKSRT\Settings\ThemeSearch::get_meilisearch_config();
return [
'host' => (string) \AKSRT\Settings\Settings::get_value('meilisearch_host', ''),
'api_key' => (string) \AKSRT\Settings\Settings::get_value('meilisearch_api_key', ''),
'index' => (string) \AKSRT\Settings\Settings::get_value('meilisearch_index', 'aksrt_posts'),
'host' => (string) $config['api_url'],
'api_key' => (string) $config['api_key'],
'index' => (string) $config['index_name'],
];
}
+3 -20
View File
@@ -11,23 +11,9 @@ defined('ABSPATH') || exit;
class NavWalker extends \Walker_Nav_Menu {
/** @var array<string,mixed> */
private $settings;
/** @var int[] */
public static $submenu_ids = [];
/**
* @param array<string,mixed> $settings
*/
public function __construct(array $settings = []) {
$this->settings = $settings ?: (
function_exists('aksrt_get_menu_decoration_settings')
? aksrt_get_menu_decoration_settings()
: ['icon_enabled' => true, 'badge_enabled' => true]
);
}
/**
* Skip WP children when parent uses senior submenu.
*/
@@ -41,18 +27,15 @@ class NavWalker extends \Walker_Nav_Menu {
public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0): void {
$title = '<span class="menu-item-title">' . $item->title . '</span>';
$icon_enabled = !empty($this->settings['icon_enabled']);
$badge_enabled = !empty($this->settings['badge_enabled']);
$icon = function_exists('aksrt_menu_pz') ? (string) aksrt_menu_pz((int) $item->ID, 'icon', '') : '';
$badge = function_exists('aksrt_menu_pz') ? (string) aksrt_menu_pz((int) $item->ID, 'badge', '') : '';
$badge_class = function_exists('aksrt_menu_pz') ? (string) aksrt_menu_pz((int) $item->ID, 'badge_class', '') : '';
if ($icon && function_exists('aksrt_render_menu_icon')) {
$title = aksrt_render_menu_icon($icon, $icon_enabled) . $title;
$title = aksrt_render_menu_icon($icon) . $title;
}
if ($badge && function_exists('aksrt_render_menu_badge')) {
$title .= aksrt_render_menu_badge($badge, $badge_class, $badge_enabled);
$title .= aksrt_render_menu_badge($badge, $badge_class);
}
$item->title = $title;
@@ -208,7 +191,7 @@ class NavWalker extends \Walker_Nav_Menu {
if ($link_url !== '') {
$target = !empty($args['link']['target']) ? ' target="' . esc_attr((string) $args['link']['target']) . '"' : '';
return '<div class="' . esc_attr($class) . '"><a href="' . esc_url($link_url) . '"' . $target . '>'
. $title_html . '<i class="fa fa-angle-double-right icon-hover-show" aria-hidden="true"></i></a></div>';
. $title_html . '<i class="fa fas fa-angle-double-right icon-hover-show" aria-hidden="true"></i></a></div>';
}
return '<div class="' . esc_attr($class) . '"><a href="javascript:;">' . $title_html . '</a></div>';
}
+1 -1
View File
@@ -121,7 +121,7 @@ class SiteNotice {
<?php echo $title; ?>
</h3>
<button type="button" class="aksrt-site-notice__close" aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>">
<i class="fas fa-times"></i>
<i class="fa fas fa-times"></i>
</button>
</div>
<div class="aksrt-site-notice__body">
+107 -46
View File
@@ -49,45 +49,109 @@ trait DisplayPageGroups {
/**
* 获取顶部多功能组件设置
*/
public static function get_header_components_settings(): array {
$s = self::get_all();
$allowed_page_types = [
'home',
'category',
'tag',
'author',
'single',
'search',
'page',
];
$show_on = isset($s['header_components_show_on']) ? (array) $s['header_components_show_on'] : ['home'];
$show_on = array_values(array_intersect(
array_map('sanitize_key', $show_on),
$allowed_page_types
));
$show_type = $s['header_components_device_visibility'] ?? '';
if (!in_array($show_type, ['', 'only_pc', 'only_sm'], true)) {
$show_type = '';
}
return [
'search_enabled' => self::header_components_search_enabled(),
'search_config' => self::get_header_components_search_config(),
'cards_enabled' => self::header_components_cards_enabled(),
'show_on_pages' => $show_on,
'show_type' => $show_type,
'filter_blur' => isset($s['header_components_filter_blur_devices']) ? array_values(array_intersect(array_map('sanitize_key', (array) $s['header_components_filter_blur_devices']), ['pc', 'mobile'])) : [],
'card_show' => isset($s['header_components_card_show_devices']) ? array_values(array_intersect(array_map('sanitize_key', (array) $s['header_components_card_show_devices']), ['pc', 'mobile'])) : ['pc', 'mobile'],
'slider_config' => self::get_slider_config(),
'icon_cards' => self::get_header_components_icon_cards(),
'card_columns' => self::get_header_components_card_columns(),
'card_bg_enabled' => self::header_components_card_bg_enabled(),
];
}
public static function get_header_slider_settings(): array {
$s = self::get_all();
$allowed_page_types = [
'home',
'category',
'tag',
'author',
'single',
'search',
'page',
'topics',
'forum_home',
'forum_plate',
'forum_post',
];
$show_on = isset($s['header_slider_show']) ? (array) $s['header_slider_show'] : [];
$show_on = array_values(array_intersect(
array_map('sanitize_key', $show_on),
$allowed_page_types
));
$show_type = $s['header_slider_show_type'] ?? '';
if (!in_array($show_type, ['', 'only_pc', 'only_sm'], true)) {
$show_type = '';
}
$slider_option = is_array($s['header_slider_option'] ?? null) ? $s['header_slider_option'] : self::header_slider_option_defaults();
$search_option = is_array($s['header_slider_search_option'] ?? null) ? $s['header_slider_search_option'] : self::header_slider_search_defaults();
$card_option = is_array($s['header_slider_card_option'] ?? null) ? $s['header_slider_card_option'] : self::header_slider_card_defaults();
return [
'slides' => is_array($s['header_slider'] ?? null) ? $s['header_slider'] : self::header_slider_default_slides(),
'show_on_pages' => $show_on,
'show_type' => $show_type,
'nav_color' => sanitize_hex_color((string) ($s['header_slider_nav_color'] ?? '')) ?: '',
'slider_config' => $slider_option,
'search_show' => self::sanitize_device_visibility($s['header_slider_search_s'] ?? ['pc_s', 'm_s']),
'search_config' => $search_option,
'card_show' => self::sanitize_device_visibility($s['header_slider_card_s'] ?? ['pc_s', 'm_s']),
'card_config' => $card_option,
'filter_blur' => self::sanitize_device_visibility($s['header_slider_filter_blur'] ?? ['pc_s', 'm_s']),
];
}
/** @return list<array<string,mixed>> */
private static function header_slider_default_slides(): array {
$base = defined('AKSRT_URI') ? trailingslashit(AKSRT_URI) . 'assets/vendor/zibll/img/' : '';
$slides = [];
foreach (['slider-bg.jpg', 'user_t.jpg'] as $image) {
$slides[] = [
'background' => $base . $image,
'link' => ['url' => 'https://www.zibll.com/', 'target' => '_blank'],
'text' => ['desc' => '', 'title' => ''],
'text_align' => 'left-bottom',
'text_parallax' => 30,
'text_size_m' => 20,
'text_size_pc' => 30,
];
}
return $slides;
}
/** @return array<string,mixed> */
private static function header_slider_option_defaults(): array {
return [
'direction' => 'horizontal', 'loop' => true, 'button' => true,
'pagination' => true, 'effect' => 'slide', 'scale_height' => false,
'auto_height' => false, 'pc_height' => 550, 'm_height' => 280,
'spacebetween' => 0, 'speed' => 0, 'autoplay' => true, 'interval' => 6,
];
}
/** @return array<string,mixed> */
private static function header_slider_search_defaults(): array {
return [
'show_keywords' => true, 'popular_limit' => 6, 'show_input_cat' => false,
'in_cat' => '', 'more_cats' => [], 'show_type' => false, 'in_type' => 'post',
'before_html' => '<div class="em16 font-bold mb10">更优雅的Wordpress主题</div><div>这是导航栏幻灯片多功能组件,可在后台进行配置</div>',
'after_html' => '',
];
}
/** @return array<string,mixed> */
private static function header_slider_card_defaults(): array {
return [
'show_widget_bg' => false,
'icon_radius4' => false,
'cards' => [
['icon' => 'zibsvg-vip_1', 'customize_icon' => '', 'icon_class' => 'c-yellow', 'link' => [], 'title' => '图标卡片', 'desc' => '这是一个图标卡片示例'],
['icon' => 'zibsvg-vip_2', 'customize_icon' => '', 'icon_class' => 'c-blue-2', 'link' => [], 'title' => '原创作品', 'desc' => '这是一个图标卡片示例'],
['icon' => 'zibsvg-hot', 'customize_icon' => '', 'icon_class' => 'jb-pink', 'link' => [], 'title' => '灵感来源<badge class="ml6 jb-yellow">NEW</badge>', 'desc' => '这是一个图标卡片示例'],
['icon' => 'fa fas fa-ioxhost', 'customize_icon' => '', 'icon_class' => 'jb-cyan', 'link' => [], 'title' => '系统工具 <badge class="ml6 jb-blue">GO <span class="fa fas fa-angle-right em12"></span></badge>', 'desc' => '这是一个图标卡片示例'],
],
];
}
/** @return list<string> */
private static function sanitize_device_visibility($value): array {
return array_values(array_intersect(array_map('sanitize_key', (array) $value), ['pc_s', 'm_s']));
}
/**
* 获取"全局&功能"域的合并设置
*/
public static function get_global_settings(): array {
$s = self::get_all();
return [
'site_logo' => self::logo_url(),
'site_logo_dark' => self::logo_dark_url(),
@@ -105,12 +169,14 @@ trait DisplayPageGroups {
'qj_dh_xs' => self::get_qj_loading_style(),
'container_max_width' => self::container_max_width(),
'font_family' => self::font_family(),
'search_type' => self::search_mode(),
'search_placeholder' => self::search_placeholder(),
'search_history_enabled' => self::search_history_enabled(),
'hot_search_enabled' => self::hot_search_enabled(),
'hot_search_keywords' => self::hot_search_keywords(),
'search_suggestions_enabled' => self::search_suggestions_enabled(),
'search_type' => !isset($s['search_type']) || !empty($s['search_type']),
'search_type_in' => sanitize_key((string) ($s['search_type_in'] ?? 'post')),
'search_placeholder' => self::search_placeholder(),
'search_history' => self::search_history_enabled(),
'search_popular_key' => self::hot_search_enabled(),
'search_popular_title' => self::search_popular_title(),
'search_popular_sticky' => self::search_popular_sticky(),
'search_popular_key_num' => max(10, min(50, (int) ($s['search_popular_key_num'] ?? 20))),
'search_posts' => self::search_posts_enabled(),
'search_no_page' => self::search_no_page(),
'search_exclude_cats' => self::search_exclude_cats(),
@@ -132,8 +198,6 @@ trait DisplayPageGroups {
'footer' => self::get_footer_settings(),
'tabbar' => self::get_footer_tabbar_settings(),
'floating_buttons' => self::get_floating_buttons_settings(),
'header_nav' => self::get_header_nav_settings(),
'header_newposts' => self::get_header_newposts_config(),
'header_theme' => self::get_header_theme_config(),
'friend_links' => self::get_friend_links(),
'cms_features' => self::get_cms_features(),
@@ -147,7 +211,7 @@ trait DisplayPageGroups {
*/
public static function get_page_display_settings(): array {
return [
'header_components' => self::get_header_components_settings(),
'header_slider' => self::get_header_slider_settings(),
'homepage' => self::get_homepage_fixed_settings(),
'category_recommend' => self::get_category_recommend_settings(),
'category' => self::get_category_page_settings(),
@@ -155,9 +219,6 @@ trait DisplayPageGroups {
'user_home' => self::get_user_home_settings(),
'other' => self::get_other_page_settings(),
'background' => self::get_global_background_settings(),
'menu_decoration' => function_exists('aksrt_get_menu_decoration_settings')
? aksrt_get_menu_decoration_settings()
: [],
];
}
+12 -159
View File
@@ -56,135 +56,6 @@ class DisplayRuntime {
update_option('aksrt_friend_links', $links);
}
/**
* 是否显示顶部组件搜索覆盖框
*/
public static function header_components_search_enabled(): bool {
$settings = Settings::get_all();
return !empty($settings['header_components_search_enabled']);
}
/**
* Hero 搜索组件详细配置(PC/移动分别 + 子选项)
*
* @return array{pc:bool,mobile:bool,show:bool,show_keywords:bool,popular_limit:int,show_input_cat:bool,show_type:bool,keywords:string[],categories:array,type_options:array,before_html:string,after_html:string}
*/
public static function get_header_components_search_config(): array {
$settings = Settings::get_all();
$master = self::header_components_search_enabled();
$is_mobile = function_exists('wp_is_mobile') && wp_is_mobile();
$pc_on = $master && (!isset($settings['header_components_search_pc']) || !empty($settings['header_components_search_pc']));
$mobile_on = $master && (!isset($settings['header_components_search_mobile']) || !empty($settings['header_components_search_mobile']));
$show = $is_mobile ? $mobile_on : $pc_on;
$show_kw = !empty($settings['header_components_search_show_keywords']);
$kw_limit = max(1, min(50, (int) ($settings['header_components_search_popular_limit'] ?? 6)));
$show_cat = !empty($settings['header_components_search_show_input_cat']);
$show_type = !empty($settings['header_components_search_show_type']);
$in_cat = sanitize_text_field((string) ($settings['header_components_search_in_cat'] ?? ''));
$in_type = sanitize_key((string) ($settings['header_components_search_in_type'] ?? 'post')) ?: 'post';
$more_cats = isset($settings['header_components_search_more_cats'])
? array_values(array_filter(array_map('absint', (array) $settings['header_components_search_more_cats'])))
: [];
// Mobile: hide hot keywords (zibll).
if ($is_mobile) {
$show_kw = false;
}
$keywords = [];
if ($show && $show_kw) {
if (function_exists('aksrt_get_search_hot_keywords')) {
$keywords = (array) aksrt_get_search_hot_keywords();
} else {
$raw = $settings['hot_search_keywords'] ?? '';
$keywords = is_array($raw) ? $raw : preg_split('/[\s,]+/', (string) $raw, -1, PREG_SPLIT_NO_EMPTY);
}
$keywords = array_slice(array_map('sanitize_text_field', array_values($keywords)), 0, $kw_limit);
}
$categories = [];
if ($show && $show_cat) {
$cat_args = ['hide_empty' => true, 'number' => 50];
if ($more_cats) {
$cat_args['include'] = $more_cats;
$cat_args['orderby'] = 'include';
$cat_args['hide_empty'] = false;
}
$cats = get_categories($cat_args);
foreach ($cats as $cat) {
$categories[] = ['id' => (int) $cat->term_id, 'name' => (string) $cat->name];
}
}
$type_options = [];
if ($show && $show_type) {
$types = Settings::get_search_content_types();
$labels = [
'post' => __('文章', 'aksrt'),
'user' => __('用户', 'aksrt'),
'page' => __('页面', 'aksrt'),
];
$enabled = $types['enabled'] ?? $types;
if (is_array($enabled)) {
foreach ($enabled as $type_key => $type_value) {
// Support both map[key=>bool] and list of keys.
if (is_int($type_key) && is_string($type_value)) {
$k = $type_value;
$on = true;
} else {
$k = (string) $type_key;
$on = (bool) $type_value;
}
if (!$on || $k === '') {
continue;
}
$type_options[] = [
'key' => $k,
'label' => $labels[$k] ?? $k,
];
}
}
}
$before_html = isset($settings['header_components_search_before_html'])
? (string) $settings['header_components_search_before_html']
: '';
$after_html = isset($settings['header_components_search_after_html'])
? (string) $settings['header_components_search_after_html']
: '';
return [
'pc' => $pc_on,
'mobile' => $mobile_on,
'show' => $show,
'show_keywords' => $show_kw,
'popular_limit' => $kw_limit,
'show_input_cat' => $show_cat,
'show_type' => $show_type,
'in_cat' => $in_cat,
'in_type' => $in_type,
'more_cats' => $more_cats,
'keywords' => $keywords,
'categories' => $categories,
'type_options' => $type_options,
'before_html' => $before_html,
'after_html' => $after_html,
];
}
public static function header_components_cards_enabled(): bool {
$settings = Settings::get_all();
return !empty($settings['header_components_cards_enabled']);
}
public static function homepage_module_hero_enabled(): bool {
$settings = Settings::get_all();
return !isset($settings['homepage_module_hero_enabled']) || !empty($settings['homepage_module_hero_enabled']);
}
public static function homepage_module_banner_enabled(): bool {
$settings = Settings::get_all();
return !isset($settings['homepage_module_banner_enabled']) || !empty($settings['homepage_module_banner_enabled']);
@@ -197,47 +68,29 @@ class DisplayRuntime {
*/
public static function get_slider_config(): array {
$settings = Settings::get_all();
$config = $settings['slider_config'] ?? [];
$config = is_array($settings['header_slider_option'] ?? null) ? $settings['header_slider_option'] : [];
return [
'effect' => in_array($config['effect'] ?? '', ['fade', 'slide', 'cube', 'coverflow', 'flip'], true) ? $config['effect'] : 'fade',
'direction' => in_array($settings['slider_config_direction'] ?? ($config['direction'] ?? ''), ['horizontal', 'vertical'], true)
? ($settings['slider_config_direction'] ?? ($config['direction'] ?? 'horizontal')) : 'horizontal',
'direction' => in_array($config['direction'] ?? '', ['horizontal', 'vertical'], true) ? $config['direction'] : 'horizontal',
'loop' => !isset($config['loop']) || !empty($config['loop']),
'autoplay_interval' => max(1000, min(30000, (int) ($config['autoplay_interval'] ?? 5000))),
'autoplay_interval' => max(0, min(20000, (int) ($config['interval'] ?? 6) * 1000)),
'pagination' => !isset($config['pagination']) || !empty($config['pagination']),
'navigation' => !isset($config['navigation']) || !empty($config['navigation']),
'button' => isset($settings['slider_config_button']) ? !empty($settings['slider_config_button']) : (!isset($config['button']) || !empty($config['button'])),
'button' => !isset($config['button']) || !empty($config['button']),
'auto_height' => !empty($config['auto_height']),
'pc_height' => isset($config['pc_height']) && $config['pc_height'] !== '' ? sanitize_text_field($config['pc_height']) : '',
'mobile_height' => isset($config['mobile_height']) && $config['mobile_height'] !== '' ? sanitize_text_field($config['mobile_height']) : '',
'max_height' => isset($settings['slider_config_max_height']) && $settings['slider_config_max_height'] !== '' ? sanitize_text_field($settings['slider_config_max_height']) : (isset($config['max_height']) && $config['max_height'] !== '' ? sanitize_text_field($config['max_height']) : ''),
'min_height' => isset($settings['slider_config_min_height']) && $settings['slider_config_min_height'] !== '' ? sanitize_text_field($settings['slider_config_min_height']) : (isset($config['min_height']) && $config['min_height'] !== '' ? sanitize_text_field($config['min_height']) : ''),
'scale_height' => !empty($settings['slider_config_scale_height'] ?? ($config['scale_height'] ?? false)),
'scale' => !empty($settings['slider_config_scale'] ?? ($config['scale'] ?? false)),
'speed' => max(100, min(3000, (int) ($settings['slider_config_speed'] ?? ($config['speed'] ?? 300)))),
'space_between' => max(0, min(100, (int) ($config['space_between'] ?? 0))),
'nav_color' => sanitize_hex_color((string) ($settings['header_components_nav_color'] ?? '')) ?: '',
'mobile_height' => isset($config['m_height']) && $config['m_height'] !== '' ? sanitize_text_field($config['m_height']) : '',
'max_height' => isset($config['max_height']) && $config['max_height'] !== '' ? sanitize_text_field($config['max_height']) : '',
'min_height' => isset($config['min_height']) && $config['min_height'] !== '' ? sanitize_text_field($config['min_height']) : '',
'scale_height' => !empty($config['scale_height']),
'scale' => (int) ($config['scale'] ?? 40),
'speed' => max(0, min(3000, (int) ($config['speed'] ?? 0))),
'space_between' => max(0, min(500, (int) ($config['spacebetween'] ?? 0))),
'nav_color' => sanitize_hex_color((string) ($settings['header_slider_nav_color'] ?? '')) ?: '',
];
}
public static function get_header_components_icon_cards(): array {
$settings = Settings::get_all();
$cards = $settings['header_components_icon_cards'] ?? [];
return is_array($cards) ? array_values($cards) : [];
}
public static function get_header_components_card_columns(): int {
$settings = Settings::get_all();
$columns = (int) ($settings['header_components_card_columns'] ?? 4);
return max(2, min(6, $columns));
}
public static function header_components_card_bg_enabled(): bool {
$settings = Settings::get_all();
return !empty($settings['header_components_card_bg']);
}
/**
* 获取全局背景设置
*/
+4 -89
View File
@@ -8,91 +8,6 @@ namespace AKSRT\Settings;
defined('ABSPATH') || exit;
trait FacadeBulk {
/**
* Header navigation display settings.
*
* @return array{
* fixed:bool,search_enabled:bool,user_menu:bool,publish_btn:bool,mobile_drawer:bool,
* nav_style:string,max_width:int,scroll_down_hide:bool,layout:string,mobile_layout:string,
* mobile_align:string,nav_pay_vip:bool,nav_user_pay_vip:bool
* }
*/
public static function get_header_nav_settings(): array {
$settings = self::get_all();
$nav_style = sanitize_key((string) ($settings['header_nav_style'] ?? 'default'));
$max_width = (int) ($settings['header_max_width'] ?? 1200);
$layout = sanitize_key((string) ($settings['header_layout'] ?? '1'));
$ml = sanitize_key((string) ($settings['mobile_header_layout'] ?? 'center'));
$ma = sanitize_key((string) ($settings['mobile_navbar_align'] ?? 'left'));
if (!in_array($nav_style, ['default', 'transparent', 'blur'], true)) {
$nav_style = 'default';
}
if (!in_array($max_width, [0, 1080, 1200, 1320], true)) {
$max_width = 1200;
}
return [
'fixed' => !isset($settings['header_fixed']) || !empty($settings['header_fixed']),
'search_enabled' => !isset($settings['header_search_enabled']) || !empty($settings['header_search_enabled']),
'user_menu' => !isset($settings['header_user_menu']) || !empty($settings['header_user_menu']),
// Unified with header_newposts_enabled (zibll nav_newposts).
'publish_btn' => !isset($settings['header_newposts_enabled']) || !empty($settings['header_newposts_enabled']),
'mobile_drawer' => !isset($settings['header_mobile_drawer']) || !empty($settings['header_mobile_drawer']),
'nav_style' => $nav_style,
'max_width' => $max_width,
// Zibll default: true when fixed.
'scroll_down_hide' => !isset($settings['header_scroll_down_hide']) || !empty($settings['header_scroll_down_hide']),
'layout' => in_array($layout, ['1', '2', '3'], true) ? $layout : '1',
'mobile_layout' => in_array($ml, ['center', 'left'], true) ? $ml : 'center',
'mobile_align' => in_array($ma, ['top', 'left', 'right'], true) ? $ma : 'left',
'nav_pay_vip' => !isset($settings['header_nav_pay_vip']) || !empty($settings['header_nav_pay_vip']),
'nav_user_pay_vip' => !isset($settings['header_nav_user_pay_vip']) || !empty($settings['header_nav_user_pay_vip']),
];
}
/**
* Header publish button configuration.
*
* @return array{enabled:bool,text:string,radius:int,class:string,types:string[]}
*/
public static function get_header_newposts_config(): array {
$s = self::get_all();
$types = [];
if (!empty($s['header_newposts_types']) && is_array($s['header_newposts_types'])) {
$types = array_values(array_intersect(array_map('sanitize_key', $s['header_newposts_types']), ['post']));
}
// zibll nav_newposts_radius is bool pill; map true→20px, false→0. Legacy int still accepted once.
$raw_radius = $s['header_newposts_radius'] ?? true;
if (is_bool($raw_radius) || $raw_radius === '0' || $raw_radius === '1' || $raw_radius === 0 || $raw_radius === 1) {
$radius_px = !empty($raw_radius) ? 20 : 0;
$radius_pill = !empty($raw_radius);
} else {
$radius_px = max(0, min(30, (int) $raw_radius));
$radius_pill = $radius_px >= 16;
}
return [
// Default on like zibll nav_newposts when key unset.
'enabled' => !isset($s['header_newposts_enabled']) || !empty($s['header_newposts_enabled']),
'text' => trim((string) ($s['header_newposts_text'] ?? '<i class="fa fa-pencil"></i> 发布')),
'radius' => $radius_px,
'radius_pill' => $radius_pill,
'class' => sanitize_html_class((string) (($s['header_newposts_class'] ?? '') !== '' ? $s['header_newposts_class'] : 'jb-blue')),
'types' => $types,
];
}
/**
* Header theme color configuration.
*
@@ -102,10 +17,10 @@ trait FacadeBulk {
$s = self::get_all();
return [
'custom' => !empty($s['header_theme_custom']),
'bg_custom' => sanitize_hex_color((string) ($s['header_theme_bg_custom'] ?? '')) ?: '',
'bg' => sanitize_hex_color((string) ($s['header_theme_bg'] ?? '')) ?: '',
'color_custom' => sanitize_hex_color((string) ($s['header_theme_color_custom'] ?? '')) ?: '',
'custom' => !empty($s['header_theme_custom']),
'bg_custom' => sanitize_hex_color((string) ($s['header_theme_bg_custom'] ?? '')) ?: '',
'bg' => sanitize_hex_color((string) ($s['header_theme_bg'] ?? '')) ?: '',
'color_custom' => sanitize_hex_color((string) ($s['header_theme_color_custom'] ?? '')) ?: '',
];
}
-1
View File
@@ -218,7 +218,6 @@ class HomeCms {
'home_list_sort_dropdown' => !empty($s['home_list_sort_dropdown']),
'homepage_tab_posts_per_page' => max(1, min(20, (int) ($s['homepage_tab_posts_per_page'] ?? 6))),
'homepage_tab_limit' => max(1, min(12, (int) ($s['homepage_tab_limit'] ?? 4))),
'homepage_module_hero_enabled' => !isset($s['homepage_module_hero_enabled']) || !empty($s['homepage_module_hero_enabled']),
'homepage_module_banner_enabled' => !isset($s['homepage_module_banner_enabled']) || !empty($s['homepage_module_banner_enabled']),
];
-49
View File
@@ -151,41 +151,10 @@ trait HomepageReader {
return HomeCms::homepage_tab_limit();
}
// ============================================
// 顶部多功能组件设置(图标卡片 + 搜索覆盖)
// ============================================
/**
* 是否显示顶部组件搜索覆盖框
*/
public static function header_components_search_enabled(): bool {
return DisplayRuntime::header_components_search_enabled();
}
/**
* 顶部组件搜索详细配置(PC/移动分别 + 子选项)
*
* @return array{pc:bool,mobile:bool,show_keywords:bool,popular_limit:int,show_input_cat:bool,show_type:bool,keywords:string[],categories:array,type_options:array}
*/
public static function get_header_components_search_config(): array {
return DisplayRuntime::get_header_components_search_config();
}
/**
* 是否显示顶部组件图标卡片覆盖
*/
public static function header_components_cards_enabled(): bool {
return DisplayRuntime::header_components_cards_enabled();
}
/**
* 获取顶部组件图标卡片配置
* @return array
*/
public static function homepage_module_hero_enabled(): bool {
return DisplayRuntime::homepage_module_hero_enabled();
}
public static function homepage_module_banner_enabled(): bool {
return DisplayRuntime::homepage_module_banner_enabled();
}
@@ -199,24 +168,6 @@ trait HomepageReader {
return DisplayRuntime::get_slider_config();
}
public static function get_header_components_icon_cards(): array {
return DisplayRuntime::get_header_components_icon_cards();
}
/**
* 获取顶部组件卡片列数
*/
public static function get_header_components_card_columns(): int {
return DisplayRuntime::get_header_components_card_columns();
}
/**
* 是否显示顶部组件卡片背景色
*/
public static function header_components_card_bg_enabled(): bool {
return DisplayRuntime::header_components_card_bg_enabled();
}
/**
* 获取页脚配色配置
*/
+7 -7
View File
@@ -196,7 +196,7 @@ class Integration {
[
'id' => 'tab_home',
'type' => 'home',
'icon' => 'fas fa-home',
'icon' => 'fa fas fa-home',
'text' => __('首页', 'aksrt'),
'link' => '',
'badge' => '',
@@ -210,7 +210,7 @@ class Integration {
[
'id' => 'tab_category',
'type' => 'category',
'icon' => 'fas fa-th-large',
'icon' => 'fa fas fa-th-large',
'text' => __('分类', 'aksrt'),
'link' => '',
'badge' => '',
@@ -223,7 +223,7 @@ class Integration {
[
'id' => 'tab_search',
'type' => 'search',
'icon' => 'fas fa-search',
'icon' => 'fa fas fa-search',
'text' => __('搜索', 'aksrt'),
'link' => '',
'badge' => '',
@@ -237,7 +237,7 @@ class Integration {
[
'id' => 'tab_auth',
'type' => 'auth',
'icon' => 'fas fa-user',
'icon' => 'fa fas fa-user',
'text' => __('我的', 'aksrt'),
'link' => '',
'badge' => '',
@@ -439,7 +439,7 @@ class Integration {
[
'id' => 'btn_wechat',
'type' => 'service_wechat',
'icon' => 'fab fa-weixin',
'icon' => 'fa fab fa-weixin',
'icon_dark' => '',
'icon_light' => '',
'text' => __('微信', 'aksrt'),
@@ -463,7 +463,7 @@ class Integration {
[
'id' => 'btn_theme',
'type' => 'theme_mode',
'icon' => 'fas fa-sun',
'icon' => 'fa fas fa-sun',
'icon_dark' => '',
'icon_light' => '',
'text' => __('主题', 'aksrt'),
@@ -487,7 +487,7 @@ class Integration {
[
'id' => 'btn_top',
'type' => 'back_top',
'icon' => 'fas fa-chevron-up',
'icon' => 'fa fas fa-chevron-up',
'icon_dark' => '',
'icon_light' => '',
'text' => __('顶部', 'aksrt'),
+2 -2
View File
@@ -70,7 +70,7 @@ class PostDisplay {
'scale' => max(20, min(200, (int) ($card_option['scale'] ?? 70))),
],
'mult_thumb_cat' => is_array($settings['mult_thumb_cat'] ?? null) ? array_values(array_filter(array_map('intval', $settings['mult_thumb_cat']))) : [],
'ajax_trigger' => wp_kses_post((string) ($settings['ajax_trigger'] ?? '<i class="fa fa-angle-right"></i>加载更多')),
'ajax_trigger' => wp_kses_post((string) ($settings['ajax_trigger'] ?? '<i class="fa fas fa-angle-right"></i>加载更多')),
'ajax_nomore' => wp_kses_post((string) ($settings['ajax_nomore'] ?? '没有更多内容了')),
];
}
@@ -412,7 +412,7 @@ class PostDisplay {
if (is_admin() || !($query instanceof \WP_Query) || !$query->is_main_query()) {
return;
}
if (!$query->is_home() && !$query->is_archive() && !$query->is_search()) {
if (!$query->is_home() && !$query->is_archive()) {
return;
}
if ($query->get('orderby')) {
+5 -16
View File
@@ -77,6 +77,9 @@ class Settings {
// 搜索结果排除(search_no_page / search_exclude_cats)
add_action('pre_get_posts', [self::class, 'filter_search_query']);
add_filter('posts_search', [ThemeSearch::class, 'filter_posts_search'], 50, 2);
add_filter('posts_join', [ThemeSearch::class, 'filter_posts_search_join'], 50, 2);
add_filter('posts_distinct', [ThemeSearch::class, 'filter_posts_search_distinct'], 50, 2);
// 全局列表默认排序(list_orderby)
add_action('pre_get_posts', [self::class, 'apply_list_orderby']);
@@ -236,13 +239,6 @@ class Settings {
/** 获取搜索模式 */
public static function search_mode(): string {
return ThemeSearch::search_mode();
}
/** 是否启用搜索历史 */
public static function search_history_enabled(): bool {
return ThemeSearch::search_history_enabled();
@@ -278,13 +274,6 @@ class Settings {
/** 是否启用搜索建议 */
public static function search_suggestions_enabled(): bool {
return ThemeSearch::search_suggestions_enabled();
}
/** 是否在搜索面板显示热门文章 */
public static function search_posts_enabled(): bool {
return ThemeSearch::search_posts_enabled();
@@ -320,8 +309,8 @@ class Settings {
/** 是否显示更多分类 */
public static function search_more_cat_obj(): bool {
/** 允许用户选择的更多分类 ID */
public static function search_more_cat_obj(): array {
return ThemeSearch::search_more_cat_obj();
}
+168 -81
View File
@@ -14,31 +14,22 @@ class ThemeSearch {
return $placeholder !== '' ? $placeholder : __('开启精彩搜索', 'aksrt');
}
public static function search_mode(): string {
$mode = sanitize_key((string) Settings::get_value('search_mode', ''));
if ($mode === '' || !in_array($mode, ['default', 'ajax', 'redirect'], true)) {
$mode = sanitize_key((string) Settings::get_value('search_type', 'default'));
}
return in_array($mode, ['default', 'ajax', 'redirect'], true) ? $mode : 'default';
}
public static function search_history_enabled(): bool {
$settings = Settings::get_all();
return !array_key_exists('search_history_enabled', $settings) || !empty($settings['search_history_enabled']);
return !array_key_exists('search_history', $settings) || !empty($settings['search_history']);
}
public static function hot_search_enabled(): bool {
$settings = Settings::get_all();
return !array_key_exists('hot_search_enabled', $settings) || !empty($settings['hot_search_enabled']);
return !array_key_exists('search_popular_key', $settings) || !empty($settings['search_popular_key']);
}
public static function hot_search_keywords(): array {
$raw = Settings::get_value('hot_search_keywords', '');
if (is_array($raw)) {
$items = $raw;
} else {
$items = preg_split('/[\r\n,]+/', (string) $raw) ?: [];
}
$items = self::search_popular_sticky();
$counts = get_option('search_keywords', []);
if (is_array($counts)) {
$items = array_merge($items, array_keys($counts));
}
$items = array_map(
static function ($keyword): string {
@@ -66,16 +57,12 @@ class ThemeSearch {
if (is_array($raw)) {
$items = $raw;
} else {
$items = preg_split('/[\r\n,]+/', (string) $raw) ?: [];
$items = preg_split('/[\r\n,,]+/', (string) $raw) ?: [];
}
$items = array_map(static fn($k) => trim(sanitize_text_field((string) $k)), $items);
return array_values(array_filter(array_unique($items), fn(string $k) => $k !== ''));
}
public static function search_suggestions_enabled(): bool {
return self::search_mode() === 'ajax' && !empty(Settings::get_value('search_suggestions_enabled', false));
}
public static function search_posts_enabled(): bool {
return !empty(Settings::get_value('search_posts', false));
}
@@ -103,8 +90,10 @@ class ThemeSearch {
return trim((string) Settings::get_value('search_cat_in', ''));
}
public static function search_more_cat_obj(): bool {
return !empty(Settings::get_value('search_more_cat_obj', true));
public static function search_more_cat_obj(): array {
$raw = Settings::get_value('search_more_cat_obj', []);
$items = is_array($raw) ? $raw : (preg_split('/[,,\s]+/', (string) $raw) ?: []);
return array_values(array_filter(array_unique(array_map('absint', $items))));
}
public static function search_custom_key_enabled(): bool {
@@ -112,42 +101,47 @@ class ThemeSearch {
}
public static function search_custom_key(): array {
$raw = Settings::get_value('search_custom_key', 'title,content');
$raw = Settings::get_value('search_custom_key', ['title', 'content', 'excerpt', 'post_tag', 'forum_topic', 'shop_cat', 'shop_discount']);
if (is_array($raw)) {
$items = $raw;
} else {
$items = preg_split('/[,,\s]+/', (string) $raw) ?: [];
}
$items = array_map(static fn($k) => trim(sanitize_key((string) $k)), $items);
$valid = ['title', 'content', 'excerpt', 'category', 'tag', 'author'];
$valid = ['title', 'content', 'excerpt', 'category', 'post_tag', 'topics', 'coment', 'user', 'forum_topic', 'forum_tag', 'shop_cat', 'shop_tag', 'shop_discount'];
return array_values(array_intersect(array_filter(array_unique($items)), $valid));
}
public static function search_facets_enabled(): bool {
return !empty(Settings::get_value('search_facets', false));
return !empty(Settings::get_value('search_facets', []));
}
public static function search_facets_order(): array {
$raw = Settings::get_value('search_facets_order', "category\ntag");
$items = is_array($raw) ? $raw : (preg_split('/[\r\n]+/', (string) $raw) ?: []);
$items = array_map(static fn($s) => trim(sanitize_key((string) $s)), $items);
$raw = Settings::get_value('search_facets', []);
$items = is_array($raw) ? array_keys($raw) : [];
$items = array_map(static fn($s) => trim(sanitize_key((string) $s)), $items);
return array_values(array_filter(array_unique($items), fn(string $s) => $s !== ''));
}
public static function get_meilisearch_config(): array {
$s = Settings::get_all();
$s = Settings::get_all();
$opt = is_array($s['search_ms_opt'] ?? null) ? $s['search_ms_opt'] : [];
$enabled = !empty($s['search_ms_enabled']);
$api_url = esc_url_raw(trim((string) ($s['search_ms_api_url'] ?? '')));
$api_key = sanitize_text_field((string) ($s['search_ms_api_key'] ?? ''));
$index_prefix = sanitize_key((string) ($s['search_ms_index_prefix'] ?? 'aksrt'));
$synonyms_raw = trim((string) ($s['search_ms_synonyms'] ?? ''));
$synonyms = [];
if ($synonyms_raw !== '') {
$decoded = json_decode($synonyms_raw, true);
if (is_array($decoded)) {
$synonyms = $decoded;
}
$enabled = !empty($s['search_ms_s']);
$api_url = esc_url_raw(trim((string) ($opt['api_url'] ?? 'http://127.0.0.1:7700')));
$api_key = sanitize_text_field((string) ($opt['api_key'] ?? ''));
$index_prefix = sanitize_key((string) ($opt['index_prefix'] ?? 'aksrt'));
$synonyms_raw = $opt['synonyms'] ?? [];
$synonyms = [];
foreach ((array) $synonyms_raw as $row) {
if (!is_array($row)) {
continue;
}
$key = trim(sanitize_text_field((string) ($row['key'] ?? '')));
$values = array_values(array_filter(array_map('trim', explode(',', sanitize_text_field((string) ($row['val'] ?? ''))))));
if ($key !== '' && $values) {
$synonyms[$key] = $values;
}
}
return [
@@ -156,15 +150,96 @@ class ThemeSearch {
'api_key' => $api_key,
'index_prefix' => $index_prefix !== '' ? $index_prefix : 'aksrt',
'synonyms' => $synonyms,
'index_name' => ($index_prefix !== '' ? $index_prefix : 'aksrt') . '_posts',
];
}
'index_name' => ($index_prefix !== '' ? $index_prefix : 'aksrt') . '_posts',
];
}
public static function filter_posts_search(string $search, \WP_Query $query): string {
if (!$query->is_search() || !$query->get('s') || !self::search_custom_key_enabled()) {
return $search;
}
if (sanitize_key((string) $query->get('type')) === 'user') {
return ' AND 1=0';
}
$config = self::get_meilisearch_config();
if (!empty($config['enabled'])) {
return $search;
}
$keys = self::search_custom_key();
if (!$keys) {
return $search;
}
global $wpdb;
$terms = (array) ($query->query_vars['search_terms'] ?? []);
if (!$terms) {
$terms = [(string) $query->get('s')];
}
$groups = [];
$taxonomies = ['post_tag', 'category', 'topics', 'forum_tag', 'forum_topic', 'shop_tag', 'shop_cat', 'shop_discount'];
foreach ($terms as $term) {
$like = (!empty($query->query_vars['exact']) ? '' : '%') . $wpdb->esc_like((string) $term) . (!empty($query->query_vars['exact']) ? '' : '%');
$parts = [];
foreach ($keys as $key) {
if ($key === 'title') $parts[] = $wpdb->prepare("{$wpdb->posts}.post_title LIKE %s", $like);
elseif ($key === 'content') $parts[] = $wpdb->prepare("{$wpdb->posts}.post_content LIKE %s", $like);
elseif ($key === 'excerpt') $parts[] = $wpdb->prepare("{$wpdb->posts}.post_excerpt LIKE %s", $like);
elseif (in_array($key, $taxonomies, true)) $parts[] = $wpdb->prepare('(aksrt_search_tt.taxonomy = %s AND aksrt_search_terms.name LIKE %s)', $key, $like);
elseif ($key === 'coment') $parts[] = $wpdb->prepare('aksrt_search_comments.comment_content LIKE %s', $like);
elseif ($key === 'user') $parts[] = $wpdb->prepare('(aksrt_search_users.user_nicename LIKE %s OR aksrt_search_users.display_name LIKE %s)', $like, $like);
}
if ($parts) {
$groups[] = '(' . implode(' OR ', $parts) . ')';
}
}
if (!$groups) {
return $search;
}
if (!is_user_logged_in()) {
$groups[] = "({$wpdb->posts}.post_password = '')";
}
return ' AND ' . implode(' AND ', $groups);
}
public static function filter_posts_search_join(string $join, \WP_Query $query): string {
if (!$query->is_search() || !$query->get('s') || !self::search_custom_key_enabled() || !empty(self::get_meilisearch_config()['enabled'])) {
return $join;
}
global $wpdb;
$keys = self::search_custom_key();
if (in_array('coment', $keys, true)) {
$join .= " LEFT JOIN {$wpdb->comments} AS aksrt_search_comments ON ({$wpdb->posts}.ID = aksrt_search_comments.comment_post_ID)";
}
if (in_array('user', $keys, true)) {
$join .= " LEFT JOIN {$wpdb->users} AS aksrt_search_users ON ({$wpdb->posts}.post_author = aksrt_search_users.ID)";
}
if (array_intersect(['post_tag', 'category', 'topics', 'forum_tag', 'forum_topic', 'shop_tag', 'shop_cat', 'shop_discount'], $keys)) {
$join .= " LEFT JOIN {$wpdb->term_relationships} AS aksrt_search_tr ON ({$wpdb->posts}.ID = aksrt_search_tr.object_id)";
$join .= " LEFT JOIN {$wpdb->term_taxonomy} AS aksrt_search_tt ON (aksrt_search_tr.term_taxonomy_id = aksrt_search_tt.term_taxonomy_id)";
$join .= " LEFT JOIN {$wpdb->terms} AS aksrt_search_terms ON (aksrt_search_tt.term_id = aksrt_search_terms.term_id)";
}
return $join;
}
public static function filter_posts_search_distinct(string $distinct, \WP_Query $query): string {
return $query->is_search() && $query->get('s') && self::search_custom_key_enabled() ? 'DISTINCT' : $distinct;
}
public static function filter_search_query($query): void {
if (is_admin() || !$query->is_main_query() || !$query->is_search()) {
return;
}
$type = isset($_REQUEST['type']) ? sanitize_key((string) wp_unslash($_REQUEST['type'])) : '';
if (!in_array($type, ['post', 'user'], true)) {
$type = self::get_search_content_types()['default'];
}
$query->set('type', $type);
if ($type === 'user') {
$query->set('post__in', [0]);
return;
}
if (self::search_no_page()) {
$existing = $query->get('post_type');
if (empty($existing)) {
@@ -174,17 +249,52 @@ class ThemeSearch {
$exclude_cats = self::search_exclude_cats();
if (!empty($exclude_cats)) {
$cat_query = $query->get('cat');
$negatives = array_map(fn(int $id) => -$id, $exclude_cats);
if (!empty($cat_query)) {
$existing = is_array($cat_query) ? $cat_query : explode(',', (string) $cat_query);
$existing = array_map('intval', $existing);
$merged = array_merge($existing, $negatives);
$query->set('cat', implode(',', array_unique($merged)));
} else {
$query->set('cat', implode(',', $negatives));
foreach ($exclude_cats as $category_id) {
$children = get_term_children($category_id, 'category');
if (!is_wp_error($children)) {
$exclude_cats = array_merge($exclude_cats, $children);
}
}
$query->set('category__not_in', array_values(array_unique(array_map('absint', $exclude_cats))));
}
$term_id = isset($_REQUEST['trem']) ? absint(wp_unslash($_REQUEST['trem'])) : 0;
if ($term_id > 0) {
$term = get_term($term_id);
if ($term instanceof \WP_Term) {
$tax_query = (array) $query->get('tax_query');
$tax_query[] = [
'taxonomy' => $term->taxonomy,
'field' => 'term_id',
'terms' => $term->term_id,
];
$query->set('tax_query', $tax_query);
}
}
$user_id = isset($_REQUEST['user']) ? absint(wp_unslash($_REQUEST['user'])) : 0;
if ($user_id > 0) {
$query->set('author', $user_id);
}
$orderby = isset($_REQUEST['orderby']) ? sanitize_key((string) wp_unslash($_REQUEST['orderby'])) : '';
$meta_keys = [
'views' => 'aksrt_post_views',
'like' => '_aksrt_like_count',
'favorite' => '_aksrt_favorite_count',
'sales_volume' => '_aksrt_sales_volume',
];
if (isset($meta_keys[$orderby])) {
$query->set('meta_key', $meta_keys[$orderby]);
$query->set('orderby', ['meta_value_num' => 'DESC', 'date' => 'DESC']);
$query->set('order', 'DESC');
} elseif ($orderby === 'comment_count') {
$query->set('orderby', 'comment_count');
$query->set('order', 'DESC');
} elseif ($orderby === 'date') {
$query->set('orderby', 'date');
$query->set('order', 'DESC');
}
}
public static function apply_list_orderby($query): void {
@@ -221,37 +331,14 @@ class ThemeSearch {
}
public static function get_search_content_types(): array {
$all_types = [
'post' => 'search_type_post',
'user' => 'search_type_user',
'category' => 'search_type_category',
'tag' => 'search_type_tag',
];
$enabled = [];
$all = Settings::get_all();
foreach ($all_types as $type => $key) {
$default_on = in_array($type, ['post', 'category', 'tag'], true);
$is_enabled = array_key_exists($key, $all)
? !empty(Settings::get_value($key, $default_on))
: $default_on;
if ($is_enabled) {
$enabled[] = $type;
}
}
if (empty($enabled)) {
$enabled = ['post'];
}
$default = sanitize_key((string) Settings::get_value('search_default_type', 'post'));
if (!in_array($default, $enabled, true)) {
$default = $enabled[0];
$types = ['post', 'user'];
$default = sanitize_key((string) Settings::get_value('search_type_in', 'post'));
if (!in_array($default, $types, true)) {
$default = 'post';
}
return [
'types' => $enabled,
'types' => $types,
'default' => $default,
];
}
+2 -9
View File
@@ -54,13 +54,7 @@ final class AssetManager {
$css = $root . '/assets/widgets/frontend.css';
$js = $root . '/assets/widgets/frontend.js';
wp_register_style(self::STYLE_HANDLE, $uri . '/assets/widgets/frontend.css', ['aksrt-style'], is_file($css) ? (string) filemtime($css) : null);
wp_register_script(self::SCRIPT_HANDLE, $uri . '/assets/widgets/frontend.js', [], is_file($js) ? (string) filemtime($js) : null, true);
if (!wp_style_is('aksrt-swiper', 'registered')) {
wp_register_style('aksrt-swiper', $uri . '/assets/css/frontend/swiper-bundle.min.css', [], '11.2.10');
}
if (!wp_script_is('aksrt-swiper', 'registered')) {
wp_register_script('aksrt-swiper', $uri . '/assets/js/swiper-bundle.min.js', [], '11.2.10', true);
}
wp_register_script(self::SCRIPT_HANDLE, $uri . '/assets/widgets/frontend.js', ['loader_js'], is_file($js) ? (string) filemtime($js) : null, true);
$third_party = $uri . '/assets/widgets/third-party/';
wp_register_script('aksrt-widget-hls', $third_party . 'hls.min.js', [], 'reference-pinned', true);
wp_register_script('aksrt-widget-flv', $third_party . 'flv.min.js', [], 'reference-pinned', true);
@@ -72,8 +66,7 @@ final class AssetManager {
private static function enqueue_optional(string $asset): void {
if ($asset === 'swiper') {
wp_enqueue_style('aksrt-swiper');
wp_enqueue_script('aksrt-swiper');
// Zibll main.js owns the single Swiper runtime and discovers .new-swiper.
} elseif ($asset === 'dplayer') {
wp_enqueue_script('aksrt-widget-dplayer');
} elseif (in_array($asset, ['hls', 'flv', 'dash'], true)) {
+1 -1
View File
@@ -74,7 +74,7 @@ final class FormRenderer {
echo '<input class="widefat aksrt-widget-color" type="text" id="' . esc_attr($field_id) . '" name="' . esc_attr($field_name) . '" value="' . esc_attr((string) $value) . '">';
break;
case 'icon':
echo '<div class="aksrt-widget-icon"><i class="' . esc_attr((string) $value) . '" aria-hidden="true"></i><input class="widefat" type="text" id="' . esc_attr($field_id) . '" name="' . esc_attr($field_name) . '" value="' . esc_attr((string) $value) . '" placeholder="fa fa-star"></div>';
echo '<div class="aksrt-widget-icon"><i class="' . esc_attr((string) $value) . '" aria-hidden="true"></i><input class="widefat" type="text" id="' . esc_attr($field_id) . '" name="' . esc_attr($field_name) . '" value="' . esc_attr((string) $value) . '" placeholder="fa fas fa-star"></div>';
break;
case 'link':
self::link($widget, $key, is_array($value) ? $value : []);
@@ -130,7 +130,7 @@ final class ContentRenderer {
return RendererHelpers::empty_state(__('当前文章未配置付费内容', 'aksrt'));
}
if (function_exists('aksrt_has_paid_access') && aksrt_has_paid_access($post)) {
$html = '<div class="aksrt-post-pay is-authorized ' . esc_attr((string) $instance['theme']) . '"><i class="fas fa-check-circle" aria-hidden="true"></i><strong>' . esc_html__('内容已解锁', 'aksrt') . '</strong><p>' . esc_html__('你已拥有当前知识内容的访问权限。', 'aksrt') . '</p>';
$html = '<div class="aksrt-post-pay is-authorized ' . esc_attr((string) $instance['theme']) . '"><i class="fa fas fa-check-circle" aria-hidden="true"></i><strong>' . esc_html__('内容已解锁', 'aksrt') . '</strong><p>' . esc_html__('你已拥有当前知识内容的访问权限。', 'aksrt') . '</p>';
$html .= function_exists('aksrt_get_pay_attributes_html') ? aksrt_get_pay_attributes_html($post, 'aksrt-post-pay__attrs') : '';
$html .= function_exists('aksrt_get_demo_link_html') ? aksrt_get_demo_link_html($post, 'aksrt-widget-button') : '';
return $html . '</div>';
@@ -17,20 +17,20 @@ final class GeneralRenderer {
$action = esc_url(home_url('/'));
$placeholder = esc_attr((string) $i['placeholder']);
$style = sanitize_html_class((string) $i['search_style']);
return '<form class="aksrt-widget-search aksrt-widget-search--' . $style . '" role="search" method="get" action="' . $action . '"><label><span class="screen-reader-text">' . esc_html__('搜索:', 'aksrt') . '</span><input type="search" name="s" placeholder="' . $placeholder . '" autocomplete="off"></label><button type="submit" aria-label="' . esc_attr__('搜索', 'aksrt') . '"><i class="fas fa-search" aria-hidden="true"></i><span>' . esc_html__('搜索', 'aksrt') . '</span></button></form>';
return '<form class="aksrt-widget-search aksrt-widget-search--' . $style . '" role="search" method="get" action="' . $action . '"><label><span class="screen-reader-text">' . esc_html__('搜索:', 'aksrt') . '</span><input type="search" name="s" placeholder="' . $placeholder . '" autocomplete="off"></label><button type="submit" aria-label="' . esc_attr__('搜索', 'aksrt') . '"><i class="fa fas fa-search" aria-hidden="true"></i><span>' . esc_html__('搜索', 'aksrt') . '</span></button></form>';
}
private static function render_posts_toc(array $i): string {
if (!is_singular('post')) {
return '';
}
return '<nav class="aksrt-widget-toc' . (!empty($i['collapsed']) ? ' is-collapsed' : '') . '" data-min-headings="' . (int) $i['min_headings'] . '" data-scroll-offset="' . (int) $i['offset'] . '" aria-label="' . esc_attr__('文章目录', 'aksrt') . '"><button class="aksrt-widget-toc__toggle" type="button" aria-expanded="' . (empty($i['collapsed']) ? 'true' : 'false') . '"><span>' . esc_html__('文章目录', 'aksrt') . '</span><i class="fas fa-chevron-down" aria-hidden="true"></i></button><ol class="aksrt-widget-toc__list"></ol><p class="aksrt-widget-toc__empty">' . esc_html__('正在生成目录…', 'aksrt') . '</p></nav>';
return '<nav class="aksrt-widget-toc' . (!empty($i['collapsed']) ? ' is-collapsed' : '') . '" data-min-headings="' . (int) $i['min_headings'] . '" data-scroll-offset="' . (int) $i['offset'] . '" aria-label="' . esc_attr__('文章目录', 'aksrt') . '"><button class="aksrt-widget-toc__toggle" type="button" aria-expanded="' . (empty($i['collapsed']) ? 'true' : 'false') . '"><span>' . esc_html__('文章目录', 'aksrt') . '</span><i class="fa fas fa-chevron-down" aria-hidden="true"></i></button><ol class="aksrt-widget-toc__list"></ol><p class="aksrt-widget-toc__empty">' . esc_html__('正在生成目录…', 'aksrt') . '</p></nav>';
}
private static function render_quote(array $i): string {
$quotes = RendererHelpers::lines((string) $i['quotes']);
$text = $quotes ? $quotes[array_rand($quotes)] : __('保持好奇,持续创造。', 'aksrt');
return '<figure class="aksrt-widget-quote" data-source="' . esc_attr((string) $i['source']) . '" data-interval="' . (int) $i['interval'] . '"><i class="fas fa-quote-left" aria-hidden="true"></i><blockquote>' . esc_html($text) . '</blockquote><button type="button" aria-label="' . esc_attr__('换一句', 'aksrt') . '"><i class="fas fa-sync-alt" aria-hidden="true"></i></button></figure>';
return '<figure class="aksrt-widget-quote" data-source="' . esc_attr((string) $i['source']) . '" data-interval="' . (int) $i['interval'] . '"><i class="fa fas fa-quote-left" aria-hidden="true"></i><blockquote>' . esc_html($text) . '</blockquote><button type="button" aria-label="' . esc_attr__('换一句', 'aksrt') . '"><i class="fa fas fa-sync-alt" aria-hidden="true"></i></button></figure>';
}
private static function render_icon_cards(array $i): string {
@@ -55,7 +55,7 @@ final class GeneralRenderer {
} else {
$link = RendererHelpers::link((array) ($card['link'] ?? []));
$tag = $link['url'] ? 'a' : 'div';
$html .= '<' . $tag . ' class="aksrt-widget-icon-card ' . esc_attr((string) ($card['color'] ?? '')) . '"' . ($link['url'] ? ' href="' . $link['url'] . '"' . RendererHelpers::link_attrs($link) : '') . '><i class="' . esc_attr((string) ($card['icon'] ?? 'fa fa-star')) . '" aria-hidden="true"></i><span><strong>' . esc_html((string) ($card['title'] ?? '')) . '</strong><small>' . esc_html((string) ($card['description'] ?? '')) . '</small></span></' . $tag . '>';
$html .= '<' . $tag . ' class="aksrt-widget-icon-card ' . esc_attr((string) ($card['color'] ?? '')) . '"' . ($link['url'] ? ' href="' . $link['url'] . '"' . RendererHelpers::link_attrs($link) : '') . '><i class="' . esc_attr((string) ($card['icon'] ?? 'fa fas fa-star')) . '" aria-hidden="true"></i><span><strong>' . esc_html((string) ($card['title'] ?? '')) . '</strong><small>' . esc_html((string) ($card['description'] ?? '')) . '</small></span></' . $tag . '>';
}
}
return $html . '</div>';
@@ -201,6 +201,6 @@ final class GeneralRenderer {
$content = '<strong>' . esc_html((string) ($item['title'] ?? '')) . '</strong><span>' . esc_html((string) ($item['description'] ?? '')) . '</span>';
$slides .= '<div class="swiper-slide">' . ($link['url'] ? '<a href="' . $link['url'] . '"' . RendererHelpers::link_attrs($link) . '>' . $content . '</a>' : $content) . '</div>';
}
return '<div class="aksrt-widget-notice"><i class="fas fa-bullhorn" aria-hidden="true"></i><div class="swiper aksrt-widget-swiper" data-aksrt-swiper="notice" data-interval="' . ((int) $i['interval'] * 1000) . '"><div class="swiper-wrapper">' . $slides . '</div></div></div>';
return '<div class="aksrt-widget-notice"><i class="fa fas fa-bullhorn" aria-hidden="true"></i><div class="new-swiper aksrt-widget-swiper" data-aksrt-swiper="notice" data-direction="vertical" data-loop="true" data-autoplay="1" data-interval="' . ((int) $i['interval'] * 1000) . '"><div class="swiper-wrapper">' . $slides . '</div></div></div>';
}
}
@@ -47,7 +47,7 @@ final class KnowledgeProductRenderer {
}
$html .= '<h3>' . esc_html((string) ($plan['title'] ?? '')) . '</h3><div class="aksrt-pricing-card__price">' . esc_html((string) ($plan['price'] ?? '')) . '</div><p>' . esc_html((string) ($plan['description'] ?? '')) . '</p><ul>';
foreach (RendererHelpers::lines((string) ($plan['features'] ?? '')) as $feature) {
$html .= '<li><i class="fas fa-check" aria-hidden="true"></i>' . esc_html($feature) . '</li>';
$html .= '<li><i class="fa fas fa-check" aria-hidden="true"></i>' . esc_html($feature) . '</li>';
}
$html .= '</ul>' . ($url !== '' ? '<a class="aksrt-widget-button" href="' . esc_url($url) . '">' . esc_html($label) . '</a>' : '') . '</article>';
}
@@ -61,20 +61,20 @@ final class KnowledgeProductRenderer {
continue;
}
$rating = max(1, min(5, (int) ($item['rating'] ?? 5)));
$slides .= '<div class="swiper-slide"><article class="aksrt-review-card"><div class="aksrt-review-card__rating" aria-label="' . esc_attr(sprintf(__('%d 星评价', 'aksrt'), $rating)) . '">' . str_repeat('<i class="fas fa-star" aria-hidden="true"></i>', $rating) . '</div><blockquote>' . esc_html((string) ($item['description'] ?? '')) . '</blockquote><footer>' . RendererHelpers::image((string) ($item['image'] ?? ''), '', 'aksrt-review-card__avatar') . '<span><strong>' . esc_html((string) ($item['title'] ?? '')) . '</strong><small>' . esc_html((string) ($item['value'] ?? '')) . '</small></span></footer></article></div>';
$slides .= '<div class="swiper-slide"><article class="aksrt-review-card"><div class="aksrt-review-card__rating" aria-label="' . esc_attr(sprintf(__('%d 星评价', 'aksrt'), $rating)) . '">' . str_repeat('<i class="fa fas fa-star" aria-hidden="true"></i>', $rating) . '</div><blockquote>' . esc_html((string) ($item['description'] ?? '')) . '</blockquote><footer>' . RendererHelpers::image((string) ($item['image'] ?? ''), '', 'aksrt-review-card__avatar') . '<span><strong>' . esc_html((string) ($item['title'] ?? '')) . '</strong><small>' . esc_html((string) ($item['value'] ?? '')) . '</small></span></footer></article></div>';
}
return '<div class="swiper aksrt-widget-swiper aksrt-reviews" data-aksrt-swiper="cards"><div class="swiper-wrapper">' . $slides . '</div><div class="swiper-pagination"></div></div>';
return '<div class="new-swiper aksrt-widget-swiper aksrt-reviews" data-aksrt-swiper="cards"><div class="swiper-wrapper">' . $slides . '</div><div class="swiper-pagination"></div></div>';
}
private static function faq(array $i): string {
$html = '<div class="aksrt-faq">';
if (!empty($i['search'])) {
$html .= '<label class="aksrt-faq__search"><i class="fas fa-search" aria-hidden="true"></i><span class="screen-reader-text">' . esc_html__('搜索常见问题', 'aksrt') . '</span><input type="search" placeholder="' . esc_attr__('搜索问题', 'aksrt') . '"></label>';
$html .= '<label class="aksrt-faq__search"><i class="fa fas fa-search" aria-hidden="true"></i><span class="screen-reader-text">' . esc_html__('搜索常见问题', 'aksrt') . '</span><input type="search" placeholder="' . esc_attr__('搜索问题', 'aksrt') . '"></label>';
}
$html .= '<div class="aksrt-faq__items">';
foreach ((array) $i['items'] as $index => $item) {
$id = 'aksrt-faq-' . $index . '-' . wp_rand(1000, 9999);
$html .= '<section class="aksrt-faq__item" data-search="' . esc_attr(wp_strip_all_tags((string) ($item['question'] ?? '') . ' ' . (string) ($item['answer'] ?? ''))) . '"><button type="button" aria-expanded="false" aria-controls="' . esc_attr($id) . '"><span>' . esc_html((string) ($item['question'] ?? '')) . '</span><i class="fas fa-plus" aria-hidden="true"></i></button><div id="' . esc_attr($id) . '" hidden>' . wp_kses_post((string) ($item['answer'] ?? '')) . '</div></section>';
$html .= '<section class="aksrt-faq__item" data-search="' . esc_attr(wp_strip_all_tags((string) ($item['question'] ?? '') . ' ' . (string) ($item['answer'] ?? ''))) . '"><button type="button" aria-expanded="false" aria-controls="' . esc_attr($id) . '"><span>' . esc_html((string) ($item['question'] ?? '')) . '</span><i class="fa fas fa-plus" aria-hidden="true"></i></button><div id="' . esc_attr($id) . '" hidden>' . wp_kses_post((string) ($item['answer'] ?? '')) . '</div></section>';
}
return $html . '</div></div>';
}
@@ -41,7 +41,7 @@ final class SliderRenderer {
if ($slides === '') {
return RendererHelpers::empty_state(__('请配置幻灯片', 'aksrt'));
}
$slider = '<div class="swiper aksrt-widget-swiper aksrt-slider" data-aksrt-swiper="slider" data-direction="' . esc_attr((string) $instance['direction']) . '" data-effect="' . esc_attr((string) $instance['effect']) . '" data-loop="' . (!empty($instance['loop']) ? '1' : '0') . '" data-autoplay="' . (!empty($instance['autoplay']) ? '1' : '0') . '" data-interval="' . ((int) $instance['interval'] * 1000) . '" data-speed="' . (int) $instance['speed'] . '" data-space="' . (int) $instance['spacebetween'] . '" style="--aksrt-slider-height:' . (int) $instance['pc_height'] . 'px;--aksrt-slider-height-m:' . (int) $instance['m_height'] . 'px"><div class="swiper-wrapper">' . $slides . '</div>';
$slider = '<div class="new-swiper aksrt-widget-swiper aksrt-slider" data-aksrt-swiper="slider" data-direction="' . esc_attr((string) $instance['direction']) . '" data-effect="' . esc_attr((string) $instance['effect']) . '"' . (!empty($instance['loop']) ? ' data-loop="true"' : '') . (!empty($instance['autoplay']) ? ' data-autoplay="1"' : '') . ' data-interval="' . ((int) $instance['interval'] * 1000) . '" data-speed="' . (int) $instance['speed'] . '" data-spaceBetween="' . (int) $instance['spacebetween'] . '" style="--aksrt-slider-height:' . (int) $instance['pc_height'] . 'px;--aksrt-slider-height-m:' . (int) $instance['m_height'] . 'px"><div class="swiper-wrapper">' . $slides . '</div>';
if (!empty($instance['button'])) {
$slider .= '<button type="button" class="swiper-button-prev" aria-label="' . esc_attr__('上一张', 'aksrt') . '"></button><button type="button" class="swiper-button-next" aria-label="' . esc_attr__('下一张', 'aksrt') . '"></button>';
}
+1 -1
View File
@@ -264,7 +264,7 @@ final class WidgetSchemas {
return [
['id' => 'title', 'type' => 'text', 'label' => '标题', 'default' => ''],
['id' => 'description', 'type' => 'textarea', 'label' => '说明', 'default' => ''],
['id' => 'icon', 'type' => 'icon', 'label' => '图标', 'default' => 'fa fa-star'],
['id' => 'icon', 'type' => 'icon', 'label' => '图标', 'default' => 'fa fas fa-star'],
['id' => 'custom_icon', 'type' => 'upload', 'label' => '自定义图标', 'default' => ''],
['id' => 'color', 'type' => 'palette', 'label' => '颜色', 'default' => 'jb-blue', 'options' => CommonFields::palette()],
['id' => 'link', 'type' => 'link', 'label' => '链接', 'default' => []],