Skip to content

feat: 新增限额管理功能 - #27

Merged
ding113 merged 20 commits into
mainfrom
dev
Oct 30, 2025
Merged

feat: 新增限额管理功能#27
ding113 merged 20 commits into
mainfrom
dev

Conversation

@ding113

@ding113 ding113 commented Oct 30, 2025

Copy link
Copy Markdown
Owner

No description provided.

claude Bot and others added 20 commits October 29, 2025 23:40
* fix: 供应商管理列表增加类型筛选和图标显示, close #22

新功能:
1. 增加供应商类型筛选功能
   - 支持按 Claude、Claude Auth、Codex、Gemini CLI、OpenAI Compatible 筛选
   - 显示当前筛选结果数量

2. 供应商卡片名称增加类型图标和标签
   - 类型图标(5 种不同颜色和图标)
   - 类型标签(文字说明)
   - 鼠标悬停显示类型描述

实现细节:
- 新增 provider-type-utils.tsx:统一管理供应商类型配置
- 新增 provider-type-filter.tsx:类型筛选组件
- 修改 provider-manager.tsx:集成筛选功能和计数显示
- 修改 provider-list-item.tsx:添加类型图标和标签

Close #22

* feat: 添加 @lobehub/icons 依赖并更新供应商类型图标

- 新增 @lobehub/icons 依赖,支持更丰富的图标展示。
- 更新供应商类型配置,使用新的图标组件替代原有图标。
- 为 Anthropic 类型添加专用的橙色包装组件,提升视觉一致性。

影响范围:
- 供应商管理界面图标展示更为美观,增强用户体验。

---------

Co-authored-by: Claude Code Bot <noreply@anthropic.com>
Co-authored-by: ding113 <h.ding.262@gmail.com>
- 修复 sumUserCostToday 中 SQL JOIN 条件错误(message_request.key 应与 keys.key 关联,而非 keys.id)
- 修复日志字符串插值未生效问题(单引号改为反引号)
- 移除不必要的类型断言,利用 TypeScript 类型收窄
- 优化 Redis TTL 计算,使用配置时区而非服务器本地时区
- 添加 date-fns-tz 依赖用于时区处理

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Modified `claude-assistant.yml` to reduce pull request event types and limit issue event types to only labeled events.
- Updated `claude-ci-autofix.yml` to remove the requirement for associated pull requests, allowing CI fixes on any branch.
- 修复 src/repository/statistics.ts 中的 TypeScript any 类型错误(第 579 行)
- 移除 src/app/dashboard/_components/user/key-limit-usage.tsx 中未使用的 err 变量
- 移除 src/app/settings/providers/_components/provider-list-item.tsx 中未使用的导入(ServerCog, AddProviderDialog)
- 移除 src/app/usage-doc/page.tsx 中未使用的导入和变量(cn, lang, configDir)
- 移除 src/lib/rate-limit/service.ts 中未使用的 now 变量

所有修复均为 ESLint 相关的代码质量改进,不影响功能逻辑。

相关 CI Run: https://github.com/ding113/claude-code-hub/actions/runs/18933737607
- Removed the requirement for the commit message in scenario B to include [skip ci], ensuring it triggers CI again.
- Adjusted instructions for auto-fixing CI failures to reflect the new commit message policy.

This change aims to streamline the CI process and improve clarity in the workflow documentation.
- Introduced a new environment variable ENABLE_CODEX_INSTRUCTIONS_INJECTION to control the injection of official Codex instructions into requests.
- Updated .env.example and CLAUDE.md to document the new feature and its usage scenarios.
- Modified request-sanitizer.ts to implement the logic for conditionally replacing instructions based on the new feature flag.

This enhancement allows for better compatibility with certain Codex providers that require official instructions.
- Implemented a check to ensure that the provider belongs to the user's specified group, enhancing security and user experience.
- Added debug logging for session provider group mismatches to aid in troubleshooting.

This change ensures that only appropriate providers are selected based on user group settings.
- Modified the SQL query in getProviderStatistics to calculate today's cost and call count using JavaScript Date for local timezone handling.
- This change ensures accurate statistics based on the user's local time, improving the reliability of provider data reporting.
- Implemented `getProviderLimitUsage` and `getUserLimitUsage` functions to retrieve usage statistics for providers and users, respectively.
- These functions include permission checks and dynamic imports to avoid circular dependencies.
- Updated the dashboard header to include a link for quota management, enhancing user navigation.
- Refactored the `RateLimitService` to utilize new utility functions for time range and TTL calculations, improving code maintainability.
将三个配额统计页面(users/providers/keys)的 UI 逻辑重构为独立组件,提升代码复用性和可维护性。

**主要改动**:
- 提取用户配额组件到 `_components/users-quota-client.tsx`
- 提取服务商配额组件到 `_components/providers-quota-manager.tsx`
- 提取密钥配额组件到 `_components/keys-quota-manager.tsx`
- 新增公共配额工具栏组件 `components/quota/quota-toolbar.tsx`
- 新增前端设计文档 `FRONTEND_DESIGN.md`

**技术改进**:
- 统一配额卡片展示逻辑
- 支持排序和过滤功能
- 改善代码组织结构

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
新增功能:
- 创建密钥限额编辑 Dialog,支持设置/修改/清除所有类型限额
- 重构密钥限额页面布局,分离已设置和未设置限额的密钥
- 未设置限额的密钥收纳到底部可折叠区域,使用紧凑的横向分栏布局

改进细节:
- EditKeyQuotaDialog: 支持编辑 5小时/周/月消费限额和并发 Session 限额
- 显示当前用量对比,帮助用户合理设置限额
- 提供"清除所有限额"按钮,快速重置配置
- 已设置限额的密钥保持卡片布局,展示详细的进度条和重置时间
- 未设置限额的密钥使用列表布局(一行一个),节省空间不占用主视觉区域
- 所有密钥卡片/列表项都添加"设置限额"按钮,操作统一便捷

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Fetch system currency settings in all quota pages (users, keys, providers)
- Pass currencyCode prop through component hierarchy: Page → Manager → Client → Dialog
- Update all formatCurrency() calls to use system-configured currency code
- Update EditKeyQuotaDialog to dynamically display currency symbol from configuration
- Ensure consistent currency display (USD, CNY, etc.) across entire quota management feature

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude claude Bot added the invalid This doesn't seem right label Oct 30, 2025
@ding113 ding113 added enhancement New feature or request and removed invalid This doesn't seem right labels Oct 30, 2025
Repository owner deleted a comment from claude Bot Oct 30, 2025
@ding113

ding113 commented Oct 30, 2025

Copy link
Copy Markdown
Owner Author

此 PR 是从 dev 分支合并到 main 分支,因此请无视目标分支规则正常审核

@claude

claude Bot commented Oct 30, 2025

Copy link
Copy Markdown
Contributor

代码审查报告 🔍

感谢提交这个全面的限额管理功能!这是一个设计良好、实现细致的大型 PR。以下是我的审查意见:


亮点与优秀设计

1. 时间算法修正 (src/lib/rate-limit/time-utils.ts)

  • 自然时间窗口:周/月限额改为自然周一和月初重置,更符合业务直觉
  • 动态 TTL 计算:Redis key 的过期时间精确到下一个重置点,避免数据泄漏
  • 时区处理规范:统一使用 Asia/Shanghai 时区,使用 date-fns-tz 处理
  • 类型安全:完整的 TypeScript 类型定义

2. 降级策略完善 (src/lib/rate-limit/service.ts)

  • Fail Open 原则:Redis 不可用时自动降级到数据库,不影响服务可用性
  • Cache Warming:数据库查询后自动回写 Redis,优化后续请求性能
  • 原子性保证:使用 Lua 脚本解决并发检查的竞态条件
  • 详细日志记录:每个关键路径都有 info/warn 级别日志

3. 前端架构清晰 (src/app/dashboard/quotas/)

  • Server/Client 分离:Server Component 负责数据获取,Client Component 处理交互
  • 组件复用性高QuotaToolbarQuotaProgress 可在多个页面复用
  • 进度条颜色警告:4 级颜色(正常/警告/危险/超限)清晰直观
  • 自动刷新机制:使用 useTransition + router.refresh 优雅处理

4. 文档完善 (FRONTEND_DESIGN.md)

  • 详尽的设计文档:818 行完整记录设计思路、实施细节、测试结果
  • 架构图和目录结构:清晰展示代码组织
  • 未来优化建议:列出了短期/中期/长期的改进方向

⚠️ 需要注意的问题

1. 环境变量新增但未在文档中突出强调

ENABLE_CODEX_INSTRUCTIONS_INJECTION=false
  • 📝 建议:在 README.md 主文档的"环境变量"章节也添加说明,避免用户遗漏
  • 📝 建议:在 Docker Compose 示例配置中也添加此变量

2. LiteLLM 价格数据更新

  • public/seed/litellm-prices.json 有 22532 行新增和 24047 行删除
  • ✅ 这是正常的价格数据同步,但建议:
    • 📝 在 PR 描述中说明价格数据的更新来源和日期
    • 📝 考虑添加自动化脚本定期同步价格数据

3. CI 工作流修改

  • .github/workflows/claude-ci-autofix.yml 中移除了 [skip ci] 标记
  • ⚠️ 这意味着自动修复会再次触发 CI,可能导致循环
  • 📝 建议:确认这是有意为之还是应该保留 [skip ci] 避免无限循环

🔒 安全性检查

通过的检查

  1. 所有 API 都经过 Session 认证(Server Actions)
  2. 用户只能查看自己的限额(非管理员)
  3. 敏感数据不暴露到客户端
  4. Redis 操作有完整的错误处理
  5. 没有 SQL 注入风险(使用 Drizzle ORM)

⚠️ 建议加固

  1. 并发限制的边界测试

    • 建议添加压力测试,验证 Lua 脚本在高并发下的正确性
    • 测试 Redis 不可用时的降级路径是否真的 Fail Open
  2. 时区边界情况

    • 测试服务器时区与配置时区不一致时的行为
    • 测试夏令时切换时的边界情况

📊 性能评估

优化点

  • Server Components 减少客户端包大小
  • Redis Pipeline 批量操作
  • useMemo 避免重复计算
  • 并发查询(Promise.all)

📝 建议进一步优化

  1. Keys 和 Providers 页面

    • 当前未拆分 Client Component,用户多时可能影响交互响应
    • 建议参考 Users 页面的模式进行拆分
  2. 数据库查询

    • getUsersWithQuotas 中使用 Promise.all 查询所有用户限额
    • 当用户数 > 100 时,考虑添加分页或懒加载

🧪 测试建议

功能测试清单(建议添加自动化测试)

  • 时间窗口切换测试(周一 00:00 重置、月初重置)
  • Redis 不可用时的降级测试
  • 并发请求的限流测试(Lua 脚本正确性)
  • 不同时区下的时间计算测试
  • 进度条颜色变化测试(60%, 80%, 100% 边界)

性能测试建议

  • 100+ 用户时的页面加载时间
  • 高频刷新(10s)时的服务器压力
  • Redis Pipeline 批量操作的延迟

📋 代码质量

通过的检查

  • TypeScript 类型检查通过
  • ESLint 检查通过
  • 代码风格一致
  • 注释清晰完整
  • 错误处理完善

📝 小建议

  1. QuotaToolbar 组件

    • 当前有很多 props(sortOptions, filterOptions 等)
    • 考虑使用配置对象或 Context 简化
  2. magic numbers

    • 60% / 80% / 100% 等阈值建议提取为常量
    • 示例:const QUOTA_WARNING_THRESHOLD = 0.6

🎯 总体评价

这是一个高质量的 PR:

  • ✅ 功能完整,覆盖用户/密钥/供应商三层限额
  • ✅ 架构清晰,Server/Client 分离合理
  • ✅ 性能优化到位,有完善的降级策略
  • ✅ 文档详尽,FRONTEND_DESIGN.md 可作为最佳实践参考
  • ✅ 类型安全,代码质量高

建议操作

  1. 解决上述 ⚠️ 标记的问题(CI 循环风险、环境变量文档)
  2. 添加部分自动化测试(时间窗口、并发限流)
  3. 合并后监控生产环境的 Redis 性能和降级情况

📌 合并前检查清单

  • 确认 CI workflow 修改不会导致无限循环
  • 更新 README.md 主文档的环境变量说明
  • 验证 Docker Compose 配置包含新环境变量
  • 在测试环境验证周一/月初的限额重置逻辑
  • 确认 LiteLLM 价格数据来源可靠

整体推荐:✅ 批准合并(解决检查清单后)

感谢贡献这么优秀的功能!💯

Comment thread .github/workflows/claude-ci-autofix.yml
Comment thread .env.example
* - weekly: 到下周一 00:00 的秒数
* - monthly: 到下月 1 号 00:00 的秒数
*/
export function getTTLForPeriod(period: TimePeriod): number {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

优秀设计:动态 TTL 避免数据泄漏

这个设计很棒!通过动态计算 TTL 到下一个重置点,确保:

  1. Redis key 在正确的时间自动过期
  2. 不会出现"跨周/跨月"的脏数据
  3. 节省 Redis 内存

建议:考虑添加单元测试验证边界情况:

// 测试用例
test("weekly TTL at Sunday 23:59", () => {
  // 周日 23:59 的 TTL 应该约为 60 秒(1分钟后是周一)
});

test("monthly TTL on last day", () => {
  // 月末最后一天的 TTL 应该正确计算到次月 1 号
});

Comment thread src/lib/rate-limit/service.ts
<p className="text-muted-foreground">查看和管理所有层级的限额使用情况</p>
</div>

<Tabs defaultValue="users" className="space-y-4">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📝 UI 小建议:Tabs 选中状态未根据当前路由高亮

当前问题:无论在哪个子页面,defaultValue="users" 都会高亮"用户限额"。

建议修复:根据当前路由动态设置 value

"use client";
import { usePathname } from "next/navigation";

export default function QuotasLayout({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();
  const currentTab = pathname.split("/").pop() || "users";

  return (
    <div className="space-y-6">
      {/* ...省略... */}
      <Tabs value={currentTab} className="space-y-4">
        {/* ...省略... */}
      </Tabs>
    </div>
  );
}

或者使用 Shadcn 的导航组件(更语义化):

<nav className="flex space-x-2">
  <Link href="/dashboard/quotas/users">
    <Button variant={isActive ? "default" : "ghost"}>用户限额</Button>
  </Link>
  {/* ... */}
</nav>

@claude claude Bot added the documentation Improvements or additions to documentation label Oct 30, 2025
@ding113
ding113 merged commit c1d3ecf into main Oct 30, 2025
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant