mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-02-02 18:28:41 +08:00
模块化上传驱动,使用泛型优化工具库降低冗余
This commit is contained in:
parent
fdc48b9335
commit
62ecbb7f26
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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{}
|
||||
|
@ -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 - 网站拒绝显示此网页")
|
||||
})
|
||||
|
@ -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"
|
||||
)
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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对象存储
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -141,6 +141,5 @@ func ModuleSelect() form.Selects {
|
||||
Name: skeleton.Label,
|
||||
})
|
||||
}
|
||||
|
||||
return lst
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -66,7 +66,6 @@ func GetUser(ctx context.Context) *model.Identity {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.User
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,6 @@ func FilterAuth(m *gdb.Model) *gdb.Model {
|
||||
if !needAuth {
|
||||
return m
|
||||
}
|
||||
|
||||
return m.Handler(FilterAuthWithField(filterField))
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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"` // 认证元数据
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,6 @@ func New(name ...string) PayClient {
|
||||
default:
|
||||
panic(fmt.Sprintf("暂不支持的支付方式:%v", payType))
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -69,5 +69,4 @@ func consumerListen(ctx context.Context, job consumerStrategy) {
|
||||
}); listenErr != nil {
|
||||
g.Log().Fatalf(ctx, "消费队列:%s 监听失败, err:%+v", topic, listenErr)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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()
|
||||
})
|
||||
|
22
server/internal/library/storager/config.go
Normal file
22
server/internal/library/storager/config.go
Normal file
@ -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)
|
||||
}
|
@ -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 {
|
12
server/internal/library/storager/model.go
Normal file
12
server/internal/library/storager/model.go
Normal file
@ -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
|
||||
}
|
228
server/internal/library/storager/upload.go
Normal file
228
server/internal/library/storager/upload.go
Normal file
@ -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
|
||||
}
|
42
server/internal/library/storager/upload_cos.go
Normal file
42
server/internal/library/storager/upload_cos.go
Normal file
@ -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
|
||||
}
|
42
server/internal/library/storager/upload_local.go
Normal file
42
server/internal/library/storager/upload_local.go
Normal file
@ -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
|
||||
}
|
42
server/internal/library/storager/upload_oss.go
Normal file
42
server/internal/library/storager/upload_oss.go
Normal file
@ -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
|
||||
}
|
52
server/internal/library/storager/upload_qiniu.go
Normal file
52
server/internal/library/storager/upload_qiniu.go
Normal file
@ -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
|
||||
}
|
45
server/internal/library/storager/upload_ucloud.go
Normal file
45
server/internal/library/storager/upload_ucloud.go
Normal file
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -307,6 +307,6 @@ func (s *sAdminMenu) LoginPermissions(ctx context.Context, memberId int64) (list
|
||||
}
|
||||
}
|
||||
|
||||
lists = convert.UniqueSliceString(lists)
|
||||
lists = convert.UniqueSlice(lists)
|
||||
return
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -289,7 +289,6 @@ func (manager *ClientManager) start() {
|
||||
g.Log().Info(ctxManager, "websocket closeSignal quit..")
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))]
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -12,12 +12,6 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
const ( //文件大小单位
|
||||
_ = iota
|
||||
KB = 1 << (10 * iota)
|
||||
MB
|
||||
)
|
||||
|
||||
type fileInfo struct { //文件信息
|
||||
name string
|
||||
size int64
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
51
server/utility/simple/event.go
Normal file
51
server/utility/simple/event.go
Normal file
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user