增加便民服务页面
This commit is contained in:
@@ -26,7 +26,7 @@
|
|||||||
- 📱 **响应式布局** - 完美适配 PC 端和移动端
|
- 📱 **响应式布局** - 完美适配 PC 端和移动端
|
||||||
- 🌐 **多语言支持** - 支持中文/英文切换
|
- 🌐 **多语言支持** - 支持中文/英文切换
|
||||||
- ⚡ **性能优化** - 轻量级设计,加载快速
|
- ⚡ **性能优化** - 轻量级设计,加载快速
|
||||||
- 🎯 **自定义文章类型** - 支持公告通知独立管理
|
- 🎯 **自定义内容类型** - 支持公告通知、社团新闻、便民服务独立管理
|
||||||
|
|
||||||
## 🚀 快速开始
|
## 🚀 快速开始
|
||||||
|
|
||||||
@@ -91,6 +91,37 @@ git clone https://github.com/itstudio-2002/ITStudioMainSite.git
|
|||||||
- 未设置 `itstudio_weight` 的文章按 `0` 处理。
|
- 未设置 `itstudio_weight` 的文章按 `0` 处理。
|
||||||
- 当高权重文章不足 4 篇时,页面会自动用最新文章补足。
|
- 当高权重文章不足 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/
|
ITStudioMainSite/
|
||||||
├── assets/
|
├── assets/
|
||||||
│ ├── css/
|
│ ├── css/
|
||||||
│ │ └── main.css # 主样式文件
|
│ │ ├── content.css # 内容页样式
|
||||||
|
│ │ ├── front-page.css # 首页样式
|
||||||
|
│ │ └── services-page.css # 便民服务页样式
|
||||||
│ └── js/
|
│ └── js/
|
||||||
│ ├── theme-toggle.js # 主题切换功能
|
│ ├── theme-toggle.js # 主题切换功能
|
||||||
│ └── main.js # 主要 JavaScript
|
│ └── main.js # 主要 JavaScript
|
||||||
@@ -127,6 +160,7 @@ ITStudioMainSite/
|
|||||||
├── footer.php # 底部模板
|
├── footer.php # 底部模板
|
||||||
├── single.php # 单篇文章模板
|
├── single.php # 单篇文章模板
|
||||||
├── page.php # 页面模板
|
├── page.php # 页面模板
|
||||||
|
├── page-services.php # 便民服务页面模板
|
||||||
├── archive.php # 归档页面模板
|
├── archive.php # 归档页面模板
|
||||||
└── 404.php # 404 错误页面
|
└── 404.php # 404 错误页面
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+473
-1
@@ -23,7 +23,7 @@ add_filter('pings_open', '__return_false', 20, 2);
|
|||||||
add_filter('comments_array', '__return_empty_array', 10, 2);
|
add_filter('comments_array', '__return_empty_array', 10, 2);
|
||||||
|
|
||||||
function itstudio_disable_comments_post_types() {
|
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) {
|
foreach ($post_types as $post_type) {
|
||||||
if (post_type_supports($post_type, 'comments')) {
|
if (post_type_supports($post_type, 'comments')) {
|
||||||
remove_post_type_support($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);
|
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
|
// 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-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);
|
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,
|
'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', 'announcement');
|
||||||
register_taxonomy_for_object_type('post_tag', 'news');
|
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');
|
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');
|
||||||
|
?>
|
||||||
|
<p>
|
||||||
|
<label for="itstudio_service_title_cn"><strong><?php esc_html_e('中文名称', 'itstudio'); ?></strong></label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="itstudio_service_title_cn"
|
||||||
|
name="itstudio_service_title_cn"
|
||||||
|
class="widefat"
|
||||||
|
placeholder="<?php echo esc_attr((string) get_the_title($post)); ?>"
|
||||||
|
value="<?php echo esc_attr($title_cn); ?>"
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="itstudio_service_title_en"><strong><?php esc_html_e('英文名称', 'itstudio'); ?></strong></label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="itstudio_service_title_en"
|
||||||
|
name="itstudio_service_title_en"
|
||||||
|
class="widefat"
|
||||||
|
placeholder="Service Name"
|
||||||
|
value="<?php echo esc_attr($title_en); ?>"
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="itstudio_service_excerpt_cn"><strong><?php esc_html_e('中文简介', 'itstudio'); ?></strong></label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<textarea
|
||||||
|
id="itstudio_service_excerpt_cn"
|
||||||
|
name="itstudio_service_excerpt_cn"
|
||||||
|
class="widefat"
|
||||||
|
rows="3"
|
||||||
|
placeholder="<?php echo esc_attr((string) get_the_excerpt($post)); ?>"
|
||||||
|
><?php echo esc_textarea($excerpt_cn); ?></textarea>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="itstudio_service_excerpt_en"><strong><?php esc_html_e('英文简介', 'itstudio'); ?></strong></label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<textarea
|
||||||
|
id="itstudio_service_excerpt_en"
|
||||||
|
name="itstudio_service_excerpt_en"
|
||||||
|
class="widefat"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Short English description"
|
||||||
|
><?php echo esc_textarea($excerpt_en); ?></textarea>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="itstudio_service_url"><strong><?php esc_html_e('目标链接', 'itstudio'); ?></strong></label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<input
|
||||||
|
type="url"
|
||||||
|
id="itstudio_service_url"
|
||||||
|
name="itstudio_service_url"
|
||||||
|
class="widefat"
|
||||||
|
placeholder="https://example.com"
|
||||||
|
value="<?php echo esc_attr($service_url); ?>"
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p class="description">
|
||||||
|
<?php esc_html_e('支持分别填写中英文名称与简介;未填写时会回退到标题/摘要。', 'itstudio'); ?>
|
||||||
|
</p>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
function itstudio_save_service_meta($post_id) {
|
||||||
|
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_POST['itstudio_service_meta_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['itstudio_service_meta_nonce'])), 'itstudio_save_service_meta')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!current_user_can('edit_post', $post_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_post_type($post_id) !== 'service') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$title_cn = isset($_POST['itstudio_service_title_cn']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_title_cn'])) : '';
|
||||||
|
$title_en = isset($_POST['itstudio_service_title_en']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_title_en'])) : '';
|
||||||
|
$excerpt_cn = isset($_POST['itstudio_service_excerpt_cn']) ? sanitize_textarea_field(wp_unslash($_POST['itstudio_service_excerpt_cn'])) : '';
|
||||||
|
$excerpt_en = isset($_POST['itstudio_service_excerpt_en']) ? sanitize_textarea_field(wp_unslash($_POST['itstudio_service_excerpt_en'])) : '';
|
||||||
|
|
||||||
|
$meta_updates = array(
|
||||||
|
itstudio_get_service_title_cn_meta_key() => 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');
|
||||||
|
?>
|
||||||
|
<div class="form-field term-itstudio-service-name-cn-wrap">
|
||||||
|
<label for="itstudio_service_cat_name_cn"><?php esc_html_e('中文名称', 'itstudio'); ?></label>
|
||||||
|
<input type="text" name="itstudio_service_cat_name_cn" id="itstudio_service_cat_name_cn" value="">
|
||||||
|
</div>
|
||||||
|
<div class="form-field term-itstudio-service-name-en-wrap">
|
||||||
|
<label for="itstudio_service_cat_name_en"><?php esc_html_e('英文名称', 'itstudio'); ?></label>
|
||||||
|
<input type="text" name="itstudio_service_cat_name_en" id="itstudio_service_cat_name_en" value="" placeholder="Category Name">
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
add_action('service_category_add_form_fields', 'itstudio_service_category_add_fields');
|
||||||
|
|
||||||
|
function itstudio_service_category_edit_fields($term) {
|
||||||
|
$term_id = (int) $term->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');
|
||||||
|
?>
|
||||||
|
<tr class="form-field term-itstudio-service-name-cn-wrap">
|
||||||
|
<th scope="row"><label for="itstudio_service_cat_name_cn"><?php esc_html_e('中文名称', 'itstudio'); ?></label></th>
|
||||||
|
<td><input type="text" name="itstudio_service_cat_name_cn" id="itstudio_service_cat_name_cn" value="<?php echo esc_attr($name_cn); ?>"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="form-field term-itstudio-service-name-en-wrap">
|
||||||
|
<th scope="row"><label for="itstudio_service_cat_name_en"><?php esc_html_e('英文名称', 'itstudio'); ?></label></th>
|
||||||
|
<td><input type="text" name="itstudio_service_cat_name_en" id="itstudio_service_cat_name_en" value="<?php echo esc_attr($name_en); ?>" placeholder="Category Name"></td>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
add_action('service_category_edit_form_fields', 'itstudio_service_category_edit_fields');
|
||||||
|
|
||||||
|
function itstudio_save_service_category_meta($term_id) {
|
||||||
|
if (!current_user_can('manage_categories')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($_POST['itstudio_service_category_meta_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['itstudio_service_category_meta_nonce'])), 'itstudio_save_service_category_meta')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name_cn = isset($_POST['itstudio_service_cat_name_cn']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_cat_name_cn'])) : '';
|
||||||
|
$name_en = isset($_POST['itstudio_service_cat_name_en']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_cat_name_en'])) : '';
|
||||||
|
|
||||||
|
$term_meta = array(
|
||||||
|
itstudio_get_service_category_name_cn_meta_key() => 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 '<span style="color:#888;">' . esc_html__('未分类', 'itstudio') . '</span>';
|
||||||
|
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 '<span style="color:#888;">-</span>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<a href="' . esc_url($url) . '" target="_blank" rel="noopener noreferrer">' . esc_html($url) . '</a>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_action('manage_service_posts_custom_column', 'itstudio_service_admin_custom_column', 10, 2);
|
||||||
|
|
||||||
function itstudio_archive_document_title($parts) {
|
function itstudio_archive_document_title($parts) {
|
||||||
if (is_post_type_archive('announcement')) {
|
if (is_post_type_archive('announcement')) {
|
||||||
$parts['title'] = '公告通知';
|
$parts['title'] = '公告通知';
|
||||||
@@ -369,6 +790,57 @@ function itstudio_news_fallback() {
|
|||||||
}
|
}
|
||||||
add_action('template_redirect', '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) {
|
function itstudio_get_post_views($post_id) {
|
||||||
$post_id = (int) $post_id;
|
$post_id = (int) $post_id;
|
||||||
if ($post_id <= 0) {
|
if ($post_id <= 0) {
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
<?php get_header(); ?>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$default_icon_url = get_template_directory_uri() . '/resources/it_logo_2024.svg';
|
||||||
|
$services_query = new WP_Query(array(
|
||||||
|
'post_type' => '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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<main class="site-main services-directory-page">
|
||||||
|
<div class="container">
|
||||||
|
<header class="services-directory-head">
|
||||||
|
<h1 class="services-directory-title" data-cn="便民服务" data-en="Service">便民服务</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<?php if (!empty($sections)) : ?>
|
||||||
|
<div class="services-directory-layout">
|
||||||
|
<aside class="services-directory-sidebar">
|
||||||
|
<div class="services-directory-nav-box">
|
||||||
|
<h2 class="services-directory-nav-title" data-cn="分类" data-en="Categories">分类</h2>
|
||||||
|
<ul class="services-directory-nav-list">
|
||||||
|
<?php foreach ($sections as $section) : ?>
|
||||||
|
<?php $count = count($section['items']); ?>
|
||||||
|
<li>
|
||||||
|
<a href="#service-section-<?php echo esc_attr($section['slug']); ?>">
|
||||||
|
<span class="services-directory-nav-name" data-cn="<?php echo esc_attr($section['name_cn']); ?>" data-en="<?php echo esc_attr($section['name_en']); ?>"><?php echo esc_html($section['name_cn']); ?></span>
|
||||||
|
<span class="services-directory-nav-count"><?php echo esc_html($count); ?></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<div class="services-directory-content">
|
||||||
|
<?php foreach ($sections as $section) : ?>
|
||||||
|
<section class="services-directory-group" id="service-section-<?php echo esc_attr($section['slug']); ?>">
|
||||||
|
<header class="services-directory-group-head">
|
||||||
|
<h2 data-cn="<?php echo esc_attr($section['name_cn']); ?>" data-en="<?php echo esc_attr($section['name_en']); ?>"><?php echo esc_html($section['name_cn']); ?></h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="services-directory-grid">
|
||||||
|
<?php foreach ($section['items'] as $item) : ?>
|
||||||
|
<a class="services-directory-card" href="<?php echo esc_url($item['url']); ?>" target="_blank" rel="noopener noreferrer">
|
||||||
|
<div class="services-directory-card-head">
|
||||||
|
<div class="services-directory-icon-wrap">
|
||||||
|
<?php if ($item['has_thumb']) : ?>
|
||||||
|
<?php echo get_the_post_thumbnail($item['id'], 'medium', array('class' => 'services-directory-icon')); ?>
|
||||||
|
<?php else : ?>
|
||||||
|
<img class="services-directory-icon services-directory-icon-fallback" src="<?php echo esc_url($default_icon_url); ?>" alt="<?php echo esc_attr($item['title_cn']); ?>">
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="services-directory-meta">
|
||||||
|
<h3 class="services-directory-name" data-cn="<?php echo esc_attr($item['title_cn']); ?>" data-en="<?php echo esc_attr($item['title_en']); ?>"><?php echo esc_html($item['title_cn']); ?></h3>
|
||||||
|
<span class="services-directory-category" data-cn="<?php echo esc_attr($item['term_name_cn']); ?>" data-en="<?php echo esc_attr($item['term_name_en']); ?>"><?php echo esc_html($item['term_name_cn']); ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="services-directory-desc" data-cn="<?php echo esc_attr($item['excerpt_cn']); ?>" data-en="<?php echo esc_attr($item['excerpt_en']); ?>"><?php echo esc_html($item['excerpt_cn']); ?></p>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php else : ?>
|
||||||
|
<section class="services-directory-empty">
|
||||||
|
<h2 data-cn="暂无便民服务" data-en="No services yet">暂无便民服务</h2>
|
||||||
|
<p data-cn="请先在后台“便民服务”中添加服务条目。" data-en="Please add services in wp-admin first.">请先在后台“便民服务”中添加服务条目。</p>
|
||||||
|
<?php if (current_user_can('edit_posts')) : ?>
|
||||||
|
<a class="services-directory-empty-btn" href="<?php echo esc_url(admin_url('post-new.php?post_type=service')); ?>" target="_blank" rel="noopener noreferrer" data-cn="前往新增服务" data-en="Create a service">前往新增服务</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php get_footer(); ?>
|
||||||
Reference in New Issue
Block a user