diff --git a/README.md b/README.md index 921e412..29a1723 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ + ## 感谢(排名不分先后) > gf框架 [https://github.com/gogf/gf](https://github.com/gogf/gf) > @@ -118,15 +119,9 @@ > gopay [https://github.com/go-pay/gopay](https://github.com/go-pay/gopay) - ## 交流QQ群 交流群①:190966648 HotGo框架交流1群 -> - - -> 感谢你使用HotGo,公司团队精力时间有限,因此我们不再提供免费的技术服务! -> -> 同时您也可以联系我们,雇佣我们团队为您干活,谢谢合作! +> ## 商用说明 diff --git a/docs/guide-zh-CN/sys-catalog.md b/docs/guide-zh-CN/sys-catalog.md index f2cd356..7a0cd44 100644 --- a/docs/guide-zh-CN/sys-catalog.md +++ b/docs/guide-zh-CN/sys-catalog.md @@ -67,8 +67,8 @@ | --- xxx插件 | 插件模块名称 | | --- --- api | 对外接口。提供服务的输入/输出数据结构定义 | | --- --- --- admin | 后台接口 | -| --- --- --- api | 前台通用接口,包含PC页面、uinapp接口等 | -| --- --- --- home | 前台PC端页面 | +| --- --- --- api | 前台通用接口,包含PC端、移动端接口等 | +| --- --- --- home | 前台PC端、H5端页面 | | --- --- --- websocket | 可同时为多应用提供websocket接口 | | --- --- controller | 接收/解析用户输入参数的入口/接口层,也可以理解为控制器 | | --- --- crons | 项目中由系统统一接管的定时任务处理 | @@ -83,8 +83,8 @@ | --- main.go | 插件始化文件和模块插拔接口 | | **api** | 对外接口。提供服务的输入/输出数据结构定义 | | --- admin | 后台接口 | -| --- api | 前台通用接口,包含PC页面、uinapp接口等 | -| --- home | 前台PC端页面 | +| --- api | 前台通用接口,包含PC端、移动端接口等 | +| --- home | 前台PC端、H5端页面 | | --- websocket | 可同时为多应用提供websocket接口 | | **hack** | 存放项目开发工具、脚本等内容例如,CLI工具的配置,各种shell/bat脚本等文件 | | **internal** | 业务逻辑存放目录通过Golang internal特性对外部隐藏可见性 | diff --git a/server/addons/hgexample/logic/sys/table.go b/server/addons/hgexample/logic/sys/table.go index 5b126b3..6ffbc23 100644 --- a/server/addons/hgexample/logic/sys/table.go +++ b/server/addons/hgexample/logic/sys/table.go @@ -105,18 +105,7 @@ func (s *sSysTable) List(ctx context.Context, in sysin.TableListInp) (list []*sy return } - ////关联表select - //fields, err := hgorm.GenJoinSelect(ctx, sysin.TableListModel{}, dao.AddonHgexampleTable, []*hgorm.Join{ - // {Dao: dao.AddonHgexampleTableCategory, Alias: "testCategory"}, - // //{Dao: dao.AddonHgexampleTableCategory, Alias: "testCategory"}, - //}) - - fields, err := hgorm.GenSelect(ctx, sysin.TableListModel{}, dao.AddonHgexampleTable) - if err != nil { - return - } - - if err = mod.Fields(fields).Page(in.Page, in.PerPage).OrderAsc(dao.AddonHgexampleTable.Columns().Sort).OrderDesc(dao.AddonHgexampleTable.Columns().Id).Scan(&list); err != nil { + if err = mod.Fields(sysin.TableListModel{}).Page(in.Page, in.PerPage).OrderAsc(dao.AddonHgexampleTable.Columns().Sort).OrderDesc(dao.AddonHgexampleTable.Columns().Id).Scan(&list); err != nil { err = gerror.Wrap(err, consts.ErrorORM) return } @@ -154,7 +143,7 @@ func (s *sSysTable) Export(ctx context.Context, in sysin.TableListInp) (err erro // Edit 修改/新增 func (s *sSysTable) Edit(ctx context.Context, in sysin.TableEditInp) (err error) { - if err = hgorm.IsUnique(ctx, dao.AddonHgexampleTable, g.Map{dao.AddonHgexampleTable.Columns().Qq: in.Qq}, "QQ号码已存在,请换一个", in.Id); err != nil { + if err = hgorm.IsUnique(ctx, &dao.AddonHgexampleTable, g.Map{dao.AddonHgexampleTable.Columns().Qq: in.Qq}, "QQ号码已存在,请换一个", in.Id); err != nil { return } diff --git a/server/api/api/pay/notify.go b/server/api/api/pay/notify.go index 0997c5b..dd82e68 100644 --- a/server/api/api/pay/notify.go +++ b/server/api/api/pay/notify.go @@ -10,7 +10,10 @@ type NotifyAliPayReq struct { g.Meta `path:"/pay/notify/alipay" method:"post" tags:"支付异步通知" summary:"支付宝回调"` } -type NotifyAliPayRes payin.PayNotifyModel +type NotifyAliPayRes struct { + g.Meta `mime:"text/html" type:"string" example:""` + payin.PayNotifyModel +} // NotifyWxPayReq 微信支付回调 type NotifyWxPayReq struct { @@ -24,4 +27,7 @@ type NotifyQQPayReq struct { g.Meta `path:"/pay/notify/qqpay" method:"post" tags:"支付异步通知" summary:"QQ支付回调"` } -type NotifyQQPayRes payin.PayNotifyModel +type NotifyQQPayRes struct { + g.Meta `mime:"text/xml" type:"string" example:""` + payin.PayNotifyModel +} diff --git a/server/api/api/user/hello.go b/server/api/api/user/hello.go index 5645fd1..40a4708 100644 --- a/server/api/api/user/hello.go +++ b/server/api/api/user/hello.go @@ -11,8 +11,9 @@ import ( type HelloReq struct { g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"` + Name string `json:"name" d:"hotgo" dc:"名字"` } type HelloRes struct { - g.Meta `mime:"text/html" example:"string"` + Tips string `json:"tips"` } diff --git a/server/internal/consts/http.go b/server/internal/consts/http.go new file mode 100644 index 0000000..212aa25 --- /dev/null +++ b/server/internal/consts/http.go @@ -0,0 +1,8 @@ +package consts + +const ( + HTTPContentTypeXml = "text/xml" + HTTPContentTypeHtml = "text/html" + HTTPContentTypeStream = "text/event-stream" + HTTPContentTypeJson = "application/json" +) diff --git a/server/internal/controller/api/pay/notify.go b/server/internal/controller/api/pay/notify.go index 5205ccc..c9ccf1e 100644 --- a/server/internal/controller/api/pay/notify.go +++ b/server/internal/controller/api/pay/notify.go @@ -7,8 +7,10 @@ package pay import ( "context" + "github.com/gogf/gf/v2/frame/g" "hotgo/api/api/pay" "hotgo/internal/consts" + "hotgo/internal/library/response" "hotgo/internal/model/input/payin" "hotgo/internal/service" ) @@ -21,32 +23,35 @@ type cNotify struct{} // AliPay 支付宝回调 func (c *cNotify) AliPay(ctx context.Context, _ *pay.NotifyAliPayReq) (res *pay.NotifyAliPayRes, err error) { - _, err = service.Pay().Notify(ctx, payin.PayNotifyInp{PayType: consts.PayTypeAliPay}) - if err != nil { + if _, err = service.Pay().Notify(ctx, payin.PayNotifyInp{PayType: consts.PayTypeAliPay}); err != nil { return nil, err } - res = &pay.NotifyAliPayRes{PayType: consts.PayTypeAliPay, Message: "success"} + + response.RText(g.RequestFromCtx(ctx), "success") return } // WxPay 微信支付回调 func (c *cNotify) WxPay(ctx context.Context, _ *pay.NotifyWxPayReq) (res *pay.NotifyWxPayRes, err error) { - _, err = service.Pay().Notify(ctx, payin.PayNotifyInp{PayType: consts.PayTypeWxPay}) - if err != nil { - return nil, err + if _, err = service.Pay().Notify(ctx, payin.PayNotifyInp{PayType: consts.PayTypeWxPay}); err != nil { + return } - res = &pay.NotifyWxPayRes{PayType: consts.PayTypeWxPay, Code: "SUCCESS", Message: "收单成功"} + response.CustomJson(g.RequestFromCtx(ctx), `{"code": "SUCCESS","message": "收单成功"}`) return } // QQPay QQ支付回调 func (c *cNotify) QQPay(ctx context.Context, _ *pay.NotifyQQPayReq) (res *pay.NotifyQQPayRes, err error) { - _, err = service.Pay().Notify(ctx, payin.PayNotifyInp{PayType: consts.PayTypeQQPay}) - if err != nil { - return nil, err + if _, err = service.Pay().Notify(ctx, payin.PayNotifyInp{PayType: consts.PayTypeQQPay}); err != nil { + return } - res = &pay.NotifyQQPayRes{PayType: consts.PayTypeQQPay, Message: "SUCCESS"} + r := g.RequestFromCtx(ctx) + r.Response.ClearBuffer() + r.Response.Write(``) + r.Response.WriteXml(g.Map{ + "return_code": "SUCCESS", + }) return } diff --git a/server/internal/controller/api/user/hello.go b/server/internal/controller/api/user/hello.go index 8ce539d..015f753 100644 --- a/server/internal/controller/api/user/hello.go +++ b/server/internal/controller/api/user/hello.go @@ -7,8 +7,9 @@ package user import ( "context" - "github.com/gogf/gf/v2/frame/g" + "fmt" "hotgo/api/api/user" + "hotgo/utility/simple" ) var ( @@ -17,7 +18,9 @@ var ( type cHello struct{} -func (c *cHello) Hello(ctx context.Context, _ *user.HelloReq) (res *user.HelloRes, err error) { - g.RequestFromCtx(ctx).Response.Writeln("Hello World api member!") +func (c *cHello) Hello(ctx context.Context, req *user.HelloReq) (res *user.HelloRes, err error) { + res = &user.HelloRes{ + Tips: fmt.Sprintf("hello %v, this is the api for %v applications.", req.Name, simple.AppName(ctx)), + } return } diff --git a/server/internal/library/cache/file/file.go b/server/internal/library/cache/file/file.go index 6127c07..4c88d7f 100644 --- a/server/internal/library/cache/file/file.go +++ b/server/internal/library/cache/file/file.go @@ -71,15 +71,37 @@ func (c *AdapterFile) Get(ctx context.Context, key interface{}) (*gvar.Var, erro } func (c *AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) { - return nil, gerror.New("implement me") + result, err = c.Get(ctx, key) + if err != nil { + return nil, err + } + if result.IsNil() { + return gvar.New(value), c.Set(ctx, key, value, duration) + } + return } func (c *AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) { - return nil, gerror.New("implement me") + v, err := c.Get(ctx, key) + if err != nil { + return nil, err + } + if v.IsNil() { + value, err := f(ctx) + if err != nil { + return nil, err + } + if value == nil { + return nil, nil + } + return gvar.New(value), c.Set(ctx, key, value, duration) + } else { + return v, nil + } } func (c *AdapterFile) GetOrSetFuncLock(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) { - return nil, gerror.New("implement me") + return c.GetOrSetFunc(ctx, key, f, duration) } func (c *AdapterFile) Contains(ctx context.Context, key interface{}) (bool, error) { diff --git a/server/internal/library/hggen/views/curd_generate_logic.go b/server/internal/library/hggen/views/curd_generate_logic.go index 359dbc6..2ba3b23 100644 --- a/server/internal/library/hggen/views/curd_generate_logic.go +++ b/server/internal/library/hggen/views/curd_generate_logic.go @@ -19,11 +19,11 @@ const ( LogicWhereComments = "\n\t// 查询%s\n" LogicWhereNoSupport = "\t// TODO 暂不支持生成[ %s ]查询方式,请自行补充此处代码!" LogicListSimpleSelect = "\tfields, err := hgorm.GenSelect(ctx, sysin.%sListModel{}, dao.%s)\n\tif err != nil {\n\t\treturn\n\t}" - LogicListJoinSelect = "\t//关联表select\n\tfields, err := hgorm.GenJoinSelect(ctx, %sin.%sListModel{}, dao.%s, []*hgorm.Join{\n%v\t})\n\n\tif err != nil {\n\t\terr = gerror.Wrap(err, \"获取%s关联字段失败,请稍后重试!\")\n\t\treturn\n\t}" + LogicListJoinSelect = "\t//关联表select\n\tfields, err := hgorm.GenJoinSelect(ctx, %sin.%sListModel{}, &dao.%s, []*hgorm.Join{\n%v\t})\n\n\tif err != nil {\n\t\terr = gerror.Wrap(err, \"获取%s关联字段失败,请稍后重试!\")\n\t\treturn\n\t}" LogicListJoinOnRelation = "\t// 关联表%s\n\tmod = mod.%s(hgorm.GenJoinOnRelation(\n\t\tdao.%s.Table(), dao.%s.Columns().%s, // 主表表名,关联字段\n\t\tdao.%s.Table(), \"%s\", dao.%s.Columns().%s, // 关联表表名,别名,关联字段\n\t)...)\n\n" LogicEditUpdate = "\tif _, err = s.Model(ctx%s).\n\t\t\tFields(%sin.%sUpdateFields{}).\n\t\t\tWherePri(in.%s).Data(in).Update(); err != nil {\n\t\t\terr = gerror.Wrap(err, \"修改%s失败,请稍后重试!\")\n\t\t}\n\t\treturn" LogicEditInsert = "\tif _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).\n\t\tFields(%sin.%sInsertFields{}).\n\t\tData(in).Insert(); err != nil {\n\t\terr = gerror.Wrap(err, \"新增%s失败,请稍后重试!\")\n\t}" - LogicEditUnique = "\t// 验证'%s'唯一\n\tif err = hgorm.IsUnique(ctx, dao.%s, g.Map{dao.%s.Columns().%s: in.%s}, \"%s已存在\", in.Id); err != nil {\n\t\treturn\n\t}\n" + LogicEditUnique = "\t// 验证'%s'唯一\n\tif err = hgorm.IsUnique(ctx, &dao.%s, g.Map{dao.%s.Columns().%s: in.%s}, \"%s已存在\", in.Id); err != nil {\n\t\treturn\n\t}\n" LogicSwitchUpdate = "g.Map{\n\t\tin.Key: in.Value,\n%s}" LogicStatusUpdate = "g.Map{\n\t\tdao.%s.Columns().Status: in.Status,\n%s}" ) @@ -133,7 +133,7 @@ func (l *gCurd) generateLogicListJoin(ctx context.Context, in *CurdPreviewInput) for _, join := range in.options.Join { if isEffectiveJoin(join) { - joinSelectRows = joinSelectRows + fmt.Sprintf("\t\t{Dao: dao.%s, Alias: \"%s\"},\n", join.DaoName, join.Alias) + joinSelectRows = joinSelectRows + fmt.Sprintf("\t\t{Dao: &dao.%s, Alias: \"%s\"},\n", join.DaoName, join.Alias) linkBuffer.WriteString(fmt.Sprintf(LogicListJoinOnRelation, join.Alias, consts.GenCodesJoinLinkMap[join.LinkMode], in.In.DaoName, in.In.DaoName, gstr.CaseCamel(join.MasterField), join.DaoName, join.Alias, join.DaoName, gstr.CaseCamel(join.Field))) } } @@ -143,11 +143,9 @@ func (l *gCurd) generateLogicListJoin(ctx context.Context, in *CurdPreviewInput) data["select"] = selectBuffer.String() data["fields"] = "fields" data["link"] = linkBuffer.String() - } else { data["fields"] = fmt.Sprintf("%sin.%sListModel{}", in.options.TemplateGroup, in.In.VarName) } - return data } @@ -165,7 +163,6 @@ func (l *gCurd) generateLogicListWhere(ctx context.Context, in *CurdPreviewInput } } } - return buffer.String() } diff --git a/server/internal/library/hgorm/dao.go b/server/internal/library/hgorm/dao.go index f1bce57..300f3c9 100644 --- a/server/internal/library/hgorm/dao.go +++ b/server/internal/library/hgorm/dao.go @@ -8,7 +8,6 @@ package hgorm // dao. import ( "context" - "errors" "fmt" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" @@ -25,56 +24,41 @@ type daoInstance interface { // Join 关联表属性 type Join struct { - Dao interface{} // 关联表dao实例 + Dao daoInstance // 关联表dao实例 Alias string // 别名 fields map[string]*gdb.TableField // 表字段列表 } // GenJoinOnRelation 生成关联表关联条件 func GenJoinOnRelation(masterTable, masterField, joinTable, alias, onField string) []string { - return []string{ - joinTable, - alias, - fmt.Sprintf("`%s`.`%s` = `%s`.`%s`", alias, onField, masterTable, masterField), - } + relation := fmt.Sprintf("`%s`.`%s` = `%s`.`%s`", alias, onField, masterTable, masterField) + return []string{joinTable, alias, relation} } // GenJoinSelect 生成关联表select // 这里会将实体中的字段驼峰转为下划线于数据库进行匹配,意味着数据库字段必须全部是小写字母+下划线的格式 -func GenJoinSelect(ctx context.Context, entity interface{}, masterDao interface{}, joins []*Join) (allFields string, err error) { +func GenJoinSelect(ctx context.Context, entity interface{}, dao daoInstance, joins []*Join) (allFields string, err error) { var tmpFields []string - - md, ok := masterDao.(daoInstance) - if !ok { - err = errors.New("masterDao unimplemented interface format.daoInstance") - return - } - if len(joins) == 0 { - err = errors.New("JoinFields joins len = 0") + err = gerror.New("JoinFields joins len = 0") return } for _, v := range joins { - jd, ok := v.Dao.(daoInstance) - if !ok { - err = errors.New("joins index unimplemented interface format.daoInstance") - return - } - v.fields, err = jd.Ctx(ctx).TableFields(jd.Table()) + v.fields, err = v.Dao.Ctx(ctx).TableFields(v.Dao.Table()) if err != nil { return } } - masterFields, err := md.Ctx(ctx).TableFields(md.Table()) + masterFields, err := dao.Ctx(ctx).TableFields(dao.Table()) if err != nil { return } entityFields, err := convert.GetEntityFieldTags(entity) if err != nil { - return "", err + return } if len(entityFields) == 0 { @@ -104,42 +88,7 @@ func GenJoinSelect(ctx context.Context, entity interface{}, masterDao interface{ // 主表 originalField := gstr.CaseSnakeFirstUpper(field) if _, ok := masterFields[originalField]; ok { - tmpFields = append(tmpFields, fmt.Sprintf("`%s`.`%s`", md.Table(), originalField)) - continue - } - } - return gstr.Implode(",", convert.UniqueSlice(tmpFields)), nil -} - -// GenSelect 生成select -// 这里会将实体中的字段驼峰转为下划线于数据库进行匹配,意味着数据库字段必须全部是小写字母+下划线的格式 -func GenSelect(ctx context.Context, entity interface{}, dao interface{}) (allFields string, err error) { - var tmpFields []string - - md, ok := dao.(daoInstance) - if !ok { - err = errors.New("dao unimplemented interface format.daoInstance") - return - } - - fields, err := md.Ctx(ctx).TableFields(md.Table()) - if err != nil { - return - } - - entityFields, err := convert.GetEntityFieldTags(entity) - if err != nil { - return "", err - } - - if len(entityFields) == 0 { - return "*", nil - } - - for _, field := range entityFields { - originalField := gstr.CaseSnakeFirstUpper(field) - if _, ok := fields[originalField]; ok { - tmpFields = append(tmpFields, fmt.Sprintf("`%s`", originalField)) + tmpFields = append(tmpFields, fmt.Sprintf("`%s`.`%s`", dao.Table(), originalField)) continue } } @@ -153,7 +102,7 @@ func GetPkField(ctx context.Context, dao daoInstance) (string, error) { return "", err } if len(fields) == 0 { - return "", errors.New("field not found") + return "", gerror.New("field not found") } for _, field := range fields { @@ -161,23 +110,18 @@ func GetPkField(ctx context.Context, dao daoInstance) (string, error) { return field.Name, nil } } - return "", errors.New("no primary key") + return "", gerror.New("no primary key") } // IsUnique 是否唯一 -func IsUnique(ctx context.Context, dao interface{}, where g.Map, message string, pkId ...interface{}) error { - d, ok := dao.(daoInstance) - if !ok { - return errors.New("IsUnique dao unimplemented interface format.daoInstance") - } - +func IsUnique(ctx context.Context, dao daoInstance, where g.Map, message string, pkId ...interface{}) error { if len(where) == 0 { - return errors.New("where condition cannot be empty") + return gerror.New("where condition cannot be empty") } - m := d.Ctx(ctx).Where(where) + m := dao.Ctx(ctx).Where(where) if len(pkId) > 0 { - field, err := GetPkField(ctx, d) + field, err := GetPkField(ctx, dao) if err != nil { return err } @@ -192,32 +136,28 @@ func IsUnique(ctx context.Context, dao interface{}, where g.Map, message string, if count > 0 { if message == "" { for k := range where { - message = fmt.Sprintf("in the table:%s, %v not uniqued", d.Table(), where[k]) + message = fmt.Sprintf("in the table:%s, %v not uniqued", dao.Table(), where[k]) break } } - return errors.New(message) + return gerror.New(message) } return nil } // GenSubTree 生成下级关系树 -func GenSubTree(ctx context.Context, dao interface{}, oldPid int64) (newPid int64, newLevel int, subTree string, err error) { +func GenSubTree(ctx context.Context, dao daoInstance, oldPid int64) (newPid int64, newLevel int, subTree string, err error) { // 顶级树 if oldPid <= 0 { return 0, 1, "", nil } - d, ok := dao.(daoInstance) - if !ok { - return 0, 0, "", errors.New("GenTree dao unimplemented interface format.daoInstance") - } - field, err := GetPkField(ctx, d) + field, err := GetPkField(ctx, dao) if err != nil { return 0, 0, "", err } - models, err := d.Ctx(ctx).Where(field, oldPid).One() + models, err := dao.Ctx(ctx).Where(field, oldPid).One() if err != nil { return 0, 0, "", err } diff --git a/server/internal/library/response/response.go b/server/internal/library/response/response.go index 3651176..1071c21 100644 --- a/server/internal/library/response/response.go +++ b/server/internal/library/response/response.go @@ -9,6 +9,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/os/gtime" "hotgo/internal/library/contexts" "hotgo/internal/model" "time" @@ -50,22 +51,23 @@ func RJson(r *ghttp.Request, code int, message string, data ...interface{}) { contexts.SetResponse(r.Context(), res) } -// SusJson 返回成功JSON -func SusJson(isExit bool, r *ghttp.Request, message string, data ...interface{}) { - if isExit { - JsonExit(r, gcode.CodeOK.Code(), message, data...) - return - } - RJson(r, gcode.CodeOK.Code(), message, data...) -} +// CustomJson 自定义JSON +func CustomJson(r *ghttp.Request, content interface{}) { + // 清空响应 + r.Response.ClearBuffer() -// FailJson 返回失败JSON -func FailJson(isExit bool, r *ghttp.Request, message string, data ...interface{}) { - if isExit { - JsonExit(r, gcode.CodeNil.Code(), message, data...) - return - } - RJson(r, gcode.CodeNil.Code(), message, data...) + // 写入响应 + r.Response.WriteJson(content) + + // 加入到上下文 + contexts.SetResponse(r.Context(), &model.Response{ + Code: 0, + Message: "", + Data: content, + Error: nil, + Timestamp: gtime.Timestamp(), + TraceID: gctx.CtxId(r.Context()), + }) } // Redirect 重定向 @@ -73,11 +75,6 @@ func Redirect(r *ghttp.Request, location string, code ...int) { r.Response.RedirectTo(location, code...) } -// Download 下载文件 -func Download(r *ghttp.Request, location string, code ...int) { - r.Response.ServeFileDownload("test.txt") -} - // RText 返回成功文本 func RText(r *ghttp.Request, message string) { // 清空响应 diff --git a/server/internal/logic/admin/credits_log.go b/server/internal/logic/admin/credits_log.go index be6dd67..1cfe169 100644 --- a/server/internal/logic/admin/credits_log.go +++ b/server/internal/logic/admin/credits_log.go @@ -13,7 +13,6 @@ import ( "github.com/gogf/gf/v2/errors/gerror" "hotgo/internal/consts" "hotgo/internal/dao" - "hotgo/internal/library/hgorm" "hotgo/internal/library/hgorm/handler" "hotgo/internal/model/entity" "hotgo/internal/model/input/adminin" @@ -218,12 +217,7 @@ func (s *sAdminCreditsLog) List(ctx context.Context, in adminin.CreditsLogListIn return } - fields, err := hgorm.GenSelect(ctx, adminin.CreditsLogListModel{}, dao.AdminCreditsLog) - if err != nil { - return - } - - err = mod.Fields(fields).Page(in.Page, in.PerPage).OrderDesc(dao.AdminCreditsLog.Columns().Id).Scan(&list) + err = mod.Fields(adminin.CreditsLogListModel{}).Page(in.Page, in.PerPage).OrderDesc(dao.AdminCreditsLog.Columns().Id).Scan(&list) return } diff --git a/server/internal/logic/admin/dept.go b/server/internal/logic/admin/dept.go index a663212..0c78f3d 100644 --- a/server/internal/logic/admin/dept.go +++ b/server/internal/logic/admin/dept.go @@ -58,11 +58,11 @@ func (s *sAdminDept) Delete(ctx context.Context, in adminin.DeptDeleteInp) (err // Edit 修改/新增 func (s *sAdminDept) Edit(ctx context.Context, in adminin.DeptEditInp) (err error) { - if err = hgorm.IsUnique(ctx, dao.AdminDept, g.Map{dao.AdminDept.Columns().Name: in.Name}, "名称已存在", in.Id); err != nil { + if err = hgorm.IsUnique(ctx, &dao.AdminDept, g.Map{dao.AdminDept.Columns().Name: in.Name}, "名称已存在", in.Id); err != nil { return } - if in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, dao.AdminDept, in.Pid); err != nil { + if in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, &dao.AdminDept, in.Pid); err != nil { return } diff --git a/server/internal/logic/admin/member.go b/server/internal/logic/admin/member.go index a18c346..ca403ef 100644 --- a/server/internal/logic/admin/member.go +++ b/server/internal/logic/admin/member.go @@ -380,7 +380,7 @@ func (s *sAdminMember) VerifyUnique(ctx context.Context, in adminin.VerifyUnique err = gerror.Newf("字段 [ %v ] 未配置唯一属性验证", k) return } - if err = hgorm.IsUnique(ctx, dao.AdminMember, g.Map{k: v}, message, in.Id); err != nil { + if err = hgorm.IsUnique(ctx, &dao.AdminMember, g.Map{k: v}, message, in.Id); err != nil { return } } @@ -599,7 +599,6 @@ func (s *sAdminMember) List(ctx context.Context, in adminin.MemberListInp) (list list[i].PostIds = append(list[i].PostIds, v.Int64()) } } - return } diff --git a/server/internal/logic/admin/order.go b/server/internal/logic/admin/order.go index 5b5262d..cfb95dd 100644 --- a/server/internal/logic/admin/order.go +++ b/server/internal/logic/admin/order.go @@ -294,8 +294,8 @@ func (s *sAdminOrder) List(ctx context.Context, in adminin.OrderListInp) (list [ } //关联表select - fields, err := hgorm.GenJoinSelect(ctx, adminin.OrderListModel{}, dao.AdminOrder, []*hgorm.Join{ - {Dao: dao.PayLog, Alias: "payLog"}, + fields, err := hgorm.GenJoinSelect(ctx, adminin.OrderListModel{}, &dao.AdminOrder, []*hgorm.Join{ + {Dao: &dao.PayLog, Alias: "payLog"}, }) if err != nil { diff --git a/server/internal/logic/admin/role.go b/server/internal/logic/admin/role.go index 5221eb3..ced6b5c 100644 --- a/server/internal/logic/admin/role.go +++ b/server/internal/logic/admin/role.go @@ -171,15 +171,15 @@ func (s *sAdminRole) UpdatePermissions(ctx context.Context, in adminin.UpdatePer } func (s *sAdminRole) Edit(ctx context.Context, in adminin.RoleEditInp) (err error) { - if err = hgorm.IsUnique(ctx, dao.AdminRole, g.Map{dao.AdminRole.Columns().Name: in.Name}, "名称已存在", in.Id); err != nil { + if err = hgorm.IsUnique(ctx, &dao.AdminRole, g.Map{dao.AdminRole.Columns().Name: in.Name}, "名称已存在", in.Id); err != nil { return } - if err = hgorm.IsUnique(ctx, dao.AdminRole, g.Map{dao.AdminRole.Columns().Key: in.Key}, "编码已存在", in.Id); err != nil { + if err = hgorm.IsUnique(ctx, &dao.AdminRole, g.Map{dao.AdminRole.Columns().Key: in.Key}, "编码已存在", in.Id); err != nil { return } - if in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, dao.AdminRole, in.Pid); err != nil { + if in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, &dao.AdminRole, in.Pid); err != nil { return } diff --git a/server/internal/logic/middleware/home_auth.go b/server/internal/logic/middleware/home_auth.go index 27e5dd4..66ea741 100644 --- a/server/internal/logic/middleware/home_auth.go +++ b/server/internal/logic/middleware/home_auth.go @@ -6,8 +6,6 @@ import ( // HomeAuth 前台页面鉴权中间件 func (s *sMiddleware) HomeAuth(r *ghttp.Request) { - r.Response.Header().Set("Content-Type", "text/html") - // 鉴权 // ... diff --git a/server/internal/logic/middleware/init.go b/server/internal/logic/middleware/init.go index 1c0f6a6..9f12804 100644 --- a/server/internal/logic/middleware/init.go +++ b/server/internal/logic/middleware/init.go @@ -30,9 +30,8 @@ import ( ) type sMiddleware struct { - LoginUrl string // 登录路由地址 - DemoWhiteList g.Map // 演示模式放行的路由白名单 - PayNotifyRoutes g.Map // 支付异步通知路由 + LoginUrl string // 登录路由地址 + DemoWhiteList g.Map // 演示模式放行的路由白名单 } func init() { @@ -47,11 +46,6 @@ func NewMiddleware() *sMiddleware { "/admin/site/mobileLogin": struct{}{}, // 手机号登录 "/admin/genCodes/preview": struct{}{}, // 预览代码 }, - PayNotifyRoutes: g.Map{ - "/api/pay/notify/alipay": struct{}{}, // 支付宝 - "/api/pay/notify/wxpay": struct{}{}, // 微信支付 - "/api/pay/notify/qqpay": struct{}{}, // QQ支付 - }, } } diff --git a/server/internal/logic/middleware/limit_develop.go b/server/internal/logic/middleware/limit_develop.go index faf69e8..5f0d48b 100644 --- a/server/internal/logic/middleware/limit_develop.go +++ b/server/internal/logic/middleware/limit_develop.go @@ -19,17 +19,17 @@ func (s *sMiddleware) Develop(r *ghttp.Request) { } if !gstr.InArray(ips, "*") { - cuIp := location.GetClientIp(r) + clientIp := location.GetClientIp(r) ok := false for _, ip := range ips { - if ip == cuIp { + if ip == clientIp { ok = true break } } if !ok { - response.JsonExit(r, gcode.CodeNotSupported.Code(), fmt.Sprintf("当前IP[%s]没有配置生成白名单!", cuIp)) + response.JsonExit(r, gcode.CodeNotSupported.Code(), fmt.Sprintf("当前IP[%s]没有配置生成白名单!", clientIp)) return } } diff --git a/server/internal/logic/middleware/response.go b/server/internal/logic/middleware/response.go index 298ecfa..3bf2a4b 100644 --- a/server/internal/logic/middleware/response.go +++ b/server/internal/logic/middleware/response.go @@ -6,44 +6,40 @@ package middleware import ( - "fmt" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" - "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/util/gmeta" "hotgo/internal/consts" "hotgo/internal/library/contexts" "hotgo/internal/library/response" - "hotgo/internal/model/input/payin" "hotgo/utility/charset" "hotgo/utility/simple" - "net/http" ) // ResponseHandler HTTP响应预处理 func (s *sMiddleware) ResponseHandler(r *ghttp.Request) { r.Middleware.Next() + contentType := getContentType(r) // 已存在响应 - if r.Response.BufferLength() > 0 && contexts.Get(r.Context()).Response != nil { + if contentType != consts.HTTPContentTypeStream && r.Response.BufferLength() > 0 && contexts.Get(r.Context()).Response != nil { return } - // html模板响应 - if r.Response.Header().Get("Content-Type") == "text/html" { + switch contentType { + case consts.HTTPContentTypeHtml: s.responseHtml(r) return - } - - // 支付通知响应 - if _, ok := s.PayNotifyRoutes[r.Router.Uri]; ok { - s.responsePayNotify(r) + case consts.HTTPContentTypeXml: + s.responseXml(r) return + case consts.HTTPContentTypeStream: + // ... + default: + responseJson(r) } - - // 默认json响应 - responseJson(r) } // responseHtml html模板响应 @@ -54,56 +50,23 @@ func (s *sMiddleware) responseHtml(r *ghttp.Request) { } r.Response.ClearBuffer() - _ = r.Response.WriteTplContent(simple.DefaultErrorTplContent(r.Context()), g.Map{ - "code": code, - "message": message, - "stack": resp, - }) + _ = r.Response.WriteTplContent(simple.DefaultErrorTplContent(r.Context()), g.Map{"code": code, "message": message, "stack": resp}) return } -// responsePayNotify 支付通知响应 -func (s *sMiddleware) responsePayNotify(r *ghttp.Request) { - var ( - ctx = r.Context() - err error - data *payin.PayNotifyModel - ) - +// responseXml xml响应 +func (s *sMiddleware) responseXml(r *ghttp.Request) { code, message, resp := parseResponse(r) - if code != gcode.CodeOK.Code() { - response.RJson(r, code, message, data) - return - } - - if err = gconv.Scan(resp, &data); err != nil || data == nil { - g.Log("exception").Errorf(ctx, "middleware.responsePayNotify Scan err:%+v, data:%+v", err, data) - r.Response.ClearBuffer() - r.Response.WriteStatus(http.StatusInternalServerError, err.Error()) - return - } - - switch data.PayType { - case consts.PayTypeAliPay: - response.RText(r, data.Message) - - case consts.PayTypeWxPay: - r.Response.ClearBuffer() - r.Response.WriteJson(fmt.Sprintf(`{"code": "%v","message": "%v"}`, data.Code, data.Message)) - - case consts.PayTypeQQPay: - r.Response.ClearBuffer() - r.Response.Write(``) - r.Response.WriteXml(g.Map{ - "return_code": data.Message, - }) + r.Response.ClearBuffer() + r.Response.Write(``) + switch code { + case gcode.CodeOK.Code(): + r.Response.WriteXml(g.Map{"code": code, "message": message, "data": resp}) default: - err = gerror.Newf("无效的支付方式,这可能是没有配置通知回调响应方式导致的:%+v", data) - g.Log("exception").Error(ctx, err) - r.Response.ClearBuffer() - r.Response.WriteStatus(http.StatusInternalServerError, err.Error()) + r.Response.WriteXml(g.Map{"code": code, "message": message, "error": resp}) } + return } // responseJson json响应 @@ -114,11 +77,8 @@ func responseJson(r *ghttp.Request) { // parseResponse 解析响应数据 func parseResponse(r *ghttp.Request) (code int, message string, resp interface{}) { - var ( - ctx = r.Context() - err = r.GetError() - ) - + ctx := r.Context() + err := r.GetError() if err == nil { return gcode.CodeOK.Code(), "操作成功", r.GetHandlerResponse() } @@ -126,12 +86,15 @@ func parseResponse(r *ghttp.Request) (code int, message string, resp interface{} // 是否输出错误堆栈到页面 if g.Cfg().MustGet(ctx, "hotgo.debug", true).Bool() { message = gerror.Current(err).Error() - resp = charset.ParseErrStack(err) + if getContentType(r) == consts.HTTPContentTypeHtml { + resp = charset.SerializeStack(err) + } else { + resp = charset.ParseErrStack(err) + } } else { message = consts.ErrorMessage(gerror.Current(err)) } - // 解析错误状态码 code = gerror.Code(err).Code() // 记录异常日志 @@ -142,3 +105,18 @@ func parseResponse(r *ghttp.Request) (code int, message string, resp interface{} } return } + +func getContentType(r *ghttp.Request) (contentType string) { + contentType = r.Response.Header().Get("Content-Type") + if contentType != "" { + return + } + + mime := gmeta.Get(r.GetHandlerResponse(), "mime").String() + if mime == "" { + contentType = consts.HTTPContentTypeJson + } else { + contentType = mime + } + return +} diff --git a/server/internal/logic/pay/refund.go b/server/internal/logic/pay/refund.go index 8e988c1..4436ae5 100644 --- a/server/internal/logic/pay/refund.go +++ b/server/internal/logic/pay/refund.go @@ -16,7 +16,6 @@ import ( "github.com/gogf/gf/v2/net/ghttp" "hotgo/internal/consts" "hotgo/internal/dao" - "hotgo/internal/library/hgorm" "hotgo/internal/library/hgorm/handler" "hotgo/internal/library/location" "hotgo/internal/library/payment" @@ -188,12 +187,7 @@ func (s *sPayRefund) List(ctx context.Context, in payin.PayRefundListInp) (list return } - fields, err := hgorm.GenSelect(ctx, payin.PayRefundListModel{}, dao.PayRefund) - if err != nil { - return - } - - err = mod.Fields(fields).Page(in.Page, in.PerPage).OrderDesc(dao.PayRefund.Columns().Id).Scan(&list) + err = mod.Fields(payin.PayRefundListModel{}).Page(in.Page, in.PerPage).OrderDesc(dao.PayRefund.Columns().Id).Scan(&list) return } diff --git a/server/internal/logic/sys/curd_demo.go b/server/internal/logic/sys/curd_demo.go index 1abc0ac..48504c4 100644 --- a/server/internal/logic/sys/curd_demo.go +++ b/server/internal/logic/sys/curd_demo.go @@ -83,8 +83,8 @@ func (s *sSysCurdDemo) List(ctx context.Context, in sysin.CurdDemoListInp) (list } //关联表select - fields, err := hgorm.GenJoinSelect(ctx, sysin.CurdDemoListModel{}, dao.SysGenCurdDemo, []*hgorm.Join{ - {Dao: dao.TestCategory, Alias: "testCategory"}, + fields, err := hgorm.GenJoinSelect(ctx, sysin.CurdDemoListModel{}, &dao.SysGenCurdDemo, []*hgorm.Join{ + {Dao: &dao.TestCategory, Alias: "testCategory"}, }) if err != nil { diff --git a/server/internal/logic/sys/dict_type.go b/server/internal/logic/sys/dict_type.go index ac074d8..0a30927 100644 --- a/server/internal/logic/sys/dict_type.go +++ b/server/internal/logic/sys/dict_type.go @@ -82,7 +82,7 @@ func (s *sSysDictType) Delete(ctx context.Context, in sysin.DictTypeDeleteInp) ( // Edit 修改/新增 func (s *sSysDictType) Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error) { - if err = hgorm.IsUnique(ctx, dao.SysDictType, g.Map{dao.SysDictType.Columns().Name: in.Name}, "名称已存在", in.Id); err != nil { + if err = hgorm.IsUnique(ctx, &dao.SysDictType, g.Map{dao.SysDictType.Columns().Name: in.Name}, "名称已存在", in.Id); err != nil { return } diff --git a/server/internal/logic/sys/login_log.go b/server/internal/logic/sys/login_log.go index ba708e7..f532d08 100644 --- a/server/internal/logic/sys/login_log.go +++ b/server/internal/logic/sys/login_log.go @@ -84,8 +84,8 @@ func (s *sSysLoginLog) List(ctx context.Context, in sysin.LoginLogListInp) (list } //关联表select - fields, err := hgorm.GenJoinSelect(ctx, sysin.LoginLogListModel{}, dao.SysLoginLog, []*hgorm.Join{ - {Dao: dao.SysLog, Alias: "sysLog"}, + fields, err := hgorm.GenJoinSelect(ctx, sysin.LoginLogListModel{}, &dao.SysLoginLog, []*hgorm.Join{ + {Dao: &dao.SysLog, Alias: "sysLog"}, }) if err != nil { diff --git a/server/internal/logic/sys/provinces.go b/server/internal/logic/sys/provinces.go index 5c13a76..de3568f 100644 --- a/server/internal/logic/sys/provinces.go +++ b/server/internal/logic/sys/provinces.go @@ -79,7 +79,7 @@ func (s *sSysProvinces) Delete(ctx context.Context, in sysin.ProvincesDeleteInp) // Edit 修改/新增省市区数据 func (s *sSysProvinces) Edit(ctx context.Context, in sysin.ProvincesEditInp) (err error) { // 关系树 - in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, dao.SysProvinces, in.Pid) + in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, &dao.SysProvinces, in.Pid) if err != nil { return } @@ -202,7 +202,7 @@ func (s *sSysProvinces) UniqueId(ctx context.Context, in sysin.ProvincesUniqueId return } - if err = hgorm.IsUnique(ctx, dao.SysProvinces, g.Map{dao.SysProvinces.Columns().Id: in.NewId}, "", in.OldId); err != nil { + if err = hgorm.IsUnique(ctx, &dao.SysProvinces, g.Map{dao.SysProvinces.Columns().Id: in.NewId}, "", in.OldId); err != nil { res.IsUnique = false return } diff --git a/server/internal/logic/sys/serve_log.go b/server/internal/logic/sys/serve_log.go index d69a93b..e4f8626 100644 --- a/server/internal/logic/sys/serve_log.go +++ b/server/internal/logic/sys/serve_log.go @@ -73,8 +73,8 @@ func (s *sSysServeLog) List(ctx context.Context, in sysin.ServeLogListInp) (list } //关联表select - fields, err := hgorm.GenJoinSelect(ctx, sysin.ServeLogListModel{}, dao.SysServeLog, []*hgorm.Join{ - {Dao: dao.SysLog, Alias: "sysLog"}, + fields, err := hgorm.GenJoinSelect(ctx, sysin.ServeLogListModel{}, &dao.SysServeLog, []*hgorm.Join{ + {Dao: &dao.SysLog, Alias: "sysLog"}, }) if err != nil { diff --git a/server/internal/router/home.go b/server/internal/router/home.go index 145959a..be5c9de 100644 --- a/server/internal/router/home.go +++ b/server/internal/router/home.go @@ -16,10 +16,9 @@ import ( // Home 前台页面路由 func Home(ctx context.Context, group *ghttp.RouterGroup) { - // 允许通过根地址访问的路由可以同时加到这里 - // 访问地址:http://127.0.0.1:8000 group.Group("/", func(group *ghttp.RouterGroup) { group.Middleware(service.Middleware().HomeAuth) + // 允许通过根地址访问的路由可以加到这里,访问地址:http://127.0.0.1:8000 group.Bind( base.Site, // 基础 )