package console import ( "strings" "yunyan/comm" "yunyan/pb" "github.com/gin-gonic/gin" ) // userFeedbackListReq 用户反馈列表筛选。 // // User 一栏多用:UID 精确,手机号 / 邮箱 / 用户名 / 登录账号模糊。 // 客服转来的线索形态不定,让人先选「按什么查」只是多一步。 // Content 只搜反馈正文。时间区间是 [start, end),结束日由前端按当天 24:00 换算。 type userFeedbackListReq struct { User string `json:"user"` Content string `json:"content"` Start int64 `json:"start"` End int64 `json:"end"` Page int `json:"page"` PageSize int `json:"page_size"` } // userFeedbackItem 列表行。用户字段来自提交时仍在库里的 user 行; // 账号已注销删掉时这几列为空,uid 仍在。 type userFeedbackItem struct { Id uint64 `json:"id" gorm:"column:id"` Uid string `json:"uid" gorm:"column:uid"` Message string `json:"message" gorm:"column:message"` Version string `json:"version" gorm:"column:version"` Phonemodel string `json:"phonemodel" gorm:"column:phonemodel"` Channel int32 `json:"channel" gorm:"column:channel"` Createtime int64 `json:"createtime" gorm:"column:createtime"` Name string `json:"name" gorm:"column:name"` Phone string `json:"phone" gorm:"column:phone"` Mail string `json:"mail" gorm:"column:mail"` Account string `json:"account" gorm:"column:account"` } // buildUserFeedbackWhere 拼筛选条件。表别名 f = userfeedback,u = user。 func buildUserFeedbackWhere(req *userFeedbackListReq) (string, []interface{}) { conds := make([]string, 0, 4) args := make([]interface{}, 0, 8) if kw := strings.TrimSpace(req.User); kw != "" { like := "%" + kw + "%" conds = append(conds, "(f.uid = ? OR u.phone LIKE ? OR u.mail LIKE ? OR u.name LIKE ? OR u.account LIKE ?)") args = append(args, kw, like, like, like, like) } if kw := strings.TrimSpace(req.Content); kw != "" { conds = append(conds, "f.message LIKE ?") args = append(args, "%"+kw+"%") } if req.Start > 0 { conds = append(conds, "f.createtime >= ?") args = append(args, req.Start) } if req.End > 0 { conds = append(conds, "f.createtime < ?") args = append(args, req.End) } if len(conds) == 0 { return "1=1", args } return strings.Join(conds, " AND "), args } // getUserFeedbacks 所选应用业务库里的用户反馈,按提交时间倒序。 func (this *serverComp) getUserFeedbacks(c *gin.Context) { appId := parseAppId(c.GetHeader("X-App-Id")) if !this.requireAppScope(c, appId) { return } conn, err := this.module.registry.getServiceDB(appId) if err != nil { writeErr(c, pb.ErrorCode_DBError, err.Error()) return } req := &userFeedbackListReq{} _ = c.ShouldBindJSON(req) if req.PageSize <= 0 { req.PageSize = 20 } if req.PageSize > userListPageMax { req.PageSize = userListPageMax } if req.Page < 0 { req.Page = 0 } where, args := buildUserFeedbackWhere(req) base := conn.Table(comm.TableUserFeedback+" AS f"). Joins("LEFT JOIN `"+comm.TableUser+"` AS u ON u.uid = f.uid"). Where(where, args...) var total int64 if err := base.Count(&total).Error; err != nil { writeErr(c, pb.ErrorCode_DBError, err.Error()) return } rows := make([]*userFeedbackItem, 0, req.PageSize) if total > 0 { // Count 已经用过这条链,再查要重新起一条,否则 Limit 会叠在已执行的语句上。 if err := conn.Table(comm.TableUserFeedback+" AS f"). Select("f.id, f.uid, f.message, f.version, f.phonemodel, f.channel, f.createtime, u.name, u.phone, u.mail, u.account"). Joins("LEFT JOIN `"+comm.TableUser+"` AS u ON u.uid = f.uid"). Where(where, args...). Order("f.createtime DESC, f.id DESC"). Limit(req.PageSize).Offset(req.Page * req.PageSize). Find(&rows).Error; err != nil { writeErr(c, pb.ErrorCode_DBError, err.Error()) return } } writeOK(c, gin.H{"items": rows, "total": total, "page": req.Page, "page_size": req.PageSize}) }