From 8c3ce4e89634bcd35faf0c8649db0d6b37580c8c Mon Sep 17 00:00:00 2001 From: eson <9673575+githubcontent@user.noreply.gitee.com> Date: Thu, 8 Jun 2023 15:41:49 +0800 Subject: [PATCH] =?UTF-8?q?finish=20address-list=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +- ddl/fs_address.sql | 20 ++++ model/fsaddressmodel.go | 67 +++++++++++++ model/fsaddressmodel_gen.go | 96 +++++++++++++++++++ server/home-user-auth/home-user-auth_test.go | 13 ++- .../home-user-auth/internal/handler/routes.go | 7 +- .../handler/useraddresslisthandler.go | 37 +++++++ ...ettypehandler.go => usergettypehandler.go} | 6 +- .../internal/logic/useraddresslistlogic.go | 40 ++++++++ .../{gettypelogic.go => usergettypelogic.go} | 9 +- server/home-user-auth/internal/types/types.go | 15 +++ server_api/home-user-auth.api | 24 ++++- utils/sqlfs/builder.go | 49 ++++++++++ 13 files changed, 379 insertions(+), 12 deletions(-) create mode 100644 ddl/fs_address.sql create mode 100755 model/fsaddressmodel.go create mode 100755 model/fsaddressmodel_gen.go create mode 100644 server/home-user-auth/internal/handler/useraddresslisthandler.go rename server/home-user-auth/internal/handler/{gettypehandler.go => usergettypehandler.go} (82%) create mode 100644 server/home-user-auth/internal/logic/useraddresslistlogic.go rename server/home-user-auth/internal/logic/{gettypelogic.go => usergettypelogic.go} (61%) create mode 100644 utils/sqlfs/builder.go diff --git a/README.md b/README.md index 4ae582da..5c753ee1 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,14 @@ 1. sh fs_gen_api.sh home-user-auth # 序列化api 2. sh fs_gen_mysql_model.sh fs_canteen_type # 根据ddl序列化mysql model -3. xxxx +3. 生成后就是go-zero框架的实现. 主要在logic目录下实现代码. +4. Response.Data的结构体 在api文件下定义. 方便rpc以后的接入. 参考现有的例子 #### 规范 -model的自定义函数前缀使用self_的文件命名 eg: self_fsfont.go + +sql 的值只能用 ?, 传入. 不能自己拼接. 涉及到sql安全和防注入. +例子: QueryRow("SELECT * FROM userinfo WHERE username = ? AND password = ?", sename, partname).Scan(&uid, &username, &password) + #### 参与贡献 diff --git a/ddl/fs_address.sql b/ddl/fs_address.sql new file mode 100644 index 00000000..c99ab65c --- /dev/null +++ b/ddl/fs_address.sql @@ -0,0 +1,20 @@ +-- fusentest.fs_address definition + +CREATE TABLE `fs_address` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(10) unsigned NOT NULL COMMENT '用户ID', + `name` varchar(64) NOT NULL DEFAULT '' COMMENT '地址名称', + `first_name` varchar(64) NOT NULL COMMENT 'FirstName', + `last_name` varchar(64) NOT NULL COMMENT 'LastName', + `mobile` varchar(16) NOT NULL COMMENT '手机号码', + `street` varchar(128) NOT NULL COMMENT '街道', + `suite` varchar(128) NOT NULL COMMENT '房号', + `city` varchar(128) NOT NULL COMMENT '城市', + `state` varchar(128) NOT NULL COMMENT '州名', + `country` varchar(128) NOT NULL COMMENT '国家', + `zip_code` varchar(128) NOT NULL COMMENT '邮编', + `status` tinyint(1) NOT NULL COMMENT '1正常 0异常', + `is_default` tinyint(1) NOT NULL COMMENT '1默认地址,0非默认地址', + PRIMARY KEY (`id`) USING BTREE, + KEY `user_id` (`user_id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=129 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='用户地址表'; \ No newline at end of file diff --git a/model/fsaddressmodel.go b/model/fsaddressmodel.go new file mode 100755 index 00000000..de1075ec --- /dev/null +++ b/model/fsaddressmodel.go @@ -0,0 +1,67 @@ +package model + +import ( + "context" + "fmt" + "strings" + + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" +) + +var _ FsAddressModel = (*customFsAddressModel)(nil) + +type ( + // FsAddressModel is an interface to be customized, add more methods here, + // and implement the added methods in customFsAddressModel. + FsAddressModel interface { + fsAddressModel + FindDataAddressList(ctx context.Context, userid int64) (*DataAddressList, error) + } + + customFsAddressModel struct { + *defaultFsAddressModel + } + + DataAddressList struct { + Id int64 `db:"id"` + UserId int64 `db:"user_id"` // 用户ID + Name string `db:"name"` // 地址名称 + FirstName string `db:"first_name"` // FirstName + LastName string `db:"last_name"` // LastName + Mobile string `db:"mobile"` // 手机号码 + Street string `db:"street"` // 街道 + Suite string `db:"suite"` // 房号 + City string `db:"city"` // 城市 + State string `db:"state"` // 州名 + ZipCode string `db:"zip_code"` // 邮编 + IsDefault int64 `db:"is_default"` // 1默认地址,0非默认地址 + } +) + +var ( + // DataAddressList 结构需要的字段 + fsDataAddressListRows = strings.Join(stringx.Remove(fsAddressFieldNames, "`status`", "`country`"), ",") +) + +// NewFsAddressModel returns a model for the database table. +func NewFsAddressModel(conn sqlx.SqlConn) FsAddressModel { + return &customFsAddressModel{ + defaultFsAddressModel: newFsAddressModel(conn), + } +} + +func (m *defaultFsAddressModel) FindDataAddressList(ctx context.Context, userid int64) (*DataAddressList, error) { + query := fmt.Sprintf("select %s from %s where `user_id` = ? ", fsDataAddressListRows, m.table) + var resp DataAddressList + err := m.conn.QueryRowCtx(ctx, &resp, query, userid) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} diff --git a/model/fsaddressmodel_gen.go b/model/fsaddressmodel_gen.go new file mode 100755 index 00000000..4830c9c2 --- /dev/null +++ b/model/fsaddressmodel_gen.go @@ -0,0 +1,96 @@ +// 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 ( + fsAddressFieldNames = builder.RawFieldNames(&FsAddress{}) + fsAddressRows = strings.Join(fsAddressFieldNames, ",") + fsAddressRowsExpectAutoSet = strings.Join(stringx.Remove(fsAddressFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), ",") + fsAddressRowsWithPlaceHolder = strings.Join(stringx.Remove(fsAddressFieldNames, "`id`", "`create_at`", "`create_time`", "`created_at`", "`update_at`", "`update_time`", "`updated_at`"), "=?,") + "=?" +) + +type ( + fsAddressModel interface { + Insert(ctx context.Context, data *FsAddress) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*FsAddress, error) + Update(ctx context.Context, data *FsAddress) error + Delete(ctx context.Context, id int64) error + } + + defaultFsAddressModel struct { + conn sqlx.SqlConn + table string + } + + FsAddress struct { + Id int64 `db:"id"` + UserId int64 `db:"user_id"` // 用户ID + Name string `db:"name"` // 地址名称 + FirstName string `db:"first_name"` // FirstName + LastName string `db:"last_name"` // LastName + Mobile string `db:"mobile"` // 手机号码 + Street string `db:"street"` // 街道 + Suite string `db:"suite"` // 房号 + City string `db:"city"` // 城市 + State string `db:"state"` // 州名 + Country string `db:"country"` // 国家 + ZipCode string `db:"zip_code"` // 邮编 + Status int64 `db:"status"` // 1正常 0异常 + IsDefault int64 `db:"is_default"` // 1默认地址,0非默认地址 + } +) + +func newFsAddressModel(conn sqlx.SqlConn) *defaultFsAddressModel { + return &defaultFsAddressModel{ + conn: conn, + table: "`fs_address`", + } +} + +func (m *defaultFsAddressModel) Delete(ctx context.Context, id int64) error { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + _, err := m.conn.ExecCtx(ctx, query, id) + return err +} + +func (m *defaultFsAddressModel) FindOne(ctx context.Context, id int64) (*FsAddress, error) { + query := fmt.Sprintf("select %s from %s where `id` = ? limit 1", fsAddressRows, m.table) + var resp FsAddress + err := m.conn.QueryRowCtx(ctx, &resp, query, id) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultFsAddressModel) Insert(ctx context.Context, data *FsAddress) (sql.Result, error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, fsAddressRowsExpectAutoSet) + ret, err := m.conn.ExecCtx(ctx, query, data.UserId, data.Name, data.FirstName, data.LastName, data.Mobile, data.Street, data.Suite, data.City, data.State, data.Country, data.ZipCode, data.Status, data.IsDefault) + return ret, err +} + +func (m *defaultFsAddressModel) Update(ctx context.Context, data *FsAddress) error { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, fsAddressRowsWithPlaceHolder) + _, err := m.conn.ExecCtx(ctx, query, data.UserId, data.Name, data.FirstName, data.LastName, data.Mobile, data.Street, data.Suite, data.City, data.State, data.Country, data.ZipCode, data.Status, data.IsDefault, data.Id) + return err +} + +func (m *defaultFsAddressModel) tableName() string { + return m.table +} diff --git a/server/home-user-auth/home-user-auth_test.go b/server/home-user-auth/home-user-auth_test.go index ef649768..8bf4353a 100644 --- a/server/home-user-auth/home-user-auth_test.go +++ b/server/home-user-auth/home-user-auth_test.go @@ -1,7 +1,18 @@ package main -import "testing" +import ( + "testing" +) + +type FsCanteenType struct { + Id int64 `db:"id"` // ID + Name string `db:"name"` // 餐厅名字 + Sort int64 `db:"sort"` // 排序 + Status int64 `db:"status"` // 状态位 1启用0停用 + Ctime int64 `db:"ctime"` // 添加时间 +} func TestMain(t *testing.T) { + // log.Println(model.RawFieldNames[FsCanteenType]()) main() } diff --git a/server/home-user-auth/internal/handler/routes.go b/server/home-user-auth/internal/handler/routes.go index 342f559a..9eef872f 100644 --- a/server/home-user-auth/internal/handler/routes.go +++ b/server/home-user-auth/internal/handler/routes.go @@ -22,10 +22,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/user/fonts", Handler: UserFontsHandler(serverCtx), }, + { + Method: http.MethodGet, + Path: "/user/address-list", + Handler: UserAddressListHandler(serverCtx), + }, { Method: http.MethodGet, Path: "/user/get-type", - Handler: GetTypeHandler(serverCtx), + Handler: UserGetTypeHandler(serverCtx), }, { Method: http.MethodPost, diff --git a/server/home-user-auth/internal/handler/useraddresslisthandler.go b/server/home-user-auth/internal/handler/useraddresslisthandler.go new file mode 100644 index 00000000..c34909ba --- /dev/null +++ b/server/home-user-auth/internal/handler/useraddresslisthandler.go @@ -0,0 +1,37 @@ +package handler + +import ( + "errors" + "net/http" + + "github.com/zeromicro/go-zero/core/logx" + "github.com/zeromicro/go-zero/rest/httpx" + + "fusenapi/server/home-user-auth/internal/logic" + "fusenapi/server/home-user-auth/internal/svc" + "fusenapi/server/home-user-auth/internal/types" +) + +func UserAddressListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.Request + if err := httpx.Parse(r, &req); err != nil { + httpx.OkJsonCtx(r.Context(), w, &types.Response{ + Code: 510, + Message: "parameter error", + }) + logx.Info(err) + return + } + + l := logic.NewUserAddressListLogic(r.Context(), svcCtx) + resp := l.UserAddressList(&req) + 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/gettypehandler.go b/server/home-user-auth/internal/handler/usergettypehandler.go similarity index 82% rename from server/home-user-auth/internal/handler/gettypehandler.go rename to server/home-user-auth/internal/handler/usergettypehandler.go index a7a70ba8..cd759425 100644 --- a/server/home-user-auth/internal/handler/gettypehandler.go +++ b/server/home-user-auth/internal/handler/usergettypehandler.go @@ -12,7 +12,7 @@ import ( "fusenapi/server/home-user-auth/internal/types" ) -func GetTypeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { +func UserGetTypeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.Request if err := httpx.Parse(r, &req); err != nil { @@ -24,8 +24,8 @@ func GetTypeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return } - l := logic.NewGetTypeLogic(r.Context(), svcCtx) - resp := l.GetType(&req) + l := logic.NewUserGetTypeLogic(r.Context(), svcCtx) + resp := l.UserGetType(&req) if resp != nil { httpx.OkJsonCtx(r.Context(), w, resp) } else { diff --git a/server/home-user-auth/internal/logic/useraddresslistlogic.go b/server/home-user-auth/internal/logic/useraddresslistlogic.go new file mode 100644 index 00000000..e3aeec90 --- /dev/null +++ b/server/home-user-auth/internal/logic/useraddresslistlogic.go @@ -0,0 +1,40 @@ +package logic + +import ( + "context" + + "fusenapi/model" + "fusenapi/server/home-user-auth/internal/svc" + "fusenapi/server/home-user-auth/internal/types" + "fusenapi/utils/auth" + "fusenapi/utils/basic" + + "github.com/zeromicro/go-zero/core/logx" +) + +type UserAddressListLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewUserAddressListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserAddressListLogic { + return &UserAddressListLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *UserAddressListLogic) UserAddressList(req *types.Request) (resp *types.Response) { + // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) + m := model.NewFsAddressModel(l.svcCtx.MysqlConn) + user := auth.GetUserInfoFormCtx(l.ctx) + // model里设置了 返回值. 和 types 里的一至可以直接返回 + data, err := m.FindDataAddressList(l.ctx, user.UserId) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeServiceErr, err.Error()) + } + return resp.SetStatus(basic.CodeOK, data) +} diff --git a/server/home-user-auth/internal/logic/gettypelogic.go b/server/home-user-auth/internal/logic/usergettypelogic.go similarity index 61% rename from server/home-user-auth/internal/logic/gettypelogic.go rename to server/home-user-auth/internal/logic/usergettypelogic.go index ac24d600..855db1fd 100644 --- a/server/home-user-auth/internal/logic/gettypelogic.go +++ b/server/home-user-auth/internal/logic/usergettypelogic.go @@ -11,21 +11,22 @@ import ( "github.com/zeromicro/go-zero/core/logx" ) -type GetTypeLogic struct { +type UserGetTypeLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } -func NewGetTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetTypeLogic { - return &GetTypeLogic{ +func NewUserGetTypeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserGetTypeLogic { + return &UserGetTypeLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } -func (l *GetTypeLogic) GetType(req *types.Request) (resp *types.Response) { +func (l *UserGetTypeLogic) UserGetType(req *types.Request) (resp *types.Response) { + // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) data, err := model.NewFsCanteenTypeModel(l.svcCtx.MysqlConn).FindGetType(l.ctx) if err != nil { logx.Error(err) diff --git a/server/home-user-auth/internal/types/types.go b/server/home-user-auth/internal/types/types.go index a9c04c9b..c5e97122 100644 --- a/server/home-user-auth/internal/types/types.go +++ b/server/home-user-auth/internal/types/types.go @@ -91,6 +91,21 @@ type DataStatusConfig struct { LogisticsStatus []KeyNameButton `json:"logistics_status"` //物流状态筛选项 } +type DataAddressList struct { + Id int64 `db:"id"` + UserId int64 `db:"user_id"` // 用户ID + Name string `db:"name"` // 地址名称 + FirstName string `db:"first_name"` // FirstName + LastName string `db:"last_name"` // LastName + Mobile string `db:"mobile"` // 手机号码 + Street string `db:"street"` // 街道 + Suite string `db:"suite"` // 房号 + City string `db:"city"` // 城市 + State string `db:"state"` // 州名 + ZipCode string `db:"zip_code"` // 邮编 + IsDefault int64 `db:"is_default"` // 1默认地址,0非默认地址 +} + type Response struct { Code int `json:"code"` Message string `json:"msg"` diff --git a/server_api/home-user-auth.api b/server_api/home-user-auth.api index 8223a1a9..5a07b6ee 100644 --- a/server_api/home-user-auth.api +++ b/server_api/home-user-auth.api @@ -21,7 +21,10 @@ service home-user-auth { @handler UserFontsHandler get /user/fonts(request) returns (response); - @handler GetTypeHandler + @handler UserAddressListHandler + get /user/address-list(request) returns (response); + + @handler UserGetTypeHandler get /user/get-type(request) returns (response); @handler UserSaveBasicInfoHandler @@ -29,6 +32,7 @@ service home-user-auth { @handler UserStatusConfigHandler post /user/status-config(request) returns (response); + } @server( @@ -128,4 +132,22 @@ type DataStatusConfig { Time []KeyName `json:"time"` //返回订单时间筛选项 RefundReason []KeyName `json:"refund_reason"` //退款原因说明项 LogisticsStatus []KeyNameButton `json:"logistics_status"` //物流状态筛选项 +} + +// DataAddressList /user/address-list 返回值 +type DataAddressList { + Id int64 `db:"id"` + UserId int64 `db:"user_id"` // 用户ID + Name string `db:"name"` // 地址名称 + FirstName string `db:"first_name"` // FirstName + LastName string `db:"last_name"` // LastName + Mobile string `db:"mobile"` // 手机号码 + Street string `db:"street"` // 街道 + Suite string `db:"suite"` // 房号 + City string `db:"city"` // 城市 + State string `db:"state"` // 州名 + // Country string `db:"country"` // 国家 + ZipCode string `db:"zip_code"` // 邮编 + // Status int64 `db:"status"` // 1正常 0异常 + IsDefault int64 `db:"is_default"` // 1默认地址,0非默认地址 } \ No newline at end of file diff --git a/utils/sqlfs/builder.go b/utils/sqlfs/builder.go new file mode 100644 index 00000000..f6117bb7 --- /dev/null +++ b/utils/sqlfs/builder.go @@ -0,0 +1,49 @@ +package sqlfs + +import ( + "reflect" + "strings" +) + +var dbTag = "db" + +// RawFieldNames converts golang struct field into slice string. +func RawFieldNames[T any]() []string { + + var out []string + + var a T + v := reflect.ValueOf(a) + typ := v.Type() + + for i := 0; i < v.NumField(); i++ { + // gets us a StructField + fi := typ.Field(i) + tagv := fi.Tag.Get(dbTag) + switch tagv { + case "-": + continue + default: + // get tag name with the tag opton, e.g.: + // `db:"id"` + // `db:"id,type=char,length=16"` + // `db:",type=char,length=16"` + // `db:"-,type=char,length=16"` + if strings.Contains(tagv, ",") { + tagv = strings.TrimSpace(strings.Split(tagv, ",")[0]) + } + + if tagv == "-" { + continue + } + + if len(tagv) == 0 { + tagv = fi.Name + } + + out = append(out, tagv) + } + } + + return out +}