diff --git a/ddl/fs_guest.sql b/ddl/fs_guest.sql new file mode 100644 index 00000000..980b268d --- /dev/null +++ b/ddl/fs_guest.sql @@ -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='游客表'; \ No newline at end of file diff --git a/fs_gen_mysql_model.sh b/fs_gen_mysql_model.sh index 95bf5fbd..81e4550e 100755 --- a/fs_gen_mysql_model.sh +++ b/fs_gen_mysql_model.sh @@ -1,2 +1,4 @@ #! /bin/bash -goctl model mysql ddl --src ./ddl/$1.sql --dir model/ --home ./goctl_template \ No newline at end of file +# goctl model mysql ddl --src ./ddl/$1.sql --dir model/ --home ./goctl_template + +go run generator/main.go -name $1 \ No newline at end of file diff --git a/generator/basic.go b/generator/basic.go new file mode 100644 index 00000000..42744d43 --- /dev/null +++ b/generator/basic.go @@ -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", +} diff --git a/generator/main.go b/generator/main.go new file mode 100644 index 00000000..326e1792 --- /dev/null +++ b/generator/main.go @@ -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) + } +} diff --git a/generator/main_test.go b/generator/main_test.go new file mode 100644 index 00000000..406706df --- /dev/null +++ b/generator/main_test.go @@ -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() +} diff --git a/go.mod b/go.mod index 7e076438..c4436c68 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index 27c0ccde..417ae23c 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/goctl_template/api/handler.tpl b/goctl_template/api/handler.tpl index 3da5520e..3b228256 100644 --- a/goctl_template/api/handler.tpl +++ b/goctl_template/api/handler.tpl @@ -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 { diff --git a/model/fsguestmodel.go b/model/fsguestmodel.go new file mode 100755 index 00000000..f3f3dc68 --- /dev/null +++ b/model/fsguestmodel.go @@ -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), + } +} diff --git a/model/fsguestmodel_gen.go b/model/fsguestmodel_gen.go new file mode 100755 index 00000000..71e7497c --- /dev/null +++ b/model/fsguestmodel_gen.go @@ -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 +} diff --git a/model/gmodel/fsguestmodel.go b/model/gmodel/fsguestmodel.go new file mode 100755 index 00000000..36bd6647 --- /dev/null +++ b/model/gmodel/fsguestmodel.go @@ -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是否去除背景 +} diff --git a/model/gmodel_gen/fs_address_gen.go b/model/gmodel_gen/fs_address_gen.go new file mode 100644 index 00000000..6709ab5d --- /dev/null +++ b/model/gmodel_gen/fs_address_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_canteen_product_gen.go b/model/gmodel_gen/fs_canteen_product_gen.go new file mode 100644 index 00000000..75eb8347 --- /dev/null +++ b/model/gmodel_gen/fs_canteen_product_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_canteen_type_gen.go b/model/gmodel_gen/fs_canteen_type_gen.go new file mode 100644 index 00000000..c9773ccb --- /dev/null +++ b/model/gmodel_gen/fs_canteen_type_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_cart_gen.go b/model/gmodel_gen/fs_cart_gen.go new file mode 100644 index 00000000..ffc91a8c --- /dev/null +++ b/model/gmodel_gen/fs_cart_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_faq_gen.go b/model/gmodel_gen/fs_faq_gen.go new file mode 100644 index 00000000..ceedd186 --- /dev/null +++ b/model/gmodel_gen/fs_faq_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_font_gen.go b/model/gmodel_gen/fs_font_gen.go new file mode 100644 index 00000000..7fe5fd39 --- /dev/null +++ b/model/gmodel_gen/fs_font_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_guest_gen.go b/model/gmodel_gen/fs_guest_gen.go new file mode 100644 index 00000000..747a929d --- /dev/null +++ b/model/gmodel_gen/fs_guest_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_map_library_gen.go b/model/gmodel_gen/fs_map_library_gen.go new file mode 100644 index 00000000..c17401fe --- /dev/null +++ b/model/gmodel_gen/fs_map_library_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_order_detail_gen.go b/model/gmodel_gen/fs_order_detail_gen.go new file mode 100644 index 00000000..d6c7ced2 --- /dev/null +++ b/model/gmodel_gen/fs_order_detail_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_order_detail_template_gen.go b/model/gmodel_gen/fs_order_detail_template_gen.go new file mode 100644 index 00000000..6df521c8 --- /dev/null +++ b/model/gmodel_gen/fs_order_detail_template_gen.go @@ -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} +} diff --git a/model/gmodel_gen/fs_order_gen.go b/model/gmodel_gen/fs_order_gen.go new file mode 100644 index 00000000..93453496 --- /dev/null +++ b/model/gmodel_gen/fs_order_gen.go @@ -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"` // 是否部分支付(0:否,1:是) + IsPayCompleted *int64 `gorm:"" json:"is_pay_completed"` // 是否支付完成(0:否,1:是) + IsPartProduct *int64 `gorm:"" json:"is_part_product"` // 是否部分生产(0:否,1:是) + IsPartProductCompleted *int64 `gorm:"" json:"is_part_product_completed"` // 是否部分生产完成(0:否,1:是) + IsAllProduct *int64 `gorm:"" json:"is_all_product"` // 是否全部生产(0:否,1:是) + IsAllProductCompleted *int64 `gorm:"" json:"is_all_product_completed"` // 是否全部生产完成(0:否,1:是) + IsPartDelivery *int64 `gorm:"" json:"is_part_delivery"` // 是否部分发货(0:否,1:是) + IsDeliveryCompleted *int64 `gorm:"" json:"is_delivery_completed"` // 是否发货完成(0:否,1:是) + IsComplated *int64 `gorm:"" json:"is_complated"` // 是否完成订单(0:否,1:是) + IsCancel *int64 `gorm:"" json:"is_cancel"` // 是否取消订单(0:否,1:是) + IsRefunding *int64 `gorm:"" json:"is_refunding"` // 是否退款中(0:否,1:是) + IsRefunded *int64 `gorm:"" json:"is_refunded"` // 是否退款完成(0:否,1:是) + IsDeleted *int64 `gorm:"" json:"is_deleted"` // 是否删除(0:否,1:是) + 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} } diff --git a/model/gmodel_gen/fs_product_design_gen.go b/model/gmodel_gen/fs_product_design_gen.go new file mode 100644 index 00000000..f82b24a3 --- /dev/null +++ b/model/gmodel_gen/fs_product_design_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_product_gen.go b/model/gmodel_gen/fs_product_gen.go new file mode 100644 index 00000000..c46fa992 --- /dev/null +++ b/model/gmodel_gen/fs_product_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_product_model3d_gen.go b/model/gmodel_gen/fs_product_model3d_gen.go new file mode 100644 index 00000000..e9210d89 --- /dev/null +++ b/model/gmodel_gen/fs_product_model3d_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_product_model3d_light_gen.go b/model/gmodel_gen/fs_product_model3d_light_gen.go new file mode 100644 index 00000000..c28dbf15 --- /dev/null +++ b/model/gmodel_gen/fs_product_model3d_light_gen.go @@ -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} +} diff --git a/model/gmodel_gen/fs_product_price_gen.go b/model/gmodel_gen/fs_product_price_gen.go new file mode 100644 index 00000000..1fc4cfed --- /dev/null +++ b/model/gmodel_gen/fs_product_price_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_product_size_gen.go b/model/gmodel_gen/fs_product_size_gen.go new file mode 100644 index 00000000..550d6361 --- /dev/null +++ b/model/gmodel_gen/fs_product_size_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_product_template_tags_gen.go b/model/gmodel_gen/fs_product_template_tags_gen.go new file mode 100644 index 00000000..14e85b0d --- /dev/null +++ b/model/gmodel_gen/fs_product_template_tags_gen.go @@ -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} +} diff --git a/model/gmodel_gen/fs_product_template_v2_gen.go b/model/gmodel_gen/fs_product_template_v2_gen.go new file mode 100644 index 00000000..abc5cd02 --- /dev/null +++ b/model/gmodel_gen/fs_product_template_v2_gen.go @@ -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} +} diff --git a/model/gmodel_gen/fs_qrcode_set_gen.go b/model/gmodel_gen/fs_qrcode_set_gen.go new file mode 100644 index 00000000..fb39c209 --- /dev/null +++ b/model/gmodel_gen/fs_qrcode_set_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_standard_logo_gen.go b/model/gmodel_gen/fs_standard_logo_gen.go new file mode 100644 index 00000000..dce7d66a --- /dev/null +++ b/model/gmodel_gen/fs_standard_logo_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_tags_gen.go b/model/gmodel_gen/fs_tags_gen.go new file mode 100644 index 00000000..4c17fbe5 --- /dev/null +++ b/model/gmodel_gen/fs_tags_gen.go @@ -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} } diff --git a/model/gmodel_gen/fs_user_gen.go b/model/gmodel_gen/fs_user_gen.go new file mode 100644 index 00000000..d2671f22 --- /dev/null +++ b/model/gmodel_gen/fs_user_gen.go @@ -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} } diff --git a/server/home-user-auth/internal/handler/acceptcookiehandler.go b/server/home-user-auth/internal/handler/acceptcookiehandler.go new file mode 100644 index 00000000..c4b168eb --- /dev/null +++ b/server/home-user-auth/internal/handler/acceptcookiehandler.go @@ -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) + } + } +} diff --git a/server/home-user-auth/internal/handler/routes.go b/server/home-user-auth/internal/handler/routes.go index 3bc0f466..4a12513c 100644 --- a/server/home-user-auth/internal/handler/routes.go +++ b/server/home-user-auth/internal/handler/routes.go @@ -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), ) } diff --git a/server/home-user-auth/internal/handler/useraddresslisthandler.go b/server/home-user-auth/internal/handler/useraddresslisthandler.go index 5ecc5a96..271c3e24 100644 --- a/server/home-user-auth/internal/handler/useraddresslisthandler.go +++ b/server/home-user-auth/internal/handler/useraddresslisthandler.go @@ -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 { diff --git a/server/home-user-auth/internal/handler/userbasicinfohandler.go b/server/home-user-auth/internal/handler/userbasicinfohandler.go index 8a0245b8..b6aa5894 100644 --- a/server/home-user-auth/internal/handler/userbasicinfohandler.go +++ b/server/home-user-auth/internal/handler/userbasicinfohandler.go @@ -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 { diff --git a/server/home-user-auth/internal/handler/userfontshandler.go b/server/home-user-auth/internal/handler/userfontshandler.go index b7c1a6c2..e534f790 100644 --- a/server/home-user-auth/internal/handler/userfontshandler.go +++ b/server/home-user-auth/internal/handler/userfontshandler.go @@ -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 { diff --git a/server/home-user-auth/internal/handler/usergettypehandler.go b/server/home-user-auth/internal/handler/usergettypehandler.go index 21271e41..ccd49a20 100644 --- a/server/home-user-auth/internal/handler/usergettypehandler.go +++ b/server/home-user-auth/internal/handler/usergettypehandler.go @@ -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 { diff --git a/server/home-user-auth/internal/handler/usersavebasicinfohandler.go b/server/home-user-auth/internal/handler/usersavebasicinfohandler.go index a5894ff7..5e48dd1d 100644 --- a/server/home-user-auth/internal/handler/usersavebasicinfohandler.go +++ b/server/home-user-auth/internal/handler/usersavebasicinfohandler.go @@ -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 { diff --git a/server/home-user-auth/internal/handler/userstatusconfighandler.go b/server/home-user-auth/internal/handler/userstatusconfighandler.go index 942b53f1..bc0d5ee6 100644 --- a/server/home-user-auth/internal/handler/userstatusconfighandler.go +++ b/server/home-user-auth/internal/handler/userstatusconfighandler.go @@ -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 { diff --git a/server/home-user-auth/internal/logic/acceptcookielogic.go b/server/home-user-auth/internal/logic/acceptcookielogic.go new file mode 100644 index 00000000..4e493ea0 --- /dev/null +++ b/server/home-user-auth/internal/logic/acceptcookielogic.go @@ -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) +} diff --git a/server/home-user-auth/internal/logic/useraddresslistlogic.go b/server/home-user-auth/internal/logic/useraddresslistlogic.go index 51901f3d..c6681b0b 100644 --- a/server/home-user-auth/internal/logic/useraddresslistlogic.go +++ b/server/home-user-auth/internal/logic/useraddresslistlogic.go @@ -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) diff --git a/server/home-user-auth/internal/logic/userloginlogic.go b/server/home-user-auth/internal/logic/userloginlogic.go index 91dd916b..f877197d 100644 --- a/server/home-user-auth/internal/logic/userloginlogic.go +++ b/server/home-user-auth/internal/logic/userloginlogic.go @@ -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 { diff --git a/server/home-user-auth/internal/svc/servicecontext.go b/server/home-user-auth/internal/svc/servicecontext.go index 8c26ba0b..2d97fe86 100644 --- a/server/home-user-auth/internal/svc/servicecontext.go +++ b/server/home-user-auth/internal/svc/servicecontext.go @@ -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) { diff --git a/server_api/home-user-auth.api b/server_api/home-user-auth.api index b038ef9b..5f4a425c 100644 --- a/server_api/home-user-auth.api +++ b/server_api/home-user-auth.api @@ -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 { diff --git a/utils/auth/user.go b/utils/auth/user.go index 63c08bef..ef04cd9f 100644 --- a/utils/auth/user.go +++ b/utils/auth/user.go @@ -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 { diff --git a/utils/auth/user_test.go b/utils/auth/user_test.go new file mode 100644 index 00000000..be61e5d9 --- /dev/null +++ b/utils/auth/user_test.go @@ -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) +} diff --git a/utils/basic/basic.go b/utils/basic/basic.go index e9197a77..1818b78c 100644 --- a/utils/basic/basic.go +++ b/utils/basic/basic.go @@ -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 {