Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

1049 lines
35 KiB
Go

package userctrl
import (
"91porn-server/app/appg"
"91porn-server/app/middleware/authuser"
"91porn-server/app/service/commentser"
"91porn-server/app/service/filterser"
"91porn-server/app/service/notiser"
"91porn-server/app/service/proxyser"
"91porn-server/app/service/smsser"
"91porn-server/app/service/userser"
"91porn-server/common"
"91porn-server/common/constant"
"91porn-server/common/log"
"91porn-server/common/stderr"
"91porn-server/common/truthutil"
v10 "91porn-server/common/v10"
"91porn-server/common/ysphone"
"91porn-server/common/ysqr"
"91porn-server/models/commod"
"91porn-server/models/v/cmtmod"
"91porn-server/models/v/faqmod"
"91porn-server/models/v/settingmod"
"91porn-server/models/v/usermod"
"91porn-server/models/v/vidmod"
"91porn-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)
}
// ModifySetting doc
// @Summary 用户模块 - 修改配置信息
// @Description 用户修改配置信息
// @Tags user
// @Param privateLetters formData bool false "私信"
// @Param followWroks formData bool false "关注人的作品"
// @Param followInteraction formData bool false "关注人的随拍"
// @Param recommend formData bool false "作品推荐"
// @Param liveRemind formData bool false "开播提醒"
// @Param dynamicCover formData bool false "动态封面"
// @Param preUpload formData bool false "提前上传"
// @Param blackGround formData string false "背景图"
// @Param watch formData integer false "谁可以看"
// @Param reply formData integer false "谁可以回复"
// @Param watchMultiFlash formData bool false "允许好友在多闪内查看我的随拍"
// @Param privateAccount formData bool false "私密账号"
// @Param selfRecommended formData bool false "允许将我推荐给好友"
// @Param message formData integer false "谁可以发消息给我"
// @Param watchILike formData integer false "谁可以看我的喜欢列表"
// @Param blackGround formData string false "背景图"
// @Param watch formData integer false "谁可以看"
// @Param reply formData integer false "谁可以回复"
// @Param watchMultiFlash formData bool false "允许好友在多闪内查看我的随拍"
// @Param privateAccount formData bool false "私密账号"
// @Param selfRecommended formData bool false "允许将我推荐给好友"
// @Param message formData integer false "谁可以发消息给我"
// @Param watchILike formData integer false "谁可以看我的喜欢列表"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/setting [post]
func ModifySetting(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, nil)
return
}
set := settingmod.SettingSelector{}
if err = ctx.ShouldBind(&set); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, err.Error())
return
}
if err = settingmod.UpdateSetting(uid, set); err != nil {
common.ServeJSON(ctx, stderr.ErrServerUnavailable, err.Error())
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)
}
// ISetting doc
// @Summary 用户模块 - 配置信息查询
// @Description 用户设置信息查询
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/setting [get]
func ISetting(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
setting, err := settingmod.FindSetting(uid)
if err != nil {
common.ServeJSON(ctx, stderr.ErrServerUnavailable, err)
return
}
common.ServeJSON(ctx, stderr.Success, setting)
}
// 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)
}
// PublishNum doc
// @Summary 我的模块 - 用户发布的帖子数量
// @Description 作品-用户发布的帖子数量
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param q body userser.PublishNumReq true "参数"
// @Success 200 {object} userser.PublishNumRep 操作成功
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/publish/num [get]
func PublishNum(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
req := userser.PublishNumReq{}
rep, err := req.GetUserPublishNum(uid)
if err != nil {
common.ServeJSON(ctx, stderr.Failure, err)
return
}
common.ServeJSON(ctx, stderr.Success, rep)
}
// 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)
}
// AutoLocate doc
// @Summary 自动定位
// @Description 根据IP自动定位
// @Tags 用户管理
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {string} json "{"msg": "操作成功", "date": {}}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mime/autoLocate [get]
func AutoLocate(c *gin.Context) {
ip := common.GetIP(c)
city, province := common.GetLocationByIP(ip)
common.ServeJSON(c, stderr.Success, gin.H{"city": city, "province": province})
}
// 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())
}
// Inviter doc
// @Summary 获取邀请者
// @Description 邀请绑定
// @Tags 用户
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {string} json "{"msg": "操作成功", "content": ""}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/inviter [post]
func Inviter(ctx *gin.Context) {
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, err)
return
}
inviter, err := proxyser.GetInv(uid)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNetWorkBusy, " user Get Inviter fail error: "+err.Error())
return
}
common.ServeJSON(ctx, stderr.Success, gin.H{"inviter": inviter})
}
// Announce doc
// @Summary 会员中心跑马灯
// @Description 会员中心跑马灯
// @Tags 用户
// @Accept mpfd,json
// @Produce json,html
// @Success 200 {string} json "{"msg": "操作成功", "content": ""}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /api/app/mine/announce [get]
func Announce(ctx *gin.Context) {
code, data := annouser.GetAnnounceListApi()
common.ServeJSON(ctx, code, data)
}
// 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)
}
// MobileVerify 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": "操作成功","data":"加密串"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/resetpassword/mobileverify [post]
func MobileVerify(ctx *gin.Context) {
var args struct {
Mobile string `json:"mobile" form:"mobile"`
Email string `json:"email" form:"email"`
Code string `json:"code" form:"code" binding:"required"`
}
if err := ctx.ShouldBind(&args); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
if args.Email == "" && args.Mobile == "" {
common.ServeJSON(ctx, stderr.ErrInvalidRequest, nil)
return
}
if code := notiser.VerifyCaptchaCode(ctx, args.Mobile, args.Email, args.Code); code != stderr.Success {
common.ServeJSON(ctx, stderr.ErrCaptchaInvalid, nil)
return
}
code, str := userser.GenResetWorld(ctx, args.Mobile, args.Email)
common.ServeJSON(ctx, code, str)
}
// ResetPassWord doc
// @Summary 找回密码
// @Description 找回密码。邮箱、手机号
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param token body string true "加密字符串"
// @Param string body string true "密码"
// @Success 200 {string} string "操作成功"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/resetpassword [post]
func ResetPassWord(ctx *gin.Context) {
var args struct {
Token string `json:"token" form:"token" binding:"required"`
Password string `json:"passWord" form:"passWord" binding:"required"`
}
if err := ctx.ShouldBind(&args); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
code := userser.ResetPassword(ctx, args.Token, args.Password)
common.ServeJSON(ctx, code, nil)
}
// Register doc
// @Summary 注册
// @Description 注册 支持手机号、邮箱、账号
// @Tags user
// @Accept mpfd,json
// @Produce json,html
// @Param request body userser.RegisterRequestH5 true "request"
// @Success 200 {string} json "{"msg": "操作成功"}"
// @Failure 400 {string} json "{"msg": "操作失败"}"
// @Router /mine/register [post]
func Register(ctx *gin.Context) {
ua, err := common.GetUA(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
var args = userser.RegisterRequestH5{}
if err = ctx.ShouldBind(&args); err != nil {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
if args.Email == "" && args.Mobile == "" && args.Account == "" {
common.ServeJSON(ctx, stderr.ErrParamError, nil)
return
}
uid, err := common.GetUID(ctx)
if err != nil {
common.ServeJSON(ctx, stderr.ErrNoToken, nil)
return
}
u, code := userser.RegisterH5(ctx, uid, ua.SysType, args)
common.ServeJSON(ctx, code, u)
}
// 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})
}