增加社区列表接口,任务相关接口修改

This commit is contained in:
lianghuanjie
2024-12-19 21:14:14 +08:00
parent 391a9d3481
commit a3c4adfa25
32 changed files with 1163 additions and 197 deletions

View File

@@ -37,8 +37,7 @@ build:
.PHONY: img .PHONY: img
# 构建Docker镜像 # 构建Docker镜像
img: img:
docker build --platform=amd64 -t nova-task:latest . docker build --platform=amd64 -t harbor.phantom-u3d002.com/nova/nova-task:latest .
docker tag `docker images -aq -f "reference=nova-task:latest"` harbor.phantom-u3d002.com/nova/nova-task:latest
.PHONY: push .PHONY: push
push: push:

View File

@@ -8,6 +8,10 @@ service novatask {
@doc "获取任务列表" @doc "获取任务列表"
@handler GetTaskList @handler GetTaskList
get /tasks (GetTaskListReq) returns (GetTaskListResp) get /tasks (GetTaskListReq) returns (GetTaskListResp)
@doc "获取社区列表"
@handler GetCommunityList
get /community returns (GetCommunityListResp)
} }
@server ( @server (
@@ -18,7 +22,7 @@ service novatask {
service novatask { service novatask {
@doc "校验任务结果" @doc "校验任务结果"
@handler VerifyTaskResult @handler VerifyTaskResult
get /task/:id (TaskIdPath) returns (VerifyTaskResultResp) get /task (VerifyTaskResultReq) returns (VerifyTaskResultResp)
@doc "领取任务奖励" @doc "领取任务奖励"
@handler GetTaskReward @handler GetTaskReward
@@ -30,25 +34,33 @@ type GetTaskListReq {
} }
type Task { type Task {
Id uint `json:"id"` // 任务ID Id uint `json:"id"` // 任务ID
CommunityId uint `json:"community_id"` // 所属社区ID CommunityId uint `json:"community_id"` // 所属社区ID
Title string `json:"title"` // 任务标题 Title string `json:"title"` // 任务标题
SubTitle string `json:"sub_title"` // 副标题 SubTitle string `json:"sub_title"` // 副标题
Description string `json:"description"` // 任务描述 Description string `json:"description"` // 任务描述
Points int `json:"points"` // 任务积分 Points int `json:"points"` // 任务积分
ButtonText string `json:"button_text"` // 按钮文字 ButtonText string `json:"button_text"` // 按钮文字
Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay Params string `json:"params"` // 参数
Url string `json:"url"` // 跳转链接 Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay,10=invite_user
Status int8 `json:"status"` // 任务状态: 0=不启用1=启用 Url string `json:"url"` // 跳转链接
StartAt string `json:"start_at"` // 开始时间 Sort int `json:"sort"` // 排序
EndAt string `json:"end_at"` // 结束时间 StartAt string `json:"start_at"` // 开始时间
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取 EndAt string `json:"end_at"` // 结束时间
HasFinishCount int `json:"has_finish_count"` // 当前完成进度
TotalCount int `json:"total_count"` // 总进度
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取
} }
type GetTaskListResp { type GetTaskListResp {
Tasks []Task `json:"tasks"` Tasks []Task `json:"tasks"`
} }
type VerifyTaskResultReq {
ID uint `form:"id"` // 任务ID
Params string `form:"params,optional"` // 额外的参数
}
type TaskIdPath { type TaskIdPath {
ID uint `path:"id"` // 任务ID ID uint `path:"id"` // 任务ID
} }
@@ -61,3 +73,16 @@ type GetTaskRewardResp {
Points int `json:"points"` // 积分 Points int `json:"points"` // 积分
} }
type Community {
Id uint `json:"id"` // 社区ID
Title string `json:"title"` // 社区标题
Logo string `json:"logo"` // 社区图标
Description string `json:"description"` // 社区描述
StartAt int64 `json:"start_at"` // 开始时间
EndAt int64 `json:"end_at"` // 结束时间
}
type GetCommunityListResp {
CommunityList []Community `json:"community_list"` // 社区列表
}

View File

@@ -15,6 +15,23 @@
"application/json" "application/json"
], ],
"paths": { "paths": {
"/gapi/task/v1/community": {
"get": {
"summary": "获取社区列表",
"operationId": "GetCommunityList",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/GetCommunityListResp"
}
}
},
"tags": [
"task"
]
}
},
"/gapi/task/v1/reward/{id}": { "/gapi/task/v1/reward/{id}": {
"get": { "get": {
"summary": "领取任务奖励", "summary": "领取任务奖励",
@@ -45,7 +62,7 @@
] ]
} }
}, },
"/gapi/task/v1/task/{id}": { "/gapi/task/v1/task": {
"get": { "get": {
"summary": "校验任务结果", "summary": "校验任务结果",
"operationId": "VerifyTaskResult", "operationId": "VerifyTaskResult",
@@ -60,14 +77,26 @@
"parameters": [ "parameters": [
{ {
"name": "id", "name": "id",
"in": "path", "description": " 任务ID",
"in": "query",
"required": true, "required": true,
"type": "integer",
"format": "uint32"
},
{
"name": "params",
"description": " 额外的参数",
"in": "query",
"required": false,
"type": "string" "type": "string"
} }
], ],
"tags": [ "tags": [
"task" "task"
], ],
"consumes": [
"multipart/form-data"
],
"security": [ "security": [
{ {
"apiKey": [] "apiKey": []
@@ -107,6 +136,63 @@
} }
}, },
"definitions": { "definitions": {
"Community": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "uint32",
"description": " 社区ID"
},
"title": {
"type": "string",
"description": " 社区标题"
},
"logo": {
"type": "string",
"description": " 社区图标"
},
"description": {
"type": "string",
"description": " 社区描述"
},
"start_at": {
"type": "integer",
"format": "int64",
"description": " 开始时间"
},
"end_at": {
"type": "integer",
"format": "int64",
"description": " 结束时间"
}
},
"title": "Community",
"required": [
"id",
"title",
"logo",
"description",
"start_at",
"end_at"
]
},
"GetCommunityListResp": {
"type": "object",
"properties": {
"community_list": {
"type": "array",
"items": {
"$ref": "#/definitions/Community"
},
"description": " 社区列表"
}
},
"title": "GetCommunityListResp",
"required": [
"community_list"
]
},
"GetTaskListReq": { "GetTaskListReq": {
"type": "object", "type": "object",
"properties": { "properties": {
@@ -181,19 +267,23 @@
"type": "string", "type": "string",
"description": " 按钮文字" "description": " 按钮文字"
}, },
"params": {
"type": "string",
"description": " 参数"
},
"type": { "type": {
"type": "integer", "type": "integer",
"format": "int8", "format": "int8",
"description": " 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay" "description": " 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay,10=invite_user"
}, },
"url": { "url": {
"type": "string", "type": "string",
"description": " 跳转链接" "description": " 跳转链接"
}, },
"status": { "sort": {
"type": "integer", "type": "integer",
"format": "int8", "format": "int32",
"description": " 任务状态: 0=不启用1=启用" "description": " 排序"
}, },
"start_at": { "start_at": {
"type": "string", "type": "string",
@@ -203,6 +293,16 @@
"type": "string", "type": "string",
"description": " 结束时间" "description": " 结束时间"
}, },
"has_finish_count": {
"type": "integer",
"format": "int32",
"description": " 当前完成进度"
},
"total_count": {
"type": "integer",
"format": "int32",
"description": " 总进度"
},
"finish_state": { "finish_state": {
"type": "integer", "type": "integer",
"format": "int8", "format": "int8",
@@ -218,11 +318,14 @@
"description", "description",
"points", "points",
"button_text", "button_text",
"params",
"type", "type",
"url", "url",
"status", "sort",
"start_at", "start_at",
"end_at", "end_at",
"has_finish_count",
"total_count",
"finish_state" "finish_state"
] ]
}, },
@@ -230,6 +333,24 @@
"type": "object", "type": "object",
"title": "TaskIdPath" "title": "TaskIdPath"
}, },
"VerifyTaskResultReq": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"format": "uint32",
"description": " 任务ID"
},
"params": {
"type": "string",
"description": " 额外的参数"
}
},
"title": "VerifyTaskResultReq",
"required": [
"id"
]
},
"VerifyTaskResultResp": { "VerifyTaskResultResp": {
"type": "object", "type": "object",
"properties": { "properties": {

2
go.mod
View File

@@ -30,12 +30,14 @@ require (
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/openzipkin/zipkin-go v0.4.3 // indirect github.com/openzipkin/zipkin-go v0.4.3 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect

4
go.sum
View File

@@ -57,6 +57,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg=
github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -71,6 +73,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=

View File

@@ -15,6 +15,12 @@ import (
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes( server.AddRoutes(
[]rest.Route{ []rest.Route{
{
// 获取社区列表
Method: http.MethodGet,
Path: "/community",
Handler: task.GetCommunityListHandler(serverCtx),
},
{ {
// 获取任务列表 // 获取任务列表
Method: http.MethodGet, Method: http.MethodGet,
@@ -36,7 +42,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
{ {
// 校验任务结果 // 校验任务结果
Method: http.MethodGet, Method: http.MethodGet,
Path: "/task/:id", Path: "/task",
Handler: task.VerifyTaskResultHandler(serverCtx), Handler: task.VerifyTaskResultHandler(serverCtx),
}, },
}, },

View File

@@ -0,0 +1,22 @@
package task
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"nova_task/internal/logic/task"
"nova_task/internal/svc"
)
// 获取社区列表
func GetCommunityListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := task.NewGetCommunityListLogic(r.Context(), svcCtx)
resp, err := l.GetCommunityList()
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}

View File

@@ -12,7 +12,7 @@ import (
// 校验任务结果 // 校验任务结果
func VerifyTaskResultHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { func VerifyTaskResultHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
var req types.TaskIdPath var req types.VerifyTaskResultReq
if err := httpx.Parse(r, &req); err != nil { if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err) httpx.ErrorCtx(r.Context(), w, err)
return return

61
internal/job/earn/earn.go Normal file
View File

@@ -0,0 +1,61 @@
package earn
import (
"context"
ea "github.com/earn-alliance/earnalliance-go"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/svc"
)
// Earn 用户数据上报earn平台定时任务
type Earn struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewEarn(ctx context.Context, svcCtx *svc.ServiceContext) *Earn {
e := &Earn{ctx: ctx, svcCtx: svcCtx}
e.Run()
return e
}
func (e *Earn) Spec() string {
return "@every 5m"
}
func (e *Earn) Run() {
e.pushUserInfo(666)
e.pushUserBind()
}
func (e *Earn) pushUserInfo(shareId uint) {
us, err := e.svcCtx.PromoteBindModel.FindRequirePushUser(e.ctx, shareId)
if err != nil {
logx.Errorw("find require push user failed", logx.Field("err", err), logx.Field("share_id", shareId))
return
}
for _, u := range us {
ui, err := e.svcCtx.UserModel.FindOne(e.ctx, u.InvitedUid)
if err != nil {
logx.Errorw("find user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid))
continue
}
var twitterId string
ut, err := e.svcCtx.TwitterModel.FindOne(e.ctx, u.InvitedUid)
if err == nil {
twitterId = ut.TwitterId
}
e.svcCtx.Earn.SetIdentifiers(cast.ToString(ui.Id), &ea.Identifiers{
Email: ea.IdentifierFrom(ui.Email),
TwitterId: ea.IdentifierFrom(twitterId),
})
err = e.svcCtx.PromoteBindModel.UpdatePushUser(e.ctx, u.Id)
if err != nil {
logx.Errorw("update push user failed", logx.Field("err", err), logx.Field("uid", u.InvitedUid))
}
}
}
func (e *Earn) pushUserBind() {}

63
internal/job/job.go Normal file
View File

@@ -0,0 +1,63 @@
package job
import (
"context"
"errors"
"github.com/robfig/cron/v3"
"github.com/zeromicro/go-zero/core/logx"
"nova_task/internal/job/earn"
"nova_task/internal/job/pledge"
"nova_task/internal/svc"
)
type Job struct {
ctx context.Context
cancel context.CancelFunc
svcCtx *svc.ServiceContext
c *cron.Cron
}
type Spec interface {
Spec() string
}
func NewJob(svcCtx *svc.ServiceContext) *Job {
ctx, cancel := context.WithCancel(context.Background())
var cronList = []cron.Job{
earn.NewEarn(ctx, svcCtx),
pledge.NewPledge(ctx, svcCtx),
}
var err error
c := cron.New()
for _, cr := range cronList {
if cs, ok := cr.(Spec); ok {
_, err = c.AddJob(cs.Spec(), cr)
logx.Must(err)
continue
}
if cs, ok := cr.(cron.Schedule); ok {
c.Schedule(cs, cr)
continue
}
logx.Must(errors.New("cron job must implement either Spec or Schedule interface"))
}
return &Job{
ctx: ctx,
cancel: cancel,
svcCtx: svcCtx,
c: c,
}
}
func (j *Job) Start() {
logx.Info("start cron job")
j.c.Start()
}
func (j *Job) Stop() {
logx.Info("stop cron job")
<-j.c.Stop().Done()
logx.Info("cron job stopped")
j.cancel()
}

View File

@@ -0,0 +1,26 @@
package pledge
import (
"context"
"nova_task/internal/svc"
)
type Pledge struct {
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewPledge(ctx context.Context, svcCtx *svc.ServiceContext) *Pledge {
return &Pledge{
ctx: ctx,
svcCtx: svcCtx,
}
}
func (p *Pledge) Spec() string {
return "@every 30m"
}
func (p *Pledge) Run() {
}

View File

@@ -0,0 +1,48 @@
package task
import (
"context"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc"
"nova_task/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetCommunityListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 获取社区列表
func NewGetCommunityListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCommunityListLogic {
return &GetCommunityListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetCommunityListLogic) GetCommunityList() (*types.GetCommunityListResp, error) {
cs, err := l.svcCtx.CommunityModel.All(l.ctx)
if err != nil {
l.Errorw("get community list error", logx.Field("err", err))
return nil, errs.New(errs.ErrDatabaseOperate, err)
}
var communityList []types.Community
for _, c := range cs {
communityList = append(communityList, types.Community{
Id: c.Id,
Title: c.Title,
Logo: c.Logo,
Description: c.Description,
StartAt: c.StartAt.Time.Unix(),
EndAt: c.EndAt.Time.Unix(),
})
}
return &types.GetCommunityListResp{CommunityList: communityList}, nil
}

View File

@@ -33,7 +33,12 @@ func (l *GetTaskListLogic) GetTaskList(uid int, req *types.GetTaskListReq) (*typ
tasks, err := l.svcCtx.TaskModel.FindTasksByCommunity(l.ctx, req.CommunityId) tasks, err := l.svcCtx.TaskModel.FindTasksByCommunity(l.ctx, req.CommunityId)
if err != nil { if err != nil {
l.Errorw("get task list failed", logx.Field("err", err), logx.Field("communityId", req.CommunityId)) l.Errorw("get task list failed", logx.Field("err", err), logx.Field("communityId", req.CommunityId))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
}
count, err := l.svcCtx.PromoteBindModel.UserInviteCount(l.ctx, uint(uid))
if err != nil {
l.Errorw("get user invite count failed", logx.Field("err", err), logx.Field("uid", uid))
} }
resp := &types.GetTaskListResp{} resp := &types.GetTaskListResp{}
@@ -44,25 +49,46 @@ func (l *GetTaskListLogic) GetTaskList(uid int, req *types.GetTaskListReq) (*typ
} }
var finishState int8 var finishState int8
if uid > 0 { if uid > 0 {
tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, t.CommunityId, taskSeq) tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, t.Id, taskSeq)
if err == nil { if err == nil {
finishState = tp.Stage finishState = tp.Stage
} }
} }
hasFinishCount := 0
totalCount := 1
if t.Type == model.TASKTYPE_INVITE_USER {
totalCount = cast.ToInt(t.Param)
hasFinishCount = cast.ToInt(count)
}
if finishState >= model.TASK_PROGRESS_WAIT_REWARD {
hasFinishCount = totalCount
}
if hasFinishCount > totalCount {
hasFinishCount = totalCount
}
if hasFinishCount >= totalCount && finishState == model.TASK_PROGRESS_NOT_FINISHED {
finishState = model.TASK_PROGRESS_WAIT_VERIFY
}
resp.Tasks = append(resp.Tasks, types.Task{ resp.Tasks = append(resp.Tasks, types.Task{
Id: t.Id, Id: t.Id,
Title: t.Title, Title: t.Title,
SubTitle: t.SubTitle, SubTitle: t.SubTitle,
Description: t.Description, Description: t.Description,
Points: t.Points, Points: t.Points,
ButtonText: t.ButtonText, ButtonText: t.ButtonText,
Type: t.Type, Params: t.Param,
Url: t.Url, Type: t.Type,
StartAt: t.StartAt.Time.Format(time.DateTime), Url: t.Url,
EndAt: t.EndAt.Time.Format(time.DateTime), StartAt: t.StartAt.Time.Format(time.DateTime),
Status: t.Status, EndAt: t.EndAt.Time.Format(time.DateTime),
FinishState: finishState, Sort: t.Sort,
HasFinishCount: hasFinishCount,
TotalCount: totalCount,
FinishState: finishState,
}) })
} }

View File

@@ -35,9 +35,9 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas
task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID) task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID)
if err != nil { if err != nil {
if errors.Is(err, model.ErrNotFound) { if errors.Is(err, model.ErrNotFound) {
return nil, errs.BadRequest(errs.ErrTaskNotFound, "task not found") return nil, errs.New(errs.ErrTaskNotFound, "task not found")
} }
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
var taskSeq int var taskSeq int
if task.Type == model.TASKTYPE_DAILY_PAY { if task.Type == model.TASKTYPE_DAILY_PAY {
@@ -47,15 +47,15 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas
if err != nil { if err != nil {
if !errors.Is(err, model.ErrNotFound) { if !errors.Is(err, model.ErrNotFound) {
l.Errorw("find task progress error", logx.Field("err", err)) l.Errorw("find task progress error", logx.Field("err", err))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return nil, errs.BadRequest(errs.ErrTaskNotFinished, "task not finished") return nil, errs.New(errs.ErrTaskNotFinished, "task not finished")
} }
switch { switch {
case tp.Stage < model.TASK_PROGRESS_WAIT_REWARD: case tp.Stage < model.TASK_PROGRESS_WAIT_REWARD:
return nil, errs.BadRequest(errs.ErrTaskNotFinished, "task not finished") return nil, errs.New(errs.ErrTaskNotFinished, "task not finished")
case tp.Stage > model.TASK_PROGRESS_WAIT_REWARD: case tp.Stage > model.TASK_PROGRESS_WAIT_REWARD:
return nil, errs.BadRequest(errs.ErrTaskAlreadyReward, "task already reward") return nil, errs.New(errs.ErrTaskAlreadyReward, "task already reward")
} }
// 修改状态,增加积分和记录都在事物中执行 // 修改状态,增加积分和记录都在事物中执行
@@ -85,7 +85,7 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas
if err != nil { if err != nil {
l.Errorw("给予用户奖励实物执行失败", logx.Field("err", err), logx.Field("task", task.Id), logx.Field("uid", uid)) l.Errorw("给予用户奖励实物执行失败", logx.Field("err", err), logx.Field("task", task.Id), logx.Field("uid", uid))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return &types.GetTaskRewardResp{Points: task.Points}, nil return &types.GetTaskRewardResp{Points: task.Points}, nil

View File

@@ -27,14 +27,14 @@ func NewVerifyTaskResultLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
} }
} }
func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.VerifyTaskResultResp, error) { func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.VerifyTaskResultReq) (*types.VerifyTaskResultResp, error) {
uid := cast.ToStringMapInt(l.ctx.Value("data"))["id"] uid := cast.ToStringMapInt(l.ctx.Value("data"))["id"]
task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID) task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID)
if err != nil { if err != nil {
if errors.Is(err, model.ErrNotFound) { if errors.Is(err, model.ErrNotFound) {
return nil, errs.BadRequest(errs.ErrTaskNotFound, "task not found") return nil, errs.New(errs.ErrTaskNotFound, "task not found")
} }
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
var taskSeq int var taskSeq int
if task.Type == model.TASKTYPE_DAILY_PAY { if task.Type == model.TASKTYPE_DAILY_PAY {
@@ -44,7 +44,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
if err != nil { if err != nil {
if !errors.Is(err, model.ErrNotFound) { if !errors.Is(err, model.ErrNotFound) {
l.Errorw("find task progress error", logx.Field("err", err)) l.Errorw("find task progress error", logx.Field("err", err))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
tp = &model.NhTaskProgress{ tp = &model.NhTaskProgress{
Uid: uid, Uid: uid,
@@ -54,7 +54,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
} }
} }
if tp.Stage == model.TASK_PROGRESS_REWARDED { if tp.Stage == model.TASK_PROGRESS_REWARDED {
return nil, errs.BadRequest(errs.ErrTaskAlreadyReward, "task already reward") return nil, errs.New(errs.ErrTaskAlreadyReward, "task already reward")
} }
// todo: 校验用户是否完成该任务 // todo: 校验用户是否完成该任务
switch task.Type { switch task.Type {
@@ -62,7 +62,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
tw, err := l.svcCtx.TwitterModel.FindOneByUid(l.ctx, uint(uid)) tw, err := l.svcCtx.TwitterModel.FindOneByUid(l.ctx, uint(uid))
if err != nil { if err != nil {
if !errors.Is(err, model.ErrNotFound) { if !errors.Is(err, model.ErrNotFound) {
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return &types.VerifyTaskResultResp{Finish: false}, nil return &types.VerifyTaskResultResp{Finish: false}, nil
} }
@@ -72,6 +72,9 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
case model.TASKTYPE_BIND_DISCORD: case model.TASKTYPE_BIND_DISCORD:
case model.TASKTYPE_DAILY_PAY: case model.TASKTYPE_DAILY_PAY:
if req.Params == "" {
return &types.VerifyTaskResultResp{Finish: false}, nil
}
default: default:
} }
@@ -84,7 +87,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.
if err != nil { if err != nil {
l.Errorw("update task progress error", logx.Field("err", err)) l.Errorw("update task progress error", logx.Field("err", err))
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err) return nil, errs.New(errs.ErrDatabaseOperate, err)
} }
return &types.VerifyTaskResultResp{Finish: true}, nil return &types.VerifyTaskResultResp{Finish: true}, nil

View File

@@ -0,0 +1,81 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/patrickmn/go-cache"
"github.com/spf13/cast"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"time"
)
var _ NhPromoteBindModel = (*customNhPromoteBindModel)(nil)
type (
// NhPromoteBindModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhPromoteBindModel.
NhPromoteBindModel interface {
nhPromoteBindModel
withSession(session sqlx.Session) NhPromoteBindModel
FindRequirePushUser(ctx context.Context, shareUid uint) ([]NhPromoteBind, error)
UpdatePushUser(ctx context.Context, id uint) error
UpdatePushRole(ctx context.Context, id uint) error
UserInviteCount(ctx context.Context, uid uint) (int64, error)
}
customNhPromoteBindModel struct {
*defaultNhPromoteBindModel
userInviteCountCache *cache.Cache
}
)
// NewNhPromoteBindModel returns a model for the database table.
func NewNhPromoteBindModel(conn sqlx.SqlConn) NhPromoteBindModel {
return &customNhPromoteBindModel{
defaultNhPromoteBindModel: newNhPromoteBindModel(conn),
userInviteCountCache: cache.New(time.Minute, time.Second*65),
}
}
func (m *customNhPromoteBindModel) withSession(session sqlx.Session) NhPromoteBindModel {
return NewNhPromoteBindModel(sqlx.NewSqlConnFromSession(session))
}
func (m *customNhPromoteBindModel) FindRequirePushUser(ctx context.Context, shareUid uint) ([]NhPromoteBind, error) {
query := fmt.Sprintf("select %s from %s where `share_uid` = ? and `is_push_user` = 0 limit 100", nhPromoteBindRows, m.table)
var resp []NhPromoteBind
err := m.conn.QueryRowsCtx(ctx, &resp, query, shareUid)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return resp, nil
}
func (m *customNhPromoteBindModel) UpdatePushUser(ctx context.Context, id uint) error {
update := fmt.Sprintf("update %s set `is_push_user` = 1 where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, update, id)
return err
}
func (m *customNhPromoteBindModel) UpdatePushRole(ctx context.Context, id uint) error {
update := fmt.Sprintf("update %s set `is_push_role` = 1 where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, update, id)
return err
}
func (m *customNhPromoteBindModel) UserInviteCount(ctx context.Context, uid uint) (int64, error) {
key := cast.ToString(uid)
v, ok := m.userInviteCountCache.Get(key)
if ok {
return v.(int64), nil
}
query := fmt.Sprintf("select count(*) as `count` from %s where `share_uid` = ?", m.table)
var count int64
err := m.conn.QueryRowCtx(ctx, &count, query, uid)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return 0, err
}
m.userInviteCountCache.SetDefault(key, count)
return count, nil
}

View File

@@ -0,0 +1,104 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhPromoteBindFieldNames = builder.RawFieldNames(&NhPromoteBind{})
nhPromoteBindRows = strings.Join(nhPromoteBindFieldNames, ",")
nhPromoteBindRowsExpectAutoSet = strings.Join(stringx.Remove(nhPromoteBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhPromoteBindRowsWithPlaceHolder = strings.Join(stringx.Remove(nhPromoteBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhPromoteBindModel interface {
Insert(ctx context.Context, data *NhPromoteBind) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhPromoteBind, error)
FindOneByInvitedUid(ctx context.Context, invitedUid uint) (*NhPromoteBind, error)
Update(ctx context.Context, data *NhPromoteBind) error
Delete(ctx context.Context, id uint) error
}
defaultNhPromoteBindModel struct {
conn sqlx.SqlConn
table string
}
NhPromoteBind struct {
Id uint `db:"id"`
ShareUid uint `db:"share_uid"` // 分享者uid
InvitedUid uint `db:"invited_uid"` // 受邀者uid
CreateTime uint `db:"create_time"` // 创建时间
IsPushUser int8 `db:"is_push_user"` // 是否已推送用户信息
IsPushRole int8 `db:"is_push_role"` // 是否已推送绑定游戏账号
}
)
func newNhPromoteBindModel(conn sqlx.SqlConn) *defaultNhPromoteBindModel {
return &defaultNhPromoteBindModel{
conn: conn,
table: "`nh_promote_bind`",
}
}
func (m *defaultNhPromoteBindModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhPromoteBindModel) FindOne(ctx context.Context, id uint) (*NhPromoteBind, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhPromoteBindRows, m.table)
var resp NhPromoteBind
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhPromoteBindModel) FindOneByInvitedUid(ctx context.Context, invitedUid uint) (*NhPromoteBind, error) {
var resp NhPromoteBind
query := fmt.Sprintf("select %s from %s where `invited_uid` = ? limit 1", nhPromoteBindRows, m.table)
err := m.conn.QueryRowCtx(ctx, &resp, query, invitedUid)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhPromoteBindModel) Insert(ctx context.Context, data *NhPromoteBind) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, nhPromoteBindRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.ShareUid, data.InvitedUid, data.IsPushUser, data.IsPushRole)
return ret, err
}
func (m *defaultNhPromoteBindModel) Update(ctx context.Context, newData *NhPromoteBind) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhPromoteBindRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, newData.ShareUid, newData.InvitedUid, newData.IsPushUser, newData.IsPushRole, newData.Id)
return err
}
func (m *defaultNhPromoteBindModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,45 @@
package model
import (
"context"
"errors"
"fmt"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ NhTaskCommunityModel = (*customNhTaskCommunityModel)(nil)
type (
// NhTaskCommunityModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhTaskCommunityModel.
NhTaskCommunityModel interface {
nhTaskCommunityModel
withSession(session sqlx.Session) NhTaskCommunityModel
All(ctx context.Context) ([]NhTaskCommunity, error)
}
customNhTaskCommunityModel struct {
*defaultNhTaskCommunityModel
}
)
func (m *customNhTaskCommunityModel) All(ctx context.Context) ([]NhTaskCommunity, error) {
query := fmt.Sprintf("select %s from %s where `status` = 1", nhTaskCommunityRows, m.table)
var resp []NhTaskCommunity
err := m.conn.QueryRowsCtx(ctx, &resp, query)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
return nil, err
}
return resp, nil
}
// NewNhTaskCommunityModel returns a model for the database table.
func NewNhTaskCommunityModel(conn sqlx.SqlConn) NhTaskCommunityModel {
return &customNhTaskCommunityModel{
defaultNhTaskCommunityModel: newNhTaskCommunityModel(conn),
}
}
func (m *customNhTaskCommunityModel) withSession(session sqlx.Session) NhTaskCommunityModel {
return NewNhTaskCommunityModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,94 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhTaskCommunityFieldNames = builder.RawFieldNames(&NhTaskCommunity{})
nhTaskCommunityRows = strings.Join(nhTaskCommunityFieldNames, ",")
nhTaskCommunityRowsExpectAutoSet = strings.Join(stringx.Remove(nhTaskCommunityFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhTaskCommunityRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTaskCommunityFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhTaskCommunityModel interface {
Insert(ctx context.Context, data *NhTaskCommunity) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhTaskCommunity, error)
Update(ctx context.Context, data *NhTaskCommunity) error
Delete(ctx context.Context, id uint) error
}
defaultNhTaskCommunityModel struct {
conn sqlx.SqlConn
table string
}
NhTaskCommunity struct {
Id uint `db:"id"`
Title string `db:"title"` // 社区
Logo string `db:"logo"` // logo图片链接
Description string `db:"description"` // 描述
Status int8 `db:"status"` // 0=不启用1=启用
StartAt sql.NullTime `db:"start_at"` // 开始时间
EndAt sql.NullTime `db:"end_at"` // 结束时间
CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间
Sort int `db:"sort"` // 数字越小越靠前
}
)
func newNhTaskCommunityModel(conn sqlx.SqlConn) *defaultNhTaskCommunityModel {
return &defaultNhTaskCommunityModel{
conn: conn,
table: "`nh_task_community`",
}
}
func (m *defaultNhTaskCommunityModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhTaskCommunityModel) FindOne(ctx context.Context, id uint) (*NhTaskCommunity, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTaskCommunityRows, m.table)
var resp NhTaskCommunity
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhTaskCommunityModel) Insert(ctx context.Context, data *NhTaskCommunity) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskCommunityRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Title, data.Logo, data.Description, data.Status, data.StartAt, data.EndAt, data.Sort)
return ret, err
}
func (m *defaultNhTaskCommunityModel) Update(ctx context.Context, data *NhTaskCommunity) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskCommunityRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.Title, data.Logo, data.Description, data.Status, data.StartAt, data.EndAt, data.Sort, data.Id)
return err
}
func (m *defaultNhTaskCommunityModel) tableName() string {
return m.table
}

View File

@@ -21,6 +21,7 @@ const (
TASKTYPE_BIND_DISCORD = 7 TASKTYPE_BIND_DISCORD = 7
TASKTYPE_JOIN_TELEGRAM = 8 TASKTYPE_JOIN_TELEGRAM = 8
TASKTYPE_DAILY_PAY = 9 TASKTYPE_DAILY_PAY = 9
TASKTYPE_INVITE_USER = 10
) )
type ( type (
@@ -38,7 +39,7 @@ type (
) )
func (m *customNhTaskModel) FindTasksByCommunity(ctx context.Context, communityId uint) ([]*NhTask, error) { func (m *customNhTaskModel) FindTasksByCommunity(ctx context.Context, communityId uint) ([]*NhTask, error) {
query := fmt.Sprintf("select %s from %s where community_id = 0 or community_id = ?", nhTaskRows, m.table) query := fmt.Sprintf("select %s from %s where `status` = 1 and community_id = ? order by `sort`", nhTaskRows, m.table)
var tasks []*NhTask var tasks []*NhTask
err := m.conn.QueryRowsCtx(ctx, &tasks, query, communityId) err := m.conn.QueryRowsCtx(ctx, &tasks, query, communityId)
if err != nil && !errors.Is(err, sqlx.ErrNotFound) { if err != nil && !errors.Is(err, sqlx.ErrNotFound) {

View File

@@ -51,6 +51,8 @@ type (
EndAt sql.NullTime `db:"end_at"` // 结束时间 EndAt sql.NullTime `db:"end_at"` // 结束时间
CreatedAt time.Time `db:"created_at"` // 创建时间 CreatedAt time.Time `db:"created_at"` // 创建时间
UpdatedAt time.Time `db:"updated_at"` // 修改时间 UpdatedAt time.Time `db:"updated_at"` // 修改时间
Param string `db:"param"` // 备用参数,如果是邀请任务,可以填邀请的人数
Sort int `db:"sort"` // 数字越小越靠前
} }
) )
@@ -82,14 +84,14 @@ func (m *defaultNhTaskModel) FindOne(ctx context.Context, id uint) (*NhTask, err
} }
func (m *defaultNhTaskModel) Insert(ctx context.Context, data *NhTask) (sql.Result, error) { func (m *defaultNhTaskModel) Insert(ctx context.Context, data *NhTask) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskRowsExpectAutoSet) query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhTaskRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt) ret, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt, data.Param, data.Sort)
return ret, err return ret, err
} }
func (m *defaultNhTaskModel) Update(ctx context.Context, data *NhTask) error { func (m *defaultNhTaskModel) Update(ctx context.Context, data *NhTask) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskRowsWithPlaceHolder) query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt, data.Id) _, err := m.conn.ExecCtx(ctx, query, data.CommunityId, data.Title, data.SubTitle, data.Description, data.Points, data.ButtonText, data.Type, data.Url, data.Status, data.StartAt, data.EndAt, data.Param, data.Sort, data.Id)
return err return err
} }

View File

@@ -0,0 +1,29 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ NhTouristBindModel = (*customNhTouristBindModel)(nil)
type (
// NhTouristBindModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhTouristBindModel.
NhTouristBindModel interface {
nhTouristBindModel
withSession(session sqlx.Session) NhTouristBindModel
}
customNhTouristBindModel struct {
*defaultNhTouristBindModel
}
)
// NewNhTouristBindModel returns a model for the database table.
func NewNhTouristBindModel(conn sqlx.SqlConn) NhTouristBindModel {
return &customNhTouristBindModel{
defaultNhTouristBindModel: newNhTouristBindModel(conn),
}
}
func (m *customNhTouristBindModel) withSession(session sqlx.Session) NhTouristBindModel {
return NewNhTouristBindModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,87 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhTouristBindFieldNames = builder.RawFieldNames(&NhTouristBind{})
nhTouristBindRows = strings.Join(nhTouristBindFieldNames, ",")
nhTouristBindRowsExpectAutoSet = strings.Join(stringx.Remove(nhTouristBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhTouristBindRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTouristBindFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhTouristBindModel interface {
Insert(ctx context.Context, data *NhTouristBind) (sql.Result, error)
FindOne(ctx context.Context, id int) (*NhTouristBind, error)
Update(ctx context.Context, data *NhTouristBind) error
Delete(ctx context.Context, id int) error
}
defaultNhTouristBindModel struct {
conn sqlx.SqlConn
table string
}
NhTouristBind struct {
Id int `db:"id"`
TouristAccount string `db:"tourist_account"` // 游客账号
FormalAccount string `db:"formal_account"` // 正式账号
CreateTime int `db:"create_time"` // 创建时间
}
)
func newNhTouristBindModel(conn sqlx.SqlConn) *defaultNhTouristBindModel {
return &defaultNhTouristBindModel{
conn: conn,
table: "`nh_tourist_bind`",
}
}
func (m *defaultNhTouristBindModel) Delete(ctx context.Context, id int) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhTouristBindModel) FindOne(ctx context.Context, id int) (*NhTouristBind, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTouristBindRows, m.table)
var resp NhTouristBind
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhTouristBindModel) Insert(ctx context.Context, data *NhTouristBind) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?)", m.table, nhTouristBindRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.TouristAccount, data.FormalAccount)
return ret, err
}
func (m *defaultNhTouristBindModel) Update(ctx context.Context, data *NhTouristBind) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTouristBindRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.TouristAccount, data.FormalAccount, data.Id)
return err
}
func (m *defaultNhTouristBindModel) tableName() string {
return m.table
}

29
internal/model/nh_user_model.go Executable file
View File

@@ -0,0 +1,29 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ NhUserModel = (*customNhUserModel)(nil)
type (
// NhUserModel is an interface to be customized, add more methods here,
// and implement the added methods in customNhUserModel.
NhUserModel interface {
nhUserModel
withSession(session sqlx.Session) NhUserModel
}
customNhUserModel struct {
*defaultNhUserModel
}
)
// NewNhUserModel returns a model for the database table.
func NewNhUserModel(conn sqlx.SqlConn) NhUserModel {
return &customNhUserModel{
defaultNhUserModel: newNhUserModel(conn),
}
}
func (m *customNhUserModel) withSession(session sqlx.Session) NhUserModel {
return NewNhUserModel(sqlx.NewSqlConnFromSession(session))
}

View File

@@ -0,0 +1,108 @@
// Code generated by goctl. DO NOT EDIT.
// versions:
// goctl version: 1.7.3
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
nhUserFieldNames = builder.RawFieldNames(&NhUser{})
nhUserRows = strings.Join(nhUserFieldNames, ",")
nhUserRowsExpectAutoSet = strings.Join(stringx.Remove(nhUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
nhUserRowsWithPlaceHolder = strings.Join(stringx.Remove(nhUserFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
nhUserModel interface {
Insert(ctx context.Context, data *NhUser) (sql.Result, error)
FindOne(ctx context.Context, id uint) (*NhUser, error)
FindOneByEmail(ctx context.Context, email string) (*NhUser, error)
Update(ctx context.Context, data *NhUser) error
Delete(ctx context.Context, id uint) error
}
defaultNhUserModel struct {
conn sqlx.SqlConn
table string
}
NhUser struct {
Id uint `db:"id"`
Email string `db:"email"` // 邮箱
Password string `db:"password"` // 密码
CreateTime sql.NullInt64 `db:"create_time"` // 创建时间
InviteId int `db:"invite_id"` // 邀请码/测试码ID
LastLoginTime sql.NullInt64 `db:"last_login_time"` // 最后登陆时间
LastLoginIp string `db:"last_login_ip"` // 最后登录IP
Remarks sql.NullString `db:"remarks"` // 备注
Status uint8 `db:"status"` // 用户状态 1 正常 2 禁止
IsOpenSeason int8 `db:"is_open_season"` // 是否已开启赛季
}
)
func newNhUserModel(conn sqlx.SqlConn) *defaultNhUserModel {
return &defaultNhUserModel{
conn: conn,
table: "`nh_user`",
}
}
func (m *defaultNhUserModel) Delete(ctx context.Context, id uint) error {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, id)
return err
}
func (m *defaultNhUserModel) FindOne(ctx context.Context, id uint) (*NhUser, error) {
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhUserRows, m.table)
var resp NhUser
err := m.conn.QueryRowCtx(ctx, &resp, query, id)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhUserModel) FindOneByEmail(ctx context.Context, email string) (*NhUser, error) {
var resp NhUser
query := fmt.Sprintf("select %s from %s where `email` = ? limit 1", nhUserRows, m.table)
err := m.conn.QueryRowCtx(ctx, &resp, query, email)
switch err {
case nil:
return &resp, nil
case sqlx.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultNhUserModel) Insert(ctx context.Context, data *NhUser) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, nhUserRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.Email, data.Password, data.InviteId, data.LastLoginTime, data.LastLoginIp, data.Remarks, data.Status, data.IsOpenSeason)
return ret, err
}
func (m *defaultNhUserModel) Update(ctx context.Context, newData *NhUser) error {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhUserRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, newData.Email, newData.Password, newData.InviteId, newData.LastLoginTime, newData.LastLoginIp, newData.Remarks, newData.Status, newData.IsOpenSeason, newData.Id)
return err
}
func (m *defaultNhUserModel) tableName() string {
return m.table
}

View File

@@ -6,16 +6,14 @@ import (
) )
type err struct { type err struct {
code int code Reason
reason Reason msg string
msg string
} }
func New(code int, reason Reason, message any) error { func New(code Reason, message any) error {
return err{ return err{
code: code, code: code,
reason: reason, msg: cast.ToString(message),
msg: cast.ToString(message),
} }
} }
@@ -25,15 +23,10 @@ func (e err) Error() string {
} }
// Code return code // Code return code
func (e err) Code() int { func (e err) Code() Reason {
return e.code return e.code
} }
// Reason return reason
func (e err) Reason() Reason {
return e.reason
}
// Message return message // Message return message
func (e err) Message() string { func (e err) Message() string {
return e.msg return e.msg

View File

@@ -1,56 +1,5 @@
package errs package errs
import (
"net/http"
)
func Success() error { func Success() error {
return New(http.StatusOK, ErrSucceed, "success") return New(ErrSucceed, "ok")
}
func NotFound(reason Reason, v any) error {
return New(http.StatusNotFound, reason, v)
}
func BadRequest(reason Reason, v any) error {
return New(http.StatusBadRequest, reason, v)
}
func InternalServer(reason Reason, v any) error {
return New(http.StatusInternalServerError, reason, v)
}
// Unauthorized new Unauthorized error that is mapped to a 401 response.
func Unauthorized(reason Reason, v any) error {
return New(http.StatusUnauthorized, reason, v)
}
// Forbidden new Forbidden error that is mapped to a 403 response.
func Forbidden(reason Reason, v any) error {
return New(http.StatusForbidden, reason, v)
}
// Conflict new Conflict error that is mapped to a 409 response.
func Conflict(reason Reason, v any) error {
return New(http.StatusConflict, reason, v)
}
// ServiceUnavailable new ServiceUnavailable error that is mapped to an HTTP 503 response.
func ServiceUnavailable(reason Reason, v any) error {
return New(http.StatusServiceUnavailable, reason, v)
}
// GatewayTimeout new GatewayTimeout error that is mapped to an HTTP 504 response.
func GatewayTimeout(reason Reason, v any) error {
return New(http.StatusGatewayTimeout, reason, v)
}
// BadGateway new BadGateway error that is mapped to an HTTP 504 response.
func BadGateway(reason Reason, v any) error {
return New(http.StatusBadGateway, reason, v)
}
// ClientClosed new ClientClosed error that is mapped to an HTTP 499 response.
func ClientClosed(reason Reason, v any) error {
return New(499, reason, v)
} }

View File

@@ -2,24 +2,45 @@ package errs
import ( import (
"context" "context"
"encoding/json"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/rest/httpx" "github.com/zeromicro/go-zero/rest/httpx"
"net/http" "net/http"
"os"
"strings"
) )
var debug bool
func init() { func init() {
if strings.ToLower(os.Getenv("VANS_API_DEBUG")) == "on" {
debug = true
}
httpx.SetErrorHandlerCtx(ErrorHandleCtx) httpx.SetErrorHandlerCtx(ErrorHandleCtx)
httpx.SetErrorHandler(ErrorHandle) httpx.SetErrorHandler(ErrorHandle)
httpx.SetOkHandler(OkHandle)
} }
func SetDebug(d bool) { func OkHandle(ctx context.Context, v any) any {
debug = d return map[string]any{
"status": map[string]any{
"code": ErrSucceed,
"msg": "ok",
},
"data": v,
}
}
func WithUnauthorizedCallback() rest.RunOption {
return rest.WithUnauthorizedCallback(func(w http.ResponseWriter, r *http.Request, err error) {
body := map[string]any{
"status": map[string]any{
"code": ErrUnauthorized,
"msg": err.Error(),
},
}
data, _ := json.Marshal(body)
w.Header().Set(httpx.ContentType, "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
_, err = w.Write(data)
if err != nil {
logx.Errorw("error write response", logx.Field("type", "http"), logx.Field("error", err))
}
})
} }
func ErrorHandle(err error) (int, any) { func ErrorHandle(err error) (int, any) {
@@ -27,10 +48,9 @@ func ErrorHandle(err error) (int, any) {
} }
func ErrorHandleCtx(ctx context.Context, err error) (int, any) { func ErrorHandleCtx(ctx context.Context, err error) (int, any) {
code := http.StatusBadRequest code := ErrUnknownReason
reason := ErrInternalServer
var msg string var msg string
if ec, ok := err.(interface{ Code() int }); ok { if ec, ok := err.(interface{ Code() Reason }); ok {
code = ec.Code() code = ec.Code()
} }
if ec, ok := err.(interface{ Message() string }); ok { if ec, ok := err.(interface{ Message() string }); ok {
@@ -38,27 +58,17 @@ func ErrorHandleCtx(ctx context.Context, err error) (int, any) {
} else { } else {
msg = err.Error() msg = err.Error()
} }
if ec, ok := err.(interface{ Reason() Reason }); ok {
reason = ec.Reason()
}
var errMsg string if code < ErrUnknownReason && code >= ErrInternalServer {
if reason < ErrUnknownLogicError && reason != ErrSucceed { logx.Errorw("request system error", logx.Field("err-msg", msg))
errMsg = msg
msg = "system error" msg = "system error"
} }
body := map[string]any{ body := map[string]any{
"code": reason, "status": map[string]any{
"message": msg, "code": code,
"msg": msg,
},
} }
if errMsg != "" && debug { return http.StatusOK, body
body["err"] = errMsg
}
if ec, ok := err.(interface{ Metadata() any }); ok {
if md := ec.Metadata(); md != nil {
body["metadata"] = md
}
}
return code, body
} }

View File

@@ -3,10 +3,11 @@ package errs
type Reason int type Reason int
const ( const (
// ======= 系统错误:0~999 ======= // ======= 系统错误:10000~19999 =======
ErrUnknownReason Reason = 0 // 未知错误 ErrUnknownReason Reason = 10000 // 未知错误
ErrSucceed Reason = 200 // 成功 ErrSucceed Reason = 10200 // 成功
ErrOverload Reason = 403 // 请求超载 ErrUnauthorized Reason = 10401 // 未授权
ErrOverload Reason = 10403 // 请求超载
// ======= 服务器内部错误1000~9999 ======= // ======= 服务器内部错误1000~9999 =======
ErrInternalServer Reason = 1000 // 未知的服务器内部错误 ErrInternalServer Reason = 1000 // 未知的服务器内部错误
@@ -15,22 +16,10 @@ const (
ErrEncodePassword Reason = 1003 // 密码加密错误 ErrEncodePassword Reason = 1003 // 密码加密错误
ErrGenerateUUid Reason = 1004 // 生成uuid错误 ErrGenerateUUid Reason = 1004 // 生成uuid错误
ErrGenerateToken Reason = 1005 // 生成token错误 ErrGenerateToken Reason = 1005 // 生成token错误
ErrGetExchangeRate Reason = 1005 // 获取汇率错误
// ======= 业务层错误:10000~99999 ======= // ======= 业务层错误:20000~29999 =======
ErrUnknownLogicError Reason = 10000 // 未知的业务错误 ErrUnknownLogicError Reason = 20000 // 未知的业务错误
ErrInvalidParam Reason = 10001 // 无效参数错误 ErrTaskNotFound Reason = 20001 // 任务不存在
ErrInvalidSignature Reason = 10002 // 无效签名错误 ErrTaskAlreadyReward Reason = 20002 // 任务已领取
ErrInvalidToken Reason = 10003 // 无效的token ErrTaskNotFinished Reason = 20003 // 任务未完成
ErrInvoiceHasPaid Reason = 10004 // 订单已支付
ErrInvalidAppId Reason = 10005 // 应用id无效
ErrUserNotHasInviter Reason = 10006 // 用户没有邀请人
ErrTaskNotFound Reason = 10007 // 任务不存在
ErrTaskAlreadyReward Reason = 10008 // 任务已领取
ErrTaskNotFinished Reason = 10009 // 任务未完成
// ========= admin 业务相关错误码: 30000~39999 =========
ErrUnknownAdminError Reason = 30000 // 未知的admin错误
ErrInvalidPassword Reason = 30001 // 无效密码
ErrInvalidAccount Reason = 30002 // 无效账号
) )

View File

@@ -9,27 +9,38 @@ import (
) )
type ServiceContext struct { type ServiceContext struct {
Config config.Config Config config.Config
TaskModel model.NhTaskModel TaskModel model.NhTaskModel
TaskAssetModel model.NhTaskAssetModel TaskAssetModel model.NhTaskAssetModel
TaskAssetRecordModel model.NhTaskAssetRecordModel TaskAssetRecordModel model.NhTaskAssetRecordModel
TaskProgressModel model.NhTaskProgressModel TaskProgressModel model.NhTaskProgressModel
TwitterModel model.NhTwitterModel TwitterModel model.NhTwitterModel
Earn *ea.Client PromoteBindModel model.NhPromoteBindModel
DBConn sqlx.SqlConn TouristBindModel model.NhTouristBindModel
CommunityModel model.NhTaskCommunityModel
UserModel model.NhUserModel
Earn *ea.Client
DBConn sqlx.SqlConn
} }
func NewServiceContext(c config.Config) *ServiceContext { func NewServiceContext(c config.Config) *ServiceContext {
dbConn := c.MySql.Conn() dbConn := c.MySql.Conn()
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
TaskModel: model.NewNhTaskModel(dbConn), TaskModel: model.NewNhTaskModel(dbConn),
TaskAssetModel: model.NewNhTaskAssetModel(dbConn), TaskAssetModel: model.NewNhTaskAssetModel(dbConn),
TaskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn), TaskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn),
TaskProgressModel: model.NewNhTaskProgressModel(dbConn), TaskProgressModel: model.NewNhTaskProgressModel(dbConn),
TwitterModel: model.NewNhTwitterModel(dbConn), TwitterModel: model.NewNhTwitterModel(dbConn),
Earn: c.Earn.BuildEarnClient(), PromoteBindModel: model.NewNhPromoteBindModel(dbConn),
DBConn: dbConn, CommunityModel: model.NewNhTaskCommunityModel(dbConn),
UserModel: model.NewNhUserModel(dbConn),
Earn: c.Earn.BuildEarnClient(),
DBConn: dbConn,
} }
} }

View File

@@ -3,6 +3,19 @@
package types package types
type Community struct {
Id uint `json:"id"` // 社区ID
Title string `json:"title"` // 社区标题
Logo string `json:"logo"` // 社区图标
Description string `json:"description"` // 社区描述
StartAt int64 `json:"start_at"` // 开始时间
EndAt int64 `json:"end_at"` // 结束时间
}
type GetCommunityListResp struct {
CommunityList []Community `json:"community_list"` // 社区列表
}
type GetTaskListReq struct { type GetTaskListReq struct {
CommunityId uint `form:"community_id,optional"` // 所属社区ID CommunityId uint `form:"community_id,optional"` // 所属社区ID
} }
@@ -16,25 +29,33 @@ type GetTaskRewardResp struct {
} }
type Task struct { type Task struct {
Id uint `json:"id"` // 任务ID Id uint `json:"id"` // 任务ID
CommunityId uint `json:"community_id"` // 所属社区ID CommunityId uint `json:"community_id"` // 所属社区ID
Title string `json:"title"` // 任务标题 Title string `json:"title"` // 任务标题
SubTitle string `json:"sub_title"` // 副标题 SubTitle string `json:"sub_title"` // 副标题
Description string `json:"description"` // 任务描述 Description string `json:"description"` // 任务描述
Points int `json:"points"` // 任务积分 Points int `json:"points"` // 任务积分
ButtonText string `json:"button_text"` // 按钮文字 ButtonText string `json:"button_text"` // 按钮文字
Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay Params string `json:"params"` // 参数
Url string `json:"url"` // 跳转链接 Type int8 `json:"type"` // 任务类型: 0=follow_twitter,1=bind_twitter,2=cast_twitter,3=publish_twitter,4=repost_twitter,5=watch_youtube,6=follow_youtube,7=bind_discord,8=join_telegram,9=daily_pay,10=invite_user
Status int8 `json:"status"` // 任务状态: 0=不启用1=启用 Url string `json:"url"` // 跳转链接
StartAt string `json:"start_at"` // 开始时间 Sort int `json:"sort"` // 排序
EndAt string `json:"end_at"` // 结束时间 StartAt string `json:"start_at"` // 开始时间
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取 EndAt string `json:"end_at"` // 结束时间
HasFinishCount int `json:"has_finish_count"` // 当前完成进度
TotalCount int `json:"total_count"` // 总进度
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取
} }
type TaskIdPath struct { type TaskIdPath struct {
ID uint `path:"id"` // 任务ID ID uint `path:"id"` // 任务ID
} }
type VerifyTaskResultReq struct {
ID uint `form:"id"` // 任务ID
Params string `form:"params,optional"` // 额外的参数
}
type VerifyTaskResultResp struct { type VerifyTaskResultResp struct {
Finish bool `json:"finish"` // 是否完成 Finish bool `json:"finish"` // 是否完成
} }

View File

@@ -3,9 +3,11 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/zeromicro/go-zero/core/service"
"nova_task/internal/config" "nova_task/internal/config"
"nova_task/internal/handler" "nova_task/internal/handler"
"nova_task/internal/job"
"nova_task/internal/pkg/errs"
"nova_task/internal/svc" "nova_task/internal/svc"
"github.com/zeromicro/go-zero/core/conf" "github.com/zeromicro/go-zero/core/conf"
@@ -21,14 +23,19 @@ func main() {
conf.MustLoad(*configFile, &c) conf.MustLoad(*configFile, &c)
c.MustSetUp() c.MustSetUp()
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
ctx := svc.NewServiceContext(c) ctx := svc.NewServiceContext(c)
defer ctx.Close() defer ctx.Close()
handler.RegisterHandlers(server, ctx) serviceGroup := service.NewServiceGroup()
defer serviceGroup.Stop()
jb := job.NewJob(ctx)
serviceGroup.Add(jb)
httpSvr := rest.MustNewServer(c.RestConf, rest.WithCors(), errs.WithUnauthorizedCallback())
handler.RegisterHandlers(httpSvr, ctx)
serviceGroup.Add(httpSvr)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start() serviceGroup.Start()
} }