Skip to content

refactor: merge standardConstants and standard in team plan#6549

Merged
c121914yu merged 8 commits intolabring:mainfrom
FinleyGe:refactor/plan
Mar 15, 2026
Merged

refactor: merge standardConstants and standard in team plan#6549
c121914yu merged 8 commits intolabring:mainfrom
FinleyGe:refactor/plan

Conversation

@FinleyGe
Copy link
Collaborator

No description provided.

@github-actions
Copy link

github-actions bot commented Mar 12, 2026

Preview sandbox Image:

registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-pr:fatsgpt_sandbox_31255e61db8d27309148bed3a560f7ebd4c4d0ea

@github-actions
Copy link

github-actions bot commented Mar 12, 2026

Preview mcp_server Image:

registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-pr:fatsgpt_mcp_server_31255e61db8d27309148bed3a560f7ebd4c4d0ea

@github-actions
Copy link

github-actions bot commented Mar 12, 2026

Preview fastgpt Image:

registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt-pr:fatsgpt_31255e61db8d27309148bed3a560f7ebd4c4d0ea

@c121914yu c121914yu marked this pull request as ready for review March 12, 2026 12:37
Copilot AI review requested due to automatic review settings March 12, 2026 12:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors “team plan status” consumption across the app/service by replacing the standardConstants field with a unified standard plan object that represents effective limits (plan config defaults merged with DB overrides).

Changes:

  • Introduces TeamPlanStandardSchema / TeamPlanStandardType and updates TeamPlanStatusSchema to expose [standard] as the merged plan object (removing standardConstants).
  • Adds a buildStandardPlan helper to compute effective plan fields and updates service-level limit checks to use standard.* fields.
  • Updates multiple API routes and UI components that read plan limits (upload counts/sizes, quotas) to use teamPlanStatus.standard.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
projects/app/src/pages/api/core/dataset/presignDatasetFilePostUrl.ts Switches dataset upload presign limits to planStatus.standard.*.
projects/app/src/pages/api/core/dataset/data/insertImages.ts Switches image insert upload frequency limits to planStatus.standard.*.
projects/app/src/pages/api/core/dataset/collection/create/images.ts Switches collection image upload frequency limits to planStatus.standard.*.
projects/app/src/pages/api/core/chat/file/presignChatFilePostUrl.ts Switches chat file presign limits to planStatus.standard.*.
projects/app/src/pages/api/common/file/presignTempFilePostUrl.ts Switches temp file presign limits to planStatus.standard.*.
projects/app/src/pages/api/admin/support/appRegistration/create.ts Reads app registration quota from teamPlanStatus.standard.*.
projects/app/src/pages/account/info/index.tsx Updates plan/usage UI computations to reference teamPlanStatus.standard.*.
projects/app/src/pages/account/customDomain/index.tsx Updates custom domain quota display to teamPlanStatus.standard.*.
projects/app/src/pageComponents/dataset/detail/Import/components/FileSelector.tsx Updates dataset import file constraints to teamPlanStatus.standard.*.
projects/app/src/pageComponents/dashboard/TeamPlanStatusCard.tsx Updates rendering guard from standardConstants to standard.
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx Updates node file selection constraints to teamPlanStatus.standard.*.
projects/app/src/components/Select/FileSelectorBox.tsx Updates max size/count display/limits to teamPlanStatus.standard.*.
projects/app/src/components/core/chat/ChatContainer/ChatBox/hooks/useFileUpload.tsx Updates chat upload constraints to teamPlanStatus.standard.*.
projects/app/src/components/core/app/FileSelector/index.tsx Updates app file selector constraints to teamPlanStatus.standard.*.
projects/app/src/components/core/app/FileSelect.tsx Updates app chat file selection constraints to teamPlanStatus.standard.*.
packages/service/support/wallet/sub/utils.ts Adds merged-plan builder and changes plan status shape/derivations.
packages/service/support/permission/teamLimit.ts Updates quota enforcement to use standard.* from new plan shape.
packages/global/support/wallet/sub/type.ts Adds TeamPlanStandardSchema and updates plan status schema accordingly.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@c121914yu
Copy link
Collaborator

测试内容

  1. 用户套餐显示正常
  2. 定制版套餐显示正常
  3. admin 配置,可覆盖标准套餐
  4. 价格页正常,只显示配置内容。

@c121914yu
Copy link
Collaborator

PR Review: refactor: merge standardConstants and standard in team plan

📊 变更概览

✅ 优点

1. 代码质量提升

  • ✨ 消除了约 80 行重复的字段映射逻辑
  • ✨ 提取了 buildStandardPlan 函数,提高了代码复用性
  • ✨ 类型定义更加清晰,合并了分散的类型信息

2. 可维护性改进

  • 🎯 统一的数据结构减少了维护成本
  • 🎯 新增套餐字段时只需修改一处
  • 🎯 减少了 API 调用方的理解成本

3. 一致性增强

  • 🔄 所有代码使用统一的 standard 访问套餐信息
  • 🔄 消除了 standard vs standardConstants 的混淆

⚠️ 问题汇总

🟡 问题 1: 类型断言存在风险 (必须修复)

位置: packages/service/support/wallet/sub/utils.ts:164

问题: standard 可能为 undefined,直接使用类型断言和展开操作符不安全

// ❌ 当前代码
return {
  ...(standard as TeamPlanStandardType),  // 不安全
  name: standardConstants.name,
  // ...
};

建议修复:

// ✅ 安全的实现
const baseFields = standard ? {
  _id: standard._id,
  teamId: standard.teamId,
  type: standard.type,
  startTime: standard.startTime,
  expiredTime: standard.expiredTime,
  currentMode: standard.currentMode,
  nextMode: standard.nextMode,
  currentSubLevel: standard.currentSubLevel,
  nextSubLevel: standard.nextSubLevel,
  totalPoints: standard.totalPoints,
  annualBonusPoints: standard.annualBonusPoints,
  surplusPoints: standard.surplusPoints,
  currentExtraDatasetSize: standard.currentExtraDatasetSize
} : {} as any;

return {
  ...baseFields,
  name: standardConstants.name,
  // ... 其他字段
};

🟡 问题 2: 逻辑运算符使用不一致 (必须修复)

位置: packages/service/support/wallet/sub/utils.ts:180

问题: websiteSyncPerDataset 使用 || 而其他字段使用 ??,当值为 0 时会有问题

// ❌ 当前代码
websiteSyncPerDataset:
  standard?.websiteSyncPerDataset || standardConstants.websiteSyncPerDataset,

影响: 如果 standard.websiteSyncPerDataset0,会错误地使用 standardConstants 的值

建议修复:

// ✅ 统一使用 ??
websiteSyncPerDataset:
  standard?.websiteSyncPerDataset ?? standardConstants.websiteSyncPerDataset,

🟢 问题 3: 缺少单元测试 (建议添加)

建议: 为 buildStandardPlan 函数添加单元测试,覆盖以下场景:

  • standard 存在时,正确合并字段
  • standardundefined 时,使用默认值
  • ✅ 字段优先级正确 (DB 覆盖配置)
  • websiteSyncPerDataset0 时的边界情况

💬 总体评价

代码质量: ⭐⭐⭐⭐☆ (4/5)
安全性: ⭐⭐⭐⭐⭐ (5/5)
性能: ⭐⭐⭐⭐⭐ (5/5)
可维护性: ⭐⭐⭐⭐⭐ (5/5)

🚀 审查结论

建议通过,但需要修复 🟡 问题

这是一个高质量的重构 PR,核心思路正确,代码改进明显。建议修复以下问题后合并:

  1. 🟡 修复 buildStandardPlan 中的类型断言问题
  2. 🟡 统一使用 ?? 运算符,修复 websiteSyncPerDataset 的逻辑
  3. 🟢 为 buildStandardPlan 函数添加单元测试

审查人: Claude Code
审查时间: 2026-03-14

c121914yu
c121914yu previously approved these changes Mar 15, 2026
@c121914yu
Copy link
Collaborator

PR Review: refactor: merge standardConstants and standard in team plan

📊 变更概览

✅ 优点

  1. 优秀的重构设计: 通过引入 TeamPlanStandardSchema 合并了 standardstandardConstants 两个字段,简化了类型结构,消除了数据冗余
  2. 完善的测试覆盖: 新增了 242 行测试代码,覆盖了 buildStandardPlan 函数的所有场景,包括字段映射、回退逻辑、边界情况
  3. 系统性重构: 在整个代码库中一致性地更新了所有引用,包括前端组件、API 路由、权限检查等
  4. 代码复用: 提取了 buildStandardPlan 函数,消除了重复的字段合并逻辑
  5. 改进的文档: 为 Schema 添加了清晰的 JSDoc 注释,说明了各个类型的用途

⚠️ 问题汇总

🔴 严重问题 (1 个,必须修复)

  1. 类型安全问题: buildStandardPlan 函数的第二个参数类型定义不够严格

🟡 建议改进 (3 个)

  1. 字段命名不一致: maxAppmaxAppAmountmaxDatasetmaxDatasetAmount 的映射增加了理解成本
  2. 可选链使用: 部分代码可以使用可选链简化
  3. 测试文件位置: 测试文件应该放在 packages/service/ 对应的测试目录

🟢 可选优化 (2 个)

  1. 类型导出: 可以考虑导出更多中间类型以提高可维护性
  2. 注释补充: 部分复杂逻辑可以添加更多注释

🧪 测试建议

  1. 集成测试: 建议添加端到端测试,验证套餐信息在前端正确显示
  2. 边界测试: 测试 standardConstantsundefined 的情况
  3. 回归测试: 验证所有使用套餐信息的功能(文件上传、成员限制、应用限制等)

💬 总体评价

  • 代码质量: ⭐⭐⭐⭐☆ (4/5)
  • 安全性: ⭐⭐⭐⭐⭐ (5/5)
  • 性能: ⭐⭐⭐⭐⭐ (5/5)
  • 可维护性: ⭐⭐⭐⭐☆ (4/5)

🚀 审查结论

建议: 修复严重问题后通过

这是一个高质量的重构 PR,设计合理,测试完善。主要问题是类型定义需要加强,以及字段命名映射可以优化。修复严重问题后可以合并。


📍 详细代码评论位置

以下位置已添加具体的行级评论:

  • packages/service/support/wallet/sub/utils.ts:153-179 - buildStandardPlan 函数类型定义
  • packages/global/support/wallet/sub/type.ts:32-43 - TeamPlanStandardSchema 定义
  • projects/app/src/components/support/wallet/StandardPlanContentList.tsx:404-407 - 字段名映射

@c121914yu
Copy link
Collaborator

详细代码审查评论

🔴 严重问题

1. packages/service/support/wallet/sub/utils.ts:153-179

问题: buildStandardPlan 函数的第二个参数类型定义不够严格

当前代码:

export const buildStandardPlan = (
  standard: TeamSubSchemaType,
  standardConstants: NonNullable<ReturnType<typeof getStandardPlanConfig>>
): TeamPlanStandardType => {

问题分析:

  • 使用 NonNullable<ReturnType<typeof getStandardPlanConfig>> 依赖于函数的返回类型,这种间接依赖增加了维护成本
  • 如果 getStandardPlanConfig 函数的返回类型发生变化,这里的类型会自动变化,可能导致隐藏的类型错误
  • 类型不够明确,阅读代码时需要跳转到 getStandardPlanConfig 才能理解参数类型

建议修复:

export const buildStandardPlan = (
  standard: TeamSubSchemaType,
  standardConstants: TeamStandardSubPlanItemType
): TeamPlanStandardType => {

理由:

  • 使用明确的类型 TeamStandardSubPlanItemType 更清晰
  • 减少类型推导链,提高代码可读性
  • 如果类型不匹配,TypeScript 会在调用处报错,而不是在函数定义处

🟡 建议改进

2. packages/global/support/wallet/sub/type.ts:32-43

问题: Schema 合并使用了 spread 操作符,但缺少字段冲突的处理说明

当前代码:

export const TeamPlanStandardSchema = z.object({
  ...TeamSubSchema.omit({
    maxApp: true,
    maxDataset: true
  }).shape,
  ...TeamStandardSubPlanItemSchema.omit({
    pointPrice: true
  }).shape,
  price: z.number().optional()
});

建议:
添加注释说明为什么要 omit 这些字段,以及字段合并的优先级:

/** 
 * Merged plan type: combines DB subscription record metadata with effective plan limits
 * 
 * Omits:
 * - maxApp/maxDataset from TeamSubSchema: 这些字段在 DB 中存储,但在合并后的类型中使用 maxAppAmount/maxDatasetAmount
 * - pointPrice from TeamStandardSubPlanItemSchema: 避免与 price 字段冲突
 * 
 * Field priority: TeamStandardSubPlanItemSchema fields override TeamSubSchema fields when both exist
 */
export const TeamPlanStandardSchema = z.object({
  ...TeamSubSchema.omit({
    maxApp: true,
    maxDataset: true
  }).shape,
  ...TeamStandardSubPlanItemSchema.omit({
    pointPrice: true
  }).shape,
  price: z.number().optional()
});

3. projects/app/src/components/support/wallet/StandardPlanContentList.tsx:404-407

问题: 字段名映射不一致,增加理解成本

当前代码:

maxAppAmount: standplan?.maxAppAmount ?? plan.maxAppAmount,
maxDatasetAmount: standplan?.maxDatasetAmount ?? plan.maxDatasetAmount,

背景: 在 buildStandardPlan 中,standard.maxApp 被映射到 result.maxAppAmount,但在这里又需要使用 standplan?.maxAppAmount

建议: 考虑在数据库层面统一字段命名,或者在类型定义中添加更清晰的注释说明这种映射关系。

替代方案: 如果无法修改数据库字段名,建议在 TeamSubSchema 的注释中明确说明:

/**
 * TeamSub Schema in DB.
 * Configs are optional
 * 
 * Note: maxApp maps to maxAppAmount in merged plan, maxDataset maps to maxDatasetAmount
 */

4. packages/service/support/permission/teamLimit.ts

建议: 使用可选链简化代码

当前代码:

if (standard && newCount + memberCount > standard.maxTeamMember) {
  return Promise.reject(TeamErrEnum.teamOverSize);
}

建议优化:

if (standard?.maxTeamMember && newCount + memberCount > standard.maxTeamMember) {
  return Promise.reject(TeamErrEnum.teamOverSize);
}

这样可以避免 standard 存在但 maxTeamMemberundefined 的情况导致的逻辑错误。


🟢 可选优化

5. test/cases/service/support/wallet/sub/utils.test.ts

建议: 测试文件位置优化

当前位置: test/cases/service/support/wallet/sub/utils.test.ts

建议位置: packages/service/support/wallet/sub/__tests__/utils.test.tspackages/service/test/support/wallet/sub/utils.test.ts

理由:

  • 将测试文件放在被测试代码附近,更容易维护
  • 符合常见的 monorepo 测试组织模式
  • 便于 IDE 自动发现和运行测试

6. packages/service/support/wallet/sub/utils.ts:216-233

建议: 添加注释说明复杂的业务逻辑

当前代码:

/** 配置里的套餐 */
const standardPlans = global.subPlans?.standard;
// ...
/** 数据库里的,用户目前 active 的套餐 */
const standardPlan = teamStandardPlans[0];
// ...
/** 静态的套餐配置,如果是 custom 则返回 advanced */
const standardConstants = ...

优点: 已经添加了中文注释,这很好!

建议: 可以进一步补充说明为什么 custom 套餐要返回 advanced 配置:

/** 
 * 静态的套餐配置
 * 如果是 custom 套餐,返回 advanced 配置作为基础模板
 * 因为 custom 套餐通常是在 advanced 基础上定制的
 */

📋 测试覆盖分析

测试文件 utils.test.ts 的覆盖情况:

已覆盖:

  • 展示字段从 standardConstants 获取
  • DB 元数据从 standard spread
  • 限制字段的 DB override 逻辑
  • 字段名映射 (maxApp → maxAppAmount)
  • 所有可选字段的回退逻辑

⚠️ 建议补充:

  • getTeamStandPlan 函数的测试
  • getTeamPlanStatus 函数的测试
  • 边界情况:standardConstants 为 undefined
  • 集成测试:验证前端组件正确显示合并后的数据

🎯 重构影响范围分析

类型变更影响:

  • TeamPlanStatusTypestandardConstants 字段被移除
  • ✅ 所有使用 teamPlanStatus.standardConstants 的地方已更新为 teamPlanStatus.standard
  • ✅ 前端组件、API 路由、权限检查全部更新

潜在风险:

  • ⚠️ 如果有外部系统或插件依赖 standardConstants 字段,需要更新
  • ⚠️ 如果有缓存的 TeamPlanStatusType 数据,需要清理缓存

建议:

  1. 在发布说明中明确说明这是一个 breaking change
  2. 提供迁移指南,说明如何从 standardConstants 迁移到 standard
  3. 考虑添加运行时警告,如果检测到使用了旧的 standardConstants 字段

@c121914yu c121914yu merged commit 21b3f85 into labring:main Mar 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants