diff --git a/README.md b/README.md index 9953363..5434b5d 100644 --- a/README.md +++ b/README.md @@ -60,16 +60,36 @@ git clone https://github.com/itstudio-2002/ITStudioMainSite.git #### 2. 发布公告 主题内置了"公告通知"自定义文章类型: -1. 进入 **公告 > 新建公告** +1. 进入 **Announcement > 新建 Announcement** 2. 填写标题和内容 3. 发布即可在首页显示 -#### 3. 技术博客 +#### 3. 发布新闻 -使用 WordPress 默认的文章功能发布技术博客: -1. 进入 **文章 > 写文章** -2. 撰写博客内容 -3. 发布后会在首页博客栏显示 +主题内置了"社团新闻"自定义文章类型: +1. 进入 **News > 新建 News** +2. 填写标题和内容 +3. 发布即可在首页显示 + +#### 4. 新闻公告页权重字段(ACF) + +新闻公告页右侧“高权重文章”读取 ACF 数值字段 `itstudio_weight`(数值越大,排序越靠前)。 + +适用范围: +- 默认文章(`post`) +- 公告(`announcement`) +- 新闻(`news`) + +设置步骤: +1. 安装并启用插件 **Advanced Custom Fields (ACF)**。 +2. 主题会自动注册字段组“内容权重”,字段名为 `itstudio_weight`(显示名“权重”)。 +3. 编辑文章时在右侧填写“权重”数值(例如 `10`、`50`、`100`)。 +4. 更新或发布文章。 + +说明: +- 当前仅读取 ACF 字段值,不再使用 Gutenberg 的“自定义字段”面板作为权重来源。 +- 未设置 `itstudio_weight` 的文章按 `0` 处理。 +- 当高权重文章不足 4 篇时,页面会自动用最新文章补足。 ## 🎨 设计规范 @@ -144,7 +164,7 @@ MIT License - 详见 LICENSE 文件 🎯 **使命**: 发现人才,培养人才,输送人才 🔗 **链接**: -- GitHub: [github.com/itstudio-2002](https://github.com/itstudio-2002) +- GitHub: [https://github.com/ITStudioOUC](https://github.com/ITStudioOUC) - Email: contact@itstudio.club ## 🤝 贡献 @@ -158,4 +178,4 @@ MIT License - 详见 LICENSE 文件 - ✅ 基础主题功能实现 - ✅ 响应式设计完成 - ✅ 主题切换功能 -- ✅ 自定义文章类型(公告) \ No newline at end of file +- ✅ 自定义文章类型(公告) diff --git a/archive.php b/archive.php index 8f1e973..f4b162b 100644 --- a/archive.php +++ b/archive.php @@ -1,5 +1,240 @@ + + + + $active_post_type, + 'post_status' => 'publish', + 'posts_per_page' => 10, + 'paged' => $paged, + 's' => $keyword, + 'ignore_sticky_posts' => true, + 'orderby' => 'date', + 'order' => 'DESC', +)); + +$featured_query = new WP_Query(array( + 'post_type' => $active_post_type, + 'post_status' => 'publish', + 'posts_per_page' => 4, + 'ignore_sticky_posts' => true, + 'meta_key' => $weight_meta_key, + 'orderby' => array( + 'meta_value_num' => 'DESC', + 'date' => 'DESC', + ), + 'order' => 'DESC', + 'no_found_rows' => true, +)); +$featured_ids = array_map('intval', wp_list_pluck($featured_query->posts, 'ID')); +wp_reset_postdata(); + +if (count($featured_ids) < 4) { + $fill_query = new WP_Query(array( + 'post_type' => $active_post_type, + 'post_status' => 'publish', + 'posts_per_page' => 4 - count($featured_ids), + 'ignore_sticky_posts' => true, + 'post__not_in' => $featured_ids, + 'orderby' => 'date', + 'order' => 'DESC', + 'no_found_rows' => true, + )); + $featured_ids = array_merge($featured_ids, array_map('intval', wp_list_pluck($fill_query->posts, 'ID'))); + wp_reset_postdata(); +} +$featured_ids = array_slice(array_values(array_unique($featured_ids)), 0, 4); +?> +
+
+
+

+
+ +
+ +
+ +
+
+ have_posts()) : ?> +
+ have_posts()) : $list_query->the_post(); ?> + + + +
+ + + +

+ + +
+ + +
+
+
+
@@ -30,8 +265,8 @@
-
@@ -57,15 +292,16 @@ 2, - 'prev_text' => __('← 上一页', 'itstudio'), - 'next_text' => __('下一页 →', 'itstudio'), + 'prev_text' => __('Previous', 'itstudio'), + 'next_text' => __('Next', 'itstudio'), )); ?>
-

+

+ diff --git a/assets/css/content.css b/assets/css/content.css index a8379a8..49cf65a 100644 --- a/assets/css/content.css +++ b/assets/css/content.css @@ -543,3 +543,433 @@ ol.comment-list { .gh-file-content { padding: 20px; } .gh-pro-header .entry-title { font-size: 1.75rem; } } + +/* News & Announcements Archive */ +.news-archive-page { + padding: 36px 0 60px; +} + +.news-archive-head { + margin-bottom: 0; +} + +.news-archive-title { + margin: 0; + font-size: clamp(2.05rem, 1.2vw + 1.6rem, 2.9rem); + line-height: 1.2; + color: var(--color-primary); +} + +.news-archive-tools { + margin-top: 14px; + display: grid; + grid-template-columns: 1fr minmax(240px, 320px); + gap: 12px; + align-items: center; +} + +.news-archive-tools-single { + grid-template-columns: minmax(240px, 420px); + justify-content: end; + margin-left: auto; +} + +.news-archive-search { + display: grid; + grid-template-columns: 1fr auto; + gap: 8px; +} + +.news-archive-search input[type="search"] { + width: 100%; + height: 36px; + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + background: transparent; + color: var(--text-primary); + padding: 0 11px; + font-size: 0.88rem; +} + +.news-archive-search input[type="search"]:focus { + outline: none; + border-color: var(--color-primary); +} + +.news-archive-search button { + height: 36px; + padding: 0 12px; + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + background: transparent; + color: var(--text-primary); + font-size: 0.86rem; + font-weight: 600; + cursor: pointer; +} + +.news-archive-search button:hover { + border-color: var(--color-primary); + color: var(--color-primary); +} + +.news-archive-layout { + margin-top: 22px; + display: grid; + grid-template-columns: minmax(0, 1fr) 320px; + gap: 28px; + align-items: start; +} + +.news-main-column { + min-width: 0; +} + +.news-stream { + display: flex; + flex-direction: column; +} + +.news-story { + display: grid; + grid-template-columns: minmax(0, 1fr) 232px; + align-items: start; + gap: 16px; + padding: 16px 0; + border-bottom: 1px solid var(--border-default); +} + +.news-story-cover { + display: flex; + align-items: center; + justify-content: center; + height: 144px; + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + overflow: hidden; + background: color-mix(in srgb, var(--bg-surface) 88%, transparent); +} + +.news-story-cover img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.news-story-cover img.news-story-cover-fallback { + width: 33.333%; + height: auto; + max-height: 33.333%; + object-fit: contain; +} + +.news-story-body { + min-width: 0; +} + +.news-story-title { + margin: 0; + font-size: clamp(1.32rem, 0.2vw + 1.24rem, 1.62rem); + line-height: 1.35; +} + +.news-story-title a { + color: var(--text-primary); + text-decoration: none; +} + +.news-story-title a:hover { + color: var(--color-primary); +} + +.news-story-meta { + margin-top: 8px; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px; + color: var(--text-secondary); + font-size: 0.8rem; + font-family: var(--font-mono); +} + +.news-story-meta-item { + display: inline-flex; + align-items: center; + gap: 4px; +} + +.news-story-meta-item strong { + color: var(--text-primary); +} + +.news-story-meta-dot { + color: var(--border-default); +} + +.news-story-excerpt { + margin: 10px 0 0; + color: var(--text-secondary); + line-height: 1.66; + font-size: 0.95rem; +} + +.news-story-tags { + margin-top: 10px; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 6px; +} + +.news-story-tag-label { + font-size: 0.78rem; + color: var(--text-secondary); + font-family: var(--font-mono); +} + +.news-story-tag, +.news-story-tag-empty { + display: inline-flex; + align-items: center; + min-height: 22px; + padding: 0 8px; + border: 1px solid var(--border-default); + border-radius: 999px; + font-size: 0.75rem; + color: var(--text-secondary); + background: color-mix(in srgb, var(--bg-card) 88%, transparent); +} + +.news-story-tag { + text-decoration: none; +} + +.news-story-tag:hover { + color: var(--color-primary); + border-color: var(--color-primary); +} + +.news-side-column { + min-width: 0; +} + +.news-side-block { + margin-top: 16px; + border: 1px solid var(--border-default); + border-radius: var(--radius-md); + padding: 14px; + background: color-mix(in srgb, var(--bg-card) 84%, transparent); +} + +.news-side-title { + margin: 0; + font-size: 1.06rem; + color: var(--text-primary); + line-height: 1.3; +} + +.news-side-list { + list-style: none; + margin: 12px 0 0; + padding: 0; + display: grid; + gap: 12px; +} + +.news-side-item { + display: grid; + grid-template-columns: 88px minmax(0, 1fr); + gap: 10px; + padding-bottom: 12px; + border-bottom: 1px solid var(--border-default); +} + +.news-side-item:last-child { + padding-bottom: 0; + border-bottom: 0; +} + +.news-side-cover { + width: 88px; + height: 64px; + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + overflow: hidden; + background: var(--bg-surface); + display: flex; + align-items: center; + justify-content: center; +} + +.news-side-cover img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.news-side-cover img.news-side-cover-fallback { + width: 33.333%; + height: auto; + max-height: 33.333%; + object-fit: contain; +} + +.news-side-body { + min-width: 0; +} + +.news-side-item-title { + margin: 0; + font-size: 0.9rem; + line-height: 1.4; +} + +.news-side-item-title a { + color: var(--text-primary); + text-decoration: none; +} + +.news-side-item-title a:hover { + color: var(--color-primary); +} + +.news-side-meta { + margin-top: 6px; + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 5px; + color: var(--text-secondary); + font-size: 0.73rem; + font-family: var(--font-mono); +} + +.news-side-meta-dot { + color: var(--border-default); +} + +.news-side-empty { + color: var(--text-secondary); + font-size: 0.86rem; +} + +.news-archive-pagination { + margin-top: 18px; + display: flex; + justify-content: center; +} + +.news-archive-pagination .page-numbers { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 34px; + min-height: 34px; + padding: 0 10px; + margin: 0 4px; + border: 1px solid var(--border-default); + border-radius: var(--radius-sm); + background: var(--bg-card); + color: var(--text-secondary); + font-size: 0.88rem; +} + +.news-archive-pagination .page-numbers.current { + color: var(--color-primary); + border-color: var(--color-primary); +} + +.news-archive-empty { + margin: 14px 0 0; + color: var(--text-secondary); +} + +@media (max-width: 1180px) { + .news-archive-layout { + grid-template-columns: minmax(0, 1fr) 292px; + gap: 22px; + } + + .news-story { + grid-template-columns: minmax(0, 1fr) 204px; + } + + .news-story-cover { + height: 132px; + } +} + +@media (max-width: 980px) { + .news-archive-layout { + grid-template-columns: 1fr; + } + + .news-side-block { + margin-top: 0; + } + + .news-side-column { + order: -1; + } + + .news-main-column { + order: 1; + } +} + +@media (max-width: 760px) { + .news-archive-page { + padding: 28px 0 50px; + } + + .news-archive-tools { + margin-top: 14px; + } + + .news-archive-tools { + grid-template-columns: 1fr; + } + + .news-archive-tools-single { + grid-template-columns: 1fr; + margin-left: 0; + } + + .news-archive-search { + grid-template-columns: 1fr; + } + + .news-story { + grid-template-columns: 1fr; + gap: 12px; + } + + .news-story-cover { + order: -1; + height: 168px; + } + + .news-story-body { + order: 1; + } + + .news-story-title { + font-size: 1.08rem; + } + + .news-side-item { + grid-template-columns: 82px minmax(0, 1fr); + } + + .news-side-cover { + width: 82px; + height: 58px; + } +} + +@media (max-width: 560px) { + .news-story-cover { + height: 168px; + } +} diff --git a/assets/css/front-page.css b/assets/css/front-page.css index 2a74b47..afa5865 100644 --- a/assets/css/front-page.css +++ b/assets/css/front-page.css @@ -113,19 +113,15 @@ .services-provided h2, .landing-feed-head h2 { margin: 0 0 12px; - font-size: 1.15rem; - color: var(--text-primary); + font-size: clamp(1.35rem, 0.5vw + 1.2rem, 1.75rem); + color: var(--color-primary); display: flex; align-items: center; } .services-provided h2::before, .landing-feed-head h2::before { - content: "#"; - margin-right: 8px; - color: var(--color-primary); - font-family: var(--font-mono); - font-weight: 700; + content: none; } .services-grid-box { diff --git a/assets/js/lang-toggle.js b/assets/js/lang-toggle.js index b6abca8..295d95e 100644 --- a/assets/js/lang-toggle.js +++ b/assets/js/lang-toggle.js @@ -3,30 +3,63 @@ const body = document.body; function getPreferredLang() { const savedLang = localStorage.getItem('language'); - if (savedLang) { + if (savedLang === 'zh' || savedLang === 'en') { return savedLang; } return 'zh'; } -function setLang(lang) { - if (lang === 'en') { - body.setAttribute('lang', 'en'); - if (langToggle) { - langToggle.querySelector('.lang-text').textContent = '中'; - } - } else { - body.setAttribute('lang', 'zh'); - if (langToggle) { - langToggle.querySelector('.lang-text').textContent = 'EN'; +function setElementTextByLang(element, lang) { + const nextText = lang === 'en' ? element.getAttribute('data-en') : element.getAttribute('data-cn'); + if (!nextText) { + return; + } + + if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') { + const inputType = (element.getAttribute('type') || '').toLowerCase(); + if (inputType === 'submit' || inputType === 'button' || inputType === 'reset') { + element.value = nextText; + return; } } - // 处理 Input 元素的值切换 (input[type=submit] cannot use CSS content replacement) - const inputs = document.querySelectorAll('input[type="submit"][data-cn][data-en]'); - inputs.forEach(input => { - input.value = lang === 'en' ? input.getAttribute('data-en') : input.getAttribute('data-cn'); - }); + element.textContent = nextText; +} + +function setElementPlaceholderByLang(element, lang) { + const key = lang === 'en' ? 'data-en-placeholder' : 'data-cn-placeholder'; + const value = element.getAttribute(key); + if (value) { + element.setAttribute('placeholder', value); + } +} + +function setElementAriaLabelByLang(element, lang) { + const key = lang === 'en' ? 'data-en-aria-label' : 'data-cn-aria-label'; + const value = element.getAttribute(key); + if (value) { + element.setAttribute('aria-label', value); + } +} + +function setLang(lang) { + body.setAttribute('lang', lang); + + if (langToggle) { + const langText = langToggle.querySelector('.lang-text'); + if (langText) { + langText.textContent = lang === 'en' ? '\u4e2d' : 'EN'; + } + } + + const textNodes = document.querySelectorAll('[data-cn][data-en]'); + textNodes.forEach((element) => setElementTextByLang(element, lang)); + + const placeholderNodes = document.querySelectorAll('[data-cn-placeholder][data-en-placeholder]'); + placeholderNodes.forEach((element) => setElementPlaceholderByLang(element, lang)); + + const ariaNodes = document.querySelectorAll('[data-cn-aria-label][data-en-aria-label]'); + ariaNodes.forEach((element) => setElementAriaLabelByLang(element, lang)); localStorage.setItem('language', lang); } @@ -37,7 +70,7 @@ setLang(initialLang); if (langToggle) { langToggle.addEventListener('click', () => { const currentLang = body.getAttribute('lang'); - const newLang = currentLang === 'en' ? 'zh' : 'en'; - setLang(newLang); + const nextLang = currentLang === 'en' ? 'zh' : 'en'; + setLang(nextLang); }); } diff --git a/functions.php b/functions.php index 925876a..dc81d9d 100644 --- a/functions.php +++ b/functions.php @@ -131,13 +131,97 @@ function itstudio_custom_post_types() { ), 'public' => true, 'has_archive' => true, - 'supports' => array('title', 'editor', 'thumbnail', 'excerpt'), + 'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'), + 'taxonomies' => array('post_tag'), 'menu_icon' => 'dashicons-megaphone', 'show_in_rest' => true, )); + + register_post_type('news', array( + 'labels' => array( + 'name' => __('News', 'itstudio'), + 'singular_name' => __('News', 'itstudio'), + ), + 'public' => true, + 'has_archive' => 'news', + 'rewrite' => array( + 'slug' => 'news', + 'with_front' => false, + ), + 'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'), + 'taxonomies' => array('post_tag'), + 'menu_icon' => 'dashicons-media-document', + 'show_in_rest' => true, + )); + + register_taxonomy_for_object_type('post_tag', 'announcement'); + register_taxonomy_for_object_type('post_tag', 'news'); } add_action('init', 'itstudio_custom_post_types'); +function itstudio_register_acf_fields() { + if (!function_exists('acf_add_local_field_group')) { + return; + } + + acf_add_local_field_group(array( + 'key' => 'group_itstudio_content_priority', + 'title' => '内容权重', + 'fields' => array( + array( + 'key' => 'field_itstudio_weight', + 'label' => '权重', + 'name' => 'itstudio_weight', + 'type' => 'number', + 'instructions' => '数值越大,文章在侧栏排序越靠前。', + 'required' => 0, + 'default_value' => 0, + 'min' => 0, + 'step' => 1, + ), + ), + 'location' => array( + array( + array( + 'param' => 'post_type', + 'operator' => '==', + 'value' => 'post', + ), + ), + array( + array( + 'param' => 'post_type', + 'operator' => '==', + 'value' => 'announcement', + ), + ), + array( + array( + 'param' => 'post_type', + 'operator' => '==', + 'value' => 'news', + ), + ), + ), + 'position' => 'side', + 'style' => 'default', + 'active' => true, + 'show_in_rest' => 1, + )); +} +add_action('acf/init', 'itstudio_register_acf_fields'); + +function itstudio_archive_document_title($parts) { + if (is_post_type_archive('announcement')) { + $parts['title'] = html_entity_decode('公告通知', ENT_QUOTES, 'UTF-8'); + } elseif (is_post_type_archive('news')) { + $parts['title'] = html_entity_decode('社团新闻', ENT_QUOTES, 'UTF-8'); + } + + return $parts; +} +add_filter('document_title_parts', 'itstudio_archive_document_title', 20); + // Fallback: render /about even if the page isn't created in WP admin. function itstudio_about_fallback() { if (!is_404()) { @@ -189,6 +273,59 @@ function itstudio_about_fallback() { } add_action('template_redirect', 'itstudio_about_fallback'); +// Fallback: render /news via archive.php even if the page isn't created in WP admin. +function itstudio_news_fallback() { + if (!is_404()) { + return; + } + + global $wp; + $request = isset($wp->request) ? trim($wp->request, '/') : ''; + if ($request !== 'news') { + return; + } + + $template = locate_template('archive.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' => 'news', + '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; + }); + $GLOBALS['itstudio_archive_mode'] = 'news'; + status_header(200); + nocache_headers(); + include $template; + unset($GLOBALS['itstudio_archive_mode']); + exit; + } +} +add_action('template_redirect', 'itstudio_news_fallback'); + /** * GitHub 风格评论 */ @@ -263,3 +400,110 @@ function itstudio_comment_callback($comment, $args, $depth) { - 爱特工作室 + 爱特工作室 IT Studio @@ -79,20 +79,26 @@ if (!$announcement_nav_url) { $announcement_nav_url = home_url('/announcements'); } + $news_nav_url = get_post_type_archive_link('news'); + if (!$news_nav_url) { + $news_nav_url = home_url('/news'); + } $posts_page_id = (int) get_option('page_for_posts'); $blog_nav_url = $posts_page_id ? get_permalink($posts_page_id) : ''; if (!$blog_nav_url) { $blog_nav_url = home_url('/blog'); } + $blog_nav_url = 'https://blog.itstudio.club'; ?>