Merge branch 'develop' of gitee.com:fusenpack/fusenapi into develop

This commit is contained in:
laodaming 2023-06-15 11:39:24 +08:00
commit 255c3c3c88
50 changed files with 1415 additions and 144 deletions

17
ddl/fs_guest.sql Normal file
View File

@ -0,0 +1,17 @@
-- fusentest.fs_guest definition
CREATE TABLE `fs_guest` (
`guest_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '游客ID',
`auth_key` varchar(512) NOT NULL DEFAULT '' COMMENT 'jwt token',
`status` tinyint(3) unsigned DEFAULT '1' COMMENT '1正常 0不正常',
`is_del` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 1删除',
`created_at` int(11) NOT NULL DEFAULT '0' COMMENT '添加时间',
`updated_at` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
`is_open_render` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否打开个性化渲染1开启0关闭',
`is_thousand_face` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已经存在千人千面1存在0不存在',
`is_low_rendering` tinyint(1) unsigned zerofill NOT NULL DEFAULT '0' COMMENT '是否开启低渲染模型渲染',
`is_remove_bg` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户上传logo是否去除背景',
PRIMARY KEY (`guest_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='游客表';

View File

@ -1,2 +1,4 @@
#! /bin/bash
goctl model mysql ddl --src ./ddl/$1.sql --dir model/ --home ./goctl_template
# goctl model mysql ddl --src ./ddl/$1.sql --dir model/ --home ./goctl_template
go run generator/main.go -name $1

118
generator/basic.go Normal file
View File

@ -0,0 +1,118 @@
package main
const (
_ int = iota
LongVarBinary
LongVarChar
GeometryCollection
GeomCollection
LineString
MultiLineString
MultiPoint
MultiPolygon
Point
Polygon
Json
Geometry
Enum
Set
Bit
Time
Timestamp
DateTime
Binary
VarBinary
Blob
Year
Decimal
Dec
Fixed
Numeric
Float
Float4
Float8
Double
Real
TinyInt
SmallInt
MediumInt
Int
Integer
BigInt
MiddleInt
Int1
Int2
Int3
Int4
Int8
Date
TinyBlob
MediumBlob
LongBlob
Bool
Boolean
Serial
NVarChar
NChar
Char
Character
VarChar
TinyText
Text
MediumText
LongText
)
var SQLTypeToGoTypeMap = map[int]string{
LongVarBinary: "[]byte",
Binary: "[]byte",
VarBinary: "[]byte",
Blob: "[]byte",
TinyBlob: "[]byte",
MediumBlob: "[]byte",
LongBlob: "[]byte",
LongVarChar: "*string",
NVarChar: "*string",
NChar: "*string",
Char: "*string",
Character: "*string",
VarChar: "*string",
TinyText: "*string",
Text: "*string",
MediumText: "*string",
LongText: "*string",
Time: "*time.Time",
Timestamp: "*time.Time",
DateTime: "*time.Time",
Date: "*time.Time",
Year: "*int64",
TinyInt: "*int64",
SmallInt: "*int64",
MediumInt: "*int64",
Int: "*int64",
Integer: "*int64",
BigInt: "*int64",
MiddleInt: "*int64",
Int1: "*int64",
Int2: "*int64",
Int3: "*int64",
Int4: "*int64",
Int8: "*int64",
Serial: "*int64",
Decimal: "*float64",
Dec: "*float64",
Fixed: "*float64",
Numeric: "*float64",
Float: "*float64",
Float4: "*float64",
Float8: "*float64",
Double: "*float64",
Real: "*float64",
Bool: "*bool",
Boolean: "*bool",
}

133
generator/main.go Normal file
View File

@ -0,0 +1,133 @@
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/zeromicro/ddl-parser/parser"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
var targerDir = "ddl"
var genDir = "model/gmodel_gen"
func toPascalCase(s string) string {
words := strings.Split(s, "_")
for i, word := range words {
words[i] = cases.Title(language.English).String(strings.ToLower(word))
}
return strings.Join(words, "")
}
func main() {
var name string
flag.StringVar(&name, "name", "", "输入需要序列化的ddl文件名, 不需要后缀.ddl")
flag.Parse()
if name != "" {
name = fmt.Sprintf("%s/%s.sql", targerDir, name)
GenFromPath(name)
} else {
matches, err := filepath.Glob(fmt.Sprintf("%s/*.sql", targerDir))
if err != nil {
panic(err)
}
for _, pth := range matches {
GenFromPath(pth)
}
}
}
func GenFromPath(pth string) {
p, err := filepath.Abs(pth)
if err != nil {
panic(err)
}
ddlfilestr, err := ioutil.ReadFile(pth)
if err != nil {
panic(err)
}
// PRIMARY KEY (`guest_id`) USING BTREE
re := regexp.MustCompile("PRIMARY\\s+KEY\\s+\\(\\s*`([^`]+)`\\s*\\)|`([^`]+)` [^\n]+PRIMARY\\s+KEY\\s+")
matches := re.FindStringSubmatch(string(ddlfilestr))
PrimaryStr := ""
if len(matches) > 0 {
PrimaryStr = matches[1]
}
var importstr = "import (\"gorm.io/gorm\"\n"
// 匹配到主键定义
parser.NewParser()
result, err := parser.NewParser().From(p)
if err != nil {
panic(err)
}
fcontent := "package model\n"
for _, table := range result {
structstr := "type %s struct {%s\n}\n"
tableName := toPascalCase(table.Name)
fieldstr := ""
for _, col := range table.Columns {
fieldName := toPascalCase(col.Name)
typeName := SQLTypeToGoTypeMap[col.DataType.Type()]
if typeName == "*time.Time" {
importstr += "\"time\"\n"
}
tagstr := "`gorm:"
if col.Name == PrimaryStr {
tagstr += "\"primary_key\""
typeName = typeName[1:]
} else {
tagstr += "\"\""
}
tagstr += fmt.Sprintf(" json:\"%s\"`", col.Name)
fieldColStr := fmt.Sprintf("\n%s %s %s// %s", fieldName, typeName, tagstr, col.Constraint.Comment)
fieldstr += fieldColStr
}
fcontent += importstr + ")\n"
fcontent += fmt.Sprintf(structstr, tableName, fieldstr)
modelstr := fmt.Sprintf(`type %sModel struct {db *gorm.DB}`, tableName)
fcontent += modelstr
fcontent += "\n"
newfuncstr := fmt.Sprintf(`func New%sModel(db *gorm.DB) *%sModel {return &%sModel{db}}`, tableName, tableName, tableName)
fcontent += newfuncstr
fcontent += "\n"
genGoFileName := fmt.Sprintf("%s/%s_gen.go", genDir, table.Name)
f, err := os.OpenFile(genGoFileName, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
f.WriteString(fcontent)
err = f.Close()
if err != nil {
panic(err)
}
err = exec.Command("gofmt", "-w", genGoFileName).Run()
if err != nil {
panic(err)
}
// log.Println(fcontent)
}
}

14
generator/main_test.go Normal file
View File

@ -0,0 +1,14 @@
package main
import (
"testing"
)
func TestMain(t *testing.T) {
// args := []string{"-name", "fs_guest"}
targerDir = "../" + targerDir
genDir = "../" + genDir
// os.Args = []string{"cmd", "-name=fs_guest"}
main()
}

8
go.mod
View File

@ -13,6 +13,11 @@ require (
gorm.io/gorm v1.25.1
)
require (
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521184019-c5ad59b459ec // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
)
require (
github.com/474420502/requests v1.32.1
github.com/jinzhu/inflection v1.0.0 // indirect
@ -47,6 +52,7 @@ require (
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/zeromicro/ddl-parser v1.0.4
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect
@ -60,7 +66,7 @@ require (
go.uber.org/automaxprocs v1.5.2 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/text v0.9.0
google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197 // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect

6
go.sum
View File

@ -41,6 +41,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
github.com/alicebob/miniredis/v2 v2.30.2 h1:lc1UAUT9ZA7h4srlfBmBt2aorm5Yftk9nBjxz7EyY9I=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521184019-c5ad59b459ec h1:EEyRvzmpEUZ+I8WmD5cw/vY8EqhambkOqy5iFr0908A=
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521184019-c5ad59b459ec/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
@ -178,6 +180,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@ -235,6 +239,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
github.com/zeromicro/ddl-parser v1.0.4 h1:fzU0ZNfV/a6T/WO8TvZZeJE9hmdt3qHvVUsW1X9SGJQ=
github.com/zeromicro/ddl-parser v1.0.4/go.mod h1:ISU/8NuPyEpl9pa17Py9TBPetMjtsiHrb9f5XGiYbo8=
github.com/zeromicro/go-zero v1.5.2 h1:vpMlZacCMtgdtYzKI3OMyhS6mZ9UQctiAh0J7gIq31I=
github.com/zeromicro/go-zero v1.5.2/go.mod h1:ndCd1nMMAdEMZgPfdm1fpavHUdBW0ykB6ckCRaSG10w=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=

View File

@ -15,28 +15,40 @@ import (
func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 解析jwtToken
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error())
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
// 从Token里获取对应的信息
userinfo, err := auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
{{if .HasRequest}}var req types.{{.RequestType}}
@ -53,7 +65,6 @@ func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
{{end}}l := {{.LogicName}}.New{{.LogicType}}(r.Context(), svcCtx)
{{if .HasResp}}resp{{end}} := l.{{.Call}}({{if .HasRequest}}&req, {{end}}userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
// 否则发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
if resp != nil {
{{if .HasResp}}httpx.OkJsonCtx(r.Context(), w, resp){{else}}httpx.Ok(w){{end}}
} else {

24
model/fsguestmodel.go Executable file
View File

@ -0,0 +1,24 @@
package model
import "github.com/zeromicro/go-zero/core/stores/sqlx"
var _ FsGuestModel = (*customFsGuestModel)(nil)
type (
// FsGuestModel is an interface to be customized, add more methods here,
// and implement the added methods in customFsGuestModel.
FsGuestModel interface {
fsGuestModel
}
customFsGuestModel struct {
*defaultFsGuestModel
}
)
// NewFsGuestModel returns a model for the database table.
func NewFsGuestModel(conn sqlx.SqlConn) FsGuestModel {
return &customFsGuestModel{
defaultFsGuestModel: newFsGuestModel(conn),
}
}

92
model/fsguestmodel_gen.go Executable file
View File

@ -0,0 +1,92 @@
// Code generated by goctl. DO NOT EDIT.
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
)
var (
fsGuestFieldNames = builder.RawFieldNames(&FsGuest{})
fsGuestRows = strings.Join(fsGuestFieldNames, ",")
fsGuestRowsExpectAutoSet = strings.Join(stringx.Remove(fsGuestFieldNames, "`guest_id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",")
fsGuestRowsWithPlaceHolder = strings.Join(stringx.Remove(fsGuestFieldNames, "`guest_id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?"
)
type (
fsGuestModel interface {
Insert(ctx context.Context, data *FsGuest) (sql.Result, error)
FindOne(ctx context.Context, guestId int64) (*FsGuest, error)
Update(ctx context.Context, data *FsGuest) error
Delete(ctx context.Context, guestId int64) error
}
defaultFsGuestModel struct {
conn sqlx.SqlConn
table string
}
FsGuest struct {
GuestId int64 `db:"guest_id"` // 游客ID
AuthKey string `db:"auth_key"` // jwt token
Status int64 `db:"status"` // 1正常 0不正常
IsDel int64 `db:"is_del"` // 是否删除 1删除
CreatedAt int64 `db:"created_at"` // 添加时间
UpdatedAt int64 `db:"updated_at"` // 更新时间
IsOpenRender int64 `db:"is_open_render"` // 是否打开个性化渲染1开启0关闭
IsThousandFace int64 `db:"is_thousand_face"` // 是否已经存在千人千面1存在0不存在
IsLowRendering int64 `db:"is_low_rendering"` // 是否开启低渲染模型渲染
IsRemoveBg int64 `db:"is_remove_bg"` // 用户上传logo是否去除背景
}
)
func newFsGuestModel(conn sqlx.SqlConn) *defaultFsGuestModel {
return &defaultFsGuestModel{
conn: conn,
table: "`fs_guest`",
}
}
func (m *defaultFsGuestModel) Delete(ctx context.Context, guestId int64) error {
query := fmt.Sprintf("delete from %s where `guest_id` = ?", m.table)
_, err := m.conn.ExecCtx(ctx, query, guestId)
return err
}
func (m *defaultFsGuestModel) FindOne(ctx context.Context, guestId int64) (*FsGuest, error) {
query := fmt.Sprintf("select %s from %s where `guest_id` = ? limit 1", fsGuestRows, m.table)
var resp FsGuest
err := m.conn.QueryRowCtx(ctx, &resp, query, guestId)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultFsGuestModel) Insert(ctx context.Context, data *FsGuest) (sql.Result, error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?)", m.table, fsGuestRowsExpectAutoSet)
ret, err := m.conn.ExecCtx(ctx, query, data.AuthKey, data.Status, data.IsDel, data.IsOpenRender, data.IsThousandFace, data.IsLowRendering, data.IsRemoveBg)
return ret, err
}
func (m *defaultFsGuestModel) Update(ctx context.Context, data *FsGuest) error {
query := fmt.Sprintf("update %s set %s where `guest_id` = ?", m.table, fsGuestRowsWithPlaceHolder)
_, err := m.conn.ExecCtx(ctx, query, data.AuthKey, data.Status, data.IsDel, data.IsOpenRender, data.IsThousandFace, data.IsLowRendering, data.IsRemoveBg, data.GuestId)
return err
}
func (m *defaultFsGuestModel) tableName() string {
return m.table
}

14
model/gmodel/fsguestmodel.go Executable file
View File

@ -0,0 +1,14 @@
package gmodel
type FsGuest struct {
GuestId int64 `gorm:"" json:"guest_id"` // ID
AuthKey *string `gorm: json:"auth_key"` // jwt token
Status *int64 `gorm: json:"status"` // 1正常 0不正常
IsDel *int64 `gorm: json:"is_del"` // 是否删除 1删除
CreatedAt *int64 `gorm: json:"created_at"` // 添加时间
UpdatedAt *int64 `gorm: json:"updated_at"` // 更新时间
IsOpenRender *int64 `gorm: json:"is_open_render"` // 是否打开个性化渲染1开启0关闭
IsThousandFace *int64 `gorm: json:"is_thousand_face"` // 是否已经存在千人千面1存在0不存在
IsLowRendering *int64 `gorm: json:"is_low_rendering"` // 是否开启低渲染模型渲染
IsRemoveBg *int64 `gorm: json:"is_remove_bg"` // 用户上传logo是否去除背景
}

View File

@ -0,0 +1,25 @@
package model
import (
"gorm.io/gorm"
)
type FsAddress struct {
Id int64 `gorm:"primary_key" json:"id"` //
UserId *int64 `gorm:"" json:"user_id"` // 用户ID
Name *string `gorm:"" json:"name"` // 地址名称
FirstName *string `gorm:"" json:"first_name"` // FirstName
LastName *string `gorm:"" json:"last_name"` // LastName
Mobile *string `gorm:"" json:"mobile"` // 手机号码
Street *string `gorm:"" json:"street"` // 街道
Suite *string `gorm:"" json:"suite"` // 房号
City *string `gorm:"" json:"city"` // 城市
State *string `gorm:"" json:"state"` // 州名
Country *string `gorm:"" json:"country"` // 国家
ZipCode *string `gorm:"" json:"zip_code"` // 邮编
Status *int64 `gorm:"" json:"status"` // 1正常 0异常
IsDefault *int64 `gorm:"" json:"is_default"` // 1默认地址0非默认地址
}
type FsAddressModel struct{ db *gorm.DB }
func NewFsAddressModel(db *gorm.DB) *FsAddressModel { return &FsAddressModel{db} }

View File

@ -0,0 +1,19 @@
package model
import (
"gorm.io/gorm"
)
type FsCanteenProduct struct {
Id int64 `gorm:"primary_key" json:"id"` // ID
CanteenType *int64 `gorm:"" json:"canteen_type"` // 餐厅类别id
ProductId *int64 `gorm:"" json:"product_id"` // 产品id
SizeId *int64 `gorm:"" json:"size_id"` // 尺寸id
Sort *int64 `gorm:"" json:"sort"` // 排序
Status *int64 `gorm:"" json:"status"` // 状态位 1启用0停用
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
Sid *string `gorm:"" json:"sid"` // 前端带入的id
}
type FsCanteenProductModel struct{ db *gorm.DB }
func NewFsCanteenProductModel(db *gorm.DB) *FsCanteenProductModel { return &FsCanteenProductModel{db} }

View File

@ -0,0 +1,16 @@
package model
import (
"gorm.io/gorm"
)
type FsCanteenType struct {
Id int64 `gorm:"primary_key" json:"id"` // ID
Name *string `gorm:"" json:"name"` // 餐厅名字
Sort *int64 `gorm:"" json:"sort"` // 排序
Status *int64 `gorm:"" json:"status"` // 状态位 1启用0停用
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
}
type FsCanteenTypeModel struct{ db *gorm.DB }
func NewFsCanteenTypeModel(db *gorm.DB) *FsCanteenTypeModel { return &FsCanteenTypeModel{db} }

View File

@ -0,0 +1,29 @@
package model
import (
"time"
"gorm.io/gorm"
)
type FsCart struct {
Id int64 `gorm:"primary_key" json:"id"` // id
UserId *int64 `gorm:"" json:"user_id"` // 用户ID
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
TemplateId *int64 `gorm:"" json:"template_id"` // 模板ID
PriceId *int64 `gorm:"" json:"price_id"` // 价格ID
MaterialId *int64 `gorm:"" json:"material_id"` // 材质ID
SizeId *int64 `gorm:"" json:"size_id"` // 尺寸ID
BuyNum *int64 `gorm:"" json:"buy_num"` // 购买数量
Cover *string `gorm:"" json:"cover"` // 截图
DesignId *int64 `gorm:"" json:"design_id"` // 设计ID
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
Status *int64 `gorm:"" json:"status"` // 状态位
OptionalId *int64 `gorm:"" json:"optional_id"` // 选项ID
IsCheck *int64 `gorm:"" json:"is_check"` // 是否选中状态0未选中1选中
TsTime *time.Time `gorm:"" json:"ts_time"` //
IsEmail *int64 `gorm:"" json:"is_email"` // 是否发送邮件
}
type FsCartModel struct{ db *gorm.DB }
func NewFsCartModel(db *gorm.DB) *FsCartModel { return &FsCartModel{db} }

View File

@ -0,0 +1,19 @@
package model
import (
"gorm.io/gorm"
)
type FsFaq struct {
Id int64 `gorm:"primary_key" json:"id"` //
TagId *int64 `gorm:"" json:"tag_id"` // 分类ID
TagName *string `gorm:"" json:"tag_name"` // 分类名称
Title *string `gorm:"" json:"title"` // 标题
Content *string `gorm:"" json:"content"` // 内容
Status *int64 `gorm:"" json:"status"` // 状态(0:禁用1:启用)
Sort *int64 `gorm:"" json:"sort"` // 排序
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
}
type FsFaqModel struct{ db *gorm.DB }
func NewFsFaqModel(db *gorm.DB) *FsFaqModel { return &FsFaqModel{db} }

View File

@ -0,0 +1,16 @@
package model
import (
"gorm.io/gorm"
)
type FsFont struct {
Id int64 `gorm:"primary_key" json:"id"` // id
Title *string `gorm:"" json:"title"` // 字体名字
LinuxFontname *string `gorm:"" json:"linux_fontname"` // linux对应字体名
FilePath *string `gorm:"" json:"file_path"` // 字体文件路径
Sort *int64 `gorm:"" json:"sort"` // 排序
}
type FsFontModel struct{ db *gorm.DB }
func NewFsFontModel(db *gorm.DB) *FsFontModel { return &FsFontModel{db} }

View File

@ -0,0 +1,21 @@
package model
import (
"gorm.io/gorm"
)
type FsGuest struct {
GuestId int64 `gorm:"primary_key" json:"guest_id"` // 游客ID
AuthKey *string `gorm:"" json:"auth_key"` // jwt token
Status *int64 `gorm:"" json:"status"` // 1正常 0不正常
IsDel *int64 `gorm:"" json:"is_del"` // 是否删除 1删除
CreatedAt *int64 `gorm:"" json:"created_at"` // 添加时间
UpdatedAt *int64 `gorm:"" json:"updated_at"` // 更新时间
IsOpenRender *int64 `gorm:"" json:"is_open_render"` // 是否打开个性化渲染1开启0关闭
IsThousandFace *int64 `gorm:"" json:"is_thousand_face"` // 是否已经存在千人千面1存在0不存在
IsLowRendering *int64 `gorm:"" json:"is_low_rendering"` // 是否开启低渲染模型渲染
IsRemoveBg *int64 `gorm:"" json:"is_remove_bg"` // 用户上传logo是否去除背景
}
type FsGuestModel struct{ db *gorm.DB }
func NewFsGuestModel(db *gorm.DB) *FsGuestModel { return &FsGuestModel{db} }

View File

@ -0,0 +1,18 @@
package model
import (
"gorm.io/gorm"
)
type FsMapLibrary struct {
Id int64 `gorm:"primary_key" json:"id"` // Id
Title *string `gorm:"" json:"title"` // 名称
Info *string `gorm:"" json:"info"` // 贴图数据
Sort *int64 `gorm:"" json:"sort"` // 排序
Status *int64 `gorm:"" json:"status"` // 状态 1启用
Ctime *int64 `gorm:"" json:"ctime"` // 创建时间
TagId *int64 `gorm:"" json:"tag_id"` // 模板标签id
}
type FsMapLibraryModel struct{ db *gorm.DB }
func NewFsMapLibraryModel(db *gorm.DB) *FsMapLibraryModel { return &FsMapLibraryModel{db} }

View File

@ -0,0 +1,35 @@
package model
import (
"gorm.io/gorm"
)
type FsOrderDetail struct {
Id int64 `gorm:"primary_key" json:"id"` //
Sn *string `gorm:"" json:"sn"` // 唯一编码
OrderId *int64 `gorm:"" json:"order_id"` // 订单ID
UserId *int64 `gorm:"" json:"user_id"` // 用户ID
FactoryId *int64 `gorm:"" json:"factory_id"` // 工厂ID
OrderDetailTemplateId *int64 `gorm:"" json:"order_detail_template_id"` // 详情templateID
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
BuyNum *int64 `gorm:"" json:"buy_num"` // 购买数量
PushNum *int64 `gorm:"" json:"push_num"` // 已发数量
Amount *int64 `gorm:"" json:"amount"` // 单价
Cover *string `gorm:"" json:"cover"` // 截图
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
Status *int64 `gorm:"" json:"status"` // 状态位 是否推送到厂家 是否生产完成 是否发货完成
OptionalId *int64 `gorm:"" json:"optional_id"` // 选项ID
OptionalTitle *string `gorm:"" json:"optional_title"` // 选项名称
OptionPrice *int64 `gorm:"" json:"option_price"` // 配件价格
IsTofactory *int64 `gorm:"" json:"is_tofactory"` // 是否推送到工厂
IsProduct *int64 `gorm:"" json:"is_product"` // 是否生产中
IsProductCompletion *int64 `gorm:"" json:"is_product_completion"` // 是否生产完成
IsCloud *int64 `gorm:"" json:"is_cloud"` // 是否是云仓订单
IsTocloud *int64 `gorm:"" json:"is_tocloud"` // 是否已发云仓(云仓单要发货到云仓,直接发到用户的不需要发到云仓)
IsDeliver *int64 `gorm:"" json:"is_deliver"` // 是否已发货
IsEnd *int64 `gorm:"" json:"is_end"` // 是否完成订单(签收)
CartId *int64 `gorm:"" json:"cart_id"` // 购物车编号
}
type FsOrderDetailModel struct{ db *gorm.DB }
func NewFsOrderDetailModel(db *gorm.DB) *FsOrderDetailModel { return &FsOrderDetailModel{db} }

View File

@ -0,0 +1,24 @@
package model
import (
"gorm.io/gorm"
)
type FsOrderDetailTemplate struct {
Id int64 `gorm:"primary_key" json:"id"` //
Sn *string `gorm:"" json:"sn"` // 唯一编码
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
ModelId *int64 `gorm:"" json:"model_id"` // 模型ID
TemplateId *int64 `gorm:"" json:"template_id"` // 模板ID
MaterialId *int64 `gorm:"" json:"material_id"` // 材质id
SizeId *int64 `gorm:"" json:"size_id"` // 尺寸id
EachBoxNum *int64 `gorm:"" json:"each_box_num"` // 每一箱的个数
EachBoxWeight *float64 `gorm:"" json:"each_box_weight"` // 每一箱的重量 单位KG
DesignId *int64 `gorm:"" json:"design_id"` // 设计ID
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
}
type FsOrderDetailTemplateModel struct{ db *gorm.DB }
func NewFsOrderDetailTemplateModel(db *gorm.DB) *FsOrderDetailTemplateModel {
return &FsOrderDetailTemplateModel{db}
}

View File

@ -0,0 +1,48 @@
package model
import (
"gorm.io/gorm"
"time"
)
type FsOrder struct {
Id int64 `gorm:"primary_key" json:"id"` //
Sn *string `gorm:"" json:"sn"` // 订单编号 FS211224OL2XDKNP
UserId *int64 `gorm:"" json:"user_id"` // 用户ID
SellerUserId *int64 `gorm:"" json:"seller_user_id"` // 销售员ID 0:自主下单
TotalAmount *int64 `gorm:"" json:"total_amount"` // 总价
PayedAmount *int64 `gorm:"" json:"payed_amount"` // 已支付金额
PayMethod *int64 `gorm:"" json:"pay_method"` // 支付方式 1paypal 2strip
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
Utime *int64 `gorm:"" json:"utime"` // 更新时间
Ptime *int64 `gorm:"" json:"ptime"` // 最后一次 支付时间(可能多次支付)
AddressId *int64 `gorm:"" json:"address_id"` // 地址ID或者云仓ID
DeliveryMethod *int64 `gorm:"" json:"delivery_method"` // 配送方式 1:直接发货到收获地址 2云仓
CustomerMark *string `gorm:"" json:"customer_mark"` // 客户备注
Mark *string `gorm:"" json:"mark"` // 后台订单备注
AddressInfo *string `gorm:"" json:"address_info"` // 详细地址信息JSON
IsSup *int64 `gorm:"" json:"is_sup"` // 0不是补货 1是补货
Status *int64 `gorm:"" json:"status"` // 状态位0未支付1部分支付2支付完成3部分生产4部分生产完成5全部生产6全部生产完成7部分发货8发货完成9完成订单10取消订单11:退款中12退款完成13:订单已删除14:订单已关闭)
IsPartPay *int64 `gorm:"" json:"is_part_pay"` // 是否部分支付01
IsPayCompleted *int64 `gorm:"" json:"is_pay_completed"` // 是否支付完成01
IsPartProduct *int64 `gorm:"" json:"is_part_product"` // 是否部分生产01
IsPartProductCompleted *int64 `gorm:"" json:"is_part_product_completed"` // 是否部分生产完成01
IsAllProduct *int64 `gorm:"" json:"is_all_product"` // 是否全部生产01
IsAllProductCompleted *int64 `gorm:"" json:"is_all_product_completed"` // 是否全部生产完成01
IsPartDelivery *int64 `gorm:"" json:"is_part_delivery"` // 是否部分发货01
IsDeliveryCompleted *int64 `gorm:"" json:"is_delivery_completed"` // 是否发货完成01
IsComplated *int64 `gorm:"" json:"is_complated"` // 是否完成订单01
IsCancel *int64 `gorm:"" json:"is_cancel"` // 是否取消订单01
IsRefunding *int64 `gorm:"" json:"is_refunding"` // 是否退款中01
IsRefunded *int64 `gorm:"" json:"is_refunded"` // 是否退款完成01
IsDeleted *int64 `gorm:"" json:"is_deleted"` // 是否删除01
RefundReasonId *int64 `gorm:"" json:"refund_reason_id"` // 取消订单原因ID
RefundReason *string `gorm:"" json:"refund_reason"` // 取消订单原因
TsTime *time.Time `gorm:"" json:"ts_time"` //
IsSure *int64 `gorm:"" json:"is_sure"` // 是否确认订单 1确认0未确认
DeliverSn *string `gorm:"" json:"deliver_sn"` // 发货单号
EmailTime *int64 `gorm:"" json:"email_time"` // 邮件发送时间
}
type FsOrderModel struct{ db *gorm.DB }
func NewFsOrderModel(db *gorm.DB) *FsOrderModel { return &FsOrderModel{db} }

View File

@ -0,0 +1,28 @@
package model
import (
"gorm.io/gorm"
"time"
)
type FsProductDesign struct {
Id int64 `gorm:"primary_key" json:"id"` //
Sn *string `gorm:"" json:"sn"` // 唯一标识
UserId *int64 `gorm:"" json:"user_id"` // 用户ID
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
TemplateId *int64 `gorm:"" json:"template_id"` // 模型ID
MaterialId *int64 `gorm:"" json:"material_id"` // 材质ID
SizeId *int64 `gorm:"" json:"size_id"` // 尺寸ID
OptionalId *int64 `gorm:"" json:"optional_id"` // 选项ID
Cover *string `gorm:"" json:"cover"` // 封面图
Info *string `gorm:"" json:"info"` // 保留的设计信息
Utime *time.Time `gorm:"" json:"utime"` // 更新时间
Status *int64 `gorm:"" json:"status"` // 状态
IsDel *int64 `gorm:"" json:"is_del"` // 是否删除 0未删除 1删除
IsPay *int64 `gorm:"" json:"is_pay"` // 是否已有支付 0 未 1 有
LogoColor *string `gorm:"" json:"logo_color"` // logo图片备选项
PageGuid *string `gorm:"" json:"page_guid"` // 页面识别id
}
type FsProductDesignModel struct{ db *gorm.DB }
func NewFsProductDesignModel(db *gorm.DB) *FsProductDesignModel { return &FsProductDesignModel{db} }

View File

@ -0,0 +1,40 @@
package model
import (
"gorm.io/gorm"
)
type FsProduct struct {
Id int64 `gorm:"primary_key" json:"id"` //
Sn *string `gorm:"" json:"sn"` // 商品编号 P98f087j
Type *int64 `gorm:"" json:"type"` // 分类ID
Title *string `gorm:"" json:"title"` // 名称
TitleCn *string `gorm:"" json:"title_cn"` // 中文名称
Cover *string `gorm:"" json:"cover"` // 封面图
Imgs *string `gorm:"" json:"imgs"` // 一个或多个介绍图或视频
Keywords *string `gorm:"" json:"keywords"` // 关键字
Intro *string `gorm:"" json:"intro"` // 简要描述
Sort *int64 `gorm:"" json:"sort"` // 排序
SelledNum *int64 `gorm:"" json:"selled_num"` // 已卖数量
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
View *int64 `gorm:"" json:"view"` // 浏览量
SizeIds *string `gorm:"" json:"size_ids"` // 尺寸 1,2,3,4
MaterialIds *string `gorm:"" json:"material_ids"` // 材质 1,2,3
TagIds *string `gorm:"" json:"tag_ids"` // 标签 逗号间隔
Status *int64 `gorm:"" json:"status"` // 状态位 弃用
ProduceDays *int64 `gorm:"" json:"produce_days"` // 生产天数
DeliveryDays *int64 `gorm:"" json:"delivery_days"` // 运送天数
CoverImg *string `gorm:"" json:"cover_img"` // 背景图
IsShelf *int64 `gorm:"" json:"is_shelf"` // 是否上架
IsRecommend *int64 `gorm:"" json:"is_recommend"` // 是否推荐
IsHot *int64 `gorm:"" json:"is_hot"` // 是否热销
IsProtection *int64 `gorm:"" json:"is_protection"` // 是否环保
IsMicrowave *int64 `gorm:"" json:"is_microwave"` // 是否可微波炉
IsDel *int64 `gorm:"" json:"is_del"` // 是否删除
RecommendProduct *string `gorm:"" json:"recommend_product"` // 推荐产品id例如: 1,3,4,5
RecommendProductSort *string `gorm:"" json:"recommend_product_sort"` // 推荐排序例如:1324
SceneIds *string `gorm:"" json:"scene_ids"` // 关联的场景id
}
type FsProductModel struct{ db *gorm.DB }
func NewFsProductModel(db *gorm.DB) *FsProductModel { return &FsProductModel{db} }

View File

@ -0,0 +1,29 @@
package model
import (
"gorm.io/gorm"
)
type FsProductModel3d struct {
Id int64 `gorm:"primary_key" json:"id"` //
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
Tag *int64 `gorm:"" json:"tag"` // 类别1模型2配件3场景
Title *string `gorm:"" json:"title"` // 标题
Name *string `gorm:"" json:"name"` // 详情页展示名称
ModelInfo *string `gorm:"" json:"model_info"` // 模型详情
MaterialId *int64 `gorm:"" json:"material_id"` // 材质ID
SizeId *int64 `gorm:"" json:"size_id"` // 尺寸ID
Sort *int64 `gorm:"" json:"sort"` // 排序
Light *int64 `gorm:"" json:"light"` // 灯光组
LightList *string `gorm:"" json:"light_list"` // 灯光备选项
PartId *int64 `gorm:"" json:"part_id"` // 配件选项id配件就是模型的id
PartList *string `gorm:"" json:"part_list"` // 配件备选项
Status *int64 `gorm:"" json:"status"` // 状态位 显示 删除
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
OptionTemplate *int64 `gorm:"" json:"option_template"` // 配件绑定的公共模板
Price *int64 `gorm:"" json:"price"` // 仅配件用,配件的价格, 单位:美分
Sku *string `gorm:"" json:"sku"` // sku
}
type FsProductModel3dModel struct{ db *gorm.DB }
func NewFsProductModel3dModel(db *gorm.DB) *FsProductModel3dModel { return &FsProductModel3dModel{db} }

View File

@ -0,0 +1,18 @@
package model
import (
"gorm.io/gorm"
)
type FsProductModel3dLight struct {
Id int64 `gorm:"primary_key" json:"id"` //
Name *string `gorm:"" json:"name"` // 灯光名称
Info *string `gorm:"" json:"info"` // 灯光数据json格式
Status *int64 `gorm:"" json:"status"` // 状态值1显示0删除
Ctime *int64 `gorm:"" json:"ctime"` // 创建时间
}
type FsProductModel3dLightModel struct{ db *gorm.DB }
func NewFsProductModel3dLightModel(db *gorm.DB) *FsProductModel3dLightModel {
return &FsProductModel3dLightModel{db}
}

View File

@ -0,0 +1,24 @@
package model
import (
"gorm.io/gorm"
)
type FsProductPrice struct {
Id int64 `gorm:"primary_key" json:"id"` //
Sn *string `gorm:"" json:"sn"` // 唯一编码
Title *string `gorm:"" json:"title"` // 标题描述
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
MaterialId *int64 `gorm:"" json:"material_id"` // 材质ID
SizeId *int64 `gorm:"" json:"size_id"` // 尺寸ID
EachBoxNum *int64 `gorm:"" json:"each_box_num"` // 每一箱的个数
EachBoxWeight *float64 `gorm:"" json:"each_box_weight"` // 每一箱的重量 单位KG
MinBuyNum *int64 `gorm:"" json:"min_buy_num"` // 最少购买量
StepNum *string `gorm:"" json:"step_num"` // 数量阶梯 eg:10,20,30
StepPrice *string `gorm:"" json:"step_price"` // 价格阶梯 eg:100,50,25
Status *int64 `gorm:"" json:"status"` // 是否可用
IsDefault *int64 `gorm:"" json:"is_default"` // 是否默认
}
type FsProductPriceModel struct{ db *gorm.DB }
func NewFsProductPriceModel(db *gorm.DB) *FsProductPriceModel { return &FsProductPriceModel{db} }

View File

@ -0,0 +1,21 @@
package model
import (
"gorm.io/gorm"
)
type FsProductSize struct {
Id int64 `gorm:"primary_key" json:"id"` //
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
Title *string `gorm:"" json:"title"` // 标题 10*10*20
Cover *string `gorm:"" json:"cover"` // 封面图
CoverImg *string `gorm:"" json:"cover_img"` // 背景图
Capacity *string `gorm:"" json:"capacity"` // 自己填的尺寸名称
Status *int64 `gorm:"" json:"status"` // 状态位 显示 删除
Sort *int64 `gorm:"" json:"sort"` // 排序
Remark *string `gorm:"" json:"remark"` // 备注信息
PartsCanDeleted *int64 `gorm:"" json:"parts_can_deleted"` // 配件是否可移除 1是0否
}
type FsProductSizeModel struct{ db *gorm.DB }
func NewFsProductSizeModel(db *gorm.DB) *FsProductSizeModel { return &FsProductSizeModel{db} }

View File

@ -0,0 +1,17 @@
package model
import (
"gorm.io/gorm"
)
type FsProductTemplateTags struct {
Id int64 `gorm:"primary_key" json:"id"` // ID
Title *string `gorm:"" json:"title"` // 标题
Status *int64 `gorm:"" json:"status"` // 状态 1可用
CreateAt *int64 `gorm:"" json:"create_at"` // 创建时间
}
type FsProductTemplateTagsModel struct{ db *gorm.DB }
func NewFsProductTemplateTagsModel(db *gorm.DB) *FsProductTemplateTagsModel {
return &FsProductTemplateTagsModel{db}
}

View File

@ -0,0 +1,29 @@
package model
import (
"gorm.io/gorm"
)
type FsProductTemplateV2 struct {
Id int64 `gorm:"primary_key" json:"id"` //
ProductId *int64 `gorm:"" json:"product_id"` // 产品ID
ModelId *int64 `gorm:"" json:"model_id"` // 模型ID
Title *string `gorm:"" json:"title"` // 模板sku,预留字段
Name *string `gorm:"" json:"name"` // 名称
CoverImg *string `gorm:"" json:"cover_img"` // 模板背景图
TemplateInfo *string `gorm:"" json:"template_info"` // 模板详情
MaterialImg *string `gorm:"" json:"material_img"` // 合成好的贴图
Sort *int64 `gorm:"" json:"sort"` // 排序
LogoWidth *int64 `gorm:"" json:"logo_width"` // logo图最大宽度
LogoHeight *int64 `gorm:"" json:"logo_height"` // logo图最大高度
IsPublic *int64 `gorm:"" json:"is_public"` // 是否可公用1:可以0不可以
Status *int64 `gorm:"" json:"status"` // 状态1正常 2异常
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
Tag *string `gorm:"" json:"tag"` // 标签(用户自填)
IsDel *int64 `gorm:"" json:"is_del"` // 是否删除 1删除
}
type FsProductTemplateV2Model struct{ db *gorm.DB }
func NewFsProductTemplateV2Model(db *gorm.DB) *FsProductTemplateV2Model {
return &FsProductTemplateV2Model{db}
}

View File

@ -0,0 +1,23 @@
package model
import (
"gorm.io/gorm"
)
type FsQrcodeSet struct {
Id int64 `gorm:"primary_key" json:"id"` // id
Name *string `gorm:"" json:"name"` // 二维码组件名称
Size *int64 `gorm:"" json:"size"` // 二维码内容尺寸
IndexX *int64 `gorm:"" json:"index_x"` // x偏移量
IndexY *int64 `gorm:"" json:"index_y"` // y偏移量
SvgWebsite *string `gorm:"" json:"svg_website"` // website d数据
SvgInstagram *string `gorm:"" json:"svg_instagram"` // svg instagram d数据
SvgFacebook *string `gorm:"" json:"svg_facebook"` // svg facebook d数据
Status *int64 `gorm:"" json:"status"` // 状态
AdminId *int64 `gorm:"" json:"admin_id"` // 操作人
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
Utime *int64 `gorm:"" json:"utime"` // 更新时间
}
type FsQrcodeSetModel struct{ db *gorm.DB }
func NewFsQrcodeSetModel(db *gorm.DB) *FsQrcodeSetModel { return &FsQrcodeSetModel{db} }

View File

@ -0,0 +1,16 @@
package model
import (
"gorm.io/gorm"
)
type FsStandardLogo struct {
Id int64 `gorm:"primary_key" json:"id"` // ID
Name *string `gorm:"" json:"name"` // logo名称
Image *string `gorm:"" json:"image"` // 图片地址
Ctime *int64 `gorm:"" json:"ctime"` // 添加时间
Status *int64 `gorm:"" json:"status"` // 状态 1正常 0删除
}
type FsStandardLogoModel struct{ db *gorm.DB }
func NewFsStandardLogoModel(db *gorm.DB) *FsStandardLogoModel { return &FsStandardLogoModel{db} }

View File

@ -0,0 +1,22 @@
package model
import (
"gorm.io/gorm"
)
type FsTags struct {
Id int64 `gorm:"primary_key" json:"id"` // ID
Title *string `gorm:"" json:"title"` // 标题
Level *int64 `gorm:"" json:"level"` // 层级、分类 1 => 二维码分类
ClickNum *int64 `gorm:"" json:"click_num"` // 点击次数
Sort *int64 `gorm:"" json:"sort"` // 排序(从大到小)
CreateAt *int64 `gorm:"" json:"create_at"` // 创建时间
Icon *string `gorm:"" json:"icon"` // 标签图标
Status *int64 `gorm:"" json:"status"` // 状态 1可用
Description *string `gorm:"" json:"description"` // 介绍 Seo
RecommendProduct *string `gorm:"" json:"recommend_product"` // 推荐产品id例如: 1,3,4,5
RecommendProductSort *string `gorm:"" json:"recommend_product_sort"` // 推荐排序例如:1324
}
type FsTagsModel struct{ db *gorm.DB }
func NewFsTagsModel(db *gorm.DB) *FsTagsModel { return &FsTagsModel{db} }

View File

@ -0,0 +1,37 @@
package model
import (
"gorm.io/gorm"
)
type FsUser struct {
Id int64 `gorm:"primary_key" json:"id"` // ID
FaceId *int64 `gorm:"" json:"face_id"` // facebook的userid
Sub *int64 `gorm:"" json:"sub"` // google的sub
FirstName *string `gorm:"" json:"first_name"` // FirstName
LastName *string `gorm:"" json:"last_name"` // LastName
Username *string `gorm:"" json:"username"` // 用户名
Company *string `gorm:"" json:"company"` // 公司名称
Mobile *string `gorm:"" json:"mobile"` // 手机号码
AuthKey *string `gorm:"" json:"auth_key"` //
PasswordHash *string `gorm:"" json:"password_hash"` //
VerificationToken *string `gorm:"" json:"verification_token"` //
PasswordResetToken *string `gorm:"" json:"password_reset_token"` //
Email *string `gorm:"" json:"email"` // 邮箱
Type *int64 `gorm:"" json:"type"` // 1普通餐厅 2连锁餐厅
Status *int64 `gorm:"" json:"status"` // 1正常 0不正常
IsDel *int64 `gorm:"" json:"is_del"` // 是否删除 1删除
CreatedAt *int64 `gorm:"" json:"created_at"` // 添加时间
UpdatedAt *int64 `gorm:"" json:"updated_at"` // 更新时间
IsOrderStatusEmail *int64 `gorm:"" json:"is_order_status_email"` // 订单状态改变时是否接收邮件
IsEmailAdvertisement *int64 `gorm:"" json:"is_email_advertisement"` // 是否接收邮件广告
IsOrderStatusPhone *int64 `gorm:"" json:"is_order_status_phone"` // 订单状态改变是是否接收电话
IsPhoneAdvertisement *int64 `gorm:"" json:"is_phone_advertisement"` // 是否接收短信广告
IsOpenRender *int64 `gorm:"" json:"is_open_render"` // 是否打开个性化渲染1开启0关闭
IsThousandFace *int64 `gorm:"" json:"is_thousand_face"` // 是否已经存在千人千面1存在0不存在
IsLowRendering *int64 `gorm:"" json:"is_low_rendering"` // 是否开启低渲染模型渲染
IsRemoveBg *int64 `gorm:"" json:"is_remove_bg"` // 用户上传logo是否去除背景
}
type FsUserModel struct{ db *gorm.DB }
func NewFsUserModel(db *gorm.DB) *FsUserModel { return &FsUserModel{db} }

View File

@ -0,0 +1,78 @@
package handler
import (
"errors"
"net/http"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx"
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"fusenapi/server/home-user-auth/internal/logic"
"fusenapi/server/home-user-auth/internal/svc"
"fusenapi/server/home-user-auth/internal/types"
)
func AcceptCookieHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.Request
// 如果端点有请求结构体则使用httpx.Parse方法从HTTP请求体中解析请求数据
if err := httpx.Parse(r, &req); err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 510,
Message: "parameter error",
})
logx.Info(err)
return
}
// 创建一个业务逻辑层实例
l := logic.NewAcceptCookieLogic(r.Context(), svcCtx)
resp := l.AcceptCookie(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {
err := errors.New("server logic is error, resp must not be nil")
httpx.ErrorCtx(r.Context(), w, err)
logx.Error(err)
}
}
}

View File

@ -17,6 +17,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/user/login",
Handler: UserLoginHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/user/accept-cookie",
Handler: AcceptCookieHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/user/fonts",
@ -42,17 +47,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/user/basic-info",
Handler: UserBasicInfoHandler(serverCtx),
},
},
)
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/user/address-list",
Handler: UserAddressListHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
)
}

View File

@ -15,15 +15,31 @@ import (
"fusenapi/server/home-user-auth/internal/types"
)
var wantJwt = true
func UserAddressListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var userinfo *auth.UserInfo
var err error
if wantJwt {
userinfo, err = auth.ParseJwtToken(w, r, &svcCtx.Config.Auth.AccessSecret)
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
@ -32,6 +48,9 @@ func UserAddressListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.Request
@ -48,7 +67,6 @@ func UserAddressListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewUserAddressListLogic(r.Context(), svcCtx)
resp := l.UserAddressList(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
// 否则发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {

View File

@ -17,28 +17,40 @@ import (
func UserBasicInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 解析jwtToken
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error())
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
// 从Token里获取对应的信息
userinfo, err := auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.Request
@ -55,7 +67,6 @@ func UserBasicInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewUserBasicInfoLogic(r.Context(), svcCtx)
resp := l.UserBasicInfo(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
// 否则发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {

View File

@ -17,28 +17,40 @@ import (
func UserFontsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 解析jwtToken
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error())
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
// 从Token里获取对应的信息
userinfo, err := auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.Request
@ -55,7 +67,6 @@ func UserFontsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewUserFontsLogic(r.Context(), svcCtx)
resp := l.UserFonts(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
// 否则发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {

View File

@ -17,28 +17,40 @@ import (
func UserGetTypeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 解析jwtToken
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error())
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
// 从Token里获取对应的信息
userinfo, err := auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.Request
@ -55,7 +67,6 @@ func UserGetTypeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewUserGetTypeLogic(r.Context(), svcCtx)
resp := l.UserGetType(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
// 否则发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {

View File

@ -17,28 +17,40 @@ import (
func UserSaveBasicInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 解析jwtToken
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error())
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
// 从Token里获取对应的信息
userinfo, err := auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.RequestBasicInfoForm
@ -55,7 +67,6 @@ func UserSaveBasicInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewUserSaveBasicInfoLogic(r.Context(), svcCtx)
resp := l.UserSaveBasicInfo(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
// 否则发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {

View File

@ -17,28 +17,40 @@ import (
func UserStatusConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 解析jwtToken
var (
// 定义错误变量
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error())
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
// 从Token里获取对应的信息
userinfo, err := auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.Request
@ -55,7 +67,6 @@ func UserStatusConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
l := logic.NewUserStatusConfigLogic(r.Context(), svcCtx)
resp := l.UserStatusConfig(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
// 否则发送500内部服务器错误的JSON响应并记录错误消息logx.Error。
if resp != nil {
httpx.OkJsonCtx(r.Context(), w, resp)
} else {

View File

@ -0,0 +1,38 @@
package logic
import (
"fusenapi/utils/auth"
"fusenapi/utils/basic"
"context"
"fusenapi/server/home-user-auth/internal/svc"
"fusenapi/server/home-user-auth/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AcceptCookieLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAcceptCookieLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AcceptCookieLogic {
return &AcceptCookieLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AcceptCookieLogic) AcceptCookie(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
// userinfo 传入值时, 一定不为null
idtyp := userinfo.GetIdType()
if idtyp == auth.IDTYPE_Guest {
return resp.SetStatus(basic.CodeDupGuestErr)
}
return resp.SetStatus(basic.CodeOK)
}

View File

@ -29,7 +29,7 @@ func NewUserAddressListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *U
func (l *UserAddressListLogic) UserAddressList(req *types.Request, userinfo *auth.UserInfo) (resp *basic.Response) {
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
m := model.NewFsAddressModel(l.svcCtx.MysqlConn)
userinfo.GetIdType()
// user := auth.GetUserInfoFormCtx(l.ctx)
// if user.UserId == 0 {
// return resp.SetStatus(basic.CodeUnAuth)

View File

@ -48,7 +48,7 @@ func (l *UserLoginLogic) UserLogin(req *types.RequestUserLogin) (resp *basic.Res
// 如果密码匹配,则生成 JWT Token。
nowSec := time.Now().Unix()
jwtToken, err = auth.GenerateJwtToken(l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, int(userModel.Id))
jwtToken, err = auth.GenerateJwtToken(&l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, nowSec, int64(userModel.Id), 0)
// 如果生成 JWT Token 失败,则抛出错误并返回未认证的状态码。
if err != nil {

View File

@ -24,8 +24,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
func (svcCxt *ServiceContext) ParseJwtToken(r *http.Request) (jwt.MapClaims, error) {
AuthKey := r.Header.Get("Authorization")
if len(AuthKey) <= 50 {
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
if AuthKey == "" {
return nil, nil
}
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {

View File

@ -18,6 +18,9 @@ service home-user-auth {
@handler UserLoginHandler
post /user/login(RequestUserLogin) returns (response);
@handler AcceptCookieHandler
post /user/accept-cookie(request) returns (response);
@handler UserFontsHandler
get /user/fonts(request) returns (response);
@ -33,17 +36,9 @@ service home-user-auth {
@handler UserBasicInfoHandler
get /user/basic-info(request) returns (response);
// @handler UserAddressListHandler
// get /user/address-list(request) returns (response);
}
@server(
jwt: Auth
)
service home-user-auth {
@handler UserAddressListHandler
get /user/address-list(request) returns (response);
}
type RequestBasicInfoForm {

View File

@ -8,17 +8,41 @@ import (
"net/http"
"github.com/golang-jwt/jwt"
"github.com/google/uuid"
"github.com/zeromicro/go-zero/core/logx"
)
type IDTYPE int
const (
// 白板用户, 以观众身份命名, 没有接收Cookie, 没有拿到guest_id的用户
IDTYPE_Onlooker IDTYPE = 0
// 登录用户
IDTYPE_User IDTYPE = 1
// 游客 接收授权拿到guest_id的用户
IDTYPE_Guest IDTYPE = 2
)
type UserInfo struct {
UserId int64 `json:"userid"`
UserId int64 `json:"user_id"`
GuestId int64 `json:"guest_id"`
}
// GetIdType 用户确认用户身份类型
func (info *UserInfo) GetIdType() IDTYPE {
if info.UserId != 0 {
return IDTYPE_User
}
if info.GuestId != 0 {
return IDTYPE_Guest
}
return IDTYPE_Onlooker
}
// 获取登录信息
func GetUserInfoFormCtx(ctx context.Context) UserInfo {
uid, err := ctx.Value("userid").(json.Number).Int64()
uid, err := ctx.Value("user_id").(json.Number).Int64()
if err != nil {
logx.Error("parse uid form context err:", err.Error())
return UserInfo{}
@ -28,43 +52,60 @@ func GetUserInfoFormCtx(ctx context.Context) UserInfo {
// 获取登录信息
func GetUserInfoFormMapClaims(claims jwt.MapClaims) (*UserInfo, error) {
if userid, ok := claims["userid"]; ok {
userinfo := &UserInfo{}
if userid, ok := claims["user_id"]; ok {
uid, ok := userid.(float64)
if !ok {
err := errors.New(fmt.Sprint("parse uid form context err:", userid))
logx.Error("parse uid form context err:", err)
return nil, err
}
return &UserInfo{UserId: int64(uid)}, nil
userinfo.UserId = int64(uid)
} else {
err := errors.New(`userid not in claims`)
logx.Error(`userid not in claims`)
return nil, err
}
if guestid, ok := claims["guest_id"]; ok {
gid, ok := guestid.(float64)
if !ok {
err := errors.New(fmt.Sprint("parse guestid form context err:", guestid))
logx.Error("parse guestid form context err:", err)
return nil, err
}
userinfo.GuestId = int64(gid)
} else {
err := errors.New(`userid not in claims`)
logx.Error(`userid not in claims`)
return nil, err
}
return userinfo, nil
}
func GenerateJwtToken(accessSecret string, accessExpire, nowSec int64, userid int) (string, error) {
func GenerateJwtToken(accessSecret *string, accessExpire, nowSec int64, userid int64, guestid int64) (string, error) {
claims := make(jwt.MapClaims)
claims["exp"] = nowSec + accessExpire
claims["iat"] = nowSec
claims["userid"] = userid
if userid == 0 {
u, err := uuid.NewUUID()
if err != nil {
logx.Error(err)
return "", err
}
claims["guestid"] = u.String() // TODO: 未完成
if userid == 0 && guestid == 0 {
err := errors.New("userid and guestid cannot be 0 at the same time")
logx.Error(err)
return "", err
}
claims["user_id"] = userid
claims["guest_id"] = guestid
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte(accessSecret))
return token.SignedString([]byte(*accessSecret))
}
func ParseJwtToken(w http.ResponseWriter, r *http.Request, AccessSecret *string) (*UserInfo, error) {
// 解析jwtToken
claims, err := getJwtClaims(r, AccessSecret)
claims, err := getJwtClaimsFromRequest(r, AccessSecret)
// 如果解析出错则返回未授权的JSON响应并记录错误消息
if err != nil {
// httpx.OkJsonCtx(r.Context(), w, &basic.Response{
@ -89,12 +130,17 @@ func ParseJwtToken(w http.ResponseWriter, r *http.Request, AccessSecret *string)
return userinfo, err
}
func getJwtClaims(r *http.Request, AccessSecret *string) (jwt.MapClaims, error) {
func getJwtClaimsFromRequest(r *http.Request, AccessSecret *string) (jwt.MapClaims, error) {
AuthKey := r.Header.Get("Authorization")
if len(AuthKey) <= 50 {
return nil, errors.New(fmt.Sprint("Error parsing token, len:", len(AuthKey)))
}
return getJwtClaims(AuthKey, AccessSecret)
}
func getJwtClaims(AuthKey string, AccessSecret *string) (jwt.MapClaims, error) {
token, err := jwt.Parse(AuthKey, func(token *jwt.Token) (interface{}, error) {
// 检查签名方法是否为 HS256
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {

30
utils/auth/user_test.go Normal file
View File

@ -0,0 +1,30 @@
package auth
import (
"testing"
"time"
)
// TestGenJwt 测试jwt序列化
func TestGenJwt(t *testing.T) {
now := time.Now().Unix()
secret := "fusen123"
a, err := GenerateJwtToken(&secret, 3600, now, 123, 1234)
if err != nil {
t.Error(err)
}
// log.Println(a)
claims, err := getJwtClaims(a, &secret)
if err != nil {
t.Error(err)
}
userinfo, err := GetUserInfoFormMapClaims(claims)
if err != nil {
t.Error(err)
}
if userinfo.UserId != 123 || userinfo.GuestId != 1234 {
t.Error(userinfo)
}
// log.Println(claims)
}

View File

@ -13,8 +13,9 @@ var (
CodeServiceErr = &StatusResponse{510, "server logic error"} // server logic 错误
CodeUnAuth = &StatusResponse{401, "unauthorized"} // 未授权
CodeUpdateErr = &StatusResponse{5000, "update database error"} // update database logic 错误
CodeRequestParamsErr = &StatusResponse{5001, "invalid request param"} // api参数校验 错误
CodeUpdateErr = &StatusResponse{5000, "update database error"} // update database logic 错误
CodeDupGuestErr = &StatusResponse{5001, "the user is already a guest user and does not need to apply again"} // 用户已经是guest用户不需要重复申请 错误
CodeRequestParamsErr = &StatusResponse{5002, "invalid request param"} // api参数校验 错误
)
type Response struct {