fix(widgets): restore single-card reference UI for search and quote widgets
The 搜索框 and 一言 sidebar widgets fell into the generic renderer branch, so they rendered a .jio-panel card wrapping a second bespoke card (.jio-widget-search / .jio-widget-quote). In-article 一言 also used divergent modifier classes and an extra hover rule. - search: render through the shared jio_get_search_box() (legacy keyword, history and category pickers) inside one reference card, mirroring the reference widget's markup and title default 「搜索」 - quote: render the reference .yiyan-box card itself as the click root; the shell now emits only the reference widget-container/title wrapper - article 一言: adopt the reference class lists for header, footer and the standalone after-article box; drop the invented yiyan--* modifiers and the duplicate hover/opacity rules - client: fill .cn/.en in the reference order (first line .cn, second .en) and drop the stale window.JioYiyan bridge plus the dead qv-yiyan.php AJAX path in runtime main.js - schema: replace the ad-hoc search_style radio with the reference switches (keywords, history, input category, more_cats) and default title - assets: enqueue assets/js/yiyan.js through the quote widget's asset list Tests: widget-system suite 820/821 (the one failure is the pre-existing frontend-lifecycle theme-init stub); new search/quote card contracts pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
1549d5b25d
commit
f80ca1e27d
19 files changed
+276
-182
No files matched your search
@@ -58,7 +58,7 @@ final class AssetManager {
|
||||
wp_register_style('jio-pay-box', $uri . '/assets/css/frontend/pay-box.css', ['jio-public'], is_file($pay_css) ? (string) filemtime($pay_css) : null);
|
||||
$yiyan_js = $root . '/assets/js/yiyan.js';
|
||||
wp_register_script('jio-yiyan', $uri . '/assets/js/yiyan.js', ['loader_js'], is_file($yiyan_js) ? (string) filemtime($yiyan_js) : null, true);
|
||||
wp_register_script(self::SCRIPT_HANDLE, $uri . '/assets/widgets/frontend.js', ['loader_js', 'jio-yiyan'], is_file($js) ? (string) filemtime($js) : null, 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('jio-widget-hls', $third_party . 'hls.min.js', [], 'reference-pinned', true);
|
||||
wp_register_script('jio-widget-flv', $third_party . 'flv.min.js', [], 'reference-pinned', true);
|
||||
@@ -77,6 +77,8 @@ final class AssetManager {
|
||||
wp_enqueue_script('jio-widget-' . $asset);
|
||||
} elseif ($asset === 'tilt') {
|
||||
wp_enqueue_script('jio-widget-tilt');
|
||||
} elseif ($asset === 'yiyan') {
|
||||
wp_enqueue_script('jio-yiyan');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,10 @@ final class FrontendRenderer {
|
||||
echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
return;
|
||||
}
|
||||
if (in_array($definition->slug(), ['search', 'quote'], true)) {
|
||||
self::render_reference_widget($definition, $instance, $widget, $content, true);
|
||||
return;
|
||||
}
|
||||
if (in_array($definition->slug(), ['user_card', 'author_card', 'tab_posts', 'posts'], true)) {
|
||||
self::render_reference_widget($definition, $instance, $widget, $content);
|
||||
return;
|
||||
@@ -90,7 +94,13 @@ final class FrontendRenderer {
|
||||
echo (string) ($args['after_widget'] ?? '</section>'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
private static function render_reference_widget(WidgetDefinition $definition, array $instance, SchemaWidget $widget, string $content): void {
|
||||
/**
|
||||
* 参考主题侧栏结构:widget-container > 标题 + 内容。
|
||||
*
|
||||
* 搜索框 / 一言自带卡片(.zib-widget.widget-search / .yiyan-box),
|
||||
* 此时不再套 .widget-content 与第二层卡片;其余模块保持 .widget-content 结构层。
|
||||
*/
|
||||
private static function render_reference_widget(WidgetDefinition $definition, array $instance, SchemaWidget $widget, string $content, bool $own_card = false): void {
|
||||
$classes = ['jio-widget-box-wrap', 'jio-' . str_replace('_', '-', $definition->slug()) . '-wrap'];
|
||||
if (in_array($definition->slug(), ['user_card', 'author_card'], true)) {
|
||||
$classes[] = 'jio-user-widget-wrap';
|
||||
@@ -103,12 +113,12 @@ final class FrontendRenderer {
|
||||
$classes[] = 'jio-widget--affix';
|
||||
}
|
||||
|
||||
$content_classes = ['widget-content'];
|
||||
$animation = '';
|
||||
if (!empty($instance['animation_in'])) {
|
||||
$content_classes[] = 'obs-animate ani-' . sanitize_html_class((string) $instance['animation_in']);
|
||||
}
|
||||
if (!empty($instance['animation_repeat'])) {
|
||||
$content_classes[] = 'obs-animate-repeat';
|
||||
$animation = ' obs-animate ani-' . sanitize_html_class((string) $instance['animation_in']);
|
||||
if (!empty($instance['animation_repeat'])) {
|
||||
$animation .= ' obs-animate-repeat';
|
||||
}
|
||||
}
|
||||
|
||||
$style = self::style($instance);
|
||||
@@ -116,7 +126,11 @@ final class FrontendRenderer {
|
||||
echo '<div class="' . esc_attr(implode(' ', $classes)) . '" data-jio-widget="' . esc_attr($definition->slug()) . '" data-widget-id="' . esc_attr((string) $widget->id) . '"' . $affix_attr . ($style !== '' ? ' style="' . esc_attr($style) . '"' : '') . '>';
|
||||
echo '<div class="widget-container"><div>';
|
||||
echo self::reference_title($instance); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<div class="' . esc_attr(implode(' ', $content_classes)) . '">' . $content . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
if ($own_card) {
|
||||
echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
} else {
|
||||
echo '<div class="widget-content' . esc_attr($animation) . '">' . $content . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
echo '</div></div></div>';
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,27 @@ final class GeneralRenderer {
|
||||
}
|
||||
|
||||
private static function render_search(array $i): string {
|
||||
$action = esc_url(home_url('/'));
|
||||
$placeholder = esc_attr((string) $i['placeholder']);
|
||||
$style = sanitize_html_class((string) $i['search_style']);
|
||||
return '<form class="jio-widget-search jio-widget-search--' . $style . '" role="search" method="get" action="' . $action . '"><label><span class="screen-reader-text">' . esc_html__('搜索:', 'jio') . '</span><input type="search" name="s" placeholder="' . $placeholder . '" autocomplete="off"></label><button type="submit" aria-label="' . esc_attr__('搜索', 'jio') . '"><i class="fa fas fa-search" aria-hidden="true"></i><span>' . esc_html__('搜索', 'jio') . '</span></button></form>';
|
||||
if (!function_exists('jio_get_search_box')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$selected = array_values(array_filter(array_map('absint', preg_split('/[,,\s]+/', (string) ($i['in_cat'] ?? '')) ?: [])));
|
||||
$more_cats = array_values(array_filter(array_map('absint', preg_split('/[,,\s]+/', (string) ($i['more_cats'] ?? '')) ?: [])));
|
||||
$box = (string) jio_get_search_box([
|
||||
'class' => '',
|
||||
'show_keywords' => !empty($i['show_keywords']),
|
||||
'show_history' => !empty($i['show_history']),
|
||||
'keywords_title' => trim((string) ($i['keywords_title'] ?? '')) !== '' ? (string) $i['keywords_title'] : '热门搜索',
|
||||
'placeholder' => trim((string) ($i['placeholder'] ?? '')) !== '' ? (string) $i['placeholder'] : '开启精彩搜索',
|
||||
'show_input_cat' => !empty($i['show_input_cat']),
|
||||
'in_cat' => $selected ? (int) $selected[0] : 0,
|
||||
'more_cats' => $more_cats,
|
||||
]);
|
||||
if ($box === '') {
|
||||
return '';
|
||||
}
|
||||
// 参考主题:一键外框 .zib-widget.widget-search → 本项目同等卡片 .jio-panel.widget-search。
|
||||
return '<div class="jio-panel widget-search">' . $box . '</div>';
|
||||
}
|
||||
|
||||
private static function render_posts_toc(array $i): string {
|
||||
@@ -34,9 +51,13 @@ final class GeneralRenderer {
|
||||
}
|
||||
|
||||
private static function render_quote(array $i): string {
|
||||
return function_exists('jio_get_yiyan_markup')
|
||||
? jio_get_yiyan_markup(['class' => 'jio-widget-quote'])
|
||||
: '';
|
||||
if (!function_exists('jio_get_yiyan_markup')) {
|
||||
return '';
|
||||
}
|
||||
// 参考主题:.yiyan-box 既是卡片也是点击切换的根元素,内部只有 .yiyan。
|
||||
return jio_get_yiyan_markup([
|
||||
'class' => 'yiyan-box main-bg text-center box-body radius8 main-shadow',
|
||||
]);
|
||||
}
|
||||
|
||||
private static function render_icon_cards(array $i): string {
|
||||
|
||||
@@ -78,6 +78,7 @@ final class WidgetCatalog {
|
||||
],
|
||||
'fields' => WidgetSchemas::for($slug),
|
||||
'assets' => self::assets($slug),
|
||||
'title_default' => $slug === 'search' ? '搜索' : '',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -88,6 +89,9 @@ final class WidgetCatalog {
|
||||
if (in_array($slug, ['slider', 'slider_media_combo', 'reviews', 'oneline_posts'], true)) {
|
||||
return ['swiper'];
|
||||
}
|
||||
if ($slug === 'quote') {
|
||||
return ['yiyan'];
|
||||
}
|
||||
if ($slug === 'video') {
|
||||
return ['dplayer', 'hls', 'flv', 'dash'];
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ final class WidgetDefinition {
|
||||
private array $fields;
|
||||
private array $common;
|
||||
private array $assets;
|
||||
private string $title_default;
|
||||
|
||||
public function __construct(array $definition) {
|
||||
$slug = (string) ($definition['slug'] ?? '');
|
||||
@@ -50,6 +51,7 @@ final class WidgetDefinition {
|
||||
(array) ($definition['common'] ?? [])
|
||||
);
|
||||
$this->assets = array_values(array_unique(array_map('strval', (array) ($definition['assets'] ?? []))));
|
||||
$this->title_default = trim((string) ($definition['title_default'] ?? ''));
|
||||
}
|
||||
|
||||
public function slug(): string {
|
||||
@@ -89,7 +91,16 @@ final class WidgetDefinition {
|
||||
}
|
||||
|
||||
public function fields(): array {
|
||||
return array_merge(CommonFields::for_definition($this->common), $this->fields);
|
||||
$fields = array_merge(CommonFields::for_definition($this->common), $this->fields);
|
||||
if ($this->title_default !== '' && !empty($this->common['title'])) {
|
||||
foreach ($fields as $index => $field) {
|
||||
if (($field['id'] ?? '') === 'title') {
|
||||
$fields[$index]['default'] = $this->title_default;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/** Admin form layout: reference header (description, reminder), common params, then the "模块内容配置" subheading. */
|
||||
|
||||
@@ -33,8 +33,19 @@ final class WidgetSchemas {
|
||||
switch ($slug) {
|
||||
case 'search':
|
||||
return [
|
||||
['id' => 'placeholder', 'type' => 'text', 'label' => '提示文字', 'default' => '输入关键词搜索'],
|
||||
['id' => 'search_style', 'type' => 'radio', 'label' => '显示样式', 'default' => 'button', 'options' => ['button' => '按钮式', 'compact' => '紧凑式', 'large' => '大尺寸']],
|
||||
['id' => 'placeholder', 'type' => 'text', 'label' => '提示文字', 'default' => '开启精彩搜索'],
|
||||
['id' => 'show_keywords', 'type' => 'switcher', 'label' => '显示热门搜索关键词', 'default' => false],
|
||||
['id' => 'show_history', 'type' => 'switcher', 'label' => '显示用户搜索历史', 'default' => false],
|
||||
['id' => 'keywords_title', 'type' => 'text', 'label' => '热门搜索-标题', 'default' => '热门搜索', 'dependency' => ['show_keywords', '!=', '']],
|
||||
['id' => 'show_input_cat', 'type' => 'switcher', 'label' => '显示分类', 'default' => false],
|
||||
[
|
||||
'id' => 'in_cat', 'type' => 'text', 'label' => '默认已选择的分类', 'default' => '', 'sanitize' => 'ids',
|
||||
'description' => '填写分类ID,可留空', 'dependency' => ['show_input_cat', '!=', ''],
|
||||
],
|
||||
[
|
||||
'id' => 'more_cats', 'type' => 'text', 'label' => '更多分类的ID', 'default' => '', 'sanitize' => 'ids',
|
||||
'description' => '默认为全部分类,如需自定义则将分类的ID填入下方,多个ID用逗号隔开', 'dependency' => ['show_input_cat', '!=', ''],
|
||||
],
|
||||
];
|
||||
case 'posts_toc':
|
||||
return [
|
||||
|
||||
Reference in new issue
Block a user