Skip to content

Conversation

@TechQuery
Copy link
Member

@TechQuery TechQuery commented Jan 8, 2026

PR-51 PR-51 PR-51 Powered by Pull Request Badge

  1. [add] model & card component of Open Source Project (closes 市集板块 #41)
  2. [fix] Git tag & commit relation of GitHub-reward

Summary by CodeRabbit

发布说明

  • 新增功能
    • 导航菜单调整:子菜单第一项标签更新并新增“Bazaar 项目”入口,便于浏览平台项目
    • 搜索增强:支持对“项目”模型的全面搜索(名称、来源、语言、标签等)
    • 展示优化:项目以卡片形式展示,含名称、源码链接、主页、语言、标签与描述
    • 新增奖项页面:提供奖项列表页面,支持服务端获取并展示奖项数据

✏️ Tip: You can customize this high-level summary in your review settings.

[fix] Git tag & commit relation of GitHub-reward
@coderabbitai
Copy link

coderabbitai bot commented Jan 8, 2026

📝 Walkthrough

Walkthrough

在导航中新增市集项目链接,添加 Project 与 Award 数据模型和配置项,新增 ProjectCard 组件,并在搜索页注册 project 卡片渲染,新增 awards 列表页面的服务端数据获取。总体为市集/奖项数据展示与搜索支撑模块改动。

Changes

Cohort / File(s) 变更摘要
导航
components/Navigator/MainNavigator.tsx
将开源项目子菜单首项标签从 t('open_source_projects') 改为 t('self_developed_projects'),新增 /search/project 路由项(添加 bazaar 项目入口)
配置
models/configuration.ts
新增导出常量 ProjectTableIdAwardTableId(来自环境变量 NEXT_PUBLIC_PROJECT_TABLE_ID / NEXT_PUBLIC_AWARD_TABLE_ID)
项目模型
models/Project.ts
新增 Project 类型、ProjectModel(继承 BiDataTable)与 SearchProjectModel(继承 BiSearch),包含字段抽取与 languages/tags 解析
奖项模型
models/Award.ts
新增 Award 类型、AwardModelSearchAwardModel,用于读取与搜索奖项数据
系统注册
models/System.ts
SystemModel.searchMap 中注册 projectaward 对应的搜索模型(导入 SearchProjectModelSearchAwardModel
UI 组件
components/Project/Card.tsx
新增 ProjectCard 组件,接收 Project props,并将字段映射给现有 GitCard 进行渲染
搜索页集成
pages/search/[model]/index.tsx
project 模型添加名称映射与使用 ProjectCard 的卡片渲染映射
奖项页面
pages/award/index.tsx
新增奖项页面,使用 getServerSideProps(含 cache()/errorLogger)通过 AwardModel().getAll() 拉取 awards 并传入页面 props

Sequence Diagram(s)

sequenceDiagram
  participant User as 浏览器用户
  participant SearchPage as 搜索页 (pages/search/[model])
  participant Server as Next.js Server
  participant SearchModel as SearchProjectModel
  participant Bitable as Lark/Bitable API
  participant UI as ProjectCard/GitCard

  User->>SearchPage: 访问 /search/project 或发起搜索
  SearchPage->>Server: 请求(SSR 或 API 调用)/ 发起搜索请求
  Server->>SearchModel: 调用 SearchProjectModel.search(...)
  SearchModel->>Bitable: 发送查询到 Lark/Bitable
  Bitable-->>SearchModel: 返回记录
  SearchModel-->>Server: 返回归一化的 Project 数据
  Server-->>SearchPage: 返回数据(props 或 JSON)
  SearchPage->>UI: 为每个 Project 渲染 ProjectCard
  UI-->>User: 显示项目卡片 (GitCard)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

feature

Poem

市集新窗映朝阳,🛍️
模型字段整齐行,
卡片一排连搜索,
后端拉取数据忙,
展位上线共欢畅!

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning PR部分满足#41需求(创建市集板块),但实现不完整:缺少Award卡片组件、导航菜单未正确配置、页面布局空白。 补全Award卡片组件、修复MainNavigator中的'self_developed_projects'标签、完善award页面UI布局、确保市集板块主题一致。
Out of Scope Changes check ⚠️ Warning 引入了Award相关变更(Award.ts、award页面、System.ts配置),超出了PR标题声称的"Open Source Project"范围。 明确Award变更是否属于本PR或应独立为单独PR;若保留,更新PR标题以包含Award模型;若移除,恢复System.ts和configuration.ts原状。
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR标题准确概括了主要变更:添加开源项目的模型和卡片组件,与代码改动一致。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot
Copy link

dosubot bot commented Jan 8, 2026

Related Documentation

Checked 9 published document(s) in 0 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In @components/Project/Card.tsx:
- Around line 6-14: ProjectCard currently force-casts all props (name,
sourceLink, link, languages, tags, summary) to string/string[] which bypasses
type checks for TableCellValue and can cause runtime errors; update ProjectCard
to perform safe type guards/parsers for each prop (e.g., check typeof or
Array.isArray and coerce/format values only when valid, handle missing/invalid
cases with fallbacks) or call a safe conversion helper from models/Project.ts
that returns the expected string/string[] types, and wrap the component export
with MobX observer() (same pattern used by ActivityCard and OrganizationCard) so
the card reacts to observable changes.

In @models/configuration.ts:
- Around line 38-39: Add documentation and example env file for the
NEXT_PUBLIC_* vars referenced by ActivityTableId and ProjectTableId: create a
.env.example at project root that lists NEXT_PUBLIC_PROJECT_TABLE_ID,
NEXT_PUBLIC_ACTIVITY_TABLE_ID (and any other NEXT_PUBLIC_* keys) with brief
descriptions (e.g., Lark Bitable table IDs) and placeholder values; update
README.md or CONTRIBUTING.md with a short section explaining how to populate
these vars and where to obtain the table IDs; and ensure CI/CD / Vercel
deployment instructions include steps to add these environment variables to the
deployment settings.

In @models/Project.ts:
- Around line 38-50: In extractFields, guard against calling split on undefined
and ensure safe access to link properties: for languages and tags replace
languages?.toString().split(...) and tags?.toString().split(...) with a
nullish-safe expression like (languages ??
'').toString().split(/\s*,\s*/).filter(Boolean) and (tags ??
'').toString().split(/\s*,\s*/).filter(Boolean); and ensure sourceLink and link
use optional chaining on the casted TableCellLink (e.g. (sourceLink as
TableCellLink)?.link and (link as TableCellLink)?.link) so accessing .link
cannot throw if the value is not a TableCellLink.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e63932a and 83c2689.

⛔ Files ignored due to path filters (5)
  • .env is excluded by none and included by none
  • .github/scripts/share-reward.ts is excluded by none and included by none
  • translation/en-US.ts is excluded by none and included by none
  • translation/zh-CN.ts is excluded by none and included by none
  • translation/zh-TW.ts is excluded by none and included by none
📒 Files selected for processing (6)
  • components/Navigator/MainNavigator.tsx
  • components/Project/Card.tsx
  • models/Project.ts
  • models/System.ts
  • models/configuration.ts
  • pages/search/[model]/index.tsx
🧰 Additional context used
📓 Path-based instructions (6)
models/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

models/**/*.ts: Import './Base' in model files to ensure proper GitHub client configuration
Use ContentModel with the configured client from mobx-github for content access
Use treeFrom utility from web-utility for hierarchical data structures

Files:

  • models/Project.ts
  • models/configuration.ts
  • models/System.ts
{models,pages/api}/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Import and use the configured githubClient from models/Base.ts; do not create new GitHub API instances

Files:

  • models/Project.ts
  • models/configuration.ts
  • models/System.ts
{models,pages/api}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Decode Base64 GitHub content using atob(item.content) when processing responses

Files:

  • models/Project.ts
  • models/configuration.ts
  • models/System.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use optional chaining and modern ECMAScript features
Let TypeScript infer types when possible to avoid verbose annotations
Import from established sources (e.g., ContentModel from mobx-github, utilities from web-utility) rather than reimplementing
Use minimal exports and avoid unnecessary custom implementations

Files:

  • models/Project.ts
  • pages/search/[model]/index.tsx
  • components/Project/Card.tsx
  • models/configuration.ts
  • models/System.ts
  • components/Navigator/MainNavigator.tsx
{pages,components}/**/*.tsx

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

{pages,components}/**/*.tsx: ALWAYS use React Bootstrap components instead of custom HTML elements in UI code
Use semantic HTML structure (article, header, section); use

    for countable items,
      for navigation; apply list-unstyled on first-level lists
      All user-facing text MUST use the i18n t() function (no hardcoded strings)
      Use React Bootstrap 2.10 components consistently for responsive design

Files:

  • pages/search/[model]/index.tsx
  • components/Project/Card.tsx
  • components/Navigator/MainNavigator.tsx
pages/**/*.tsx

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For static generation, allow errors to bubble naturally (do not swallow errors)

Files:

  • pages/search/[model]/index.tsx
🧠 Learnings (3)
📚 Learning: 2025-09-11T00:30:03.492Z
Learnt from: CR
Repo: Open-Source-Bazaar/Open-Source-Bazaar.github.io PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-11T00:30:03.492Z
Learning: Applies to models/**/*.ts : Import './Base' in model files to ensure proper GitHub client configuration

Applied to files:

  • models/Project.ts
  • pages/search/[model]/index.tsx
  • models/System.ts
📚 Learning: 2025-09-11T00:30:03.492Z
Learnt from: CR
Repo: Open-Source-Bazaar/Open-Source-Bazaar.github.io PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-11T00:30:03.492Z
Learning: Applies to models/**/*.ts : Use ContentModel with the configured client from mobx-github for content access

Applied to files:

  • models/Project.ts
📚 Learning: 2025-09-11T00:30:03.492Z
Learnt from: CR
Repo: Open-Source-Bazaar/Open-Source-Bazaar.github.io PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-09-11T00:30:03.492Z
Learning: Applies to {pages,components}/**/*.tsx : All user-facing text MUST use the i18n t() function (no hardcoded strings)

Applied to files:

  • pages/search/[model]/index.tsx
🧬 Code graph analysis (3)
models/Project.ts (2)
models/Base.ts (2)
  • LarkBase (54-57)
  • larkClient (59-62)
models/configuration.ts (1)
  • LarkBitableId (37-39)
components/Project/Card.tsx (2)
models/Project.ts (1)
  • Project (13-27)
components/Git/Card.tsx (1)
  • GitCard (16-70)
models/System.ts (1)
models/Project.ts (1)
  • SearchProjectModel (53-66)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build-and-Deploy
🔇 Additional comments (10)
pages/search/[model]/index.tsx (3)

13-13: 导入结构规范。

ProjectCard 导入遵循了已有的命名和路径约定,与 ActivityCard 和 OrganizationCard 保持一致。


44-44: 国际化处理正确。

正确使用 t('open_source_projects') 实现国际化,符合代码规范要求。


50-50: 组件映射合理。

将 ProjectCard 注册到 SearchCardMap,结构清晰且类型安全。

models/System.ts (2)

26-26: 搜索映射扩展合理。

将 project 注册到 searchMap,与现有 activity 和 NGO 条目保持一致,类型安全。


9-9: 模型文件已正确导入 './Base'。

models/Project.ts 已导入 ./Base,GitHub 客户端配置符合编码规范要求。

components/Navigator/MainNavigator.tsx (1)

41-42: 导航菜单更新规范。

两处修改均正确使用 i18n t() 函数,区分"自研项目"和"市集项目",语义清晰,符合国际化要求。

models/Project.ts (4)

1-11: 导入结构正确。

正确地从 ./Base 导入了配置好的 larkClient,符合代码规范。此文件用于 Lark/Bitable 集成,而非 GitHub API,因此 GitHub 相关的指导原则在此不适用。


13-27: 类型定义清晰准确。

Project 类型正确扩展了 LarkBase,并定义了项目所需的所有字段。使用 TableCellValue 作为统一类型符合 mobx-lark 的设计。


32-36: 配置设置合理。

queryOptions 和构造函数默认参数的设置符合项目需求,使用了配置文件中的常量值。


53-66: 搜索模型配置完整。

searchKeys 数组涵盖了所有相关的可搜索文本字段,合理地排除了 logo 字段。搜索功能设计合理。

Comment on lines +6 to +14
export const ProjectCard: FC<Project> = ({ name, sourceLink, link, languages, tags, summary }) => (
<GitCard
full_name={name as string}
html_url={sourceLink as string}
homepage={link as string}
languages={languages as string[]}
topics={tags as string[]}
description={summary as string}
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

类型断言存在安全隐患,且缺少 MobX observer 包装。

此组件存在两个问题:

  1. 类型安全问题(关键):所有属性都使用 as stringas string[] 强制类型转换。根据 models/Project.ts 的定义,这些字段的类型是 TableCellValue,它可能是多种类型(number、boolean、array 等)。强制转换会绕过 TypeScript 的类型检查,可能导致运行时错误。

  2. 缺少 MobX observer:参考 ActivityCardOrganizationCard,卡片组件应该用 observer() 包装以响应数据变化。如果 Project 数据是可观察的(observable),当前实现将无法正确更新 UI。

🔧 建议的修复方案

方案 1(推荐):类型守卫 + observer 包装

-import { FC } from 'react';
+import { observer } from 'mobx-react';
+import { FC } from 'react';

 import { Project } from '../../models/Project';
 import { GitCard } from '../Git/Card';

-export const ProjectCard: FC<Project> = ({ name, sourceLink, link, languages, tags, summary }) => (
-  <GitCard
-    full_name={name as string}
-    html_url={sourceLink as string}
-    homepage={link as string}
-    languages={languages as string[]}
-    topics={tags as string[]}
-    description={summary as string}
-  />
-);
+export const ProjectCard: FC<Project> = observer(
+  ({ name, sourceLink, link, languages, tags, summary }) => {
+    const safeString = (value: unknown) => (typeof value === 'string' ? value : '');
+    const safeArray = (value: unknown) => (Array.isArray(value) ? value : []);
+
+    return (
+      <GitCard
+        full_name={safeString(name)}
+        html_url={safeString(sourceLink)}
+        homepage={safeString(link)}
+        languages={safeArray(languages) as string[]}
+        topics={safeArray(tags) as string[]}
+        description={safeString(summary)}
+      />
+    );
+  },
+);

方案 2:在 Project 模型层添加类型转换

如果 TableCellValue 总是返回正确类型,可在 models/Project.ts 中添加类型断言辅助函数,然后在组件中使用这些安全的转换。

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In @components/Project/Card.tsx around lines 6 - 14, ProjectCard currently
force-casts all props (name, sourceLink, link, languages, tags, summary) to
string/string[] which bypasses type checks for TableCellValue and can cause
runtime errors; update ProjectCard to perform safe type guards/parsers for each
prop (e.g., check typeof or Array.isArray and coerce/format values only when
valid, handle missing/invalid cases with fallbacks) or call a safe conversion
helper from models/Project.ts that returns the expected string/string[] types,
and wrap the component export with MobX observer() (same pattern used by
ActivityCard and OrganizationCard) so the card reacts to observable changes.

Comment on lines 38 to 39
ActivityTableId = process.env.NEXT_PUBLIC_ACTIVITY_TABLE_ID!,
ProjectTableId = process.env.NEXT_PUBLIC_PROJECT_TABLE_ID!;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n models/configuration.ts | head -50

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 1725


🏁 Script executed:

# Check for imports in configuration.ts to verify GitHub client handling
rg "import" models/configuration.ts -A 2

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 195


🏁 Script executed:

# Search for environment variable configuration documentation
fd -t f "{\.env,.env.example,\.env.local,README}" --exec cat {} \; 2>/dev/null | head -100

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

# Check if NEXT_PUBLIC_PROJECT_TABLE_ID is documented anywhere
rg "NEXT_PUBLIC_PROJECT_TABLE_ID|PROJECT_TABLE_ID" --type ts --type tsx --type md

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 118


🏁 Script executed:

# Check if models/Base.ts exists
ls -la models/Base.ts 2>/dev/null || echo "Base.ts not found"

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 154


🏁 Script executed:

# Search for where configuration.ts is imported
rg "from.*configuration|import.*configuration" --type ts --type tsx -B 1 -A 1

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 118


🏁 Script executed:

# Look for environment variable documentation in common config files
rg "NEXT_PUBLIC_PROJECT_TABLE_ID|PROJECT_TABLE_ID" -B 2 -A 2

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 359


🏁 Script executed:

# Check deployment/build configuration files
fd -t f "vercel|github|docker|build|deploy" --exec cat {} \; 2>/dev/null | head -50

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

# Search for .env examples or documentation
fd -type f -name "*env*" -o -name "*.example" 2>/dev/null

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

cat -n models/Base.ts

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 2812


🏁 Script executed:

# Check which model files import Base.ts
rg "from.*['\"]./Base['\"]|import.*Base.*from" models/ --type ts

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 699


🏁 Script executed:

# Check how configuration.ts is used in models directory
rg "configuration" models/ --type ts -B 1 -A 1

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 654


🏁 Script executed:

# Check if there's a .env.example or similar documentation
find . -name "*.example" -o -name ".env*" -o -name "README*" | head -20

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

# Check deployment/build configuration files for env variable documentation
fd -type f "vercel|next.config" | xargs cat 2>/dev/null | head -100

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 261


🏁 Script executed:

# Check if Lark table IDs are used in documentation
rg "ACTIVITY_TABLE_ID|PROJECT_TABLE_ID|LARK_BITABLE" . --type md -B 1 -A 1

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

# Search for any README or documentation files
find . -maxdepth 3 -type f \( -name "README*" -o -name "*.md" \) | head -20

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

# Check for next.config.js or vercel.json
find . -maxdepth 2 -type f \( -name "next.config*" -o -name "vercel.json" -o -name ".env.example" \)

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

# Look for any documentation mentioning environment variables
rg "NEXT_PUBLIC|环境变量|environment variable" . --type md -l 2>/dev/null || echo "No markdown files found with env var documentation"

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 141


🏁 Script executed:

# Check how other projects in this repo handle environment variables
rg -l "NEXT_PUBLIC" . --type ts | head -5 | xargs -I {} grep -l "NEXT_PUBLIC" {}

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 116


🏁 Script executed:

# Look at package.json or CI/CD configuration
find . -maxdepth 2 \( -name "package.json" -o -name ".github" -o -name "Dockerfile" \)

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


补充完善环境变量文档配置。

代码模式本身一致,ProjectTableId 的导出遵循了既有约定。然而,缺少关键的部署配置文档:NEXT_PUBLIC_PROJECT_TABLE_ID(同时包括 NEXT_PUBLIC_ACTIVITY_TABLE_ID 等)未在 .env.example 或部署说明中记录,这会影响部署过程。建议:

  1. 在项目根目录创建 .env.example 文件,列出所有 NEXT_PUBLIC_* 环境变量及其说明(特别是 Lark Bitable 表 ID)
  2. 在 README.md 或贡献指南中补充环境变量配置说明
  3. 确保部署流程(Vercel、CI/CD)正确配置这些变量
🤖 Prompt for AI Agents
In @models/configuration.ts around lines 38 - 39, Add documentation and example
env file for the NEXT_PUBLIC_* vars referenced by ActivityTableId and
ProjectTableId: create a .env.example at project root that lists
NEXT_PUBLIC_PROJECT_TABLE_ID, NEXT_PUBLIC_ACTIVITY_TABLE_ID (and any other
NEXT_PUBLIC_* keys) with brief descriptions (e.g., Lark Bitable table IDs) and
placeholder values; update README.md or CONTRIBUTING.md with a short section
explaining how to populate these vars and where to obtain the table IDs; and
ensure CI/CD / Vercel deployment instructions include steps to add these
environment variables to the deployment settings.

Comment on lines +38 to +50
extractFields({
fields: { sourceLink, link, languages, tags, ...fields },
...meta
}: TableRecord<Project>) {
return {
...meta,
...fields,
sourceLink: (sourceLink as TableCellLink)?.link,
link: (link as TableCellLink)?.link,
languages: languages?.toString().split(/\s*,\s*/) || [],
tags: tags?.toString().split(/\s*,\s*/) || [],
};
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

修复字段提取逻辑中的运行时错误风险。

关键问题(第 47-48 行):
languagestagsundefined 时,languages?.toString().split(...) 会抛出 TypeError。可选链只保护了 toString() 调用,但 split() 仍然会在 undefined 上调用导致错误。

次要问题(第 45-46 行):
类型断言后访问 .link 属性缺少可选链,如果 sourceLinklink 不是 TableCellLink 类型,可能返回 undefined

🔧 建议的修复方案
 extractFields({
   fields: { sourceLink, link, languages, tags, ...fields },
   ...meta
 }: TableRecord<Project>) {
   return {
     ...meta,
     ...fields,
-    sourceLink: (sourceLink as TableCellLink)?.link,
-    link: (link as TableCellLink)?.link,
-    languages: languages?.toString().split(/\s*,\s*/) || [],
-    tags: tags?.toString().split(/\s*,\s*/) || [],
+    sourceLink: (sourceLink as TableCellLink | undefined)?.link,
+    link: (link as TableCellLink | undefined)?.link,
+    languages: (languages?.toString() ?? '').split(/\s*,\s*/).filter(Boolean),
+    tags: (tags?.toString() ?? '').split(/\s*,\s*/).filter(Boolean),
   };
 }

或使用更简洁的写法:

-    languages: languages?.toString().split(/\s*,\s*/) || [],
-    tags: tags?.toString().split(/\s*,\s*/) || [],
+    languages: languages ? String(languages).split(/\s*,\s*/) : [],
+    tags: tags ? String(tags).split(/\s*,\s*/) : [],
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
extractFields({
fields: { sourceLink, link, languages, tags, ...fields },
...meta
}: TableRecord<Project>) {
return {
...meta,
...fields,
sourceLink: (sourceLink as TableCellLink)?.link,
link: (link as TableCellLink)?.link,
languages: languages?.toString().split(/\s*,\s*/) || [],
tags: tags?.toString().split(/\s*,\s*/) || [],
};
}
extractFields({
fields: { sourceLink, link, languages, tags, ...fields },
...meta
}: TableRecord<Project>) {
return {
...meta,
...fields,
sourceLink: (sourceLink as TableCellLink | undefined)?.link,
link: (link as TableCellLink | undefined)?.link,
languages: (languages?.toString() ?? '').split(/\s*,\s*/).filter(Boolean),
tags: (tags?.toString() ?? '').split(/\s*,\s*/).filter(Boolean),
};
}
🤖 Prompt for AI Agents
In @models/Project.ts around lines 38 - 50, In extractFields, guard against
calling split on undefined and ensure safe access to link properties: for
languages and tags replace languages?.toString().split(...) and
tags?.toString().split(...) with a nullish-safe expression like (languages ??
'').toString().split(/\s*,\s*/).filter(Boolean) and (tags ??
'').toString().split(/\s*,\s*/).filter(Boolean); and ensure sourceLink and link
use optional chaining on the casted TableCellLink (e.g. (sourceLink as
TableCellLink)?.link and (link as TableCellLink)?.link) so accessing .link
cannot throw if the value is not a TableCellLink.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @models/configuration.ts:
- Around line 38-40: Add a .env.example documenting the required env vars
referenced in models/configuration.ts: list NEXT_PUBLIC_ACTIVITY_TABLE_ID,
NEXT_PUBLIC_PROJECT_TABLE_ID, NEXT_PUBLIC_AWARD_TABLE_ID with short descriptions
and example values so new devs know they are required for ActivityTableId,
ProjectTableId, and AwardTableId; optionally mention runtime requirement in
README and remove or guard non-null assertions in
ActivityTableId/ProjectTableId/AwardTableId if you prefer runtime-safe errors.
🧹 Nitpick comments (2)
pages/award/index.tsx (1)

12-14: 页面组件待实现 UI 内容。

当前组件返回空片段,显然是占位实现。后续添加 UI 时请注意:

  1. 必须使用 React Bootstrap 组件(而非原生 HTML 元素),遵循编码规范
  2. 所有用户可见文本必须使用 t() 函数进行国际化处理
  3. 使用语义化 HTML 结构(如 <article><section> 等)

需要我协助生成初始的 Award 列表页面 UI 代码吗?

models/Award.ts (1)

27-29: 搜索字段选择合理,建议补充注释说明。

searchKeys 包含了主要文本字段(奖项名称、提名人信息、理由等),未包含 videoUrlcreatedAtvotes 是合理的(这些字段不适合文本搜索)。

💡 可选:添加注释说明字段选择逻辑
 export class SearchAwardModel extends BiSearch<Award>(AwardModel) {
+  // 仅搜索文本类字段,排除 URL、日期和数值字段
   searchKeys = ['awardName', 'nomineeName', 'nomineeDesc', 'reason', 'nominator'];
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83c2689 and fe734f2.

⛔ Files ignored due to path filters (1)
  • .env is excluded by none and included by none
📒 Files selected for processing (4)
  • models/Award.ts
  • models/System.ts
  • models/configuration.ts
  • pages/award/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • models/System.ts
🧰 Additional context used
📓 Path-based instructions (6)
models/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

models/**/*.ts: Import './Base' in model files to ensure proper GitHub client configuration
Use ContentModel with the configured client from mobx-github for content access
Use treeFrom utility from web-utility for hierarchical data structures

Files:

  • models/configuration.ts
  • models/Award.ts
{models,pages/api}/**/*.ts

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Import and use the configured githubClient from models/Base.ts; do not create new GitHub API instances

Files:

  • models/configuration.ts
  • models/Award.ts
{models,pages/api}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Decode Base64 GitHub content using atob(item.content) when processing responses

Files:

  • models/configuration.ts
  • models/Award.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use optional chaining and modern ECMAScript features
Let TypeScript infer types when possible to avoid verbose annotations
Import from established sources (e.g., ContentModel from mobx-github, utilities from web-utility) rather than reimplementing
Use minimal exports and avoid unnecessary custom implementations

Files:

  • models/configuration.ts
  • pages/award/index.tsx
  • models/Award.ts
{pages,components}/**/*.tsx

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

{pages,components}/**/*.tsx: ALWAYS use React Bootstrap components instead of custom HTML elements in UI code
Use semantic HTML structure (article, header, section); use

    for countable items,
      for navigation; apply list-unstyled on first-level lists
      All user-facing text MUST use the i18n t() function (no hardcoded strings)
      Use React Bootstrap 2.10 components consistently for responsive design

Files:

  • pages/award/index.tsx
pages/**/*.tsx

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

For static generation, allow errors to bubble naturally (do not swallow errors)

Files:

  • pages/award/index.tsx
🧬 Code graph analysis (1)
pages/award/index.tsx (1)
models/Award.ts (2)
  • AwardModel (17-25)
  • Award (6-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build-and-Deploy
🔇 Additional comments (4)
pages/award/index.tsx (1)

6-10: 服务端数据获取模式正确。

使用 compose(cache(), errorLogger, ...) 的中间件组合模式符合 Pages Router 最佳实践,cache 和错误日志处理配置得当。

models/Award.ts (3)

3-4: 正确使用配置化的 Lark 客户端。

./Base 导入 larkClient 符合编码规范要求,确保了统一的 API 客户端配置和认证管理。


6-15: Award 类型定义清晰。

使用模板字面量类型 `nominee${'Name' | 'Desc'}` 生成 nomineeNamenomineeDesc 字段,简洁且类型安全。所有字段统一映射到 TableCellValue 符合 Lark 数据表结构。


17-25: AwardModel 实现规范。

类扩展 BiDataTable<Award> 并正确配置:

  • 使用统一的 larkClient
  • 设置 queryOptions 为非数组模式
  • 构造函数提供合理的默认参数

符合项目 Lark 数据表模型的标准模式。

Comment on lines +38 to +40
ActivityTableId = process.env.NEXT_PUBLIC_ACTIVITY_TABLE_ID!,
ProjectTableId = process.env.NEXT_PUBLIC_PROJECT_TABLE_ID!,
AwardTableId = process.env.NEXT_PUBLIC_AWARD_TABLE_ID!;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Step 1: Check if .env.example exists and its contents
echo "=== Looking for environment configuration files ==="
fd -t f '\.(env|example)' | head -20

echo ""
echo "=== Checking .env.example for the mentioned variables ==="
if [ -f ".env.example" ]; then
  grep -n "ACTIVITY_TABLE_ID\|PROJECT_TABLE_ID\|AWARD_TABLE_ID" .env.example || echo "Variables not found in .env.example"
else
  echo ".env.example not found"
fi

echo ""
echo "=== Checking README files ==="
fd -t f 'README' -i | head -10

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 255


🏁 Script executed:

#!/bin/bash
# Step 2: Read models/configuration.ts to understand the context
echo "=== Reading models/configuration.ts ==="
wc -l models/configuration.ts

echo ""
echo "=== Content around lines 38-40 ==="
sed -n '30,50p' models/configuration.ts

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 667


🏁 Script executed:

#!/bin/bash
# Step 3: Search for usage of these table IDs in the codebase
echo "=== Searching for usage of AwardTableId ==="
rg "AwardTableId" -A 2 -B 2 | head -30

echo ""
echo "=== Searching for usage of ProjectTableId ==="
rg "ProjectTableId" -A 2 -B 2 | head -30

echo ""
echo "=== Searching for usage of ActivityTableId ==="
rg "ActivityTableId" -A 2 -B 2 | head -30

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 2683


🏁 Script executed:

#!/bin/bash
# Step 4: Check Award.ts and Project.ts for context
echo "=== Checking Award.ts ==="
fd -name "Award.ts" | head -5

echo ""
echo "=== Checking Project.ts ==="
fd -name "Project.ts" | head -5

# Read Award.ts if it exists
if [ -f "models/Award.ts" ]; then
  echo "=== First 50 lines of models/Award.ts ==="
  head -50 models/Award.ts
fi

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 1424


需要在项目中补充环境变量文档。

ActivityTableIdProjectTableIdAwardTableId 这三个常量使用了非空断言 !,意味着对应的环境变量(NEXT_PUBLIC_ACTIVITY_TABLE_IDNEXT_PUBLIC_PROJECT_TABLE_IDNEXT_PUBLIC_AWARD_TABLE_ID)是运行时必需的。目前项目中不存在 .env.example 文件,这些环境变量的配置要求无法被记录,新开发者将无法知道需要设置哪些变量,容易导致运行时错误。

建议创建或更新 .env.example 文件,列出所有必需的环境变量及其说明,确保项目配置的透明度和可维护性。

🤖 Prompt for AI Agents
In @models/configuration.ts around lines 38 - 40, Add a .env.example documenting
the required env vars referenced in models/configuration.ts: list
NEXT_PUBLIC_ACTIVITY_TABLE_ID, NEXT_PUBLIC_PROJECT_TABLE_ID,
NEXT_PUBLIC_AWARD_TABLE_ID with short descriptions and example values so new
devs know they are required for ActivityTableId, ProjectTableId, and
AwardTableId; optionally mention runtime requirement in README and remove or
guard non-null assertions in ActivityTableId/ProjectTableId/AwardTableId if you
prefer runtime-safe errors.

@TechQuery TechQuery added the feature New feature or request label Jan 8, 2026
@TechQuery TechQuery merged commit 07fe075 into main Jan 9, 2026
5 checks passed
@TechQuery TechQuery deleted the TechQuery/issue41 branch January 9, 2026 02:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

市集板块

2 participants