init: hgmj server initial commit

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 16:50:13 +08:00
co-authored by Claude Opus 4.7
commit 625e89c15d
1870 changed files with 254090 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
package userctrl
import "91jd-server/models/commod"
// PageRule 通用分页验证结构体
type PageRule struct {
UID uint64 `json:"uid" form:"uid"`
//hot 热度值排序;watch 最多播放;like 最多点赞(收藏);new 最新视频
Type string `json:"type" form:"type"`
// 点赞类型: SP:长视频 SHORT:短视频 COVER:图文帖子 PIC:图集帖子 SEED_LINK:种子/黄油帖子 TAG:标签 COMMENT:评论 video:动漫 image:漫画 text:小说"
LikeType string `json:"likeType" form:"likeType"`
//0 默认全部 1 长视频 2 短视频 3-帖子 4-图集
PlayTimeType int `json:"playTimeType" form:"playTimeType"`
commod.Page
}
var portrait = []string{
"image/gy/8j/hw/la/aa283b9a2c6c443883da2c6dec05c19a.jpeg",
"image/e5/oq/hd/hi/2a120f6ebb44468b92a1f0c55b4a475c.jpeg",
"image/tl/gc/lk/5p/96586678db814f579e6eaf8ef55165bc.jpeg",
"image/hm/21/19/57/e5c625d1a903453e8fc8e3e3575c860b.jpeg",
"image/0v/h7/g1/tb/f3d02445d42e49b7915b843aecfb7c7c.jpeg",
"image/en/fl/su/8w/d7e168beed5c4742be13cf998613d112.jpeg",
"image/25/2q/gh/fd/a122e79c556c40c1a61e4ad55219134f.jpeg",
"image/6h/2k/gs/5x/6fe68e9d41ae4cbda2a5e34e64ba4af9.jpeg",
"image/kz/2y/xv/a9/ad29c0e2fb7e43c282a9c1d4d70e1185.jpeg",
"image/1s/h3/hi/ht/1de64b74f1c34545ae8013553b12c6c1.jpeg",
"image/6n/os/7a/24/7e5031e18874496bb7481fbe27a85d34.jpeg",
"image/vo/g9/nj/l2/f288707eeb9041b8b471f0ac5f25fcdd.jpeg",
"image/of/cg/cb/zm/90280c2e0c2c4198b677c0e0430c3166.jpeg",
"image/ex/yb/so/l0/5011e1a5415c400783ab5d29d1d68129.jpeg",
"image/0b/4n/ct/hs/9d84d100aba340558f68e638e45c6203.jpeg",
"image/2b/bz/6w/g5/bbb4d6d1c0064491a5131a75a0d23546.jpeg",
"image/qf/n1/oq/m6/a29791ca041541c192205e1c82073398.jpeg",
"image/oa/u8/w3/f6/d149a55b4e894fbba332fa06889a091a.jpeg",
"image/ar/8x/9u/xw/e69e7be1a7174e6d96049b9b84888989.jpeg",
"image/g0/uu/64/mu/3bdcdd6c86a64b589bfcd0c9fac2d7da.jpeg",
"image/xa/a2/gs/dz/406b619f79684992837334ec2c21cffb.jpeg",
"image/eq/wo/4y/8e/749252631f5c40bda89d19150bfc661c.jpeg",
"image/ox/z3/3u/tr/227819454ccf4851b0905c2c74331394.jpeg",
"image/75/fj/s5/b4/afeeaada5460465982cc8539d7c1ff03.jpeg",
"image/jr/8v/e2/84/4e75fdfcf8404700b3f1e3b352ed45e0.jpeg",
"image/pd/1s/ld/mp/779ce7c27d71446188b40cdf11774df0.jpeg",
"image/nb/92/0s/gc/f158a9166e3648c8be5de39259556caa.jpeg",
"image/kh/bj/aa/zp/a5088e99962049a398f92033838c97ad.jpeg",
}
+40
View File
@@ -0,0 +1,40 @@
package userctrl
import (
"91jd-server/app/service/userser"
"91jd-server/common"
"91jd-server/common/stderr"
"github.com/gin-gonic/gin"
)
// ConsumePrivilege doc
// @Summary 消耗预售卡预付权益
// @Description 消耗预售卡预付权益
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param q body userser.ConsumeReq false "请求参数"
// @Success 200 {string} string "操作成功"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/privilege/consume [post]
func ConsumePrivilege(ctx *gin.Context) {
// 获取用户当前配置
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
var args userser.ConsumeReq
if err := ctx.ShouldBind(&args); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
err = userser.Consume(uid, args.PrivilegeType, args.Count)
if err != nil {
common.ServeJSON(ctx, stderr.Failure, nil)
}
common.ServeJSON(ctx, stderr.Success, nil)
}
+807
View File
@@ -0,0 +1,807 @@
package userctrl
import (
"91jd-server/app/appg"
"91jd-server/app/middleware/authuser"
"91jd-server/app/service/commentser"
"91jd-server/app/service/filterser"
"91jd-server/app/service/proxyser"
"91jd-server/app/service/smsser"
"91jd-server/app/service/userser"
"91jd-server/common"
"91jd-server/common/constant"
"91jd-server/common/log"
"91jd-server/common/stderr"
"91jd-server/common/truthutil"
v10 "91jd-server/common/v10"
"91jd-server/common/ysphone"
"91jd-server/common/ysqr"
"91jd-server/models/commod"
"91jd-server/models/v/cmtmod"
"91jd-server/models/v/faqmod"
"91jd-server/models/v/usermod"
"91jd-server/models/v/vidmod"
"91jd-server/web/service/annouser"
"strconv"
"strings"
"github.com/gin-gonic/gin"
)
var devIDNilValue = "00000000-0000-0000-0000-000000000000"
var maxNameRune = 12
// MobileBind doc
// @Summary 用户模块 - 绑定手机号
// @Description 绑定手机号
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param mobile formData string true "电话号码"
// @Param code formData string true "验证码"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/mobileBind [post]
func MobileBind(ctx *gin.Context) {
var args struct {
Mobile string `json:"mobile" form:"mobile" binding:"required"`
Code string `json:"code" form:"code" binding:"required"`
PassWord string `json:"passWord"`
}
if err := ctx.ShouldBind(&args); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
args.Mobile = strings.TrimSpace(args.Mobile)
if !v10.IsGlobalizationPhoneNumber(args.Mobile) {
common.ServeJSON(ctx, stderr.ErrMobileInvalid, nil)
return
}
args.Mobile = ysphone.FormatPhoneNumber(args.Mobile)
verifyCode := smsser.VerifySmsCode(args.Mobile, args.Code)
if verifyCode != stderr.Success {
common.ServeJSON(ctx, verifyCode, nil)
return
}
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, nil)
return
}
code := userser.MobileBind(uid, args.Mobile, args.PassWord)
common.ServeJSON(ctx, code, nil)
}
// MobileLogin doc
// @Summary 用户模块 - 使用机号登陆
// @Description 使用手机号登陆
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param mobile formData string true "电话号码"
// @Param code formData string true "验证码"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/mobileLoginOnly [post]
func MobileLogin(ctx *gin.Context) {
var args struct {
Mobile string `json:"mobile" form:"mobile" binding:"required"`
Code string `json:"code" form:"code" binding:"required"`
}
if err := ctx.ShouldBind(&args); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
args.Mobile = ysphone.FormatPhoneNumber(strings.TrimSpace(args.Mobile))
fakeMobilePrefixLen := len(constant.FakeMobilePrefix)
if len(args.Mobile) < fakeMobilePrefixLen {
common.ServeJSON(ctx, stderr.ErrMobileInvalid, nil)
return
}
//非马甲手机号 需要校验
if args.Mobile[:fakeMobilePrefixLen] != constant.FakeMobilePrefix {
if !v10.IsGlobalizationPhoneNumber(args.Mobile) {
common.ServeJSON(ctx, stderr.ErrMobileInvalid, nil)
return
}
verifyCode := smsser.VerifySmsCode(args.Mobile, args.Code)
if verifyCode != stderr.Success {
common.ServeJSON(ctx, verifyCode, "")
return
}
} else {
//马甲账号验证1 验证码
if args.Code != appg.Static.VerifyCodeForFake {
common.ServeJSON(ctx, stderr.ErrCaptchaInvalid, "")
return
}
}
ip := common.GetIP(ctx)
ua, _ := common.GetUA(ctx)
userInfo, code := userser.MobileLoginOnly(ip, args.Mobile, ua)
if code == stderr.Success {
userInfo.LoginType = usermod.MobileLogin
common.ServeJSON(ctx, code, gin.H{"token": userInfo.Token, "userInfo": userInfo})
return
}
if code == stderr.ErrAccessForbid {
common.ServeJSON(ctx, code, gin.H{"uid": userInfo.UID, "reason": userInfo.LockReason})
return
}
common.ServeJSON(ctx, code, nil)
}
// Modify doc
// @Summary 用户模块 - 修改信息
// @Description 用户修改信息
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param gender formData string false "性别"
// @Param name formData string false "用户名称"
// @Param age formData integer false "年龄"
// @Param mobile formData string false "手机号"
// @Param password formData integer false "密码"
// @Param portrait formData string false "头像"
// @Param background formData string false "背景图"
// @Param status formData integer false "状态"
// @Param role formData string false "角色"
// @Param summary formData string false "简介"
// @Param region formData string false "地区"
// @Param promotionCode formData string false "推广码"
// @Param qRCode formData string false "二维码"
// @Param birthday formData string false "生日"
// @Param promotionCode formData string false "生日"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/info [post]
func Modify(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, nil)
return
}
set := usermod.UserModifyReq{}
if err = ctx.ShouldBind(&set); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
if set.AppLock != nil {
if len(*set.AppLock) != 4 {
common.ServeJSON(ctx, stderr.ErrParamError, "app_lock length invalid")
return
}
if _, err = strconv.ParseInt(*set.AppLock, 10, 64); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, "app_lock is not number string")
return
}
}
if set.Portrait != nil || set.Name != nil || set.Background != nil || set.Summary != nil {
u, err := usermod.FindUserByUID(uid)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, err.Error())
return
}
if u == nil {
common.ServeJSON(ctx, stderr.UserIsNotExists, "")
return
}
//if set.Portrait != nil && u.CreatedAt.After(time.Now().Add(-7*24*time.Hour)) {
// common.ServeJSON(ctx, stderr.UserActiveNotEnough, "")
// return
//}
if !u.IsPaidVIP() {
common.ServeJSON(ctx, stderr.NoVipPrivilege, "")
return
}
if set.Name != nil {
if len([]rune(*set.Name)) > maxNameRune {
common.ServeJSON(ctx, stderr.ErrUserNameTooLong, nil)
return
}
newName, err := filterser.TextFilter(*set.Name)
if err == nil {
// 检查合法性
if !truthutil.CheckIsValid(newName, 0) {
msg := map[string]interface{}{"msg": "昵称设置错误"}
common.ServeJsonWithExtra(ctx, stderr.Failure, nil, msg)
return
}
set.Name = &newName
}
name := strings.TrimSpace(*set.Name)
set.Name = &name
}
if set.Summary != nil {
newSummary, err := filterser.TextFilter(*set.Summary)
if err == nil {
// 检查合法性
if !truthutil.CheckIsValid(newSummary, 0) {
msg := map[string]interface{}{"msg": "个性签名设置错误"}
common.ServeJsonWithExtra(ctx, stderr.Failure, nil, msg)
return
}
set.Summary = &newSummary
}
}
}
if _, err = usermod.UpdateSelf(uid, set); err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, err)
return
}
common.ServeJSON(ctx, stderr.Success, nil)
}
// LoginWithDevice doc
// @Summary 用户模块 - 用户登陆
// @Description 登陆
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param devID formData string true "设备ID"
// @Param devType formData string true "设备型号"
// @Param sysType formData string true "系统类型" Enums(Android-10,IOS-13)
// @Param ver formData string true "app 应用版本号"
// @Param buildID formData string true "app 构建ID(包ID)"
// @Param channel formData string false "渠道"
// @Param promotionCode formData string false "推广码"
// @Param devToken formData string false "设备token"
// @Param cutInfos formData string false "剪切板信息"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/login [post]
func LoginWithDevice(ctx *gin.Context) {
token := ctx.Request.Header.Get("Authorization")
p := usermod.DevLoginP{}
if err := ctx.ShouldBind(&p); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err.Error())
return
}
if p.DevID == devIDNilValue {
common.ServeJSON(ctx, stderr.ErrParamError, "devID is nil")
return
}
if !common.IsNormalDevId(p.DevID) {
common.ServeJSON(ctx, stderr.ErrParamError, "devID is invalid")
return
}
ua, _ := common.GetUA(ctx)
ip := common.GetIP(ctx)
userInfo, code, loginType, err := userser.DeviceLogin(ip, p, token, ua)
if err != nil {
log.Warn("LoginWithDevice", log.E(err))
if code != 0 {
if code == stderr.ErrAccessForbid {
common.ServeJSON(ctx, code, gin.H{"uid": userInfo.UID, "reason": userInfo.LockReason})
return
}
common.ServeJSON(ctx, code, err.Error())
return
}
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, err.Error())
return
}
userInfo.LoginType = loginType
common.ServeJSON(ctx, stderr.Success, userInfo)
}
// MyRights doc
// @Summary 用户模块 - 用户权益查询
// @Description 用户权益,包括观影券
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {object} usermod.UserRights
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/rights [get]
func MyRights(c *gin.Context) {
uid, err := common.GetUID(c)
if err != nil {
common.ServeJSON(c, stderr.ErrNoToken, nil)
return
}
userRights, err := userser.MyRights(uid)
if err != nil {
common.ServeJSON(c, stderr.ErrNetWorkBusy, "")
return
}
log.Info("userRights info", log.Any("res", userRights))
common.ServeJSON(c, stderr.Success, userRights)
}
// Info doc
// @Summary 用户模块 - 基本信息查询
// @Description 用户基本信息查询
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param uid formData integer false "用户id(如果是查看自己页面则不传)"
// @Success 200 {object} usermod.UserRes "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/info [get]
func Info(ctx *gin.Context) {
uid, _ := common.GetUID(ctx)
var user struct {
UID uint64 `form:"uid" json:"uid"`
}
if err := ctx.ShouldBind(&user); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
if user.UID != 0 {
info, err := userser.OtherInfo(uid, user.UID)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, "")
return
}
common.ServeJSON(ctx, stderr.Success, info)
return
}
info, err := userser.Info(uid)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, "")
return
}
log.Debug("info", log.Any("info", info))
common.ServeJSON(ctx, stderr.Success, info)
}
// Collection doc
// @Summary 我的模块 - 我的帖子
// @Description 作品,传uid是获取所传uid的作品,不传是获取自己的作品
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param uid formData integer false "用户id"
// @Param pageSize formData int true "每页显示条数"
// @Param pageNumber formData int true "当前第几页"
// @Param uid formData uint64 false "用户id(查询其他用户使用,非必传)"
// @Param type formData string false "hot 热度值排序;new 最新视频"
// @Success 200 {object} userser.VideoListResp 操作成功
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/collection [get]
func Collection(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
pgR := PageRule{}
if err = ctx.ShouldBind(&pgR); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
var collection []*vidmod.VideoInfoResp
var hasNext bool
var total int64
if pgR.UID == 0 {
collection, total, hasNext, err = userser.IVList(uid, pgR.Type, pgR.PageSize, pgR.PageNumber, pgR.PlayTimeType)
} else {
collection, total, hasNext, err = userser.HisVList(uid, pgR.UID, pgR.PageSize, pgR.PageNumber, pgR.Type, pgR.PlayTimeType)
}
if err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, err)
return
}
resp := userser.VideoListResp{
List: collection,
Total: total,
HasNext: hasNext,
}
common.ServeJSON(ctx, stderr.Success, resp)
}
// PublishList doc
// @Summary 我的模块 - 用户发布的帖子列表
// @Description 作品-用户发布的帖子列表
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param q body userser.PublishWorkReq true "参数"
// @Success 200 {object} userser.PublishWorkRep 操作成功
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/publish [get]
func PublishList(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
req := userser.PublishWorkReq{}
if err = ctx.ShouldBind(&req); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
rep, err := req.GetUserPublishWorkList(uid)
if err != nil {
common.ServeJSON(ctx, stderr.Failure, err)
return
}
common.ServeJSON(ctx, stderr.Success, rep)
}
// PublishWorkDelete doc
// @Summary 我的模块 - 删除我发布但未通过审核的作品
// @Description 作品-删除我发布但未通过审核的作品
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param q body userser.PublishWorkDeleteReq true "参数"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/publish/delete [post]
func PublishWorkDelete(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
req := userser.PublishWorkDeleteReq{}
if err = ctx.ShouldBind(&req); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
err = req.UserPublishWorkDelete(uid)
if err != nil {
common.ServeJSON(ctx, stderr.Failure, err)
return
}
common.ServeJSON(ctx, stderr.Success, nil)
}
// BuyVidList doc
// @Summary 我的模块 - 购买的视频
// @Description 我购买的视频
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param uid formData integer false "用户id"
// @Param pageSize formData int true "每页显示条数"
// @Param pageNumber formData int true "当前第几页"
// @Param newsType formData string true "购买类型 SP,SHORT,COVER,PIC,SEED_LINK"
// @Success 200 {object} userser.VideoListResp 操作成功
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/buyVid [get]
func BuyVidList(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
var p struct {
UID uint64 `form:"uid" json:"uid"`
PageNumber int64 `form:"pageNumber" json:"pageNumber" binding:"required"`
PageSize int64 `form:"pageSize" json:"pageSize" binding:"required"`
NewsType string `form:"newsType" json:"newsType"`
}
if err = ctx.ShouldBind(&p); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
vList, total, hasNext, err := userser.BuyVidList(uid, p.UID, p.NewsType, p.PageSize, p.PageNumber)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, err)
return
}
resp := userser.VideoListResp{
List: vList,
Total: total,
HasNext: hasNext,
}
common.ServeJSON(ctx, stderr.Success, resp)
}
// Like doc
// @Summary 我的模块 - 我的喜欢
// @Description 喜欢,传uid是获取所传uid的喜欢,不传是获取自己的喜欢
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param q query userser.GetUserLikeReq true "每页显示条数"
// @Success 200 {object} userser.ILikeListRep 操作成功
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/like [get]
func Like(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
req := userser.GetUserLikeReq{}
err = ctx.ShouldBind(&req)
if err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
vList, hasNext, err := userser.UserLikesVidList(uid, &req)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, nil)
return
}
resp := userser.ILikeListRep{
List: vList,
HasNext: hasNext,
}
common.ServeJSON(ctx, stderr.Success, resp)
return
}
// Comment doc
// @Summary 我的模块 - 我的评论
// @Description 我的评论
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param pageSize formData int true "每页显示条数"
// @Param pageNumber formData int true "当前第几页"
// @Success 200 {object} userser.VideoListResp 操作成功
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/comment [get]
func Comment(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
pgR := PageRule{}
err = ctx.ShouldBind(&pgR)
if err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
list, hasNext, err := commentser.GetMyCmtList(uid, pgR.Page)
if err != nil {
common.ServeJSON(ctx, stderr.ErrDbQueryError, err)
return
}
common.ServeJSON(ctx, stderr.Success, &cmtmod.MyCmtResp{
List: list,
HasNext: hasNext,
})
}
// FaqList doc
// @Summary 用户常见问题
// @Description 用户常见问题列表
// @Tags 用户管理
// @Accept mpfd,json
// @Produce json,html
// @Param category query string false "问题类型"
// @Param pageNumber query integer true "当前页"
// @Param pageSize query integer true "每页条数"
// @Success 200 {string} json "{"msg": "操作成功", "date": {}}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/faq/list [get]
func FaqList(c *gin.Context) {
var args struct {
Category string `form:"cate" json:"cate" binding:"required"`
commod.Page
}
if err := c.ShouldBind(&args); err != nil {
common.ServeJSON(c, stderr.ErrParamError, "web user FaqList arg error "+err.Error())
return
}
stdQuery := commod.StdQuery{Page: &commod.PageBy{Num: args.PageNumber, Size: args.PageSize}}
page, err := userser.FaqList(args.Category, stdQuery)
if err != nil {
common.ServeJSON(c, stderr.ErrNetWorkBusy, "web user PlayRecord error: "+err.Error())
return
}
common.ServeJSON(c, stderr.Success, page)
}
// FaqCateList doc
// @Summary 用户常见问题
// @Description 用户常见问题分类列表
// @Tags 用户管理
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {string} json "{"msg": "操作成功", "date": {}}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /web/user/faq/cate/list [get]
func FaqCateList(c *gin.Context) {
page, err := faqmod.FaqCateList()
if err != nil {
common.ServeJSON(c, stderr.ErrNetWorkBusy, "web user FaqCateList error: "+err.Error())
return
}
common.ServeJSON(c, stderr.Success, page)
}
// QrCode doc
// @Summary 二维码
// @Description 二维码
// @Tags 用户管理
// @Accept mpfd,json
// @Produce json,html
// @Param Authorization header string true "user token"
// @Success 200 {string} json "{"msg": "操作成功", "content": ""}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/certificate/qr [get]
func QrCode(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
user, _ := usermod.FindUserByUID(uid)
if user == nil {
common.ServeJSON(ctx, stderr.AdminIsNotExist, "")
return
}
t := ysqr.Login
if actType, b := ctx.Get("actType"); b {
at, ok := actType.(ysqr.ActType)
if ok {
t = at
}
}
content := ysqr.Content{
UID: user.UID,
T: t,
LoginClaims: ysqr.LoginClaims{
DevID: user.DevID,
},
}
common.ServeJSON(ctx, stderr.Success, gin.H{
"content": content.String(authuser.GetTokenSecret()),
})
}
// Invite doc
// @Summary 邀请
// @Description 邀请绑定
// @Tags 用户
// @Accept mpfd,json
// @Produce json,html
// @Param promotionCode formData string true "邀请码"
// @Success 200 {string} json "{"msg": "操作成功", "content": ""}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/inviteBind [post]
func Invite(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
var p struct {
PromCode string `json:"promotionCode" bson:"promotionCode"` //推广码
}
if err = ctx.ShouldBind(&p); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
code := proxyser.InviteBind(uid, p.PromCode, true)
common.ServeJSON(ctx, code, code.Msg())
}
// AnnounceList doc
// @Summary 跑马灯列表
// @Description 跑马灯列表
// @Tags 用户
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {object} []annoumod.Announce "success"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/announce/list [get]
func AnnounceList(ctx *gin.Context) {
code, data := annouser.GetAnnounceList()
common.ServeJSON(ctx, code, data)
}
// LoginWithH5 doc
// @Summary 用户模块 - 注册用户接口
// @Description 手机注册登陆
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param request usermod.LoginWithH5 body object true "request"
// @Success 200 {object} usermod.UserRes "success"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/login/h5 [post]
func LoginWithH5(ctx *gin.Context) {
p := usermod.LoginWithH5{}
if err := ctx.ShouldBind(&p); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
// 仅允许 h5/ios 端登录注册,其余 sysType 一律拒绝
if p.SysType != "h5" && p.SysType != "ios" {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
// devID 以 web 开头的为攻击流量,直接拒绝(忽略大小写)
if strings.HasPrefix(strings.ToLower(p.DevID), "web") {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
ip := common.GetIP(ctx)
ua, err := common.GetUA(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
log.Info("login info", log.Any("ip", ip), log.Any("p", p), log.Any("ua", ua))
user, code, err := userser.H5Login(ctx, ip, p, ua)
if err != nil || code != stderr.Success {
log.ErrorX(ctx, "login h5 failed", log.Any("req", p), log.Any("ip", ip), log.E(err))
common.ServeJSON(ctx, code, nil)
return
}
common.ServeJSON(ctx, code, user)
}
// LoginByQRCode doc
// @Summary 用户模块 - 登录
// @Description H5用户通过二维码登录
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param request body usermod.LoginH5ByQRCode true "request"
// @Success 200 {object} usermod.UserRes "success"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/login/h5/qr [post]
func LoginByQRCode(ctx *gin.Context) {
req := usermod.LoginH5ByQRCode{}
if err := ctx.ShouldBind(&req); err != nil {
log.Error("bind request parameter failed")
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
user, err := userser.H5LoginByQRCode(ctx, req.Content, common.GetIP(ctx))
if err != stderr.Success {
common.ServeJSON(ctx, err, nil)
return
}
common.ServeJSON(ctx, stderr.Success, user)
}
// ExtractQRCode doc
// @Summary 解析二维码
// @Description 解析二维码
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {string} string "success"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/qrcode/extract [post]
func ExtractQRCode(ctx *gin.Context) {
file, err := ctx.FormFile("qrcode")
if err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err)
return
}
f, err := file.Open()
if err != nil {
common.ServeJSON(ctx, stderr.ErrInterServerError, err)
return
}
content, err := common.DecodeQRCode(f)
f.Close()
if err != nil {
common.ServeJSON(ctx, stderr.ErrInterServerError, err)
return
}
common.ServeJSON(ctx, stderr.Success, content)
}
// Portrait 头像列表
//
// @Summary 头像列表
// @Description 头像列表
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param Authorization header string true "user token"
// @Success 200 {string} json "{"msg": "操作成功", "content": ""}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/portrait [get]
func Portrait(ctx *gin.Context) {
common.ServeJSON(ctx, stderr.Success, gin.H{"data": portrait})
}