207 lines
8.4 KiB
PHP
207 lines
8.4 KiB
PHP
<?php
|
|
/**
|
|
* Scrolling notice bar (zibll widget_ui_notice / zib_notice → vertical new-swiper).
|
|
*
|
|
* @package AKSRT
|
|
*/
|
|
|
|
namespace AKSRT\Widgets;
|
|
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class NoticeWidget extends \WP_Widget {
|
|
|
|
public function __construct() {
|
|
parent::__construct('aksrt_notice', esc_html__('AKSRT 滚动公告', 'aksrt'), [
|
|
'description' => esc_html__('多条公告垂直滚动(共享 Swiper 栈)。', 'aksrt'),
|
|
'classname' => 'widget_aksrt_notice',
|
|
]);
|
|
}
|
|
|
|
public function widget($args, $instance): void {
|
|
$items = $this->normalize_items($instance);
|
|
if (!$items) {
|
|
if (current_user_can('manage_options')) {
|
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
echo function_exists('aksrt_get_widget_null')
|
|
? aksrt_get_widget_null(__('请添加至少一条公告', 'aksrt')) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
: '<p class="widget-empty">' . esc_html__('请添加至少一条公告', 'aksrt') . '</p>';
|
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
return;
|
|
}
|
|
|
|
$color = sanitize_html_class((string) ($instance['color'] ?? 'c-blue'));
|
|
$blank = !empty($instance['blank']);
|
|
$radius = !empty($instance['radius']);
|
|
$interval = max(2, min(15, (int) ($instance['interval'] ?? 4)));
|
|
$align = sanitize_html_class((string) ($instance['alignment'] ?? ''));
|
|
|
|
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
$title = apply_filters('widget_title', (string) ($instance['title'] ?? ''), $instance, $this->id_base);
|
|
if ($title !== '') {
|
|
echo $args['before_title'] . esc_html($title) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
$wrap_cls = 'aksrt-scroll-notice swiper-bulletin color-' . $color;
|
|
if ($radius) {
|
|
$wrap_cls .= ' is-radius radius';
|
|
}
|
|
if ($align !== '') {
|
|
$wrap_cls .= ' ' . $align;
|
|
}
|
|
echo '<div class="' . esc_attr($wrap_cls) . '">';
|
|
echo '<div class="aksrt-scroll-notice__icon bulletin-icon"><i class="fas fa-bullhorn" aria-hidden="true"></i></div>';
|
|
|
|
// Prefer shared vertical new-swiper (zib_notice parity) via slider.js Type C.
|
|
echo '<div class="new-swiper aksrt-notice-swiper" data-direction="vertical" data-loop data-autoplay data-interval="' . esc_attr((string) ($interval * 1000)) . '">';
|
|
echo '<div class="swiper-wrapper">';
|
|
foreach ($items as $item) {
|
|
$inner = '';
|
|
if ($item['icon'] !== '') {
|
|
$icon = $item['icon'];
|
|
if (strpos($icon, 'fa-') === 0 && strpos($icon, ' ') === false) {
|
|
$icon = 'fa ' . $icon;
|
|
}
|
|
$inner .= '<div class="relative bulletin-icon mr6"><i class="abs-center ' . esc_attr($icon) . '" aria-hidden="true"></i></div>';
|
|
}
|
|
$inner .= esc_html($item['title']);
|
|
echo '<div class="swiper-slide notice-slide">';
|
|
if ($item['href'] !== '') {
|
|
echo '<a class="text-ellipsis"' .
|
|
($blank ? ' target="_blank" rel="noopener noreferrer"' : '') .
|
|
' href="' . esc_url($item['href']) . '">' . $inner . '</a>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
} else {
|
|
echo '<span class="text-ellipsis">' . $inner . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
echo '</div>';
|
|
}
|
|
echo '</div></div>';
|
|
|
|
echo '</div>';
|
|
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $instance
|
|
* @return array<int, array{title:string,icon:string,href:string}>
|
|
*/
|
|
private function normalize_items(array $instance): array {
|
|
$raw = $instance['items'] ?? $instance['img_ids'] ?? null;
|
|
if ($raw === null && !empty($instance['content'])) {
|
|
return [[
|
|
'title' => wp_strip_all_tags((string) $instance['content']),
|
|
'icon' => sanitize_text_field((string) ($instance['icon'] ?? 'fas fa-bullhorn')),
|
|
'href' => '',
|
|
]];
|
|
}
|
|
if (is_string($raw)) {
|
|
$decoded = json_decode($raw, true);
|
|
$raw = is_array($decoded) ? $decoded : [];
|
|
}
|
|
if (!is_array($raw)) {
|
|
return [];
|
|
}
|
|
$out = [];
|
|
foreach ($raw as $row) {
|
|
if (!is_array($row)) {
|
|
continue;
|
|
}
|
|
$title = sanitize_text_field((string) ($row['title'] ?? $row['content'] ?? ''));
|
|
if ($title === '') {
|
|
continue;
|
|
}
|
|
$out[] = [
|
|
'title' => $title,
|
|
'icon' => sanitize_text_field((string) ($row['icon'] ?? '')),
|
|
'href' => esc_url_raw(trim((string) ($row['href'] ?? $row['url'] ?? $row['link'] ?? ''))),
|
|
];
|
|
if (count($out) >= 12) {
|
|
break;
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function form($instance): void {
|
|
$items = $this->normalize_items($instance);
|
|
if (!$items) {
|
|
$items = [
|
|
['title' => '', 'icon' => 'fas fa-bullhorn', 'href' => ''],
|
|
['title' => '', 'icon' => 'fas fa-info-circle', 'href' => ''],
|
|
];
|
|
}
|
|
$json = wp_json_encode($items, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
$colors = [
|
|
'c-blue' => __('透明蓝', 'aksrt'),
|
|
'c-green' => __('透明绿', 'aksrt'),
|
|
'c-yellow' => __('透明黄', 'aksrt'),
|
|
'c-red' => __('透明粉红', 'aksrt'),
|
|
'c-purple' => __('透明紫', 'aksrt'),
|
|
'c-blue-2' => __('透明深蓝', 'aksrt'),
|
|
'c-green-2' => __('透明墨绿', 'aksrt'),
|
|
'c-yellow-2' => __('透明橘黄', 'aksrt'),
|
|
'c-red-2' => __('透明红', 'aksrt'),
|
|
'c-purple-2' => __('透明深紫', 'aksrt'),
|
|
'b-theme' => __('主题色', 'aksrt'),
|
|
'b-red' => __('红色', 'aksrt'),
|
|
'b-yellow' => __('黄色', 'aksrt'),
|
|
'b-blue' => __('蓝色', 'aksrt'),
|
|
'b-green' => __('绿色', 'aksrt'),
|
|
'b-purple' => __('紫色', 'aksrt'),
|
|
];
|
|
?>
|
|
<p>
|
|
<label><?php esc_html_e('标题(可选)', 'aksrt'); ?>
|
|
<input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title')); ?>" value="<?php echo esc_attr((string) ($instance['title'] ?? '')); ?>">
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><?php esc_html_e('公告条目 JSON', 'aksrt'); ?>
|
|
<textarea class="widefat" rows="6" name="<?php echo esc_attr($this->get_field_name('items')); ?>" placeholder='[{"title":"公告内容","icon":"fas fa-bullhorn","href":""}]'><?php echo esc_textarea((string) $json); ?></textarea>
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><?php esc_html_e('切换间隔(秒)', 'aksrt'); ?>
|
|
<input class="tiny-text" type="number" min="2" max="15" name="<?php echo esc_attr($this->get_field_name('interval')); ?>" value="<?php echo esc_attr((string) ((int) ($instance['interval'] ?? 4))); ?>">
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><?php esc_html_e('主题色彩', 'aksrt'); ?>
|
|
<select class="widefat" name="<?php echo esc_attr($this->get_field_name('color')); ?>">
|
|
<?php foreach ($colors as $k => $label) : ?>
|
|
<option value="<?php echo esc_attr($k); ?>" <?php selected(($instance['color'] ?? 'c-blue'), $k); ?>><?php echo esc_html($label); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><?php esc_html_e('对齐', 'aksrt'); ?>
|
|
<select name="<?php echo esc_attr($this->get_field_name('alignment')); ?>">
|
|
<option value="" <?php selected(($instance['alignment'] ?? ''), ''); ?>><?php esc_html_e('靠左', 'aksrt'); ?></option>
|
|
<option value="text-center" <?php selected(($instance['alignment'] ?? ''), 'text-center'); ?>><?php esc_html_e('居中', 'aksrt'); ?></option>
|
|
<option value="text-right" <?php selected(($instance['alignment'] ?? ''), 'text-right'); ?>><?php esc_html_e('靠右', 'aksrt'); ?></option>
|
|
</select>
|
|
</label>
|
|
</p>
|
|
<p>
|
|
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('blank')); ?>" value="1" <?php checked(!empty($instance['blank'])); ?>> <?php esc_html_e('链接新窗口', 'aksrt'); ?></label><br>
|
|
<label><input type="checkbox" name="<?php echo esc_attr($this->get_field_name('radius')); ?>" value="1" <?php checked(!empty($instance['radius'])); ?>> <?php esc_html_e('两端圆形', 'aksrt'); ?></label>
|
|
</p>
|
|
<?php
|
|
}
|
|
|
|
public function update($new_instance, $old_instance): array {
|
|
return [
|
|
'title' => sanitize_text_field((string) ($new_instance['title'] ?? '')),
|
|
'items' => $this->normalize_items(['items' => $new_instance['items'] ?? []]),
|
|
'interval' => max(2, min(15, (int) ($new_instance['interval'] ?? 4))),
|
|
'color' => sanitize_html_class((string) ($new_instance['color'] ?? 'c-blue')),
|
|
'alignment' => sanitize_html_class((string) ($new_instance['alignment'] ?? '')),
|
|
'blank' => !empty($new_instance['blank']) ? 1 : 0,
|
|
'radius' => !empty($new_instance['radius']) ? 1 : 0,
|
|
];
|
|
}
|
|
}
|