From 92c625ea4ac67ea7c4413b801cf436ead9f2a667 Mon Sep 17 00:00:00 2001 From: Rogee Date: Thu, 30 Jul 2026 10:37:38 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E5=90=8E=E7=99=BD=E5=B1=8F=20+=20label=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E9=97=AA=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 白屏: security.routes.js 缺少 security_settings_index 命名路由, SidebarGroup 的 router.resolve 抛错导致所有 sidebar 组件渲染失败. 修复: 添加命名子路由指向空占位组件. 闪屏: 后端 FilterParams.Labels 用 form:"labels" 绑定, 无法解析 Chatwoot 前端的 labels[] 数组参数, label 过滤从未生效. IntersectionObserver 检测到"还有更多数据"不断触发 loadMore, 8秒内发出 1000+ 次重复请求形成无限循环. 修复: 新增 LabelsArr []string 字段绑定 form:"labels[]", 在 handler 中合并到 Labels 字段. --- .../handler/api/v1/conversation_handler.go | 16 +++++++ .../internal/service/conversation_service.go | 3 +- .../settings/security/security.routes.js | 45 ++++++++++++------- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/backend/internal/handler/api/v1/conversation_handler.go b/backend/internal/handler/api/v1/conversation_handler.go index f7739c45..76ee3667 100644 --- a/backend/internal/handler/api/v1/conversation_handler.go +++ b/backend/internal/handler/api/v1/conversation_handler.go @@ -79,6 +79,15 @@ func (h *ConversationHandler) List(c *gin.Context) { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } + // Merge labels[] array params into Labels (comma-separated) for backward compat. + // Chatwoot frontend sends labels[]=xxx as separate query params. + if len(params.LabelsArr) > 0 { + if params.Labels != "" { + params.Labels = params.Labels + "," + strings.Join(params.LabelsArr, ",") + } else { + params.Labels = strings.Join(params.LabelsArr, ",") + } + } result, svcErr := h.conversationSvc.ListWithFinder(c.Request.Context(), accountID, getUserID(c), params, p.Offset, p.PerPage) if svcErr != nil { @@ -522,6 +531,13 @@ func (h *ConversationHandler) Search(c *gin.Context) { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrValidation, err.Error()) return } + if len(params.LabelsArr) > 0 { + if params.Labels != "" { + params.Labels = params.Labels + "," + strings.Join(params.LabelsArr, ",") + } else { + params.Labels = strings.Join(params.LabelsArr, ",") + } + } result, svcErr := h.conversationSvc.ListWithFinder(c.Request.Context(), accountID, getUserID(c), params, p.Offset, p.PerPage) if svcErr != nil { diff --git a/backend/internal/service/conversation_service.go b/backend/internal/service/conversation_service.go index 9693fbe2..62249a37 100644 --- a/backend/internal/service/conversation_service.go +++ b/backend/internal/service/conversation_service.go @@ -782,7 +782,8 @@ type FilterParams struct { InboxIDs []uint `json:"inbox_ids,omitempty" form:"inbox_ids"` // multi-inbox filtering (Chatwoot: inbox_id can be array) TeamID *uint `json:"team_id,omitempty" form:"team_id"` Labels string `json:"labels,omitempty" form:"labels"` - Tags string `json:"tags,omitempty" form:"tags"` // custom tags (Chatwoot: same as labels via ActsAsTaggableOn) + LabelsArr []string `json:"labels_arr,omitempty" form:"labels[]"` // Chatwoot frontend sends labels[] array params + Tags string `json:"tags,omitempty" form:"tags"` // custom tags (Chatwoot: same as labels via ActsAsTaggableOn) ConversationType string `json:"conversation_type,omitempty" form:"conversation_type" validate:"omitempty,oneof=mention participating unattended"` SortBy string `json:"sort_by,omitempty" form:"sort_by" validate:"omitempty,oneof=last_activity_at_asc last_activity_at_desc created_at_asc created_at_desc priority_asc priority_desc waiting_since_asc waiting_since_desc priority_desc_created_at_asc latest sort_on_created_at sort_on_priority sort_on_waiting_since"` UpdatedWithin *int `json:"updated_within,omitempty" form:"updated_within"` // seconds diff --git a/frontend/app/javascript/dashboard/routes/dashboard/settings/security/security.routes.js b/frontend/app/javascript/dashboard/routes/dashboard/settings/security/security.routes.js index 6abba2dc..93d26e8c 100644 --- a/frontend/app/javascript/dashboard/routes/dashboard/settings/security/security.routes.js +++ b/frontend/app/javascript/dashboard/routes/dashboard/settings/security/security.routes.js @@ -1,20 +1,35 @@ import { frontendURL } from '../../../../helper/URLHelper'; import SettingsWrapper from '../SettingsWrapper.vue'; +const SecurityIndex = { + render() { + return null; + }, +}; + export default { - routes: [ - { - path: frontendURL('accounts/:accountId/settings/security'), - meta: { - permissions: ['administrator'], - }, - component: SettingsWrapper, - props: { - headerTitle: 'SECURITY_SETTINGS.TITLE', - icon: 'i-lucide-shield', - showNewButton: false, - }, - children: [], - }, - ], + routes: [ + { + path: frontendURL('accounts/:accountId/settings/security'), + meta: { + permissions: ['administrator'], + }, + component: SettingsWrapper, + props: { + headerTitle: 'SECURITY_SETTINGS.TITLE', + icon: 'i-lucide-shield', + showNewButton: false, + }, + children: [ + { + path: '', + name: 'security_settings_index', + component: SecurityIndex, + meta: { + permissions: ['administrator'], + }, + }, + ], + }, + ], };