From 62ecbb7f26b4807ebfeac85c16d84e5c838221b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=9F=E5=B8=85?= <133814250@qq.com> Date: Fri, 2 Jun 2023 20:29:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=8C=96=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=EF=BC=8C=E4=BD=BF=E7=94=A8=E6=B3=9B=E5=9E=8B?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B7=A5=E5=85=B7=E5=BA=93=E9=99=8D=E4=BD=8E?= =?UTF-8?q?=E5=86=97=E4=BD=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/Makefile | 18 + server/addons/hgexample/logic/sys/table.go | 4 +- .../hgexample/model/input/sysin/table.go | 2 - .../addons/hgexample/router/genrouter/init.go | 6 +- server/api/admin/attachment/attachment.go | 33 +- server/internal/cmd/http.go | 3 +- server/internal/consts/debris.go | 2 +- server/internal/consts/tcp.go | 5 +- server/internal/consts/upload.go | 10 + .../controller/admin/sys/attachment.go | 41 +- server/internal/dao/sys_attachment.go | 39 -- server/internal/library/addons/addons.go | 2 - server/internal/library/addons/build.go | 1 - server/internal/library/addons/module.go | 1 - server/internal/library/casbin/adapter.go | 17 +- server/internal/library/contexts/context.go | 1 - server/internal/library/ems/ems.go | 2 - server/internal/library/hggen/hggen.go | 3 - server/internal/library/hggen/init.go | 2 - .../hggen/views/curd_generate_web_model.go | 2 +- server/internal/library/hgorm/dao.go | 7 +- .../library/hgorm/handler/filter_auth.go | 1 - server/internal/library/location/location.go | 23 +- server/internal/library/location/region.go | 2 - server/internal/library/network/tcp/client.go | 66 +-- .../library/network/tcp/client_cron.go | 5 +- .../library/network/tcp/client_handle.go | 2 + server/internal/library/network/tcp/model.go | 1 + server/internal/library/network/tcp/router.go | 7 +- server/internal/library/network/tcp/rpc.go | 5 +- server/internal/library/network/tcp/server.go | 42 +- .../library/network/tcp/server_cron.go | 5 +- .../library/network/tcp/server_handle.go | 2 + .../internal/library/payment/alipay/handle.go | 2 - server/internal/library/payment/payment.go | 1 - .../internal/library/payment/qqpay/handle.go | 2 - .../internal/library/payment/wxpay/handle.go | 2 - server/internal/library/queue/consumer.go | 1 - server/internal/library/queue/kafkamq.go | 8 +- server/internal/library/storager/config.go | 22 + .../library/storager}/mime.go | 24 +- server/internal/library/storager/model.go | 12 + server/internal/library/storager/upload.go | 228 +++++++++ .../internal/library/storager/upload_cos.go | 42 ++ .../internal/library/storager/upload_local.go | 42 ++ .../internal/library/storager/upload_oss.go | 42 ++ .../internal/library/storager/upload_qiniu.go | 52 ++ .../library/storager/upload_ucloud.go | 45 ++ server/internal/logic/admin/dept.go | 4 +- server/internal/logic/admin/menu.go | 2 +- server/internal/logic/admin/notice.go | 20 +- server/internal/logic/admin/order.go | 2 +- server/internal/logic/admin/post.go | 2 +- server/internal/logic/admin/role.go | 10 +- server/internal/logic/common/upload.go | 405 +-------------- .../internal/logic/middleware/admin_auth.go | 1 - server/internal/logic/pay/pay.go | 2 +- server/internal/logic/sys/addons.go | 2 - server/internal/logic/sys/addons_config.go | 21 +- server/internal/logic/sys/attachment.go | 134 +---- server/internal/logic/sys/blacklist.go | 2 +- server/internal/logic/sys/config.go | 16 +- server/internal/logic/sys/cron.go | 2 +- server/internal/logic/sys/cron_group.go | 1 - server/internal/logic/sys/curd_demo.go | 2 +- server/internal/logic/sys/dict_data.go | 1 - server/internal/logic/sys/ems_log.go | 2 +- server/internal/logic/sys/gen_codes.go | 4 +- server/internal/logic/sys/log.go | 5 +- server/internal/logic/sys/login_log.go | 1 - server/internal/logic/sys/sms_log.go | 2 +- server/internal/logic/view/view_buildin.go | 37 -- server/internal/model/input/adminin/dept.go | 2 +- server/internal/model/input/adminin/member.go | 2 +- server/internal/model/input/adminin/order.go | 2 +- .../internal/model/input/sysin/attachment.go | 38 +- .../internal/model/input/sysin/cron_group.go | 2 +- .../internal/model/input/sysin/curd_demo.go | 2 +- .../internal/model/input/sysin/provinces.go | 2 +- server/internal/router/genrouter/init.go | 7 +- server/internal/service/admin.go | 286 +++++------ server/internal/service/common.go | 12 +- server/internal/service/sys.go | 464 +++++++++--------- server/internal/service/tcpclient.go | 24 +- server/internal/websocket/client_manager.go | 1 - .../addon/router/genrouter/init.go.template | 8 +- .../generate/default/curd/input.go.template | 2 +- .../generate/default/curd/logic.go.template | 2 +- server/utility/charset/charset.go | 33 +- server/utility/convert/convert.go | 32 +- server/utility/file/file.go | 6 - server/utility/format/format.go | 65 ++- server/utility/signal/signal.go | 56 --- server/utility/simple/event.go | 51 ++ server/utility/useragent/useragent.go | 61 +-- server/utility/validate/include.go | 32 +- 96 files changed, 1276 insertions(+), 1483 deletions(-) create mode 100644 server/internal/library/storager/config.go rename server/{utility/file => internal/library/storager}/mime.go (89%) create mode 100644 server/internal/library/storager/model.go create mode 100644 server/internal/library/storager/upload.go create mode 100644 server/internal/library/storager/upload_cos.go create mode 100644 server/internal/library/storager/upload_local.go create mode 100644 server/internal/library/storager/upload_oss.go create mode 100644 server/internal/library/storager/upload_qiniu.go create mode 100644 server/internal/library/storager/upload_ucloud.go delete mode 100644 server/utility/signal/signal.go create mode 100644 server/utility/simple/event.go diff --git a/server/Makefile b/server/Makefile index 2fed213..ba7cfdb 100644 --- a/server/Makefile +++ b/server/Makefile @@ -12,27 +12,33 @@ build: @cd ../web && yarn build && \cp -rf ./dist/* ../server$(ADMIN_RESOURCE_PATH) @echo "y" | gf build + # 通过热编译启动所有服务 .PHONY: all all: gf run main.go --args "all" + .PHONY: http http: gf run main.go --args "http" + .PHONY: queue queue: gf run main.go --args "queue" + .PHONY: cron cron: gf run main.go --args "cron" + .PHONY: auth auth: gf run main.go --args "auth" + # 启动web服务 .PHONY: web web: @@ -44,11 +50,20 @@ web: refresh: @go run main.go tools -m=casbin -a1=refresh + # 清理casbin权限 .PHONY: clear clear: @go run main.go tools -m=casbin -a1=clear + +# 运行代码质量分析工具 +# https://github.com/ywanbing/golangci +.PHONY: ci +ci: + golangci-lint run + + .PHONY: killmain killmain: @kill -9 $(ps -ef|grep main|grep -v grep|awk '{print $2}') @@ -79,11 +94,13 @@ cli.install: dao: cli.install @gf gen dao + # Generate Go files for Service. .PHONY: service service: cli.install @gf gen service + # Build image, deploy image and yaml to current kubectl environment and make port forward to local machine. .PHONY: start start: @@ -92,6 +109,7 @@ start: make deploy; \ make port; + # Build docker image. .PHONY: image image: cli.install diff --git a/server/addons/hgexample/logic/sys/table.go b/server/addons/hgexample/logic/sys/table.go index faedc65..5b126b3 100644 --- a/server/addons/hgexample/logic/sys/table.go +++ b/server/addons/hgexample/logic/sys/table.go @@ -189,7 +189,7 @@ func (s *sSysTable) Status(ctx context.Context, in sysin.TableStatusInp) (err er return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } @@ -209,7 +209,7 @@ func (s *sSysTable) Switch(ctx context.Context, in sysin.TableSwitchInp) (err er // ... } - if !validate.InSliceString(fields, in.Key) { + if !validate.InSlice(fields, in.Key) { err = gerror.New("开关键名不在白名单") return } diff --git a/server/addons/hgexample/model/input/sysin/table.go b/server/addons/hgexample/model/input/sysin/table.go index 5cb043a..f8c5df1 100644 --- a/server/addons/hgexample/model/input/sysin/table.go +++ b/server/addons/hgexample/model/input/sysin/table.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package sysin import ( @@ -53,7 +52,6 @@ func (in *TableEditInp) Filter(ctx context.Context) (err error) { if err := g.Validator().Rules("float|between:0,5").Messages("请输入一个浮点数|推荐星只能是0~5星").Data(in.Star).Run(ctx); err != nil { return err.Current() } - return } diff --git a/server/addons/hgexample/router/genrouter/init.go b/server/addons/hgexample/router/genrouter/init.go index ad87248..d15d513 100644 --- a/server/addons/hgexample/router/genrouter/init.go +++ b/server/addons/hgexample/router/genrouter/init.go @@ -15,7 +15,7 @@ import ( ) var ( - NoLogin []interface{} // 无需登录 + NoLoginRouter []interface{} // 无需登录 LoginRequiredRouter []interface{} // 需要登录 ) @@ -23,8 +23,8 @@ var ( func Register(ctx context.Context, group *ghttp.RouterGroup) { prefix := addons.RouterPrefix(ctx, consts.AppAdmin, global.GetSkeleton().Name) group.Group(prefix, func(group *ghttp.RouterGroup) { - if len(NoLogin) > 0 { - group.Bind(NoLogin...) + if len(NoLoginRouter) > 0 { + group.Bind(NoLoginRouter...) } group.Middleware(service.Middleware().AdminAuth) if len(LoginRequiredRouter) > 0 { diff --git a/server/api/admin/attachment/attachment.go b/server/api/admin/attachment/attachment.go index 221ea72..c3ba94d 100644 --- a/server/api/admin/attachment/attachment.go +++ b/server/api/admin/attachment/attachment.go @@ -3,17 +3,15 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package attachment import ( "github.com/gogf/gf/v2/frame/g" - "hotgo/internal/model/entity" "hotgo/internal/model/input/form" "hotgo/internal/model/input/sysin" ) -// ListReq 查询列表 +// ListReq 查询附件列表 type ListReq struct { form.PageReq form.RangeDateReq @@ -28,41 +26,18 @@ type ListRes struct { form.PageRes } -// ViewReq 获取信息 +// ViewReq 获取附件信息 type ViewReq struct { Id int64 `json:"id" v:"required#附件ID不能为空" dc:"附件ID"` - g.Meta `path:"/attachment/view" method:"get" tags:"附件" summary:"获取指定信息"` + g.Meta `path:"/attachment/view" method:"get" tags:"附件" summary:"获取指定附件信息"` } type ViewRes struct { *sysin.AttachmentViewModel } -// EditReq 修改/新增 -type EditReq struct { - entity.SysAttachment - g.Meta `path:"/attachment/edit" method:"post" tags:"附件" summary:"修改/新增附件"` -} -type EditRes struct{} - -// DeleteReq 删除 +// DeleteReq 删除附件 type DeleteReq struct { Id interface{} `json:"id" v:"required#附件ID不能为空" dc:"附件ID"` g.Meta `path:"/attachment/delete" method:"post" tags:"附件" summary:"删除附件"` } type DeleteRes struct{} - -// MaxSortReq 最大排序 -type MaxSortReq struct { - Id int64 `json:"id" dc:"附件ID"` - g.Meta `path:"/attachment/maxSort" method:"get" tags:"附件" summary:"附件最大排序"` -} -type MaxSortRes struct { - Sort int `json:"sort" dc:"排序"` -} - -// StatusReq 更新状态 -type StatusReq struct { - entity.SysAttachment - g.Meta `path:"/attachment/status" method:"post" tags:"附件" summary:"更新附件状态"` -} -type StatusRes struct{} diff --git a/server/internal/cmd/http.go b/server/internal/cmd/http.go index afb5a8e..d932f49 100644 --- a/server/internal/cmd/http.go +++ b/server/internal/cmd/http.go @@ -21,7 +21,7 @@ var ( Http = &gcmd.Command{ Name: "http", Usage: "http", - Brief: "HTTP服务", + Brief: "HTTP服务,也可以称为主服务,包含http、websocket、tcpserver多个可对外服务", Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { // 加载权限 casbin.InitEnforcer(ctx) @@ -32,6 +32,7 @@ var ( s.BindStatusHandler(404, func(r *ghttp.Request) { r.Response.Writeln("404 - 你似乎来到了没有知识存在的荒原…") }) + s.BindStatusHandler(403, func(r *ghttp.Request) { r.Response.Writeln("403 - 网站拒绝显示此网页") }) diff --git a/server/internal/consts/debris.go b/server/internal/consts/debris.go index b8bb253..f190a71 100644 --- a/server/internal/consts/debris.go +++ b/server/internal/consts/debris.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package consts // 碎片 @@ -12,4 +11,5 @@ const ( DemoTips = "演示系统已隐藏" NilJsonToString = "{}" // 空json初始化值 RegionSpilt = " / " // 地区分隔符 + Unknown = "Unknown" ) diff --git a/server/internal/consts/tcp.go b/server/internal/consts/tcp.go index b805885..e6a1347 100644 --- a/server/internal/consts/tcp.go +++ b/server/internal/consts/tcp.go @@ -1,7 +1,5 @@ package consts -import "time" - const ( TCPMsgCodeSuccess = 2000 // 成功的状态码 ) @@ -21,5 +19,6 @@ const ( ) const ( - TCPRpcTimeout = time.Second * 10 // rpc通讯超时时间, 默认10s + TCPHeartbeatTimeout = 300 // tcp心跳超时,默认300s + TCPRpcTimeout = 10 // rpc通讯超时时间, 默认10s ) diff --git a/server/internal/consts/upload.go b/server/internal/consts/upload.go index 25031db..cbf2926 100644 --- a/server/internal/consts/upload.go +++ b/server/internal/consts/upload.go @@ -5,6 +5,16 @@ // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE package consts +// 上传类型 +const ( + UploadTypeFile = 1 // 文件 + UploadTypeImage = 2 // 图片 + UploadTypeDoc = 3 // 文档 + UploadTypeAudio = 4 // 音频 + UploadTypeVideo = 5 // 视频 +) + +// 上传存储驱动 const ( UploadDriveLocal = "local" // 本地驱动 UploadDriveUCloud = "ucloud" // ucloud对象存储 diff --git a/server/internal/controller/admin/sys/attachment.go b/server/internal/controller/admin/sys/attachment.go index 4ae3a87..bc15b9a 100644 --- a/server/internal/controller/admin/sys/attachment.go +++ b/server/internal/controller/admin/sys/attachment.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package sys import ( @@ -21,7 +20,7 @@ var ( type cAttachment struct{} -// Delete 删除 +// Delete 删除附件 func (c *cAttachment) Delete(ctx context.Context, req *attachment.DeleteReq) (res *attachment.DeleteRes, err error) { var in sysin.AttachmentDeleteInp if err = gconv.Scan(req, &in); err != nil { @@ -32,30 +31,7 @@ func (c *cAttachment) Delete(ctx context.Context, req *attachment.DeleteReq) (re return } -// Edit 更新 -func (c *cAttachment) Edit(ctx context.Context, req *attachment.EditReq) (res *attachment.EditRes, err error) { - var in sysin.AttachmentEditInp - if err = gconv.Scan(req, &in); err != nil { - return - } - - err = service.SysAttachment().Edit(ctx, in) - return -} - -// MaxSort 最大排序 -func (c *cAttachment) MaxSort(ctx context.Context, req *attachment.MaxSortReq) (res *attachment.MaxSortRes, err error) { - data, err := service.SysAttachment().MaxSort(ctx, sysin.AttachmentMaxSortInp{Id: req.Id}) - if err != nil { - return - } - - res = new(attachment.MaxSortRes) - res.Sort = data.Sort - return -} - -// View 获取指定信息 +// View 获取指定附件信息 func (c *cAttachment) View(ctx context.Context, req *attachment.ViewReq) (res *attachment.ViewRes, err error) { data, err := service.SysAttachment().View(ctx, sysin.AttachmentViewInp{Id: req.Id}) if err != nil { @@ -67,7 +43,7 @@ func (c *cAttachment) View(ctx context.Context, req *attachment.ViewReq) (res *a return } -// List 查看列表 +// List 查看附件列表 func (c *cAttachment) List(ctx context.Context, req *attachment.ListReq) (res *attachment.ListRes, err error) { var in sysin.AttachmentListInp if err = gconv.Scan(req, &in); err != nil { @@ -86,14 +62,3 @@ func (c *cAttachment) List(ctx context.Context, req *attachment.ListReq) (res *a res.PerPage = req.PerPage return } - -// Status 更新部门状态 -func (c *cAttachment) Status(ctx context.Context, req *attachment.StatusReq) (res *attachment.StatusRes, err error) { - var in sysin.AttachmentStatusInp - if err = gconv.Scan(req, &in); err != nil { - return - } - - err = service.SysAttachment().Status(ctx, in) - return -} diff --git a/server/internal/dao/sys_attachment.go b/server/internal/dao/sys_attachment.go index 9507083..4be9a29 100644 --- a/server/internal/dao/sys_attachment.go +++ b/server/internal/dao/sys_attachment.go @@ -5,15 +5,7 @@ package dao import ( - "context" - "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gtime" - "hotgo/internal/consts" "hotgo/internal/dao/internal" - "hotgo/internal/model/input/sysin" - "hotgo/internal/service" - "hotgo/utility/format" ) // internalSysAttachmentDao is internal type for wrapping internal DAO implements. @@ -31,34 +23,3 @@ var ( internal.NewSysAttachmentDao(), } ) - -func (dao *sysAttachmentDao) GetMd5File(ctx context.Context, md5 string) (data *sysin.AttachmentListModel, err error) { - if err = dao.Ctx(ctx). - Where("md5", md5). - Scan(&data); err != nil { - err = gerror.Wrap(err, consts.ErrorORM) - return nil, err - } - - if data == nil { - return nil, nil - } - - conf, err := service.SysConfig().GetUpload(ctx) - if err != nil { - return nil, nil - } - - data.SizeFormat = format.FileSize(data.Size) - data.FileUrl = service.CommonUpload().LastUrl(ctx, conf, data.FileUrl, data.Drive) - - // 只有在上传时才会检查md5值,如果文件存在则更新最后上传时间,保证上传列表更新显示在最前面 - if data.Id > 0 { - _, _ = dao.Ctx(ctx).Where("id", data.Id).Data(g.Map{ - "status": consts.StatusEnabled, - "updated_at": gtime.Now(), - }).Update() - } - - return data, nil -} diff --git a/server/internal/library/addons/addons.go b/server/internal/library/addons/addons.go index cacd102..108d7a9 100644 --- a/server/internal/library/addons/addons.go +++ b/server/internal/library/addons/addons.go @@ -23,10 +23,8 @@ func Tpl(name, tpl string) string { // 最终效果:/应用名称/插件模块名称/xxx/xxx。如果你不喜欢现在的路由风格,可以自行调整 func RouterPrefix(ctx context.Context, app, name string) string { var prefix = "/" - if app != "" { prefix = g.Cfg().MustGet(ctx, "router."+app+".prefix", "/"+app+"").String() } - return prefix + "/" + name } diff --git a/server/internal/library/addons/build.go b/server/internal/library/addons/build.go index dd3f50e..02b4afa 100644 --- a/server/internal/library/addons/build.go +++ b/server/internal/library/addons/build.go @@ -91,7 +91,6 @@ func Build(ctx context.Context, sk Skeleton, conf *model.BuildAddonConfig) (err if err = gfile.PutContents(webViewsPath+"/config/system.vue", gstr.ReplaceByMap(webConfigSystem, replaces)); err != nil { return } - return } diff --git a/server/internal/library/addons/module.go b/server/internal/library/addons/module.go index 0b09b7a..34feb5c 100644 --- a/server/internal/library/addons/module.go +++ b/server/internal/library/addons/module.go @@ -141,6 +141,5 @@ func ModuleSelect() form.Selects { Name: skeleton.Label, }) } - return lst } diff --git a/server/internal/library/casbin/adapter.go b/server/internal/library/casbin/adapter.go index 5e2e7a2..afdd42a 100644 --- a/server/internal/library/casbin/adapter.go +++ b/server/internal/library/casbin/adapter.go @@ -104,21 +104,18 @@ func (a *adapter) model() *gdb.Model { // create a policy table when it's not exists. func (a *adapter) createPolicyTable() (err error) { _, err = a.db.Exec(context.TODO(), fmt.Sprintf(createPolicyTableSql, a.table)) - return } // drop policy table from the storage. func (a *adapter) dropPolicyTable() (err error) { _, err = a.db.Exec(context.TODO(), fmt.Sprintf(dropPolicyTableSql, a.table)) - return } // LoadPolicy loads all policy rules from the storage. func (a *adapter) LoadPolicy(model model.Model) (err error) { var rules []policyRule - if err = a.model().Scan(&rules); err != nil { return } @@ -126,7 +123,6 @@ func (a *adapter) LoadPolicy(model model.Model) (err error) { for _, rule := range rules { a.loadPolicyRule(rule, model) } - return } @@ -159,14 +155,12 @@ func (a *adapter) SavePolicy(model model.Model) (err error) { return } } - return } // AddPolicy adds a policy rule to the storage. func (a *adapter) AddPolicy(sec string, ptype string, rule []string) (err error) { _, err = a.model().Insert(a.buildPolicyRule(ptype, rule)) - return } @@ -183,7 +177,6 @@ func (a *adapter) AddPolicies(sec string, ptype string, rules [][]string) (err e } _, err = a.model().Insert(policyRules) - return } @@ -228,14 +221,12 @@ func (a *adapter) RemovePolicies(sec string, ptype string, rules [][]string) (er } _, err = db.Delete() - return } // UpdatePolicy updates a policy rule from storage. func (a *adapter) UpdatePolicy(sec string, ptype string, oldRule, newRule []string) (err error) { _, err = a.model().Update(a.buildPolicyRule(ptype, newRule), a.buildPolicyRule(ptype, oldRule)) - return } @@ -244,18 +235,14 @@ func (a *adapter) UpdatePolicies(sec string, ptype string, oldRules, newRules [] if len(oldRules) == 0 || len(newRules) == 0 { return } - - err = a.db.Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error { + return a.db.Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error { for i := 0; i < int(math.Min(float64(len(oldRules)), float64(len(newRules)))); i++ { if _, err = tx.Model(a.table).Update(a.buildPolicyRule(ptype, newRules[i]), a.buildPolicyRule(ptype, oldRules[i])); err != nil { return err } } - return nil }) - - return } // 加载策略规则 @@ -285,7 +272,6 @@ func (a *adapter) loadPolicyRule(rule policyRule, model model.Model) { if rule.V5 != "" { ruleText += ", " + rule.V5 } - if err := persist.LoadPolicyLine(ruleText, model); err != nil { panic(err) } @@ -318,6 +304,5 @@ func (a *adapter) buildPolicyRule(ptype string, data []string) policyRule { if len(data) > 5 { rule.V5 = data[5] } - return rule } diff --git a/server/internal/library/contexts/context.go b/server/internal/library/contexts/context.go index df24bfb..b6606ff 100644 --- a/server/internal/library/contexts/context.go +++ b/server/internal/library/contexts/context.go @@ -66,7 +66,6 @@ func GetUser(ctx context.Context) *model.Identity { if c == nil { return nil } - return c.User } diff --git a/server/internal/library/ems/ems.go b/server/internal/library/ems/ems.go index 28c122c..f5615b9 100644 --- a/server/internal/library/ems/ems.go +++ b/server/internal/library/ems/ems.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package ems import ( @@ -47,6 +46,5 @@ func sendToMail(config *model.EmailConfig, to, subject, body, mailType string) e } msg := []byte("To: " + to + "\r\nFrom: " + config.SendName + "<" + config.User + ">" + "\r\nSubject: " + subject + "\r\n" + contentType + "\r\n\r\n" + body) - return smtp.SendMail(config.Addr, auth, config.User, sendTo, msg) } diff --git a/server/internal/library/hggen/hggen.go b/server/internal/library/hggen/hggen.go index 9c20b4d..fe9ba66 100644 --- a/server/internal/library/hggen/hggen.go +++ b/server/internal/library/hggen/hggen.go @@ -33,7 +33,6 @@ func Dao(ctx context.Context) (err error) { } gendao.DoGenDaoForArray(ctx, inp) } - return } @@ -126,7 +125,6 @@ func TableSelects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin. } res.Addons = addons.ModuleSelect() - return } @@ -163,7 +161,6 @@ func GenTypeSelect(ctx context.Context) (res sysin.GenTypeSelects, err error) { res = append(res, row) } sort.Sort(res) - return } diff --git a/server/internal/library/hggen/init.go b/server/internal/library/hggen/init.go index 6ad8a3f..7ff306c 100644 --- a/server/internal/library/hggen/init.go +++ b/server/internal/library/hggen/init.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package hggen import ( @@ -77,7 +76,6 @@ func GetDaoConfig(group string) gendao.CGenDaoInput { panic(err) } } - return inp } diff --git a/server/internal/library/hggen/views/curd_generate_web_model.go b/server/internal/library/hggen/views/curd_generate_web_model.go index 9abaf9d..5434812 100644 --- a/server/internal/library/hggen/views/curd_generate_web_model.go +++ b/server/internal/library/hggen/views/curd_generate_web_model.go @@ -81,7 +81,7 @@ func (l *gCurd) generateWebModelDictOptions(ctx context.Context, in *CurdPreview } } - dictTypeIds = convert.UniqueSliceInt64(dictTypeIds) + dictTypeIds = convert.UniqueSlice(dictTypeIds) if len(dictTypeIds) == 0 { options["has"] = false return options, nil diff --git a/server/internal/library/hgorm/dao.go b/server/internal/library/hgorm/dao.go index 32e523a..f1bce57 100644 --- a/server/internal/library/hgorm/dao.go +++ b/server/internal/library/hgorm/dao.go @@ -108,8 +108,7 @@ func GenJoinSelect(ctx context.Context, entity interface{}, masterDao interface{ continue } } - - return gstr.Implode(",", convert.UniqueSliceString(tmpFields)), nil + return gstr.Implode(",", convert.UniqueSlice(tmpFields)), nil } // GenSelect 生成select @@ -144,8 +143,7 @@ func GenSelect(ctx context.Context, entity interface{}, dao interface{}) (allFie continue } } - - return gstr.Implode(",", convert.UniqueSliceString(tmpFields)), nil + return gstr.Implode(",", convert.UniqueSlice(tmpFields)), nil } // GetPkField 获取dao实例中的主键名称 @@ -163,7 +161,6 @@ func GetPkField(ctx context.Context, dao daoInstance) (string, error) { return field.Name, nil } } - return "", errors.New("no primary key") } diff --git a/server/internal/library/hgorm/handler/filter_auth.go b/server/internal/library/hgorm/handler/filter_auth.go index 558b149..30a7fc7 100644 --- a/server/internal/library/hgorm/handler/filter_auth.go +++ b/server/internal/library/hgorm/handler/filter_auth.go @@ -38,7 +38,6 @@ func FilterAuth(m *gdb.Model) *gdb.Model { if !needAuth { return m } - return m.Handler(FilterAuthWithField(filterField)) } diff --git a/server/internal/library/location/location.go b/server/internal/library/location/location.go index c15e3e1..a8e26c0 100644 --- a/server/internal/library/location/location.go +++ b/server/internal/library/location/location.go @@ -72,20 +72,19 @@ func WhoisLocation(ctx context.Context, ip string) (*IpLocationData, error) { return nil, err } - var whoisData *WhoisRegionData - if err = gconv.Struct([]byte(str), &whoisData); err != nil { + var who *WhoisRegionData + if err = gconv.Struct([]byte(str), &who); err != nil { return nil, err } - return &IpLocationData{ - Ip: whoisData.Ip, - Region: whoisData.Addr, - Province: whoisData.Pro, - ProvinceCode: gconv.Int64(whoisData.ProCode), - City: whoisData.City, - CityCode: gconv.Int64(whoisData.CityCode), - Area: whoisData.Region, - AreaCode: gconv.Int64(whoisData.RegionCode), + Ip: who.Ip, + Region: who.Addr, + Province: who.Pro, + ProvinceCode: gconv.Int64(who.ProCode), + City: who.City, + CityCode: gconv.Int64(who.CityCode), + Area: who.Region, + AreaCode: gconv.Int64(who.RegionCode), }, nil } @@ -159,7 +158,6 @@ func GetLocation(ctx context.Context, ip string) (data *IpLocationData, err erro } cacheMap.Set(ip, data) } - return } @@ -234,6 +232,5 @@ func GetClientIp(r *ghttp.Request) string { if gstr.Contains(ip, ", ") { ip = gstr.StrTillEx(ip, ", ") } - return ip } diff --git a/server/internal/library/location/region.go b/server/internal/library/location/region.go index 96246bc..cd179eb 100644 --- a/server/internal/library/location/region.go +++ b/server/internal/library/location/region.go @@ -52,7 +52,6 @@ func ParseSimpleRegion(ctx context.Context, id int64, spilt ...string) (string, } return ParseRegion(ctx, ids[0], ids[1], id, spilt...) } - return "", gerror.New("currently, it is only supported to regional areas") } @@ -104,6 +103,5 @@ func ParseRegion(ctx context.Context, province int64, city int64, county int64, if province > 0 && city > 0 { return provinceName.String() + sp + cityName.String(), nil } - return provinceName.String(), nil } diff --git a/server/internal/library/network/tcp/client.go b/server/internal/library/network/tcp/client.go index f51c564..fcd01e2 100644 --- a/server/internal/library/network/tcp/client.go +++ b/server/internal/library/network/tcp/client.go @@ -22,41 +22,42 @@ import ( // ClientConfig 客户端配置 type ClientConfig struct { - Addr string - Auth *AuthMeta - Timeout time.Duration - ConnectInterval time.Duration - MaxConnectCount uint - ConnectCount uint - AutoReconnect bool - LoginEvent CallbackEvent - CloseEvent CallbackEvent + Addr string // 连接地址 + Auth *AuthMeta // 认证元数据 + Timeout time.Duration // 连接超时时间 + ConnectInterval time.Duration // 重连时间间隔 + MaxConnectCount uint // 最大重连次数,0不限次数 + ConnectCount uint // 已重连次数 + AutoReconnect bool // 是否开启自动重连 + LoginEvent CallbackEvent // 登录成功事件 + CloseEvent CallbackEvent // 连接关闭事件 } // Client 客户端 type Client struct { - Ctx context.Context - Logger *glog.Logger - IsLogin bool // 是否已登录 - addr string - auth *AuthMeta - rpc *Rpc - timeout time.Duration - connectInterval time.Duration - maxConnectCount uint - connectCount uint - autoReconnect bool - loginEvent CallbackEvent - closeEvent CallbackEvent - sync.Mutex - heartbeat int64 - routers map[string]RouterHandler - conn *gtcp.Conn - wg sync.WaitGroup - closeFlag bool // 关闭标签,关闭以后可以重连 - stopFlag bool // 停止标签,停止以后不能重连 + Ctx context.Context // 上下文 + Logger *glog.Logger // 日志处理器 + IsLogin bool // 是否已登录 + addr string // 连接地址 + auth *AuthMeta // 认证元数据 + rpc *Rpc // rpc协议支持 + timeout time.Duration // 连接超时时间 + connectInterval time.Duration // 重连时间间隔 + maxConnectCount uint // 最大重连次数,0不限次数 + connectCount uint // 已重连次数 + autoReconnect bool // 是否开启自动重连 + loginEvent CallbackEvent // 登录成功事件 + closeEvent CallbackEvent // 连接关闭事件 + sync.Mutex // 状态锁 + heartbeat int64 // 心跳 + routers map[string]RouterHandler // 已注册的路由 + conn *gtcp.Conn // 连接对象 + wg sync.WaitGroup // 状态控制 + closeFlag bool // 关闭标签,关闭以后可以重连 + stopFlag bool // 停止标签,停止以后不能重连 } +// NewClient 初始化一个tcp客户端 func NewClient(config *ClientConfig) (client *Client, err error) { client = new(Client) @@ -110,7 +111,7 @@ func NewClient(config *ClientConfig) (client *Client, err error) { return } -// Start 启动 +// Start 启动tcp连接 func (client *Client) Start() (err error) { client.Lock() defer client.Unlock() @@ -133,7 +134,6 @@ func (client *Client) Start() (err error) { simple.SafeGo(client.Ctx, func(ctx context.Context) { client.connect() }) - return } @@ -165,6 +165,7 @@ func (client *Client) RegisterRouter(routers map[string]RouterHandler) (err erro return } +// dial func (client *Client) dial() *gtcp.Conn { for { conn, err := gtcp.NewConn(client.addr, client.timeout) @@ -218,6 +219,7 @@ reconnect: client.startCron() } +// read func (client *Client) read() { simple.SafeGo(client.Ctx, func(ctx context.Context) { defer func() { @@ -347,7 +349,6 @@ func (client *Client) Write(data interface{}) error { return gerror.Newf("client json message pointer required: %+v", data) } msg := &Message{Router: msgType.Elem().Name(), Data: data} - return SendPkg(client.conn, msg) } @@ -379,7 +380,6 @@ func (client *Client) RpcRequest(ctx context.Context, data interface{}) (res int err = gerror.New("traceID is required") return } - return client.rpc.Request(key, func() { _ = client.Write(data) }) diff --git a/server/internal/library/network/tcp/client_cron.go b/server/internal/library/network/tcp/client_cron.go index b2ea45f..a315511 100644 --- a/server/internal/library/network/tcp/client_cron.go +++ b/server/internal/library/network/tcp/client_cron.go @@ -13,21 +13,24 @@ import ( "hotgo/internal/consts" ) +// getCronKey 生成客户端定时任务名称 func (client *Client) getCronKey(s string) string { return fmt.Sprintf("tcp.client_%s_%s:%s", s, client.auth.Group, client.auth.Name) } +// stopCron 停止定时任务 func (client *Client) stopCron() { for _, v := range gcron.Entries() { gcron.Remove(v.Name) } } +// startCron 启动定时任务 func (client *Client) startCron() { // 心跳超时检查 if gcron.Search(client.getCronKey(consts.TCPCronHeartbeatVerify)) == nil { _, _ = gcron.AddSingleton(client.Ctx, "@every 600s", func(ctx context.Context) { - if client.heartbeat < gtime.Timestamp()-600 { + if client.heartbeat < gtime.Timestamp()-consts.TCPHeartbeatTimeout { client.Logger.Debugf(client.Ctx, "client heartbeat timeout, about to reconnect..") client.Destroy() } diff --git a/server/internal/library/network/tcp/client_handle.go b/server/internal/library/network/tcp/client_handle.go index a003dfa..a084347 100644 --- a/server/internal/library/network/tcp/client_handle.go +++ b/server/internal/library/network/tcp/client_handle.go @@ -37,6 +37,7 @@ func (client *Client) serverLogin() { } } +// onResponseServerLogin 接收服务登陆响应结果 func (client *Client) onResponseServerLogin(ctx context.Context, args ...interface{}) { var in *msgin.ResponseServerLogin if err := gconv.Scan(args[0], &in); err != nil { @@ -58,6 +59,7 @@ func (client *Client) onResponseServerLogin(ctx context.Context, args ...interfa } } +// onResponseServerHeartbeat 接收心跳响应结果 func (client *Client) onResponseServerHeartbeat(ctx context.Context, args ...interface{}) { var in *msgin.ResponseServerHeartbeat if err := gconv.Scan(args[0], &in); err != nil { diff --git a/server/internal/library/network/tcp/model.go b/server/internal/library/network/tcp/model.go index 2b16435..1e3ca59 100644 --- a/server/internal/library/network/tcp/model.go +++ b/server/internal/library/network/tcp/model.go @@ -19,6 +19,7 @@ type AuthMeta struct { EndAt *gtime.Time `json:"-"` } +// Context tcp上下文 type Context struct { Conn *gtcp.Conn `json:"conn"` Auth *AuthMeta `json:"auth"` // 认证元数据 diff --git a/server/internal/library/network/tcp/router.go b/server/internal/library/network/tcp/router.go index 31216f2..39ce024 100644 --- a/server/internal/library/network/tcp/router.go +++ b/server/internal/library/network/tcp/router.go @@ -14,8 +14,10 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) -var GoPool = grpool.New(100) +// GoPool 初始化一个协程池,用于处理消息处理 +var GoPool = grpool.New(20) +// RouterHandler 路由消息处理器 type RouterHandler func(ctx context.Context, args ...interface{}) // Message 路由消息 @@ -24,6 +26,7 @@ type Message struct { Data interface{} `json:"data"` } +// SendPkg 打包发送的数据包 func SendPkg(conn *gtcp.Conn, message *Message) error { b, err := json.Marshal(message) if err != nil { @@ -32,6 +35,7 @@ func SendPkg(conn *gtcp.Conn, message *Message) error { return conn.SendPkg(b) } +// RecvPkg 解包 func RecvPkg(conn *gtcp.Conn) (*Message, error) { if data, err := conn.RecvPkg(); err != nil { return nil, err @@ -58,7 +62,6 @@ func MsgPkg(data interface{}, auth *AuthMeta, traceID string) string { if msg == nil { return "" } - return msg.TraceID } diff --git a/server/internal/library/network/tcp/rpc.go b/server/internal/library/network/tcp/rpc.go index 6aee4e1..2dfc691 100644 --- a/server/internal/library/network/tcp/rpc.go +++ b/server/internal/library/network/tcp/rpc.go @@ -22,6 +22,7 @@ type Rpc struct { callbacks map[string]RpcRespFunc } +// RpcResp 响应结构 type RpcResp struct { res interface{} err error @@ -29,6 +30,7 @@ type RpcResp struct { type RpcRespFunc func(resp interface{}, err error) +// NewRpc 初始化一个rpc协议 func NewRpc(ctx context.Context) *Rpc { return &Rpc{ ctx: ctx, @@ -57,7 +59,6 @@ func (r *Rpc) HandleMsg(ctx context.Context, cancel context.CancelFunc, data int }) return true } - return false } @@ -99,7 +100,7 @@ func (r *Rpc) Request(callId string, send func()) (res interface{}, err error) { <-waitCh select { - case <-time.After(consts.TCPRpcTimeout): + case <-time.After(time.Second * consts.TCPRpcTimeout): err = gerror.New("rpc response timeout") return case got := <-resCh: diff --git a/server/internal/library/network/tcp/server.go b/server/internal/library/network/tcp/server.go index 19d060d..fc76764 100644 --- a/server/internal/library/network/tcp/server.go +++ b/server/internal/library/network/tcp/server.go @@ -19,35 +19,38 @@ import ( "time" ) +// ClientConn 连接到tcp服务器的客户端对象 type ClientConn struct { - Conn *gtcp.Conn - Auth *AuthMeta - heartbeat int64 + Conn *gtcp.Conn // 连接对象 + Auth *AuthMeta // 认证元数据 + heartbeat int64 // 心跳 } +// ServerConfig tcp服务器配置 type ServerConfig struct { Name string // 服务名称 Addr string // 监听地址 } +// Server tcp服务器对象结构 type Server struct { - Ctx context.Context - Logger *glog.Logger - addr string - name string - rpc *Rpc - ln *gtcp.Server - wgLn sync.WaitGroup - mutex sync.Mutex - closeFlag bool - clients map[string]*ClientConn // 已登录的认证客户端 - mutexConns sync.Mutex - wgConns sync.WaitGroup - cronRouters map[string]RouterHandler // 路由 - queueRouters map[string]RouterHandler - authRouters map[string]RouterHandler + Ctx context.Context // 上下文 + Logger *glog.Logger // 日志处理器 + addr string // 连接地址 + name string // 服务器名称 + rpc *Rpc // rpc协议 + ln *gtcp.Server // tcp服务器 + wgLn sync.WaitGroup // 状态控制,主要用于tcp服务器能够按流程启动退出 + mutex sync.Mutex // 服务器状态锁 + closeFlag bool // 服务关闭标签 + clients map[string]*ClientConn // 已登录的认证客户端 + mutexConns sync.Mutex // 连接锁,主要用于客户端上下线 + cronRouters map[string]RouterHandler // 定时任务路由 + queueRouters map[string]RouterHandler // 队列路由 + authRouters map[string]RouterHandler // 任务路由 } +// NewServer 初始一个tcp服务器对象 func NewServer(config *ServerConfig) (server *Server, err error) { if config == nil { err = gerror.New("config is nil") @@ -84,6 +87,7 @@ func NewServer(config *ServerConfig) (server *Server, err error) { return } +// accept func (server *Server) accept(conn *gtcp.Conn) { defer func() { server.mutexConns.Lock() @@ -262,6 +266,7 @@ func (server *Server) RegisterQueueRouter(routers map[string]RouterHandler) { } } +// Listen 监听服务 func (server *Server) Listen() (err error) { server.wgLn.Add(1) defer server.wgLn.Done() @@ -283,7 +288,6 @@ func (server *Server) Close() { } server.clients = nil server.mutexConns.Unlock() - server.wgConns.Wait() if server.ln != nil { _ = server.ln.Close() diff --git a/server/internal/library/network/tcp/server_cron.go b/server/internal/library/network/tcp/server_cron.go index 6787e9e..46ce808 100644 --- a/server/internal/library/network/tcp/server_cron.go +++ b/server/internal/library/network/tcp/server_cron.go @@ -13,16 +13,19 @@ import ( "hotgo/internal/consts" ) +// getCronKey 生成服务端定时任务名称 func (server *Server) getCronKey(s string) string { return fmt.Sprintf("tcp.server_%s_%s", s, server.name) } +// stopCron 停止定时任务 func (server *Server) stopCron() { for _, v := range gcron.Entries() { gcron.Remove(v.Name) } } +// startCron 启动定时任务 func (server *Server) startCron() { // 心跳超时检查 if gcron.Search(server.getCronKey(consts.TCPCronHeartbeatVerify)) == nil { @@ -31,7 +34,7 @@ func (server *Server) startCron() { return } for _, client := range server.clients { - if client.heartbeat < gtime.Timestamp()-300 { + if client.heartbeat < gtime.Timestamp()-consts.TCPHeartbeatTimeout { _ = client.Conn.Close() server.Logger.Debugf(server.Ctx, "client heartbeat timeout, close conn. auth:%+v", client.Auth) } diff --git a/server/internal/library/network/tcp/server_handle.go b/server/internal/library/network/tcp/server_handle.go index d5859f0..b86d7df 100644 --- a/server/internal/library/network/tcp/server_handle.go +++ b/server/internal/library/network/tcp/server_handle.go @@ -17,6 +17,7 @@ import ( "hotgo/utility/convert" ) +// onServerLogin 处理客户端登录 func (server *Server) onServerLogin(ctx context.Context, args ...interface{}) { var ( in = new(msgin.ServerLogin) @@ -137,6 +138,7 @@ func (server *Server) onServerLogin(ctx context.Context, args ...interface{}) { _ = server.Write(user.Conn, res) } +// onServerHeartbeat 处理客户端心跳 func (server *Server) onServerHeartbeat(ctx context.Context, args ...interface{}) { var ( in *msgin.ServerHeartbeat diff --git a/server/internal/library/payment/alipay/handle.go b/server/internal/library/payment/alipay/handle.go index 2afde09..045321a 100644 --- a/server/internal/library/payment/alipay/handle.go +++ b/server/internal/library/payment/alipay/handle.go @@ -93,7 +93,6 @@ func (h *aliPay) Notify(ctx context.Context, in payin.NotifyInp) (res *payin.Not res.OutTradeNo = notify.OutTradeNo res.PayAt = notify.GmtPayment res.ActualAmount = gconv.Float64(notify.ReceiptAmount) - return } @@ -115,7 +114,6 @@ func (h *aliPay) CreateOrder(ctx context.Context, in payin.CreateOrderInp) (res default: err = gerror.Newf("暂未支持的交易方式:%v", in.Pay.TradeType) } - return } diff --git a/server/internal/library/payment/payment.go b/server/internal/library/payment/payment.go index 15fb06d..e68c75e 100644 --- a/server/internal/library/payment/payment.go +++ b/server/internal/library/payment/payment.go @@ -44,7 +44,6 @@ func New(name ...string) PayClient { default: panic(fmt.Sprintf("暂不支持的支付方式:%v", payType)) } - return client } diff --git a/server/internal/library/payment/qqpay/handle.go b/server/internal/library/payment/qqpay/handle.go index ee7646f..ccb1d74 100644 --- a/server/internal/library/payment/qqpay/handle.go +++ b/server/internal/library/payment/qqpay/handle.go @@ -75,7 +75,6 @@ func (h *qqPay) Notify(ctx context.Context, in payin.NotifyInp) (res *payin.Noti res.OutTradeNo = notify.OutTradeNo res.PayAt = gtime.New(notify.TimeEnd) res.ActualAmount = gconv.Float64(notify.CouponFee) / 100 // 用户本次交易中,实际支付的金额 转为元,和系统内保持一至 - return } @@ -119,7 +118,6 @@ func (h *qqPay) CreateOrder(ctx context.Context, in payin.CreateOrderInp) (res * default: err = gerror.Newf("暂未支持的交易方式:%v", in.Pay.TradeType) } - return } diff --git a/server/internal/library/payment/wxpay/handle.go b/server/internal/library/payment/wxpay/handle.go index e65f0b1..ee199e6 100644 --- a/server/internal/library/payment/wxpay/handle.go +++ b/server/internal/library/payment/wxpay/handle.go @@ -105,7 +105,6 @@ func (h *wxPay) Notify(ctx context.Context, in payin.NotifyInp) (res *payin.Noti res.OutTradeNo = notify.OutTradeNo res.PayAt = gtime.New(notify.SuccessTime) res.ActualAmount = float64(notify.Amount.PayerTotal / 100) // 转为元,和系统内保持一至 - return } @@ -121,7 +120,6 @@ func (h *wxPay) CreateOrder(ctx context.Context, in payin.CreateOrderInp) (res * default: err = gerror.Newf("暂未支持的交易方式:%v", in.Pay.TradeType) } - return } diff --git a/server/internal/library/queue/consumer.go b/server/internal/library/queue/consumer.go index 1a9ea46..89d16a0 100644 --- a/server/internal/library/queue/consumer.go +++ b/server/internal/library/queue/consumer.go @@ -69,5 +69,4 @@ func consumerListen(ctx context.Context, job consumerStrategy) { }); listenErr != nil { g.Log().Fatalf(ctx, "消费队列:%s 监听失败, err:%+v", topic, listenErr) } - } diff --git a/server/internal/library/queue/kafkamq.go b/server/internal/library/queue/kafkamq.go index 0f185dd..f987265 100644 --- a/server/internal/library/queue/kafkamq.go +++ b/server/internal/library/queue/kafkamq.go @@ -11,7 +11,8 @@ import ( "github.com/Shopify/sarama" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" - "hotgo/utility/signal" + "github.com/gogf/gf/v2/os/gproc" + "os" "time" ) @@ -109,14 +110,13 @@ func (r *KafkaMq) ListenReceiveMsgDo(topic string, receiveDo func(mqMsg MqMsg)) <-consumer.ready g.Log().Debug(ctx, "kafka consumer up and running!...") - signal.AppDefer(func() { + gproc.AddSigHandlerShutdown(func(sig os.Signal) { g.Log().Debug(ctx, "kafka consumer close...") cancel() if err = r.consumerIns.Close(); err != nil { g.Log().Fatalf(ctx, "kafka Error closing client, err:%+v", err) } }) - return } @@ -203,7 +203,7 @@ func doRegisterKafkaProducer(connOpt KafkaConfig, mqIns *KafkaMq) (err error) { return } - signal.AppDefer(func() { + gproc.AddSigHandlerShutdown(func(sig os.Signal) { g.Log().Debug(ctx, "kafka producer AsyncClose...") mqIns.producerIns.AsyncClose() }) diff --git a/server/internal/library/storager/config.go b/server/internal/library/storager/config.go new file mode 100644 index 0000000..0314161 --- /dev/null +++ b/server/internal/library/storager/config.go @@ -0,0 +1,22 @@ +package storager + +import ( + "context" + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + "hotgo/internal/model" +) + +var config *model.UploadConfig + +func SetConfig(c *model.UploadConfig) { + config = c +} + +func GetConfig() *model.UploadConfig { + return config +} + +func GetModel(ctx context.Context) *gdb.Model { + return g.Model("sys_attachment").Ctx(ctx) +} diff --git a/server/utility/file/mime.go b/server/internal/library/storager/mime.go similarity index 89% rename from server/utility/file/mime.go rename to server/internal/library/storager/mime.go index 3776836..cae30fa 100644 --- a/server/utility/file/mime.go +++ b/server/internal/library/storager/mime.go @@ -1,9 +1,9 @@ -// Package file +// Package storager // @Link https://github.com/bufanyun/hotgo // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -package file +package storager import ( "github.com/gogf/gf/v2/errors/gerror" @@ -14,7 +14,7 @@ import ( "path" ) -// 文件分类 +// 文件归属分类 const ( KindImg = "images" // 图片 KindDoc = "document" // 文档 @@ -85,6 +85,24 @@ func IsImgType(ext string) bool { return ok } +// IsDocType 判断是否为文档 +func IsDocType(ext string) bool { + _, ok := docType[ext] + return ok +} + +// IsAudioType 判断是否为音频 +func IsAudioType(ext string) bool { + _, ok := audioType[ext] + return ok +} + +// IsVideoType 判断是否为视频 +func IsVideoType(ext string) bool { + _, ok := videoType[ext] + return ok +} + // GetImgType 获取图片类型 func GetImgType(ext string) (string, error) { if mime, ok := imgType[ext]; ok { diff --git a/server/internal/library/storager/model.go b/server/internal/library/storager/model.go new file mode 100644 index 0000000..a557314 --- /dev/null +++ b/server/internal/library/storager/model.go @@ -0,0 +1,12 @@ +package storager + +// FileMeta 文件元数据 +type FileMeta struct { + Filename string // 文件名称 + Size int64 // 文件大小 + Kind string // 文件所属分类 + MetaType string // 文件类型 + NaiveType string // NaiveUI类型 + Ext string // 文件后缀名 + Md5 string // 文件hash +} diff --git a/server/internal/library/storager/upload.go b/server/internal/library/storager/upload.go new file mode 100644 index 0000000..d3b1bfe --- /dev/null +++ b/server/internal/library/storager/upload.go @@ -0,0 +1,228 @@ +package storager + +import ( + "context" + "fmt" + "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/os/gtime" + "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/util/grand" + "hotgo/internal/consts" + "hotgo/internal/library/contexts" + "hotgo/internal/model/entity" + "hotgo/utility/encrypt" + "hotgo/utility/url" + "hotgo/utility/validate" + "strconv" + "strings" +) + +// UploadDrive 存储驱动 +type UploadDrive interface { + // Upload 上传 + Upload(ctx context.Context, file *ghttp.UploadFile) (fullPath string, err error) +} + +// New 初始化存储驱动 +func New(name ...string) UploadDrive { + var ( + driveType = consts.UploadDriveLocal + drive UploadDrive + ) + + if len(name) > 0 && name[0] != "" { + driveType = name[0] + } + + switch driveType { + case consts.UploadDriveLocal: + drive = &LocalDrive{} + case consts.UploadDriveUCloud: + drive = &UCloudDrive{} + case consts.UploadDriveCos: + drive = &CosDrive{} + case consts.UploadDriveOss: + drive = &OssDrive{} + case consts.UploadDriveQiNiu: + drive = &QiNiuDrive{} + default: + panic(fmt.Sprintf("暂不支持的存储驱动:%v", driveType)) + } + return drive +} + +// DoUpload 上传入口 +func DoUpload(ctx context.Context, file *ghttp.UploadFile, typ int) (result *entity.SysAttachment, err error) { + if file == nil { + err = gerror.New("文件必须!") + return + } + + meta, err := GetFileMeta(file) + if err != nil { + return + } + + if _, err = GetFileType(meta.Ext); err != nil { + return + } + + switch typ { + case consts.UploadTypeFile: + if config.FileSize > 0 && meta.Size > config.FileSize*1024*1024 { + err = gerror.Newf("文件大小不能超过%vMB", config.FileSize) + return + } + case consts.UploadTypeImage: + if !IsImgType(meta.Ext) { + err = gerror.New("上传的文件不是图片") + return + } + if config.ImageSize > 0 && meta.Size > config.ImageSize*1024*1024 { + err = gerror.Newf("图片大小不能超过%vMB", config.ImageSize) + return + } + case consts.UploadTypeDoc: + if !IsDocType(meta.Ext) { + err = gerror.New("上传的文件不是文档") + return + } + case consts.UploadTypeAudio: + if !IsAudioType(meta.Ext) { + err = gerror.New("上传的文件不是音频") + return + } + case consts.UploadTypeVideo: + if !IsVideoType(meta.Ext) { + err = gerror.New("上传的文件不是视频") + return + } + default: + err = gerror.Newf("无效的上传类型:%v", typ) + return + } + + result, err = hasFile(ctx, meta.Md5) + if err != nil { + return + } + + if result != nil { + return + } + + // 上传到驱动 + fullPath, err := New(config.Drive).Upload(ctx, file) + if err != nil { + return + } + // 写入附件记录 + return write(ctx, meta, fullPath) +} + +// LastUrl 根据驱动获取最终文件访问地址 +func LastUrl(ctx context.Context, fullPath, drive string) string { + if validate.IsURL(fullPath) { + return fullPath + } + + switch drive { + case consts.UploadDriveLocal: + return url.GetAddr(ctx) + "/" + fullPath + case consts.UploadDriveUCloud: + return config.UCloudEndpoint + "/" + fullPath + case consts.UploadDriveCos: + return config.CosBucketURL + "/" + fullPath + case consts.UploadDriveOss: + return config.OssBucketURL + "/" + fullPath + case consts.UploadDriveQiNiu: + return config.QiNiuDomain + "/" + fullPath + default: + return fullPath + } +} + +// GetFileMeta 获取上传文件元数据 +func GetFileMeta(file *ghttp.UploadFile) (meta *FileMeta, err error) { + meta = new(FileMeta) + meta.Filename = file.Filename + meta.Size = file.Size + meta.Ext = Ext(file.Filename) + meta.Kind = GetFileKind(meta.Ext) + meta.MetaType, err = GetFileType(meta.Ext) + if err != nil { + return + } + + // 兼容naiveUI + naiveType := "text/plain" + if IsImgType(Ext(file.Filename)) { + naiveType = "" + } + meta.NaiveType = naiveType + + // 文件hash + b, err := UploadFileByte(file) + if err != nil { + return + } + meta.Md5 = encrypt.Md5ToString(gconv.String(encrypt.Hash32(b))) + return +} + +// GenFullPath 根据目录和文件类型生成一个绝对地址 +func GenFullPath(basePath, ext string) string { + fileName := strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6) + fileName = fileName + ext + return basePath + gtime.Date() + "/" + strings.ToLower(fileName) +} + +// write 写入附件记录 +func write(ctx context.Context, meta *FileMeta, fullPath string) (models *entity.SysAttachment, err error) { + models = &entity.SysAttachment{ + Id: 0, + AppId: contexts.GetModule(ctx), + MemberId: contexts.GetUserId(ctx), + Drive: config.Drive, + Size: meta.Size, + Path: fullPath, + FileUrl: fullPath, + Name: meta.Filename, + Kind: meta.Kind, + MetaType: meta.MetaType, + NaiveType: meta.NaiveType, + Ext: meta.Ext, + Md5: meta.Md5, + Status: consts.StatusEnabled, + } + + id, err := GetModel(ctx).Data(models).InsertAndGetId() + if err != nil { + return + } + models.Id = id + return +} + +// hasFile 检查附件是否存在 +func hasFile(ctx context.Context, md5 string) (res *entity.SysAttachment, err error) { + if err = GetModel(ctx).Where("md5", md5).Scan(&res); err != nil { + err = gerror.Wrap(err, "检查文件hash时出现错误") + return + } + + if res == nil { + return + } + + // 只有在上传时才会检查md5值,如果附件存在则更新最后上传时间,保证上传列表更新显示在最前面 + if res.Id > 0 { + _, _ = GetModel(ctx).WherePri(res.Id).Data(g.Map{ + "status": consts.StatusEnabled, + "updated_at": gtime.Now(), + }).Update() + } + return +} diff --git a/server/internal/library/storager/upload_cos.go b/server/internal/library/storager/upload_cos.go new file mode 100644 index 0000000..d008dd8 --- /dev/null +++ b/server/internal/library/storager/upload_cos.go @@ -0,0 +1,42 @@ +package storager + +import ( + "context" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gfile" + "github.com/tencentyun/cos-go-sdk-v5" + "net/http" + "net/url" +) + +// CosDrive 腾讯云cos驱动 +type CosDrive struct { +} + +// Upload 上传到腾讯云cos对象存储 +func (d *CosDrive) Upload(ctx context.Context, file *ghttp.UploadFile) (fullPath string, err error) { + if config.CosPath == "" { + err = gerror.New("COS存储驱动必须配置存储路径!") + return + } + + // 流式上传本地小文件 + f2, err := file.Open() + defer func() { _ = f2.Close() }() + if err != nil { + return + } + + URL, _ := url.Parse(config.CosBucketURL) + client := cos.NewClient(&cos.BaseURL{BucketURL: URL}, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: config.CosSecretId, + SecretKey: config.CosSecretKey, + }, + }) + + fullPath = GenFullPath(config.UCloudPath, gfile.Ext(file.Filename)) + _, err = client.Object.Put(ctx, fullPath, f2, nil) + return +} diff --git a/server/internal/library/storager/upload_local.go b/server/internal/library/storager/upload_local.go new file mode 100644 index 0000000..8c57022 --- /dev/null +++ b/server/internal/library/storager/upload_local.go @@ -0,0 +1,42 @@ +package storager + +import ( + "context" + "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/os/gtime" + "strings" +) + +// LocalDrive 本地驱动 +type LocalDrive struct { +} + +// Upload 上传到本地 +func (d *LocalDrive) Upload(ctx context.Context, file *ghttp.UploadFile) (fullPath string, err error) { + var ( + sp = g.Cfg().MustGet(ctx, "server.serverRoot") + nowDate = gtime.Date() + ) + + if sp.IsEmpty() { + err = gerror.New("本地上传驱动必须配置静态路径!") + return + } + + if config.LocalPath == "" { + err = gerror.New("本地上传驱动必须配置本地存储路径!") + return + } + + // 包含静态文件夹的路径 + fullDirPath := strings.Trim(sp.String(), "/") + "/" + config.LocalPath + nowDate + fileName, err := file.Save(fullDirPath, true) + if err != nil { + return + } + // 不含静态文件夹的路径 + fullPath = config.LocalPath + nowDate + "/" + fileName + return +} diff --git a/server/internal/library/storager/upload_oss.go b/server/internal/library/storager/upload_oss.go new file mode 100644 index 0000000..441d395 --- /dev/null +++ b/server/internal/library/storager/upload_oss.go @@ -0,0 +1,42 @@ +package storager + +import ( + "context" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gfile" +) + +// OssDrive 阿里云oss驱动 +type OssDrive struct { +} + +// Upload 上传到阿里云oss +func (d *OssDrive) Upload(ctx context.Context, file *ghttp.UploadFile) (fullPath string, err error) { + if config.OssPath == "" { + err = gerror.New("OSS存储驱动必须配置存储路径!") + return + } + + // 流式上传本地小文件 + f2, err := file.Open() + defer func() { _ = f2.Close() }() + if err != nil { + return + } + + client, err := oss.New(config.OssEndpoint, config.OssSecretId, config.OssSecretKey) + if err != nil { + return + } + + bucket, err := client.Bucket(config.OssBucket) + if err != nil { + return + } + + fullPath = GenFullPath(config.UCloudPath, gfile.Ext(file.Filename)) + err = bucket.PutObject(fullPath, f2) + return +} diff --git a/server/internal/library/storager/upload_qiniu.go b/server/internal/library/storager/upload_qiniu.go new file mode 100644 index 0000000..c4ade73 --- /dev/null +++ b/server/internal/library/storager/upload_qiniu.go @@ -0,0 +1,52 @@ +package storager + +import ( + "context" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gfile" + "github.com/qiniu/go-sdk/v7/auth/qbox" + "github.com/qiniu/go-sdk/v7/storage" +) + +// QiNiuDrive 七牛云对象存储驱动 +type QiNiuDrive struct { +} + +// Upload 上传到七牛云对象存储 +func (d *QiNiuDrive) Upload(ctx context.Context, file *ghttp.UploadFile) (fullPath string, err error) { + if config.QiNiuPath == "" { + err = gerror.New("七牛云存储驱动必须配置存储路径!") + return + } + + // 流式上传本地小文件 + f2, err := file.Open() + defer func() { _ = f2.Close() }() + if err != nil { + return + } + + putPolicy := storage.PutPolicy{ + Scope: config.QiNiuBucket, + } + token := putPolicy.UploadToken(qbox.NewMac(config.QiNiuAccessKey, config.QiNiuSecretKey)) + + cfg := storage.Config{} + + // 是否使用https域名 + cfg.UseHTTPS = true + + // 上传是否使用CDN上传加速 + cfg.UseCdnDomains = false + + // 空间对应的机房 + cfg.Region, err = storage.GetRegion(config.QiNiuAccessKey, config.QiNiuBucket) + if err != nil { + return + } + + fullPath = GenFullPath(config.UCloudPath, gfile.Ext(file.Filename)) + err = storage.NewFormUploader(&cfg).Put(ctx, &storage.PutRet{}, token, fullPath, f2, file.Size, &storage.PutExtra{}) + return +} diff --git a/server/internal/library/storager/upload_ucloud.go b/server/internal/library/storager/upload_ucloud.go new file mode 100644 index 0000000..e91ebe7 --- /dev/null +++ b/server/internal/library/storager/upload_ucloud.go @@ -0,0 +1,45 @@ +package storager + +import ( + "context" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gfile" + upload "github.com/ufilesdk-dev/ufile-gosdk" +) + +// UCloudDrive UCloud对象存储驱动 +type UCloudDrive struct { +} + +// Upload 上传到UCloud对象存储 +func (d *UCloudDrive) Upload(ctx context.Context, file *ghttp.UploadFile) (fullPath string, err error) { + if config.UCloudPath == "" { + err = gerror.New("UCloud存储驱动必须配置存储路径!") + return + } + + client, err := upload.NewFileRequest(&upload.Config{ + PublicKey: config.UCloudPublicKey, + PrivateKey: config.UCloudPrivateKey, + BucketHost: config.UCloudBucketHost, + BucketName: config.UCloudBucketName, + FileHost: config.UCloudFileHost, + Endpoint: config.UCloudEndpoint, + VerifyUploadMD5: false, + }, nil) + if err != nil { + return + } + + // 流式上传本地小文件 + f2, err := file.Open() + defer func() { _ = f2.Close() }() + if err != nil { + return + } + + fullPath = GenFullPath(config.UCloudPath, gfile.Ext(file.Filename)) + err = client.IOPut(f2, fullPath, "") + return +} diff --git a/server/internal/logic/admin/dept.go b/server/internal/logic/admin/dept.go index 0ed5935..a663212 100644 --- a/server/internal/logic/admin/dept.go +++ b/server/internal/logic/admin/dept.go @@ -223,8 +223,8 @@ func (s *sAdminDept) List(ctx context.Context, in adminin.DeptListInp) (res *adm } if len(ids) > 0 { - ids = convert.UniqueSliceInt64(ids) - pids = convert.UniqueSliceInt64(pids) + ids = convert.UniqueSlice(ids) + pids = convert.UniqueSlice(pids) mod = mod.Wheref(`id in (?) or pid in (?)`, ids, pids) } diff --git a/server/internal/logic/admin/menu.go b/server/internal/logic/admin/menu.go index 9ee997a..a0884fd 100644 --- a/server/internal/logic/admin/menu.go +++ b/server/internal/logic/admin/menu.go @@ -307,6 +307,6 @@ func (s *sAdminMenu) LoginPermissions(ctx context.Context, memberId int64) (list } } - lists = convert.UniqueSliceString(lists) + lists = convert.UniqueSlice(lists) return } diff --git a/server/internal/logic/admin/notice.go b/server/internal/logic/admin/notice.go index 2b03f93..32ab5d8 100644 --- a/server/internal/logic/admin/notice.go +++ b/server/internal/logic/admin/notice.go @@ -124,7 +124,7 @@ func (s *sAdminNotice) Status(ctx context.Context, in adminin.NoticeStatusInp) ( return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } @@ -322,16 +322,14 @@ func (s *sAdminNotice) UnreadCount(ctx context.Context, in adminin.NoticeUnreadC // messageIds 获取我的消息所有的消息ID func (s *sAdminNotice) messageIds(ctx context.Context, memberId int64) (ids []int64, err error) { - mod := s.Model(ctx, &handler.Option{FilterAuth: false}). + array, err := s.Model(ctx, &handler.Option{FilterAuth: false}). Fields("id"). Where("status", consts.StatusEnabled). Where("(`type` IN(?) OR (`type` = ? and JSON_CONTAINS(`receiver`,'"+gconv.String(memberId)+"')))", []int{consts.NoticeTypeNotify, consts.NoticeTypeNotice}, consts.NoticeTypeLetter, - ) - - array, err := mod.Array() + ).Array() if err != nil { - return nil, err + return } for _, v := range array { @@ -351,14 +349,15 @@ func (s *sAdminNotice) UpRead(ctx context.Context, in adminin.NoticeUpReadInp) ( err = gerror.New("获取用户信息失败!") return } + if err = dao.AdminNotice.Ctx(ctx).Where("id", in.Id).Scan(&data); err != nil { err = gerror.Wrap(err, consts.ErrorORM) - return err + return } + if data == nil { return gerror.New("公告不存在") } - return s.updatedReadClicks(ctx, in.Id, memberId) } @@ -408,13 +407,12 @@ func (s *sAdminNotice) ReadAll(ctx context.Context, in adminin.NoticeReadAllInp) } for _, messageId := range messageIds { - if !validate.InSliceInt64(readIds, messageId) { + if !validate.InSlice(readIds, messageId) { if err = s.updatedReadClicks(ctx, messageId, memberId); err != nil { return } } } - return } @@ -435,7 +433,7 @@ func (s *sAdminNotice) updatedReadClicks(ctx context.Context, noticeId, memberId _, err = dao.AdminNoticeRead.Ctx(ctx).Data(entity.AdminNoticeRead{NoticeId: noticeId, MemberId: memberId}).Insert() return } - _, err = dao.AdminNoticeRead.Ctx(ctx).Where(dao.AdminNoticeRead.Columns().Id, models.Id).Increment("clicks", 1) + _, err = dao.AdminNoticeRead.Ctx(ctx).Where(dao.AdminNoticeRead.Columns().Id, models.Id).Increment(dao.AdminNoticeRead.Columns().Clicks, 1) return } diff --git a/server/internal/logic/admin/order.go b/server/internal/logic/admin/order.go index 78fba2a..5b5262d 100644 --- a/server/internal/logic/admin/order.go +++ b/server/internal/logic/admin/order.go @@ -382,7 +382,7 @@ func (s *sAdminOrder) Status(ctx context.Context, in adminin.OrderStatusInp) (er return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/logic/admin/post.go b/server/internal/logic/admin/post.go index 205003c..df4e0d0 100644 --- a/server/internal/logic/admin/post.go +++ b/server/internal/logic/admin/post.go @@ -203,7 +203,7 @@ func (s *sAdminPost) Status(ctx context.Context, in adminin.PostStatusInp) (err return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/logic/admin/role.go b/server/internal/logic/admin/role.go index ee54679..5221eb3 100644 --- a/server/internal/logic/admin/role.go +++ b/server/internal/logic/admin/role.go @@ -57,7 +57,6 @@ func (s *sAdminRole) Verify(ctx context.Context, path, method string) bool { g.Log().Infof(ctx, "admin Verify Enforce err:%+v", err) return false } - return ok } @@ -102,7 +101,6 @@ func (s *sAdminRole) GetName(ctx context.Context, id int64) (name string, err er err = gerror.Wrap(err, consts.ErrorORM) return } - return r.String(), nil } @@ -148,7 +146,7 @@ func (s *sAdminRole) UpdatePermissions(ctx context.Context, in adminin.UpdatePer } // 去重 - in.MenuIds = convert.UniqueSliceInt64(in.MenuIds) + in.MenuIds = convert.UniqueSlice(in.MenuIds) list := make(g.List, 0, len(in.MenuIds)) for _, v := range in.MenuIds { @@ -169,7 +167,6 @@ func (s *sAdminRole) UpdatePermissions(ctx context.Context, in adminin.UpdatePer if err != nil { return } - return casbin.Refresh(ctx) } @@ -296,19 +293,18 @@ func (s *sAdminRole) DataScopeEdit(ctx context.Context, in *adminin.DataScopeEdi return gerror.New("超管角色拥有全部权限,无需修改!") } - if in.DataScope == consts.RoleDataDeptCustom && len(convert.UniqueSliceInt64(in.CustomDept)) == 0 { + if in.DataScope == consts.RoleDataDeptCustom && len(convert.UniqueSlice(in.CustomDept)) == 0 { return gerror.New("自定义权限必须配置自定义部门!") } models.DataScope = in.DataScope - models.CustomDept = gjson.New(convert.UniqueSliceInt64(in.CustomDept)) + models.CustomDept = gjson.New(convert.UniqueSlice(in.CustomDept)) _, err = dao.AdminRole.Ctx(ctx). Fields(dao.AdminRole.Columns().DataScope, dao.AdminRole.Columns().CustomDept). Where("id", in.Id). Data(models). Update() - return } diff --git a/server/internal/logic/common/upload.go b/server/internal/logic/common/upload.go index 763d549..3be90d1 100644 --- a/server/internal/logic/common/upload.go +++ b/server/internal/logic/common/upload.go @@ -7,33 +7,12 @@ package common import ( "context" - "github.com/aliyun/aliyun-oss-go-sdk/oss" - "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/os/gfile" - "github.com/gogf/gf/v2/os/gtime" - "github.com/gogf/gf/v2/util/gconv" - "github.com/gogf/gf/v2/util/grand" - "github.com/qiniu/go-sdk/v7/auth/qbox" - "github.com/qiniu/go-sdk/v7/storage" - "github.com/tencentyun/cos-go-sdk-v5" - ufile "github.com/ufilesdk-dev/ufile-gosdk" "hotgo/internal/consts" - "hotgo/internal/dao" - "hotgo/internal/model" + "hotgo/internal/library/storager" "hotgo/internal/model/input/sysin" "hotgo/internal/service" - "hotgo/utility/encrypt" - f "hotgo/utility/file" "hotgo/utility/format" - utilityurl "hotgo/utility/url" - "hotgo/utility/validate" - "net/http" - "net/url" - "strconv" - "strings" - "time" ) type sCommonUpload struct{} @@ -47,391 +26,31 @@ func init() { } // UploadFile 上传文件 -func (s *sCommonUpload) UploadFile(ctx context.Context, file *ghttp.UploadFile) (result *sysin.AttachmentListModel, err error) { - if file == nil { - err = gerror.New("文件必须!") - return - } - - meta, err := s.fileMeta(file) +func (s *sCommonUpload) UploadFile(ctx context.Context, file *ghttp.UploadFile) (res *sysin.AttachmentListModel, err error) { + attachment, err := storager.DoUpload(ctx, file, consts.UploadTypeFile) if err != nil { return } - if _, err = f.GetFileType(meta.Ext); err != nil { - return - } - - result, err = s.HasFile(ctx, meta.Md5) - if err != nil { - return - } - - if result != nil { - return - } - - conf, err := service.SysConfig().GetUpload(ctx) - if err != nil { - return - } - - switch conf.Drive { - case consts.UploadDriveLocal: - return s.UploadLocal(ctx, conf, file, meta) - case consts.UploadDriveUCloud: - return s.UploadUCloud(ctx, conf, file, meta) - case consts.UploadDriveCos: - return s.UploadCOS(ctx, conf, file, meta) - case consts.UploadDriveOss: - return s.UploadOSS(ctx, conf, file, meta) - case consts.UploadDriveQiNiu: - return s.UploadQiNiu(ctx, conf, file, meta) - default: - return nil, gerror.Newf("暂不支持上传驱动:%v", conf.Drive) + attachment.FileUrl = storager.LastUrl(ctx, attachment.FileUrl, attachment.Drive) + res = &sysin.AttachmentListModel{ + SysAttachment: *attachment, + SizeFormat: format.FileSize(attachment.Size), } + return } // UploadImage 上传图片 -func (s *sCommonUpload) UploadImage(ctx context.Context, file *ghttp.UploadFile) (result *sysin.AttachmentListModel, err error) { - if file == nil { - err = gerror.New("文件必须!") - return - } - - meta, err := s.fileMeta(file) +func (s *sCommonUpload) UploadImage(ctx context.Context, file *ghttp.UploadFile) (res *sysin.AttachmentListModel, err error) { + attachment, err := storager.DoUpload(ctx, file, consts.UploadTypeImage) if err != nil { return } - if !f.IsImgType(meta.Ext) { - err = gerror.New("上传的文件不是图片") - return - } - - if meta.Size > 2*1024*1024 { - err = gerror.New("图片大小不能超过2MB") - return - } - - result, err = s.HasFile(ctx, meta.Md5) - if err != nil { - return - } - - if result != nil { - return - } - - conf, err := service.SysConfig().GetUpload(ctx) - if err != nil { - return - } - - switch conf.Drive { - case consts.UploadDriveLocal: - return s.UploadLocal(ctx, conf, file, meta) - case consts.UploadDriveUCloud: - return s.UploadUCloud(ctx, conf, file, meta) - case consts.UploadDriveCos: - return s.UploadCOS(ctx, conf, file, meta) - case consts.UploadDriveOss: - return s.UploadOSS(ctx, conf, file, meta) - case consts.UploadDriveQiNiu: - return s.UploadQiNiu(ctx, conf, file, meta) - default: - err = gerror.Newf("暂不支持上传驱动:%v", conf.Drive) - return - } -} - -// UploadLocal 上传本地 -func (s *sCommonUpload) UploadLocal(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) { - var ( - value = g.Cfg().MustGet(ctx, "server.serverRoot") - nowDate = time.Now().Format("2006-01-02") - ) - - if value.IsEmpty() { - err = gerror.New("本地上传驱动必须配置静态路径!") - return - } - - if conf.LocalPath == "" { - err = gerror.New("本地上传驱动必须配置本地存储路径!") - return - } - - // 包含静态文件夹的路径 - fullDirPath := strings.Trim(value.String(), "/") + "/" + conf.LocalPath + nowDate - fileName, err := file.Save(fullDirPath, true) - if err != nil { - return - } - // 不含静态文件夹的路径 - fullPath := conf.LocalPath + nowDate + "/" + fileName - - attachment, err := service.SysAttachment().Add(ctx, meta, fullPath, consts.UploadDriveLocal) - if err != nil { - return - } - - attachment.FileUrl = s.LastUrl(ctx, conf, attachment.FileUrl, attachment.Drive) - result = &sysin.AttachmentListModel{ + attachment.FileUrl = storager.LastUrl(ctx, attachment.FileUrl, attachment.Drive) + res = &sysin.AttachmentListModel{ SysAttachment: *attachment, SizeFormat: format.FileSize(attachment.Size), } return } - -// UploadUCloud 上传UCloud对象存储 -func (s *sCommonUpload) UploadUCloud(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) { - if conf.UCloudPath == "" { - err = gerror.New("UCloud存储驱动必须配置存储路径!") - return - } - - nowDate := time.Now().Format("2006-01-02") - fileName := strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) - fileName = fileName + gfile.Ext(file.Filename) - fullPath := conf.UCloudPath + nowDate + "/" + fileName - config := &ufile.Config{ - PublicKey: conf.UCloudPublicKey, - PrivateKey: conf.UCloudPrivateKey, - BucketHost: conf.UCloudBucketHost, - BucketName: conf.UCloudBucketName, - FileHost: conf.UCloudFileHost, - Endpoint: conf.UCloudEndpoint, - VerifyUploadMD5: false, - } - - req, err := ufile.NewFileRequest(config, nil) - if err != nil { - return - } - - // 流式上传本地小文件 - f2, err := file.Open() - defer func() { _ = f2.Close() }() - if err != nil { - return - } - - if err = req.IOPut(f2, fullPath, ""); err != nil { - return - } - - attachment, err := service.SysAttachment().Add(ctx, meta, fullPath, consts.UploadDriveUCloud) - if err != nil { - return - } - - attachment.FileUrl = s.LastUrl(ctx, conf, attachment.FileUrl, attachment.Drive) - result = &sysin.AttachmentListModel{ - SysAttachment: *attachment, - SizeFormat: format.FileSize(attachment.Size), - } - return -} - -// UploadCOS 上传腾讯云对象存储 -func (s *sCommonUpload) UploadCOS(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) { - if conf.CosPath == "" { - err = gerror.New("COS存储驱动必须配置存储路径!") - return - } - - nowDate := time.Now().Format("2006-01-02") - fileName := strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) - fileName = fileName + gfile.Ext(file.Filename) - fullPath := conf.CosPath + nowDate + "/" + fileName - - // 流式上传本地小文件 - f2, err := file.Open() - defer func() { _ = f2.Close() }() - if err != nil { - return - } - - u, _ := url.Parse(conf.CosBucketURL) - b := &cos.BaseURL{BucketURL: u} - c := cos.NewClient(b, &http.Client{ - Transport: &cos.AuthorizationTransport{ - SecretID: conf.CosSecretId, - SecretKey: conf.CosSecretKey, - }, - }) - - if _, err = c.Object.Put(ctx, fullPath, f2, nil); err != nil { - return - } - - attachment, err := service.SysAttachment().Add(ctx, meta, fullPath, consts.UploadDriveCos) - if err != nil { - return - } - - attachment.FileUrl = s.LastUrl(ctx, conf, attachment.FileUrl, attachment.Drive) - result = &sysin.AttachmentListModel{ - SysAttachment: *attachment, - SizeFormat: format.FileSize(attachment.Size), - } - return -} - -// UploadOSS 上传阿里云云对象存储 -func (s *sCommonUpload) UploadOSS(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) { - if conf.OssPath == "" { - err = gerror.New("OSS存储驱动必须配置存储路径!") - return - } - - nowDate := time.Now().Format("2006-01-02") - fileName := strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) - fileName = fileName + gfile.Ext(file.Filename) - fullPath := conf.OssPath + nowDate + "/" + fileName - - // 流式上传本地小文件 - f2, err := file.Open() - defer func() { _ = f2.Close() }() - if err != nil { - return - } - - client, err := oss.New(conf.OssEndpoint, conf.OssSecretId, conf.OssSecretKey) - if err != nil { - return - } - - bucket, err := client.Bucket(conf.OssBucket) - if err != nil { - return - } - - if err = bucket.PutObject(fullPath, f2); err != nil { - return - } - - attachment, err := service.SysAttachment().Add(ctx, meta, fullPath, consts.UploadDriveOss) - if err != nil { - return - } - - attachment.FileUrl = s.LastUrl(ctx, conf, attachment.FileUrl, attachment.Drive) - result = &sysin.AttachmentListModel{ - SysAttachment: *attachment, - SizeFormat: format.FileSize(attachment.Size), - } - return -} - -// UploadQiNiu 上传七牛云对象存储 -func (s *sCommonUpload) UploadQiNiu(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) { - if conf.QiNiuPath == "" { - err = gerror.New("七牛云存储驱动必须配置存储路径!") - return - } - - nowDate := time.Now().Format("2006-01-02") - fileName := strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) - fileName = fileName + gfile.Ext(file.Filename) - fullPath := conf.QiNiuPath + nowDate + "/" + fileName - - // 流式上传本地小文件 - f2, err := file.Open() - defer func() { _ = f2.Close() }() - if err != nil { - return - } - - putPolicy := storage.PutPolicy{ - Scope: conf.QiNiuBucket, - } - token := putPolicy.UploadToken(qbox.NewMac(conf.QiNiuAccessKey, conf.QiNiuSecretKey)) - - cfg := storage.Config{} - - // 是否使用https域名 - cfg.UseHTTPS = true - - // 上传是否使用CDN上传加速 - cfg.UseCdnDomains = false - - // 空间对应的机房 - cfg.Region, err = storage.GetRegion(conf.QiNiuAccessKey, conf.QiNiuBucket) - if err != nil { - return - } - - if err = storage.NewFormUploader(&cfg).Put(ctx, &storage.PutRet{}, token, fullPath, f2, file.Size, &storage.PutExtra{}); err != nil { - return - } - - attachment, err := service.SysAttachment().Add(ctx, meta, fullPath, consts.UploadDriveQiNiu) - if err != nil { - return - } - - attachment.FileUrl = s.LastUrl(ctx, conf, attachment.FileUrl, attachment.Drive) - result = &sysin.AttachmentListModel{ - SysAttachment: *attachment, - SizeFormat: format.FileSize(attachment.Size), - } - return -} - -// LastUrl 根据驱动获取最终文件访问地址 -func (s *sCommonUpload) LastUrl(ctx context.Context, conf *model.UploadConfig, fullPath, drive string) string { - if validate.IsURL(fullPath) { - return fullPath - } - - switch drive { - case consts.UploadDriveLocal: - return utilityurl.GetAddr(ctx) + "/" + fullPath - case consts.UploadDriveUCloud: - return conf.UCloudEndpoint + "/" + fullPath - case consts.UploadDriveCos: - return conf.CosBucketURL + "/" + fullPath - case consts.UploadDriveOss: - return conf.OssBucketURL + "/" + fullPath - case consts.UploadDriveQiNiu: - return conf.QiNiuDomain + "/" + fullPath - default: - return fullPath - } -} - -// HasFile 文件是否存在 -func (s *sCommonUpload) HasFile(ctx context.Context, md5 string) (res *sysin.AttachmentListModel, err error) { - res, err = dao.SysAttachment.GetMd5File(ctx, md5) - return -} - -// fileMeta 上传文件元数据 -func (s *sCommonUpload) fileMeta(file *ghttp.UploadFile) (meta *sysin.UploadFileMeta, err error) { - meta = new(sysin.UploadFileMeta) - meta.Filename = file.Filename - meta.Size = file.Size - meta.Ext = f.Ext(file.Filename) - meta.Kind = f.GetFileKind(meta.Ext) - meta.MetaType, err = f.GetFileType(meta.Ext) - if err != nil { - return - } - - // 兼容naiveUI - naiveType := "text/plain" - if f.IsImgType(f.Ext(file.Filename)) { - naiveType = "" - } - meta.NaiveType = naiveType - - // 文件hash - b, err := f.UploadFileByte(file) - if err != nil { - return - } - meta.Md5 = encrypt.Md5ToString(gconv.String(encrypt.Hash32(b))) - return -} diff --git a/server/internal/logic/middleware/admin_auth.go b/server/internal/logic/middleware/admin_auth.go index 38daacd..ee522b6 100644 --- a/server/internal/logic/middleware/admin_auth.go +++ b/server/internal/logic/middleware/admin_auth.go @@ -32,7 +32,6 @@ func (s *sMiddleware) AdminAuth(r *ghttp.Request) { // 将用户信息传递到上下文中 if err := deliverUserContext(r); err != nil { - g.Log().Warningf(ctx, "deliverUserContext err:%+v", err) response.JsonExit(r, gcode.CodeNotAuthorized.Code(), err.Error()) return } diff --git a/server/internal/logic/pay/pay.go b/server/internal/logic/pay/pay.go index 35b8462..c4a24c8 100644 --- a/server/internal/logic/pay/pay.go +++ b/server/internal/logic/pay/pay.go @@ -138,7 +138,7 @@ func (s *sPay) Status(ctx context.Context, in payin.PayStatusInp) (err error) { return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/logic/sys/addons.go b/server/internal/logic/sys/addons.go index b789207..74d2c3c 100644 --- a/server/internal/logic/sys/addons.go +++ b/server/internal/logic/sys/addons.go @@ -90,7 +90,6 @@ func (s *sSysAddons) List(ctx context.Context, in sysin.AddonsListInp) (list []* } totalCount = len(sks) - return } @@ -129,7 +128,6 @@ func (s *sSysAddons) Build(ctx context.Context, in sysin.AddonsBuildInp) (err er err = gerror.New("没有找到有效的生成或插件配置,请检查配置文件是否正常") return } - return addons.Build(ctx, in.Skeleton, genConfig.Addon) } diff --git a/server/internal/logic/sys/addons_config.go b/server/internal/logic/sys/addons_config.go index ead37d6..edad31d 100644 --- a/server/internal/logic/sys/addons_config.go +++ b/server/internal/logic/sys/addons_config.go @@ -54,8 +54,8 @@ func (s *sSysAddonsConfig) GetConfigByGroup(ctx context.Context, in sysin.GetAdd Scan(&models); err != nil { return nil, err } - isDemo := g.Cfg().MustGet(ctx, "hotgo.isDemo", false) + isDemo := g.Cfg().MustGet(ctx, "hotgo.isDemo", false) if len(models) > 0 { res = new(sysin.GetAddonsConfigModel) res.List = make(g.Map, len(models)) @@ -71,7 +71,6 @@ func (s *sSysAddonsConfig) GetConfigByGroup(ctx context.Context, in sysin.GetAdd } } } - return } @@ -105,10 +104,10 @@ func (s *sSysAddonsConfig) UpdateConfigByGroup(ctx context.Context, in sysin.Upd Where("addon_name", in.AddonName). Where("group", in.Group). Scan(&models); err != nil { - return err + return } - err = dao.SysAddonsConfig.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { + err = dao.SysAddonsConfig.Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) { for k, v := range in.List { row := s.getConfigByKey(k, models) // 新增 @@ -130,20 +129,15 @@ func (s *sSysAddonsConfig) UpdateConfigByGroup(ctx context.Context, in sysin.Upd } // 更新 - _, err = dao.SysAddonsConfig.Ctx(ctx).Where("id", row.Id).Data(g.Map{"value": v, "updated_at": gtime.Now()}).Update() - if err != nil { + if _, err = dao.SysAddonsConfig.Ctx(ctx).Where("id", row.Id).Data(g.Map{"value": v, "updated_at": gtime.Now()}).Update(); err != nil { err = gerror.Wrap(err, consts.ErrorORM) - return err + return } } - return nil + return }) - if err != nil { - return err - } - - return nil + return } func (s *sSysAddonsConfig) getConfigByKey(key string, models []*entity.SysAddonsConfig) *entity.SysAddonsConfig { @@ -156,6 +150,5 @@ func (s *sSysAddonsConfig) getConfigByKey(key string, models []*entity.SysAddons return v } } - return nil } diff --git a/server/internal/logic/sys/attachment.go b/server/internal/logic/sys/attachment.go index 3a887ec..9c76db1 100644 --- a/server/internal/logic/sys/attachment.go +++ b/server/internal/logic/sys/attachment.go @@ -9,17 +9,12 @@ import ( "context" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/os/gtime" - "hotgo/internal/consts" "hotgo/internal/dao" - "hotgo/internal/library/contexts" "hotgo/internal/library/hgorm/handler" - "hotgo/internal/model/entity" - "hotgo/internal/model/input/form" + "hotgo/internal/library/storager" "hotgo/internal/model/input/sysin" "hotgo/internal/service" "hotgo/utility/format" - "hotgo/utility/validate" ) type sSysAttachment struct{} @@ -37,92 +32,41 @@ func (s *sSysAttachment) Model(ctx context.Context, option ...*handler.Option) * return handler.Model(dao.SysAttachment.Ctx(ctx), option...) } -// Delete 删除 +// Delete 删除附件 func (s *sSysAttachment) Delete(ctx context.Context, in sysin.AttachmentDeleteInp) (err error) { - _, err = s.Model(ctx).Where("id", in.Id).Delete() + if _, err = s.Model(ctx).WherePri(in.Id).Delete(); err != nil { + err = gerror.Wrap(err, "删除附件失败,请稍后重试!") + } return } -// Edit 修改/新增 -func (s *sSysAttachment) Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error) { - if in.Name == "" { - err = gerror.New("标题不能为空") - return - } - - // 修改 - if in.Id > 0 { - _, err = s.Model(ctx).Where("id", in.Id).Data(in).Update() - return - } - - // 新增 - _, err = dao.SysAttachment.Ctx(ctx).Data(in).Insert() - return -} - -// Status 更新部门状态 -func (s *sSysAttachment) Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error) { - if in.Id <= 0 { - err = gerror.New("ID不能为空") - return - } - - if in.Status <= 0 { - err = gerror.New("状态不能为空") - return - } - - if !validate.InSliceInt(consts.StatusSlice, in.Status) { - err = gerror.New("状态不正确") - return - } - - // 修改 - _, err = s.Model(ctx).Where("id", in.Id).Data("status", in.Status).Update() - return -} - -// MaxSort 最大排序 -func (s *sSysAttachment) MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (res *sysin.AttachmentMaxSortModel, err error) { - if in.Id > 0 { - if err = s.Model(ctx).Where("id", in.Id).Order("sort desc").Scan(&res); err != nil { - return - } - } - - if res == nil { - res = new(sysin.AttachmentMaxSortModel) - } - res.Sort = form.DefaultMaxSort(ctx, res.Sort) - return -} - -// View 获取指定字典类型信息 +// View 获取附件信息 func (s *sSysAttachment) View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error) { - err = s.Model(ctx).Where("id", in.Id).Scan(&res) + if err = s.Model(ctx).WherePri(in.Id).Scan(&res); err != nil { + err = gerror.Wrap(err, "获取附件信息失败,请稍后重试!") + } return } -// List 获取列表 +// List 获取附件列表 func (s *sSysAttachment) List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error) { mod := s.Model(ctx) if in.MemberId > 0 { - mod = mod.Where("member_id", in.MemberId) + mod = mod.Where(dao.SysAttachment.Columns().MemberId, in.MemberId) } if in.Drive != "" { - mod = mod.Where("drive", in.Drive) + mod = mod.Where(dao.SysAttachment.Columns().Drive, in.Drive) } if in.Status > 0 { - mod = mod.Where("status", in.Status) + mod = mod.Where(dao.SysAttachment.Columns().Status, in.Status) } totalCount, err = mod.Count() if err != nil { - err = gerror.Wrap(err, consts.ErrorORM) + err = gerror.Wrap(err, "获取附件数据行失败!") return } @@ -130,58 +74,14 @@ func (s *sSysAttachment) List(ctx context.Context, in sysin.AttachmentListInp) ( return } - if err = mod.Page(in.Page, in.PerPage).Order("updated_at desc").Scan(&list); err != nil { - err = gerror.Wrap(err, consts.ErrorORM) - return - } - - conf, err := service.SysConfig().GetUpload(ctx) - if err != nil { + if err = mod.Page(in.Page, in.PerPage).OrderDesc(dao.SysAttachment.Columns().UpdatedAt).Scan(&list); err != nil { + err = gerror.Wrap(err, "获取附件列表失败!") return } for _, v := range list { v.SizeFormat = format.FileSize(v.Size) - v.FileUrl = service.CommonUpload().LastUrl(ctx, conf, v.FileUrl, v.Drive) + v.FileUrl = storager.LastUrl(ctx, v.FileUrl, v.Drive) } return } - -// Add 新增附件 -func (s *sSysAttachment) Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (models *entity.SysAttachment, err error) { - var ( - c = contexts.Get(ctx) - user = c.User - memberId int64 = 0 - ) - - if user != nil { - memberId = user.Id - } - - models = &entity.SysAttachment{ - Id: 0, - AppId: c.Module, - MemberId: memberId, - Drive: drive, - Size: meta.Size, - Path: fullPath, - FileUrl: fullPath, - Name: meta.Filename, - Kind: meta.Kind, - MetaType: meta.MetaType, - NaiveType: meta.NaiveType, - Ext: meta.Ext, - Md5: meta.Md5, - Status: consts.StatusEnabled, - CreatedAt: gtime.Now(), - UpdatedAt: gtime.Now(), - } - id, err := dao.SysAttachment.Ctx(ctx).Data(models).InsertAndGetId() - if err != nil { - return - } - - models.Id = id - return -} diff --git a/server/internal/logic/sys/blacklist.go b/server/internal/logic/sys/blacklist.go index 24f8ec8..d75225a 100644 --- a/server/internal/logic/sys/blacklist.go +++ b/server/internal/logic/sys/blacklist.go @@ -71,7 +71,7 @@ func (s *sSysBlacklist) Status(ctx context.Context, in sysin.BlacklistStatusInp) return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/logic/sys/config.go b/server/internal/logic/sys/config.go index e62e81d..335b6bf 100644 --- a/server/internal/logic/sys/config.go +++ b/server/internal/logic/sys/config.go @@ -16,6 +16,7 @@ import ( "hotgo/internal/consts" "hotgo/internal/dao" "hotgo/internal/library/payment" + "hotgo/internal/library/storager" "hotgo/internal/library/token" "hotgo/internal/library/wechat" "hotgo/internal/model" @@ -35,6 +36,7 @@ func init() { service.RegisterSysConfig(NewSysConfig()) } +// InitConfig 初始化一些系统启动就需要用到的配置 func (s *sSysConfig) InitConfig(ctx context.Context) { wx, err := s.GetWechat(ctx) if err != nil { @@ -48,12 +50,17 @@ func (s *sSysConfig) InitConfig(ctx context.Context) { } payment.SetConfig(pay) + upload, err := s.GetUpload(ctx) + if err != nil { + g.Log().Fatalf(ctx, "init upload conifg fail:%+v", err) + } + storager.SetConfig(upload) + tk, err := s.GetLoadToken(ctx) if err != nil { g.Log().Fatalf(ctx, "init token conifg fail:%+v", err) } token.SetConfig(tk) - } // GetLogin 获取登录配置 @@ -267,7 +274,6 @@ func (s *sSysConfig) UpdateConfigByGroup(ctx context.Context, in sysin.UpdateCon return s.syncUpdate(ctx, in) }) - return } @@ -281,7 +287,6 @@ func (s *sSysConfig) getConfigByKey(key string, models []*entity.SysConfig) *ent return v } } - return nil } @@ -298,6 +303,11 @@ func (s *sSysConfig) syncUpdate(ctx context.Context, in sysin.UpdateConfigInp) ( if err == nil { payment.SetConfig(pay) } + case "upload": + upload, err := s.GetUpload(ctx) + if err == nil { + storager.SetConfig(upload) + } } if err != nil { diff --git a/server/internal/logic/sys/cron.go b/server/internal/logic/sys/cron.go index c74f736..a1b8fee 100644 --- a/server/internal/logic/sys/cron.go +++ b/server/internal/logic/sys/cron.go @@ -106,7 +106,7 @@ func (s *sSysCron) Status(ctx context.Context, in sysin.CronStatusInp) (err erro return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/logic/sys/cron_group.go b/server/internal/logic/sys/cron_group.go index 42a9724..fbbc2a7 100644 --- a/server/internal/logic/sys/cron_group.go +++ b/server/internal/logic/sys/cron_group.go @@ -46,7 +46,6 @@ func (s *sSysCronGroup) Edit(ctx context.Context, in sysin.CronGroupEditInp) (er if _, err = dao.SysCronGroup.Ctx(ctx).Fields(sysin.CronGroupInsertFields{}).Data(in).Insert(); err != nil { err = gerror.Wrap(err, consts.ErrorORM) } - return } diff --git a/server/internal/logic/sys/curd_demo.go b/server/internal/logic/sys/curd_demo.go index e072593..1abc0ac 100644 --- a/server/internal/logic/sys/curd_demo.go +++ b/server/internal/logic/sys/curd_demo.go @@ -198,7 +198,7 @@ func (s *sSysCurdDemo) Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) ( // ... } - if !validate.InSliceString(fields, in.Key) { + if !validate.InSlice(fields, in.Key) { err = gerror.New("开关键名不在白名单") return } diff --git a/server/internal/logic/sys/dict_data.go b/server/internal/logic/sys/dict_data.go index f8a17de..756744a 100644 --- a/server/internal/logic/sys/dict_data.go +++ b/server/internal/logic/sys/dict_data.go @@ -44,7 +44,6 @@ func (s *sSysDictData) Edit(ctx context.Context, in sysin.DictDataEditInp) (err err = gerror.Wrap(err, consts.ErrorORM) return err } - return nil } diff --git a/server/internal/logic/sys/ems_log.go b/server/internal/logic/sys/ems_log.go index 1b43bc0..dc8921c 100644 --- a/server/internal/logic/sys/ems_log.go +++ b/server/internal/logic/sys/ems_log.go @@ -76,7 +76,7 @@ func (s *sSysEmsLog) Status(ctx context.Context, in sysin.EmsLogStatusInp) (err return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/logic/sys/gen_codes.go b/server/internal/logic/sys/gen_codes.go index efb3baa..967474f 100644 --- a/server/internal/logic/sys/gen_codes.go +++ b/server/internal/logic/sys/gen_codes.go @@ -110,7 +110,7 @@ func (s *sSysGenCodes) Status(ctx context.Context, in sysin.GenCodesStatusInp) ( return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } @@ -274,7 +274,6 @@ func (s *sSysGenCodes) ColumnSelect(ctx context.Context, in sysin.GenCodesColumn res[k].Name = fmt.Sprintf("%s (%s)", v.Value, v.Label) res[k].Label = res[k].Name } - return } @@ -306,6 +305,5 @@ func (s *sSysGenCodes) Build(ctx context.Context, in sysin.GenCodesBuildInp) (er _ = s.Status(ctx, sysin.GenCodesStatusInp{Id: in.Id, Status: consts.GenCodesStatusFail}) return err } - return } diff --git a/server/internal/logic/sys/log.go b/server/internal/logic/sys/log.go index a88781f..bc7bfa7 100644 --- a/server/internal/logic/sys/log.go +++ b/server/internal/logic/sys/log.go @@ -230,7 +230,6 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog { Status: consts.StatusEnabled, TakeUpTime: takeUpTime, } - return data } @@ -241,8 +240,7 @@ func (s *sSysLog) View(ctx context.Context, in sysin.LogViewInp) (res *sysin.Log return } - isDemo := g.Cfg().MustGet(ctx, "hotgo.isDemo", false) - if isDemo.Bool() { + if g.Cfg().MustGet(ctx, "hotgo.isDemo", false).Bool() { res.HeaderData = gjson.New(`{ "none": [ "` + consts.DemoTips + `" @@ -364,6 +362,5 @@ func (s *sSysLog) List(ctx context.Context, in sysin.LogListInp) (list []*sysin. } } - return } diff --git a/server/internal/logic/sys/login_log.go b/server/internal/logic/sys/login_log.go index 75a8089..ba708e7 100644 --- a/server/internal/logic/sys/login_log.go +++ b/server/internal/logic/sys/login_log.go @@ -107,7 +107,6 @@ func (s *sSysLoginLog) List(ctx context.Context, in sysin.LoginLogListInp) (list v.Os = useragent.GetOs(v.SysLogUserAgent) v.Browser = useragent.GetBrowser(v.SysLogUserAgent) } - return } diff --git a/server/internal/logic/sys/sms_log.go b/server/internal/logic/sys/sms_log.go index 53439bf..977960f 100644 --- a/server/internal/logic/sys/sms_log.go +++ b/server/internal/logic/sys/sms_log.go @@ -71,7 +71,7 @@ func (s *sSysSmsLog) Status(ctx context.Context, in sysin.SmsLogStatusInp) (err return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/logic/view/view_buildin.go b/server/internal/logic/view/view_buildin.go index 40087d9..5f7337c 100644 --- a/server/internal/logic/view/view_buildin.go +++ b/server/internal/logic/view/view_buildin.go @@ -3,11 +3,9 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package view import ( - "fmt" "hotgo/internal/consts" "github.com/gogf/gf/v2/net/ghttp" @@ -44,41 +42,6 @@ func (s *viewBuildIn) UrlPath() string { return s.httpRequest.URL.Path } -// FormatTime 格式化时间 -func (s *viewBuildIn) FormatTime(gt *gtime.Time) string { - if gt == nil { - return "" - } - n := gtime.Now().Timestamp() - t := gt.Timestamp() - - var ys int64 = 31536000 - var ds int64 = 86400 - var hs int64 = 3600 - var ms int64 = 60 - var ss int64 = 1 - - var rs string - - d := n - t - switch { - case d > ys: - rs = fmt.Sprintf("%d年前", int(d/ys)) - case d > ds: - rs = fmt.Sprintf("%d天前", int(d/ds)) - case d > hs: - rs = fmt.Sprintf("%d小时前", int(d/hs)) - case d > ms: - rs = fmt.Sprintf("%d分钟前", int(d/ms)) - case d > ss: - rs = fmt.Sprintf("%d秒前", int(d/ss)) - default: - rs = "刚刚" - } - - return rs -} - // Version 随机数 开发环境时间戳,线上为前端版本号 func (s *viewBuildIn) Version() string { var rand string diff --git a/server/internal/model/input/adminin/dept.go b/server/internal/model/input/adminin/dept.go index df2aa4a..bd71abe 100644 --- a/server/internal/model/input/adminin/dept.go +++ b/server/internal/model/input/adminin/dept.go @@ -124,7 +124,7 @@ func (in *DeptStatusInp) Filter(ctx context.Context) (err error) { return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/model/input/adminin/member.go b/server/internal/model/input/adminin/member.go index 8361c59..61906c3 100644 --- a/server/internal/model/input/adminin/member.go +++ b/server/internal/model/input/adminin/member.go @@ -225,7 +225,7 @@ func (in *MemberStatusInp) Filter(ctx context.Context) (err error) { return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/model/input/adminin/order.go b/server/internal/model/input/adminin/order.go index 618b595..6c75cf5 100644 --- a/server/internal/model/input/adminin/order.go +++ b/server/internal/model/input/adminin/order.go @@ -25,7 +25,7 @@ type OrderAcceptRefundInp struct { } func (in *OrderAcceptRefundInp) Filter(ctx context.Context) (err error) { - if !validate.InSliceInt64(consts.OrderStatusSlice, in.Status) { + if !validate.InSlice(consts.OrderStatusSlice, in.Status) { err = gerror.Newf("订单状态不正确") return } diff --git a/server/internal/model/input/sysin/attachment.go b/server/internal/model/input/sysin/attachment.go index ff4a799..11577f9 100644 --- a/server/internal/model/input/sysin/attachment.go +++ b/server/internal/model/input/sysin/attachment.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package sysin import ( @@ -11,28 +10,13 @@ import ( "hotgo/internal/model/input/form" ) -// AttachmentMaxSortInp 最大排序 -type AttachmentMaxSortInp struct { - Id int64 -} - -type AttachmentMaxSortModel struct { - Sort int -} - -// AttachmentEditInp 修改/新增字典数据 -type AttachmentEditInp struct { - entity.SysAttachment -} -type AttachmentEditModel struct{} - -// AttachmentDeleteInp 删除字典类型 +// AttachmentDeleteInp 删除附件 type AttachmentDeleteInp struct { Id interface{} } type AttachmentDeleteModel struct{} -// AttachmentViewInp 获取信息 +// AttachmentViewInp 获取附件信息 type AttachmentViewInp struct { Id int64 } @@ -41,7 +25,7 @@ type AttachmentViewModel struct { entity.SysAttachment } -// AttachmentListInp 获取列表 +// AttachmentListInp 获取附件列表 type AttachmentListInp struct { form.PageReq form.RangeDateReq @@ -54,19 +38,3 @@ type AttachmentListModel struct { entity.SysAttachment SizeFormat string `json:"sizeFormat" description:"长度"` } - -// AttachmentStatusInp 更新状态 -type AttachmentStatusInp struct { - entity.SysAttachment -} -type AttachmentStatusModel struct{} - -type UploadFileMeta struct { - Filename string - Size int64 - Kind string - MetaType string - NaiveType string - Ext string - Md5 string -} diff --git a/server/internal/model/input/sysin/cron_group.go b/server/internal/model/input/sysin/cron_group.go index 495b453..a94fbc9 100644 --- a/server/internal/model/input/sysin/cron_group.go +++ b/server/internal/model/input/sysin/cron_group.go @@ -108,7 +108,7 @@ func (in *CronGroupStatusInp) Filter(ctx context.Context) (err error) { return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/model/input/sysin/curd_demo.go b/server/internal/model/input/sysin/curd_demo.go index 0dfe53b..f203dfb 100644 --- a/server/internal/model/input/sysin/curd_demo.go +++ b/server/internal/model/input/sysin/curd_demo.go @@ -186,7 +186,7 @@ func (in *CurdDemoStatusInp) Filter(ctx context.Context) (err error) { return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/model/input/sysin/provinces.go b/server/internal/model/input/sysin/provinces.go index 89096a0..479e712 100644 --- a/server/internal/model/input/sysin/provinces.go +++ b/server/internal/model/input/sysin/provinces.go @@ -114,7 +114,7 @@ func (in *ProvincesStatusInp) Filter(ctx context.Context) (err error) { return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/internal/router/genrouter/init.go b/server/internal/router/genrouter/init.go index ceba68e..dcfd590 100644 --- a/server/internal/router/genrouter/init.go +++ b/server/internal/router/genrouter/init.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package genrouter import ( @@ -14,7 +13,7 @@ import ( ) var ( - NoLogin []interface{} // 无需登录 + NoLoginRouter []interface{} // 无需登录 LoginRequiredRouter []interface{} // 需要登录 ) @@ -22,8 +21,8 @@ var ( func Register(ctx context.Context, group *ghttp.RouterGroup) { prefix := g.Cfg().MustGet(ctx, "router.admin.prefix", "/admin") group.Group(prefix.String(), func(group *ghttp.RouterGroup) { - if len(NoLogin) > 0 { - group.Bind(NoLogin...) + if len(NoLoginRouter) > 0 { + group.Bind(NoLoginRouter...) } group.Middleware(service.Middleware().AdminAuth) if len(LoginRequiredRouter) > 0 { diff --git a/server/internal/service/admin.go b/server/internal/service/admin.go index 11e5b24..3a34375 100644 --- a/server/internal/service/admin.go +++ b/server/internal/service/admin.go @@ -19,6 +19,68 @@ import ( ) type ( + IAdminMember interface { + AddBalance(ctx context.Context, in adminin.MemberAddBalanceInp) (err error) + AddIntegral(ctx context.Context, in adminin.MemberAddIntegralInp) (err error) + UpdateCash(ctx context.Context, in adminin.MemberUpdateCashInp) (err error) + UpdateEmail(ctx context.Context, in adminin.MemberUpdateEmailInp) (err error) + UpdateMobile(ctx context.Context, in adminin.MemberUpdateMobileInp) (err error) + UpdateProfile(ctx context.Context, in adminin.MemberUpdateProfileInp) (err error) + UpdatePwd(ctx context.Context, in adminin.MemberUpdatePwdInp) (err error) + ResetPwd(ctx context.Context, in adminin.MemberResetPwdInp) (err error) + VerifyUnique(ctx context.Context, in adminin.VerifyUniqueInp) (err error) + Delete(ctx context.Context, in adminin.MemberDeleteInp) (err error) + Edit(ctx context.Context, in adminin.MemberEditInp) (err error) + View(ctx context.Context, in adminin.MemberViewInp) (res *adminin.MemberViewModel, err error) + List(ctx context.Context, in adminin.MemberListInp) (list []*adminin.MemberListModel, totalCount int, err error) + Status(ctx context.Context, in adminin.MemberStatusInp) (err error) + GenTree(ctx context.Context, pid int64) (level int, newTree string, err error) + LoginMemberInfo(ctx context.Context) (res *adminin.LoginMemberInfoModel, err error) + MemberLoginStat(ctx context.Context, in adminin.MemberLoginStatInp) (res *adminin.MemberLoginStatModel, err error) + GetIdByCode(ctx context.Context, in adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) + Select(ctx context.Context, in adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) + VerifySuperId(ctx context.Context, verifyId int64) bool + FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model + } + IAdminMemberPost interface { + UpdatePostIds(ctx context.Context, memberId int64, postIds []int64) (err error) + } + IAdminMenu interface { + MaxSort(ctx context.Context, req *menu.MaxSortReq) (res *menu.MaxSortRes, err error) + NameUnique(ctx context.Context, req *menu.NameUniqueReq) (res *menu.NameUniqueRes, err error) + CodeUnique(ctx context.Context, req *menu.CodeUniqueReq) (res *menu.CodeUniqueRes, err error) + Delete(ctx context.Context, req *menu.DeleteReq) (err error) + Edit(ctx context.Context, req *menu.EditReq) (err error) + View(ctx context.Context, req *menu.ViewReq) (res *menu.ViewRes, err error) + List(ctx context.Context, req *menu.ListReq) (lists []map[string]interface{}, err error) + GetMenuList(ctx context.Context, memberId int64) (res *role.DynamicRes, err error) + LoginPermissions(ctx context.Context, memberId int64) (lists adminin.MemberLoginPermissions, err error) + } + IAdminNotice interface { + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + Delete(ctx context.Context, in adminin.NoticeDeleteInp) (err error) + Edit(ctx context.Context, in adminin.NoticeEditInp) (err error) + Status(ctx context.Context, in adminin.NoticeStatusInp) (err error) + MaxSort(ctx context.Context, in adminin.NoticeMaxSortInp) (res *adminin.NoticeMaxSortModel, err error) + View(ctx context.Context, in adminin.NoticeViewInp) (res *adminin.NoticeViewModel, err error) + List(ctx context.Context, in adminin.NoticeListInp) (list []*adminin.NoticeListModel, totalCount int, err error) + PullMessages(ctx context.Context, in adminin.PullMessagesInp) (res *adminin.PullMessagesModel, err error) + UnreadCount(ctx context.Context, in adminin.NoticeUnreadCountInp) (res *adminin.NoticeUnreadCountModel, err error) + UpRead(ctx context.Context, in adminin.NoticeUpReadInp) (err error) + ReadAll(ctx context.Context, in adminin.NoticeReadAllInp) (err error) + MessageList(ctx context.Context, in adminin.NoticeMessageListInp) (list []*adminin.NoticeMessageListModel, totalCount int, err error) + } + IAdminSite interface { + Register(ctx context.Context, in adminin.RegisterInp) (err error) + AccountLogin(ctx context.Context, in adminin.AccountLoginInp) (res *adminin.LoginModel, err error) + MobileLogin(ctx context.Context, in adminin.MobileLoginInp) (res *adminin.LoginModel, err error) + } + IAdminCash interface { + View(ctx context.Context, in adminin.CashViewInp) (res *adminin.CashViewModel, err error) + List(ctx context.Context, in adminin.CashListInp) (list []*adminin.CashListModel, totalCount int, err error) + Apply(ctx context.Context, in adminin.CashApplyInp) (err error) + Payment(ctx context.Context, in adminin.CashPaymentInp) (err error) + } IAdminCreditsLog interface { Model(ctx context.Context, option ...*handler.Option) *gdb.Model SaveBalance(ctx context.Context, in adminin.CreditsLogSaveBalanceInp) (res *adminin.CreditsLogSaveBalanceModel, err error) @@ -26,8 +88,32 @@ type ( List(ctx context.Context, in adminin.CreditsLogListInp) (list []*adminin.CreditsLogListModel, totalCount int, err error) Export(ctx context.Context, in adminin.CreditsLogListInp) (err error) } - IAdminMemberPost interface { - UpdatePostIds(ctx context.Context, memberId int64, postIds []int64) (err error) + IAdminDept interface { + Delete(ctx context.Context, in adminin.DeptDeleteInp) (err error) + Edit(ctx context.Context, in adminin.DeptEditInp) (err error) + Status(ctx context.Context, in adminin.DeptStatusInp) (err error) + MaxSort(ctx context.Context, in adminin.DeptMaxSortInp) (res *adminin.DeptMaxSortModel, err error) + View(ctx context.Context, in adminin.DeptViewInp) (res *adminin.DeptViewModel, err error) + Option(ctx context.Context, in adminin.DeptOptionInp) (res *adminin.DeptOptionModel, totalCount int, err error) + List(ctx context.Context, in adminin.DeptListInp) (res *adminin.DeptListModel, err error) + GetName(ctx context.Context, id int64) (name string, err error) + } + IAdminMonitor interface { + StartMonitor(ctx context.Context) + GetMeta(ctx context.Context) *model.MonitorData + } + IAdminOrder interface { + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + AcceptRefund(ctx context.Context, in adminin.OrderAcceptRefundInp) (err error) + ApplyRefund(ctx context.Context, in adminin.OrderApplyRefundInp) (err error) + PayNotify(ctx context.Context, in payin.NotifyCallFuncInp) (err error) + Create(ctx context.Context, in adminin.OrderCreateInp) (res *adminin.OrderCreateModel, err error) + List(ctx context.Context, in adminin.OrderListInp) (list []*adminin.OrderListModel, totalCount int, err error) + Export(ctx context.Context, in adminin.OrderListInp) (err error) + Edit(ctx context.Context, in adminin.OrderEditInp) (err error) + Delete(ctx context.Context, in adminin.OrderDeleteInp) (err error) + View(ctx context.Context, in adminin.OrderViewInp) (res *adminin.OrderViewModel, err error) + Status(ctx context.Context, in adminin.OrderStatusInp) (err error) } IAdminPost interface { Delete(ctx context.Context, in adminin.PostDeleteInp) (err error) @@ -52,109 +138,34 @@ type ( DataScopeSelect() (res form.Selects) DataScopeEdit(ctx context.Context, in *adminin.DataScopeEditInp) (err error) } - IAdminCash interface { - View(ctx context.Context, in adminin.CashViewInp) (res *adminin.CashViewModel, err error) - List(ctx context.Context, in adminin.CashListInp) (list []*adminin.CashListModel, totalCount int, err error) - Apply(ctx context.Context, in adminin.CashApplyInp) (err error) - Payment(ctx context.Context, in adminin.CashPaymentInp) (err error) - } - IAdminMember interface { - AddBalance(ctx context.Context, in adminin.MemberAddBalanceInp) (err error) - AddIntegral(ctx context.Context, in adminin.MemberAddIntegralInp) (err error) - UpdateCash(ctx context.Context, in adminin.MemberUpdateCashInp) (err error) - UpdateEmail(ctx context.Context, in adminin.MemberUpdateEmailInp) (err error) - UpdateMobile(ctx context.Context, in adminin.MemberUpdateMobileInp) (err error) - UpdateProfile(ctx context.Context, in adminin.MemberUpdateProfileInp) (err error) - UpdatePwd(ctx context.Context, in adminin.MemberUpdatePwdInp) (err error) - ResetPwd(ctx context.Context, in adminin.MemberResetPwdInp) (err error) - VerifyUnique(ctx context.Context, in adminin.VerifyUniqueInp) (err error) - Delete(ctx context.Context, in adminin.MemberDeleteInp) (err error) - Edit(ctx context.Context, in adminin.MemberEditInp) (err error) - View(ctx context.Context, in adminin.MemberViewInp) (res *adminin.MemberViewModel, err error) - List(ctx context.Context, in adminin.MemberListInp) (list []*adminin.MemberListModel, totalCount int, err error) - Status(ctx context.Context, in adminin.MemberStatusInp) (err error) - GenTree(ctx context.Context, pid int64) (level int, newTree string, err error) - LoginMemberInfo(ctx context.Context) (res *adminin.LoginMemberInfoModel, err error) - MemberLoginStat(ctx context.Context, in adminin.MemberLoginStatInp) (res *adminin.MemberLoginStatModel, err error) - GetIdByCode(ctx context.Context, in adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) - Select(ctx context.Context, in adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) - VerifySuperId(ctx context.Context, verifyId int64) bool - FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model - } - IAdminMenu interface { - MaxSort(ctx context.Context, req *menu.MaxSortReq) (res *menu.MaxSortRes, err error) - NameUnique(ctx context.Context, req *menu.NameUniqueReq) (res *menu.NameUniqueRes, err error) - CodeUnique(ctx context.Context, req *menu.CodeUniqueReq) (res *menu.CodeUniqueRes, err error) - Delete(ctx context.Context, req *menu.DeleteReq) (err error) - Edit(ctx context.Context, req *menu.EditReq) (err error) - View(ctx context.Context, req *menu.ViewReq) (res *menu.ViewRes, err error) - List(ctx context.Context, req *menu.ListReq) (lists []map[string]interface{}, err error) - GetMenuList(ctx context.Context, memberId int64) (res *role.DynamicRes, err error) - LoginPermissions(ctx context.Context, memberId int64) (lists adminin.MemberLoginPermissions, err error) - } - IAdminMonitor interface { - StartMonitor(ctx context.Context) - GetMeta(ctx context.Context) *model.MonitorData - } - IAdminNotice interface { - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - Delete(ctx context.Context, in adminin.NoticeDeleteInp) (err error) - Edit(ctx context.Context, in adminin.NoticeEditInp) (err error) - Status(ctx context.Context, in adminin.NoticeStatusInp) (err error) - MaxSort(ctx context.Context, in adminin.NoticeMaxSortInp) (res *adminin.NoticeMaxSortModel, err error) - View(ctx context.Context, in adminin.NoticeViewInp) (res *adminin.NoticeViewModel, err error) - List(ctx context.Context, in adminin.NoticeListInp) (list []*adminin.NoticeListModel, totalCount int, err error) - PullMessages(ctx context.Context, in adminin.PullMessagesInp) (res *adminin.PullMessagesModel, err error) - UnreadCount(ctx context.Context, in adminin.NoticeUnreadCountInp) (res *adminin.NoticeUnreadCountModel, err error) - UpRead(ctx context.Context, in adminin.NoticeUpReadInp) (err error) - ReadAll(ctx context.Context, in adminin.NoticeReadAllInp) (err error) - MessageList(ctx context.Context, in adminin.NoticeMessageListInp) (list []*adminin.NoticeMessageListModel, totalCount int, err error) - } - IAdminOrder interface { - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - AcceptRefund(ctx context.Context, in adminin.OrderAcceptRefundInp) (err error) - ApplyRefund(ctx context.Context, in adminin.OrderApplyRefundInp) (err error) - PayNotify(ctx context.Context, in payin.NotifyCallFuncInp) (err error) - Create(ctx context.Context, in adminin.OrderCreateInp) (res *adminin.OrderCreateModel, err error) - List(ctx context.Context, in adminin.OrderListInp) (list []*adminin.OrderListModel, totalCount int, err error) - Export(ctx context.Context, in adminin.OrderListInp) (err error) - Edit(ctx context.Context, in adminin.OrderEditInp) (err error) - Delete(ctx context.Context, in adminin.OrderDeleteInp) (err error) - View(ctx context.Context, in adminin.OrderViewInp) (res *adminin.OrderViewModel, err error) - Status(ctx context.Context, in adminin.OrderStatusInp) (err error) - } - IAdminSite interface { - Register(ctx context.Context, in adminin.RegisterInp) (err error) - AccountLogin(ctx context.Context, in adminin.AccountLoginInp) (res *adminin.LoginModel, err error) - MobileLogin(ctx context.Context, in adminin.MobileLoginInp) (res *adminin.LoginModel, err error) - } - IAdminDept interface { - Delete(ctx context.Context, in adminin.DeptDeleteInp) (err error) - Edit(ctx context.Context, in adminin.DeptEditInp) (err error) - Status(ctx context.Context, in adminin.DeptStatusInp) (err error) - MaxSort(ctx context.Context, in adminin.DeptMaxSortInp) (res *adminin.DeptMaxSortModel, err error) - View(ctx context.Context, in adminin.DeptViewInp) (res *adminin.DeptViewModel, err error) - Option(ctx context.Context, in adminin.DeptOptionInp) (res *adminin.DeptOptionModel, totalCount int, err error) - List(ctx context.Context, in adminin.DeptListInp) (res *adminin.DeptListModel, err error) - GetName(ctx context.Context, id int64) (name string, err error) - } ) var ( + localAdminSite IAdminSite localAdminCash IAdminCash localAdminCreditsLog IAdminCreditsLog - localAdminMemberPost IAdminMemberPost + localAdminDept IAdminDept + localAdminMonitor IAdminMonitor + localAdminOrder IAdminOrder localAdminPost IAdminPost localAdminRole IAdminRole - localAdminDept IAdminDept localAdminMember IAdminMember + localAdminMemberPost IAdminMemberPost localAdminMenu IAdminMenu - localAdminMonitor IAdminMonitor localAdminNotice IAdminNotice - localAdminOrder IAdminOrder - localAdminSite IAdminSite ) +func AdminSite() IAdminSite { + if localAdminSite == nil { + panic("implement not found for interface IAdminSite, forgot register?") + } + return localAdminSite +} + +func RegisterAdminSite(i IAdminSite) { + localAdminSite = i +} + func AdminCash() IAdminCash { if localAdminCash == nil { panic("implement not found for interface IAdminCash, forgot register?") @@ -177,15 +188,37 @@ func RegisterAdminCreditsLog(i IAdminCreditsLog) { localAdminCreditsLog = i } -func AdminMemberPost() IAdminMemberPost { - if localAdminMemberPost == nil { - panic("implement not found for interface IAdminMemberPost, forgot register?") +func AdminDept() IAdminDept { + if localAdminDept == nil { + panic("implement not found for interface IAdminDept, forgot register?") } - return localAdminMemberPost + return localAdminDept } -func RegisterAdminMemberPost(i IAdminMemberPost) { - localAdminMemberPost = i +func RegisterAdminDept(i IAdminDept) { + localAdminDept = i +} + +func AdminMonitor() IAdminMonitor { + if localAdminMonitor == nil { + panic("implement not found for interface IAdminMonitor, forgot register?") + } + return localAdminMonitor +} + +func RegisterAdminMonitor(i IAdminMonitor) { + localAdminMonitor = i +} + +func AdminOrder() IAdminOrder { + if localAdminOrder == nil { + panic("implement not found for interface IAdminOrder, forgot register?") + } + return localAdminOrder +} + +func RegisterAdminOrder(i IAdminOrder) { + localAdminOrder = i } func AdminPost() IAdminPost { @@ -210,17 +243,6 @@ func RegisterAdminRole(i IAdminRole) { localAdminRole = i } -func AdminDept() IAdminDept { - if localAdminDept == nil { - panic("implement not found for interface IAdminDept, forgot register?") - } - return localAdminDept -} - -func RegisterAdminDept(i IAdminDept) { - localAdminDept = i -} - func AdminMember() IAdminMember { if localAdminMember == nil { panic("implement not found for interface IAdminMember, forgot register?") @@ -232,6 +254,17 @@ func RegisterAdminMember(i IAdminMember) { localAdminMember = i } +func AdminMemberPost() IAdminMemberPost { + if localAdminMemberPost == nil { + panic("implement not found for interface IAdminMemberPost, forgot register?") + } + return localAdminMemberPost +} + +func RegisterAdminMemberPost(i IAdminMemberPost) { + localAdminMemberPost = i +} + func AdminMenu() IAdminMenu { if localAdminMenu == nil { panic("implement not found for interface IAdminMenu, forgot register?") @@ -243,17 +276,6 @@ func RegisterAdminMenu(i IAdminMenu) { localAdminMenu = i } -func AdminMonitor() IAdminMonitor { - if localAdminMonitor == nil { - panic("implement not found for interface IAdminMonitor, forgot register?") - } - return localAdminMonitor -} - -func RegisterAdminMonitor(i IAdminMonitor) { - localAdminMonitor = i -} - func AdminNotice() IAdminNotice { if localAdminNotice == nil { panic("implement not found for interface IAdminNotice, forgot register?") @@ -264,25 +286,3 @@ func AdminNotice() IAdminNotice { func RegisterAdminNotice(i IAdminNotice) { localAdminNotice = i } - -func AdminOrder() IAdminOrder { - if localAdminOrder == nil { - panic("implement not found for interface IAdminOrder, forgot register?") - } - return localAdminOrder -} - -func RegisterAdminOrder(i IAdminOrder) { - localAdminOrder = i -} - -func AdminSite() IAdminSite { - if localAdminSite == nil { - panic("implement not found for interface IAdminSite, forgot register?") - } - return localAdminSite -} - -func RegisterAdminSite(i IAdminSite) { - localAdminSite = i -} diff --git a/server/internal/service/common.go b/server/internal/service/common.go index d7e8444..e2b18f1 100644 --- a/server/internal/service/common.go +++ b/server/internal/service/common.go @@ -7,7 +7,6 @@ package service import ( "context" - "hotgo/internal/model" "hotgo/internal/model/input/commonin" "hotgo/internal/model/input/sysin" @@ -16,15 +15,8 @@ import ( type ( ICommonUpload interface { - UploadFile(ctx context.Context, file *ghttp.UploadFile) (result *sysin.AttachmentListModel, err error) - UploadImage(ctx context.Context, file *ghttp.UploadFile) (result *sysin.AttachmentListModel, err error) - UploadLocal(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) - UploadUCloud(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) - UploadCOS(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) - UploadOSS(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) - UploadQiNiu(ctx context.Context, conf *model.UploadConfig, file *ghttp.UploadFile, meta *sysin.UploadFileMeta) (result *sysin.AttachmentListModel, err error) - LastUrl(ctx context.Context, conf *model.UploadConfig, fullPath, drive string) string - HasFile(ctx context.Context, md5 string) (res *sysin.AttachmentListModel, err error) + UploadFile(ctx context.Context, file *ghttp.UploadFile) (res *sysin.AttachmentListModel, err error) + UploadImage(ctx context.Context, file *ghttp.UploadFile) (res *sysin.AttachmentListModel, err error) } ICommonWechat interface { Authorize(ctx context.Context, in commonin.WechatAuthorizeInp) (res *commonin.WechatAuthorizeModel, err error) diff --git a/server/internal/service/sys.go b/server/internal/service/sys.go index 3199d03..4f2a820 100644 --- a/server/internal/service/sys.go +++ b/server/internal/service/sys.go @@ -17,11 +17,71 @@ import ( ) type ( - ISysDictData interface { - Delete(ctx context.Context, in sysin.DictDataDeleteInp) error - Edit(ctx context.Context, in sysin.DictDataEditInp) (err error) - List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error) - Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error) + ISysSmsLog interface { + Delete(ctx context.Context, in sysin.SmsLogDeleteInp) (err error) + Edit(ctx context.Context, in sysin.SmsLogEditInp) (err error) + Status(ctx context.Context, in sysin.SmsLogStatusInp) (err error) + MaxSort(ctx context.Context, in sysin.SmsLogMaxSortInp) (res *sysin.SmsLogMaxSortModel, err error) + View(ctx context.Context, in sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error) + List(ctx context.Context, in sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error) + SendCode(ctx context.Context, in sysin.SendCodeInp) (err error) + GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error) + AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error) + VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error) + } + ISysServeLog interface { + Model(ctx context.Context) *gdb.Model + List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error) + Export(ctx context.Context, in sysin.ServeLogListInp) (err error) + Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error) + View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error) + RealWrite(ctx context.Context, models entity.SysServeLog) (err error) + } + ISysAddons interface { + List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error) + Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error) + Build(ctx context.Context, in sysin.AddonsBuildInp) (err error) + Install(ctx context.Context, in sysin.AddonsInstallInp) (err error) + Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error) + UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error) + } + ISysCron interface { + StartCron(ctx context.Context) + Delete(ctx context.Context, in sysin.CronDeleteInp) (err error) + Edit(ctx context.Context, in sysin.CronEditInp) (err error) + Status(ctx context.Context, in sysin.CronStatusInp) (err error) + MaxSort(ctx context.Context, in sysin.CronMaxSortInp) (res *sysin.CronMaxSortModel, err error) + View(ctx context.Context, in sysin.CronViewInp) (res *sysin.CronViewModel, err error) + List(ctx context.Context, in sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error) + OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err error) + } + ISysCurdDemo interface { + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error) + Export(ctx context.Context, in sysin.CurdDemoListInp) (err error) + Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err error) + Delete(ctx context.Context, in sysin.CurdDemoDeleteInp) (err error) + MaxSort(ctx context.Context, in sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error) + View(ctx context.Context, in sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error) + Status(ctx context.Context, in sysin.CurdDemoStatusInp) (err error) + Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) (err error) + } + ISysDictType interface { + Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error) + Delete(ctx context.Context, in sysin.DictTypeDeleteInp) (err error) + Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error) + TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error) + } + ISysEmsLog interface { + Delete(ctx context.Context, in sysin.EmsLogDeleteInp) (err error) + Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error) + Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error) + View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error) + List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error) + Send(ctx context.Context, in sysin.SendEmsInp) (err error) + GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error) + AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error) + VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error) } ISysGenCodes interface { Delete(ctx context.Context, in sysin.GenCodesDeleteInp) (err error) @@ -37,32 +97,11 @@ type ( Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error) Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error) } - ISysLog interface { - Export(ctx context.Context, in sysin.LogListInp) (err error) - RealWrite(ctx context.Context, log entity.SysLog) (err error) - AutoLog(ctx context.Context) error - AnalysisLog(ctx context.Context) entity.SysLog - View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error) - Delete(ctx context.Context, in sysin.LogDeleteInp) (err error) - List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error) - } - ISysServeLog interface { - Model(ctx context.Context) *gdb.Model - List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error) - Export(ctx context.Context, in sysin.ServeLogListInp) (err error) - Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error) - View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error) - RealWrite(ctx context.Context, models entity.SysServeLog) (err error) - } - ISysCron interface { - StartCron(ctx context.Context) - Delete(ctx context.Context, in sysin.CronDeleteInp) (err error) - Edit(ctx context.Context, in sysin.CronEditInp) (err error) - Status(ctx context.Context, in sysin.CronStatusInp) (err error) - MaxSort(ctx context.Context, in sysin.CronMaxSortInp) (res *sysin.CronMaxSortModel, err error) - View(ctx context.Context, in sysin.CronViewInp) (res *sysin.CronViewModel, err error) - List(ctx context.Context, in sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error) - OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err error) + ISysAttachment interface { + Model(ctx context.Context, option ...*handler.Option) *gdb.Model + Delete(ctx context.Context, in sysin.AttachmentDeleteInp) (err error) + View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error) + List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error) } ISysBlacklist interface { Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error) @@ -95,32 +134,35 @@ type ( ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error) UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) (err error) } - ISysCurdDemo interface { - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error) - Export(ctx context.Context, in sysin.CurdDemoListInp) (err error) - Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err error) - Delete(ctx context.Context, in sysin.CurdDemoDeleteInp) (err error) - MaxSort(ctx context.Context, in sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error) - View(ctx context.Context, in sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error) - Status(ctx context.Context, in sysin.CurdDemoStatusInp) (err error) - Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) (err error) + ISysLog interface { + Export(ctx context.Context, in sysin.LogListInp) (err error) + RealWrite(ctx context.Context, log entity.SysLog) (err error) + AutoLog(ctx context.Context) error + AnalysisLog(ctx context.Context) entity.SysLog + View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error) + Delete(ctx context.Context, in sysin.LogDeleteInp) (err error) + List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error) } - ISysDictType interface { - Tree(ctx context.Context) (list []*sysin.DictTypeTree, err error) - Delete(ctx context.Context, in sysin.DictTypeDeleteInp) (err error) - Edit(ctx context.Context, in sysin.DictTypeEditInp) (err error) - TreeSelect(ctx context.Context, in sysin.DictTreeSelectInp) (list []*sysin.DictTypeTree, err error) + ISysLoginLog interface { + Model(ctx context.Context) *gdb.Model + List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error) + Export(ctx context.Context, in sysin.LoginLogListInp) (err error) + Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error) + View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error) + Push(ctx context.Context, in sysin.LoginLogPushInp) + RealWrite(ctx context.Context, models entity.SysLoginLog) (err error) } - ISysAttachment interface { - Model(ctx context.Context, option ...*handler.Option) *gdb.Model - Delete(ctx context.Context, in sysin.AttachmentDeleteInp) (err error) - Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error) - Status(ctx context.Context, in sysin.AttachmentStatusInp) (err error) - MaxSort(ctx context.Context, in sysin.AttachmentMaxSortInp) (res *sysin.AttachmentMaxSortModel, err error) - View(ctx context.Context, in sysin.AttachmentViewInp) (res *sysin.AttachmentViewModel, err error) - List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error) - Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (models *entity.SysAttachment, err error) + ISysProvinces interface { + Tree(ctx context.Context) (list []g.Map, err error) + Delete(ctx context.Context, in sysin.ProvincesDeleteInp) (err error) + Edit(ctx context.Context, in sysin.ProvincesEditInp) (err error) + Status(ctx context.Context, in sysin.ProvincesStatusInp) (err error) + MaxSort(ctx context.Context, in sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error) + View(ctx context.Context, in sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error) + List(ctx context.Context, in sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error) + ChildrenList(ctx context.Context, in sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error) + UniqueId(ctx context.Context, in sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error) + Select(ctx context.Context, in sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error) } ISysAddonsConfig interface { GetConfigByGroup(ctx context.Context, in sysin.GetAddonsConfigInp) (res *sysin.GetAddonsConfigModel, err error) @@ -136,122 +178,54 @@ type ( List(ctx context.Context, in sysin.CronGroupListInp) (list []*sysin.CronGroupListModel, totalCount int, err error) Select(ctx context.Context, in sysin.CronGroupSelectInp) (res *sysin.CronGroupSelectModel, err error) } - ISysEmsLog interface { - Delete(ctx context.Context, in sysin.EmsLogDeleteInp) (err error) - Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error) - Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error) - View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error) - List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error) - Send(ctx context.Context, in sysin.SendEmsInp) (err error) - GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error) - AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error) - VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error) - } - ISysProvinces interface { - Tree(ctx context.Context) (list []g.Map, err error) - Delete(ctx context.Context, in sysin.ProvincesDeleteInp) (err error) - Edit(ctx context.Context, in sysin.ProvincesEditInp) (err error) - Status(ctx context.Context, in sysin.ProvincesStatusInp) (err error) - MaxSort(ctx context.Context, in sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error) - View(ctx context.Context, in sysin.ProvincesViewInp) (res *sysin.ProvincesViewModel, err error) - List(ctx context.Context, in sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error) - ChildrenList(ctx context.Context, in sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error) - UniqueId(ctx context.Context, in sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error) - Select(ctx context.Context, in sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error) - } - ISysAddons interface { - List(ctx context.Context, in sysin.AddonsListInp) (list []*sysin.AddonsListModel, totalCount int, err error) - Selects(ctx context.Context, in sysin.AddonsSelectsInp) (res *sysin.AddonsSelectsModel, err error) - Build(ctx context.Context, in sysin.AddonsBuildInp) (err error) - Install(ctx context.Context, in sysin.AddonsInstallInp) (err error) - Upgrade(ctx context.Context, in sysin.AddonsUpgradeInp) (err error) - UnInstall(ctx context.Context, in sysin.AddonsUnInstallInp) (err error) - } - ISysSmsLog interface { - Delete(ctx context.Context, in sysin.SmsLogDeleteInp) (err error) - Edit(ctx context.Context, in sysin.SmsLogEditInp) (err error) - Status(ctx context.Context, in sysin.SmsLogStatusInp) (err error) - MaxSort(ctx context.Context, in sysin.SmsLogMaxSortInp) (res *sysin.SmsLogMaxSortModel, err error) - View(ctx context.Context, in sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error) - List(ctx context.Context, in sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error) - SendCode(ctx context.Context, in sysin.SendCodeInp) (err error) - GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error) - AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error) - VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error) - } - ISysLoginLog interface { - Model(ctx context.Context) *gdb.Model - List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error) - Export(ctx context.Context, in sysin.LoginLogListInp) (err error) - Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error) - View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error) - Push(ctx context.Context, in sysin.LoginLogPushInp) - RealWrite(ctx context.Context, models entity.SysLoginLog) (err error) + ISysDictData interface { + Delete(ctx context.Context, in sysin.DictDataDeleteInp) error + Edit(ctx context.Context, in sysin.DictDataEditInp) (err error) + List(ctx context.Context, in sysin.DictDataListInp) (list []*sysin.DictDataListModel, totalCount int, err error) + Select(ctx context.Context, in sysin.DataSelectInp) (list sysin.DataSelectModel, err error) } ) var ( - localSysDictData ISysDictData - localSysGenCodes ISysGenCodes - localSysLog ISysLog - localSysServeLog ISysServeLog localSysCron ISysCron + localSysCurdDemo ISysCurdDemo + localSysServeLog ISysServeLog + localSysAddons ISysAddons localSysBlacklist ISysBlacklist localSysConfig ISysConfig - localSysCurdDemo ISysCurdDemo localSysDictType ISysDictType - localSysAttachment ISysAttachment - localSysAddonsConfig ISysAddonsConfig - localSysCronGroup ISysCronGroup localSysEmsLog ISysEmsLog - localSysProvinces ISysProvinces - localSysAddons ISysAddons - localSysSmsLog ISysSmsLog + localSysGenCodes ISysGenCodes + localSysAttachment ISysAttachment + localSysCronGroup ISysCronGroup + localSysDictData ISysDictData + localSysLog ISysLog localSysLoginLog ISysLoginLog + localSysProvinces ISysProvinces + localSysAddonsConfig ISysAddonsConfig + localSysSmsLog ISysSmsLog ) -func SysProvinces() ISysProvinces { - if localSysProvinces == nil { - panic("implement not found for interface ISysProvinces, forgot register?") +func SysConfig() ISysConfig { + if localSysConfig == nil { + panic("implement not found for interface ISysConfig, forgot register?") } - return localSysProvinces + return localSysConfig } -func RegisterSysProvinces(i ISysProvinces) { - localSysProvinces = i +func RegisterSysConfig(i ISysConfig) { + localSysConfig = i } -func SysAddons() ISysAddons { - if localSysAddons == nil { - panic("implement not found for interface ISysAddons, forgot register?") +func SysDictType() ISysDictType { + if localSysDictType == nil { + panic("implement not found for interface ISysDictType, forgot register?") } - return localSysAddons + return localSysDictType } -func RegisterSysAddons(i ISysAddons) { - localSysAddons = i -} - -func SysAddonsConfig() ISysAddonsConfig { - if localSysAddonsConfig == nil { - panic("implement not found for interface ISysAddonsConfig, forgot register?") - } - return localSysAddonsConfig -} - -func RegisterSysAddonsConfig(i ISysAddonsConfig) { - localSysAddonsConfig = i -} - -func SysCronGroup() ISysCronGroup { - if localSysCronGroup == nil { - panic("implement not found for interface ISysCronGroup, forgot register?") - } - return localSysCronGroup -} - -func RegisterSysCronGroup(i ISysCronGroup) { - localSysCronGroup = i +func RegisterSysDictType(i ISysDictType) { + localSysDictType = i } func SysEmsLog() ISysEmsLog { @@ -265,61 +239,6 @@ func RegisterSysEmsLog(i ISysEmsLog) { localSysEmsLog = i } -func SysLoginLog() ISysLoginLog { - if localSysLoginLog == nil { - panic("implement not found for interface ISysLoginLog, forgot register?") - } - return localSysLoginLog -} - -func RegisterSysLoginLog(i ISysLoginLog) { - localSysLoginLog = i -} - -func SysSmsLog() ISysSmsLog { - if localSysSmsLog == nil { - panic("implement not found for interface ISysSmsLog, forgot register?") - } - return localSysSmsLog -} - -func RegisterSysSmsLog(i ISysSmsLog) { - localSysSmsLog = i -} - -func SysServeLog() ISysServeLog { - if localSysServeLog == nil { - panic("implement not found for interface ISysServeLog, forgot register?") - } - return localSysServeLog -} - -func RegisterSysServeLog(i ISysServeLog) { - localSysServeLog = i -} - -func SysCron() ISysCron { - if localSysCron == nil { - panic("implement not found for interface ISysCron, forgot register?") - } - return localSysCron -} - -func RegisterSysCron(i ISysCron) { - localSysCron = i -} - -func SysDictData() ISysDictData { - if localSysDictData == nil { - panic("implement not found for interface ISysDictData, forgot register?") - } - return localSysDictData -} - -func RegisterSysDictData(i ISysDictData) { - localSysDictData = i -} - func SysGenCodes() ISysGenCodes { if localSysGenCodes == nil { panic("implement not found for interface ISysGenCodes, forgot register?") @@ -331,28 +250,6 @@ func RegisterSysGenCodes(i ISysGenCodes) { localSysGenCodes = i } -func SysLog() ISysLog { - if localSysLog == nil { - panic("implement not found for interface ISysLog, forgot register?") - } - return localSysLog -} - -func RegisterSysLog(i ISysLog) { - localSysLog = i -} - -func SysDictType() ISysDictType { - if localSysDictType == nil { - panic("implement not found for interface ISysDictType, forgot register?") - } - return localSysDictType -} - -func RegisterSysDictType(i ISysDictType) { - localSysDictType = i -} - func SysAttachment() ISysAttachment { if localSysAttachment == nil { panic("implement not found for interface ISysAttachment, forgot register?") @@ -375,15 +272,81 @@ func RegisterSysBlacklist(i ISysBlacklist) { localSysBlacklist = i } -func SysConfig() ISysConfig { - if localSysConfig == nil { - panic("implement not found for interface ISysConfig, forgot register?") +func SysDictData() ISysDictData { + if localSysDictData == nil { + panic("implement not found for interface ISysDictData, forgot register?") } - return localSysConfig + return localSysDictData } -func RegisterSysConfig(i ISysConfig) { - localSysConfig = i +func RegisterSysDictData(i ISysDictData) { + localSysDictData = i +} + +func SysLog() ISysLog { + if localSysLog == nil { + panic("implement not found for interface ISysLog, forgot register?") + } + return localSysLog +} + +func RegisterSysLog(i ISysLog) { + localSysLog = i +} + +func SysLoginLog() ISysLoginLog { + if localSysLoginLog == nil { + panic("implement not found for interface ISysLoginLog, forgot register?") + } + return localSysLoginLog +} + +func RegisterSysLoginLog(i ISysLoginLog) { + localSysLoginLog = i +} + +func SysProvinces() ISysProvinces { + if localSysProvinces == nil { + panic("implement not found for interface ISysProvinces, forgot register?") + } + return localSysProvinces +} + +func RegisterSysProvinces(i ISysProvinces) { + localSysProvinces = i +} + +func SysAddonsConfig() ISysAddonsConfig { + if localSysAddonsConfig == nil { + panic("implement not found for interface ISysAddonsConfig, forgot register?") + } + return localSysAddonsConfig +} + +func RegisterSysAddonsConfig(i ISysAddonsConfig) { + localSysAddonsConfig = i +} + +func SysCronGroup() ISysCronGroup { + if localSysCronGroup == nil { + panic("implement not found for interface ISysCronGroup, forgot register?") + } + return localSysCronGroup +} + +func RegisterSysCronGroup(i ISysCronGroup) { + localSysCronGroup = i +} + +func SysSmsLog() ISysSmsLog { + if localSysSmsLog == nil { + panic("implement not found for interface ISysSmsLog, forgot register?") + } + return localSysSmsLog +} + +func RegisterSysSmsLog(i ISysSmsLog) { + localSysSmsLog = i } func SysCurdDemo() ISysCurdDemo { @@ -396,3 +359,36 @@ func SysCurdDemo() ISysCurdDemo { func RegisterSysCurdDemo(i ISysCurdDemo) { localSysCurdDemo = i } + +func SysServeLog() ISysServeLog { + if localSysServeLog == nil { + panic("implement not found for interface ISysServeLog, forgot register?") + } + return localSysServeLog +} + +func RegisterSysServeLog(i ISysServeLog) { + localSysServeLog = i +} + +func SysAddons() ISysAddons { + if localSysAddons == nil { + panic("implement not found for interface ISysAddons, forgot register?") + } + return localSysAddons +} + +func RegisterSysAddons(i ISysAddons) { + localSysAddons = i +} + +func SysCron() ISysCron { + if localSysCron == nil { + panic("implement not found for interface ISysCron, forgot register?") + } + return localSysCron +} + +func RegisterSysCron(i ISysCron) { + localSysCron = i +} diff --git a/server/internal/service/tcpclient.go b/server/internal/service/tcpclient.go index 110e7e2..fd094fa 100644 --- a/server/internal/service/tcpclient.go +++ b/server/internal/service/tcpclient.go @@ -28,21 +28,10 @@ type ( ) var ( - localAuthClient IAuthClient localCronClient ICronClient + localAuthClient IAuthClient ) -func CronClient() ICronClient { - if localCronClient == nil { - panic("implement not found for interface ICronClient, forgot register?") - } - return localCronClient -} - -func RegisterCronClient(i ICronClient) { - localCronClient = i -} - func AuthClient() IAuthClient { if localAuthClient == nil { panic("implement not found for interface IAuthClient, forgot register?") @@ -53,3 +42,14 @@ func AuthClient() IAuthClient { func RegisterAuthClient(i IAuthClient) { localAuthClient = i } + +func CronClient() ICronClient { + if localCronClient == nil { + panic("implement not found for interface ICronClient, forgot register?") + } + return localCronClient +} + +func RegisterCronClient(i ICronClient) { + localCronClient = i +} diff --git a/server/internal/websocket/client_manager.go b/server/internal/websocket/client_manager.go index 8e1793c..71fd1ba 100644 --- a/server/internal/websocket/client_manager.go +++ b/server/internal/websocket/client_manager.go @@ -289,7 +289,6 @@ func (manager *ClientManager) start() { g.Log().Info(ctxManager, "websocket closeSignal quit..") return } - } } diff --git a/server/resource/generate/default/addon/router/genrouter/init.go.template b/server/resource/generate/default/addon/router/genrouter/init.go.template index 0ba9331..d15d513 100644 --- a/server/resource/generate/default/addon/router/genrouter/init.go.template +++ b/server/resource/generate/default/addon/router/genrouter/init.go.template @@ -8,14 +8,14 @@ package genrouter import ( "context" "github.com/gogf/gf/v2/net/ghttp" - "hotgo/addons/@{.name}/global" + "hotgo/addons/hgexample/global" "hotgo/internal/consts" "hotgo/internal/library/addons" "hotgo/internal/service" ) var ( - NoLogin []interface{} // 无需登录 + NoLoginRouter []interface{} // 无需登录 LoginRequiredRouter []interface{} // 需要登录 ) @@ -23,8 +23,8 @@ var ( func Register(ctx context.Context, group *ghttp.RouterGroup) { prefix := addons.RouterPrefix(ctx, consts.AppAdmin, global.GetSkeleton().Name) group.Group(prefix, func(group *ghttp.RouterGroup) { - if len(NoLogin) > 0 { - group.Bind(NoLogin...) + if len(NoLoginRouter) > 0 { + group.Bind(NoLoginRouter...) } group.Middleware(service.Middleware().AdminAuth) if len(LoginRequiredRouter) > 0 { diff --git a/server/resource/generate/default/curd/input.go.template b/server/resource/generate/default/curd/input.go.template index e5f483f..33fe824 100644 --- a/server/resource/generate/default/curd/input.go.template +++ b/server/resource/generate/default/curd/input.go.template @@ -117,7 +117,7 @@ func (in *@{.varName}StatusInp) Filter(ctx context.Context) (err error) { return } - if !validate.InSliceInt(consts.StatusSlice, in.Status) { + if !validate.InSlice(consts.StatusSlice, in.Status) { err = gerror.New("状态不正确") return } diff --git a/server/resource/generate/default/curd/logic.go.template b/server/resource/generate/default/curd/logic.go.template index 5d7da46..75ee9ec 100644 --- a/server/resource/generate/default/curd/logic.go.template +++ b/server/resource/generate/default/curd/logic.go.template @@ -159,7 +159,7 @@ func (s *s@{.servFunName}) Switch(ctx context.Context, in @{.templateGroup}in.@{ // ... } - if !validate.InSliceString(fields, in.Key) { + if !validate.InSlice(fields, in.Key) { err = gerror.New("开关键名不在白名单") return } diff --git a/server/utility/charset/charset.go b/server/utility/charset/charset.go index 0b4714c..9715495 100644 --- a/server/utility/charset/charset.go +++ b/server/utility/charset/charset.go @@ -9,41 +9,11 @@ import ( "crypto/rand" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" - "github.com/gogf/gf/v2/util/gconv" - "hotgo/utility/convert" r "math/rand" "strings" "time" ) -// SplitMemberIds 从截取字串符中读取用户ID -func SplitMemberIds(str, pos string) (memberIds []int64) { - receiver := strings.Split(strings.TrimSpace(str), pos) - if len(receiver) == 0 { - return memberIds - } - if len(receiver) == 1 && strings.TrimSpace(receiver[0]) == "" { - return memberIds - } - - for _, memberId := range receiver { - memberIds = append(memberIds, gconv.Int64(strings.TrimSpace(memberId))) - } - return convert.UniqueSliceInt64(memberIds) -} - -// GetMapKeysByString 获取map的所有key,字串符类型 -func GetMapKeysByString(m map[string]string) []string { - // 数组默认长度为map长度,后面append时,不需要重新申请内存和拷贝,效率很高 - j := 0 - keys := make([]string, len(m)) - for k := range m { - keys[j] = k - j++ - } - return keys -} - // RandomCreateBytes 生成随机字串符 func RandomCreateBytes(n int, alphabets ...byte) []byte { if len(alphabets) == 0 { @@ -51,13 +21,12 @@ func RandomCreateBytes(n int, alphabets ...byte) []byte { } var bytes = make([]byte, n) var randBy bool - r.Seed(time.Now().UnixNano()) if num, err := rand.Read(bytes); num != n || err != nil { randBy = true } for i, b := range bytes { if randBy { - bytes[i] = alphabets[r.Intn(len(alphabets))] + bytes[i] = alphabets[r.New(r.NewSource(time.Now().UnixNano())).Intn(len(alphabets))] } else { bytes[i] = alphabets[b%byte(len(alphabets))] } diff --git a/server/utility/convert/convert.go b/server/utility/convert/convert.go index 8eb9085..8b13a37 100644 --- a/server/utility/convert/convert.go +++ b/server/utility/convert/convert.go @@ -17,23 +17,21 @@ var ( fieldTags = []string{"json"} // 实体字段名称映射 ) -// UniqueSliceInt64 切片去重 -func UniqueSliceInt64(languages []int64) []int64 { - result := make([]int64, 0, len(languages)) - temp := map[int64]struct{}{} - for _, item := range languages { - if _, ok := temp[item]; !ok { - temp[item] = struct{}{} - result = append(result, item) - } +// GetMapKeys 获取map的所有key +func GetMapKeys[K comparable](m map[K]any) []K { + j := 0 + keys := make([]K, len(m)) + for k := range m { + keys[j] = k + j++ } - return result + return keys } -// UniqueSliceString 切片去重 -func UniqueSliceString(languages []string) []string { - result := make([]string, 0, len(languages)) - temp := map[string]struct{}{} +// UniqueSlice 切片去重 +func UniqueSlice[K comparable](languages []K) []K { + result := make([]K, 0, len(languages)) + temp := map[K]struct{}{} for _, item := range languages { if _, ok := temp[item]; !ok { temp[item] = struct{}{} @@ -121,19 +119,19 @@ func reflectTag(reflectType reflect.Type, filterTags []string, tags []string) ([ // reflectTagName 解析实体中的描述标签,优先级:description > dc > json > Name func reflectTagName(field reflect.StructField, filterTags []string, isDef bool) string { - if validate.InSliceString(filterTags, "description") { + if validate.InSlice(filterTags, "description") { if description, ok := field.Tag.Lookup("description"); ok && description != "" { return description } } - if validate.InSliceString(filterTags, "dc") { + if validate.InSlice(filterTags, "dc") { if dc, ok := field.Tag.Lookup("dc"); ok && dc != "" { return dc } } - if validate.InSliceString(filterTags, "json") { + if validate.InSlice(filterTags, "json") { if jsonName, ok := field.Tag.Lookup("json"); ok && jsonName != "" { return jsonName } diff --git a/server/utility/file/file.go b/server/utility/file/file.go index ed77ad9..7fdb48c 100644 --- a/server/utility/file/file.go +++ b/server/utility/file/file.go @@ -12,12 +12,6 @@ import ( "path/filepath" ) -const ( //文件大小单位 - _ = iota - KB = 1 << (10 * iota) - MB -) - type fileInfo struct { //文件信息 name string size int64 diff --git a/server/utility/format/format.go b/server/utility/format/format.go index fffaad2..85e8139 100644 --- a/server/utility/format/format.go +++ b/server/utility/format/format.go @@ -7,40 +7,67 @@ package format import ( "fmt" + "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" "strconv" ) // Round2String 四舍五入保留小数,默认2位 -func Round2String(value float64, args ...interface{}) (v string) { +func Round2String(value float64, args ...interface{}) string { var places = 2 if len(args) > 0 { places = gconv.Int(args[0]) } - - cDig := strconv.Itoa(places) - val := fmt.Sprintf("%0."+cDig+"f", value) - return val + return fmt.Sprintf("%0."+strconv.Itoa(places)+"f", value) } // Round2Float64 四舍五入保留小数,默认2位 -func Round2Float64(value float64, args ...interface{}) (v float64) { +func Round2Float64(value float64, args ...interface{}) float64 { return gconv.Float64(Round2String(value, args...)) } // FileSize 字节的单位转换 保留两位小数 -func FileSize(fileSize int64) (size string) { - if fileSize < 1024 { - return fmt.Sprintf("%.2fB", float64(fileSize)/float64(1)) - } else if fileSize < (1024 * 1024) { - return fmt.Sprintf("%.2fKB", float64(fileSize)/float64(1024)) - } else if fileSize < (1024 * 1024 * 1024) { - return fmt.Sprintf("%.2fMB", float64(fileSize)/float64(1024*1024)) - } else if fileSize < (1024 * 1024 * 1024 * 1024) { - return fmt.Sprintf("%.2fGB", float64(fileSize)/float64(1024*1024*1024)) - } else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) { - return fmt.Sprintf("%.2fTB", float64(fileSize)/float64(1024*1024*1024*1024)) - } else { - return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(1024*1024*1024*1024*1024)) +func FileSize(data int64) string { + var factor float64 = 1024 + res := float64(data) + for _, unit := range []string{"", "K", "M", "G", "T", "P"} { + if res < factor { + return fmt.Sprintf("%.2f%sB", res, unit) + } + res /= factor } + return fmt.Sprintf("%.2f%sB", res, "P") +} + +// AgoTime 多久以前 +func AgoTime(gt *gtime.Time) string { + if gt == nil { + return "" + } + n := gtime.Now().Timestamp() + t := gt.Timestamp() + + var ys int64 = 31536000 + var ds int64 = 86400 + var hs int64 = 3600 + var ms int64 = 60 + var ss int64 = 1 + var rs string + + d := n - t + switch { + case d > ys: + rs = fmt.Sprintf("%d年前", int(d/ys)) + case d > ds: + rs = fmt.Sprintf("%d天前", int(d/ds)) + case d > hs: + rs = fmt.Sprintf("%d小时前", int(d/hs)) + case d > ms: + rs = fmt.Sprintf("%d分钟前", int(d/ms)) + case d > ss: + rs = fmt.Sprintf("%d秒前", int(d/ss)) + default: + rs = "刚刚" + } + return rs } diff --git a/server/utility/signal/signal.go b/server/utility/signal/signal.go deleted file mode 100644 index 88320f4..0000000 --- a/server/utility/signal/signal.go +++ /dev/null @@ -1,56 +0,0 @@ -// Package signal -// @Link https://github.com/bufanyun/hotgo -// @Copyright Copyright (c) 2023 HotGo CLI -// @Author Ms <133814250@qq.com> -// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// -package signal - -import ( - "sync" -) - -type StopSignal int32 - -type exitWait struct { - mutex sync.Mutex - wg *sync.WaitGroup - deferFuns []func() - stopSignList []chan StopSignal -} - -var exitWaitHandler *exitWait - -func init() { - exitWaitHandler = &exitWait{ - wg: &sync.WaitGroup{}, - } -} - -// ExitWaitFunDo 退出后等待处理完成 -func ExitWaitFunDo(doFun func()) { - exitWaitHandler.wg.Add(1) - defer exitWaitHandler.wg.Done() - if doFun != nil { - doFun() - } -} - -// AppDefer 应用退出后置操作 -func AppDefer(deferFun ...func()) { - exitWaitHandler.mutex.Lock() - defer exitWaitHandler.mutex.Unlock() - for _, funcItem := range deferFun { - if funcItem != nil { - exitWaitHandler.deferFuns = append(exitWaitHandler.deferFuns, funcItem) - } - } -} - -// ListenStop 订阅app退出信号 -func ListenStop(stopSig chan StopSignal) { - exitWaitHandler.mutex.Lock() - defer exitWaitHandler.mutex.Unlock() - - exitWaitHandler.stopSignList = append(exitWaitHandler.stopSignList, stopSig) -} diff --git a/server/utility/simple/event.go b/server/utility/simple/event.go new file mode 100644 index 0000000..bcc5651 --- /dev/null +++ b/server/utility/simple/event.go @@ -0,0 +1,51 @@ +package simple + +import ( + "context" + "sync" +) + +type EventFunc func(ctx context.Context, args ...interface{}) + +type sEvent struct { + sync.Mutex + list map[string][]EventFunc // 所有事件的列表 +} + +var event *sEvent + +// InstanceEvent 事件实例 +func InstanceEvent() *sEvent { + if event == nil { + event = &sEvent{ + list: make(map[string][]EventFunc), + } + } + return event +} + +// Register 往一个分组中注册事件 +func (e *sEvent) Register(group string, callback EventFunc) { + e.Lock() + defer e.Unlock() + e.list[group] = append(e.list[group], callback) +} + +// Call 回调一个分组的事件 +func (e *sEvent) Call(group string, ctx context.Context, args ...interface{}) { + if events, ok := e.list[group]; ok { + for _, f := range events { + f(ctx, args...) + } + } +} + +// Remove 移动一个分组的事件 +func (e *sEvent) Remove(group string) { + delete(e.list, group) +} + +// Clear 清空事件列表 +func (e *sEvent) Clear() { + e.list = make(map[string][]EventFunc) +} diff --git a/server/utility/useragent/useragent.go b/server/utility/useragent/useragent.go index 4668585..5c4a12b 100644 --- a/server/utility/useragent/useragent.go +++ b/server/utility/useragent/useragent.go @@ -8,35 +8,40 @@ package useragent import ( "fmt" "github.com/gogf/gf/v2/text/gstr" + "hotgo/internal/consts" "regexp" "strings" ) // GetOs 获取OS名称 func GetOs(userAgent string) string { - osName := "Unknown" + osName := consts.Unknown if userAgent == "" { return osName } - strRe, _ := regexp.Compile(`(?i:\((.*?)\))`) - userAgent = strRe.FindString(userAgent) + var ( + strRe, _ = regexp.Compile(`(?i:\((.*?)\))`) + levelNames = ":micromessenger:dart:Windows NT:Windows Mobile:Windows Phone:Windows Phone OS:Macintosh|Macintosh:Mac OS:CrOS|CrOS:iPhone OS:iPad|iPad:OS:Android:Linux:blackberry:hpwOS:Series:Symbian:PalmOS:SymbianOS:J2ME:Sailfish:Bada:MeeGo:webOS|hpwOS:Maemo:" + namesArr = strings.Split(strings.Trim(levelNames, ":"), ":") + regStrArr = make([]string, len(namesArr)) + ) - levelNames := ":micromessenger:dart:Windows NT:Windows Mobile:Windows Phone:Windows Phone OS:Macintosh|Macintosh:Mac OS:CrOS|CrOS:iPhone OS:iPad|iPad:OS:Android:Linux:blackberry:hpwOS:Series:Symbian:PalmOS:SymbianOS:J2ME:Sailfish:Bada:MeeGo:webOS|hpwOS:Maemo:" - var regStrArr []string - namesArr := strings.Split(strings.Trim(levelNames, ":"), ":") - for _, name := range namesArr { - regStrArr = append(regStrArr, fmt.Sprintf("(%s[\\s?\\/XxSs0-9_.]+)", name)) + for k, name := range namesArr { + regStrArr[k] = fmt.Sprintf("(%s[\\s?\\/XxSs0-9_.]+)", name) } - regexpStr := fmt.Sprintf("(?i:%s)", strings.Join(regStrArr, "|")) - nameRe, _ := regexp.Compile(regexpStr) - names := nameRe.FindAllString(userAgent, -1) - name := "" + userAgent = strRe.FindString(userAgent) + var ( + nameRe, _ = regexp.Compile(fmt.Sprintf("(?i:%s)", strings.Join(regStrArr, "|"))) + names = nameRe.FindAllString(userAgent, -1) + name = "" + ) + for _, s := range names { - if name == "" { + if len(name) == 0 { name = strings.TrimSpace(s) - } else if len(name) > 0 { + } else { if strings.Contains(name, "Macintosh") && s != "" { name = strings.TrimSpace(s) } else if strings.Contains(name, s) { @@ -62,30 +67,32 @@ func GetOs(userAgent string) string { if name != "" { osName = name } - return osName } // GetBrowser 获取浏览器名称 func GetBrowser(userAgent string) string { - deviceName := "Unknown" + var ( + deviceName = consts.Unknown + levelNames = ":VivoBrowser:QQDownload:QQBrowser:QQ:MQQBrowser:MicroMessenger:TencentTraveler:LBBROWSER:TaoBrowser:BrowserNG:UCWEB:TwonkyBeamBrowser:NokiaBrowser:OviBrowser:NF-Browser:OneBrowser:Obigo:DiigoBrowser:baidubrowser:baiduboxapp:xiaomi:Redmi:MI:Lumia:Micromax:MSIEMobile:IEMobile:EdgiOS:Yandex:Mercury:Openwave:TouchPad:UBrowser:Presto:Maxthon:MetaSr:Trident:Opera:IEMobile:Edge:Chrome:Chromium:OPR:CriOS:Firefox:FxiOS:fennec:CrMo:Safari:Nexus One:Nexus S:Nexus:Blazer:teashark:bolt:HTC:Dell:Motorola:Samsung:LG:Sony:SonyST:SonyLT:SonyEricsson:Asus:Palm:Vertu:Pantech:Fly:Wiko:i-mobile:Alcatel:Nintendo:Amoi:INQ:ONEPLUS:Tapatalk:PDA:Novarra-Vision:NetFront:Minimo:FlyFlow:Dolfin:Nokia:Series:AppleWebKit:Mobile:Mozilla:Version:" + namesArr = strings.Split(strings.Trim(levelNames, ":"), ":") + regStrArr []string + ) - levelNames := ":VivoBrowser:QQDownload:QQBrowser:QQ:MQQBrowser:MicroMessenger:TencentTraveler:LBBROWSER:TaoBrowser:BrowserNG:UCWEB:TwonkyBeamBrowser:NokiaBrowser:OviBrowser:NF-Browser:OneBrowser:Obigo:DiigoBrowser:baidubrowser:baiduboxapp:xiaomi:Redmi:MI:Lumia:Micromax:MSIEMobile:IEMobile:EdgiOS:Yandex:Mercury:Openwave:TouchPad:UBrowser:Presto:Maxthon:MetaSr:Trident:Opera:IEMobile:Edge:Chrome:Chromium:OPR:CriOS:Firefox:FxiOS:fennec:CrMo:Safari:Nexus One:Nexus S:Nexus:Blazer:teashark:bolt:HTC:Dell:Motorola:Samsung:LG:Sony:SonyST:SonyLT:SonyEricsson:Asus:Palm:Vertu:Pantech:Fly:Wiko:i-mobile:Alcatel:Nintendo:Amoi:INQ:ONEPLUS:Tapatalk:PDA:Novarra-Vision:NetFront:Minimo:FlyFlow:Dolfin:Nokia:Series:AppleWebKit:Mobile:Mozilla:Version:" - - var regStrArr []string - namesArr := strings.Split(strings.Trim(levelNames, ":"), ":") for _, name := range namesArr { regStrArr = append(regStrArr, fmt.Sprintf("(%s[\\s?\\/0-9.]+)", name)) } - regexpStr := fmt.Sprintf("(?i:%s)", strings.Join(regStrArr, "|")) - nameRe, _ := regexp.Compile(regexpStr) - names := nameRe.FindAllString(userAgent, -1) - level := 0 + var ( + regexpStr = fmt.Sprintf("(?i:%s)", strings.Join(regStrArr, "|")) + nameRe, _ = regexp.Compile(regexpStr) + names = nameRe.FindAllString(userAgent, -1) + level = 0 + ) + for _, name := range names { replaceRe, _ := regexp.Compile(`(?i:[\s?\/0-9.]+)`) - n := replaceRe.ReplaceAllString(name, "") - l := strings.Index(levelNames, fmt.Sprintf(":%s:", n)) + l := strings.Index(levelNames, fmt.Sprintf(":%s:", replaceRe.ReplaceAllString(name, ""))) if level == 0 { deviceName = strings.TrimSpace(name) } @@ -95,7 +102,6 @@ func GetBrowser(userAgent string) string { deviceName = strings.TrimSpace(name) } } - return deviceName } @@ -119,6 +125,5 @@ func getWinOsNameWithWinNT(sName string) string { break } } - return osName } diff --git a/server/utility/validate/include.go b/server/utility/validate/include.go index 77501ca..7b445a4 100644 --- a/server/utility/validate/include.go +++ b/server/utility/validate/include.go @@ -3,18 +3,16 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package validate import ( - "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" ) // 包含判断 // InSliceExistStr 判断字符或切片字符是否存在指定字符 -func InSliceExistStr(elems interface{}, search string) bool { +func InSliceExistStr(elems any, search string) bool { switch elems.(type) { case []string: elem := gconv.Strings(elems) @@ -26,35 +24,15 @@ func InSliceExistStr(elems interface{}, search string) bool { default: return gconv.String(elems) == search } - return false } -// InSliceInt64 元素是否存在于切片中 -func InSliceInt64(slice []int64, key int64) bool { - if len(slice) == 0 { - return false - } - for i := 0; i < len(slice); i++ { - if slice[i] == key { +// InSlice 元素是否存在于切片中 +func InSlice[K comparable](slice []K, key K) bool { + for _, v := range slice { + if v == key { return true } } return false } - -func InSliceInt(slice []int, key int) bool { - if len(slice) == 0 { - return false - } - for i := 0; i < len(slice); i++ { - if slice[i] == key { - return true - } - } - return false -} - -func InSliceString(slice []string, key string) bool { - return gstr.InArray(slice, key) -}