Skip to content

Commit

Permalink
完善个人中心
Browse files Browse the repository at this point in the history
  • Loading branch information
Calcium-Ion committed Nov 21, 2023
1 parent fa45f3b commit fd57a1d
Show file tree
Hide file tree
Showing 9 changed files with 806 additions and 486 deletions.
59 changes: 59 additions & 0 deletions controller/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func setupLogin(user *model.User, c *gin.Context) {
DisplayName: user.DisplayName,
Role: user.Role,
Status: user.Status,
Group: user.Group,
}
c.JSON(http.StatusOK, gin.H{
"message": "",
Expand Down Expand Up @@ -284,6 +285,42 @@ func GenerateAccessToken(c *gin.Context) {
return
}

type TransferAffQuotaRequest struct {
Quota int `json:"quota" binding:"required"`
}

func TransferAffQuota(c *gin.Context) {
id := c.GetInt("id")
user, err := model.GetUserById(id, true)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
tran := TransferAffQuotaRequest{}
if err := c.ShouldBindJSON(&tran); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
err = user.TransferAffQuotaToQuota(tran.Quota)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "划转失败 " + err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "划转成功",
})
}

func GetAffCode(c *gin.Context) {
id := c.GetInt("id")
user, err := model.GetUserById(id, true)
Expand Down Expand Up @@ -330,6 +367,28 @@ func GetSelf(c *gin.Context) {
return
}

func GetUserModels(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
id = c.GetInt("id")
}
user, err := model.GetUserById(id, true)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
models := model.GetGroupModels(user.Group)
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": models,
})
return
}

func UpdateUser(c *gin.Context) {
var updatedUser model.User
err := json.NewDecoder(c.Request.Body).Decode(&updatedUser)
Expand Down
10 changes: 10 additions & 0 deletions model/ability.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ type Ability struct {
Priority *int64 `json:"priority" gorm:"bigint;default:0;index"`
}

func GetGroupModels(group string) []string {
var abilities []Ability
DB.Where("`group` = ?", group).Find(&abilities)
models := make([]string, 0, len(abilities))
for _, ability := range abilities {
models = append(models, ability.Model)
}
return models
}

func GetRandomSatisfiedChannel(group string, model string) (*Channel, error) {
ability := Ability{}
groupCol := "`group`"
Expand Down
42 changes: 22 additions & 20 deletions model/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,28 +220,30 @@ func PostConsumeTokenQuota(tokenId int, userQuota int, quota int, preConsumedQuo
}

if sendEmail {
quotaTooLow := userQuota >= common.QuotaRemindThreshold && userQuota-(quota+preConsumedQuota) < common.QuotaRemindThreshold
noMoreQuota := userQuota-(quota+preConsumedQuota) <= 0
if quotaTooLow || noMoreQuota {
go func() {
email, err := GetUserEmail(token.UserId)
if err != nil {
common.SysError("failed to fetch user email: " + err.Error())
}
prompt := "您的额度即将用尽"
if noMoreQuota {
prompt = "您的额度已用尽"
}
if email != "" {
topUpLink := fmt.Sprintf("%s/topup", common.ServerAddress)
err = common.SendEmail(prompt, email,
fmt.Sprintf("%s,当前剩余额度为 %d,为了不影响您的使用,请及时充值。<br/>充值链接:<a href='%s'>%s</a>", prompt, userQuota, topUpLink, topUpLink))
if (quota + preConsumedQuota) != 0 {
quotaTooLow := userQuota >= common.QuotaRemindThreshold && userQuota-(quota+preConsumedQuota) < common.QuotaRemindThreshold
noMoreQuota := userQuota-(quota+preConsumedQuota) <= 0
if quotaTooLow || noMoreQuota {
go func() {
email, err := GetUserEmail(token.UserId)
if err != nil {
common.SysError("failed to send email" + err.Error())
common.SysError("failed to fetch user email: " + err.Error())
}
common.SysLog("user quota is low, consumed quota: " + strconv.Itoa(quota) + ", user quota: " + strconv.Itoa(userQuota))
}
}()
prompt := "您的额度即将用尽"
if noMoreQuota {
prompt = "您的额度已用尽"
}
if email != "" {
topUpLink := fmt.Sprintf("%s/topup", common.ServerAddress)
err = common.SendEmail(prompt, email,
fmt.Sprintf("%s,当前剩余额度为 %d,为了不影响您的使用,请及时充值。<br/>充值链接:<a href='%s'>%s</a>", prompt, userQuota, topUpLink, topUpLink))
if err != nil {
common.SysError("failed to send email" + err.Error())
}
common.SysLog("user quota is low, consumed quota: " + strconv.Itoa(quota) + ", user quota: " + strconv.Itoa(userQuota))
}
}()
}
}
}

Expand Down
54 changes: 53 additions & 1 deletion model/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ type User struct {
RequestCount int `json:"request_count" gorm:"type:int;default:0;"` // request number
Group string `json:"group" gorm:"type:varchar(32);default:'default'"`
AffCode string `json:"aff_code" gorm:"type:varchar(32);column:aff_code;uniqueIndex"`
AffCount int `json:"aff_count" gorm:"type:int;default:0;column:aff_count"`
AffQuota int `json:"aff_quota" gorm:"type:int;default:0;column:aff_quota"` // 邀请剩余额度
AffHistoryQuota int `json:"aff_history_quota" gorm:"type:int;default:0;column:aff_history"` // 邀请历史额度
InviterId int `json:"inviter_id" gorm:"type:int;column:inviter_id;index"`
}

Expand Down Expand Up @@ -77,6 +80,54 @@ func DeleteUserById(id int) (err error) {
return user.Delete()
}

func inviteUser(inviterId int) (err error) {
user, err := GetUserById(inviterId, true)
if err != nil {
return err
}
user.AffCount++
user.AffQuota += common.QuotaForInviter
user.AffHistoryQuota += common.QuotaForInviter
return DB.Save(user).Error
}

func (user *User) TransferAffQuotaToQuota(quota int) error {
// 检查quota是否小于最小额度
if float64(quota) < common.QuotaPerUnit {
return fmt.Errorf("转移额度最小为%s!", common.LogQuota(int(common.QuotaPerUnit)))
}

// 开始数据库事务
tx := DB.Begin()
if tx.Error != nil {
return tx.Error
}
defer tx.Rollback() // 确保在函数退出时事务能回滚

// 加锁查询用户以确保数据一致性
err := tx.Set("gorm:query_option", "FOR UPDATE").First(&user, user.Id).Error
if err != nil {
return err
}

// 再次检查用户的AffQuota是否足够
if user.AffQuota < quota {
return errors.New("邀请额度不足!")
}

// 更新用户额度
user.AffQuota -= quota
user.Quota += quota

// 保存用户状态
if err := tx.Save(user).Error; err != nil {
return err
}

// 提交事务
return tx.Commit().Error
}

func (user *User) Insert(inviterId int) error {
var err error
if user.Password != "" {
Expand All @@ -101,8 +152,9 @@ func (user *User) Insert(inviterId int) error {
RecordLog(user.Id, LogTypeSystem, fmt.Sprintf("使用邀请码赠送 %s", common.LogQuota(common.QuotaForInvitee)))
}
if common.QuotaForInviter > 0 {
_ = IncreaseUserQuota(inviterId, common.QuotaForInviter)
//_ = IncreaseUserQuota(inviterId, common.QuotaForInviter)
RecordLog(inviterId, LogTypeSystem, fmt.Sprintf("邀请用户赠送 %s", common.LogQuota(common.QuotaForInviter)))
_ = inviteUser(inviterId)
}
}
return nil
Expand Down
2 changes: 2 additions & 0 deletions router/api-router.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ func SetApiRouter(router *gin.Engine) {
selfRoute.Use(middleware.UserAuth())
{
selfRoute.GET("/self", controller.GetSelf)
selfRoute.GET("/models", controller.GetUserModels)
selfRoute.PUT("/self", controller.UpdateSelf)
selfRoute.DELETE("/self", controller.DeleteSelf)
selfRoute.GET("/token", controller.GenerateAccessToken)
selfRoute.GET("/aff", controller.GetAffCode)
selfRoute.POST("/topup", controller.TopUp)
selfRoute.POST("/pay", controller.RequestEpay)
selfRoute.POST("/amount", controller.RequestAmount)
selfRoute.POST("/aff_transfer", controller.TransferAffQuota)
}

adminRoute := userRoute.Group("/")
Expand Down
Loading

0 comments on commit fd57a1d

Please sign in to comment.