增加任务接口逻辑
This commit is contained in:
@@ -10,9 +10,13 @@ service novatask {
|
|||||||
@handler GetTaskList
|
@handler GetTaskList
|
||||||
get /tasks (GetTaskListReq) returns (GetTaskListResp)
|
get /tasks (GetTaskListReq) returns (GetTaskListResp)
|
||||||
|
|
||||||
|
@doc "校验任务结果"
|
||||||
|
@handler VerifyTaskResult
|
||||||
|
get /task/:id (TaskIdPath) returns (VerifyTaskResultResp)
|
||||||
|
|
||||||
@doc "领取任务奖励"
|
@doc "领取任务奖励"
|
||||||
@handler GetTaskReward
|
@handler GetTaskReward
|
||||||
get /reward/:id (GetTaskRewardReq) returns (GetTaskRewardResp)
|
get /reward/:id (TaskIdPath) returns (GetTaskRewardResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetTaskListReq {
|
type GetTaskListReq {
|
||||||
@@ -21,25 +25,32 @@ type GetTaskListReq {
|
|||||||
|
|
||||||
type Task {
|
type Task {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
|
CommunityId uint `json:"community_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"`
|
Type int8 `json:"type"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Status int8 `json:"status"`
|
||||||
StartAt string `json:"start_at"`
|
StartAt string `json:"start_at"`
|
||||||
EndAt string `json:"end_at"`
|
EndAt string `json:"end_at"`
|
||||||
Status int8 `json:"status"`
|
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetTaskListResp {
|
type GetTaskListResp {
|
||||||
Tasks []Task `json:"tasks"`
|
Tasks []Task `json:"tasks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetTaskRewardReq {
|
type TaskIdPath {
|
||||||
ID uint `path:"id"`
|
ID uint `path:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VerifyTaskResultResp {
|
||||||
|
Finish bool `json:"finish"`
|
||||||
|
}
|
||||||
|
|
||||||
type GetTaskRewardResp {
|
type GetTaskRewardResp {
|
||||||
Points int `json:"points"`
|
Points int `json:"points"`
|
||||||
}
|
}
|
||||||
|
|||||||
12
doc/sql/novatask.sql
Normal file
12
doc/sql/novatask.sql
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
CREATE TABLE `nh_task_progress`
|
||||||
|
(
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`uid` int(11) NOT NULL,
|
||||||
|
`task_id` int(11) unsigned NOT NULL COMMENT '任务id',
|
||||||
|
`task_seq` int(11) NOT NULL COMMENT '用于可重复任务的序列号',
|
||||||
|
`stage` tinyint NOT NULL DEFAULT 0 COMMENT '任务的阶段, 0:未完成 1:待校验 2:已完成未领取 3:已领取',
|
||||||
|
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||||
|
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE KEY `uid_task_id_seq` (`uid`, `task_id`, `task_seq`)
|
||||||
|
) COMMENT='用户任务节点';
|
||||||
@@ -45,6 +45,36 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/task/v1/task/{id}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "校验任务结果",
|
||||||
|
"operationId": "VerifyTaskResult",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/VerifyTaskResultResp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"task"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"apiKey": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/task/v1/tasks": {
|
"/api/task/v1/tasks": {
|
||||||
"get": {
|
"get": {
|
||||||
"summary": "获取任务列表",
|
"summary": "获取任务列表",
|
||||||
@@ -109,10 +139,6 @@
|
|||||||
"tasks"
|
"tasks"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"GetTaskRewardReq": {
|
|
||||||
"type": "object",
|
|
||||||
"title": "GetTaskRewardReq"
|
|
||||||
},
|
|
||||||
"GetTaskRewardResp": {
|
"GetTaskRewardResp": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -133,6 +159,10 @@
|
|||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "uint32"
|
"format": "uint32"
|
||||||
},
|
},
|
||||||
|
"community_id": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32"
|
||||||
|
},
|
||||||
"title": {
|
"title": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
@@ -153,29 +183,57 @@
|
|||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int8"
|
"format": "int8"
|
||||||
},
|
},
|
||||||
|
"url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int8"
|
||||||
|
},
|
||||||
"start_at": {
|
"start_at": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"end_at": {
|
"end_at": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"status": {
|
"finish_state": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int8"
|
"format": "int8",
|
||||||
|
"description": " 0:未完成 1:待校验 2:已完成未领取 3:已领取"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"title": "Task",
|
"title": "Task",
|
||||||
"required": [
|
"required": [
|
||||||
"id",
|
"id",
|
||||||
|
"community_id",
|
||||||
"title",
|
"title",
|
||||||
"sub_title",
|
"sub_title",
|
||||||
"description",
|
"description",
|
||||||
"points",
|
"points",
|
||||||
"button_text",
|
"button_text",
|
||||||
"type",
|
"type",
|
||||||
|
"url",
|
||||||
|
"status",
|
||||||
"start_at",
|
"start_at",
|
||||||
"end_at",
|
"end_at",
|
||||||
"status"
|
"finish_state"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TaskIdPath": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "TaskIdPath"
|
||||||
|
},
|
||||||
|
"VerifyTaskResultResp": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"finish": {
|
||||||
|
"type": "boolean",
|
||||||
|
"format": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "VerifyTaskResultResp",
|
||||||
|
"required": [
|
||||||
|
"finish"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -4,6 +4,7 @@ go 1.23.4
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.1
|
github.com/golang-jwt/jwt/v4 v4.5.1
|
||||||
|
github.com/shopspring/decimal v1.4.0
|
||||||
github.com/spf13/cast v1.7.0
|
github.com/spf13/cast v1.7.0
|
||||||
github.com/zeromicro/go-zero v1.7.4
|
github.com/zeromicro/go-zero v1.7.4
|
||||||
)
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -65,6 +65,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
|
|||||||
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/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/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
Path: "/reward/:id",
|
Path: "/reward/:id",
|
||||||
Handler: task.GetTaskRewardHandler(serverCtx),
|
Handler: task.GetTaskRewardHandler(serverCtx),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// 校验任务结果
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/task/:id",
|
||||||
|
Handler: task.VerifyTaskResultHandler(serverCtx),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// 获取任务列表
|
// 获取任务列表
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package task
|
package task
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/rest/httpx"
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"net/http"
|
||||||
"nova_task/internal/logic/task"
|
"nova_task/internal/logic/task"
|
||||||
"nova_task/internal/svc"
|
"nova_task/internal/svc"
|
||||||
"nova_task/internal/types"
|
"nova_task/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 获取任务列表
|
// GetTaskListHandler 获取任务列表
|
||||||
func GetTaskListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func GetTaskListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var req types.GetTaskListReq
|
var req types.GetTaskListReq
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
// 领取任务奖励
|
// 领取任务奖励
|
||||||
func GetTaskRewardHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
func GetTaskRewardHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var req types.GetTaskRewardReq
|
var req types.TaskIdPath
|
||||||
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
|
||||||
|
|||||||
29
internal/handler/task/verify_task_result_handler.go
Normal file
29
internal/handler/task/verify_task_result_handler.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"nova_task/internal/logic/task"
|
||||||
|
"nova_task/internal/svc"
|
||||||
|
"nova_task/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 校验任务结果
|
||||||
|
func VerifyTaskResultHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.TaskIdPath
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := task.NewVerifyTaskResultLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.VerifyTaskResult(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package task
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"nova_task/internal/model"
|
||||||
"nova_task/internal/pkg/errs"
|
"nova_task/internal/pkg/errs"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ func NewGetTaskListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTa
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *GetTaskListLogic) GetTaskList(req *types.GetTaskListReq) (*types.GetTaskListResp, error) {
|
func (l *GetTaskListLogic) GetTaskList(req *types.GetTaskListReq) (*types.GetTaskListResp, error) {
|
||||||
|
uid := cast.ToInt(l.ctx.Value("uid"))
|
||||||
|
|
||||||
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))
|
||||||
@@ -35,6 +39,15 @@ func (l *GetTaskListLogic) GetTaskList(req *types.GetTaskListReq) (*types.GetTas
|
|||||||
|
|
||||||
resp := &types.GetTaskListResp{}
|
resp := &types.GetTaskListResp{}
|
||||||
for _, t := range tasks {
|
for _, t := range tasks {
|
||||||
|
taskSeq := 0
|
||||||
|
if t.Type == model.TASKTYPE_DAILY_PAY {
|
||||||
|
taskSeq = cast.ToInt(time.Now().Format("20060102"))
|
||||||
|
}
|
||||||
|
var finishState int8
|
||||||
|
tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, t.CommunityId, taskSeq)
|
||||||
|
if err == nil {
|
||||||
|
finishState = tp.Stage
|
||||||
|
}
|
||||||
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,
|
||||||
@@ -43,9 +56,11 @@ func (l *GetTaskListLogic) GetTaskList(req *types.GetTaskListReq) (*types.GetTas
|
|||||||
Points: t.Points,
|
Points: t.Points,
|
||||||
ButtonText: t.ButtonText,
|
ButtonText: t.ButtonText,
|
||||||
Type: t.Type,
|
Type: t.Type,
|
||||||
|
Url: t.Url,
|
||||||
StartAt: t.StartAt.Time.Format(time.DateTime),
|
StartAt: t.StartAt.Time.Format(time.DateTime),
|
||||||
EndAt: t.EndAt.Time.Format(time.DateTime),
|
EndAt: t.EndAt.Time.Format(time.DateTime),
|
||||||
Status: t.Status,
|
Status: t.Status,
|
||||||
|
FinishState: finishState,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ package task
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"nova_task/internal/model"
|
||||||
|
"nova_task/internal/pkg/errs"
|
||||||
|
"time"
|
||||||
|
|
||||||
"nova_task/internal/svc"
|
"nova_task/internal/svc"
|
||||||
"nova_task/internal/types"
|
"nova_task/internal/types"
|
||||||
@@ -9,13 +14,13 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetTaskRewardLogic v领取任务奖励
|
||||||
type GetTaskRewardLogic struct {
|
type GetTaskRewardLogic struct {
|
||||||
logx.Logger
|
logx.Logger
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
svcCtx *svc.ServiceContext
|
svcCtx *svc.ServiceContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// 领取任务奖励
|
|
||||||
func NewGetTaskRewardLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTaskRewardLogic {
|
func NewGetTaskRewardLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTaskRewardLogic {
|
||||||
return &GetTaskRewardLogic{
|
return &GetTaskRewardLogic{
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
@@ -24,8 +29,50 @@ func NewGetTaskRewardLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Get
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *GetTaskRewardLogic) GetTaskReward(req *types.GetTaskRewardReq) (resp *types.GetTaskRewardResp, err error) {
|
func (l *GetTaskRewardLogic) GetTaskReward(req *types.TaskIdPath) (resp *types.GetTaskRewardResp, err error) {
|
||||||
// todo: add your logic here and delete this line
|
uid := cast.ToInt(l.ctx.Value("uid"))
|
||||||
|
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.InternalServer(errs.ErrDatabaseOperate, err)
|
||||||
|
}
|
||||||
|
var taskSeq int
|
||||||
|
if task.Type == model.TASKTYPE_DAILY_PAY {
|
||||||
|
taskSeq = cast.ToInt(time.Now().Format("20060102"))
|
||||||
|
}
|
||||||
|
tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, task.Id, taskSeq)
|
||||||
|
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.BadRequest(errs.ErrTaskNotFinished, "task not finished")
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case tp.Stage < model.TASK_PROGRESS_WAIT_REWARD:
|
||||||
|
return nil, errs.BadRequest(errs.ErrTaskNotFinished, "task not finished")
|
||||||
|
case tp.Stage > model.TASK_PROGRESS_WAIT_REWARD:
|
||||||
|
return nil, errs.BadRequest(errs.ErrTaskAlreadyReward, "task already reward")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 给予用户奖励
|
||||||
|
err = l.svcCtx.TaskAssetModel.AddUserPoint(l.ctx, uid, task.Points)
|
||||||
|
if err != nil {
|
||||||
|
l.Errorw("add user point error", logx.Field("err", err))
|
||||||
|
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录用户获奖记录
|
||||||
|
_, err = l.svcCtx.TaskAssetRecordModel.Insert(l.ctx, &model.NhTaskAssetRecord{
|
||||||
|
Uid: uid,
|
||||||
|
EventId: uint64(task.Id),
|
||||||
|
AssetField: "points",
|
||||||
|
Count: float64(task.Points),
|
||||||
|
Remark: task.Title,
|
||||||
|
CreateTime: int(time.Now().Unix()),
|
||||||
|
})
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
80
internal/logic/task/verify_task_result_logic.go
Normal file
80
internal/logic/task/verify_task_result_logic.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"nova_task/internal/model"
|
||||||
|
"nova_task/internal/pkg/errs"
|
||||||
|
"nova_task/internal/svc"
|
||||||
|
"nova_task/internal/types"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VerifyTaskResultLogic 校验任务结果逻辑
|
||||||
|
type VerifyTaskResultLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVerifyTaskResultLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VerifyTaskResultLogic {
|
||||||
|
return &VerifyTaskResultLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *VerifyTaskResultLogic) VerifyTaskResult(req *types.TaskIdPath) (*types.VerifyTaskResultResp, error) {
|
||||||
|
uid := cast.ToInt(l.ctx.Value("uid"))
|
||||||
|
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.InternalServer(errs.ErrDatabaseOperate, err)
|
||||||
|
}
|
||||||
|
var taskSeq int
|
||||||
|
if task.Type == model.TASKTYPE_DAILY_PAY {
|
||||||
|
taskSeq = cast.ToInt(time.Now().Format("20060102"))
|
||||||
|
}
|
||||||
|
tp, err := l.svcCtx.TaskProgressModel.FindOneByUidTaskIdTaskSeq(l.ctx, uid, task.Id, taskSeq)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
tp = &model.NhTaskProgress{
|
||||||
|
Uid: uid,
|
||||||
|
TaskId: task.Id,
|
||||||
|
TaskSeq: taskSeq,
|
||||||
|
Stage: model.TASK_PROGRESS_NOT_FINISHED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tp.Stage == model.TASK_PROGRESS_REWARDED {
|
||||||
|
return nil, errs.BadRequest(errs.ErrTaskAlreadyReward, "task already reward")
|
||||||
|
}
|
||||||
|
// todo: 校验用户是否完成该任务
|
||||||
|
switch task.Type {
|
||||||
|
case model.TASKTYPE_BIND_TWITTER:
|
||||||
|
case model.TASKTYPE_BIND_DISCORD:
|
||||||
|
case model.TASKTYPE_DAILY_PAY:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
tp.Stage = model.TASK_PROGRESS_WAIT_REWARD
|
||||||
|
if tp.Id > 0 {
|
||||||
|
err = l.svcCtx.TaskProgressModel.Update(l.ctx, tp)
|
||||||
|
} else {
|
||||||
|
_, err = l.svcCtx.TaskProgressModel.Insert(l.ctx, tp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
l.Errorw("update task progress error", logx.Field("err", err))
|
||||||
|
return nil, errs.InternalServer(errs.ErrDatabaseOperate, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.VerifyTaskResultResp{Finish: true}, nil
|
||||||
|
}
|
||||||
41
internal/model/nh_task_asset_model.go
Executable file
41
internal/model/nh_task_asset_model.go
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ NhTaskAssetModel = (*customNhTaskAssetModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// NhTaskAssetModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customNhTaskAssetModel.
|
||||||
|
NhTaskAssetModel interface {
|
||||||
|
nhTaskAssetModel
|
||||||
|
withSession(session sqlx.Session) NhTaskAssetModel
|
||||||
|
AddUserPoint(ctx context.Context, uid int, points int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
customNhTaskAssetModel struct {
|
||||||
|
*defaultNhTaskAssetModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewNhTaskAssetModel returns a model for the database table.
|
||||||
|
func NewNhTaskAssetModel(conn sqlx.SqlConn) NhTaskAssetModel {
|
||||||
|
return &customNhTaskAssetModel{
|
||||||
|
defaultNhTaskAssetModel: newNhTaskAssetModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customNhTaskAssetModel) withSession(session sqlx.Session) NhTaskAssetModel {
|
||||||
|
return NewNhTaskAssetModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customNhTaskAssetModel) AddUserPoint(ctx context.Context, uid int, points int) error {
|
||||||
|
insertOrUpdate := fmt.Sprintf("INSERT INTO %s (`uid`, `points`, `create_time`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `points` = `points` + ?", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, insertOrUpdate, uid, points, time.Now().Unix(), points)
|
||||||
|
return err
|
||||||
|
}
|
||||||
106
internal/model/nh_task_asset_model_gen.go
Executable file
106
internal/model/nh_task_asset_model_gen.go
Executable file
@@ -0,0 +1,106 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
"github.com/shopspring/decimal"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nhTaskAssetFieldNames = builder.RawFieldNames(&NhTaskAsset{})
|
||||||
|
nhTaskAssetRows = strings.Join(nhTaskAssetFieldNames, ",")
|
||||||
|
nhTaskAssetRowsExpectAutoSet = strings.Join(stringx.Remove(nhTaskAssetFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
nhTaskAssetRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTaskAssetFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
nhTaskAssetModel interface {
|
||||||
|
Insert(ctx context.Context, data *NhTaskAsset) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int) (*NhTaskAsset, error)
|
||||||
|
FindOneByUid(ctx context.Context, uid int) (*NhTaskAsset, error)
|
||||||
|
Update(ctx context.Context, data *NhTaskAsset) error
|
||||||
|
Delete(ctx context.Context, id int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultNhTaskAssetModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
NhTaskAsset struct {
|
||||||
|
Id int `db:"id"`
|
||||||
|
Uid int `db:"uid"`
|
||||||
|
Points decimal.Decimal `db:"points"` // 积分值
|
||||||
|
ElitePoints decimal.Decimal `db:"elite_points"` // 高级积分
|
||||||
|
Keys int `db:"keys"` // 宝箱钥匙
|
||||||
|
CreateTime int `db:"create_time"` // 创建时间
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newNhTaskAssetModel(conn sqlx.SqlConn) *defaultNhTaskAssetModel {
|
||||||
|
return &defaultNhTaskAssetModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`nh_task_asset`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskAssetModel) 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 *defaultNhTaskAssetModel) FindOne(ctx context.Context, id int) (*NhTaskAsset, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTaskAssetRows, m.table)
|
||||||
|
var resp NhTaskAsset
|
||||||
|
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 *defaultNhTaskAssetModel) FindOneByUid(ctx context.Context, uid int) (*NhTaskAsset, error) {
|
||||||
|
var resp NhTaskAsset
|
||||||
|
query := fmt.Sprintf("select %s from %s where `uid` = ? limit 1", nhTaskAssetRows, m.table)
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, uid)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskAssetModel) Insert(ctx context.Context, data *NhTaskAsset) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, nhTaskAssetRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.Points, data.ElitePoints, data.Keys)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskAssetModel) Update(ctx context.Context, newData *NhTaskAsset) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskAssetRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.Points, newData.ElitePoints, newData.Keys, newData.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskAssetModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
||||||
29
internal/model/nh_task_asset_record_model.go
Executable file
29
internal/model/nh_task_asset_record_model.go
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var _ NhTaskAssetRecordModel = (*customNhTaskAssetRecordModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// NhTaskAssetRecordModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customNhTaskAssetRecordModel.
|
||||||
|
NhTaskAssetRecordModel interface {
|
||||||
|
nhTaskAssetRecordModel
|
||||||
|
withSession(session sqlx.Session) NhTaskAssetRecordModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customNhTaskAssetRecordModel struct {
|
||||||
|
*defaultNhTaskAssetRecordModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewNhTaskAssetRecordModel returns a model for the database table.
|
||||||
|
func NewNhTaskAssetRecordModel(conn sqlx.SqlConn) NhTaskAssetRecordModel {
|
||||||
|
return &customNhTaskAssetRecordModel{
|
||||||
|
defaultNhTaskAssetRecordModel: newNhTaskAssetRecordModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customNhTaskAssetRecordModel) withSession(session sqlx.Session) NhTaskAssetRecordModel {
|
||||||
|
return NewNhTaskAssetRecordModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
||||||
91
internal/model/nh_task_asset_record_model_gen.go
Executable file
91
internal/model/nh_task_asset_record_model_gen.go
Executable file
@@ -0,0 +1,91 @@
|
|||||||
|
// 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 (
|
||||||
|
nhTaskAssetRecordFieldNames = builder.RawFieldNames(&NhTaskAssetRecord{})
|
||||||
|
nhTaskAssetRecordRows = strings.Join(nhTaskAssetRecordFieldNames, ",")
|
||||||
|
nhTaskAssetRecordRowsExpectAutoSet = strings.Join(stringx.Remove(nhTaskAssetRecordFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
nhTaskAssetRecordRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTaskAssetRecordFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
nhTaskAssetRecordModel interface {
|
||||||
|
Insert(ctx context.Context, data *NhTaskAssetRecord) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int) (*NhTaskAssetRecord, error)
|
||||||
|
Update(ctx context.Context, data *NhTaskAssetRecord) error
|
||||||
|
Delete(ctx context.Context, id int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultNhTaskAssetRecordModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
NhTaskAssetRecord struct {
|
||||||
|
Id int `db:"id"`
|
||||||
|
Uid int `db:"uid"`
|
||||||
|
EventId uint64 `db:"event_id"` // 日志事件
|
||||||
|
AssetField string `db:"asset_field"` // 积分或钥匙字段
|
||||||
|
Count float64 `db:"count"` // 数量 正数获得,负数消耗
|
||||||
|
Remark string `db:"remark"` // 备注
|
||||||
|
ProvideUid uint `db:"provide_uid"` // 贡献人,当事件为返利事件
|
||||||
|
CreateTime int `db:"create_time"` // 创建时间
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newNhTaskAssetRecordModel(conn sqlx.SqlConn) *defaultNhTaskAssetRecordModel {
|
||||||
|
return &defaultNhTaskAssetRecordModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`nh_task_asset_record`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskAssetRecordModel) 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 *defaultNhTaskAssetRecordModel) FindOne(ctx context.Context, id int) (*NhTaskAssetRecord, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTaskAssetRecordRows, m.table)
|
||||||
|
var resp NhTaskAssetRecord
|
||||||
|
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 *defaultNhTaskAssetRecordModel) Insert(ctx context.Context, data *NhTaskAssetRecord) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, nhTaskAssetRecordRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.EventId, data.AssetField, data.Count, data.Remark, data.ProvideUid)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskAssetRecordModel) Update(ctx context.Context, data *NhTaskAssetRecord) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskAssetRecordRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.Uid, data.EventId, data.AssetField, data.Count, data.Remark, data.ProvideUid, data.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskAssetRecordModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
||||||
@@ -9,6 +9,20 @@ import (
|
|||||||
|
|
||||||
var _ NhTaskModel = (*customNhTaskModel)(nil)
|
var _ NhTaskModel = (*customNhTaskModel)(nil)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 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
|
||||||
|
TASKTYPE_FOLLOW_TWITTER = 0
|
||||||
|
TASKTYPE_BIND_TWITTER = 1
|
||||||
|
TASKTYPE_CAST_TWITTER = 2
|
||||||
|
TASKTYPE_PUBLISH_TWITTER = 3
|
||||||
|
TASKTYPE_REPOST_TWITTER = 4
|
||||||
|
TASKTYPE_WATCH_YOUTUBE = 5
|
||||||
|
TASKTYPE_FOLLOW_YOUTUBE = 6
|
||||||
|
TASKTYPE_BIND_DISCORD = 7
|
||||||
|
TASKTYPE_JOIN_TELEGRAM = 8
|
||||||
|
TASKTYPE_DAILY_PAY = 9
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// NhTaskModel is an interface to be customized, add more methods here,
|
// NhTaskModel is an interface to be customized, add more methods here,
|
||||||
// and implement the added methods in customNhTaskModel.
|
// and implement the added methods in customNhTaskModel.
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ type (
|
|||||||
Description string `db:"description"` // 描述
|
Description string `db:"description"` // 描述
|
||||||
Points int `db:"points"` // 积分数量
|
Points int `db:"points"` // 积分数量
|
||||||
ButtonText string `db:"button_text"` // 按钮上的文字
|
ButtonText string `db:"button_text"` // 按钮上的文字
|
||||||
Type int8 `db:"type"` // 0=一次性任务,1=每天任务
|
Type int8 `db:"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 `db:"url"` // 跳转链接
|
||||||
Status int8 `db:"status"` // 0=不启用,1=启用
|
Status int8 `db:"status"` // 0=不启用,1=启用
|
||||||
StartAt sql.NullTime `db:"start_at"` // 开始时间
|
StartAt sql.NullTime `db:"start_at"` // 开始时间
|
||||||
EndAt sql.NullTime `db:"end_at"` // 结束时间
|
EndAt sql.NullTime `db:"end_at"` // 结束时间
|
||||||
@@ -81,14 +82,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.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)
|
||||||
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.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.Id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
internal/model/nh_task_progress_model.go
Executable file
37
internal/model/nh_task_progress_model.go
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var _ NhTaskProgressModel = (*customNhTaskProgressModel)(nil)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 任务的阶段, 0:未完成 1:待校验 2:已完成未领取 3:已领取
|
||||||
|
TASK_PROGRESS_NOT_FINISHED = 0
|
||||||
|
TASK_PROGRESS_WAIT_VERIFY = 1
|
||||||
|
TASK_PROGRESS_WAIT_REWARD = 2
|
||||||
|
TASK_PROGRESS_REWARDED = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// NhTaskProgressModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customNhTaskProgressModel.
|
||||||
|
NhTaskProgressModel interface {
|
||||||
|
nhTaskProgressModel
|
||||||
|
withSession(session sqlx.Session) NhTaskProgressModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customNhTaskProgressModel struct {
|
||||||
|
*defaultNhTaskProgressModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewNhTaskProgressModel returns a model for the database table.
|
||||||
|
func NewNhTaskProgressModel(conn sqlx.SqlConn) NhTaskProgressModel {
|
||||||
|
return &customNhTaskProgressModel{
|
||||||
|
defaultNhTaskProgressModel: newNhTaskProgressModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customNhTaskProgressModel) withSession(session sqlx.Session) NhTaskProgressModel {
|
||||||
|
return NewNhTaskProgressModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
||||||
106
internal/model/nh_task_progress_model_gen.go
Executable file
106
internal/model/nh_task_progress_model_gen.go
Executable file
@@ -0,0 +1,106 @@
|
|||||||
|
// 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 (
|
||||||
|
nhTaskProgressFieldNames = builder.RawFieldNames(&NhTaskProgress{})
|
||||||
|
nhTaskProgressRows = strings.Join(nhTaskProgressFieldNames, ",")
|
||||||
|
nhTaskProgressRowsExpectAutoSet = strings.Join(stringx.Remove(nhTaskProgressFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||||
|
nhTaskProgressRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTaskProgressFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
nhTaskProgressModel interface {
|
||||||
|
Insert(ctx context.Context, data *NhTaskProgress) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, id int) (*NhTaskProgress, error)
|
||||||
|
FindOneByUidTaskIdTaskSeq(ctx context.Context, uid int, taskId uint, taskSeq int) (*NhTaskProgress, error)
|
||||||
|
Update(ctx context.Context, data *NhTaskProgress) error
|
||||||
|
Delete(ctx context.Context, id int) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultNhTaskProgressModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
NhTaskProgress struct {
|
||||||
|
Id int `db:"id"`
|
||||||
|
Uid int `db:"uid"`
|
||||||
|
TaskId uint `db:"task_id"` // 任务id
|
||||||
|
TaskSeq int `db:"task_seq"` // 用于可重复任务的序列号
|
||||||
|
Stage int8 `db:"stage"` // 任务的阶段, 0:未完成 1:待校验 2:已完成未领取 3:已领取
|
||||||
|
CreatedAt time.Time `db:"created_at"` // 创建时间
|
||||||
|
UpdatedAt time.Time `db:"updated_at"` // 修改时间
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newNhTaskProgressModel(conn sqlx.SqlConn) *defaultNhTaskProgressModel {
|
||||||
|
return &defaultNhTaskProgressModel{
|
||||||
|
conn: conn,
|
||||||
|
table: "`nh_task_progress`",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskProgressModel) 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 *defaultNhTaskProgressModel) FindOne(ctx context.Context, id int) (*NhTaskProgress, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTaskProgressRows, m.table)
|
||||||
|
var resp NhTaskProgress
|
||||||
|
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 *defaultNhTaskProgressModel) FindOneByUidTaskIdTaskSeq(ctx context.Context, uid int, taskId uint, taskSeq int) (*NhTaskProgress, error) {
|
||||||
|
var resp NhTaskProgress
|
||||||
|
query := fmt.Sprintf("select %s from %s where `uid` = ? and `task_id` = ? and `task_seq` = ? limit 1", nhTaskProgressRows, m.table)
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, uid, taskId, taskSeq)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskProgressModel) Insert(ctx context.Context, data *NhTaskProgress) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?)", m.table, nhTaskProgressRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.Uid, data.TaskId, data.TaskSeq, data.Stage)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskProgressModel) Update(ctx context.Context, newData *NhTaskProgress) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, nhTaskProgressRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, newData.Uid, newData.TaskId, newData.TaskSeq, newData.Stage, newData.Id)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultNhTaskProgressModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
||||||
@@ -70,37 +70,37 @@ func (b *TokenBuilder) ParseUidFromToken(tokenStr string) (string, string, strin
|
|||||||
return appid, userId, tgId, expiredAt, nil
|
return appid, userId, tgId, expiredAt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//// ParseUid 解析出uid
|
// ParseUid 解析出uid
|
||||||
//func (b *TokenBuilder) ParseUid(r *http.Request) (string, error) {
|
func (b *TokenBuilder) ParseUid(r *http.Request) (string, error) {
|
||||||
// parser := token.NewTokenParser()
|
parser := token.NewTokenParser()
|
||||||
// tok, err := parser.ParseToken(r, b.config.AccessSecret, "")
|
tok, err := parser.ParseToken(r, b.config.AccessSecret, "")
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return "", err
|
return "", err
|
||||||
// }
|
}
|
||||||
// if !tok.Valid {
|
if !tok.Valid {
|
||||||
// return "", errors.New("token is invalid")
|
return "", errors.New("token is invalid")
|
||||||
// }
|
}
|
||||||
// if claims, ok := tok.Claims.(jwt.MapClaims); ok {
|
if claims, ok := tok.Claims.(jwt.MapClaims); ok {
|
||||||
// if uid, ok := claims["uid"]; ok {
|
if uid, ok := claims["uid"]; ok {
|
||||||
// return cast.ToString(uid), nil
|
return cast.ToString(uid), nil
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// return "", errors.New("token not exist uid")
|
return "", errors.New("token not exist uid")
|
||||||
//}
|
}
|
||||||
|
|
||||||
//func ParseUid(r *http.Request, accessSecret string) (string, error) {
|
func ParseUid(r *http.Request, accessSecret string) (string, error) {
|
||||||
// parser := token.NewTokenParser()
|
parser := token.NewTokenParser()
|
||||||
// tok, err := parser.ParseToken(r, accessSecret, "")
|
tok, err := parser.ParseToken(r, accessSecret, "")
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// return "", err
|
return "", err
|
||||||
// }
|
}
|
||||||
// if !tok.Valid {
|
if !tok.Valid {
|
||||||
// return "", errors.New("token is invalid")
|
return "", errors.New("token is invalid")
|
||||||
// }
|
}
|
||||||
// if claims, ok := tok.Claims.(jwt.MapClaims); ok {
|
if claims, ok := tok.Claims.(jwt.MapClaims); ok {
|
||||||
// if uid, ok := claims["uid"]; ok {
|
if uid, ok := claims["uid"]; ok {
|
||||||
// return cast.ToString(uid), nil
|
return cast.ToString(uid), nil
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// return "", errors.New("token not exist uid")
|
return "", errors.New("token not exist uid")
|
||||||
//}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ const (
|
|||||||
ErrInvoiceHasPaid Reason = 10004 // 订单已支付
|
ErrInvoiceHasPaid Reason = 10004 // 订单已支付
|
||||||
ErrInvalidAppId Reason = 10005 // 应用id无效
|
ErrInvalidAppId Reason = 10005 // 应用id无效
|
||||||
ErrUserNotHasInviter Reason = 10006 // 用户没有邀请人
|
ErrUserNotHasInviter Reason = 10006 // 用户没有邀请人
|
||||||
|
ErrTaskNotFound Reason = 10007 // 任务不存在
|
||||||
|
ErrTaskAlreadyReward Reason = 10008 // 任务已领取
|
||||||
|
ErrTaskNotFinished Reason = 10009 // 任务未完成
|
||||||
|
|
||||||
// ========= admin 业务相关错误码: 30000~39999 =========
|
// ========= admin 业务相关错误码: 30000~39999 =========
|
||||||
ErrUnknownAdminError Reason = 30000 // 未知的admin错误
|
ErrUnknownAdminError Reason = 30000 // 未知的admin错误
|
||||||
|
|||||||
@@ -8,11 +8,18 @@ import (
|
|||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
TaskModel model.NhTaskModel
|
TaskModel model.NhTaskModel
|
||||||
|
TaskAssetModel model.NhTaskAssetModel
|
||||||
|
TaskAssetRecordModel model.NhTaskAssetRecordModel
|
||||||
|
TaskProgressModel model.NhTaskProgressModel
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
|
dbConn := c.MySql.Conn()
|
||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
TaskModel: model.NewNhTaskModel(c.MySql.Conn()),
|
TaskModel: model.NewNhTaskModel(dbConn),
|
||||||
|
TaskAssetModel: model.NewNhTaskAssetModel(dbConn),
|
||||||
|
TaskAssetRecordModel: model.NewNhTaskAssetRecordModel(dbConn),
|
||||||
|
TaskProgressModel: model.NewNhTaskProgressModel(dbConn),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,23 +11,30 @@ type GetTaskListResp struct {
|
|||||||
Tasks []Task `json:"tasks"`
|
Tasks []Task `json:"tasks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetTaskRewardReq struct {
|
|
||||||
ID uint `path:"id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetTaskRewardResp struct {
|
type GetTaskRewardResp struct {
|
||||||
Points int `json:"points"`
|
Points int `json:"points"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Task struct {
|
type Task struct {
|
||||||
Id uint `json:"id"`
|
Id uint `json:"id"`
|
||||||
|
CommunityId uint `json:"community_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"`
|
Type int8 `json:"type"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Status int8 `json:"status"`
|
||||||
StartAt string `json:"start_at"`
|
StartAt string `json:"start_at"`
|
||||||
EndAt string `json:"end_at"`
|
EndAt string `json:"end_at"`
|
||||||
Status int8 `json:"status"`
|
FinishState int8 `json:"finish_state"` // 0:未完成 1:待校验 2:已完成未领取 3:已领取
|
||||||
|
}
|
||||||
|
|
||||||
|
type TaskIdPath struct {
|
||||||
|
ID uint `path:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifyTaskResultResp struct {
|
||||||
|
Finish bool `json:"finish"`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user