Skip to content

feat: 添加项目功能 - #548

Draft
wuziyue840 wants to merge 2 commits into
CuteLeaf:masterfrom
wuziyue840:master
Draft

feat: 添加项目功能#548
wuziyue840 wants to merge 2 commits into
CuteLeaf:masterfrom
wuziyue840:master

Conversation

@wuziyue840

@wuziyue840 wuziyue840 commented Aug 8, 2026

Copy link
Copy Markdown

Type of change

  • Bug fix (a non-breaking change that fixes an issue)
  • New feature (a non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Other (please describe):

Checklist

  • I have read the CONTRIBUTING document.
  • I have checked to ensure that this Pull Request is not for personal changes.
  • I have performed a self-review of my own code.
  • My changes generate no new warnings.

Related Issue

Changes

  • 添加了项目功能
  • 更新了相关配置文件

How To Test

  1. 拉取本分支代码
  2. 运行项目查看功能是否正常

Screenshots (if applicable)

Additional Notes

Summary by Sourcery

添加一个可配置的项目页面,包含列表视图和详情视图,并集成导航,同时为所有支持的语言提供国际化文案。

新功能:

  • 引入项目列表页面,包含分类标签、搜索功能和项目卡片。
  • 添加项目详情页面,用于展示元数据、技术栈、特性、富文本内容和截图。
  • 提供集中式的项目配置,并为分类和项目条目提供类型定义。
  • 在站点配置中暴露项目页面开关,并在导航栏中添加项目入口。

改进:

  • 扩展 i18n key 和翻译,使其覆盖所有受支持语言中的项目相关 UI 文本。
Original summary in English

Summary by Sourcery

Add a configurable projects page with listing and detail views, including navigation integration and internationalized text for all supported languages.

New Features:

  • Introduce a projects listing page with category tabs, search, and project cards.
  • Add a project detail page that shows metadata, tech stack, features, rich content, and screenshots.
  • Provide a centralized projects configuration with typed definitions for categories and project items.
  • Expose a projects page toggle in the site configuration and add a projects entry to the navigation bar.

Enhancements:

  • Extend i18n keys and translations to cover projects-related UI strings across all supported locales.

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

@wuziyue840 is attempting to deploy a commit to the xiaye's projects Team on Vercel.

A member of the Team first needs to authorize it.

@netlify

netlify Bot commented Aug 8, 2026

Copy link
Copy Markdown

Deploy Preview for demo-firefly ready!

Name Link
🔨 Latest commit bdec8d6
🔍 Latest deploy log https://app.netlify.com/projects/demo-firefly/deploys/6a771091aa29e200085904f1
😎 Deploy Preview https://deploy-preview-548--demo-firefly.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@sourcery-ai

sourcery-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Reviewer's Guide

添加一个可配置的项目页面和项目详情页面,具备完整的 i18n 支持并集成到导航中。

浏览新的项目列表和详情页面的序列图

sequenceDiagram
  actor User
  participant NavBar
  participant Browser
  participant ProjectsPage
  participant ProjectsDetailPage

  User->>NavBar: click LinkPresets.Projects
  NavBar->>Browser: navigate /projects/
  Browser->>ProjectsPage: load projects.astro
  ProjectsPage->>ProjectsPage: check siteConfig.pages.projects
  alt [projects page disabled]
    ProjectsPage-->>Browser: Astro.redirect("/404/")
  else [projects page enabled]
    ProjectsPage->>ProjectsPage: group projectsConfig.projects by category
    ProjectsPage->>ProjectsPage: build tabs from projectsConfig.categories
    ProjectsPage-->>Browser: render ProjectsGrid
    User->>Browser: click ProjectCard
    alt [item.link && item.external]
      Browser-->>Browser: open item.link in new tab
    else [item.link && !item.external]
      Browser-->>Browser: navigate to item.link
    else [no link but has content/features/screenshots]
      Browser->>ProjectsDetailPage: request /projects/{id}/
      ProjectsDetailPage->>ProjectsDetailPage: getStaticPaths()
      ProjectsDetailPage->>ProjectsDetailPage: find project by id
      alt [project not found or !siteConfig.pages.projects]
        ProjectsDetailPage-->>Browser: Astro.redirect("/404/")
      else [project found with detail]
        ProjectsDetailPage-->>Browser: render detail sections
      end
    else [no link and no detail]
      Browser-->>User: no navigation (card is not clickable)
    end
  end
Loading

File-Level Changes

Change Details Files
引入一个带类型且可配置的项目系统,并将其连接到全局配置导出中。
  • 定义 ProjectsConfig、ProjectItem 和 ProjectCategory 类型,用于建模项目数据和页面行为。
  • 添加带示例数据的 projectsConfig 配置,并从中央配置索引中导出。
  • 从类型索引中暴露新的与项目相关的类型,以便更广泛地使用。
src/types/projectsConfig.ts
src/config/projectsConfig.ts
src/config/index.ts
src/types/config.ts
添加项目列表页面和按项目的详情页面,其布局、路由和行为基于配置。
  • 创建一个项目列表页面,按类别对项目进行分组,支持可选的“All”标签,并在没有项目时显示空状态消息。
  • 创建一个动态项目详情页面,从配置中静态生成路由,检查功能可用性,并在合适的情况下重定向到列表页或 404。
  • 使用 MainGridLayout 和 siteConfig.pages.projects,将这些页面集成到现有布局和站点级功能开关中。
src/pages/projects.astro
src/pages/projects/[id].astro
src/config/siteConfig.ts
src/types/siteConfig.ts
为项目 UI 实现 Svelte 组件,包括卡片、网格、标签导航和分区。
  • 添加 ProjectCard 组件,用于渲染单个项目卡片,支持有条件的点击行为、标签处理和图片懒加载。
  • 添加 ProjectsGrid 组件,用于管理标签状态、搜索过滤、基于哈希的标签恢复,以及按标签分组项目。
  • 添加 TabNav 组件,用于渲染支持 i18n 的标签和搜索输入,将标签状态与 URL 哈希同步,并监听哈希变化。
  • 添加 ProjectSection 组件,用于按类别/分区渲染带标题的 ProjectCard 网格。
src/components/pages/projects/ProjectCard.svelte
src/components/pages/projects/ProjectsGrid.svelte
src/components/pages/projects/TabNav.svelte
src/components/pages/projects/ProjectSection.svelte
将项目功能集成到导航和页面开关中,使其可发现且可控制。
  • 添加一个 Projects 导航预设,包含标签、图标、URL 和 pageKey,并将其纳入动态导航栏链接中。
  • 扩展 SiteConfig 的 pages,加入一个 projects 布尔值并默认启用。
  • 确保列表页面和详情页面都会基于 siteConfig.pages.projects 进行守卫,在禁用时重定向到 404。
src/config/navBarConfig.ts
src/config/siteConfig.ts
src/types/siteConfig.ts
为项目功能在所有支持语言中提供完整的 i18n 支持。
  • 在全局 key 枚举中添加与项目相关的标签和分区的新 i18n key。
  • 为所有新 key 提供英文、日文、韩文、俄文、简体中文和繁体中文的本地化字符串。
  • 在项目页面和组件中使用这些 key,用于标题、副标题、空状态和分区标题。
src/i18n/i18nKey.ts
src/i18n/languages/en.ts
src/i18n/languages/ja.ts
src/i18n/languages/ko.ts
src/i18n/languages/ru.ts
src/i18n/languages/zh_CN.ts
src/i18n/languages/zh_TW.ts

Tips and commands

Interacting with Sourcery

  • 触发新的代码审查: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 从审查评论生成 GitHub issue: 通过回复某条审查评论让 Sourcery 从该评论创建一个 issue。你也可以在审查评论下回复 @sourcery-ai issue 来从该评论创建 issue。
  • 生成 pull request 标题: 在 pull request 标题的任意位置写入 @sourcery-ai,即可随时生成一个标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 描述正文的任意位置写入 @sourcery-ai summary,即可在该位置生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来在任何时候(重新)生成摘要。
  • 生成审查者指南: 在 pull request 中评论 @sourcery-ai guide,即可在任何时候(重新)生成审查者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,即可将所有 Sourcery 评论标记为已解决。如果你已经处理完所有评论且不想再看到它们,这会很有用。
  • 取消所有 Sourcery 审查: 在 pull request 中评论 @sourcery-ai dismiss,即可取消所有现有的 Sourcery 审查。如果你想以一次新的审查重新开始,这尤其有用——别忘了再评论 @sourcery-ai review 来触发新的审查!

Customizing Your Experience

访问你的 dashboard 以:

  • 启用或禁用审查功能,例如 Sourcery 生成的 pull request 摘要、审查者指南等。
  • 更改审查语言。
  • 添加、移除或编辑自定义审查指令。
  • 调整其他审查设置。

Getting Help

Original review guide in English

Reviewer's Guide

Adds a configurable projects page and project detail pages, with full i18n support and navigation integration.

Sequence diagram for navigating the new projects list and detail pages

sequenceDiagram
  actor User
  participant NavBar
  participant Browser
  participant ProjectsPage
  participant ProjectsDetailPage

  User->>NavBar: click LinkPresets.Projects
  NavBar->>Browser: navigate /projects/
  Browser->>ProjectsPage: load projects.astro
  ProjectsPage->>ProjectsPage: check siteConfig.pages.projects
  alt [projects page disabled]
    ProjectsPage-->>Browser: Astro.redirect("/404/")
  else [projects page enabled]
    ProjectsPage->>ProjectsPage: group projectsConfig.projects by category
    ProjectsPage->>ProjectsPage: build tabs from projectsConfig.categories
    ProjectsPage-->>Browser: render ProjectsGrid
    User->>Browser: click ProjectCard
    alt [item.link && item.external]
      Browser-->>Browser: open item.link in new tab
    else [item.link && !item.external]
      Browser-->>Browser: navigate to item.link
    else [no link but has content/features/screenshots]
      Browser->>ProjectsDetailPage: request /projects/{id}/
      ProjectsDetailPage->>ProjectsDetailPage: getStaticPaths()
      ProjectsDetailPage->>ProjectsDetailPage: find project by id
      alt [project not found or !siteConfig.pages.projects]
        ProjectsDetailPage-->>Browser: Astro.redirect("/404/")
      else [project found with detail]
        ProjectsDetailPage-->>Browser: render detail sections
      end
    else [no link and no detail]
      Browser-->>User: no navigation (card is not clickable)
    end
  end
Loading

File-Level Changes

Change Details Files
Introduce a typed, configurable projects system and wire it into global config exports.
  • Define ProjectsConfig, ProjectItem, and ProjectCategory types to model projects data and page behavior.
  • Add projectsConfig configuration with example data and export it from the central config index.
  • Expose new project-related types from the types index for wider use.
src/types/projectsConfig.ts
src/config/projectsConfig.ts
src/config/index.ts
src/types/config.ts
Add a projects page and per-project detail pages with layout, routing, and behavior based on configuration.
  • Create a projects listing page that groups projects by category, supports an optional 'All' tab, and shows empty-state messaging when no projects exist.
  • Create a dynamic project detail page that statically generates routes from config, checks feature availability, and redirects to list/404 when appropriate.
  • Use MainGridLayout and siteConfig.pages.projects to integrate these pages into the existing layout and site-level feature toggles.
src/pages/projects.astro
src/pages/projects/[id].astro
src/config/siteConfig.ts
src/types/siteConfig.ts
Implement Svelte components for the projects UI, including cards, grid, tab navigation, and sections.
  • Add ProjectCard component to render a single project card with conditional click behavior, tag handling, and lazy image loading.
  • Add ProjectsGrid component to manage tab state, search filtering, hash-based tab restoration, and grouping of projects per tab.
  • Add TabNav component to render i18n-aware tabs and search input, syncing tab state with the URL hash and listening to hash changes.
  • Add ProjectSection component to render a titled grid of ProjectCard items per category/section.
src/components/pages/projects/ProjectCard.svelte
src/components/pages/projects/ProjectsGrid.svelte
src/components/pages/projects/TabNav.svelte
src/components/pages/projects/ProjectSection.svelte
Integrate the projects feature into navigation and page toggles so it is discoverable and controllable.
  • Add a Projects nav preset with label, icon, URL, and pageKey, and include it in the dynamic navbar links.
  • Extend SiteConfig pages to include a projects boolean and enable it by default.
  • Ensure both list and detail pages guard on siteConfig.pages.projects and redirect to 404 when disabled.
src/config/navBarConfig.ts
src/config/siteConfig.ts
src/types/siteConfig.ts
Provide full i18n support for the projects feature across supported languages.
  • Add new i18n keys for projects-related labels and sections in the global key enum.
  • Supply localized strings for all new keys in English, Japanese, Korean, Russian, Simplified Chinese, and Traditional Chinese.
  • Use these keys throughout the projects pages and components for titles, subtitles, empty states, and section headings.
src/i18n/i18nKey.ts
src/i18n/languages/en.ts
src/i18n/languages/ja.ts
src/i18n/languages/ko.ts
src/i18n/languages/ru.ts
src/i18n/languages/zh_CN.ts
src/i18n/languages/zh_TW.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题,并给出了一些整体性的反馈:

  • ProjectCard.svelte 组件在可点击和不可点击两种分支间几乎重复了所有标记;可以考虑将共享的布局提取到一个单独的结构中,只在需要时用 <a> 包裹,从而降低维护成本。
  • 新增的 LinkPresets.Projects 条目和 projectsConfig.categories 名称使用了硬编码的中文字符串;如果导航和页面标题的其他部分都是通过 i18n 做本地化的,建议也通过翻译键来驱动这些字段,以保持语言行为的一致性。
  • TabNav.svelteProjectsGrid.svelte 中直接访问了 window;因为这些组件是通过 client:load 使用的,这样做是安全的,但你仍然可以考虑对 window 是否为 undefined 做保护,以避免未来如果更改 hydration 模式可能带来的问题。
给 AI Agent 的提示
Please address the comments from this code review:

## Overall Comments
- The `ProjectCard.svelte` component duplicates almost all markup between the clickable and non-clickable branches; consider extracting the shared layout into a single structure and only conditionally wrapping it with an `<a>` to reduce maintenance overhead.
- The new `LinkPresets.Projects` entry and `projectsConfig.categories` names are hardcoded Chinese strings; if the rest of the nav and page titles are localized via i18n, consider wiring these through the translation keys to keep language behavior consistent.
- In `TabNav.svelte` and `ProjectsGrid.svelte`, direct `window` access is assumed; since these components are used with `client:load`, it’s safe but you may still want to guard against `window` being undefined to avoid issues if the hydration mode changes in the future.

## Individual Comments

### Comment 1
<location path="src/components/pages/projects/ProjectSection.svelte" line_range="15" />
<code_context>
+const { sectionId, sectionTitle, items, isActive }: Props = $props();
+</script>
+
+<div id="projects-section-{sectionId}" class="{isActive ? 'block' : 'hidden'}">
+  {#if sectionTitle}
+    <h3 class="text-lg font-semibold text-neutral-900 dark:text-neutral-100 mb-4 flex items-center gap-2">
</code_context>
<issue_to_address>
**issue (bug_risk):** The section `id` attribute is treated as a literal string rather than interpolating `sectionId`.

In Svelte, `id="projects-section-{sectionId}"` is treated as a literal string, so `sectionId` is never interpolated. If you need unique IDs per section (for anchors, scrolling, etc.), use template syntax instead: `id={`projects-section-${sectionId}`}` so the ID actually includes the `sectionId` value.
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得我们的代码评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • The ProjectCard.svelte component duplicates almost all markup between the clickable and non-clickable branches; consider extracting the shared layout into a single structure and only conditionally wrapping it with an <a> to reduce maintenance overhead.
  • The new LinkPresets.Projects entry and projectsConfig.categories names are hardcoded Chinese strings; if the rest of the nav and page titles are localized via i18n, consider wiring these through the translation keys to keep language behavior consistent.
  • In TabNav.svelte and ProjectsGrid.svelte, direct window access is assumed; since these components are used with client:load, it’s safe but you may still want to guard against window being undefined to avoid issues if the hydration mode changes in the future.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `ProjectCard.svelte` component duplicates almost all markup between the clickable and non-clickable branches; consider extracting the shared layout into a single structure and only conditionally wrapping it with an `<a>` to reduce maintenance overhead.
- The new `LinkPresets.Projects` entry and `projectsConfig.categories` names are hardcoded Chinese strings; if the rest of the nav and page titles are localized via i18n, consider wiring these through the translation keys to keep language behavior consistent.
- In `TabNav.svelte` and `ProjectsGrid.svelte`, direct `window` access is assumed; since these components are used with `client:load`, it’s safe but you may still want to guard against `window` being undefined to avoid issues if the hydration mode changes in the future.

## Individual Comments

### Comment 1
<location path="src/components/pages/projects/ProjectSection.svelte" line_range="15" />
<code_context>
+const { sectionId, sectionTitle, items, isActive }: Props = $props();
+</script>
+
+<div id="projects-section-{sectionId}" class="{isActive ? 'block' : 'hidden'}">
+  {#if sectionTitle}
+    <h3 class="text-lg font-semibold text-neutral-900 dark:text-neutral-100 mb-4 flex items-center gap-2">
</code_context>
<issue_to_address>
**issue (bug_risk):** The section `id` attribute is treated as a literal string rather than interpolating `sectionId`.

In Svelte, `id="projects-section-{sectionId}"` is treated as a literal string, so `sectionId` is never interpolated. If you need unique IDs per section (for anchors, scrolling, etc.), use template syntax instead: `id={`projects-section-${sectionId}`}` so the ID actually includes the `sectionId` value.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

const { sectionId, sectionTitle, items, isActive }: Props = $props();
</script>

<div id="projects-section-{sectionId}" class="{isActive ? 'block' : 'hidden'}">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): 区块的 id 属性被当作字面字符串处理,而不是插入 sectionId

在 Svelte 中,id="projects-section-{sectionId}" 会被视为字面量字符串,因此 sectionId 根本不会被插入。如果你需要为每个区块生成唯一的 ID(用于锚点、滚动等),请使用模板语法:id={projects-section-${sectionId}},这样生成的 ID 才会真正包含 sectionId 的值。

Original comment in English

issue (bug_risk): The section id attribute is treated as a literal string rather than interpolating sectionId.

In Svelte, id="projects-section-{sectionId}" is treated as a literal string, so sectionId is never interpolated. If you need unique IDs per section (for anchors, scrolling, etc.), use template syntax instead: id={projects-section-${sectionId}} so the ID actually includes the sectionId value.

@CuteLeaf
CuteLeaf marked this pull request as draft August 9, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant