初始化项目
This commit is contained in:
40
internal/config/config.go
Normal file
40
internal/config/config.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
rest.RestConf
|
||||
MySql MySqlConf
|
||||
Auth struct {
|
||||
AccessSecret string
|
||||
AccessExpire int64
|
||||
}
|
||||
}
|
||||
|
||||
// MySqlConf mysql配置
|
||||
type MySqlConf struct {
|
||||
Addr string
|
||||
User string
|
||||
Password string
|
||||
Database string
|
||||
Loc string `json:",default=Local"`
|
||||
Log string `json:",default=disableStmt,options=allow|disable|disableStmt"`
|
||||
}
|
||||
|
||||
func (m MySqlConf) Dsn() string {
|
||||
return fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=%s", m.User, m.Password, m.Addr, m.Database, url.QueryEscape(m.Loc))
|
||||
}
|
||||
|
||||
func (m MySqlConf) Conn(opts ...sqlx.SqlOption) sqlx.SqlConn {
|
||||
if m.Log == "disable" {
|
||||
sqlx.DisableLog()
|
||||
} else if m.Log == "disableStmt" {
|
||||
sqlx.DisableStmtLog()
|
||||
}
|
||||
return sqlx.NewMysql(m.Dsn(), opts...)
|
||||
}
|
||||
34
internal/handler/routes.go
Normal file
34
internal/handler/routes.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.7.3
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
task "nova_task/internal/handler/task"
|
||||
"nova_task/internal/svc"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest"
|
||||
)
|
||||
|
||||
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
server.AddRoutes(
|
||||
[]rest.Route{
|
||||
{
|
||||
// 领取任务奖励
|
||||
Method: http.MethodGet,
|
||||
Path: "/reward/:id",
|
||||
Handler: task.GetTaskRewardHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 获取任务列表
|
||||
Method: http.MethodGet,
|
||||
Path: "/tasks",
|
||||
Handler: task.GetTaskListHandler(serverCtx),
|
||||
},
|
||||
},
|
||||
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
|
||||
rest.WithPrefix("/api/task/v1"),
|
||||
)
|
||||
}
|
||||
29
internal/handler/task/get_task_list_handler.go
Normal file
29
internal/handler/task/get_task_list_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 GetTaskListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetTaskListReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := task.NewGetTaskListLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetTaskList(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
29
internal/handler/task/get_task_reward_handler.go
Normal file
29
internal/handler/task/get_task_reward_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 GetTaskRewardHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.GetTaskRewardReq
|
||||
if err := httpx.Parse(r, &req); err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
return
|
||||
}
|
||||
|
||||
l := task.NewGetTaskRewardLogic(r.Context(), svcCtx)
|
||||
resp, err := l.GetTaskReward(&req)
|
||||
if err != nil {
|
||||
httpx.ErrorCtx(r.Context(), w, err)
|
||||
} else {
|
||||
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
53
internal/logic/task/get_task_list_logic.go
Normal file
53
internal/logic/task/get_task_list_logic.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"context"
|
||||
"nova_task/internal/pkg/errs"
|
||||
"time"
|
||||
|
||||
"nova_task/internal/svc"
|
||||
"nova_task/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetTaskListLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewGetTaskListLogic 获取任务列表
|
||||
func NewGetTaskListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTaskListLogic {
|
||||
return &GetTaskListLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetTaskListLogic) GetTaskList(req *types.GetTaskListReq) (*types.GetTaskListResp, error) {
|
||||
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)
|
||||
}
|
||||
|
||||
resp := &types.GetTaskListResp{}
|
||||
for _, t := range tasks {
|
||||
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,
|
||||
StartAt: t.StartAt.Time.Format(time.DateTime),
|
||||
EndAt: t.EndAt.Time.Format(time.DateTime),
|
||||
Status: t.Status,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
31
internal/logic/task/get_task_reward_logic.go
Normal file
31
internal/logic/task/get_task_reward_logic.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package task
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"nova_task/internal/svc"
|
||||
"nova_task/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetTaskRewardLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 领取任务奖励
|
||||
func NewGetTaskRewardLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTaskRewardLogic {
|
||||
return &GetTaskRewardLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetTaskRewardLogic) GetTaskReward(req *types.GetTaskRewardReq) (resp *types.GetTaskRewardResp, err error) {
|
||||
// todo: add your logic here and delete this line
|
||||
|
||||
return
|
||||
}
|
||||
45
internal/model/nh_task_model.go
Executable file
45
internal/model/nh_task_model.go
Executable file
@@ -0,0 +1,45 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
var _ NhTaskModel = (*customNhTaskModel)(nil)
|
||||
|
||||
type (
|
||||
// NhTaskModel is an interface to be customized, add more methods here,
|
||||
// and implement the added methods in customNhTaskModel.
|
||||
NhTaskModel interface {
|
||||
nhTaskModel
|
||||
withSession(session sqlx.Session) NhTaskModel
|
||||
FindTasksByCommunity(ctx context.Context, communityId uint) ([]*NhTask, error)
|
||||
}
|
||||
|
||||
customNhTaskModel struct {
|
||||
*defaultNhTaskModel
|
||||
}
|
||||
)
|
||||
|
||||
func (m *customNhTaskModel) FindTasksByCommunity(ctx context.Context, communityId uint) ([]*NhTask, error) {
|
||||
query := fmt.Sprintf("select %s from %s where community_id = ?", nhTaskRows, m.table)
|
||||
var tasks []*NhTask
|
||||
err := m.conn.QueryRowsCtx(ctx, &tasks, query, communityId)
|
||||
if err != nil && !errors.Is(err, sqlx.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return tasks, nil
|
||||
}
|
||||
|
||||
// NewNhTaskModel returns a model for the database table.
|
||||
func NewNhTaskModel(conn sqlx.SqlConn) NhTaskModel {
|
||||
return &customNhTaskModel{
|
||||
defaultNhTaskModel: newNhTaskModel(conn),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *customNhTaskModel) withSession(session sqlx.Session) NhTaskModel {
|
||||
return NewNhTaskModel(sqlx.NewSqlConnFromSession(session))
|
||||
}
|
||||
97
internal/model/nh_task_model_gen.go
Executable file
97
internal/model/nh_task_model_gen.go
Executable file
@@ -0,0 +1,97 @@
|
||||
// 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 (
|
||||
nhTaskFieldNames = builder.RawFieldNames(&NhTask{})
|
||||
nhTaskRows = strings.Join(nhTaskFieldNames, ",")
|
||||
nhTaskRowsExpectAutoSet = strings.Join(stringx.Remove(nhTaskFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
|
||||
nhTaskRowsWithPlaceHolder = strings.Join(stringx.Remove(nhTaskFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
|
||||
)
|
||||
|
||||
type (
|
||||
nhTaskModel interface {
|
||||
Insert(ctx context.Context, data *NhTask) (sql.Result, error)
|
||||
FindOne(ctx context.Context, id uint) (*NhTask, error)
|
||||
Update(ctx context.Context, data *NhTask) error
|
||||
Delete(ctx context.Context, id uint) error
|
||||
}
|
||||
|
||||
defaultNhTaskModel struct {
|
||||
conn sqlx.SqlConn
|
||||
table string
|
||||
}
|
||||
|
||||
NhTask struct {
|
||||
Id uint `db:"id"`
|
||||
CommunityId uint `db:"community_id"` // 合作社区ID,0=官方平台
|
||||
Title string `db:"title"` // 大标题
|
||||
SubTitle string `db:"sub_title"` // 子标题
|
||||
Description string `db:"description"` // 描述
|
||||
Points int `db:"points"` // 积分数量
|
||||
ButtonText string `db:"button_text"` // 按钮上的文字
|
||||
Type int8 `db:"type"` // 0=一次性任务,1=每天任务
|
||||
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"` // 修改时间
|
||||
}
|
||||
)
|
||||
|
||||
func newNhTaskModel(conn sqlx.SqlConn) *defaultNhTaskModel {
|
||||
return &defaultNhTaskModel{
|
||||
conn: conn,
|
||||
table: "`nh_task`",
|
||||
}
|
||||
}
|
||||
|
||||
func (m *defaultNhTaskModel) 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 *defaultNhTaskModel) FindOne(ctx context.Context, id uint) (*NhTask, error) {
|
||||
query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", nhTaskRows, m.table)
|
||||
var resp NhTask
|
||||
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 *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.Status, data.StartAt, data.EndAt)
|
||||
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.Status, data.StartAt, data.EndAt, data.Id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *defaultNhTaskModel) tableName() string {
|
||||
return m.table
|
||||
}
|
||||
5
internal/model/vars.go
Normal file
5
internal/model/vars.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package model
|
||||
|
||||
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
|
||||
var ErrNotFound = sqlx.ErrNotFound
|
||||
106
internal/pkg/encrypt/jwt/jwt.go
Normal file
106
internal/pkg/encrypt/jwt/jwt.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
jwt "github.com/golang-jwt/jwt/v4"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/zeromicro/go-zero/rest/token"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
AccessSecret string `json:",default=ac2d27613e131be6286c0eb17139293d"`
|
||||
AccessExpire time.Duration `json:",default=24h"`
|
||||
}
|
||||
|
||||
type TokenBuilder struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
func NewTokenBuilder(config Config) *TokenBuilder {
|
||||
return &TokenBuilder{config: config}
|
||||
}
|
||||
|
||||
// GenerateToken 生成token
|
||||
func (b *TokenBuilder) GenerateToken(kvs map[string]any) (string, int64, error) {
|
||||
// 创建一个新的 Token
|
||||
tok := jwt.New(jwt.SigningMethodHS256)
|
||||
// 设置 Token 的声明(Payload)
|
||||
claims := tok.Claims.(jwt.MapClaims)
|
||||
for k, v := range kvs {
|
||||
claims[k] = v
|
||||
}
|
||||
expiredAt := time.Now().Add(b.config.AccessExpire).Unix()
|
||||
claims["exp"] = expiredAt // 设置过期时间
|
||||
|
||||
// 使用密钥签名 Token
|
||||
tkStr, err := tok.SignedString([]byte(b.config.AccessSecret))
|
||||
return tkStr, expiredAt, err
|
||||
}
|
||||
|
||||
func (b *TokenBuilder) ParseUidFromToken(tokenStr string) (string, string, string, int64, error) {
|
||||
r := &http.Request{Header: http.Header{}}
|
||||
r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tokenStr))
|
||||
parser := token.NewTokenParser()
|
||||
tok, err := parser.ParseToken(r, b.config.AccessSecret, "")
|
||||
if err != nil {
|
||||
return "", "", "", 0, err
|
||||
}
|
||||
if !tok.Valid {
|
||||
return "", "", "", 0, errors.New("token is invalid")
|
||||
}
|
||||
var appid, userId, tgId string
|
||||
var expiredAt int64
|
||||
if claims, ok := tok.Claims.(jwt.MapClaims); ok {
|
||||
if uid, ok := claims["uid"]; ok {
|
||||
userId = cast.ToString(uid)
|
||||
}
|
||||
if aid, ok := claims["app_id"]; ok {
|
||||
appid = cast.ToString(aid)
|
||||
}
|
||||
if tid, ok := claims["tg_id"]; ok {
|
||||
tgId = cast.ToString(tid)
|
||||
}
|
||||
if exp, ok := claims["exp"]; ok {
|
||||
expiredAt = cast.ToInt64(exp)
|
||||
}
|
||||
}
|
||||
return appid, userId, tgId, expiredAt, nil
|
||||
}
|
||||
|
||||
//// ParseUid 解析出uid
|
||||
//func (b *TokenBuilder) ParseUid(r *http.Request) (string, error) {
|
||||
// parser := token.NewTokenParser()
|
||||
// tok, err := parser.ParseToken(r, b.config.AccessSecret, "")
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// if !tok.Valid {
|
||||
// return "", errors.New("token is invalid")
|
||||
// }
|
||||
// if claims, ok := tok.Claims.(jwt.MapClaims); ok {
|
||||
// if uid, ok := claims["uid"]; ok {
|
||||
// return cast.ToString(uid), nil
|
||||
// }
|
||||
// }
|
||||
// return "", errors.New("token not exist uid")
|
||||
//}
|
||||
|
||||
//func ParseUid(r *http.Request, accessSecret string) (string, error) {
|
||||
// parser := token.NewTokenParser()
|
||||
// tok, err := parser.ParseToken(r, accessSecret, "")
|
||||
// if err != nil {
|
||||
// return "", err
|
||||
// }
|
||||
// if !tok.Valid {
|
||||
// return "", errors.New("token is invalid")
|
||||
// }
|
||||
// if claims, ok := tok.Claims.(jwt.MapClaims); ok {
|
||||
// if uid, ok := claims["uid"]; ok {
|
||||
// return cast.ToString(uid), nil
|
||||
// }
|
||||
// }
|
||||
// return "", errors.New("token not exist uid")
|
||||
//}
|
||||
31
internal/pkg/encrypt/md5/md5.go
Normal file
31
internal/pkg/encrypt/md5/md5.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package md5
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func Md5(src []byte) string {
|
||||
has := md5.Sum(src)
|
||||
md5Str := hex.EncodeToString(has[:])
|
||||
return md5Str
|
||||
}
|
||||
|
||||
func Md5str(src string) string {
|
||||
return Md5([]byte(src))
|
||||
}
|
||||
|
||||
func Md516(src string) string {
|
||||
data := []byte(src)
|
||||
has := md5.Sum(data)
|
||||
md5Str := hex.EncodeToString(has[:])
|
||||
return md5Str[8:24]
|
||||
}
|
||||
|
||||
func Md516Upper(src string) string {
|
||||
data := []byte(src)
|
||||
has := md5.Sum(data)
|
||||
md5Str := fmt.Sprintf("%X", has)
|
||||
return md5Str[8:24]
|
||||
}
|
||||
30
internal/pkg/encrypt/sha/sha.go
Normal file
30
internal/pkg/encrypt/sha/sha.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package sha
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func Sha1(src string) string {
|
||||
h := sha1.New()
|
||||
h.Write([]byte(src))
|
||||
sh := hex.EncodeToString(h.Sum(nil))
|
||||
return sh
|
||||
}
|
||||
|
||||
func Sha256(src string) string {
|
||||
m := sha256.New()
|
||||
m.Write([]byte(src))
|
||||
res := hex.EncodeToString(m.Sum(nil))
|
||||
return res
|
||||
}
|
||||
|
||||
func HmacSha256Base64(src, secret string) string {
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(src))
|
||||
sign := base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
return sign
|
||||
}
|
||||
40
internal/pkg/errs/error.go
Normal file
40
internal/pkg/errs/error.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package errs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type err struct {
|
||||
code int
|
||||
reason Reason
|
||||
msg string
|
||||
}
|
||||
|
||||
func New(code int, reason Reason, message any) error {
|
||||
return err{
|
||||
code: code,
|
||||
reason: reason,
|
||||
msg: cast.ToString(message),
|
||||
}
|
||||
}
|
||||
|
||||
// Error error
|
||||
func (e err) Error() string {
|
||||
return fmt.Sprintf("code=%d msg=%s", e.code, e.msg)
|
||||
}
|
||||
|
||||
// Code return code
|
||||
func (e err) Code() int {
|
||||
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
|
||||
}
|
||||
56
internal/pkg/errs/errors.go
Normal file
56
internal/pkg/errs/errors.go
Normal file
@@ -0,0 +1,56 @@
|
||||
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)
|
||||
}
|
||||
64
internal/pkg/errs/http_respone.go
Normal file
64
internal/pkg/errs/http_respone.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package errs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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)
|
||||
}
|
||||
|
||||
func SetDebug(d bool) {
|
||||
debug = d
|
||||
}
|
||||
|
||||
func ErrorHandle(err error) (int, any) {
|
||||
return ErrorHandleCtx(context.Background(), err)
|
||||
}
|
||||
|
||||
func ErrorHandleCtx(ctx context.Context, err error) (int, any) {
|
||||
code := http.StatusBadRequest
|
||||
reason := ErrInternalServer
|
||||
var msg string
|
||||
if ec, ok := err.(interface{ Code() int }); ok {
|
||||
code = ec.Code()
|
||||
}
|
||||
if ec, ok := err.(interface{ Message() string }); ok {
|
||||
msg = ec.Message()
|
||||
} 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
|
||||
msg = "system error"
|
||||
}
|
||||
|
||||
body := map[string]any{
|
||||
"code": reason,
|
||||
"message": 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
|
||||
}
|
||||
33
internal/pkg/errs/reason.go
Normal file
33
internal/pkg/errs/reason.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package errs
|
||||
|
||||
type Reason int
|
||||
|
||||
const (
|
||||
// ======= 系统错误:0~999 =======
|
||||
ErrUnknownReason Reason = 0 // 未知错误
|
||||
ErrSucceed Reason = 200 // 成功
|
||||
ErrOverload Reason = 403 // 请求超载
|
||||
|
||||
// ======= 服务器内部错误:1000~9999 =======
|
||||
ErrInternalServer Reason = 1000 // 未知的服务器内部错误
|
||||
ErrDatabaseOperate Reason = 1001 // 数据库错误
|
||||
ErrRedisOperate Reason = 1002 // redis错误
|
||||
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 // 用户没有邀请人
|
||||
|
||||
// ========= admin 业务相关错误码: 30000~39999 =========
|
||||
ErrUnknownAdminError Reason = 30000 // 未知的admin错误
|
||||
ErrInvalidPassword Reason = 30001 // 无效密码
|
||||
ErrInvalidAccount Reason = 30002 // 无效账号
|
||||
)
|
||||
18
internal/svc/service_context.go
Normal file
18
internal/svc/service_context.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"nova_task/internal/config"
|
||||
"nova_task/internal/model"
|
||||
)
|
||||
|
||||
type ServiceContext struct {
|
||||
Config config.Config
|
||||
TaskModel model.NhTaskModel
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
return &ServiceContext{
|
||||
Config: c,
|
||||
TaskModel: model.NewNhTaskModel(c.MySql.Conn()),
|
||||
}
|
||||
}
|
||||
33
internal/types/types.go
Normal file
33
internal/types/types.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Code generated by goctl. DO NOT EDIT.
|
||||
// goctl 1.7.3
|
||||
|
||||
package types
|
||||
|
||||
type GetTaskListReq struct {
|
||||
CommunityId uint `form:"community_id"`
|
||||
}
|
||||
|
||||
type GetTaskListResp struct {
|
||||
Tasks []Task `json:"tasks"`
|
||||
}
|
||||
|
||||
type GetTaskRewardReq struct {
|
||||
ID uint `path:"id"`
|
||||
}
|
||||
|
||||
type GetTaskRewardResp struct {
|
||||
Points int `json:"points"`
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
Id uint `json:"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"`
|
||||
StartAt string `json:"start_at"`
|
||||
EndAt string `json:"end_at"`
|
||||
Status int8 `json:"status"`
|
||||
}
|
||||
Reference in New Issue
Block a user