feat: integrate xxl-job-admin to implements automatic task scheduling

This commit is contained in:
RockYang
2024-03-22 13:47:16 +08:00
parent bf5e72b7e0
commit f7a565bb80
15 changed files with 2267 additions and 132 deletions

View File

@@ -85,6 +85,7 @@ const (
PowerRefund = PowerType(3) // 任务SD,MJ执行失败退款
PowerInvite = PowerType(4) // 邀请奖励
PowerReward = PowerType(5) // 众筹
PowerGift = PowerType(6) // 系统赠送
)
func (t PowerType) String() string {

View File

@@ -181,7 +181,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
var user model.User
res := h.DB.Model(&model.User{}).First(&user, session.UserId)
if res.Error != nil {
utils.ReplyMessage(ws, "非法用户,请联系管理员")
utils.ReplyMessage(ws, "未授权用户,您正在进行非法操作")
return res.Error
}
var userVo vo.User
@@ -203,12 +203,6 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
return nil
}
if userVo.Power <= 0 {
utils.ReplyMessage(ws, "您的对话次数已经用尽,请联系管理员或者充值点卡继续对话!")
utils.ReplyMessage(ws, ErrImg)
return nil
}
if userVo.ExpiredTime > 0 && userVo.ExpiredTime <= time.Now().Unix() {
utils.ReplyMessage(ws, "您的账号已经过期,请联系管理员!")
utils.ReplyMessage(ws, ErrImg)

View File

@@ -89,7 +89,7 @@ func (h *RewardHandler) Verify(c *gin.Context) {
Amount: exchange.Power,
Balance: user.Power + exchange.Power,
Mark: types.PowerAdd,
Model: "",
Model: "众筹支付",
Remark: fmt.Sprintf("众筹充值算力,金额:%f价格%f", item.Amount, h.App.SysConfig.PowerPrice),
CreatedAt: time.Now(),
})

View File

@@ -55,7 +55,7 @@ func (h *UserHandler) Register(c *gin.Context) {
// 检查验证码
var key string
if data.RegWay == "email" || data.RegWay == "mobile" {
if data.RegWay == "email" || data.RegWay == "mobile" || data.Code != "" {
key = CodeStorePrefix + data.Username
code, err := h.redis.Get(c, key).Result()
if err != nil || code != data.Code {

View File

@@ -40,12 +40,13 @@ func NewXXLJobExecutor(config *types.AppConfig, db *gorm.DB) *XXLJobExecutor {
func (e *XXLJobExecutor) Run() error {
e.executor.RegTask("ClearOrders", e.ClearOrders)
e.executor.RegTask("ResetVipPower", e.ResetVipPower)
e.executor.RegTask("ResetUserPower", e.ResetUserPower)
return e.executor.Run()
}
// ClearOrders 清理未支付的订单,如果没有抛出异常则表示执行成功
func (e *XXLJobExecutor) ClearOrders(cxt context.Context, param *xxl.RunReq) (msg string) {
logger.Debug("执行清理未支付订单...")
logger.Info("执行清理未支付订单...")
var sysConfig model.Config
res := e.db.Where("marker", "system").First(&sysConfig)
if res.Error != nil {
@@ -64,15 +65,17 @@ func (e *XXLJobExecutor) ClearOrders(cxt context.Context, param *xxl.RunReq) (ms
timeout := time.Now().Unix() - int64(config.OrderPayTimeout)
start := utils.Stamp2str(timeout)
// 这里不是用软删除,而是永久删除订单
res = e.db.Unscoped().Where("status != ? AND created_at < ?", types.OrderPaidSuccess, start).Delete(&model.Order{})
return fmt.Sprintf("Clear order successfully, affect rows: %d", res.RowsAffected)
res = e.db.Unscoped().Where("status IN ? AND created_at < ?", []types.OrderStatus{types.OrderNotPaid, types.OrderScanned}, start).Delete(&model.Order{})
logger.Infof("Clear order successfully, affect rows: %d", res.RowsAffected)
return "success"
}
// ResetVipPower 清理过期的 VIP 会员
// ResetVipPower 重置VIP会员算力
// 自动将 VIP 会员的算力补充到每月赠送的最大值
func (e *XXLJobExecutor) ResetVipPower(cxt context.Context, param *xxl.RunReq) (msg string) {
logger.Info("开始进行月底账号盘点...")
var users []model.User
res := e.db.Where("vip = ?", 1).Find(&users)
res := e.db.Where("vip", 1).Where("status", 1).Find(&users)
if res.Error != nil {
return "No vip users found"
}
@@ -90,23 +93,27 @@ func (e *XXLJobExecutor) ResetVipPower(cxt context.Context, param *xxl.RunReq) (
}
for _, u := range users {
if u.Power <= 0 {
u.Power = 0
// 处理过期的 VIP
if u.ExpiredTime > 0 && u.ExpiredTime <= time.Now().Unix() {
u.Vip = false
e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("vip", false)
continue
}
u.Power += config.VipMonthPower
// update user
tx := e.db.Updates(&u)
// 记录算力充值日志
tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", config.VipMonthPower))
// 记录算力变动日志
if tx.Error == nil {
var user model.User
e.db.Where("id", u.Id).First(&user)
e.db.Create(&model.PowerLog{
UserId: u.Id,
Username: u.Username,
Type: types.PowerRecharge,
Amount: config.VipMonthPower,
Mark: types.PowerAdd,
Balance: u.Power + config.VipMonthPower,
Model: "",
Remark: fmt.Sprintf("月底盘点,会员每月赠送算力%d", config.VipMonthPower),
Balance: user.Power,
Model: "系统盘点",
Remark: fmt.Sprintf("VIP会员每月算力派发%d", config.VipMonthPower),
CreatedAt: time.Now(),
})
}
@@ -115,6 +122,58 @@ func (e *XXLJobExecutor) ResetVipPower(cxt context.Context, param *xxl.RunReq) (
return "success"
}
func (e *XXLJobExecutor) ResetUserPower(cxt context.Context, param *xxl.RunReq) (msg string) {
logger.Info("今日算力派发开始:", time.Now())
var users []model.User
res := e.db.Where("status", 1).Find(&users)
if res.Error != nil {
return "No matching users"
}
var sysConfig model.Config
res = e.db.Where("marker", "system").First(&sysConfig)
if res.Error != nil {
return "error with get system config: " + res.Error.Error()
}
var config types.SystemConfig
err := utils.JsonDecode(sysConfig.Config, &config)
if err != nil {
return "error with decode system config: " + err.Error()
}
var counter = 0
var totalPower = 0
for _, u := range users {
if u.Power >= config.DailyPower {
continue
}
var power = config.DailyPower - u.Power
// update user
tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", power))
// 记录算力充值日志
if tx.Error == nil {
var user model.User
e.db.Where("id", u.Id).First(&user)
e.db.Create(&model.PowerLog{
UserId: u.Id,
Username: u.Username,
Type: types.PowerGift,
Amount: power,
Mark: types.PowerAdd,
Balance: user.Power,
Model: "系统赠送",
Remark: fmt.Sprintf("系统每日算力派发,今日额度:%d", config.VipMonthPower),
CreatedAt: time.Now(),
})
}
counter++
totalPower += power
}
logger.Infof("今日派发算力结束!累计派发 %d 人,累计派发算力:%d", counter, totalPower)
return "success"
}
type customLogger struct{}
func (l *customLogger) Info(format string, a ...interface{}) {

View File

@@ -1,9 +1,8 @@
package main
import (
"chatplus/utils"
"fmt"
"regexp"
"strings"
)
type Person struct {
@@ -18,27 +17,8 @@ type Student struct {
func main() {
text := `
开始创作您的LOGO了基于您提供的描述我将设计一个主题内容为一个小人推着一个购物车的卡通风格LOGO。稍等片刻您的创意即将变为现实。
{"prompt":"Create a cartoon-style logo featuring a character pushing a shopping cart. The design should be colorful, vibrant, and engaging, showcasing the character in a dynamic and cheerful pose. The shopping cart should be noticeable but not overpower the character. Use bright and welcoming colors to make the logo inviting and fun. The character can be stylized in a cute and approachable manner, suitable for a wide range of audiences. Ensure the logo is clear and easily recognizable at small sizes.","size":"1024x1024"}
text := "2024-06-01 08:34:46"
fmt.Println(utils.Str2stamp(text))
![image1](https://filesystem.site/cdn/20240320/JQIliW99JMPZRjMkgS2PlWNlfUtqDu.webp)
[下载1](https://filesystem.site/cdn/download/20240320/JQIliW99JMPZRjMkgS2PlWNlfUtqDu.webp)
这是为您设计的卡通风格LOGO主题是一个小人推着购物车。请查看图像看它是否满足您的需求。如果您对这个设计满意请访问 [Vectorizer.ai](https://vectorizer.ai/) 将其转换为矢量图,以便在不同大小和格式下保持清晰度。如果您觉得需要进一步的调整或改进,请告诉我,我们可以继续优化设计。`
pattern := `!\[([^\]]*)]\(([^)]+)\)`
re := regexp.MustCompile(pattern)
matches := re.FindAllStringSubmatch(text, -1)
// 下载图片并替换链接地址
for _, match := range matches {
imageURL := match[2]
fmt.Println(imageURL)
// 对于相同地址的图片,已经被替换了,就不再重复下载了
if !strings.Contains(text, imageURL) {
continue
}
}
fmt.Println(utils.Stamp2str(utils.Str2stamp(text)))
}

View File

@@ -62,7 +62,7 @@ func Str2stamp(str string) int64 {
}
layout := "2006-01-02 15:04:05"
t, err := time.Parse(layout, str)
t, err := time.ParseInLocation(layout, str, time.Local)
if err != nil {
return 0
}