From 5f9908195fcb4fcde52fa591de52403a52788930 Mon Sep 17 00:00:00 2001 From: summer <> Date: Thu, 16 Oct 2025 18:48:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(1.0):=20=E6=96=B0=E5=A2=9E=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=88=97=E8=A1=A8=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs.go | 119 ++++++++++++++++++++++++++ docs/swagger.json | 119 ++++++++++++++++++++++++++ docs/swagger.yaml | 81 ++++++++++++++++++ internal/api/app/app_user_list.go | 137 ++++++++++++++++++++++++++++++ internal/code/code.go | 1 + internal/code/zh-cn.go | 1 + internal/router/router.go | 1 + 7 files changed, 459 insertions(+) create mode 100755 internal/api/app/app_user_list.go diff --git a/docs/docs.go b/docs/docs.go index bf55fdc..6f14299 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -469,6 +469,77 @@ const docTemplate = `{ } } }, + "/admin/app/users": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "小程序用户列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.小程序" + ], + "summary": "小程序用户列表", + "parameters": [ + { + "type": "string", + "description": "小程序ID", + "name": "app_id", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "用户昵称", + "name": "user_name", + "in": "query" + }, + { + "type": "string", + "description": "用户ID", + "name": "user_id", + "in": "query" + }, + { + "type": "integer", + "default": 1, + "description": "当前页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页返回的数据量,最多 100 条", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.userListResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, "/admin/app/{id}": { "put": { "security": [ @@ -1061,6 +1132,54 @@ const docTemplate = `{ } } }, + "app.userListData": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "user_avatar": { + "description": "用户头像", + "type": "string" + }, + "user_id": { + "description": "用户ID", + "type": "string" + }, + "user_mobile": { + "description": "用户手机号", + "type": "string" + }, + "user_name": { + "description": "用户昵称", + "type": "string" + } + } + }, + "app.userListResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.userListData" + } + }, + "page": { + "description": "当前页码", + "type": "integer" + }, + "page_size": { + "description": "每页返回的数据量", + "type": "integer" + }, + "total": { + "description": "符合查询条件的总记录数", + "type": "integer" + } + } + }, "code.Failure": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 626064a..968277f 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -461,6 +461,77 @@ } } }, + "/admin/app/users": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "小程序用户列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.小程序" + ], + "summary": "小程序用户列表", + "parameters": [ + { + "type": "string", + "description": "小程序ID", + "name": "app_id", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "用户昵称", + "name": "user_name", + "in": "query" + }, + { + "type": "string", + "description": "用户ID", + "name": "user_id", + "in": "query" + }, + { + "type": "integer", + "default": 1, + "description": "当前页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页返回的数据量,最多 100 条", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.userListResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, "/admin/app/{id}": { "put": { "security": [ @@ -1053,6 +1124,54 @@ } } }, + "app.userListData": { + "type": "object", + "properties": { + "created_at": { + "description": "创建时间", + "type": "string" + }, + "user_avatar": { + "description": "用户头像", + "type": "string" + }, + "user_id": { + "description": "用户ID", + "type": "string" + }, + "user_mobile": { + "description": "用户手机号", + "type": "string" + }, + "user_name": { + "description": "用户昵称", + "type": "string" + } + } + }, + "app.userListResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.userListData" + } + }, + "page": { + "description": "当前页码", + "type": "integer" + }, + "page_size": { + "description": "每页返回的数据量", + "type": "integer" + }, + "total": { + "description": "符合查询条件的总记录数", + "type": "integer" + } + } + }, "code.Failure": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index fcd4463..5678958 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -148,6 +148,40 @@ definitions: description: 提示信息 type: string type: object + app.userListData: + properties: + created_at: + description: 创建时间 + type: string + user_avatar: + description: 用户头像 + type: string + user_id: + description: 用户ID + type: string + user_mobile: + description: 用户手机号 + type: string + user_name: + description: 用户昵称 + type: string + type: object + app.userListResponse: + properties: + list: + items: + $ref: '#/definitions/app.userListData' + type: array + page: + description: 当前页码 + type: integer + page_size: + description: 每页返回的数据量 + type: integer + total: + description: 符合查询条件的总记录数 + type: integer + type: object code.Failure: properties: code: @@ -765,6 +799,53 @@ paths: summary: 获取意图关键字列表 tags: - 管理端.意图关键字 + /admin/app/users: + get: + consumes: + - application/json + description: 小程序用户列表 + parameters: + - description: 小程序ID + in: query + name: app_id + required: true + type: string + - description: 用户昵称 + in: query + name: user_name + type: string + - description: 用户ID + in: query + name: user_id + type: string + - default: 1 + description: 当前页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页返回的数据量,最多 100 条 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.userListResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 小程序用户列表 + tags: + - 管理端.小程序 /admin/apps: get: consumes: diff --git a/internal/api/app/app_user_list.go b/internal/api/app/app_user_list.go new file mode 100755 index 0000000..19ec0f3 --- /dev/null +++ b/internal/api/app/app_user_list.go @@ -0,0 +1,137 @@ +package app + +import ( + "fmt" + "net/http" + + "mini-chat/internal/code" + "mini-chat/internal/pkg/core" + "mini-chat/internal/pkg/timeutil" + "mini-chat/internal/pkg/validation" + + "gorm.io/gorm" +) + +type userListRequest struct { + AppID string `form:"app_id"` // 小程序ID + UserID string `form:"user_id"` // 用户ID + UserName string `form:"user_name"` // 用户昵称 + Page int `form:"page"` // 当前页码,默认为第一页 + PageSize int `form:"page_size"` // 每页返回的数据量 +} + +type userListData struct { + UserID string `json:"user_id"` // 用户ID + UserName string `json:"user_name"` // 用户昵称 + UserMobile string `json:"user_mobile"` // 用户手机号 + UserAvatar string `json:"user_avatar"` // 用户头像 + CreatedAt string `json:"created_at"` // 创建时间 +} + +type userListResponse struct { + Page int `json:"page"` // 当前页码 + PageSize int `json:"page_size"` // 每页返回的数据量 + Total int64 `json:"total"` // 符合查询条件的总记录数 + List []userListData `json:"list"` +} + +// UserPageList 小程序用户列表 +// @Summary 小程序用户列表 +// @Description 小程序用户列表 +// @Tags 管理端.小程序 +// @Accept json +// @Produce json +// @Param app_id query string true "小程序ID" +// @Param user_name query string false "用户昵称" +// @Param user_id query string false "用户ID" +// @Param page query int true "当前页码" default(1) +// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) +// @Success 200 {object} userListResponse +// @Failure 400 {object} code.Failure +// @Router /admin/app/users [get] +// @Security LoginVerifyToken +func (h *handler) UserPageList() core.HandlerFunc { + return func(ctx core.Context) { + req := new(userListRequest) + res := new(userListResponse) + + 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.ListAppUserError, + fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListAppUserError)), + )) + return + } + + query := h.readDB.AppUser.WithContext(ctx.RequestContext()).Where(h.readDB.AppUser.AppID.Eq(req.AppID)) + + if req.UserID != "" { + query = query.Where(h.readDB.AppUser.UserID.Eq(req.UserID)) + } + + if req.UserName != "" { + query = query.Where(h.readDB.AppUser.UserName.Like(fmt.Sprintf("%%%s%%", req.UserName))) + } + + listQueryDB := query.Session(&gorm.Session{}) + countQueryDB := query.Session(&gorm.Session{}) + + resultData, err := listQueryDB. + Order(h.readDB.AppUser.ID.Desc()). + Limit(req.PageSize). + Offset((req.Page - 1) * req.PageSize).Find() + if err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ListAppUserError, + fmt.Sprintf("%s:%s", code.Text(code.ListAppUserError), err.Error())), + ) + return + } + + count, err := countQueryDB.Count() + if err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ListAppUserError, + fmt.Sprintf("%s:%s", code.Text(code.ListAppUserError), err.Error())), + ) + return + } + + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = count + res.List = make([]userListData, len(resultData)) + + for k, v := range resultData { + res.List[k] = userListData{ + UserID: v.UserID, + UserName: v.UserName, + UserMobile: v.UserMobile, + UserAvatar: v.UserAvatar, + CreatedAt: timeutil.FriendlyTime(v.CreatedAt), + } + } + + ctx.Payload(res) + } +} diff --git a/internal/code/code.go b/internal/code/code.go index 5f77b6f..d72f6af 100644 --- a/internal/code/code.go +++ b/internal/code/code.go @@ -27,6 +27,7 @@ const ( ListAppError = 20203 ModifyAppError = 20204 CreateAppUserError = 20205 + ListAppUserError = 20206 CreateKeywordError = 20301 ListKeywordError = 20302 diff --git a/internal/code/zh-cn.go b/internal/code/zh-cn.go index 551331e..3a2fbb4 100644 --- a/internal/code/zh-cn.go +++ b/internal/code/zh-cn.go @@ -13,6 +13,7 @@ var zhCNText = map[int]string{ ListAppError: "获取小程序列表失败", ModifyAppError: "修改小程序失败", CreateAppUserError: "创建用户失败", + ListAppUserError: "获取用户列表失败", CreateKeywordError: "创建关键字失败", DeleteKeywordError: "删除关键字失败", diff --git a/internal/router/router.go b/internal/router/router.go index 396824d..6fc50f8 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -82,6 +82,7 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo, cron cron.Server) (co adminAuthApiRouter.PUT("/app/keyword/material/:id", keywordHandler.ModifyKeywordMaterial()) // 修改意图关键字素材 adminAuthApiRouter.GET("/app/keyword/materials", keywordHandler.KeywordMaterialPageList()) // 获取意图关键字素材列表 + adminAuthApiRouter.GET("/app/users", appHandler.UserPageList()) // 获取小程序用户列表 adminAuthApiRouter.POST("/send_message", messageHandler.AdminSendMessage()) // 发送消息 }