diff --git a/src/AKSRT/Widgets/WidgetFaq.php b/src/AKSRT/Widgets/WidgetFaq.php index 138a4f8b..ebf98dc9 100644 --- a/src/AKSRT/Widgets/WidgetFaq.php +++ b/src/AKSRT/Widgets/WidgetFaq.php @@ -1,6 +1,6 @@ esc_html__('可折叠 FAQ 列表,支持搜索框与侧栏文档卡。', 'aksrt'), + 'description' => esc_html__('FAQ 摘要卡 + 文档链接列表 + 帮助 CTA。', 'aksrt'), 'classname' => 'widget_aksrt_faq', ] ); @@ -25,6 +27,12 @@ class WidgetFaq extends \WP_Widget { public function widget($args, $instance): void { $faqs = $this->normalize_faqs($instance['faqs'] ?? []); if (!$faqs) { + if (current_user_can('manage_options')) { + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo '
' . esc_html__('常见问题解答:', 'aksrt') . '' . + esc_html__('请添加至少一条问题', 'aksrt') . '
'; + echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } return; } @@ -35,23 +43,60 @@ class WidgetFaq extends \WP_Widget { } $uid = 'aksrt-faq-' . esc_attr($this->id); - echo '
'; + echo '
'; if (!empty($instance['search_s'])) { $ph = (string) ($instance['search_placeholder'] ?? __('搜索问题…', 'aksrt')); - echo ''; + $btn = (string) ($instance['search_btn_text'] ?? __('搜索', 'aksrt')); + echo '
'; + echo '
'; } - echo '
'; + $doc_title = trim((string) ($instance['doc_title'] ?? '')); + $doc_desc = trim((string) ($instance['doc_desc'] ?? '')); + $doc_icon = sanitize_text_field((string) ($instance['doc_icon'] ?? 'fas fa-book')); + $doc_links = $this->normalize_doc_links($instance['doc_links'] ?? []); + $help_title = trim((string) ($instance['help_title'] ?? '')); + $help_sub = trim((string) ($instance['help_subtitle'] ?? '')); + $help_icon = sanitize_text_field((string) ($instance['help_icon'] ?? 'fas fa-graduation-cap')); + $help_url = esc_url_raw(trim((string) ($instance['help_btn_url'] ?? ''))); + $help_btn = trim((string) ($instance['help_btn_text'] ?? '')); + + $has_doc = ($doc_title !== '' || $doc_desc !== '' || $doc_links); + $has_help = ($help_title !== '' || $help_sub !== '' || ($help_btn !== '' && $help_url !== '')); + + $main_cls = 'aksrt-faq__main produck-faq-main'; + if (!$has_doc && !$has_help) { + $main_cls .= ' is-full'; + } + echo '
'; + echo '
'; + $n = 0; foreach ($faqs as $f) { $n++; - $num = str_pad((string) $n, 2, '0', STR_PAD_LEFT); - echo '
'; - echo '' . esc_html($num) . '' . esc_html($f['question']) . ''; + $num = str_pad((string) $n, 2, '0', STR_PAD_LEFT); + $tone = self::BADGE_TONES[($n - 1) % count(self::BADGE_TONES)]; + $preview = $f['answer'] !== '' ? wp_strip_all_tags($f['answer']) : ''; + if ($preview !== '') { + $preview = wp_trim_words($preview, 28); + } + echo '
'; + echo ''; + echo '' . esc_html($num) . ''; + echo ''; + echo '' . esc_html($f['question']) . ''; + if ($preview !== '') { + echo '' . esc_html($preview) . ''; + } + echo ''; + echo ''; + echo ''; if ($f['answer'] !== '') { echo '
' . wp_kses_post(wpautop($f['answer'])) . '
'; } @@ -59,41 +104,78 @@ class WidgetFaq extends \WP_Widget { } echo '
'; - $doc_title = trim((string) ($instance['doc_title'] ?? '')); - $doc_desc = trim((string) ($instance['doc_desc'] ?? '')); - $help_title = trim((string) ($instance['help_title'] ?? '')); - $help_url = esc_url_raw(trim((string) ($instance['help_btn_url'] ?? ''))); - $help_btn = trim((string) ($instance['help_btn_text'] ?? '')); - if ($doc_title !== '' || $help_title !== '') { - echo '
'; - if ($doc_title !== '') { - echo '
' . esc_html($doc_title) . ''; + if ($has_doc || $has_help) { + echo ''; } - echo '
'; + echo '
'; echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * @param mixed $raw - * @return array + * @return array */ private function normalize_faqs($raw): array { if (is_string($raw)) { @@ -112,11 +194,10 @@ class WidgetFaq extends \WP_Widget { if ($q === '') { continue; } - $a = (string) ($row['answer'] ?? $row['a'] ?? ''); - // Allow basic HTML in answers after kses on output. $out[] = [ 'question' => $q, - 'answer' => wp_kses_post($a), + 'answer' => wp_kses_post((string) ($row['answer'] ?? $row['a'] ?? '')), + 'category' => sanitize_key((string) ($row['category'] ?? 'all')), ]; if (count($out) >= 30) { break; @@ -125,39 +206,120 @@ class WidgetFaq extends \WP_Widget { return $out; } + /** + * @param mixed $raw + * @return array + */ + private function normalize_doc_links($raw): array { + 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'] ?? '')); + $url = esc_url_raw(trim((string) ($row['url'] ?? $row['link'] ?? ''))); + if ($title === '' && $url === '') { + continue; + } + $out[] = [ + 'title' => $title, + 'url' => $url, + 'desc' => sanitize_text_field((string) ($row['desc'] ?? '')), + 'icon' => sanitize_text_field((string) ($row['icon'] ?? '')), + 'tag' => sanitize_text_field((string) ($row['tag'] ?? '')), + 'btn_text' => sanitize_text_field((string) ($row['btn_text'] ?? '')), + ]; + if (count($out) >= 12) { + break; + } + } + return $out; + } + public function form($instance): void { - $faqs = is_string($instance['faqs'] ?? null) - ? (string) $instance['faqs'] - : wp_json_encode($this->normalize_faqs($instance['faqs'] ?? []), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + $faqs = $this->normalize_faqs($instance['faqs'] ?? []); + if (!$faqs) { + $faqs = [ + ['question' => '', 'answer' => '', 'category' => 'all'], + ['question' => '', 'answer' => '', 'category' => 'all'], + ]; + } + $doc_links = $this->normalize_doc_links($instance['doc_links'] ?? []); + if (!$doc_links) { + $doc_links = [ + ['title' => '', 'url' => '', 'desc' => '', 'icon' => 'fas fa-file-alt', 'tag' => '', 'btn_text' => ''], + ]; + } ?>

-

- -

-

+

+ +

+

+ +

+
+

+

+

-

-

+

+ +

+
+

+

+

+

+ +

+

+ +