Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a29772de0 | |||
| 194065af8d | |||
| a118b75379 | |||
| 09d59162d0 | |||
| 1323bc7aa8 | |||
| 604245add2 | |||
| 90bbc11712 |
@@ -7,6 +7,7 @@ import (
|
||||
"likedream-goframe/internal/controller/common"
|
||||
"likedream-goframe/internal/controller/cpdaily"
|
||||
"likedream-goframe/internal/controller/menu"
|
||||
"likedream-goframe/internal/controller/music"
|
||||
"likedream-goframe/internal/controller/role"
|
||||
"likedream-goframe/internal/controller/user"
|
||||
"likedream-goframe/internal/controller/user_login"
|
||||
@@ -53,6 +54,8 @@ func StartServer(ctx context.Context) {
|
||||
cpdailyGroup.Bind(cpdaily.NewCpTaskCtrlV1())
|
||||
cpdailyGroup.Bind(cpdaily.NewCpImageCtrlV1())
|
||||
cpdailyGroup.Bind(cpdaily.NewCpTaskLogCtrlV1())
|
||||
musicGroup := group.Group("/music").Middleware(middleware.AuthHandler, middleware.PermissionHandler)
|
||||
musicGroup.Bind(music.NewMusicCtrlV1())
|
||||
})
|
||||
|
||||
s.SetPort(port.Int())
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package v1
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type SearchMusicReq struct {
|
||||
g.Meta `path:"/search" method:"get" tags:"Music" summary:"搜索音乐"`
|
||||
Keyword string `json:"keyword"`
|
||||
}
|
||||
|
||||
type DownloadMusicReq struct {
|
||||
g.Meta `path:"/download" method:"get" tags:"Music" summary:"下载音乐"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func NewImageClassifier(modelPath, classesPath string) (*ImageClassifier, error)
|
||||
ort.SetSharedLibraryPath(dir)
|
||||
err = ort.InitializeEnvironment()
|
||||
if err != nil {
|
||||
logger.Logger.Info("初始化onnx:", zap.String("绝对路径", absPath), zap.String("父文件夹", dir))
|
||||
logger.Logger.Error("初始化onnx:", zap.String("绝对路径", absPath), zap.String("父文件夹", dir))
|
||||
return nil, fmt.Errorf("初始化ONNX Runtime失败: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ func (c *CpdailyCollectionTask) QueryFormByTitle(ctx context.Context, titleGlob
|
||||
}
|
||||
|
||||
if matchTask == nil {
|
||||
utils.OkOrPanic(errors.NewBusinessError(404, fmt.Sprintf("未找到表单信息: %s", titleGlob)), func(err error) error {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, fmt.Sprintf("未找到表单信息: %s", titleGlob)), func(err error) error {
|
||||
return oops.With("host", c.host).
|
||||
In("CpdailyCollectionTask.QueryFormByTitle").
|
||||
Wrap(err)
|
||||
@@ -196,7 +196,7 @@ func (c *CpdailyCollectionTask) QueryFormByTitle(ctx context.Context, titleGlob
|
||||
detailDatas := detailJSON["datas"].MapStrVar()
|
||||
|
||||
if len(detailDatas) == 0 {
|
||||
utils.OkOrPanic(errors.NewBusinessError(404, "未找到表单数据"), func(err error) error {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "未找到表单数据"), func(err error) error {
|
||||
return oops.With("host", c.host).
|
||||
In("CpdailyCollectionTask.QueryFormByTitle").
|
||||
With("titleGlob", titleGlob).
|
||||
@@ -230,7 +230,7 @@ func (c *CpdailyCollectionTask) QueryFormByTitle(ctx context.Context, titleGlob
|
||||
formDatas := formJSON["datas"].MapStrVar()
|
||||
|
||||
if len(formDatas) == 0 {
|
||||
utils.OkOrPanic(errors.NewBusinessError(404, "未找到表单数据"), func(err error) error {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "未找到表单数据"), func(err error) error {
|
||||
return oops.With("host", c.host).
|
||||
In("CpdailyCollectionTask.QueryFormByTitle").
|
||||
With("titleGlob", titleGlob).
|
||||
|
||||
@@ -147,8 +147,8 @@ func (c *CpdailyAutoSignTask) QueryFormByTitle(ctx context.Context, titleGlob st
|
||||
|
||||
findMatchTitle := func(jsonArr []any) map[string]*gvar.Var {
|
||||
for _, rawJson := range jsonArr {
|
||||
item, ok := rawJson.(map[string]*gvar.Var)
|
||||
if !ok {
|
||||
item := gvar.New(rawJson).MapStrVar()
|
||||
if len(item) == 0 {
|
||||
continue
|
||||
}
|
||||
taskName, exist := item["taskName"]
|
||||
@@ -178,7 +178,7 @@ func (c *CpdailyAutoSignTask) QueryFormByTitle(ctx context.Context, titleGlob st
|
||||
if matchTask == nil {
|
||||
matchTask = findMatchTitle(signedTasks)
|
||||
if matchTask == nil {
|
||||
utils.OkOrPanic(errors.NewBusinessError(404, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
|
||||
return oops.With("host", c.host).
|
||||
In("CpdailyAutoSignTask.QueryFormByTitle").
|
||||
Wrap(err)
|
||||
@@ -210,7 +210,7 @@ func (c *CpdailyAutoSignTask) QueryFormByTitle(ctx context.Context, titleGlob st
|
||||
formDatas := detailResponseJSON["datas"].MapStrVar()
|
||||
|
||||
if len(formDatas) == 0 {
|
||||
utils.OkOrPanic(errors.NewBusinessError(404, "任务数据为空"), func(err error) error {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "任务数据为空"), func(err error) error {
|
||||
return oops.With("host", c.host).
|
||||
In("CpdailyAutoSignTask.QueryFormByTitle").
|
||||
With("titleGlob", titleGlob).
|
||||
@@ -293,7 +293,7 @@ func (c *CpdailyAutoSignTask) QueryFormByYearMonth(ctx context.Context, titleGlo
|
||||
if matchTask == nil {
|
||||
matchTask = findMatchTitle(signedTasks)
|
||||
if matchTask == nil {
|
||||
utils.OkOrPanic(errors.NewBusinessError(404, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, fmt.Sprintf("任务未找到: %s", titleGlob)), func(err error) error {
|
||||
return oops.
|
||||
With("host", c.host).
|
||||
With("year", year).
|
||||
@@ -332,7 +332,7 @@ func (c *CpdailyAutoSignTask) QueryFormByYearMonth(ctx context.Context, titleGlo
|
||||
formDatas := detailResponseJSON["datas"].MapStrVar()
|
||||
|
||||
if len(formDatas) == 0 {
|
||||
utils.OkOrPanic(errors.NewBusinessError(404, "任务数据为空"), func(err error) error {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "任务数据为空"), func(err error) error {
|
||||
return oops.
|
||||
With("host", c.host).
|
||||
With("year", year).
|
||||
@@ -379,12 +379,12 @@ func (c *CpdailyAutoSignTask) ParseFormJson(ctx context.Context, rawJson map[str
|
||||
dto = &formtype.CpTaskFormItem{
|
||||
Title: "签到具体地址",
|
||||
ColName: "address",
|
||||
Type: formtype.ItemTypeAddress,
|
||||
Type: formtype.ItemTypeInput,
|
||||
Required: true,
|
||||
}
|
||||
list = append(list, dto)
|
||||
|
||||
var current uint
|
||||
var current uint = 1
|
||||
|
||||
if isPhoto := rows["isPhoto"]; isPhoto != nil && isPhoto.Int() == 1 {
|
||||
dto = &formtype.CpTaskFormItem{
|
||||
@@ -539,7 +539,7 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
|
||||
|
||||
previewUrl := imageuploader.UploadImageFromStorage(ctx, c.host, imageId, types.TaskTypeSign, c.client)
|
||||
|
||||
resultForm["signImg"] = gvar.New(previewUrl)
|
||||
resultForm["signPhotoUrl"] = gvar.New(previewUrl)
|
||||
}
|
||||
|
||||
// 处理验证码
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package httpclient
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"time"
|
||||
|
||||
"resty.dev/v3"
|
||||
)
|
||||
|
||||
var Music = resty.New().
|
||||
SetCookieJar(nil).
|
||||
SetTimeout(3 * time.Minute).
|
||||
SetTLSClientConfig(&tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
@@ -0,0 +1,68 @@
|
||||
package music
|
||||
|
||||
import (
|
||||
"context"
|
||||
"likedream-goframe/internal/application/httpclient"
|
||||
"likedream-goframe/internal/common/errors"
|
||||
"likedream-goframe/internal/utils"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/samber/oops"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
var MusicDownloader *Downloader
|
||||
|
||||
type Downloader struct {
|
||||
}
|
||||
|
||||
func (c *Downloader) Search(ctx context.Context, keyword string) (result []MusicSearchResult) {
|
||||
client := httpclient.Music.Clone(ctx)
|
||||
response, err := client.R().Get("https://www.gequbao.net/s/" + url.PathEscape(keyword))
|
||||
if err != nil {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "搜索出错1"), oops.WithContext(ctx).Wrap)
|
||||
}
|
||||
defer response.Body.Close()
|
||||
reader, err := goquery.NewDocumentFromReader(response.Body)
|
||||
if err != nil {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "搜索出错2"), oops.WithContext(ctx).Wrap)
|
||||
}
|
||||
card := reader.Find(".card")
|
||||
find := card.Find(".card-text > .row:not(:first-child)")
|
||||
find.Each(func(i int, item *goquery.Selection) {
|
||||
selection := item.Find("a")
|
||||
url, _ := selection.Attr("href")
|
||||
name := strings.TrimSpace(selection.Find(".text-primary span").Text())
|
||||
singer := strings.TrimSpace(selection.Find(".text-jade").Text())
|
||||
result = append(result, MusicSearchResult{
|
||||
Name: name,
|
||||
Singer: singer,
|
||||
Path: url,
|
||||
})
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Downloader) Download(ctx context.Context, url string) string {
|
||||
client := httpclient.Music.Clone(ctx)
|
||||
response, err := client.R().Get("https://www.gequbao.net" + url)
|
||||
if err != nil {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "下载出错1"), oops.WithContext(ctx).Wrap)
|
||||
}
|
||||
html := response.String()
|
||||
reg := regexp.MustCompile("window\\.play_id = '(.*?)';")
|
||||
play_id := reg.FindStringSubmatch(html)[1]
|
||||
post, err := client.R().SetBody(map[string]string{
|
||||
"id": play_id,
|
||||
}).Post("https://www.gequbao.net/api/play-url")
|
||||
if err != nil {
|
||||
utils.OkOrPanic(errors.NewBusinessError(503, "下载出错2"), oops.WithContext(ctx).Wrap)
|
||||
}
|
||||
download_url := gjson.Get(post.String(), "data.url").String()
|
||||
|
||||
// 下载音频文件
|
||||
return download_url
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package music
|
||||
|
||||
type MusicSearchResult struct {
|
||||
Name string `json:"name"`
|
||||
Singer string `json:"singer"`
|
||||
Path string `json:"url"`
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package music
|
||||
|
||||
import (
|
||||
"context"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
"likedream-goframe/internal/application/music"
|
||||
"likedream-goframe/internal/utils"
|
||||
)
|
||||
|
||||
type IMusicCtrlV1 interface {
|
||||
Search(ctx context.Context, req *v1.SearchMusicReq) (res *utils.Response[[]music.MusicSearchResult], err error)
|
||||
Download(ctx context.Context, req *v1.DownloadMusicReq) (res *utils.Response[any], err error)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package music
|
||||
|
||||
import (
|
||||
"context"
|
||||
v1 "likedream-goframe/internal/api/v1"
|
||||
"likedream-goframe/internal/application/music"
|
||||
"likedream-goframe/internal/utils"
|
||||
)
|
||||
|
||||
type MusicCtrlV1 struct {
|
||||
}
|
||||
|
||||
func NewMusicCtrlV1() IMusicCtrlV1 {
|
||||
return &MusicCtrlV1{}
|
||||
}
|
||||
|
||||
func (c *MusicCtrlV1) Search(ctx context.Context, req *v1.SearchMusicReq) (res *utils.Response[[]music.MusicSearchResult], err error) {
|
||||
defer utils.Pass(&err)
|
||||
return utils.SuccessWithData(music.MusicDownloader.Search(ctx, req.Keyword)), nil
|
||||
}
|
||||
|
||||
func (c *MusicCtrlV1) Download(ctx context.Context, req *v1.DownloadMusicReq) (res *utils.Response[any], err error) {
|
||||
defer utils.Pass(&err)
|
||||
|
||||
// 获取音频下载地址
|
||||
downloadUrl := music.MusicDownloader.Download(ctx, req.Path)
|
||||
return utils.SuccessWithData[any](downloadUrl), nil
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package cst
|
||||
|
||||
const (
|
||||
TaskCpdaily = "task:cpdaily"
|
||||
TaskEmail = "task:email"
|
||||
TaskCpdaily = "task:cpdaily"
|
||||
TaskEmail = "task:email"
|
||||
TaskResetDaily = "task:reset:daily"
|
||||
|
||||
TaskQueueCpdaily = "queue:cpdaily"
|
||||
TaskQueueEmail = "queue:email"
|
||||
TaskQueueDefault = "default"
|
||||
)
|
||||
|
||||
@@ -14,12 +14,17 @@ func Init(ctx context.Context) {
|
||||
initServer(ctx)
|
||||
initInspector(ctx)
|
||||
initScanner()
|
||||
initPeriodicTasks(ctx)
|
||||
}
|
||||
|
||||
func Stop() {
|
||||
globalScanner.StopScan()
|
||||
g.Log().Info(gctx.GetInitCtx(), "task scanner stopped")
|
||||
|
||||
if globalPeriodicTaskManager != nil {
|
||||
globalPeriodicTaskManager.Shutdown()
|
||||
}
|
||||
|
||||
e := queue.GetClient().Close()
|
||||
utils.OkOrPanic(e)
|
||||
g.Log().Info(gctx.GetInitCtx(), "asynq client closed")
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package schedule
|
||||
|
||||
import (
|
||||
"context"
|
||||
"likedream-goframe/internal/cst"
|
||||
"likedream-goframe/internal/framework/redis"
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
)
|
||||
|
||||
var globalPeriodicTaskManager *asynq.PeriodicTaskManager
|
||||
|
||||
func initPeriodicTasks(ctx context.Context) {
|
||||
// 创建周期性任务配置提供者
|
||||
provider := &periodicTaskConfigProvider{}
|
||||
|
||||
// 创建周期性任务管理器
|
||||
globalPeriodicTaskManager, _ = asynq.NewPeriodicTaskManager(
|
||||
asynq.PeriodicTaskManagerOpts{
|
||||
RedisUniversalClient: redis.GetClient(),
|
||||
PeriodicTaskConfigProvider: provider,
|
||||
SyncInterval: 0, // 立即同步,使用默认值
|
||||
},
|
||||
)
|
||||
|
||||
// 启动周期性任务管理器
|
||||
e := globalPeriodicTaskManager.Start()
|
||||
utils.OkOrPanic(e)
|
||||
}
|
||||
|
||||
// periodicTaskConfigProvider 提供周期性任务配置
|
||||
type periodicTaskConfigProvider struct{}
|
||||
|
||||
// GetConfigs 返回所有周期性任务配置
|
||||
func (p *periodicTaskConfigProvider) GetConfigs() ([]*asynq.PeriodicTaskConfig, error) {
|
||||
return []*asynq.PeriodicTaskConfig{
|
||||
{
|
||||
//Cronspec: "0 1 * * *", // 每天凌晨1点执行
|
||||
Cronspec: "0 1 * * * ",
|
||||
Task: asynq.NewTask(cst.TaskResetDaily, nil),
|
||||
Opts: []asynq.Option{
|
||||
asynq.Queue(cst.TaskQueueDefault),
|
||||
asynq.MaxRetry(3),
|
||||
asynq.Timeout(0), // 使用默认超时
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package schedule
|
||||
|
||||
import (
|
||||
"context"
|
||||
"likedream-goframe/internal/db"
|
||||
"likedream-goframe/internal/ent/cptask"
|
||||
"likedream-goframe/internal/utils"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/hibiken/asynq"
|
||||
)
|
||||
|
||||
type ResetTaskHandler struct {
|
||||
}
|
||||
|
||||
// ProcessTask 处理每日重置任务状态
|
||||
func (h *ResetTaskHandler) ProcessTask(ctx context.Context, _ *asynq.Task) (err error) {
|
||||
defer utils.Pass(&err)
|
||||
|
||||
g.Log().Info(ctx, "开始执行每日任务状态重置")
|
||||
|
||||
// 执行重置任务状态
|
||||
db.Global.CpTask.Update().Where(cptask.TaskStatusIn(cptask.TaskStatusDone, cptask.TaskStatusFail)).SetTaskStatus(cptask.TaskStatusNotStart).ExecX(ctx)
|
||||
|
||||
g.Log().Info(ctx, "每日任务状态重置完成")
|
||||
|
||||
return
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func (ts *TaskScanner) scanCpdailyTask() {
|
||||
|
||||
e = utils.Catch(func() {
|
||||
queue.AddTask(ts.ctx, asynq.NewTask(cst.TaskCpdaily, payloadWriter.Bytes()),
|
||||
asynq.TaskID(fmt.Sprintf("cpdaily:task:%d", task.ID)),
|
||||
asynq.TaskID(fmt.Sprintf("cpdaily:task:schedule:%d", task.ID)),
|
||||
asynq.MaxRetry(3),
|
||||
asynq.Unique(10*time.Second),
|
||||
asynq.ProcessAt(execTime),
|
||||
|
||||
@@ -30,7 +30,8 @@ func initServer(ctx context.Context) {
|
||||
ErrorHandler: taskErrorHandler{},
|
||||
Queues: map[string]int{
|
||||
cst.TaskQueueEmail: 2,
|
||||
cst.TaskQueueCpdaily: 8,
|
||||
cst.TaskQueueCpdaily: 10,
|
||||
cst.TaskQueueDefault: 1,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -38,6 +39,7 @@ func initServer(ctx context.Context) {
|
||||
|
||||
mux.Handle(cst.TaskCpdaily, &CpdailyTaskHandler{})
|
||||
mux.Handle(cst.TaskEmail, &EmailTaskHandler{})
|
||||
mux.Handle(cst.TaskResetDaily, &ResetTaskHandler{})
|
||||
|
||||
e := globalServer.Start(mux)
|
||||
utils.OkOrPanic(e)
|
||||
|
||||
@@ -245,17 +245,21 @@ func (v CpTaskServiceV1) ExecuteNow(ctx context.Context, req *v1.ExecuteNowReq)
|
||||
user := utils.GetUserInfoFromCtx(ctx)
|
||||
|
||||
// 查询任务并检查状态
|
||||
task := db.Global.CpTask.Query().
|
||||
cpTask := db.Global.CpTask.Query().
|
||||
Where(cptask.ID(req.Id), cptask.UserID(user.ID)).
|
||||
Select(cptask.FieldTaskStatus).
|
||||
Select(cptask.FieldTaskStatus, cptask.FieldFrequency, cptask.FieldSuccessCount).
|
||||
FirstX(ctx)
|
||||
|
||||
if task == nil {
|
||||
if cpTask == nil {
|
||||
utils.OkOrPanic(errors2.NewBusinessError(404, "任务不存在"))
|
||||
}
|
||||
// 检查任务是否存在次数
|
||||
if cpTask.Frequency-cpTask.SuccessCount <= 0 {
|
||||
utils.OkOrPanic(errors2.NewBusinessError(400, "任务没有执行次数"))
|
||||
}
|
||||
|
||||
// 检查任务是否正在执行中
|
||||
if task.TaskStatus == cptask.TaskStatusDoing {
|
||||
if cpTask.TaskStatus != cptask.TaskStatusNotStart && cpTask.TaskStatus != cptask.TaskStatusDone && cpTask.TaskStatus != cptask.TaskStatusFail {
|
||||
utils.OkOrPanic(errors2.NewBusinessError(400, "任务正在执行中,请稍后再试"))
|
||||
}
|
||||
|
||||
@@ -280,7 +284,7 @@ func (v CpTaskServiceV1) ExecuteNow(ctx context.Context, req *v1.ExecuteNowReq)
|
||||
asynq.Queue(cst.TaskQueueCpdaily),
|
||||
)
|
||||
// 更新未开始的任务状态为队列中
|
||||
db.Global.CpTask.Update().Where(cptask.ID(task.ID), cptask.TaskStatusEQ(cptask.TaskStatusNotStart)).SetTaskStatus(cptask.TaskStatusQueue).Exec(ctx)
|
||||
db.Global.CpTask.Update().Where(cptask.ID(cpTask.ID), cptask.TaskStatusEQ(cptask.TaskStatusNotStart)).SetTaskStatus(cptask.TaskStatusQueue).Exec(ctx)
|
||||
})
|
||||
if e != nil {
|
||||
g.Log().Errorf(ctx, "立即执行任务入列失败: %+v", e)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"likedream-goframe/internal/ent/sysrole"
|
||||
"likedream-goframe/internal/ent/sysuser"
|
||||
"likedream-goframe/internal/framework/ent2"
|
||||
"likedream-goframe/internal/service/balance"
|
||||
"likedream-goframe/internal/utils"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -132,22 +133,25 @@ func (s *UserInfoServiceV1) CardRecharge(ctx context.Context, req *v1.CardRechar
|
||||
tx, err := db.Global.Tx(ctx)
|
||||
utils.OkOrPanic(err)
|
||||
parent := user.QueryParent().WithAgent().FirstX(ctx)
|
||||
// 返现20%
|
||||
r, _ := decimal.NewFromString("0.2")
|
||||
cashbackValue := decimal.NewFromUint64(card.Value).Mul(r)
|
||||
if parent != nil {
|
||||
// 返现20%
|
||||
r, _ := decimal.NewFromString("0.2")
|
||||
cashbackValue := decimal.NewFromUint64(card.Value).Mul(r)
|
||||
// 这里查询父级是否是代理,代理的话要x代理费率
|
||||
if parent.Edges.Agent != nil {
|
||||
cashbackValue = cashbackValue.Mul(parent.Edges.Agent.Rate)
|
||||
}
|
||||
tx.SysUser.UpdateOneID(user.Edges.Parent.ID).SetBalance(parent.Balance.Add(cashbackValue)).SetInviteCashback(parent.InviteCashback.Add(cashbackValue)).ExecX(ctx)
|
||||
tx.SysUser.UpdateOneID(user.Edges.Parent.ID).SetInviteCashback(parent.InviteCashback.Add(cashbackValue)).ExecX(ctx)
|
||||
tx.SysCard.UpdateOneID(card.ID).SetStatus(syscard.StatusCashback).SetUsedID(user.ID).SetCashUserID(user.Edges.Parent.ID).SetCashValue(cashbackValue).ExecX(ctx)
|
||||
} else {
|
||||
//tx.SysCard.UpdateOneID(card.ID).SetStatus(cst.CardStatusUsed).SetUsedID(user.ID).ExecX(ctx)
|
||||
tx.SysCard.UpdateOneID(card.ID).SetStatus(syscard.StatusUsed).SetUsedID(user.ID).ExecX(ctx)
|
||||
}
|
||||
tx.SysUser.UpdateOneID(user.ID).SetBalance(user.Balance.Add(decimal.NewFromUint64(card.Value))).ExecX(ctx)
|
||||
err = tx.Commit()
|
||||
balance.BalanceService.ChangeUserBalance(ctx, user.ID, decimal.NewFromUint64(card.Value))
|
||||
if parent != nil {
|
||||
balance.BalanceService.ChangeUserBalance(ctx, parent.ID, cashbackValue)
|
||||
}
|
||||
utils.OkOrPanic(err, func(err error) error {
|
||||
return oops.
|
||||
WithContext(ctx).
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user