diff --git a/README.md b/README.md index ba9cf40..77e74b7 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ - 📱 **响应式布局** - 完美适配 PC 端和移动端 - 🌐 **多语言支持** - 支持中文/英文切换 - ⚡ **性能优化** - 轻量级设计,加载快速 -- 🎯 **自定义文章类型** - 支持公告通知独立管理 +- 🎯 **自定义内容类型** - 支持公告通知、社团新闻、便民服务独立管理 ## 🚀 快速开始 @@ -91,6 +91,37 @@ git clone https://github.com/itstudio-2002/ITStudioMainSite.git - 未设置 `itstudio_weight` 的文章按 `0` 处理。 - 当高权重文章不足 4 篇时,页面会自动用最新文章补足。 +#### 5. 维护便民服务目录 + +主题内置了“便民服务(service)”内容类型,`/services` 页面会自动读取并展示。 + +每条服务信息来源: +- 图标:文章特色图(Featured Image) +- 名称:服务双语字段(中文名称 / 英文名称) +- 简介:服务双语字段(中文简介 / 英文简介) +- 类别:服务分类双语字段(中文名称 / 英文名称) +- 跳转链接:编辑页中的“服务跳转链接”字段 + +后台新增步骤: +1. 进入 **便民服务 > 新增便民服务**。 +2. 在“服务双语与链接”填写: + - 中文名称 / 英文名称 + - 中文简介 / 英文简介 + - 服务跳转链接 +3. 设置特色图作为服务图标。 +4. 在右侧选择或新建“服务分类”。 +5. 发布后,该服务会自动出现在 `/services` 页面中。 + +分类双语设置: +1. 进入 **便民服务 > 服务分类**。 +2. 新增或编辑分类时,可填写“中文名称”和“英文名称”。 +3. 前台会根据语言切换自动显示对应分类名。 + +说明: +- 若未设置“服务跳转链接”,前端会回退到该服务文章自身链接。 +- 若未设置特色图,前端会使用 `resources/it_logo_2024.svg` 作为默认图标。 +- 新增内容类型后若前台路由未生效,请进入 **设置 > 固定链接** 点击一次“保存更改”刷新重写规则。 + ## 🎨 设计规范 ### 主题色彩 @@ -112,7 +143,9 @@ git clone https://github.com/itstudio-2002/ITStudioMainSite.git ITStudioMainSite/ ├── assets/ │ ├── css/ -│ │ └── main.css # 主样式文件 +│ │ ├── content.css # 内容页样式 +│ │ ├── front-page.css # 首页样式 +│ │ └── services-page.css # 便民服务页样式 │ └── js/ │ ├── theme-toggle.js # 主题切换功能 │ └── main.js # 主要 JavaScript @@ -127,6 +160,7 @@ ITStudioMainSite/ ├── footer.php # 底部模板 ├── single.php # 单篇文章模板 ├── page.php # 页面模板 +├── page-services.php # 便民服务页面模板 ├── archive.php # 归档页面模板 └── 404.php # 404 错误页面 ``` diff --git a/assets/css/services-page.css b/assets/css/services-page.css new file mode 100644 index 0000000..e51dc25 --- /dev/null +++ b/assets/css/services-page.css @@ -0,0 +1,280 @@ +.services-directory-page { + padding: 36px 0 68px; +} + +.services-directory-head { + margin-bottom: 40px; +} + +.services-directory-title { + margin: 0; + font-size: clamp(2rem, 1.6vw + 1.5rem, 3rem); + line-height: 1.15; + color: var(--color-primary); +} + +.services-directory-layout { + display: grid; + grid-template-columns: 230px minmax(0, 1fr); + gap: 28px; + align-items: start; +} + +.services-directory-sidebar { + position: sticky; + top: calc(var(--header-height) + 18px); +} + +.services-directory-nav-box { + border: 1px solid var(--border-default); + border-radius: var(--radius-md); + background: color-mix(in srgb, var(--bg-surface) 92%, transparent); + padding: 14px; +} + +.services-directory-nav-title { + margin: 0; + font-size: 1rem; + color: var(--text-primary); +} + +.services-directory-nav-list { + margin-top: 10px; + display: flex; + flex-direction: column; + gap: 5px; +} + +.services-directory-nav-list a { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + padding: 8px 10px; + border-radius: 8px; + color: var(--text-secondary); + text-decoration: none; + border: 1px solid transparent; +} + +.services-directory-nav-list a:hover { + color: var(--color-primary); + border-color: var(--border-default); + background: color-mix(in srgb, var(--bg-card) 88%, transparent); +} + +.services-directory-nav-name { + font-size: 0.94rem; +} + +.services-directory-nav-count { + min-width: 26px; + padding: 1px 7px; + border-radius: 999px; + text-align: center; + font-size: 0.74rem; + font-weight: 700; + color: var(--text-secondary); + background: color-mix(in srgb, var(--bg-card) 72%, var(--bg-surface) 28%); + border: 1px solid var(--border-default); +} + +.services-directory-content { + min-width: 0; +} + +.services-directory-group { + scroll-margin-top: calc(var(--header-height) + 18px); +} + +.services-directory-group + .services-directory-group { + margin-top: 28px; +} + +.services-directory-group-head { + margin-bottom: 12px; +} + +.services-directory-group-head h2 { + margin: 0; + font-size: 1.52rem; + color: var(--text-primary); +} + +.services-directory-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 14px; + align-items: start; +} + +.services-directory-card { + display: block; + border: 1px solid var(--border-default); + border-radius: 12px; + background: color-mix(in srgb, var(--bg-card) 94%, transparent); + padding: 12px; + min-height: 0; + color: inherit; + text-decoration: none; + transition: transform var(--duration-fast) var(--ease-in-out), border-color var(--duration-fast) var(--ease-in-out), box-shadow var(--duration-fast) var(--ease-in-out); +} + +.services-directory-card:hover { + transform: translateY(-2px); + border-color: color-mix(in srgb, var(--color-primary) 52%, var(--border-default) 48%); + box-shadow: var(--shadow-sm); +} + +.services-directory-card-head { + display: flex; + align-items: center; + gap: 12px; +} + +.services-directory-icon-wrap { + width: 54px; + height: 54px; + border-radius: 12px; + border: none; + background: transparent; + overflow: hidden; + display: block; + flex-shrink: 0; +} + +.services-directory-icon { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.services-directory-icon-fallback { + opacity: 1; +} + +.services-directory-meta { + min-width: 0; +} + +.services-directory-name { + margin: 0; + font-size: 1.16rem; + line-height: 1.28; + color: var(--text-primary); + font-weight: 760; +} + +.services-directory-category { + margin-top: 4px; + display: inline-block; + font-size: 0.8rem; + color: var(--text-secondary); +} + +.services-directory-desc { + margin: 10px 0 0; + padding-top: 10px; + border-top: 1px solid color-mix(in srgb, var(--border-default) 84%, transparent); + color: var(--text-secondary); + font-size: 0.94rem; + line-height: 1.55; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.services-directory-empty { + margin-top: 16px; + border: 1px solid var(--border-default); + border-radius: 12px; + padding: 28px; + text-align: center; + background: color-mix(in srgb, var(--bg-card) 95%, transparent); +} + +.services-directory-empty h2 { + margin: 0; + font-size: 1.6rem; + color: var(--text-primary); +} + +.services-directory-empty p { + margin: 10px 0 0; + color: var(--text-secondary); +} + +.services-directory-empty-btn { + margin-top: 16px; + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 148px; + height: 38px; + padding: 0 16px; + border-radius: 10px; + border: 1px solid color-mix(in srgb, var(--color-primary) 65%, var(--border-default) 35%); + color: var(--color-primary); + text-decoration: none; + font-weight: 700; +} + +.services-directory-empty-btn:hover { + background: color-mix(in srgb, var(--color-primary) 10%, transparent); +} + +@media (max-width: 1280px) { + .services-directory-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 980px) { + .services-directory-head { + margin-bottom: 30px; + } + + .services-directory-layout { + grid-template-columns: 1fr; + gap: 16px; + } + + .services-directory-sidebar { + position: static; + } + + .services-directory-nav-list { + flex-direction: row; + flex-wrap: wrap; + gap: 8px; + } + + .services-directory-nav-list li { + flex: 0 0 auto; + } + + .services-directory-nav-list a { + padding: 7px 11px; + } +} + +@media (max-width: 680px) { + .services-directory-page { + padding: 26px 0 52px; + } + + .services-directory-head { + margin-bottom: 24px; + } + + .services-directory-grid { + grid-template-columns: 1fr; + gap: 12px; + } + + .services-directory-card { + min-height: 0; + } +} diff --git a/functions.php b/functions.php index 2a0b027..0430834 100644 --- a/functions.php +++ b/functions.php @@ -23,7 +23,7 @@ add_filter('pings_open', '__return_false', 20, 2); add_filter('comments_array', '__return_empty_array', 10, 2); function itstudio_disable_comments_post_types() { - $post_types = array('post', 'page', 'announcement', 'news'); + $post_types = array('post', 'page', 'announcement', 'news', 'service'); foreach ($post_types as $post_type) { if (post_type_supports($post_type, 'comments')) { remove_post_type_support($post_type, 'comments'); @@ -116,6 +116,18 @@ function itstudio_enqueue_scripts() { wp_enqueue_script('itstudio-about-hero', get_template_directory_uri() . '/assets/js/home-hero.js', array(), '1.0.0', true); } + // 仅在便民服务页加载(包含 /services fallback) + $is_services = is_page('services') || is_page_template('page-services.php'); + if (!$is_services && is_404()) { + global $wp; + $request = isset($wp->request) ? trim($wp->request, '/') : ''; + $is_services = ($request === 'services'); + } + + if ($is_services) { + wp_enqueue_style('itstudio-services-page', get_template_directory_uri() . '/assets/css/services-page.css', array('itstudio-content'), '1.0.0'); + } + // Scripts wp_enqueue_script('itstudio-theme-toggle', get_template_directory_uri() . '/assets/js/theme-toggle.js', array(), '1.0.0', true); wp_enqueue_script('itstudio-lang-toggle', get_template_directory_uri() . '/assets/js/lang-toggle.js', array(), '1.0.0', true); @@ -197,6 +209,47 @@ function itstudio_custom_post_types() { 'show_in_rest' => true, )); + register_taxonomy('service_category', array('service'), array( + 'labels' => array( + 'name' => __('服务分类', 'itstudio'), + 'singular_name' => __('服务分类', 'itstudio'), + ), + 'hierarchical' => true, + 'public' => true, + 'show_ui' => true, + 'show_admin_column' => false, + 'show_in_rest' => true, + 'rewrite' => array( + 'slug' => 'service-category', + 'with_front' => false, + ), + )); + + register_post_type('service', array( + 'labels' => array( + 'name' => __('便民服务', 'itstudio'), + 'singular_name' => __('便民服务', 'itstudio'), + 'menu_name' => __('便民服务', 'itstudio'), + 'add_new_item' => __('新增便民服务', 'itstudio'), + 'edit_item' => __('编辑便民服务', 'itstudio'), + ), + 'public' => true, + 'show_ui' => true, + 'show_in_menu' => true, + 'show_in_nav_menus' => false, + 'exclude_from_search' => true, + 'publicly_queryable' => true, + 'has_archive' => false, + 'rewrite' => array( + 'slug' => 'service', + 'with_front' => false, + ), + 'supports' => array('title', 'excerpt', 'thumbnail', 'page-attributes'), + 'taxonomies' => array('service_category'), + 'menu_icon' => 'dashicons-admin-tools', + 'show_in_rest' => true, + )); + register_taxonomy_for_object_type('post_tag', 'announcement'); register_taxonomy_for_object_type('post_tag', 'news'); } @@ -254,6 +307,374 @@ function itstudio_register_acf_fields() { } add_action('acf/init', 'itstudio_register_acf_fields'); +function itstudio_get_service_url_meta_key() { + return '_itstudio_service_url'; +} + +function itstudio_get_service_title_cn_meta_key() { + return '_itstudio_service_title_cn'; +} + +function itstudio_get_service_title_en_meta_key() { + return '_itstudio_service_title_en'; +} + +function itstudio_get_service_excerpt_cn_meta_key() { + return '_itstudio_service_excerpt_cn'; +} + +function itstudio_get_service_excerpt_en_meta_key() { + return '_itstudio_service_excerpt_en'; +} + +function itstudio_get_service_category_name_cn_meta_key() { + return 'itstudio_service_category_name_cn'; +} + +function itstudio_get_service_category_name_en_meta_key() { + return 'itstudio_service_category_name_en'; +} + +function itstudio_get_service_category_i18n_labels($term) { + if (!$term || is_wp_error($term)) { + return array( + 'cn' => '未分类', + 'en' => 'Uncategorized', + ); + } + + $term_id = (int) $term->term_id; + $name_cn = trim((string) get_term_meta($term_id, itstudio_get_service_category_name_cn_meta_key(), true)); + $name_en = trim((string) get_term_meta($term_id, itstudio_get_service_category_name_en_meta_key(), true)); + + if ($name_cn === '') { + $name_cn = (string) $term->name; + } + if ($name_en === '') { + $name_en = $name_cn; + } + + return array( + 'cn' => $name_cn, + 'en' => $name_en, + ); +} + +function itstudio_get_service_i18n_content($service_id, $excerpt_limit = 90) { + $service_id = (int) $service_id; + if ($service_id <= 0) { + return array( + 'title_cn' => '', + 'title_en' => '', + 'excerpt_cn' => '', + 'excerpt_en' => '', + ); + } + + $title_cn = trim((string) get_post_meta($service_id, itstudio_get_service_title_cn_meta_key(), true)); + $title_en = trim((string) get_post_meta($service_id, itstudio_get_service_title_en_meta_key(), true)); + $excerpt_cn = trim((string) get_post_meta($service_id, itstudio_get_service_excerpt_cn_meta_key(), true)); + $excerpt_en = trim((string) get_post_meta($service_id, itstudio_get_service_excerpt_en_meta_key(), true)); + + $fallback_title = trim((string) get_the_title($service_id)); + if ($fallback_title === '') { + $fallback_title = '未命名服务'; + } + + $fallback_excerpt = function_exists('itstudio_get_post_excerpt_chars') + ? itstudio_get_post_excerpt_chars($service_id, $excerpt_limit) + : wp_html_excerpt(wp_strip_all_tags((string) get_post_field('post_excerpt', $service_id)), $excerpt_limit, '...'); + $fallback_excerpt = trim((string) $fallback_excerpt); + if ($fallback_excerpt === '') { + $fallback_excerpt = '暂无简介'; + } + + if ($title_cn === '') { + $title_cn = $fallback_title; + } + if ($title_en === '') { + $title_en = $title_cn; + } + if ($excerpt_cn === '') { + $excerpt_cn = $fallback_excerpt; + } + if ($excerpt_en === '') { + $excerpt_en = $excerpt_cn; + } + + return array( + 'title_cn' => $title_cn, + 'title_en' => $title_en, + 'excerpt_cn' => $excerpt_cn, + 'excerpt_en' => $excerpt_en, + ); +} + +function itstudio_add_service_meta_boxes() { + add_meta_box( + 'itstudio_service_link', + __('服务双语与链接', 'itstudio'), + 'itstudio_render_service_link_meta_box', + 'service', + 'normal', + 'high' + ); +} +add_action('add_meta_boxes', 'itstudio_add_service_meta_boxes'); + +function itstudio_render_service_link_meta_box($post) { + $service_url = (string) get_post_meta($post->ID, itstudio_get_service_url_meta_key(), true); + $title_cn = (string) get_post_meta($post->ID, itstudio_get_service_title_cn_meta_key(), true); + $title_en = (string) get_post_meta($post->ID, itstudio_get_service_title_en_meta_key(), true); + $excerpt_cn = (string) get_post_meta($post->ID, itstudio_get_service_excerpt_cn_meta_key(), true); + $excerpt_en = (string) get_post_meta($post->ID, itstudio_get_service_excerpt_en_meta_key(), true); + wp_nonce_field('itstudio_save_service_meta', 'itstudio_service_meta_nonce'); + ?> +

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+

+ +

+ trim($title_cn), + itstudio_get_service_title_en_meta_key() => trim($title_en), + itstudio_get_service_excerpt_cn_meta_key() => trim($excerpt_cn), + itstudio_get_service_excerpt_en_meta_key() => trim($excerpt_en), + ); + + foreach ($meta_updates as $meta_key => $value) { + if ($value === '') { + delete_post_meta($post_id, $meta_key); + } else { + update_post_meta($post_id, $meta_key, $value); + } + } + + $url_meta_key = itstudio_get_service_url_meta_key(); + $raw_url = isset($_POST['itstudio_service_url']) ? trim((string) wp_unslash($_POST['itstudio_service_url'])) : ''; + + if ($raw_url === '') { + delete_post_meta($post_id, $url_meta_key); + return; + } + + if (strpos($raw_url, '/') === 0) { + $raw_url = home_url($raw_url); + } + + $service_url = esc_url_raw($raw_url); + if ($service_url === '') { + delete_post_meta($post_id, $url_meta_key); + return; + } + + update_post_meta($post_id, $url_meta_key, $service_url); +} +add_action('save_post_service', 'itstudio_save_service_meta'); + +function itstudio_service_category_add_fields($taxonomy) { + wp_nonce_field('itstudio_save_service_category_meta', 'itstudio_service_category_meta_nonce'); + ?> +
+ + +
+
+ + +
+ term_id; + $name_cn = (string) get_term_meta($term_id, itstudio_get_service_category_name_cn_meta_key(), true); + $name_en = (string) get_term_meta($term_id, itstudio_get_service_category_name_en_meta_key(), true); + wp_nonce_field('itstudio_save_service_category_meta', 'itstudio_service_category_meta_nonce'); + ?> + + + + + + + + + trim($name_cn), + itstudio_get_service_category_name_en_meta_key() => trim($name_en), + ); + + foreach ($term_meta as $meta_key => $value) { + if ($value === '') { + delete_term_meta($term_id, $meta_key); + } else { + update_term_meta($term_id, $meta_key, $value); + } + } +} +add_action('created_service_category', 'itstudio_save_service_category_meta'); +add_action('edited_service_category', 'itstudio_save_service_category_meta'); + +function itstudio_get_service_target_url($service_id) { + $service_id = (int) $service_id; + if ($service_id <= 0) { + return ''; + } + + $meta_key = itstudio_get_service_url_meta_key(); + $url = (string) get_post_meta($service_id, $meta_key, true); + if ($url !== '') { + return $url; + } + + return (string) get_permalink($service_id); +} + +function itstudio_service_admin_columns($columns) { + $columns['service_category'] = __('分类', 'itstudio'); + $columns['service_url'] = __('跳转链接', 'itstudio'); + return $columns; +} +add_filter('manage_service_posts_columns', 'itstudio_service_admin_columns'); + +function itstudio_service_admin_custom_column($column, $post_id) { + if ($column === 'service_category') { + $terms = get_the_terms($post_id, 'service_category'); + if (empty($terms) || is_wp_error($terms)) { + echo '' . esc_html__('未分类', 'itstudio') . ''; + return; + } + + $labels = array(); + foreach ($terms as $term) { + $i18n = itstudio_get_service_category_i18n_labels($term); + $label = $i18n['cn']; + if ($i18n['en'] !== $i18n['cn']) { + $label .= ' / ' . $i18n['en']; + } + $labels[] = $label; + } + + echo esc_html(implode(' | ', $labels)); + return; + } + + if ($column === 'service_url') { + $url = itstudio_get_service_target_url($post_id); + if ($url === '') { + echo '-'; + return; + } + + echo '' . esc_html($url) . ''; + } +} +add_action('manage_service_posts_custom_column', 'itstudio_service_admin_custom_column', 10, 2); + function itstudio_archive_document_title($parts) { if (is_post_type_archive('announcement')) { $parts['title'] = '公告通知'; @@ -369,6 +790,57 @@ function itstudio_news_fallback() { } add_action('template_redirect', 'itstudio_news_fallback'); +// Fallback: render /services even if the page isn't created in WP admin. +function itstudio_services_fallback() { + if (!is_404()) { + return; + } + + global $wp; + $request = isset($wp->request) ? trim($wp->request, '/') : ''; + if ($request !== 'services') { + return; + } + + $template = locate_template('page-services.php'); + if ($template) { + global $wp_query; + if ($wp_query) { + $wp_query->is_404 = false; + $wp_query->is_page = true; + $wp_query->is_singular = true; + $virtual_post = new WP_Post((object) array( + 'ID' => 0, + 'post_type' => 'page', + 'post_parent' => 0, + 'post_title' => __('便民服务', 'itstudio'), + 'post_status' => 'publish', + 'post_name' => 'services', + 'post_content' => '', + )); + $wp_query->post = $virtual_post; + $wp_query->posts = array($virtual_post); + $wp_query->queried_object = $virtual_post; + $wp_query->queried_object_id = 0; + $wp_query->post_count = 1; + $wp_query->found_posts = 1; + $wp_query->max_num_pages = 1; + global $post; + $post = $virtual_post; + setup_postdata($post); + } + add_filter('document_title_parts', function ($parts) { + $parts['title'] = __('便民服务', 'itstudio'); + return $parts; + }); + status_header(200); + nocache_headers(); + include $template; + exit; + } +} +add_action('template_redirect', 'itstudio_services_fallback'); + function itstudio_get_post_views($post_id) { $post_id = (int) $post_id; if ($post_id <= 0) { diff --git a/page-services.php b/page-services.php new file mode 100644 index 0000000..9088233 --- /dev/null +++ b/page-services.php @@ -0,0 +1,195 @@ + + + 'service', + 'post_status' => 'publish', + 'posts_per_page' => -1, + 'orderby' => array( + 'menu_order' => 'ASC', + 'date' => 'DESC', + ), +)); + +$grouped_services = array(); +$uncategorized_items = array(); + +if ($services_query->have_posts()) { + while ($services_query->have_posts()) { + $services_query->the_post(); + $service_id = get_the_ID(); + $service_terms = get_the_terms($service_id, 'service_category'); + $service_url = function_exists('itstudio_get_service_target_url') ? itstudio_get_service_target_url($service_id) : get_permalink($service_id); + $service_url = is_string($service_url) ? trim($service_url) : ''; + if ($service_url === '') { + $service_url = '#'; + } + + $i18n_content = function_exists('itstudio_get_service_i18n_content') + ? itstudio_get_service_i18n_content($service_id, 90) + : array( + 'title_cn' => get_the_title($service_id), + 'title_en' => get_the_title($service_id), + 'excerpt_cn' => function_exists('itstudio_get_post_excerpt_chars') + ? itstudio_get_post_excerpt_chars($service_id, 90) + : wp_html_excerpt(wp_strip_all_tags(get_the_excerpt() ?: get_the_content()), 90, '...'), + 'excerpt_en' => function_exists('itstudio_get_post_excerpt_chars') + ? itstudio_get_post_excerpt_chars($service_id, 90) + : wp_html_excerpt(wp_strip_all_tags(get_the_excerpt() ?: get_the_content()), 90, '...'), + ); + + $item = array( + 'id' => $service_id, + 'title_cn' => $i18n_content['title_cn'], + 'title_en' => $i18n_content['title_en'], + 'url' => $service_url, + 'excerpt_cn' => $i18n_content['excerpt_cn'], + 'excerpt_en' => $i18n_content['excerpt_en'], + 'has_thumb' => has_post_thumbnail($service_id), + 'term_name_cn' => '', + 'term_name_en' => '', + ); + + if (!empty($service_terms) && !is_wp_error($service_terms)) { + $primary_term = $service_terms[0]; + $term_id = (int) $primary_term->term_id; + $term_labels = function_exists('itstudio_get_service_category_i18n_labels') + ? itstudio_get_service_category_i18n_labels($primary_term) + : array('cn' => $primary_term->name, 'en' => $primary_term->name); + $item['term_name_cn'] = $term_labels['cn']; + $item['term_name_en'] = $term_labels['en']; + + if (!isset($grouped_services[$term_id])) { + $grouped_services[$term_id] = array( + 'term' => $primary_term, + 'items' => array(), + ); + } + $grouped_services[$term_id]['items'][] = $item; + } else { + $item['term_name_cn'] = '未分类'; + $item['term_name_en'] = 'Uncategorized'; + $uncategorized_items[] = $item; + } + } + wp_reset_postdata(); +} + +$sections = array(); +if (!empty($grouped_services)) { + $ordered_terms = get_terms(array( + 'taxonomy' => 'service_category', + 'hide_empty' => true, + )); + + if (!is_wp_error($ordered_terms) && !empty($ordered_terms)) { + foreach ($ordered_terms as $term) { + $term_id = (int) $term->term_id; + if (!isset($grouped_services[$term_id])) { + continue; + } + $term_labels = function_exists('itstudio_get_service_category_i18n_labels') + ? itstudio_get_service_category_i18n_labels($term) + : array('cn' => $term->name, 'en' => $term->name); + $sections[] = array( + 'slug' => sanitize_title($term->slug), + 'name_cn' => $term_labels['cn'], + 'name_en' => $term_labels['en'], + 'items' => $grouped_services[$term_id]['items'], + ); + } + } else { + foreach ($grouped_services as $group) { + $term_labels = function_exists('itstudio_get_service_category_i18n_labels') + ? itstudio_get_service_category_i18n_labels($group['term']) + : array('cn' => $group['term']->name, 'en' => $group['term']->name); + $sections[] = array( + 'slug' => sanitize_title($group['term']->slug), + 'name_cn' => $term_labels['cn'], + 'name_en' => $term_labels['en'], + 'items' => $group['items'], + ); + } + } +} + +if (!empty($uncategorized_items)) { + $sections[] = array( + 'slug' => 'uncategorized', + 'name_cn' => '未分类', + 'name_en' => 'Uncategorized', + 'items' => $uncategorized_items, + ); +} +?> + +
+
+
+

便民服务

+
+ + +
+ + + +
+ +
+

暂无便民服务

+

请先在后台“便民服务”中添加服务条目。

+ + 前往新增服务 + +
+ +
+
+ +