From a3c4adfa256888ecd8610b0798f1b65f96daae0e Mon Sep 17 00:00:00 2001 From: lianghuanjie Date: Thu, 19 Dec 2024 21:14:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=A4=BE=E5=8C=BA=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8E=A5=E5=8F=A3=EF=BC=8C=E4=BB=BB=E5=8A=A1=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=8E=A5=E5=8F=A3=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 3 +- doc/api/nova-task.api | 53 +++++-- doc/swagger/nova-task.json | 135 +++++++++++++++++- go.mod | 2 + go.sum | 4 + internal/handler/routes.go | 8 +- .../task/get_community_list_handler.go | 22 +++ .../task/verify_task_result_handler.go | 2 +- internal/job/earn/earn.go | 61 ++++++++ internal/job/job.go | 63 ++++++++ internal/job/pledge/pledge.go | 26 ++++ .../logic/task/get_community_list_logic.go | 48 +++++++ internal/logic/task/get_task_list_logic.go | 54 +++++-- internal/logic/task/get_task_reward_logic.go | 14 +- .../logic/task/verify_task_result_logic.go | 17 ++- internal/model/nh_promote_bind_model.go | 81 +++++++++++ internal/model/nh_promote_bind_model_gen.go | 104 ++++++++++++++ internal/model/nh_task_community_model.go | 45 ++++++ internal/model/nh_task_community_model_gen.go | 94 ++++++++++++ internal/model/nh_task_model.go | 3 +- internal/model/nh_task_model_gen.go | 8 +- internal/model/nh_tourist_bind_model.go | 29 ++++ internal/model/nh_tourist_bind_model_gen.go | 87 +++++++++++ internal/model/nh_user_model.go | 29 ++++ internal/model/nh_user_model_gen.go | 108 ++++++++++++++ internal/pkg/errs/error.go | 19 +-- internal/pkg/errs/errors.go | 53 +------ internal/pkg/errs/http_respone.go | 68 +++++---- internal/pkg/errs/reason.go | 31 ++-- internal/svc/service_context.go | 23 ++- internal/types/types.go | 47 ++++-- novatask.go | 19 ++- 32 files changed, 1163 insertions(+), 197 deletions(-) create mode 100644 internal/handler/task/get_community_list_handler.go create mode 100644 internal/job/earn/earn.go create mode 100644 internal/job/job.go create mode 100644 internal/job/pledge/pledge.go create mode 100644 internal/logic/task/get_community_list_logic.go create mode 100755 internal/model/nh_promote_bind_model.go create mode 100755 internal/model/nh_promote_bind_model_gen.go create mode 100755 internal/model/nh_task_community_model.go create mode 100755 internal/model/nh_task_community_model_gen.go create mode 100755 internal/model/nh_tourist_bind_model.go create mode 100755 internal/model/nh_tourist_bind_model_gen.go create mode 100755 internal/model/nh_user_model.go create mode 100755 internal/model/nh_user_model_gen.go diff --git a/Makefile b/Makefile index 51f0895..15795af 100644 --- a/Makefile +++ b/Makefile @@ -37,8 +37,7 @@ build: .PHONY: img # 构建Docker镜像 img: - docker build --platform=amd64 -t nova-task:latest . - docker tag `docker images -aq -f "reference=nova-task:latest"` harbor.phantom-u3d002.com/nova/nova-task:latest + docker build --platform=amd64 -t harbor.phantom-u3d002.com/nova/nova-task:latest . .PHONY: push push: diff --git a/doc/api/nova-task.api b/doc/api/nova-task.api index 3ecd187..d1e806e 100644 --- a/doc/api/nova-task.api +++ b/doc/api/nova-task.api @@ -8,6 +8,10 @@ service novatask { @doc "获取任务列表" @handler GetTaskList get /tasks (GetTaskListReq) returns (GetTaskListResp) + + @doc "获取社区列表" + @handler GetCommunityList + get /community returns (GetCommunityListResp) } @server ( @@ -18,7 +22,7 @@ service novatask { service novatask { @doc "校验任务结果" @handler VerifyTaskResult - get /task/:id (TaskIdPath) returns (VerifyTaskResultResp) + get /task (VerifyTaskResultReq) returns (VerifyTaskResultResp) @doc "领取任务奖励" @handler GetTaskReward @@ -30,25 +34,33 @@ type GetTaskListReq { } type Task { - Id uint `json:"id"` // 任务ID - CommunityId uint `json:"community_id"` // 所属社区ID - Title string `json:"title"` // 任务标题 - SubTitle string `json:"sub_title"` // 副标题 - Description string `json:"description"` // 任务描述 - Points int `json:"points"` // 任务积分 - 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 - Url string `json:"url"` // 跳转链接 - Status int8 `json:"status"` // 任务状态: 0=不启用,1=启用 - StartAt string `json:"start_at"` // 开始时间 - EndAt string `json:"end_at"` // 结束时间 - FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取 + Id uint `json:"id"` // 任务ID + CommunityId uint `json:"community_id"` // 所属社区ID + Title string `json:"title"` // 任务标题 + SubTitle string `json:"sub_title"` // 副标题 + Description string `json:"description"` // 任务描述 + Points int `json:"points"` // 任务积分 + ButtonText string `json:"button_text"` // 按钮文字 + Params string `json:"params"` // 参数 + 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 + Url string `json:"url"` // 跳转链接 + Sort int `json:"sort"` // 排序 + StartAt string `json:"start_at"` // 开始时间 + 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 { Tasks []Task `json:"tasks"` } +type VerifyTaskResultReq { + ID uint `form:"id"` // 任务ID + Params string `form:"params,optional"` // 额外的参数 +} + type TaskIdPath { ID uint `path:"id"` // 任务ID } @@ -61,3 +73,16 @@ type GetTaskRewardResp { 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"` // 社区列表 +} + diff --git a/doc/swagger/nova-task.json b/doc/swagger/nova-task.json index 2dc6008..73aef71 100644 --- a/doc/swagger/nova-task.json +++ b/doc/swagger/nova-task.json @@ -15,6 +15,23 @@ "application/json" ], "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}": { "get": { "summary": "领取任务奖励", @@ -45,7 +62,7 @@ ] } }, - "/gapi/task/v1/task/{id}": { + "/gapi/task/v1/task": { "get": { "summary": "校验任务结果", "operationId": "VerifyTaskResult", @@ -60,14 +77,26 @@ "parameters": [ { "name": "id", - "in": "path", + "description": " 任务ID", + "in": "query", "required": true, + "type": "integer", + "format": "uint32" + }, + { + "name": "params", + "description": " 额外的参数", + "in": "query", + "required": false, "type": "string" } ], "tags": [ "task" ], + "consumes": [ + "multipart/form-data" + ], "security": [ { "apiKey": [] @@ -107,6 +136,63 @@ } }, "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": { "type": "object", "properties": { @@ -181,19 +267,23 @@ "type": "string", "description": " 按钮文字" }, + "params": { + "type": "string", + "description": " 参数" + }, "type": { "type": "integer", "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": { "type": "string", "description": " 跳转链接" }, - "status": { + "sort": { "type": "integer", - "format": "int8", - "description": " 任务状态: 0=不启用,1=启用" + "format": "int32", + "description": " 排序" }, "start_at": { "type": "string", @@ -203,6 +293,16 @@ "type": "string", "description": " 结束时间" }, + "has_finish_count": { + "type": "integer", + "format": "int32", + "description": " 当前完成进度" + }, + "total_count": { + "type": "integer", + "format": "int32", + "description": " 总进度" + }, "finish_state": { "type": "integer", "format": "int8", @@ -218,11 +318,14 @@ "description", "points", "button_text", + "params", "type", "url", - "status", + "sort", "start_at", "end_at", + "has_finish_count", + "total_count", "finish_state" ] }, @@ -230,6 +333,24 @@ "type": "object", "title": "TaskIdPath" }, + "VerifyTaskResultReq": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "uint32", + "description": " 任务ID" + }, + "params": { + "type": "string", + "description": " 额外的参数" + } + }, + "title": "VerifyTaskResultReq", + "required": [ + "id" + ] + }, "VerifyTaskResultResp": { "type": "object", "properties": { diff --git a/go.mod b/go.mod index b17c2fd..a4f7ed1 100644 --- a/go.mod +++ b/go.mod @@ -30,12 +30,14 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // 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/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // 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 go.opentelemetry.io/otel v1.24.0 // indirect go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect diff --git a/go.sum b/go.sum index 03c2f8f..4514aef 100644 --- a/go.sum +++ b/go.sum @@ -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/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/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/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= 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/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 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/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= diff --git a/internal/handler/routes.go b/internal/handler/routes.go index 3604d21..e3ef417 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -15,6 +15,12 @@ import ( func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { server.AddRoutes( []rest.Route{ + { + // 获取社区列表 + Method: http.MethodGet, + Path: "/community", + Handler: task.GetCommunityListHandler(serverCtx), + }, { // 获取任务列表 Method: http.MethodGet, @@ -36,7 +42,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { { // 校验任务结果 Method: http.MethodGet, - Path: "/task/:id", + Path: "/task", Handler: task.VerifyTaskResultHandler(serverCtx), }, }, diff --git a/internal/handler/task/get_community_list_handler.go b/internal/handler/task/get_community_list_handler.go new file mode 100644 index 0000000..0308ab8 --- /dev/null +++ b/internal/handler/task/get_community_list_handler.go @@ -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) + } + } +} diff --git a/internal/handler/task/verify_task_result_handler.go b/internal/handler/task/verify_task_result_handler.go index e12b835..0586809 100644 --- a/internal/handler/task/verify_task_result_handler.go +++ b/internal/handler/task/verify_task_result_handler.go @@ -12,7 +12,7 @@ import ( // 校验任务结果 func VerifyTaskResultHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.TaskIdPath + var req types.VerifyTaskResultReq if err := httpx.Parse(r, &req); err != nil { httpx.ErrorCtx(r.Context(), w, err) return diff --git a/internal/job/earn/earn.go b/internal/job/earn/earn.go new file mode 100644 index 0000000..daf1812 --- /dev/null +++ b/internal/job/earn/earn.go @@ -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() {} diff --git a/internal/job/job.go b/internal/job/job.go new file mode 100644 index 0000000..fd05c32 --- /dev/null +++ b/internal/job/job.go @@ -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() +} diff --git a/internal/job/pledge/pledge.go b/internal/job/pledge/pledge.go new file mode 100644 index 0000000..bbb6aba --- /dev/null +++ b/internal/job/pledge/pledge.go @@ -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() { + +} diff --git a/internal/logic/task/get_community_list_logic.go b/internal/logic/task/get_community_list_logic.go new file mode 100644 index 0000000..500270f --- /dev/null +++ b/internal/logic/task/get_community_list_logic.go @@ -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 +} diff --git a/internal/logic/task/get_task_list_logic.go b/internal/logic/task/get_task_list_logic.go index 2e58d9c..7b3031a 100644 --- a/internal/logic/task/get_task_list_logic.go +++ b/internal/logic/task/get_task_list_logic.go @@ -33,7 +33,12 @@ func (l *GetTaskListLogic) GetTaskList(uid int, req *types.GetTaskListReq) (*typ tasks, err := l.svcCtx.TaskModel.FindTasksByCommunity(l.ctx, req.CommunityId) if err != nil { 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{} @@ -44,25 +49,46 @@ func (l *GetTaskListLogic) GetTaskList(uid int, req *types.GetTaskListReq) (*typ } var finishState int8 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 { 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{ - Id: t.Id, - Title: t.Title, - SubTitle: t.SubTitle, - Description: t.Description, - Points: t.Points, - ButtonText: t.ButtonText, - Type: t.Type, - Url: t.Url, - StartAt: t.StartAt.Time.Format(time.DateTime), - EndAt: t.EndAt.Time.Format(time.DateTime), - Status: t.Status, - FinishState: finishState, + Id: t.Id, + Title: t.Title, + SubTitle: t.SubTitle, + Description: t.Description, + Points: t.Points, + ButtonText: t.ButtonText, + Params: t.Param, + Type: t.Type, + Url: t.Url, + StartAt: t.StartAt.Time.Format(time.DateTime), + EndAt: t.EndAt.Time.Format(time.DateTime), + Sort: t.Sort, + HasFinishCount: hasFinishCount, + TotalCount: totalCount, + FinishState: finishState, }) } diff --git a/internal/logic/task/get_task_reward_logic.go b/internal/logic/task/get_task_reward_logic.go index 14c92ed..7ba9334 100644 --- a/internal/logic/task/get_task_reward_logic.go +++ b/internal/logic/task/get_task_reward_logic.go @@ -35,9 +35,9 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID) if err != nil { 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 if task.Type == model.TASKTYPE_DAILY_PAY { @@ -47,15 +47,15 @@ func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (*types.GetTas if err != nil { if !errors.Is(err, model.ErrNotFound) { 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 { 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: - 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 { 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 diff --git a/internal/logic/task/verify_task_result_logic.go b/internal/logic/task/verify_task_result_logic.go index 6e8ec2d..52c8690 100644 --- a/internal/logic/task/verify_task_result_logic.go +++ b/internal/logic/task/verify_task_result_logic.go @@ -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"] task, err := l.svcCtx.TaskModel.FindOne(l.ctx, req.ID) if err != nil { 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 if task.Type == model.TASKTYPE_DAILY_PAY { @@ -44,7 +44,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types. if err != nil { if !errors.Is(err, model.ErrNotFound) { 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{ Uid: uid, @@ -54,7 +54,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types. } } 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: 校验用户是否完成该任务 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)) if err != nil { 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 } @@ -72,6 +72,9 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types. case model.TASKTYPE_BIND_DISCORD: case model.TASKTYPE_DAILY_PAY: + if req.Params == "" { + return &types.VerifyTaskResultResp{Finish: false}, nil + } default: } @@ -84,7 +87,7 @@ func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types. if err != nil { 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 diff --git a/internal/model/nh_promote_bind_model.go b/internal/model/nh_promote_bind_model.go new file mode 100755 index 0000000..1d7268c --- /dev/null +++ b/internal/model/nh_promote_bind_model.go @@ -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 +} diff --git a/internal/model/nh_promote_bind_model_gen.go b/internal/model/nh_promote_bind_model_gen.go new file mode 100755 index 0000000..b43e600 --- /dev/null +++ b/internal/model/nh_promote_bind_model_gen.go @@ -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 +} diff --git a/internal/model/nh_task_community_model.go b/internal/model/nh_task_community_model.go new file mode 100755 index 0000000..1f4d0c2 --- /dev/null +++ b/internal/model/nh_task_community_model.go @@ -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)) +} diff --git a/internal/model/nh_task_community_model_gen.go b/internal/model/nh_task_community_model_gen.go new file mode 100755 index 0000000..5513197 --- /dev/null +++ b/internal/model/nh_task_community_model_gen.go @@ -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 +} diff --git a/internal/model/nh_task_model.go b/internal/model/nh_task_model.go index d0f2897..5c878cf 100755 --- a/internal/model/nh_task_model.go +++ b/internal/model/nh_task_model.go @@ -21,6 +21,7 @@ const ( TASKTYPE_BIND_DISCORD = 7 TASKTYPE_JOIN_TELEGRAM = 8 TASKTYPE_DAILY_PAY = 9 + TASKTYPE_INVITE_USER = 10 ) type ( @@ -38,7 +39,7 @@ type ( ) 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 err := m.conn.QueryRowsCtx(ctx, &tasks, query, communityId) if err != nil && !errors.Is(err, sqlx.ErrNotFound) { diff --git a/internal/model/nh_task_model_gen.go b/internal/model/nh_task_model_gen.go index b865cb4..8c16d08 100755 --- a/internal/model/nh_task_model_gen.go +++ b/internal/model/nh_task_model_gen.go @@ -51,6 +51,8 @@ type ( EndAt sql.NullTime `db:"end_at"` // 结束时间 CreatedAt time.Time `db:"created_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) { - 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) + 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, data.Param, data.Sort) return ret, err } func (m *defaultNhTaskModel) Update(ctx context.Context, data *NhTask) error { 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 } diff --git a/internal/model/nh_tourist_bind_model.go b/internal/model/nh_tourist_bind_model.go new file mode 100755 index 0000000..ca4a563 --- /dev/null +++ b/internal/model/nh_tourist_bind_model.go @@ -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)) +} diff --git a/internal/model/nh_tourist_bind_model_gen.go b/internal/model/nh_tourist_bind_model_gen.go new file mode 100755 index 0000000..c280671 --- /dev/null +++ b/internal/model/nh_tourist_bind_model_gen.go @@ -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 +} diff --git a/internal/model/nh_user_model.go b/internal/model/nh_user_model.go new file mode 100755 index 0000000..add7193 --- /dev/null +++ b/internal/model/nh_user_model.go @@ -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)) +} diff --git a/internal/model/nh_user_model_gen.go b/internal/model/nh_user_model_gen.go new file mode 100755 index 0000000..745178c --- /dev/null +++ b/internal/model/nh_user_model_gen.go @@ -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 +} diff --git a/internal/pkg/errs/error.go b/internal/pkg/errs/error.go index c3197c8..fe8ad0e 100644 --- a/internal/pkg/errs/error.go +++ b/internal/pkg/errs/error.go @@ -6,16 +6,14 @@ import ( ) type err struct { - code int - reason Reason - msg string + code Reason + msg string } -func New(code int, reason Reason, message any) error { +func New(code Reason, message any) error { return err{ - code: code, - reason: reason, - msg: cast.ToString(message), + code: code, + msg: cast.ToString(message), } } @@ -25,15 +23,10 @@ func (e err) Error() string { } // Code return code -func (e err) Code() int { +func (e err) Code() Reason { return e.code } -// Reason return reason -func (e err) Reason() Reason { - return e.reason -} - // Message return message func (e err) Message() string { return e.msg diff --git a/internal/pkg/errs/errors.go b/internal/pkg/errs/errors.go index 169c930..f767e11 100644 --- a/internal/pkg/errs/errors.go +++ b/internal/pkg/errs/errors.go @@ -1,56 +1,5 @@ package errs -import ( - "net/http" -) - func Success() error { - return New(http.StatusOK, ErrSucceed, "success") -} - -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) + return New(ErrSucceed, "ok") } diff --git a/internal/pkg/errs/http_respone.go b/internal/pkg/errs/http_respone.go index 0f1ed37..0162d6e 100644 --- a/internal/pkg/errs/http_respone.go +++ b/internal/pkg/errs/http_respone.go @@ -2,24 +2,45 @@ package errs import ( "context" + "encoding/json" + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/rest" "github.com/zeromicro/go-zero/rest/httpx" "net/http" - "os" - "strings" ) -var debug bool - func init() { - if strings.ToLower(os.Getenv("VANS_API_DEBUG")) == "on" { - debug = true - } httpx.SetErrorHandlerCtx(ErrorHandleCtx) httpx.SetErrorHandler(ErrorHandle) + httpx.SetOkHandler(OkHandle) } -func SetDebug(d bool) { - debug = d +func OkHandle(ctx context.Context, v any) any { + 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) { @@ -27,10 +48,9 @@ func ErrorHandle(err error) (int, any) { } func ErrorHandleCtx(ctx context.Context, err error) (int, any) { - code := http.StatusBadRequest - reason := ErrInternalServer + code := ErrUnknownReason var msg string - if ec, ok := err.(interface{ Code() int }); ok { + if ec, ok := err.(interface{ Code() Reason }); ok { code = ec.Code() } if ec, ok := err.(interface{ Message() string }); ok { @@ -38,27 +58,17 @@ func ErrorHandleCtx(ctx context.Context, err error) (int, any) { } else { msg = err.Error() } - if ec, ok := err.(interface{ Reason() Reason }); ok { - reason = ec.Reason() - } - var errMsg string - if reason < ErrUnknownLogicError && reason != ErrSucceed { - errMsg = msg + if code < ErrUnknownReason && code >= ErrInternalServer { + logx.Errorw("request system error", logx.Field("err-msg", msg)) msg = "system error" } body := map[string]any{ - "code": reason, - "message": msg, + "status": map[string]any{ + "code": code, + "msg": msg, + }, } - if errMsg != "" && debug { - body["err"] = errMsg - } - if ec, ok := err.(interface{ Metadata() any }); ok { - if md := ec.Metadata(); md != nil { - body["metadata"] = md - } - } - return code, body + return http.StatusOK, body } diff --git a/internal/pkg/errs/reason.go b/internal/pkg/errs/reason.go index d7d5495..06ca23d 100644 --- a/internal/pkg/errs/reason.go +++ b/internal/pkg/errs/reason.go @@ -3,10 +3,11 @@ package errs type Reason int const ( - // ======= 系统错误:0~999 ======= - ErrUnknownReason Reason = 0 // 未知错误 - ErrSucceed Reason = 200 // 成功 - ErrOverload Reason = 403 // 请求超载 + // ======= 系统错误:10000~19999 ======= + ErrUnknownReason Reason = 10000 // 未知错误 + ErrSucceed Reason = 10200 // 成功 + ErrUnauthorized Reason = 10401 // 未授权 + ErrOverload Reason = 10403 // 请求超载 // ======= 服务器内部错误:1000~9999 ======= ErrInternalServer Reason = 1000 // 未知的服务器内部错误 @@ -15,22 +16,10 @@ const ( ErrEncodePassword Reason = 1003 // 密码加密错误 ErrGenerateUUid Reason = 1004 // 生成uuid错误 ErrGenerateToken Reason = 1005 // 生成token错误 - ErrGetExchangeRate Reason = 1005 // 获取汇率错误 - // ======= 业务层错误:10000~99999 ======= - ErrUnknownLogicError Reason = 10000 // 未知的业务错误 - ErrInvalidParam Reason = 10001 // 无效参数错误 - ErrInvalidSignature Reason = 10002 // 无效签名错误 - ErrInvalidToken Reason = 10003 // 无效的token - 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 // 无效账号 + // ======= 业务层错误:20000~29999 ======= + ErrUnknownLogicError Reason = 20000 // 未知的业务错误 + ErrTaskNotFound Reason = 20001 // 任务不存在 + ErrTaskAlreadyReward Reason = 20002 // 任务已领取 + ErrTaskNotFinished Reason = 20003 // 任务未完成 ) diff --git a/internal/svc/service_context.go b/internal/svc/service_context.go index 8e489d7..59881c4 100644 --- a/internal/svc/service_context.go +++ b/internal/svc/service_context.go @@ -9,27 +9,38 @@ import ( ) type ServiceContext struct { - Config config.Config + Config config.Config + TaskModel model.NhTaskModel TaskAssetModel model.NhTaskAssetModel TaskAssetRecordModel model.NhTaskAssetRecordModel TaskProgressModel model.NhTaskProgressModel TwitterModel model.NhTwitterModel - Earn *ea.Client - DBConn sqlx.SqlConn + PromoteBindModel model.NhPromoteBindModel + TouristBindModel model.NhTouristBindModel + CommunityModel model.NhTaskCommunityModel + UserModel model.NhUserModel + + Earn *ea.Client + DBConn sqlx.SqlConn } func NewServiceContext(c config.Config) *ServiceContext { dbConn := c.MySql.Conn() return &ServiceContext{ - Config: c, + Config: c, + TaskModel: model.NewNhTaskModel(dbConn), TaskAssetModel: model.NewNhTaskAssetModel(dbConn), TaskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn), TaskProgressModel: model.NewNhTaskProgressModel(dbConn), TwitterModel: model.NewNhTwitterModel(dbConn), - Earn: c.Earn.BuildEarnClient(), - DBConn: dbConn, + PromoteBindModel: model.NewNhPromoteBindModel(dbConn), + CommunityModel: model.NewNhTaskCommunityModel(dbConn), + UserModel: model.NewNhUserModel(dbConn), + + Earn: c.Earn.BuildEarnClient(), + DBConn: dbConn, } } diff --git a/internal/types/types.go b/internal/types/types.go index 6f8734b..b0ebded 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -3,6 +3,19 @@ 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 { CommunityId uint `form:"community_id,optional"` // 所属社区ID } @@ -16,25 +29,33 @@ type GetTaskRewardResp struct { } type Task struct { - Id uint `json:"id"` // 任务ID - CommunityId uint `json:"community_id"` // 所属社区ID - Title string `json:"title"` // 任务标题 - SubTitle string `json:"sub_title"` // 副标题 - Description string `json:"description"` // 任务描述 - Points int `json:"points"` // 任务积分 - 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 - Url string `json:"url"` // 跳转链接 - Status int8 `json:"status"` // 任务状态: 0=不启用,1=启用 - StartAt string `json:"start_at"` // 开始时间 - EndAt string `json:"end_at"` // 结束时间 - FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取 + Id uint `json:"id"` // 任务ID + CommunityId uint `json:"community_id"` // 所属社区ID + Title string `json:"title"` // 任务标题 + SubTitle string `json:"sub_title"` // 副标题 + Description string `json:"description"` // 任务描述 + Points int `json:"points"` // 任务积分 + ButtonText string `json:"button_text"` // 按钮文字 + Params string `json:"params"` // 参数 + 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 + Url string `json:"url"` // 跳转链接 + Sort int `json:"sort"` // 排序 + StartAt string `json:"start_at"` // 开始时间 + 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 { ID uint `path:"id"` // 任务ID } +type VerifyTaskResultReq struct { + ID uint `form:"id"` // 任务ID + Params string `form:"params,optional"` // 额外的参数 +} + type VerifyTaskResultResp struct { Finish bool `json:"finish"` // 是否完成 } diff --git a/novatask.go b/novatask.go index 21c1ed5..a1798c0 100644 --- a/novatask.go +++ b/novatask.go @@ -3,9 +3,11 @@ package main import ( "flag" "fmt" - + "github.com/zeromicro/go-zero/core/service" "nova_task/internal/config" "nova_task/internal/handler" + "nova_task/internal/job" + "nova_task/internal/pkg/errs" "nova_task/internal/svc" "github.com/zeromicro/go-zero/core/conf" @@ -21,14 +23,19 @@ func main() { conf.MustLoad(*configFile, &c) c.MustSetUp() - server := rest.MustNewServer(c.RestConf) - defer server.Stop() - ctx := svc.NewServiceContext(c) 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) - server.Start() + serviceGroup.Start() }