🎫 feat: Enhance redemption code expiry handling & improve UI responsiveness
Backend • Introduced `validateExpiredTime` helper in `controller/redemption.go`; reused in both Add & Update endpoints to enforce “expiry time must not be earlier than now”, eliminating duplicated checks • Removed `RedemptionCodeStatusExpired` constant and all related references – expiry is now determined exclusively by the `expired_time` field for simpler, safer state management • Simplified `DeleteInvalidRedemptions`: deletes codes that are `used` / `disabled` or `enabled` but already expired, without relying on extra status codes • Controller no longer mutates `status` when listing or fetching redemption codes; clients derive expiry status from timestamp Frontend • Added reusable `isExpired` helper in `RedemptionsTable.js`; leveraged for: – status rendering (orange “Expired” tag) – action-menu enable/disable logic – row styling • Removed duplicated inline expiry logic, improving readability and performance • Adjusted toolbar layout: on small screens the “Clear invalid codes” button now wraps onto its own line, while “Add” & “Copy” remain grouped Result The codebase is now more maintainable, secure, and performant with no redundant constants, centralized validation, and cleaner UI behaviour across devices.
This commit is contained in:
@@ -21,6 +21,7 @@ type Redemption struct {
|
||||
Count int `json:"count" gorm:"-:all"` // only for api request
|
||||
UsedUserId int `json:"used_user_id"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index"`
|
||||
ExpiredTime int64 `json:"expired_time" gorm:"bigint"` // 过期时间,0 表示不过期
|
||||
}
|
||||
|
||||
func GetAllRedemptions(startIdx int, num int) (redemptions []*Redemption, total int64, err error) {
|
||||
@@ -131,6 +132,9 @@ func Redeem(key string, userId int) (quota int, err error) {
|
||||
if redemption.Status != common.RedemptionCodeStatusEnabled {
|
||||
return errors.New("该兑换码已被使用")
|
||||
}
|
||||
if redemption.ExpiredTime != 0 && redemption.ExpiredTime < common.GetTimestamp() {
|
||||
return errors.New("该兑换码已过期")
|
||||
}
|
||||
err = tx.Model(&User{}).Where("id = ?", userId).Update("quota", gorm.Expr("quota + ?", redemption.Quota)).Error
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -162,7 +166,7 @@ func (redemption *Redemption) SelectUpdate() error {
|
||||
// Update Make sure your token's fields is completed, because this will update non-zero values
|
||||
func (redemption *Redemption) Update() error {
|
||||
var err error
|
||||
err = DB.Model(redemption).Select("name", "status", "quota", "redeemed_time").Updates(redemption).Error
|
||||
err = DB.Model(redemption).Select("name", "status", "quota", "redeemed_time", "expired_time").Updates(redemption).Error
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -183,3 +187,9 @@ func DeleteRedemptionById(id int) (err error) {
|
||||
}
|
||||
return redemption.Delete()
|
||||
}
|
||||
|
||||
func DeleteInvalidRedemptions() (int64, error) {
|
||||
now := common.GetTimestamp()
|
||||
result := DB.Where("status IN ? OR (status = ? AND expired_time != 0 AND expired_time < ?)", []int{common.RedemptionCodeStatusUsed, common.RedemptionCodeStatusDisabled}, common.RedemptionCodeStatusEnabled, now).Delete(&Redemption{})
|
||||
return result.RowsAffected, result.Error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user