package keyword import ( "fmt" "net/http" "strings" "mini-chat/internal/code" "mini-chat/internal/pkg/core" "mini-chat/internal/pkg/timeutil" "mini-chat/internal/pkg/validation" "gorm.io/gorm" ) type keywordPageListRequest struct { AppID string `form:"app_id" binding:"required"` // 小程序ID Keyword string `form:"keyword"` // 意图关键字 Page int `form:"page"` // 当前页码,默认为第一页 PageSize int `form:"page_size"` // 每页返回的数据量 } type keywordListData struct { ID int32 `json:"id"` // 关键字编号 AppID string `json:"app_id"` // 小程序ID Keyword string `json:"keyword"` // 意图关键字 CreatedUser string `json:"created_user"` // 创建人 CreatedAt string `json:"created_at"` // 创建时间 UpdatedUser string `json:"updated_user"` // 更新人 UpdatedAt string `json:"updated_at"` // 更新时间 MaterialTypeCount string `json:"material_type_count"` // 素材类型数量 } type keywordPageListResponse struct { Page int `json:"page"` // 当前页码 PageSize int `json:"page_size"` // 每页返回的数据量 Total int64 `json:"total"` // 符合查询条件的总记录数 List []keywordListData `json:"list"` } // KeywordPageList 获取意图关键字列表 // @Summary 获取意图关键字列表 // @Description 获取意图关键字列表 // @Tags 管理端.意图关键字 // @Accept json // @Produce json // @Param app_id query int true "小程序ID" // @Param keyword query string false "意图关键字" // @Param page query int true "当前页码" default(1) // @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) // @Success 200 {object} keywordPageListResponse // @Failure 400 {object} code.Failure // @Router /api/admin/app/keywords [get] // @Security LoginVerifyToken func (h *handler) KeywordPageList() core.HandlerFunc { return func(ctx core.Context) { req := new(keywordPageListRequest) res := new(keywordPageListResponse) if err := ctx.ShouldBindForm(req); err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ParamBindError, validation.Error(err)), ) return } if req.Page == 0 { req.Page = 1 } if req.PageSize == 0 { req.PageSize = 20 } if req.PageSize > 100 { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ListKeywordError, fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListKeywordError)), )) return } query := h.readDB.AppKeyword.WithContext(ctx.RequestContext()) query = query.Where(h.readDB.AppKeyword.AppID.Eq(req.AppID)) if req.Keyword != "" { query = query.Where(h.readDB.AppKeyword.Keyword.Like(fmt.Sprintf("%%%s%%", req.Keyword))) } listQueryDB := query.Session(&gorm.Session{}) countQueryDB := query.Session(&gorm.Session{}) resultData, err := listQueryDB. Order(h.readDB.AppKeyword.ID.Desc()). Limit(req.PageSize). Offset((req.Page - 1) * req.PageSize). Find() if err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ListKeywordError, fmt.Sprintf("%s:%s", code.Text(code.ListKeywordError), err.Error())), ) return } count, err := countQueryDB.Count() if err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ListKeywordError, fmt.Sprintf("%s:%s", code.Text(code.ListKeywordError), err.Error())), ) return } res.Page = req.Page res.PageSize = req.PageSize res.Total = count res.List = make([]keywordListData, len(resultData)) var keywordIDs []int32 for _, v := range resultData { keywordIDs = append(keywordIDs, v.ID) } keywordIDMaterialTypeCountMap, err := h.contactMaterialTypeCount(keywordIDs) if err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ListKeywordError, fmt.Sprintf("%s:%s", code.Text(code.ListKeywordError), err.Error())), ) return } for k, v := range resultData { res.List[k] = keywordListData{ ID: v.ID, AppID: v.AppID, Keyword: v.Keyword, CreatedUser: v.CreatedUser, CreatedAt: timeutil.FriendlyTime(v.CreatedAt), UpdatedUser: v.UpdatedUser, UpdatedAt: timeutil.FriendlyTime(v.UpdatedAt), MaterialTypeCount: keywordIDMaterialTypeCountMap[v.ID], } } ctx.Payload(res) } } func (h *handler) contactMaterialTypeCount(keywordIDs []int32) (map[int32]string, error) { var results []struct { KeywordID int32 Type int Count int `db:"count"` } if err := h.readDB.AppKeywordReply. Select(h.readDB.AppKeywordReply.KeywordID, h.readDB.AppKeywordReply.Type, h.readDB.AppKeywordReply.ID.Count().As("count")). Where(h.readDB.AppKeywordReply.KeywordID.In(keywordIDs...)). Group(h.readDB.AppKeywordReply.KeywordID, h.readDB.AppKeywordReply.Type). Scan(&results); err != nil { return nil, err } keywordIDMap := make(map[int32]string) typeMap := map[int]string{ 1: "文本", 2: "图片", 3: "语音条", 4: "视频", 5: "小程序", 6: "地理位置", 7: "链接", 8: "GIF图", 9: "名片", 10: "文件", 11: "转人工", } for _, result := range results { keywordID := result.KeywordID typeDesc := fmt.Sprintf("%d条%s", result.Count, typeMap[result.Type]) if currentString, exists := keywordIDMap[keywordID]; exists { keywordIDMap[keywordID] = currentString + "、" + typeDesc + "、" } else { keywordIDMap[keywordID] = "1 组话术(共" + typeDesc } } for keywordID, resultString := range keywordIDMap { // 查找最后一个逗号的位置 commaIndex := strings.LastIndex(resultString, "、") // 如果找到逗号,替换为右括号 if commaIndex != -1 { keywordIDMap[keywordID] = resultString[:commaIndex] + ")" } else { keywordIDMap[keywordID] += ")" } } return keywordIDMap, nil }