feat: ✨ 渠道自定义标签系统(创建/编辑/筛选/记忆) - #198
Conversation
- 渠道模型新增 Tags 字段(GORM serializer:json) - 渠道创建/编辑表单支持标签输入,支持从已有标签快速选择(Popover 建议) - 分组编辑器新增按标签筛选,筛选状态按分组独立记忆(Zustand store) - LLMChannel / model/channel API 透传 tags,前端 null 归一化 - i18n:中英文标签相关翻译 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR implements a comprehensive channel custom tagging system with creation, editing, filtering, and per-group filter state persistence capabilities.
Changes:
- Added Tags field to Channel and LLMChannel models with JSON serialization support in backend (Go) and proper null-to-empty-array normalization in frontend APIs
- Implemented tag input UI with autocomplete suggestions from existing tags in channel create/edit forms
- Added per-group tag filtering in the group editor with Zustand-based state persistence to remember filter selections across component re-mounts
- Added i18n translations for tag-related UI labels in Chinese (simplified/traditional) and English
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/model/channel.go | Added Tags field to Channel model with GORM JSON serializer |
| internal/model/llm.go | Added Tags field to LLMChannel struct for API responses |
| internal/op/channel.go | Added tags field handling in channel update operations and LLM channel list generation |
| web/src/api/endpoints/channel.ts | Added tags field to Channel and related types with null normalization |
| web/src/api/endpoints/model.ts | Added tags field to LLMChannel with null normalization in select function |
| web/src/components/modules/channel/Form.tsx | Implemented tag input with popover suggestions and badge display |
| web/src/components/modules/channel/Create.tsx | Added tags initialization in channel creation form |
| web/src/components/modules/channel/CardContent.tsx | Added tags comparison and update logic in channel edit |
| web/src/components/modules/group/Editor.tsx | Added Zustand store for per-group tag filter persistence and tag-based channel filtering UI |
| web/src/components/modules/group/Card.tsx | Added tags field to SelectedMember via tagsByKey map |
| web/public/locale/*.json | Added translations for "tags", "filterByTag", and related labels |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| onClick={() => toggleTag(tag)} | ||
| className={cn( | ||
| 'px-2 py-0.5 text-xs rounded-md transition-colors', | ||
| selectedTags.includes(tag) |
There was a problem hiding this comment.
The UI uses selectedTags to highlight selected tag buttons, but the actual filtering logic uses effectiveTags (which prunes stale tags). This creates an inconsistency where stale tags (tags that no longer exist in any channel) will still appear as selected/highlighted in the UI, even though they're not actually filtering anything. Consider using effectiveTags.includes(tag) here instead to ensure the UI accurately reflects which tags are actively being used for filtering.
| selectedTags.includes(tag) | |
| effectiveTags.includes(tag) |
| {tag} | ||
| </button> | ||
| ))} | ||
| {selectedTags.length > 0 && ( |
There was a problem hiding this comment.
Similar to the tag button highlighting, the visibility of the "All" clear button is determined by selectedTags.length > 0, but the actual filtering uses effectiveTags. This means the clear button will remain visible even when all selected tags are stale and not actually filtering anything. Consider using effectiveTags.length > 0 instead for consistency.
| {selectedTags.length > 0 && ( | |
| {effectiveTags.length > 0 && ( |
- useTagFilterStore 添加 persist 中间件,刷新页面后保留标签筛选 - 修复 Zustand selector 返回新空数组引用导致的无限渲染循环(EMPTY_TAGS 稳定引用) - 添加 effectiveTags 派生状态,自动过滤已失效的标签 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
按钮高亮和"全部"按钮显示条件从 selectedTags 改为 effectiveTags, 避免 localStorage 残留失效标签时 UI 状态与过滤行为不一致。 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
tag 相关状态现在分为 4 类,持久化方式不同:
说明:
|
|
分组编辑器的标签筛选选择是否应该改成存到后端有待商榷。 |
|
感谢PR 我感觉可以和 #159 一起实现 tag 改为分组是不是更好? 改为 可以向右侧添加 分组,渠道,模型 任务量有些大,我再仔细想想,目前我先修复完现有的BUG,后面再增加新功能 |
…truirui#208 已内置) 合入的 PR: - bestruirui#262 添加活动热力图自定义日期范围选择功能 (cherry-pick) - bestruirui#271 修复日志无法滚动问题 (手动适配:VirtualizedGrid reachEnd 重置 + 日志分页偏移) - bestruirui#287 加入 rerank 转发路由 + 重复资源检测 (手动适配) - bestruirui#208 空响应检测触发负载均衡重试 → 已被 axonhub/llm 内置 WithEmptyResponseDetection() 覆盖,无需手动移植 跳过的 PR: - bestruirui#282 TOTP + JSON 替换 (+1425/-115,改动过大) - bestruirui#270 key 选择模式 (改了已删除的 images.go,需大量适配) - bestruirui#199 熔断器开关 (改了已删除的 transformer,冲突复杂) - bestruirui#198 渠道标签系统 (13 文件,改动偏大) - bestruirui#194 日志筛选增强 (8 文件 +512/-86,改动偏大) - bestruirui#190 统计清除 (合并提交多,冲突复杂) - bestruirui#184 渠道排序 (排序已内置上游,复制功能非核心) 版本升级至 v0.9.28-2 Co-Authored-By: Claude <noreply@anthropic.com>
实际效果:



标签下拉菜单(从已有标签快速选择):
已添加标签:
编辑分组页面效果: