@@ -1,6 +1,6 @@
< ? php
/**
* Multi-tab forum topic lists (zibll zib_bbs_widget_ui_tab_posts lite + lazy REST ).
* Multi-tab forum topic lists (zibll zib_bbs_widget_ui_tab_posts + shared mini rows ).
*
* @package AKSRT
*/
@@ -16,7 +16,7 @@ class WidgetForumTabTopics extends \WP_Widget {
'aksrt_forum_tab_topics' ,
esc_html__ ( '论坛 - 多栏目帖子' , 'aksrt' ),
[
'description' => esc_html__ ( '热门/最新/精华等栏目切换的帖子列表(懒加载)。' , 'aksrt' ),
'description' => esc_html__ ( '热门/最新/精华等栏目切换的帖子列表(共享迷你行 + 懒加载)。' , 'aksrt' ),
'classname' => 'widget_aksrt_forum_tab_topics' ,
]
);
@@ -35,8 +35,14 @@ class WidgetForumTabTopics extends \WP_Widget {
];
}
$count = max ( 1 , min ( 20 , ( int ) ( $instance [ 'count' ] ? ? 6 )));
$uid = 'aksrt-ftab-' . esc_attr ( $this -> id );
$rest = rest_url ( 'aksrt/v1/forum/frontend/widgets/topics' );
$style = sanitize_key (( string ) ( $instance [ 'style' ] ? ? 'mini' ) );
if ( ! in_array ( $style , [ 'mini' , 'rank' ], true )) {
$style = 'mini' ;
}
$plate = max ( 0 , ( int ) ( $instance [ 'plate' ] ? ? 0 ));
$uid = 'aksrt-ftab-' . esc_attr ( $this -> id );
// Prefer WidgetAjax forum-topics (HotTopics payload with style/plate).
$rest = rest_url ( 'aksrt/v1/widgets/forum-topics' );
echo $args [ 'before_widget' ]; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$title = apply_filters ( 'widget_title' , ( string ) ( $instance [ 'title' ] ? ? '' ), $instance , $this -> id_base );
@@ -44,23 +50,25 @@ class WidgetForumTabTopics extends \WP_Widget {
echo $args [ 'before_title' ] . esc_html ( $title ) . $args [ 'after_title' ]; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo '<div class="aksrt-ftab" id="' . $uid . '" data-rest="' . esc_url ( $rest ) . '" data-count="' . esc_attr (( string ) $count ) . '">' ;
echo '<ul class="aksrt-ftab__nav" role="tablist">' ;
echo '<div class="aksrt-ftab widget-tab-posts " id="' . $uid . '" data-aksrt-tabs="1" data-rest="' . esc_url ( $rest ) . '" data-count="' . esc_attr (( string ) $count ) . '" data-style="' . esc_attr ( $style ) . '" data-plate="' . esc_attr (( string ) $plate ) . '">' ;
echo '<ul class="aksrt-ftab__nav widget-tab-posts__nav " role="tablist">' ;
foreach ( $tabs as $i => $tab ) {
$cls = $i === 0 ? ' is-active' : '' ;
echo '<li><button type="button" class="aksrt-ftab__btn' . esc_attr ( $cls ) . '" data-index="' . ( int ) $i . '" data-orderby="' . esc_attr ( $tab [ 'orderby' ]) . '">' . esc_html ( $tab [ 'title' ]) . '</button></li>' ;
echo '<li role="presentation" ><button type="button" role="tab" class="aksrt-ftab__btn widget-tab-posts__tab ' . esc_attr ( $cls ) . '" data-index="' . ( int ) $i . '" data-orderby="' . esc_attr ( $tab [ 'orderby' ]) . '" aria-selected="' . ( $i === 0 ? 'true' : 'false' ) . '">' . esc_html ( $tab [ 'title' ]) . '</button></li>' ;
}
echo '</ul>' ;
foreach ( $tabs as $i => $tab ) {
$cls = $i === 0 ? ' is-active' : '' ;
$cls = $i === 0 ? ' is-active' : '' ;
$loaded = $i === 0 ? '1' : '0' ;
echo '<div class="aksrt-ftab__panel' . esc_attr ( $cls ) . '" data-index="' . ( int ) $i . '" data-loaded="' . esc_attr ( $loaded ) . '">' ;
echo '<div class="aksrt-ftab__panel widget-tab-posts__panel ' . esc_attr ( $cls ) . '" data-index="' . ( int ) $i . '" data-loaded="' . esc_attr ( $loaded ) . '"' . ( $i === 0 ? '' : ' hidden' ) . ' role="tabpanel" >';
if ( $i === 0 ) {
$payload = WidgetForumTopicLists :: query_payload ([
$payload = WidgetForumHotTopics :: query_payload ([
'count' => $count ,
'orderby' => $tab [ 'orderby' ],
'style ' => 'mini ' ,
'period ' => 'all ' ,
'style' => $style ,
'plate' => $plate ,
'paginate' => 'none' ,
], 1 );
echo $payload [ 'html' ]; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -77,11 +85,13 @@ class WidgetForumTabTopics extends \WP_Widget {
if(!root||root._aksrtFtab)return; root._aksrtFtab=1;
var rest=root.getAttribute('data-rest')||'';
var count=root.getAttribute('data-count')||'6';
var style=root.getAttribute('data-style')||'mini';
var plate=root.getAttribute('data-plate')||'0';
var btns=[].slice.call(root.querySelectorAll('.aksrt-ftab__btn'));
var panels=[].slice.call(root.querySelectorAll('.aksrt-ftab__panel'));
function load(panel, orderby){
if(!panel||panel.getAttribute('data-loaded')==='1'||!rest)return;
var qs=new URLSearchParams({page:'1',count:count,orderby:orderby||'date',style:'mini ',paginate:'none'});
var qs=new URLSearchParams({page:'1',count:count,orderby:orderby||'date',style:style,plate:plate,period:'all ',paginate:'none'});
var url=rest+(rest.indexOf('?')>-1?'&':'?')+qs.toString();
panel.classList.add('is-ajax-loading');
fetch(url,{credentials:'same-origin',headers:{Accept:'application/json','X-WP-Nonce':(window.aksrtData&&aksrtData.restNonce)||''}})
@@ -94,8 +104,16 @@ class WidgetForumTabTopics extends \WP_Widget {
}).catch(function(){panel.classList.remove('is-ajax-loading');});
}
function go(i){
btns.forEach(function(b,idx){b.classList.toggle('is-active',idx===i);});
panels.forEach(function(p,idx){p.classList.toggle('is-active', idx===i);}) ;
btns.forEach(function(b,idx){
var on= idx===i;
b.classList.toggle('is-active',on);
b.setAttribute('aria-selected',on?'true':'false');
});
panels.forEach(function(p,idx){
var on=idx===i;
p.classList.toggle('is-active',on);
if(on){p.removeAttribute('hidden');}else{p.setAttribute('hidden','');}
});
var btn=btns[i], panel=panels[i];
if(btn&&panel) load(panel, btn.getAttribute('data-orderby')||'date');
}
@@ -148,6 +166,8 @@ class WidgetForumTabTopics extends \WP_Widget {
$defaults = [
'title' => __('论坛栏目', 'aksrt'),
'count' => 6,
'style' => 'mini',
'plate' => 0,
'tabs' => "最新|date\n热门|views\n精华|essence",
];
$instance = wp_parse_args($instance, $defaults);
@@ -170,6 +190,19 @@ class WidgetForumTabTopics extends \WP_Widget {
<input class="tiny-text" type="number" min="1" max="20" name="<?php echo esc_attr($this->get_field_name('count')); ?>" value="<?php echo esc_attr((string) $instance['count']); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('样式', 'aksrt'); ?>
<select name="<?php echo esc_attr($this->get_field_name('style')); ?>">
<option value="mini" <?php selected($instance['style'], 'mini'); ?>><?php esc_html_e('迷你信息行', 'aksrt'); ?></option>
<option value="rank" <?php selected($instance['style'], 'rank'); ?>><?php esc_html_e('排行榜', 'aksrt'); ?></option>
</select>
</label>
</p>
<p>
<label><?php esc_html_e('版块 ID(可选)', 'aksrt'); ?>
<input class="tiny-text" type="number" min="0" name="<?php echo esc_attr($this->get_field_name('plate')); ?>" value="<?php echo esc_attr((string) ((int) $instance['plate'])); ?>">
</label>
</p>
<p>
<label><?php esc_html_e('栏目(每行: 标题|排序 date/views/essence/comments) ', 'aksrt'); ?>
<textarea class="widefat" rows="4" name="<?php echo esc_attr($this->get_field_name('tabs')); ?>"><?php echo esc_textarea((string) $tabs_val); ?></textarea>
@@ -179,9 +212,15 @@ class WidgetForumTabTopics extends \WP_Widget {
}
public function update($new_instance, $old_instance): array {
$style = sanitize_key((string) ($new_instance['style'] ?? 'mini'));
if (!in_array($style, ['mini', 'rank'], true)) {
$style = 'mini';
}
return [
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
'count' => max(1, min(20, (int) ($new_instance['count'] ?? 6))),
'style' => $style,
'plate' => max(0, (int) ($new_instance['plate'] ?? 0)),
'tabs' => sanitize_textarea_field((string) ($new_instance['tabs'] ?? '')),
];
}