更新2.1.2版本,优化部门、角色权限,增加上下级关系;增加登录、系统、短信日志;优化省市区编码

This commit is contained in:
孟帅
2023-01-25 11:49:21 +08:00
parent 11fad0132d
commit 93e0fe7250
190 changed files with 35896 additions and 7208 deletions

View File

@@ -44,6 +44,7 @@ var (
group.Middleware(
service.Middleware().Ctx, //必须第一个加载
service.Middleware().CORS,
service.Middleware().Blacklist,
service.Middleware().DemoLimit,
service.Middleware().ResponseHandler,
)

View File

@@ -8,6 +8,9 @@ package consts
import "github.com/gogf/gf/v2/util/gconv"
// RequestEncryptKey 请求加密密钥用于敏感数据加密16位字符前后端需保持一致。安全起见请修改此值
var RequestEncryptKey = []byte("f080a463654b2279")
// 配置数据类型
const (
ConfigTypeString = "string"

View File

@@ -8,5 +8,6 @@ package consts
// ContextKey 上下文
const (
ContextKey = "HotGoContext"
ContextKey = "HotGoContext" // http上下文变量名称
ContextKeyCronArgs = "args" // 定时任务参数上下文变量名称
)

View File

@@ -9,10 +9,9 @@ package consts
// 定时任务
const (
CronArgsKey = "args" // 上下文变量名称
CronSplitStr = "," // 变量分割符
CronPolicySame = 1 // 并行策略
CronPolicySingle = 2 // 单策略
CronPolicyOnce = 3 // 次策略
CronPolicyTimes = 4 // 多次策略
CronSplitStr = "," // 变量分割符
CronPolicySame = 1 // 并行策略
CronPolicySingle = 2 // 单例策略
CronPolicyOnce = 3 // 单策略
CronPolicyTimes = 4 // 次策略
)

View File

@@ -8,7 +8,7 @@ package consts
// 消息队列
const (
QueueName = `queue:`
QueueLogPath = "queue" // 需要在config中配置queue的log
QueueLogTopic = `request_log`
QueueLogTopic = `request_log` // 访问日志
QueueLoginLogTopic = `login_log` // 登录日志
QueueServeLogTopic = `serve_log` // 服务日志
)

View File

@@ -0,0 +1,24 @@
package consts
// 短信驱动
const (
SmsDriveAliYun = "aliyun" // 阿里云
SmsDriveTencent = "tencent" // 腾讯云
)
// 短信内置模板
const (
SmsTemplateCode = "code" // 通用验证码
SmsTemplateLogin = "login" // 登录
SmsTemplateRegister = "register" // 注册
SmsTemplateResetPwd = "resetPwd" // 重置密码
SmsTemplateBind = "bind" // 绑定手机号
SmsTemplateCash = "cash" // 申请提现
)
// 短信状态码
const (
SmsStatusNotUsed = 1 // 未使用
SmsStatusUsed = 2 // 已使用
)

View File

@@ -8,5 +8,5 @@ package consts
// VersionApp HotGo版本
const (
VersionApp = "2.1.1"
VersionApp = "2.1.2"
)

View File

@@ -204,14 +204,14 @@ func (c *cMember) View(ctx context.Context, req *member.ViewReq) (*member.ViewRe
return nil, err
}
roleList, _, err := service.AdminRole().List(ctx, adminin.RoleListInp{})
if err != nil {
return nil, err
}
//roleList, _, err := service.AdminRole().List(ctx, adminin.RoleListInp{})
//if err != nil {
// return nil, err
//}
var res member.ViewRes
res.Posts = postsList
res.Roles = roleList
//res.Roles = roleList
if req.Id <= 0 {
return &res, err

View File

@@ -10,6 +10,7 @@ import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/api/backend/monitor"
"hotgo/internal/consts"
"hotgo/internal/model/input/form"
@@ -46,9 +47,7 @@ func (c *cMonitor) Offline(ctx context.Context, req *monitor.OfflineReq) (res *m
// View 获取指定信息
func (c *cMonitor) View(ctx context.Context, req *monitor.OnlineViewReq) (*monitor.OnlineViewRes, error) {
var res monitor.OnlineViewRes
// ...
return &res, nil
return &monitor.OnlineViewRes{}, nil
}
// OnlineList 获取在线列表
@@ -63,26 +62,31 @@ func (c *cMonitor) OnlineList(ctx context.Context, req *monitor.OnlineListReq) (
return &res, nil
}
for c, _ := range c.wsManager.GetClients() {
if c.SendClose || c.User == nil {
for conn, _ := range c.wsManager.GetClients() {
if conn.SendClose || conn.User == nil {
continue
}
if req.UserId > 0 && req.UserId != c.User.Id {
if req.UserId > 0 && req.UserId != conn.User.Id {
continue
}
if req.Addr != "" && !gstr.Contains(conn.Addr, req.Addr) {
continue
}
clients = append(clients, &monitor.OnlineModel{
ID: c.ID,
Addr: c.Addr,
Os: useragent.GetOs(c.UserAgent),
Browser: useragent.GetBrowser(c.UserAgent),
FirstTime: c.FirstTime,
HeartbeatTime: c.HeartbeatTime,
App: c.User.App,
UserId: c.User.Id,
Username: c.User.Username,
Avatar: c.User.Avatar,
ExpTime: c.User.Exp,
ID: conn.ID,
Addr: conn.Addr,
Os: useragent.GetOs(conn.UserAgent),
Browser: useragent.GetBrowser(conn.UserAgent),
FirstTime: conn.FirstTime,
HeartbeatTime: conn.HeartbeatTime,
App: conn.User.App,
UserId: conn.User.Id,
Username: conn.User.Username,
Avatar: conn.User.Avatar,
ExpTime: conn.User.Exp,
})
}
@@ -96,11 +100,11 @@ func (c *cMonitor) OnlineList(ctx context.Context, req *monitor.OnlineListReq) (
for k, v := range clients {
if k >= offset && i <= perPage {
i++
if isDemo.Bool() {
v.Addr = consts.DemoTips
}
res.List = append(res.List, v)
i++
}
}

View File

@@ -19,6 +19,7 @@ import (
"hotgo/internal/library/captcha"
"hotgo/internal/library/jwt"
"hotgo/internal/model/input/adminin"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
@@ -60,28 +61,32 @@ func (c *cSite) getWsAddr(ctx context.Context) string {
// Captcha 登录验证码
func (c *cSite) Captcha(ctx context.Context, req *common.LoginCaptchaReq) (res *common.LoginCaptchaRes, err error) {
// 获取生成的验证码图片
Cid, Base64 := captcha.GetVerifyImgString(ctx)
res = &common.LoginCaptchaRes{Cid: Cid, Base64: Base64}
cid, base64 := captcha.Generate(ctx)
res = &common.LoginCaptchaRes{Cid: cid, Base64: base64}
return
}
// Login 提交登录
func (c *cSite) Login(ctx context.Context, req *common.LoginReq) (res *common.LoginRes, err error) {
//// 校验 验证码
//if !captcha.VerifyString(req.Cid, req.Code) {
// err = gerror.New("验证码错误")
// return
//}
//
var in adminin.MemberLoginInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
defer func() {
var response = new(adminin.MemberLoginModel)
if res != nil && res.MemberLoginModel != nil {
response = res.MemberLoginModel
}
service.SysLoginLog().Push(ctx, sysin.LoginLogPushInp{Input: in, Response: response, Err: err})
}()
// 校验 验证码
if !req.IsLock && !captcha.Verify(req.Cid, req.Code) {
err = gerror.New("验证码错误")
return
}
model, err := service.AdminMember().Login(ctx, in)
if err != nil {
return nil, err

View File

@@ -0,0 +1,37 @@
// Package common
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package common
import (
"context"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/common"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/validate"
)
var Sms = new(cSms)
type cSms struct{}
// SendTest 发送测试短信
func (c *cSms) SendTest(ctx context.Context, req *common.SendTestSmsReq) (res *common.SendTestSmsRes, err error) {
var in sysin.SendCodeInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysSmsLog().SendCode(ctx, in); err != nil {
return nil, err
}
return
}

View File

@@ -8,6 +8,7 @@ package sys
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/cron"
"hotgo/internal/model/input/form"
@@ -111,3 +112,17 @@ func (c *cCron) Status(ctx context.Context, req *cron.StatusReq) (res *cron.Stat
return res, nil
}
// OnlineExec 在线执行
func (c *cCron) OnlineExec(ctx context.Context, req *cron.OnlineExecReq) (res *cron.OnlineExecRes, err error) {
if req.Id <= 0 {
return nil, gerror.New("定时任务ID不能为空")
}
var in sysin.OnlineExecInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
return res, service.SysCron().OnlineExec(ctx, in)
}

View File

@@ -40,7 +40,7 @@ func (c *sLog) Export(ctx context.Context, req *log.ExportReq) (res *log.ExportR
return
}
// List 获取全局日志列表
// List 获取访问日志列表
func (c *sLog) List(ctx context.Context, req *log.ListReq) (*log.ListRes, error) {
var (
in sysin.LogListInp

View File

@@ -0,0 +1,104 @@
// Package sys
// @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
// @AutoGenerate Version 2.1.1
// @AutoGenerate Date 2023-01-19 16:57:33
//
package sys
import (
"context"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/loginlog"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/validate"
)
var (
LoginLog = cLoginLog{}
)
type cLoginLog struct{}
// List 查看登录日志列表
func (c *cLoginLog) List(ctx context.Context, req *loginlog.ListReq) (res *loginlog.ListRes, err error) {
var in sysin.LoginLogListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
list, totalCount, err := service.SysLoginLog().List(ctx, in)
if err != nil {
return nil, err
}
res = new(loginlog.ListRes)
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
return res, nil
}
// Export 导出登录日志列表
func (c *cLoginLog) Export(ctx context.Context, req *loginlog.ExportReq) (res *loginlog.ExportRes, err error) {
var in sysin.LoginLogListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysLoginLog().Export(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// View 获取指定登录日志信息
func (c *cLoginLog) View(ctx context.Context, req *loginlog.ViewReq) (res *loginlog.ViewRes, err error) {
var in sysin.LoginLogViewInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
data, err := service.SysLoginLog().View(ctx, in)
if err != nil {
return nil, err
}
res = new(loginlog.ViewRes)
res.LoginLogViewModel = data
return res, nil
}
// Delete 删除登录日志
func (c *cLoginLog) Delete(ctx context.Context, req *loginlog.DeleteReq) (res *loginlog.DeleteRes, err error) {
var in sysin.LoginLogDeleteInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysLoginLog().Delete(ctx, in); err != nil {
return nil, err
}
return res, nil
}

View File

@@ -21,6 +21,20 @@ var (
type cProvinces struct{}
// Tree 关系树选项列表
func (c *cProvinces) Tree(ctx context.Context, req *provinces.TreeReq) (*provinces.TreeRes, error) {
var (
res provinces.TreeRes
err error
)
res.List, err = service.SysProvinces().Tree(ctx)
if err != nil {
return nil, err
}
return &res, nil
}
// Delete 删除
func (c *cProvinces) Delete(ctx context.Context, req *provinces.DeleteReq) (res *provinces.DeleteRes, err error) {
var in sysin.ProvincesDeleteInp
@@ -47,15 +61,15 @@ func (c *cProvinces) Edit(ctx context.Context, req *provinces.EditReq) (res *pro
}
// MaxSort 最大排序
func (c *cProvinces) MaxSort(ctx context.Context, req *provinces.MaxSortReq) (*provinces.MaxSortRes, error) {
data, err := service.SysProvinces().MaxSort(ctx, sysin.ProvincesMaxSortInp{Id: req.Id})
func (c *cProvinces) MaxSort(ctx context.Context, req *provinces.MaxSortReq) (res *provinces.MaxSortRes, err error) {
data, err := service.SysProvinces().MaxSort(ctx, sysin.ProvincesMaxSortInp{})
if err != nil {
return nil, err
}
var res provinces.MaxSortRes
res.Sort = data.Sort
return &res, nil
res = new(provinces.MaxSortRes)
res.ProvincesMaxSortModel = data
return res, nil
}
// View 获取指定信息
@@ -104,3 +118,44 @@ func (c *cProvinces) Status(ctx context.Context, req *provinces.StatusReq) (res
return res, nil
}
// ChildrenList 获取省市区下级列表
func (c *cProvinces) ChildrenList(ctx context.Context, req *provinces.ChildrenListReq) (*provinces.ChildrenListRes, error) {
var (
in sysin.ProvincesChildrenListInp
res provinces.ChildrenListRes
)
if err := gconv.Scan(req, &in); err != nil {
return nil, err
}
list, totalCount, err := service.SysProvinces().ChildrenList(ctx, in)
if err != nil {
return nil, err
}
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
return &res, nil
}
// UniqueId 地区ID是否唯一
func (c *cProvinces) UniqueId(ctx context.Context, req *provinces.UniqueIdReq) (res *provinces.UniqueIdRes, err error) {
var in sysin.ProvincesUniqueIdInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
data, err := service.SysProvinces().UniqueId(ctx, in)
if err != nil {
return nil, err
}
res = new(provinces.UniqueIdRes)
res.ProvincesUniqueIdModel = data
return res, nil
}

View File

@@ -0,0 +1,102 @@
// Package sys
// @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 sys
import (
"context"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/servelog"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/validate"
)
var (
ServeLog = cServeLog{}
)
type cServeLog struct{}
// List 查看服务日志列表
func (c *cServeLog) List(ctx context.Context, req *servelog.ListReq) (res *servelog.ListRes, err error) {
var in sysin.ServeLogListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
list, totalCount, err := service.SysServeLog().List(ctx, in)
if err != nil {
return nil, err
}
res = new(servelog.ListRes)
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
return res, nil
}
// Export 导出服务日志列表
func (c *cServeLog) Export(ctx context.Context, req *servelog.ExportReq) (res *servelog.ExportRes, err error) {
var in sysin.ServeLogListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysServeLog().Export(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// View 获取指定服务日志信息
func (c *cServeLog) View(ctx context.Context, req *servelog.ViewReq) (res *servelog.ViewRes, err error) {
var in sysin.ServeLogViewInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
data, err := service.SysServeLog().View(ctx, in)
if err != nil {
return nil, err
}
res = new(servelog.ViewRes)
res.ServeLogViewModel = data
return res, nil
}
// Delete 删除服务日志
func (c *cServeLog) Delete(ctx context.Context, req *servelog.DeleteReq) (res *servelog.DeleteRes, err error) {
var in sysin.ServeLogDeleteInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysServeLog().Delete(ctx, in); err != nil {
return nil, err
}
return res, nil
}

View File

@@ -0,0 +1,113 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package sys
import (
"context"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/smslog"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
var (
SmsLog = cSmsLog{}
)
type cSmsLog struct{}
// Delete 删除
func (c *cSmsLog) Delete(ctx context.Context, req *smslog.DeleteReq) (res *smslog.DeleteRes, err error) {
var in sysin.SmsLogDeleteInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.SysSmsLog().Delete(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Edit 更新
func (c *cSmsLog) Edit(ctx context.Context, req *smslog.EditReq) (res *smslog.EditRes, err error) {
var in sysin.SmsLogEditInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.SysSmsLog().Edit(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// MaxSort 最大排序
func (c *cSmsLog) MaxSort(ctx context.Context, req *smslog.MaxSortReq) (*smslog.MaxSortRes, error) {
data, err := service.SysSmsLog().MaxSort(ctx, sysin.SmsLogMaxSortInp{Id: req.Id})
if err != nil {
return nil, err
}
var res smslog.MaxSortRes
res.Sort = data.Sort
return &res, nil
}
// View 获取指定信息
func (c *cSmsLog) View(ctx context.Context, req *smslog.ViewReq) (*smslog.ViewRes, error) {
data, err := service.SysSmsLog().View(ctx, sysin.SmsLogViewInp{Id: req.Id})
if err != nil {
return nil, err
}
var res smslog.ViewRes
res.SmsLogViewModel = data
return &res, nil
}
// List 查看列表
func (c *cSmsLog) List(ctx context.Context, req *smslog.ListReq) (*smslog.ListRes, error) {
var (
in sysin.SmsLogListInp
res smslog.ListRes
)
if err := gconv.Scan(req, &in); err != nil {
return nil, err
}
list, totalCount, err := service.SysSmsLog().List(ctx, in)
if err != nil {
return nil, err
}
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
return &res, nil
}
// Status 更新部门状态
func (c *cSmsLog) Status(ctx context.Context, req *smslog.StatusReq) (res *smslog.StatusRes, err error) {
var in sysin.SmsLogStatusInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.SysSmsLog().Status(ctx, in); err != nil {
return nil, err
}
return res, nil
}

View File

@@ -20,21 +20,17 @@ import (
"sync"
)
var (
// 添加新的任务时只需实现cronStrategy接口并加入到cronList即可
cronList = []cronStrategy{
Test, // 测试无参任务
Test2, // 测试有参任务
Monitor, // 监控
}
inst = new(tasks)
)
type cronStrategy interface {
GetName() string
Execute(ctx context.Context)
}
var (
// 添加新的任务时只需实现cronStrategy接口并加入到cronList即可
cronList []cronStrategy
inst = new(tasks)
)
type tasks struct {
list []*TaskItem
sync.RWMutex
@@ -49,7 +45,7 @@ type TaskItem struct {
Count int // 执行次数仅Policy=4时有效
}
func init() {
func LoadCronList() {
for _, cron := range cronList {
inst.Add(&TaskItem{
Name: cron.GetName(),
@@ -66,6 +62,10 @@ func StopALL() {
// StartALL 启动任务
func StartALL(sysCron []*entity.SysCron) error {
if len(inst.list) == 0 {
LoadCronList()
}
var (
err error
ct = gctx.New()
@@ -86,7 +86,7 @@ func StartALL(sysCron []*entity.SysCron) error {
if gcron.Search(cron.Name) == nil {
var (
t *gcron.Entry
ctx = context.WithValue(gctx.New(), consts.CronArgsKey, strings.Split(cron.Params, consts.CronSplitStr))
ctx = context.WithValue(gctx.New(), consts.ContextKeyCronArgs, strings.Split(cron.Params, consts.CronSplitStr))
)
switch cron.Policy {
case consts.CronPolicySame:
@@ -130,7 +130,7 @@ func StartALL(sysCron []*entity.SysCron) error {
}
}
g.Log().Debug(ct, "load scheduled task complete..")
g.Log().Debug(ct, "load cron success..")
return nil
}
@@ -140,8 +140,15 @@ func Stop(sysCron *entity.SysCron) error {
}
// Once 立即执行一次某个任务
func Once(sysCron *entity.SysCron) error {
return nil
func Once(ctx context.Context, sysCron *entity.SysCron) error {
for _, v := range cronList {
if v.GetName() == sysCron.Name {
go v.Execute(ctx)
return nil
}
}
return gerror.Newf("定时任务不存在:%+v", sysCron.Name)
}
// Delete 删除任务

View File

@@ -18,6 +18,10 @@ import (
"sync"
)
func init() {
cronList = append(cronList, Monitor)
}
// Monitor 监控
var Monitor = &cMonitor{name: "monitor"}

View File

@@ -12,6 +12,10 @@ import (
"time"
)
func init() {
cronList = append(cronList, Test)
}
// Test 测试任务
var Test = &cTest{name: "test"}

View File

@@ -13,6 +13,10 @@ import (
"time"
)
func init() {
cronList = append(cronList, Test2)
}
// Test2 测试2任务
var Test2 = &cTest2{name: "test2"}
@@ -26,7 +30,7 @@ func (c *cTest2) GetName() string {
// Execute 执行任务
func (c *cTest2) Execute(ctx context.Context) {
args, ok := ctx.Value(consts.CronArgsKey).([]string)
args, ok := ctx.Value(consts.ContextKeyCronArgs).([]string)
if !ok {
g.Log().Warning(ctx, "参数解析失败!")
return

View File

@@ -28,6 +28,8 @@ type AdminDeptColumns struct {
Leader string // 负责人
Phone string // 联系电话
Email string // 邮箱
Level string // 关系树等级
Tree string // 关系树
Sort string // 排序
Status string // 部门状态
CreatedAt string // 创建时间
@@ -44,6 +46,8 @@ var adminDeptColumns = AdminDeptColumns{
Leader: "leader",
Phone: "phone",
Email: "email",
Level: "level",
Tree: "tree",
Sort: "sort",
Status: "status",
CreatedAt: "created_at",

View File

@@ -1,143 +0,0 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// DemoDao is the data access object for table hg_demo.
type DemoDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns DemoColumns // columns contains all the column names of Table for convenient usage.
}
// DemoColumns defines and stores column names for table hg_demo.
type DemoColumns struct {
Id string // ID
CategoryId string // 分类ID
Flag string // 标签
Title string // 标题
Description string // 描述
Content string // 内容
Image string // 单图
Images string // 多图
Attachfile string // 附件
Attachfiles string // 多附件
Map string // 动态键值对
Star string // 推荐星
Price string // 价格
Views string // 浏览次数
ActivityAt string // 活动时间
StartAt string // 开启时间
EndAt string // 结束时间
Switch string // 开关
Sort string // 排序
Avatar string // 头像
Sex string // 性别
Qq string // qq
Email string // 邮箱
Mobile string // 手机号码
Hobby string // 爱好
Channel string // 渠道
Pid string // 上级ID
Level string // 树等级
Tree string // 关系树
Remark string // 备注
Status string // 状态
CreatedBy string // 创建者
UpdatedBy string // 更新者
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
DeletedAt string // 删除时间
}
// demoColumns holds the columns for table hg_demo.
var demoColumns = DemoColumns{
Id: "id",
CategoryId: "category_id",
Flag: "flag",
Title: "title",
Description: "description",
Content: "content",
Image: "image",
Images: "images",
Attachfile: "attachfile",
Attachfiles: "attachfiles",
Map: "map",
Star: "star",
Price: "price",
Views: "views",
ActivityAt: "activity_at",
StartAt: "start_at",
EndAt: "end_at",
Switch: "switch",
Sort: "sort",
Avatar: "avatar",
Sex: "sex",
Qq: "qq",
Email: "email",
Mobile: "mobile",
Hobby: "hobby",
Channel: "channel",
Pid: "pid",
Level: "level",
Tree: "tree",
Remark: "remark",
Status: "status",
CreatedBy: "created_by",
UpdatedBy: "updated_by",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
DeletedAt: "deleted_at",
}
// NewDemoDao creates and returns a new DAO object for table data access.
func NewDemoDao() *DemoDao {
return &DemoDao{
group: "default",
table: "hg_demo",
columns: demoColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *DemoDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *DemoDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *DemoDao) Columns() DemoColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *DemoDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *DemoDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *DemoDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@@ -21,6 +21,7 @@ type SysLogDao struct {
// SysLogColumns defines and stores column names for table hg_sys_log.
type SysLogColumns struct {
Id string // 日志ID
ReqId string // 对外ID
AppId string // 应用ID
MerchantId string // 商户ID
MemberId string // 用户ID
@@ -36,10 +37,9 @@ type SysLogColumns struct {
ErrorCode string // 报错code
ErrorMsg string // 报错信息
ErrorData string // 报错日志
ReqId string // 对外ID
Timestamp string // 响应时间
UserAgent string // UA信息
TakeUpTime string // 请求耗时
Timestamp string // 响应时间
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
@@ -48,6 +48,7 @@ type SysLogColumns struct {
// sysLogColumns holds the columns for table hg_sys_log.
var sysLogColumns = SysLogColumns{
Id: "id",
ReqId: "req_id",
AppId: "app_id",
MerchantId: "merchant_id",
MemberId: "member_id",
@@ -63,10 +64,9 @@ var sysLogColumns = SysLogColumns{
ErrorCode: "error_code",
ErrorMsg: "error_msg",
ErrorData: "error_data",
ReqId: "req_id",
Timestamp: "timestamp",
UserAgent: "user_agent",
TakeUpTime: "take_up_time",
Timestamp: "timestamp",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",

View File

@@ -0,0 +1,91 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// SysLoginLogDao is the data access object for table hg_sys_login_log.
type SysLoginLogDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns SysLoginLogColumns // columns contains all the column names of Table for convenient usage.
}
// SysLoginLogColumns defines and stores column names for table hg_sys_login_log.
type SysLoginLogColumns struct {
Id string // 日志ID
ReqId string // 请求ID
MemberId string // 用户ID
Username string // 用户名
Response string // 响应数据
LoginAt string // 登录时间
ErrMsg string // 错误提示
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
}
// sysLoginLogColumns holds the columns for table hg_sys_login_log.
var sysLoginLogColumns = SysLoginLogColumns{
Id: "id",
ReqId: "req_id",
MemberId: "member_id",
Username: "username",
Response: "response",
LoginAt: "login_at",
ErrMsg: "err_msg",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewSysLoginLogDao creates and returns a new DAO object for table data access.
func NewSysLoginLogDao() *SysLoginLogDao {
return &SysLoginLogDao{
group: "default",
table: "hg_sys_login_log",
columns: sysLoginLogColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *SysLoginLogDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *SysLoginLogDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *SysLoginLogDao) Columns() SysLoginLogColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *SysLoginLogDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *SysLoginLogDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysLoginLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@@ -20,40 +20,34 @@ type SysProvincesDao struct {
// SysProvincesColumns defines and stores column names for table hg_sys_provinces.
type SysProvincesColumns struct {
Id string // 省市区ID
Title string // 栏目名称
ShortTitle string // 缩写
Areacode string // 区域编码
Zipcode string // 邮政编码
Pinyin string // 拼音
Lng string // 经度
Lat string // 纬度
Pid string // 父栏目
Level string // 关系树等级
Tree string // 关系
Sort string // 排序
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
Id string // 省市区ID
Title string // 栏目名称
Pinyin string // 拼音
Lng string // 经度
Lat string // 纬度
Pid string // 父栏目
Level string // 关系树等级
Tree string // 关系
Sort string // 排序
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysProvincesColumns holds the columns for table hg_sys_provinces.
var sysProvincesColumns = SysProvincesColumns{
Id: "id",
Title: "title",
ShortTitle: "short_title",
Areacode: "areacode",
Zipcode: "zipcode",
Pinyin: "pinyin",
Lng: "lng",
Lat: "lat",
Pid: "pid",
Level: "level",
Tree: "tree",
Sort: "sort",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
Id: "id",
Title: "title",
Pinyin: "pinyin",
Lng: "lng",
Lat: "lat",
Pid: "pid",
Level: "level",
Tree: "tree",
Sort: "sort",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewSysProvincesDao creates and returns a new DAO object for table data access.

View File

@@ -0,0 +1,91 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// SysServeLogDao is the data access object for table hg_sys_serve_log.
type SysServeLogDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns SysServeLogColumns // columns contains all the column names of Table for convenient usage.
}
// SysServeLogColumns defines and stores column names for table hg_sys_serve_log.
type SysServeLogColumns struct {
Id string // 日志ID
TraceId string // 链路ID
LevelFormat string // 日志级别
Content string // 日志内容
Stack string // 打印堆栈
Line string // 调用行
TriggerNs string // 触发时间(ns)
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
}
// sysServeLogColumns holds the columns for table hg_sys_serve_log.
var sysServeLogColumns = SysServeLogColumns{
Id: "id",
TraceId: "trace_id",
LevelFormat: "level_format",
Content: "content",
Stack: "stack",
Line: "line",
TriggerNs: "trigger_ns",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewSysServeLogDao creates and returns a new DAO object for table data access.
func NewSysServeLogDao() *SysServeLogDao {
return &SysServeLogDao{
group: "default",
table: "hg_sys_serve_log",
columns: sysServeLogColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *SysServeLogDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *SysServeLogDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *SysServeLogDao) Columns() SysServeLogColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *SysServeLogDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *SysServeLogDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysServeLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@@ -0,0 +1,89 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// SysSmsLogDao is the data access object for table hg_sys_sms_log.
type SysSmsLogDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns SysSmsLogColumns // columns contains all the column names of Table for convenient usage.
}
// SysSmsLogColumns defines and stores column names for table hg_sys_sms_log.
type SysSmsLogColumns struct {
Id string // 主键
Event string // 事件
Mobile string // 手机号
Code string // 验证码或短信内容
Times string // 验证次数
Ip string // ip地址
Status string // 状态(1未验证,2已验证)
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysSmsLogColumns holds the columns for table hg_sys_sms_log.
var sysSmsLogColumns = SysSmsLogColumns{
Id: "id",
Event: "event",
Mobile: "mobile",
Code: "code",
Times: "times",
Ip: "ip",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewSysSmsLogDao creates and returns a new DAO object for table data access.
func NewSysSmsLogDao() *SysSmsLogDao {
return &SysSmsLogDao{
group: "default",
table: "hg_sys_sms_log",
columns: sysSmsLogColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *SysSmsLogDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *SysSmsLogDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *SysSmsLogDao) Columns() SysSmsLogColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *SysSmsLogDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *SysSmsLogDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysSmsLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@@ -7,7 +7,6 @@ package dao
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/consts"
"hotgo/internal/dao/internal"
"hotgo/internal/model/entity"
@@ -67,7 +66,6 @@ func (dao *sysDictTypeDao) GetTypes(ctx context.Context, id int64) (types []stri
types = append(types, v.String())
}
g.Log().Warningf(ctx, "types:%+v", types)
return types, nil
}
@@ -81,7 +79,6 @@ func (dao *sysDictTypeDao) GetType(ctx context.Context, id int64) (types string,
return types, err
}
g.Log().Warningf(ctx, "GetType types:%+v", list.String())
return list.String(), nil
}

View File

@@ -8,19 +8,19 @@ import (
"hotgo/internal/dao/internal"
)
// internalDemoDao is internal type for wrapping internal DAO implements.
type internalDemoDao = *internal.DemoDao
// internalSysLoginLogDao is internal type for wrapping internal DAO implements.
type internalSysLoginLogDao = *internal.SysLoginLogDao
// demoDao is the data access object for table hg_demo.
// sysLoginLogDao is the data access object for table hg_sys_login_log.
// You can define custom methods on it to extend its functionality as you wish.
type demoDao struct {
internalDemoDao
type sysLoginLogDao struct {
internalSysLoginLogDao
}
var (
// Demo is globally public accessible object for table hg_demo operations.
Demo = demoDao{
internal.NewDemoDao(),
// SysLoginLog is globally public accessible object for table hg_sys_login_log operations.
SysLoginLog = sysLoginLogDao{
internal.NewSysLoginLogDao(),
}
)

View File

@@ -31,20 +31,20 @@ var (
// Fill with you ideas below.
// GetRegion 获取省市编码对应的地区名称
func (dao *sysProvincesDao) GetRegion(ctx context.Context, province int, city int, spilt ...string) (string, error) {
func (dao *sysProvincesDao) GetRegion(ctx context.Context, province int64, city int64, spilt ...string) (string, error) {
var (
provinceName *gvar.Var
cityName *gvar.Var
err error
)
// TODO 默认分隔符
// 分隔符
spiltSymbol := "-"
if len(spilt) > 0 {
spiltSymbol = spilt[0]
}
if province > 0 {
if province > 0 && province < 999999 {
provinceName, err = dao.Ctx(ctx).Where("id", province).Fields("title").Value()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)

View File

@@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"hotgo/internal/dao/internal"
)
// internalSysServeLogDao is internal type for wrapping internal DAO implements.
type internalSysServeLogDao = *internal.SysServeLogDao
// sysServeLogDao is the data access object for table hg_sys_serve_log.
// You can define custom methods on it to extend its functionality as you wish.
type sysServeLogDao struct {
internalSysServeLogDao
}
var (
// SysServeLog is globally public accessible object for table hg_sys_serve_log operations.
SysServeLog = sysServeLogDao{
internal.NewSysServeLogDao(),
}
)
// Fill with you ideas below.

View File

@@ -0,0 +1,43 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"context"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/dao/internal"
)
// internalSysSmsLogDao is internal type for wrapping internal DAO implements.
type internalSysSmsLogDao = *internal.SysSmsLogDao
// sysSmsLogDao is the data access object for table hg_sys_sms_log.
// You can define custom methods on it to extend its functionality as you wish.
type sysSmsLogDao struct {
internalSysSmsLogDao
}
var (
// SysSmsLog is globally public accessible object for table hg_sys_sms_log operations.
SysSmsLog = sysSmsLogDao{
internal.NewSysSmsLogDao(),
}
)
// Fill with you ideas below.
// NowDayCount 当天发送次数
func (dao *sysSmsLogDao) NowDayCount(ctx context.Context, event, mobile string) (count int, err error) {
count, err = dao.Ctx(ctx).
Where("mobile", mobile).
Where("event", event).
WhereGTE("created_at", gtime.Now().Format("Y-m-d")).
Count()
if err != nil {
return 0, err
}
return
}

View File

@@ -10,20 +10,32 @@ import (
"context"
"fmt"
"github.com/gogf/gf/v2"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/consts"
"hotgo/internal/library/hggen"
"hotgo/internal/library/location"
"hotgo/internal/library/queue"
"hotgo/internal/model/entity"
"hotgo/internal/service"
"hotgo/utility/charset"
"hotgo/utility/simple"
"os"
)
func Init(ctx context.Context) {
if _, err := g.Cfg().Get(ctx, "hotgo.debug"); err != nil {
_, err := g.Cfg().Get(ctx, "hotgo.debug")
if err != nil {
g.Log().Fatal(ctx, "配置读取异常:", err, "\r\n你确定 config/config.yaml 文件存在且格式正确吗?\r\n")
return
}
//g.SetDebug(debug.Bool())
// 默认上海时区
if err := gtime.SetTimeZone("Asia/Shanghai"); err != nil {
g.Log().Fatalf(ctx, "时区设置异常err%+v", err)
@@ -33,12 +45,15 @@ func Init(ctx context.Context) {
RootPtah, _ = os.Getwd()
fmt.Printf("欢迎使用HotGo\r\n当前运行环境%v, 运行根路径为:%v \r\nHotGo版本v%v, gf版本%v \n", SysType, RootPtah, consts.VersionApp, gf.VERSION)
g.Log().SetHandlers(LoggingServeLogHandler)
setOrmCacheAdapter()
service.SysBlacklist().Load(ctx)
startMonitor(ctx)
hggen.InIt(ctx)
}
func startMonitor(ctx context.Context) {
@@ -62,3 +77,47 @@ func setOrmCacheAdapter() {
redisCache := gcache.NewAdapterRedis(g.Redis())
g.DB().GetCache().SetAdapter(redisCache)
}
func LoggingServeLogHandler(ctx context.Context, in *glog.HandlerInput) {
in.Next(ctx)
conf, err := service.SysConfig().GetLoadServeLog(ctx)
if err != nil {
return
}
if !conf.Switch {
return
}
if in.LevelFormat == "" || !gstr.InArray(conf.LevelFormat, in.LevelFormat) {
return
}
var data entity.SysServeLog
data.TraceId = gctx.CtxId(ctx)
data.LevelFormat = in.LevelFormat
data.Content = in.Content
data.Stack = gjson.New(charset.ParseStack(in.Stack))
data.Line = in.CallerPath
data.TriggerNs = in.Time.UnixNano()
data.Status = consts.StatusEnabled
if data.Stack.IsNil() {
data.Stack = gjson.New(consts.NilJsonToString)
}
if gstr.Contains(in.Content, `exception recovered`) {
data.LevelFormat = "PANI"
}
if conf.Queue {
err = queue.Push(consts.QueueServeLogTopic, data)
} else {
err = service.SysServeLog().RealWrite(ctx, data)
}
if err != nil {
g.Log().Printf(ctx, "LoggingServeLogHandler err:%+v", err)
}
}

View File

@@ -18,4 +18,6 @@ var (
SysType = runtime.GOOS
// MonitorData 监控数据
MonitorData model.MonitorData
// Blacklists 黑名单列表
Blacklists map[string]struct{}
)

View File

@@ -11,34 +11,53 @@ import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
"github.com/mojocn/base64Captcha"
"image/color"
)
// GetVerifyImgString 生成验证码
func GetVerifyImgString(ctx context.Context) (idKeyC string, base64stringC string) {
driver := &base64Captcha.DriverString{
Height: 80,
Width: 240,
//NoiseCount: 50,
//ShowLineOptions: 20,
Length: 4,
Source: "abcdefghjkmnpqrstuvwxyz23456789",
Fonts: []string{"chromohv.ttf"},
// Generate 生成验证码
func Generate(ctx context.Context) (id string, base64 string) {
// 字符
//driver := &base64Captcha.DriverString{
// Height: 42,
// Width: 100,
// //NoiseCount: 50,
// //ShowLineOptions: 20,
// Length: 4,
// BgColor: &color.RGBA{
// R: 255,
// G: 250,
// B: 250,
// A: 250,
// },
// Source: "0123456789", // abcdefghjkmnpqrstuvwxyz23456789
// Fonts: []string{"chromohv.ttf"},
//}
// 计算
driver := &base64Captcha.DriverMath{
Height: 42,
Width: 100,
NoiseCount: 0,
ShowLineOptions: 0,
BgColor: &color.RGBA{
R: 255,
G: 250,
B: 250,
A: 250,
},
Fonts: []string{"chromohv.ttf"},
}
driver = driver.ConvertFonts()
store := base64Captcha.DefaultMemStore
c := base64Captcha.NewCaptcha(driver, store)
idKeyC, base64stringC, err := c.Generate()
c := base64Captcha.NewCaptcha(driver.ConvertFonts(), base64Captcha.DefaultMemStore)
id, base64, err := c.Generate()
if err != nil {
g.Log().Error(ctx, err)
g.Log().Errorf(ctx, "captcha.Generate err:%+v", err)
}
return
}
// VerifyString 验证输入的验证码是否正确
func VerifyString(id, answer string) bool {
driver := new(base64Captcha.DriverString)
store := base64Captcha.DefaultMemStore
c := base64Captcha.NewCaptcha(driver, store)
answer = gstr.ToLower(answer)
return c.Verify(id, answer, true)
// Verify 验证输入的验证码是否正确
func Verify(id, answer string) bool {
c := base64Captcha.NewCaptcha(new(base64Captcha.DriverString), base64Captcha.DefaultMemStore)
return c.Verify(id, gstr.ToLower(answer), true)
}

View File

@@ -35,7 +35,7 @@ func SetUser(ctx context.Context, user *model.Identity) {
Get(ctx).User = user
}
// SetResponse 设置组件响应 用于全局日志使用
// SetResponse 设置组件响应 用于访问日志使用
func SetResponse(ctx context.Context, response *model.Response) {
Get(ctx).Response = response
}

View File

@@ -8,10 +8,53 @@ package views
import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
)
func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) {
data = make(g.Map)
return
const (
IndexApiImport = " import {%v } from '@/api/%s';"
IndexIconsImport = " import {%v } from '@vicons/antd';"
)
func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (g.Map, error) {
var (
data = make(g.Map)
apiImport = []string{" List"}
iconsImport []string
)
// 添加
if in.options.Step.HasAdd {
iconsImport = append(iconsImport, " PlusOutlined")
}
// 编辑
if in.options.Step.HasEdit {
}
// 导出
if in.options.Step.HasExport {
iconsImport = append(iconsImport, " ExportOutlined")
apiImport = append(apiImport, " Export")
}
// 删除
if in.options.Step.HasDel || in.options.Step.HasBatchDel {
iconsImport = append(iconsImport, " DeleteOutlined")
apiImport = append(apiImport, " Delete")
}
// 导出
if in.options.Step.HasStatus {
apiImport = append(apiImport, " Status")
}
data["apiImport"] = fmt.Sprintf(IndexApiImport, gstr.Implode(",", apiImport), gstr.LcFirst(in.In.VarName))
if len(iconsImport) > 0 {
data["iconsImport"] = fmt.Sprintf(IndexIconsImport, gstr.Implode(",", iconsImport))
}
return data, nil
}

View File

@@ -259,10 +259,10 @@ func (l *gCurd) generateWebModelColumnsEach(buffer *bytes.Buffer, in *CurdPrevie
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s) || !isArray(row.%s)) {\n return ``;\n }\n return row.%s.map((tagKey) => {\n return h(\n NTag,\n {\n style: {\n marginRight: '6px',\n },\n type: getOptionTag(options.value.%s, tagKey),\n bordered: false,\n },\n {\n default: () => getOptionLabel(options.value.%s, tagKey),\n }\n );\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
case FormModeUploadImage:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n return h(%s, {\n width: 32,\n height: 32,\n src: row.%s,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n },\n });\n },\n },\n", field.Dc, field.TsName, "NImage", field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n return h(%s, {\n width: 32,\n height: 32,\n src: row.%s,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n },\n });\n },\n },\n", field.Dc, field.TsName, "NImage", field.TsName)
case FormModeUploadImages:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((image) => {\n return h(%s, {\n width: 32,\n height: 32,\n src: image,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n 'margin-left': '2px',\n },\n });\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, "NImage")
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((image) => {\n return h(%s, {\n width: 32,\n height: 32,\n src: image,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n 'margin-left': '2px',\n },\n });\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, "NImage")
case FormModeUploadFile:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (row.%s === '') {\n return ``;\n }\n return h(\n %s,\n {\n size: 'small',\n },\n {\n default: () => getFileExt(row.%s),\n }\n );\n },\n },\n", field.Dc, field.TsName, field.TsName, "NAvatar", field.TsName)

View File

@@ -208,7 +208,7 @@ func IsUnique(ctx context.Context, dao interface{}, where g.Map, message string,
// GenSubTree 生成下级关系树
func GenSubTree(ctx context.Context, dao interface{}, oldPid int64) (newPid int64, newLevel int, subTree string, err error) {
// 顶级树
if oldPid == 0 {
if oldPid <= 0 {
return 0, 1, "", nil
}
@@ -221,7 +221,7 @@ func GenSubTree(ctx context.Context, dao interface{}, oldPid int64) (newPid int6
return 0, 0, "", err
}
models, err := d.Ctx(ctx).WhereNot(field, oldPid).One()
models, err := d.Ctx(ctx).Where(field, oldPid).One()
if err != nil {
return 0, 0, "", err
}

View File

@@ -15,6 +15,7 @@ import (
"hotgo/internal/consts"
"hotgo/internal/library/contexts"
"hotgo/internal/model/entity"
"hotgo/utility/tree"
)
// HandlerFilterAuth 过滤数据权限
@@ -23,7 +24,7 @@ func HandlerFilterAuth(m *gdb.Model) *gdb.Model {
var (
needAuth bool
filterField string
roleModel *entity.AdminRole
role *entity.AdminRole
ctx = m.GetCtx()
fields = escapeFieldsToSlice(m.GetFieldsStr())
co = contexts.Get(ctx)
@@ -48,34 +49,35 @@ func HandlerFilterAuth(m *gdb.Model) *gdb.Model {
return m
}
err := g.Model("admin_role").Where("id", co.User.RoleId).Scan(&roleModel)
err := g.Model("admin_role").Where("id", co.User.RoleId).Scan(&role)
if err != nil {
panic(fmt.Sprintf("HandlerFilterAuth Failed to role information err:%+v", err))
panic(fmt.Sprintf("failed to role information err:%+v", err))
}
if roleModel == nil {
panic(fmt.Sprintf("HandlerFilterAuth Failed to role information err2:%+v", err))
if role == nil {
panic("failed to role information roleModel == nil")
}
// TODO 当前不是完整功能,预计在下个版本中完善
switch roleModel.DataScope {
sq := g.Model("admin_member").Fields("id")
switch role.DataScope {
case consts.RoleDataAll: // 全部权限
// ...
case consts.RoleDataNowDept: // 当前部门
m = m.Where(filterField, co.User.DeptId)
m = m.WhereIn(filterField, sq.Where("dept_id", co.User.DeptId))
case consts.RoleDataDeptAndSub: // 当前部门及以下部门
//m = m.Where(filterField, 1)
m = m.WhereIn(filterField, sq.WhereIn("dept_id", GetDeptAndSub(co.User.DeptId)))
case consts.RoleDataDeptCustom: // 自定义部门
m = m.WhereIn(filterField, roleModel.CustomDept.Var().Ints())
m = m.WhereIn(filterField, sq.WhereIn("dept_id", role.CustomDept.Var().Ints()))
case consts.RoleDataSelf: // 仅自己
m = m.Where(filterField, co.User.Id)
case consts.RoleDataSelfAndSub: // 自己和直属下级
//m = m.Where(filterField, 1)
m = m.WhereIn(filterField, GetSelfAndSub(co.User.Id))
case consts.RoleDataSelfAndAllSub: // 自己和全部下级
//m = m.Where(filterField, 1)
m = m.WhereIn(filterField, GetSelfAndAllSub(co.User.Id))
default:
panic("HandlerFilterAuth dataScope is not registered")
panic("dataScope is not registered")
}
return m
@@ -90,3 +92,57 @@ func HandlerForceCache(m *gdb.Model) *gdb.Model {
func escapeFieldsToSlice(s string) []string {
return gstr.Explode(",", gstr.Replace(gstr.Replace(s, "`,`", ","), "`", ""))
}
// GetDeptAndSub 获取指定部门的所有下级,含本部门
func GetDeptAndSub(deptId int64) (ids []int64) {
array, err := g.Model("admin_dept").
WhereLike("tree", "%"+tree.GetIdLabel(deptId)+"%").
Fields("id").
Array()
if err != nil {
return
}
for _, v := range array {
ids = append(ids, v.Int64())
}
ids = append(ids, deptId)
return
}
// GetSelfAndSub 获取直属下级,包含自己
func GetSelfAndSub(memberId int64) (ids []int64) {
array, err := g.Model("admin_member").
Where("pid", memberId).
Fields("id").
Array()
if err != nil {
return
}
for _, v := range array {
ids = append(ids, v.Int64())
}
ids = append(ids, memberId)
return
}
// GetSelfAndAllSub 获取全部下级,包含自己
func GetSelfAndAllSub(memberId int64) (ids []int64) {
array, err := g.Model("admin_member").
WhereLike("tree", "%"+tree.GetIdLabel(memberId)+"%").
Fields("id").
Array()
if err != nil {
return
}
for _, v := range array {
ids = append(ids, v.Int64())
}
ids = append(ids, memberId)
return
}

View File

@@ -23,7 +23,7 @@ import (
)
// GenerateLoginToken 为指定用户生成token
func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh bool) (interface{}, error) {
func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh bool) (string, error) {
var (
jwtVersion = g.Cfg().MustGet(ctx, "jwt.version", "1.0")
jwtSign = g.Cfg().MustGet(ctx, "jwt.sign", "hotGo")
@@ -51,7 +51,7 @@ func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh boo
tokenString, err := token.SignedString(jwtSign.Bytes())
if err != nil {
return nil, gerror.New(err.Error())
return "", err
}
var (
@@ -65,12 +65,12 @@ func GenerateLoginToken(ctx context.Context, user *model.Identity, isRefresh boo
err = c.Set(ctx, key, tokenString, expires)
if err != nil {
return nil, gerror.New(err.Error())
return "", err
}
err = c.Set(ctx, consts.RedisJwtUserBind+user.App+":"+gconv.String(user.Id), key, expires)
if err != nil {
return nil, gerror.New(err.Error())
return "", err
}
return tokenString, err
}

View File

@@ -144,6 +144,11 @@ func GetPublicIP(ctx context.Context) (ip string, err error) {
g.Log().Warningf(ctx, "GetPublicIP alternatives are being tried err:%+v", err)
return GetPublicIP2()
}
if data == nil {
g.Log().Warningf(ctx, "publicIP address Parsing failure, check the network and firewall blocking.")
return "0.0.0.0", nil
}
return data.Ip, nil
}
@@ -190,5 +195,10 @@ func GetClientIp(r *ghttp.Request) string {
if ip == "" {
ip = r.GetClientIp()
}
// 如果存在多个,默认取第一个
if gstr.Contains(ip, ",") {
ip = gstr.TrimStr(ip, ",", -1)
}
return ip
}

View File

@@ -93,7 +93,7 @@ func InstanceProducer() (mqClient MqProducer, err error) {
return NewProducer(config.GroupName)
}
// NewProducer 新建一个生产者实例
// NewProducer 初始化生产者实例
func NewProducer(groupName string) (mqClient MqProducer, err error) {
if item, ok := mqProducerInstanceMap[groupName]; ok {
return item, nil
@@ -143,7 +143,7 @@ func NewProducer(groupName string) (mqClient MqProducer, err error) {
return mqClient, nil
}
// NewConsumer 新建一个消费者实例
// NewConsumer 初始化消费者实例
func NewConsumer(groupName string) (mqClient MqConsumer, err error) {
randTag := string(charset.RandomCreateBytes(6))

View File

@@ -87,30 +87,28 @@ func (r *KafkaMq) ListenReceiveMsgDo(topic string, receiveDo func(mqMsg MqMsg))
}
ctx, cancel := context.WithCancel(context.Background())
go func() {
go func(ctx context.Context) {
for {
if err := r.consumerIns.Consume(ctx, []string{topic}, &consumer); err != nil {
FatalLog(ctx, "kafka Error from consumer", err)
g.Log().Fatalf(ctx, "kafka Error from consumer, err%+v", err)
}
if ctx.Err() != nil {
Log(ctx, fmt.Sprintf("kafka consoumer stop : %v", ctx.Err()))
g.Log().Debugf(ctx, fmt.Sprintf("kafka consoumer stop : %v", ctx.Err()))
return
}
consumer.ready = make(chan bool)
}
}()
}(ctx)
<-consumer.ready // Await till the consumer has been set up
Log(ctx, "kafka consumer up and running!...")
g.Log().Debug(ctx, "kafka consumer up and running!...")
signal.AppDefer(func() {
Log(ctx, "kafka consumer close...")
g.Log().Debug(ctx, "kafka consumer close...")
cancel()
if err = r.consumerIns.Close(); err != nil {
FatalLog(ctx, "kafka Error closing client", err)
g.Log().Fatalf(ctx, "kafka Error closing client, err:%+v", err)
}
})
@@ -193,7 +191,7 @@ func RegisterKafkaProducer(connOpt KafkaConfig, mqIns *KafkaMq) {
}
signal.AppDefer(func() {
Log(ctx, "kafka producer AsyncClose...")
g.Log().Debug(ctx, "kafka producer AsyncClose...")
mqIns.producerIns.AsyncClose()
})
}

View File

@@ -10,33 +10,28 @@ import (
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/utility/charset"
)
const (
ConsumerLogErrFormat = "消费 [%s] 失败, mqMsgId:%+v, mqMsgData:%+v, err:%+v, stack:%+v"
ProducerLogErrFormat = "生产 [%s] 失败, data:%+v, err:%+v, stack:%+v"
)
// ConsumerLog 消费日志
func ConsumerLog(ctx context.Context, topic string, mqMsg MqMsg, err error) {
if err != nil {
g.Log(consts.QueueLogPath).Error(ctx, "消费 ["+topic+"] 失败", mqMsg, err)
g.Log().Printf(ctx, ConsumerLogErrFormat, topic, mqMsg.MsgId, mqMsg.BodyString(), err, charset.ParseErrStack(err))
} else {
g.Log(consts.QueueLogPath).Debug(ctx, "消费 ["+topic+"] 成功", mqMsg.MsgId)
g.Log().Print(ctx, "消费 ["+topic+"] 成功", mqMsg.MsgId)
}
}
// ProducerLog 生产日志
func ProducerLog(ctx context.Context, topic string, data interface{}, err error) {
if err != nil {
g.Log(consts.QueueLogPath).Error(ctx, "生产 ["+topic+"] 失败", gconv.String(data))
g.Log().Printf(ctx, ProducerLogErrFormat, topic, gconv.String(data), err, charset.ParseErrStack(err))
} else {
g.Log(consts.QueueLogPath).Debug(ctx, "生产 ["+topic+"] 成功", gconv.String(data))
g.Log().Print(ctx, "生产 ["+topic+"] 成功", gconv.String(data))
}
}
// FatalLog 致命日志
func FatalLog(ctx context.Context, text string, err error) {
g.Log(consts.QueueLogPath).Fatal(ctx, text+":", err)
}
// Log 通用日志
func Log(ctx context.Context, text string) {
g.Log(consts.QueueLogPath).Debug(ctx, text)
}

View File

@@ -0,0 +1,18 @@
package queue
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
)
// Push 推送队列
func Push(topic string, data interface{}) (err error) {
q, err := InstanceProducer()
if err != nil {
g.Log().Fatalf(ctx, "queue.InstanceProducer err:%+v", err)
return err
}
mqMsg, err := q.SendMsg(topic, gconv.String(data))
ProducerLog(ctx, topic, mqMsg.MsgId, err)
return err
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gomodule/redigo/redis"
"hotgo/internal/consts"
"hotgo/utility/encrypt"
"math/rand"
"time"
@@ -113,7 +112,7 @@ func (r *RedisMq) ListenReceiveMsgDo(topic string, receiveDo func(mqMsg MqMsg))
// 生成队列名称
func (r *RedisMq) genQueueName(groupName string, topic string) string {
return fmt.Sprintf(consts.QueueName+"%s_%s", groupName, topic)
return fmt.Sprintf("queue:%s_%s", groupName, topic)
}
func (r *RedisMq) loopReadQueue(queueName string) (mqMsgList []MqMsg) {

View File

@@ -26,8 +26,8 @@ type RocketMq struct {
// rewriteLog 重写日志
func rewriteLog() {
level := g.Cfg().MustGet(ctx, "queue.rocketmq.logLevel", "debug")
rlog.SetLogger(&RocketMqLogger{Flag: "[rocket_mq]", LevelLog: level.String()})
level := g.Cfg().MustGet(ctx, "queue.rocketmq.logLevel", "debug").String()
rlog.SetLogger(&RocketMqLogger{Flag: "[rocket_mq]", LevelLog: level})
}
// RegisterRocketProducerMust 注册并启动生产者接口实现

View File

@@ -7,7 +7,7 @@
package queue
import (
"fmt"
"github.com/gogf/gf/v2/frame/g"
)
type RocketMqLogger struct {
@@ -24,16 +24,16 @@ func (l *RocketMqLogger) Debug(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "debug" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [debug] ", msg))
g.Log().Debug(ctx, msg)
}
}
func (l *RocketMqLogger) Level(level string) {
Log(ctx, fmt.Sprint(l.Flag, " [level] ", level))
g.Log().Info(ctx, level)
}
func (l *RocketMqLogger) OutputPath(path string) (err error) {
Log(ctx, fmt.Sprint(l.Flag, " [path] ", path))
g.Log().Info(ctx, path)
return nil
}
@@ -46,7 +46,7 @@ func (l *RocketMqLogger) Info(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "info" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [info] ", msg))
g.Log().Info(ctx, msg)
}
}
@@ -59,7 +59,7 @@ func (l *RocketMqLogger) Warning(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "warn" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [warn] ", msg))
g.Log().Warning(ctx, msg)
}
}
@@ -71,7 +71,7 @@ func (l *RocketMqLogger) Error(msg string, fields map[string]interface{}) {
return
}
if l.LevelLog == "error" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [error] ", msg))
g.Log().Error(ctx, msg)
}
}
@@ -84,6 +84,6 @@ func (l *RocketMqLogger) Fatal(msg string, fields map[string]interface{}) {
}
if l.LevelLog == "fatal" || l.LevelLog == "all" {
Log(ctx, fmt.Sprint(l.Flag, " [fatal] ", msg))
g.Log().Fatal(ctx, msg)
}
}

View File

@@ -0,0 +1,112 @@
package aliyun
import (
"context"
"fmt"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
dysmsapi20170525 "github.com/alibabacloud-go/dysmsapi-20170525/v3/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
"hotgo/internal/model"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
// SendCode 发送验证码
func SendCode(ctx context.Context, in sysin.SendCodeInp, config *model.SmsConfig) (err error) {
if config == nil {
config, err = service.SysConfig().GetSms(ctx)
if err != nil {
return err
}
}
client, err := CreateClient(tea.String(config.SmsAliyunAccessKeyID), tea.String(config.SmsAliyunAccessKeySecret))
if err != nil {
return err
}
sendSmsRequest := &dysmsapi20170525.SendSmsRequest{
PhoneNumbers: tea.String(in.Mobile),
SignName: tea.String(config.SmsAliyunSign),
TemplateCode: tea.String(in.Template),
TemplateParam: tea.String(fmt.Sprintf("{\"code\":\"%v\"}", in.Code)),
}
tryErr := func() (_e error) {
defer func() {
if r := tea.Recover(recover()); r != nil {
_e = r
}
}()
// 复制代码运行请自行打印 API 的返回值
_, err = client.SendSmsWithOptions(sendSmsRequest, &util.RuntimeOptions{})
if err != nil {
return err
}
return nil
}()
return tryErr
}
// CreateClient 使用AK&SK初始化账号Client
func CreateClient(accessKeyId *string, accessKeySecret *string) (_result *dysmsapi20170525.Client, _err error) {
config := &openapi.Config{
// 必填,您的 AccessKey ID
AccessKeyId: accessKeyId,
// 必填,您的 AccessKey Secret
AccessKeySecret: accessKeySecret,
}
// 访问的域名
config.Endpoint = tea.String("dysmsapi.aliyuncs.com")
_result = &dysmsapi20170525.Client{}
_result, _err = dysmsapi20170525.NewClient(config)
return _result, _err
}
func Send(accessKeyId string, accessKeySecret string) (_err error) {
// 工程代码泄露可能会导致AccessKey泄露并威胁账号下所有资源的安全性。以下代码示例仅供参考建议使用更安全的 STS 方式更多鉴权访问方式请参见https://help.aliyun.com/document_detail/378661.html
client, _err := CreateClient(tea.String(accessKeyId), tea.String(accessKeySecret))
if _err != nil {
return _err
}
sendSmsRequest := &dysmsapi20170525.SendSmsRequest{
PhoneNumbers: tea.String("15303830571"),
SignName: tea.String("布帆云"),
TemplateCode: tea.String("SMS_198921686"),
TemplateParam: tea.String("{\"code\":\"1234\"}"),
}
runtime := &util.RuntimeOptions{}
tryErr := func() (_e error) {
defer func() {
if r := tea.Recover(recover()); r != nil {
_e = r
}
}()
// 复制代码运行请自行打印 API 的返回值
_, _err = client.SendSmsWithOptions(sendSmsRequest, runtime)
if _err != nil {
return _err
}
return nil
}()
if tryErr != nil {
var err = &tea.SDKError{}
if _t, ok := tryErr.(*tea.SDKError); ok {
err = _t
} else {
err.Message = tea.String(tryErr.Error())
}
// 如有需要,请打印 error
_, _err = util.AssertAsString(err.Message)
if _err != nil {
return _err
}
}
return _err
}

View File

@@ -0,0 +1 @@
package aliyun

View File

@@ -0,0 +1 @@
package aliyun

View File

@@ -0,0 +1,2 @@
package sms

View File

@@ -9,11 +9,11 @@ package admin
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/hgorm"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/adminin"
"hotgo/internal/service"
@@ -47,8 +47,30 @@ func (s *sAdminDept) NameUnique(ctx context.Context, in adminin.DeptNameUniqueIn
}
// Delete 删除
func (s *sAdminDept) Delete(ctx context.Context, in adminin.DeptDeleteInp) error {
_, err := dao.AdminDept.Ctx(ctx).Where("id", in.Id).Delete()
func (s *sAdminDept) Delete(ctx context.Context, in adminin.DeptDeleteInp) (err error) {
var (
models *entity.AdminDept
)
err = dao.AdminDept.Ctx(ctx).Where("id", in.Id).Scan(&models)
if err != nil {
return err
}
if models == nil {
return gerror.New("数据不存在或已删除!")
}
pidExist, err := dao.AdminDept.Ctx(ctx).Where("pid", models.Id).One()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
if !pidExist.IsEmpty() {
return gerror.New("请先删除该部门下得所有子级!")
}
_, err = dao.AdminDept.Ctx(ctx).Where("id", in.Id).Delete()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
@@ -75,8 +97,12 @@ func (s *sAdminDept) Edit(ctx context.Context, in adminin.DeptEditInp) (err erro
return err
}
in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, dao.AdminDept, in.Pid)
if err != nil {
return err
}
// 修改
in.UpdatedAt = gtime.Now()
if in.Id > 0 {
_, err = dao.AdminDept.Ctx(ctx).Where("id", in.Id).Data(in).Update()
if err != nil {
@@ -88,7 +114,6 @@ func (s *sAdminDept) Edit(ctx context.Context, in adminin.DeptEditInp) (err erro
}
// 新增
in.CreatedAt = gtime.Now()
_, err = dao.AdminDept.Ctx(ctx).Data(in).Insert()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
@@ -156,11 +181,10 @@ func (s *sAdminDept) View(ctx context.Context, in adminin.DeptViewInp) (res *adm
// List 获取列表
func (s *sAdminDept) List(ctx context.Context, in adminin.DeptListInp) (list adminin.DeptListModel, err error) {
var (
mod = dao.AdminDept.Ctx(ctx)
models []*entity.AdminDept
ids []int64
pids []int64
deptList []g.Map
mod = dao.AdminDept.Ctx(ctx)
models []*entity.AdminDept
ids []int64
pids []int64
)
// 部门名称
@@ -207,25 +231,14 @@ func (s *sAdminDept) List(ctx context.Context, in adminin.DeptListInp) (list adm
return list, err
}
for i := 0; i < len(models); i++ {
deptList = append(deptList, g.Map{
"index": models[i].Id,
"key": models[i].Id,
"label": models[i].Name,
"id": models[i].Id,
"pid": models[i].Pid,
"name": models[i].Name,
"code": models[i].Code,
"leader": models[i].Leader,
"phone": models[i].Phone,
"email": models[i].Email,
"sort": models[i].Sort,
"created_at": models[i].CreatedAt,
"status": models[i].Status,
})
list = gconv.SliceMap(models)
for k, v := range list {
list[k]["index"] = v["id"]
list[k]["key"] = v["id"]
list[k]["label"] = v["name"]
}
return tree.GenTree(deptList), nil
return tree.GenTree(list), nil
}
type DeptTree struct {

View File

@@ -9,6 +9,7 @@ package admin
import (
"context"
"github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/encoding/gbase64"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
@@ -20,11 +21,13 @@ import (
"hotgo/internal/dao"
"hotgo/internal/library/contexts"
"hotgo/internal/library/jwt"
"hotgo/internal/library/location"
"hotgo/internal/model"
"hotgo/internal/model/do"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/adminin"
"hotgo/internal/service"
"hotgo/utility/encrypt"
"hotgo/utility/tree"
"hotgo/utility/validate"
)
@@ -441,7 +444,12 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
roleInfo *entity.AdminRole
memberInfo *entity.AdminMember
identity *model.Identity
timestamp = gtime.Timestamp()
expires = g.Cfg().MustGet(ctx, "jwt.expires", 1).Int64()
exp = gconv.Int64(timestamp) + expires
lastIp = location.GetClientIp(ghttp.RequestFromCtx(ctx))
)
err = dao.AdminMember.Ctx(ctx).Where("username", in.Username).Scan(&memberInfo)
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
@@ -457,16 +465,21 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
return
}
if memberInfo.PasswordHash != gmd5.MustEncryptString(in.Password+memberInfo.Salt) {
// 解密密码
password, err := gbase64.Decode([]byte(in.Password))
if err != nil {
return nil, err
}
password, err = encrypt.AesECBDecrypt(password, consts.RequestEncryptKey)
if err != nil {
return nil, err
}
if memberInfo.PasswordHash != gmd5.MustEncryptString(string(password)+memberInfo.Salt) {
err = gerror.New("用户密码不正确")
return
}
//// 默认设备
//if in.Device != consts.AppAdmin && in.Device != consts.AppApi {
// in.Device = consts.AppAdmin
//}
err = dao.AdminRole.Ctx(ctx).
Fields("id,key,status").
Where("id", memberInfo.RoleId).
@@ -485,12 +498,6 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
return
}
// 有效期
expires := g.Cfg().MustGet(ctx, "jwt.expires", 1).Int64()
// 过期时间戳
exp := gconv.Int64(gtime.Timestamp()) + expires
identity = &model.Identity{
Id: memberInfo.Id,
Pid: memberInfo.Pid,
@@ -504,7 +511,7 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
Mobile: memberInfo.Mobile,
VisitCount: memberInfo.VisitCount,
LastTime: memberInfo.LastTime,
LastIp: memberInfo.LastIp,
LastIp: lastIp,
Exp: exp,
Expires: expires,
App: consts.AppAdmin,
@@ -517,13 +524,11 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
}
// 更新登录信息
authKey := gmd5.MustEncryptString(gconv.String(token))
_, err = dao.AdminMember.Ctx(ctx).Data(do.AdminMember{
AuthKey: gmd5.MustEncryptString(authKey),
AuthKey: gmd5.MustEncryptString(token),
VisitCount: memberInfo.VisitCount + 1,
LastTime: gtime.Timestamp(),
LastIp: ghttp.RequestFromCtx(ctx).GetClientIp(),
LastTime: timestamp,
LastIp: lastIp,
}).Where(do.AdminMember{
Id: memberInfo.Id,
}).Update()
@@ -538,7 +543,7 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
Username: identity.Username,
RealName: identity.RealName,
Avatar: identity.Avatar,
Token: gconv.String(token),
Token: token,
}
return res, nil

View File

@@ -78,7 +78,6 @@ func (s *sAdminPost) Edit(ctx context.Context, in adminin.PostEditInp) (err erro
}
// 修改
in.UpdatedAt = gtime.Now()
if in.Id > 0 {
_, err = dao.AdminPost.Ctx(ctx).Where("id", in.Id).Data(in).Update()
if err != nil {
@@ -90,7 +89,6 @@ func (s *sAdminPost) Edit(ctx context.Context, in adminin.PostEditInp) (err erro
}
// 新增
in.CreatedAt = gtime.Now()
_, err = dao.AdminPost.Ctx(ctx).Data(in).Insert()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
@@ -181,7 +179,7 @@ func (s *sAdminPost) List(ctx context.Context, in adminin.PostListInp) (list []*
return list, totalCount, nil
}
if err = mod.Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
if err = mod.Page(in.Page, in.PerPage).Order("id asc").Scan(&list); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}

View File

@@ -12,7 +12,7 @@ import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/role"
"hotgo/internal/consts"
"hotgo/internal/dao"
@@ -25,6 +25,7 @@ import (
"hotgo/internal/service"
"hotgo/utility/auth"
"hotgo/utility/convert"
"hotgo/utility/tree"
"sort"
)
@@ -67,21 +68,25 @@ func (s *sAdminRole) Verify(ctx context.Context, path, method string) bool {
}
// List 获取列表
func (s *sAdminRole) List(ctx context.Context, in adminin.RoleListInp) (list []*adminin.RoleListModel, totalCount int, err error) {
mod := dao.AdminRole.Ctx(ctx)
func (s *sAdminRole) List(ctx context.Context, in adminin.RoleListInp) (list []g.Map, totalCount int, err error) {
var (
mod = dao.AdminRole.Ctx(ctx)
models []*adminin.RoleListModel
)
totalCount, err = mod.Count()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
err = mod.Page(in.Page, in.PerPage).Order("id asc").Scan(&list)
err = mod.Page(in.Page, in.PerPage).Order("id asc").Scan(&models)
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
return list, totalCount, err
return tree.GenTree(gconv.SliceMap(models)), totalCount, err
}
// GetName 获取指定角色的名称
@@ -197,7 +202,6 @@ func (s *sAdminRole) Edit(ctx context.Context, in *role.EditReq) (err error) {
}
// 修改
in.UpdatedAt = gtime.Now()
if in.Id > 0 {
_, err = dao.AdminRole.Ctx(ctx).Where("id", in.Id).Data(in).Update()
if err != nil {
@@ -209,7 +213,6 @@ func (s *sAdminRole) Edit(ctx context.Context, in *role.EditReq) (err error) {
}
// 新增
in.CreatedAt = gtime.Now()
_, err = dao.AdminRole.Ctx(ctx).Data(in).Insert()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
@@ -222,6 +225,28 @@ func (s *sAdminRole) Delete(ctx context.Context, in *role.DeleteReq) (err error)
if in.Id <= 0 {
return gerror.New("ID不正确")
}
var (
models *entity.AdminRole
)
err = dao.AdminRole.Ctx(ctx).Where("id", in.Id).Scan(&models)
if err != nil {
return err
}
if models == nil {
return gerror.New("数据不存在或已删除!")
}
pidExist, err := dao.AdminRole.Ctx(ctx).Where("pid", models.Id).One()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
if !pidExist.IsEmpty() {
return gerror.New("请先删除该角色下得所有子级!")
}
_, err = dao.AdminRole.Ctx(ctx).Where("id", in.Id).Delete()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)

View File

@@ -14,7 +14,7 @@ import (
"hotgo/internal/service"
)
// GlobalLog 全局日志
// GlobalLog 访问日志
func (s *sHook) GlobalLog(r *ghttp.Request) {
var (
ctx = r.Context()

View File

@@ -37,7 +37,8 @@ func New() *sMiddleware {
return &sMiddleware{
LoginUrl: "/common",
DemoWhiteList: g.Map{
"/admin/site/login": struct{}{}, // 后台登录
"/admin/site/login": struct{}{}, // 后台登录
"/admin/genCodes/preview": struct{}{}, // 预览代码
},
}
}

View File

@@ -0,0 +1,23 @@
package middleware
import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"hotgo/internal/global"
"hotgo/internal/library/location"
"hotgo/internal/library/response"
)
// Blacklist IP黑名单限制中间件
func (s *sMiddleware) Blacklist(r *ghttp.Request) {
if global.Blacklists != nil {
if _, ok := global.Blacklists[location.GetClientIp(r)]; ok {
response.JsonExit(r, gcode.CodeServerBusy.Code(), "请求异常,已被封禁,如有疑问请联系管理员!")
}
} else {
g.Log().Warningf(r.Context(), "blacklists uninitialized")
}
r.Middleware.Next()
}

View File

@@ -42,14 +42,14 @@ func (s *sMiddleware) ResponseHandler(r *ghttp.Request) {
if err = r.GetError(); err != nil {
// 记录到自定义错误日志文件
g.Log("exception").Print(ctx, "exception:", err)
g.Log().Warningf(ctx, "exception:%v", err)
code = gerror.Code(err).Code()
message = err.Error()
// 是否输出错误到页面
if g.Cfg().MustGet(ctx, "hotgo.debug", true).Bool() {
data = charset.GetStack(err)
data = charset.ParseErrStack(err)
}
} else {
data = r.GetHandlerResponse()

View File

@@ -9,9 +9,13 @@ package sys
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/global"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/validate"
@@ -28,8 +32,9 @@ func init() {
}
// Delete 删除
func (s *sSysBlacklist) Delete(ctx context.Context, in sysin.BlacklistDeleteInp) error {
_, err := dao.SysBlacklist.Ctx(ctx).Where("id", in.Id).Delete()
func (s *sSysBlacklist) Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error) {
defer s.VariableLoad(ctx, err)
_, err = dao.SysBlacklist.Ctx(ctx).Where("id", in.Id).Delete()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
@@ -40,6 +45,7 @@ func (s *sSysBlacklist) Delete(ctx context.Context, in sysin.BlacklistDeleteInp)
// Edit 修改/新增
func (s *sSysBlacklist) Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error) {
defer s.VariableLoad(ctx, err)
if in.Ip == "" {
err = gerror.New("ip不能为空")
return err
@@ -69,6 +75,7 @@ func (s *sSysBlacklist) Edit(ctx context.Context, in sysin.BlacklistEditInp) (er
// Status 更新部门状态
func (s *sSysBlacklist) Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error) {
defer s.VariableLoad(ctx, err)
if in.Id <= 0 {
err = gerror.New("ID不能为空")
return err
@@ -148,3 +155,112 @@ func (s *sSysBlacklist) List(ctx context.Context, in sysin.BlacklistListInp) (li
return list, totalCount, err
}
// VariableLoad 变化加载
func (s *sSysBlacklist) VariableLoad(ctx context.Context, err error) {
if err == nil {
s.Load(ctx)
}
}
// Load 加载黑名单
func (s *sSysBlacklist) Load(ctx context.Context) {
global.Blacklists = make(map[string]struct{})
array, err := dao.SysBlacklist.Ctx(ctx).
Fields(dao.SysBlacklist.Columns().Ip).
Where(dao.SysBlacklist.Columns().Status, consts.StatusEnabled).
Array()
if err != nil {
g.Log().Fatal(ctx, "load blacklist fail%+v", err)
return
}
matchStrategy := func(originIp string) {
// 多个IP
if gstr.Contains(originIp, ",") {
ips := gstr.Explode(",", originIp)
if len(ips) > 0 {
for _, ip := range ips {
if !validate.IsIp(ip) {
continue
}
global.Blacklists[ip] = struct{}{}
}
}
return
}
// IP段
if gstr.Contains(originIp, "/24") {
segment := gstr.Replace(originIp, "/24", "")
if !validate.IsIp(segment) {
return
}
var (
start = gstr.Explode(".", segment)
prefix = gstr.Implode(".", start[:len(start)-1]) + "."
index = gconv.Int(start[len(start)-1])
)
if index < 1 {
index = 1
}
for i := index; i <= 254; i++ {
global.Blacklists[prefix+gconv.String(i)] = struct{}{}
}
return
}
// IP范围
if gstr.Contains(originIp, "-") {
originIps := gstr.Explode("-", originIp)
if len(originIps) != 2 {
return
}
if !validate.IsIp(originIps[0]) || !validate.IsIp(originIps[1]) {
return
}
var (
start = gstr.Explode(".", originIps[0])
prefix = gstr.Implode(".", start[:len(start)-1]) + "."
startIndex = gconv.Int(gstr.SubStrFromREx(originIps[0], "."))
endIndex = gconv.Int(gstr.SubStrFromREx(originIps[1], "."))
)
if startIndex >= endIndex {
global.Blacklists[originIps[0]] = struct{}{}
return
}
if startIndex < 1 {
startIndex = 1
}
if endIndex > 254 {
endIndex = 254
}
for i := startIndex; i <= endIndex; i++ {
global.Blacklists[prefix+gconv.String(i)] = struct{}{}
}
return
}
// 指定IP
if validate.IsIp(originIp) {
global.Blacklists[originIp] = struct{}{}
return
}
}
for _, v := range array {
matchStrategy(v.String())
}
}

View File

@@ -112,6 +112,14 @@ func (s *sSysConfig) GetLoadLog(ctx context.Context) (conf *model.LogConfig, err
return conf, nil
}
// GetLoadServeLog 获取本地服务日志配置
func (s *sSysConfig) GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error) {
if err = g.Cfg().MustGet(ctx, "hotgo.serveLog").Struct(&conf); err != nil {
return nil, err
}
return conf, nil
}
// GetConfigByGroup 获取指定分组的配置
func (s *sSysConfig) GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (*sysin.GetConfigModel, error) {
if in.Group == "" {

View File

@@ -10,6 +10,7 @@ import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/consts"
"hotgo/internal/crons"
@@ -18,6 +19,7 @@ import (
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/validate"
"strings"
)
type sSysCron struct{}
@@ -181,3 +183,20 @@ func (s *sSysCron) List(ctx context.Context, in sysin.CronListInp) (list []*sysi
return list, totalCount, err
}
// OnlineExec 在线执行
func (s *sSysCron) OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err error) {
var data *entity.SysCron
err = dao.SysCron.Ctx(ctx).Where(dao.SysCron.Columns().Id, in.Id).Scan(&data)
if err != nil {
return
}
if data == nil {
return gerror.New("定时任务不存在")
}
newCtx := context.WithValue(gctx.New(), consts.ContextKeyCronArgs, strings.Split(data.Params, consts.CronSplitStr))
return crons.Once(newCtx, data)
}

View File

@@ -63,7 +63,6 @@ func (s *sSysDictType) Tree(ctx context.Context) (list []g.Map, err error) {
// Delete 删除
func (s *sSysDictType) Delete(ctx context.Context, in sysin.DictTypeDeleteInp) error {
var (
models *entity.SysDictType
)
@@ -72,7 +71,7 @@ func (s *sSysDictType) Delete(ctx context.Context, in sysin.DictTypeDeleteInp) e
return err
}
if models.Id < 1 {
if models == nil {
return gerror.New("数据不存在或已删除!")
}

View File

@@ -60,7 +60,7 @@ func (s *sSysLog) Export(ctx context.Context, in sysin.LogListInp) (err error) {
var (
titleList = []string{"ID", "应用", "提交类型", "模块", "提交url", "ip地址", "报错code", "报错信息", "对外id", "请求耗时", "创建时间", "用户", "访问地"}
fileName = "全局日志导出-" + gctx.CtxId(ctx) + ".xlsx"
fileName = "访问日志导出-" + gctx.CtxId(ctx) + ".xlsx"
sheetName = "HotGo"
exportList []exportImage
row exportImage
@@ -97,15 +97,9 @@ func (s *sSysLog) Export(ctx context.Context, in sysin.LogListInp) (err error) {
}
// RealWrite 真实写入
func (s *sSysLog) RealWrite(ctx context.Context, commonLog entity.SysLog) error {
result, err := dao.SysLog.Ctx(ctx).Data(commonLog).Insert()
if err != nil {
return err
}
if _, err = result.LastInsertId(); err != nil {
return err
}
return nil
func (s *sSysLog) RealWrite(ctx context.Context, commonLog entity.SysLog) (err error) {
_, err = dao.SysLog.Ctx(ctx).Data(commonLog).Insert()
return
}
// AutoLog 根据配置自动记录请求日志
@@ -129,48 +123,31 @@ func (s *sSysLog) AutoLog(ctx context.Context) (err error) {
}
if config.Queue {
q, err := queue.InstanceProducer()
if err != nil {
queue.FatalLog(ctx, "queue.InstanceProducer err:%+v", err)
return err
}
mqMsg, err := q.SendMsg(consts.QueueLogTopic, gconv.String(data))
queue.ProducerLog(ctx, consts.QueueLogTopic, mqMsg.MsgId, err)
return err
return queue.Push(consts.QueueLogTopic, data)
}
return s.RealWrite(ctx, data)
}
// QueueJob 队列消费
func (s *sSysLog) QueueJob(ctx context.Context, mqMsg queue.MqMsg) (err error) {
var data entity.SysLog
if err = json.Unmarshal(mqMsg.Body, &data); err != nil {
return err
}
return s.RealWrite(ctx, data)
}
// AnalysisLog 解析日志数据
func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
var (
modelContext = contexts.Get(ctx)
response = modelContext.Response
user = modelContext.User
request = ghttp.RequestFromCtx(ctx)
module = modelContext.Module
clientIp = request.GetClientIp()
postData = gjson.New(consts.NilJsonToString)
getData = gjson.New(consts.NilJsonToString)
headerData = gjson.New(consts.NilJsonToString)
data = entity.SysLog{}
memberId int64 = 0
errorCode = 0
errorMsg = ""
errorData = gjson.New(consts.NilJsonToString)
traceID = ""
timestamp int64 = 0
appId = ""
modelContext = contexts.Get(ctx)
response = modelContext.Response
user = modelContext.User
request = ghttp.RequestFromCtx(ctx)
module = modelContext.Module
clientIp = location.GetClientIp(request)
postData = gjson.New(request.GetBodyString())
getData = gjson.New(request.URL.Query())
headerData = gjson.New(consts.NilJsonToString)
errorData = gjson.New(consts.NilJsonToString)
data entity.SysLog
memberId int64
errorCode int
errorMsg string
traceID string
timestamp int64
appId string
)
// 响应数据
@@ -190,17 +167,14 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
}
// post参数
if gconv.String(request.PostForm) != "" {
postData = gjson.New(gconv.String(request.PostForm))
postForm := gjson.New(gconv.String(request.PostForm)).Map()
if len(postForm) > 0 {
for k, v := range postForm {
postData.MustAppend(k, v)
}
}
if postData.IsNil() {
postData = gjson.New(request.GetBodyString())
}
// get参数
if len(request.URL.Query()) > 0 {
getData = gjson.New(request.URL.Query())
if postData.IsNil() || len(postData.Map()) == 0 {
postData = gjson.New(consts.NilJsonToString)
}
// 当前登录用户
@@ -210,22 +184,14 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
}
var ipData = new(location.IpLocationData)
//if validate.IsPublicIp(clientIp) {
// ipData, err := location.GetLocation(ctx, clientIp)
// if err != nil {
// g.Log().Errorf(ctx, "location.GetLocation err:%+v", err)
// }
// if ipData == nil {
// ipData = new(location.IpLocationData)
// }
//}
ipData, err := location.GetLocation(ctx, clientIp)
if err != nil {
g.Log().Errorf(ctx, "location.GetLocation err:%+v", err)
}
if ipData == nil {
ipData = new(location.IpLocationData)
if validate.IsPublicIp(clientIp) {
ipData, err := location.GetLocation(ctx, clientIp)
if err != nil {
g.Log().Errorf(ctx, "location.GetLocation err:%+v", err)
}
if ipData == nil {
ipData = new(location.IpLocationData)
}
}
data = entity.SysLog{

View File

@@ -0,0 +1,190 @@
// Package sys
// @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 sys
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/hgorm"
"hotgo/internal/library/queue"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/convert"
"hotgo/utility/excel"
"hotgo/utility/useragent"
)
type sSysLoginLog struct{}
func NewSysLoginLog() *sSysLoginLog {
return &sSysLoginLog{}
}
func init() {
service.RegisterSysLoginLog(NewSysLoginLog())
}
// Model 登录日志Orm模型
func (s *sSysLoginLog) Model(ctx context.Context) *gdb.Model {
return dao.SysLoginLog.Ctx(ctx)
}
// List 获取登录日志列表
func (s *sSysLoginLog) List(ctx context.Context, in sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error) {
mod := dao.SysLoginLog.Ctx(ctx)
// 查询状态
if in.Status > 0 {
mod = mod.Where(dao.SysLoginLog.Columns().Status, in.Status)
}
// 查询登录时间
if len(in.LoginAt) == 2 {
mod = mod.WhereBetween(dao.SysLoginLog.Columns().LoginAt, in.LoginAt[0], in.LoginAt[1])
}
// 查询IP地址
if in.SysLogIp != "" {
mod = mod.Where("sysLog."+dao.SysLog.Columns().Ip, in.SysLogIp)
}
// 用户名
if in.Username != "" {
mod = mod.Where(dao.SysLoginLog.Columns().Username, in.Username)
}
// 关联表sysLog
mod = mod.LeftJoin(hgorm.GenJoinOnRelation(
dao.SysLoginLog.Table(), dao.SysLoginLog.Columns().ReqId, // 主表表名,关联条件
dao.SysLog.Table(), "sysLog", dao.SysLog.Columns().ReqId, // 关联表表名,别名,关联条件
)...)
totalCount, err = mod.Clone().Count(1)
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
if totalCount == 0 {
return list, totalCount, nil
}
//关联表select
fields, err := hgorm.GenJoinSelect(ctx, sysin.LoginLogListModel{}, dao.SysLoginLog, []*hgorm.Join{
{Dao: dao.SysLog, Alias: "sysLog"},
})
if err = mod.Fields(fields).Handler(hgorm.HandlerFilterAuth).Page(in.Page, in.PerPage).OrderDesc(dao.SysLoginLog.Columns().Id).Scan(&list); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
for _, v := range list {
// 获取省市编码对应的地区名称
region, err := dao.SysProvinces.GetRegion(ctx, v.SysLogProvinceId, v.SysLogCityId)
if err != nil {
return list, totalCount, err
}
v.Region = region
v.Os = useragent.GetOs(v.SysLogUserAgent)
v.Browser = useragent.GetBrowser(v.SysLogUserAgent)
}
return list, totalCount, err
}
// Export 导出登录日志
func (s *sSysLoginLog) Export(ctx context.Context, in sysin.LoginLogListInp) (err error) {
list, totalCount, err := s.List(ctx, in)
if err != nil {
return err
}
// 字段的排序是依据tags的字段顺序如果你不想使用默认的排序方式可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
tags, err := convert.GetEntityDescTags(sysin.LoginLogExportModel{})
if err != nil {
return err
}
var (
fileName = "导出登录日志-" + gctx.CtxId(ctx) + ".xlsx"
sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, form.CalPageCount(totalCount, in.PerPage), in.Page, len(list))
exports []sysin.LoginLogExportModel
)
err = gconv.Scan(list, &exports)
if err != nil {
return err
}
if err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName); err != nil {
return
}
return
}
// Delete 删除登录日志
func (s *sSysLoginLog) Delete(ctx context.Context, in sysin.LoginLogDeleteInp) (err error) {
_, err = dao.SysLoginLog.Ctx(ctx).Where(dao.SysLoginLog.Columns().Id, in.Id).Delete()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return nil
}
// View 获取登录日志指定信息
func (s *sSysLoginLog) View(ctx context.Context, in sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error) {
if err = dao.SysLoginLog.Ctx(ctx).Where(dao.SysLoginLog.Columns().Id, in.Id).Scan(&res); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return nil, err
}
return res, nil
}
// Push 推送登录日志
func (s *sSysLoginLog) Push(ctx context.Context, in sysin.LoginLogPushInp) {
var models entity.SysLoginLog
models.ReqId = gctx.CtxId(ctx)
models.MemberId = in.Response.UserId
models.Username = in.Input.Username
models.LoginAt = gtime.Now()
models.Status = consts.StatusEnabled
if in.Err != nil {
models.Status = consts.StatusDisable
models.ErrMsg = in.Err.Error()
}
models.Response = gjson.New(consts.NilJsonToString)
if in.Response != nil && in.Response.UserId > 0 {
models.Response = gjson.New(in.Response)
}
if err := queue.Push(consts.QueueLoginLogTopic, models); err != nil {
g.Log().Warningf(ctx, "sSysLoginLog.Push err:%+v", err)
}
return
}
// RealWrite 真实写入
func (s *sSysLoginLog) RealWrite(ctx context.Context, models entity.SysLoginLog) (err error) {
_, err = dao.SysLoginLog.Ctx(ctx).Data(models).Insert()
return
}

View File

@@ -9,11 +9,16 @@ package sys
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/hgorm"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/tree"
"hotgo/utility/validate"
)
@@ -27,10 +32,48 @@ func init() {
service.RegisterSysProvinces(NewSysProvinces())
}
// Tree 关系树选项列表
func (s *sSysProvinces) Tree(ctx context.Context) (list []g.Map, err error) {
var models []*entity.SysProvinces
if err = dao.SysProvinces.Ctx(ctx).Order("pid asc,id asc,sort asc").Scan(&models); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, err
}
list = gconv.SliceMap(models)
for k, v := range list {
list[k]["key"] = v["id"]
list[k]["label"] = v["title"]
}
return tree.GenTree(list), nil
}
// Delete 删除
func (s *sSysProvinces) Delete(ctx context.Context, in sysin.ProvincesDeleteInp) error {
_, err := dao.SysProvinces.Ctx(ctx).Where("id", in.Id).Delete()
var (
models *entity.SysProvinces
)
err := dao.SysProvinces.Ctx(ctx).Where("id", in.Id).Scan(&models)
if err != nil {
return err
}
if models == nil {
return gerror.New("数据不存在或已删除!")
}
pidExist, err := dao.SysProvinces.Ctx(ctx).Where("pid", models.Id).One()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
if !pidExist.IsEmpty() {
return gerror.New("请先删除该地区下得所有子级!")
}
_, err = dao.SysProvinces.Ctx(ctx).Where("id", in.Id).Delete()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
@@ -43,12 +86,32 @@ func (s *sSysProvinces) Delete(ctx context.Context, in sysin.ProvincesDeleteInp)
func (s *sSysProvinces) Edit(ctx context.Context, in sysin.ProvincesEditInp) (err error) {
if in.Title == "" {
err = gerror.New("标题不能为空")
return
}
if in.Id <= 0 {
err = gerror.New("地区Id必须大于0")
return
}
// 关系树
in.Pid, in.Level, in.Tree, err = hgorm.GenSubTree(ctx, dao.SysProvinces, in.Pid)
if err != nil {
return err
}
isUpdate := false
models, err := s.View(ctx, sysin.ProvincesViewInp{Id: in.Id})
if err != nil {
return
}
if models != nil {
isUpdate = true
}
// 修改
in.UpdatedAt = gtime.Now()
if in.Id > 0 {
if isUpdate {
_, err = dao.SysProvinces.Ctx(ctx).Where("id", in.Id).Data(in).Update()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
@@ -59,7 +122,6 @@ func (s *sSysProvinces) Edit(ctx context.Context, in sysin.ProvincesEditInp) (er
}
// 新增
in.CreatedAt = gtime.Now()
_, err = dao.SysProvinces.Ctx(ctx).Data(in).Insert()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
@@ -97,19 +159,14 @@ func (s *sSysProvinces) Status(ctx context.Context, in sysin.ProvincesStatusInp)
}
// MaxSort 最大排序
func (s *sSysProvinces) MaxSort(ctx context.Context, in sysin.ProvincesMaxSortInp) (*sysin.ProvincesMaxSortModel, error) {
var res sysin.ProvincesMaxSortModel
if in.Id > 0 {
if err := dao.SysProvinces.Ctx(ctx).Where("id", in.Id).Order("sort desc").Scan(&res); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return nil, err
}
func (s *sSysProvinces) MaxSort(ctx context.Context, in sysin.ProvincesMaxSortInp) (res *sysin.ProvincesMaxSortModel, err error) {
if err = dao.SysProvinces.Ctx(ctx).Fields(dao.SysProvinces.Columns().Sort).OrderDesc(dao.SysProvinces.Columns().Sort).Scan(&res); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return nil, err
}
res.Sort = res.Sort + 10
return &res, nil
res.Sort = res.Sort + g.Cfg().MustGet(ctx, "hotgo.admin.maxSortIncrement").Int()
return res, nil
}
// View 获取指定字典类型信息
@@ -126,12 +183,10 @@ func (s *sSysProvinces) View(ctx context.Context, in sysin.ProvincesViewInp) (re
func (s *sSysProvinces) List(ctx context.Context, in sysin.ProvincesListInp) (list []*sysin.ProvincesListModel, totalCount int, err error) {
mod := dao.SysProvinces.Ctx(ctx)
// 访问路径
if in.Title != "" {
mod = mod.WhereLike("title", "%"+in.Title+"%")
}
// 请求方式
if in.Status > 0 {
mod = mod.Where("status", in.Status)
}
@@ -153,3 +208,53 @@ func (s *sSysProvinces) List(ctx context.Context, in sysin.ProvincesListInp) (li
return list, totalCount, err
}
// ChildrenList 获取省市区下级列表
func (s *sSysProvinces) ChildrenList(ctx context.Context, in sysin.ProvincesChildrenListInp) (list []*sysin.ProvincesChildrenListModel, totalCount int, err error) {
mod := dao.SysProvinces.Ctx(ctx)
if in.Title != "" {
mod = mod.WhereLike("title", "%"+in.Title+"%")
}
if in.Pid > 0 {
mod = mod.Where("pid", in.Pid)
}
if in.Id > 0 {
mod = mod.Where("id", in.Id)
}
totalCount, err = mod.Count()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
if totalCount == 0 {
return list, totalCount, nil
}
if err = mod.Page(in.Page, in.PerPage).Order("sort asc,id desc").Scan(&list); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
return list, totalCount, err
}
// UniqueId 获取省市区下级列表
func (s *sSysProvinces) UniqueId(ctx context.Context, in sysin.ProvincesUniqueIdInp) (res *sysin.ProvincesUniqueIdModel, err error) {
res = new(sysin.ProvincesUniqueIdModel)
res.IsUnique = true
if in.NewId == 0 {
return
}
if err = hgorm.IsUnique(ctx, dao.SysProvinces, g.Map{dao.Test.Columns().Id: in.NewId}, "", in.OldId); err != nil {
res.IsUnique = false
return res, nil
}
return res, nil
}

View File

@@ -0,0 +1,148 @@
// Package sys
// @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 sys
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/hgorm"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/convert"
"hotgo/utility/excel"
)
type sSysServeLog struct{}
func NewSysServeLog() *sSysServeLog {
return &sSysServeLog{}
}
func init() {
service.RegisterSysServeLog(NewSysServeLog())
}
// Model 服务日志Orm模型
func (s *sSysServeLog) Model(ctx context.Context) *gdb.Model {
return dao.SysServeLog.Ctx(ctx)
}
// List 获取服务日志列表
func (s *sSysServeLog) List(ctx context.Context, in sysin.ServeLogListInp) (list []*sysin.ServeLogListModel, totalCount int, err error) {
mod := dao.SysServeLog.Ctx(ctx)
// 查询链路ID
if in.TraceId != "" {
mod = mod.Where(dao.SysServeLog.Columns().TraceId, in.TraceId)
}
// 查询日志级别
if in.LevelFormat != "" {
mod = mod.WhereLike(dao.SysServeLog.Columns().LevelFormat, in.LevelFormat)
}
// 查询触发时间(ns)
if len(in.TriggerNs) == 2 {
mod = mod.WhereBetween(dao.SysServeLog.Columns().TriggerNs, in.TriggerNs[0], in.TriggerNs[1])
}
// 查询创建时间
if len(in.CreatedAt) == 2 {
mod = mod.WhereBetween(dao.SysServeLog.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
}
// 关联表sysLog
mod = mod.LeftJoin(hgorm.GenJoinOnRelation(
dao.SysServeLog.Table(), dao.SysServeLog.Columns().TraceId, // 主表表名,关联条件
dao.SysLog.Table(), "sysLog", dao.SysLog.Columns().ReqId, // 关联表表名,别名,关联条件
)...)
totalCount, err = mod.Clone().Count(1)
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
if totalCount == 0 {
return list, totalCount, nil
}
//关联表select
fields, err := hgorm.GenJoinSelect(ctx, sysin.ServeLogListModel{}, dao.SysServeLog, []*hgorm.Join{
{Dao: dao.SysLog, Alias: "sysLog"},
})
if err = mod.Fields(fields).Handler(hgorm.HandlerFilterAuth).Page(in.Page, in.PerPage).OrderDesc(dao.SysServeLog.Columns().Id).Scan(&list); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
return list, totalCount, err
}
// Export 导出服务日志
func (s *sSysServeLog) Export(ctx context.Context, in sysin.ServeLogListInp) (err error) {
list, totalCount, err := s.List(ctx, in)
if err != nil {
return err
}
// 字段的排序是依据tags的字段顺序如果你不想使用默认的排序方式可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
tags, err := convert.GetEntityDescTags(sysin.ServeLogExportModel{})
if err != nil {
return err
}
var (
fileName = "导出服务日志-" + gctx.CtxId(ctx) + ".xlsx"
sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, form.CalPageCount(totalCount, in.PerPage), in.Page, len(list))
exports []sysin.ServeLogExportModel
)
err = gconv.Scan(list, &exports)
if err != nil {
return err
}
if err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName); err != nil {
return
}
return
}
// Delete 删除服务日志
func (s *sSysServeLog) Delete(ctx context.Context, in sysin.ServeLogDeleteInp) (err error) {
_, err = dao.SysServeLog.Ctx(ctx).Where(dao.SysServeLog.Columns().Id, in.Id).Delete()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return nil
}
// View 获取服务日志指定信息
func (s *sSysServeLog) View(ctx context.Context, in sysin.ServeLogViewInp) (res *sysin.ServeLogViewModel, err error) {
if err = dao.SysServeLog.Ctx(ctx).Where(dao.SysServeLog.Columns().Id, in.Id).Scan(&res); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return nil, err
}
return res, nil
}
// RealWrite 真实写入
func (s *sSysServeLog) RealWrite(ctx context.Context, models entity.SysServeLog) (err error) {
_, err = dao.SysServeLog.Ctx(ctx).Data(models).Insert()
return
}

View File

@@ -0,0 +1,343 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package sys
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"
"github.com/gogf/gf/v2/util/grand"
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/location"
"hotgo/internal/library/sms/aliyun"
"hotgo/internal/model"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/validate"
"time"
)
type sSysSmsLog struct{}
func NewSysSmsLog() *sSysSmsLog {
return &sSysSmsLog{}
}
func init() {
service.RegisterSysSmsLog(NewSysSmsLog())
}
// Delete 删除
func (s *sSysSmsLog) Delete(ctx context.Context, in sysin.SmsLogDeleteInp) error {
_, err := dao.SysSmsLog.Ctx(ctx).Where("id", in.Id).Delete()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return nil
}
// Edit 修改/新增
func (s *sSysSmsLog) Edit(ctx context.Context, in sysin.SmsLogEditInp) (err error) {
if in.Ip == "" {
err = gerror.New("ip不能为空")
return err
}
// 修改
in.UpdatedAt = gtime.Now()
if in.Id > 0 {
_, err = dao.SysSmsLog.Ctx(ctx).Where("id", in.Id).Data(in).Update()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return nil
}
// 新增
in.CreatedAt = gtime.Now()
_, err = dao.SysSmsLog.Ctx(ctx).Data(in).Insert()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return nil
}
// Status 更新部门状态
func (s *sSysSmsLog) Status(ctx context.Context, in sysin.SmsLogStatusInp) (err error) {
if in.Id <= 0 {
err = gerror.New("ID不能为空")
return err
}
if in.Status <= 0 {
err = gerror.New("状态不能为空")
return err
}
if !validate.InSliceInt(consts.StatusMap, in.Status) {
err = gerror.New("状态不正确")
return err
}
// 修改
in.UpdatedAt = gtime.Now()
_, err = dao.SysSmsLog.Ctx(ctx).Where("id", in.Id).Data("status", in.Status).Update()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return nil
}
// MaxSort 最大排序
func (s *sSysSmsLog) MaxSort(ctx context.Context, in sysin.SmsLogMaxSortInp) (*sysin.SmsLogMaxSortModel, error) {
var res sysin.SmsLogMaxSortModel
if in.Id > 0 {
if err := dao.SysSmsLog.Ctx(ctx).Where("id", in.Id).Order("sort desc").Scan(&res); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return nil, err
}
}
res.Sort = res.Sort + 10
return &res, nil
}
// View 获取指定字典类型信息
func (s *sSysSmsLog) View(ctx context.Context, in sysin.SmsLogViewInp) (res *sysin.SmsLogViewModel, err error) {
if err = dao.SysSmsLog.Ctx(ctx).Where("id", in.Id).Scan(&res); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return nil, err
}
return res, nil
}
// List 获取列表
func (s *sSysSmsLog) List(ctx context.Context, in sysin.SmsLogListInp) (list []*sysin.SmsLogListModel, totalCount int, err error) {
mod := dao.SysSmsLog.Ctx(ctx)
if in.Status > 0 {
mod = mod.Where("status", in.Status)
}
totalCount, err = mod.Count()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
if totalCount == 0 {
return list, totalCount, nil
}
if err = mod.Page(int(in.Page), int(in.PerPage)).Order("id desc").Scan(&list); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return list, totalCount, err
}
return list, totalCount, err
}
// SendCode 发送验证码
func (s *sSysSmsLog) SendCode(ctx context.Context, in sysin.SendCodeInp) (err error) {
if in.Event == "" {
return gerror.New("事件不能为空")
}
if in.Mobile == "" {
return gerror.New("手机号不能为空")
}
var (
models *entity.SysSmsLog
)
if err = dao.SysSmsLog.Ctx(ctx).Where("event", in.Event).Where("mobile", in.Mobile).Scan(&models); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
config, err := service.SysConfig().GetSms(ctx)
if err != nil {
return err
}
in.Template, err = s.GetTemplate(ctx, in.Event, config)
if err != nil {
return err
}
err = s.AllowSend(ctx, models, config)
if err != nil {
return err
}
if in.Code == "" {
in.Code = grand.Digits(4)
}
switch config.SmsDrive {
case consts.SmsDriveAliYun:
err = aliyun.SendCode(ctx, in, config)
if err != nil {
return err
}
case consts.SmsDriveTencent:
return gerror.Newf("暂不支持短信驱动:%v", config.SmsDrive)
default:
return gerror.Newf("暂不支持短信驱动:%v", config.SmsDrive)
}
var data = new(entity.SysSmsLog)
data.Event = in.Event
data.Mobile = in.Mobile
data.Code = in.Code
data.Ip = location.GetClientIp(ghttp.RequestFromCtx(ctx))
data.Status = consts.SmsStatusNotUsed
data.CreatedAt = gtime.Now()
data.UpdatedAt = gtime.Now()
_, err = dao.SysSmsLog.Ctx(ctx).Data(data).Insert()
if err != nil {
return err
}
return nil
}
// GetTemplate 获取指定短信模板
func (s *sSysSmsLog) GetTemplate(ctx context.Context, template string, config *model.SmsConfig) (val string, err error) {
if template == "" {
return "", gerror.New("模板不能为空")
}
if config == nil {
config, err = service.SysConfig().GetSms(ctx)
if err != nil {
return "", err
}
}
switch config.SmsDrive {
case consts.SmsDriveAliYun:
if len(config.SmsAliyunTemplate) == 0 {
return "", gerror.New("管理员还没有配置任何模板!")
}
for _, v := range config.SmsAliyunTemplate {
if v.Key == template {
return v.Value, nil
}
}
case consts.SmsDriveTencent:
return "", gerror.Newf("暂不支持短信驱动:%v", config.SmsDrive)
default:
return "", gerror.Newf("暂不支持短信驱动:%v", config.SmsDrive)
}
return
}
// AllowSend 是否允许发送
func (s *sSysSmsLog) AllowSend(ctx context.Context, models *entity.SysSmsLog, config *model.SmsConfig) (err error) {
if models == nil {
return nil
}
if config == nil {
config, err = service.SysConfig().GetSms(ctx)
if err != nil {
return err
}
}
if gtime.Now().Before(models.CreatedAt.Add(time.Second * time.Duration(config.SmsMinInterval))) {
return gerror.New("发送频繁,请稍后再试!")
}
if config.SmsMaxIpLimit > 0 {
count, err := dao.SysSmsLog.NowDayCount(ctx, models.Event, models.Mobile)
if err != nil {
return err
}
if count >= config.SmsMaxIpLimit {
return gerror.New("今天发送短信过多,请次日后再试!")
}
}
return
}
// VerifyCode 效验验证码
func (s *sSysSmsLog) VerifyCode(ctx context.Context, in sysin.VerifyCodeInp) (err error) {
if in.Event == "" {
return gerror.New("事件不能为空")
}
if in.Mobile == "" {
return gerror.New("手机号不能为空")
}
config, err := service.SysConfig().GetSms(ctx)
if err != nil {
return err
}
var (
models *entity.SysSmsLog
)
if err = dao.SysSmsLog.Ctx(ctx).Where("event", in.Event).Where("mobile", in.Mobile).Order("id desc").Scan(&models); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
if models == nil {
return gerror.New("验证码错误")
}
if models.Times >= 10 {
return gerror.New("验证码错误次数过多,请重新发送!")
}
if in.Event != consts.SmsTemplateCode {
if models.Status == consts.SmsStatusUsed {
return gerror.New("验证码已使用,请重新发送!")
}
}
if gtime.Now().After(models.CreatedAt.Add(time.Second * time.Duration(config.SmsCodeExpire))) {
return gerror.New("验证码已过期,请重新发送")
}
if models.Code != in.Code {
_, err = dao.SysSmsLog.Ctx(ctx).Where("id", models.Id).Increment("times", 1)
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return gerror.New("验证码错误!")
}
_, err = dao.SysSmsLog.Ctx(ctx).Where("id", models.Id).Data(g.Map{
"times": models.Times + 1,
"status": consts.SmsStatusUsed,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return err
}
return
}

View File

@@ -82,6 +82,13 @@ type LogConfig struct {
SkipCode []string `json:"skipCode"`
}
// ServeLogConfig 服务日志配置
type ServeLogConfig struct {
Switch bool `json:"switch"`
Queue bool `json:"queue"`
LevelFormat []string `json:"levelFormat"`
}
// GenerateAppCrudTemplate curd模板
type GenerateAppCrudTemplate struct {
Group string `json:"group"`

View File

@@ -20,6 +20,8 @@ type AdminDept struct {
Leader interface{} // 负责人
Phone interface{} // 联系电话
Email interface{} // 邮箱
Level interface{} // 关系树等级
Tree interface{} // 关系树
Sort interface{} // 排序
Status interface{} // 部门状态
CreatedAt *gtime.Time // 创建时间

View File

@@ -14,6 +14,7 @@ import (
type SysLog struct {
g.Meta `orm:"table:hg_sys_log, do:true"`
Id interface{} // 日志ID
ReqId interface{} // 对外ID
AppId interface{} // 应用ID
MerchantId interface{} // 商户ID
MemberId interface{} // 用户ID
@@ -29,10 +30,9 @@ type SysLog struct {
ErrorCode interface{} // 报错code
ErrorMsg interface{} // 报错信息
ErrorData *gjson.Json // 报错日志
ReqId interface{} // 对外ID
Timestamp interface{} // 响应时间
UserAgent interface{} // UA信息
TakeUpTime interface{} // 请求耗时
Timestamp interface{} // 响应时间
Status interface{} // 状态
CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 修改时间

View File

@@ -0,0 +1,26 @@
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// SysLoginLog is the golang structure of table hg_sys_login_log for DAO operations like Where/Data.
type SysLoginLog struct {
g.Meta `orm:"table:hg_sys_login_log, do:true"`
Id interface{} // 日志ID
ReqId interface{} // 请求ID
MemberId interface{} // 用户ID
Username interface{} // 用户名
Response *gjson.Json // 响应数据
LoginAt *gtime.Time // 登录时间
ErrMsg interface{} // 错误提示
Status interface{} // 状态
CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 修改时间
}

View File

@@ -11,20 +11,17 @@ import (
// SysProvinces is the golang structure of table hg_sys_provinces for DAO operations like Where/Data.
type SysProvinces struct {
g.Meta `orm:"table:hg_sys_provinces, do:true"`
Id interface{} // 省市区ID
Title interface{} // 栏目名称
ShortTitle interface{} // 缩写
Areacode interface{} // 区域编码
Zipcode interface{} // 邮政编码
Pinyin interface{} // 拼音
Lng interface{} // 经度
Lat interface{} // 纬度
Pid interface{} // 父栏目
Level interface{} // 关系树等级
Tree interface{} // 关系
Sort interface{} // 排序
Status interface{} // 状态
CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 更新时间
g.Meta `orm:"table:hg_sys_provinces, do:true"`
Id interface{} // 省市区ID
Title interface{} // 栏目名称
Pinyin interface{} // 拼音
Lng interface{} // 经度
Lat interface{} // 纬度
Pid interface{} // 父栏目
Level interface{} // 关系树等级
Tree interface{} // 关系
Sort interface{} // 排序
Status interface{} // 状态
CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 更新时间
}

View File

@@ -0,0 +1,26 @@
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// SysServeLog is the golang structure of table hg_sys_serve_log for DAO operations like Where/Data.
type SysServeLog struct {
g.Meta `orm:"table:hg_sys_serve_log, do:true"`
Id interface{} // 日志ID
TraceId interface{} // 链路ID
LevelFormat interface{} // 日志级别
Content interface{} // 日志内容
Stack *gjson.Json // 打印堆栈
Line interface{} // 调用行
TriggerNs interface{} // 触发时间(ns)
Status interface{} // 状态
CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 修改时间
}

View File

@@ -0,0 +1,24 @@
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// SysSmsLog is the golang structure of table hg_sys_sms_log for DAO operations like Where/Data.
type SysSmsLog struct {
g.Meta `orm:"table:hg_sys_sms_log, do:true"`
Id interface{} // 主键
Event interface{} // 事件
Mobile interface{} // 手机号
Code interface{} // 验证码或短信内容
Times interface{} // 验证次数
Ip interface{} // ip地址
Status interface{} // 状态(1未验证,2已验证)
CreatedAt *gtime.Time // 创建时间
UpdatedAt *gtime.Time // 更新时间
}

View File

@@ -18,6 +18,8 @@ type AdminDept struct {
Leader string `json:"leader" description:"负责人"`
Phone string `json:"phone" description:"联系电话"`
Email string `json:"email" description:"邮箱"`
Level int `json:"level" description:"关系树等级"`
Tree string `json:"tree" description:"关系树"`
Sort int `json:"sort" description:"排序"`
Status int `json:"status" description:"部门状态"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`

View File

@@ -12,6 +12,7 @@ import (
// SysLog is the golang structure for table sys_log.
type SysLog struct {
Id int64 `json:"id" description:"日志ID"`
ReqId string `json:"reqId" description:"对外ID"`
AppId string `json:"appId" description:"应用ID"`
MerchantId uint64 `json:"merchantId" description:"商户ID"`
MemberId int64 `json:"memberId" description:"用户ID"`
@@ -27,10 +28,9 @@ type SysLog struct {
ErrorCode int `json:"errorCode" description:"报错code"`
ErrorMsg string `json:"errorMsg" description:"报错信息"`
ErrorData *gjson.Json `json:"errorData" description:"报错日志"`
ReqId string `json:"reqId" description:"对外ID"`
Timestamp int64 `json:"timestamp" description:"响应时间"`
UserAgent string `json:"userAgent" description:"UA信息"`
TakeUpTime int64 `json:"takeUpTime" description:"请求耗时"`
Timestamp int64 `json:"timestamp" description:"响应时间"`
Status int `json:"status" description:"状态"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`

View File

@@ -0,0 +1,24 @@
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime"
)
// SysLoginLog is the golang structure for table sys_login_log.
type SysLoginLog struct {
Id int64 `json:"id" description:"日志ID"`
ReqId string `json:"reqId" description:"请求ID"`
MemberId int64 `json:"memberId" description:"用户ID"`
Username string `json:"username" description:"用户名"`
Response *gjson.Json `json:"response" description:"响应数据"`
LoginAt *gtime.Time `json:"loginAt" description:"登录时间"`
ErrMsg string `json:"errMsg" description:"错误提示"`
Status int `json:"status" description:"状态"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
}

View File

@@ -10,19 +10,16 @@ import (
// SysProvinces is the golang structure for table sys_provinces.
type SysProvinces struct {
Id int64 `json:"id" description:"省市区ID"`
Title string `json:"title" description:"栏目名称"`
ShortTitle string `json:"shortTitle" description:"缩写"`
Areacode int `json:"areacode" description:"区域编码"`
Zipcode int `json:"zipcode" description:"邮政编码"`
Pinyin string `json:"pinyin" description:"拼音"`
Lng string `json:"lng" description:"经度"`
Lat string `json:"lat" description:"纬度"`
Pid int64 `json:"pid" description:"父栏目"`
Level int `json:"level" description:"关系树等级"`
Tree string `json:"tree" description:"关系"`
Sort int `json:"sort" description:"排序"`
Status int `json:"status" description:"状态"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
Id int64 `json:"id" description:"省市区ID"`
Title string `json:"title" description:"栏目名称"`
Pinyin string `json:"pinyin" description:"拼音"`
Lng string `json:"lng" description:"经度"`
Lat string `json:"lat" description:"纬度"`
Pid int64 `json:"pid" description:"父栏目"`
Level int `json:"level" description:"关系树等级"`
Tree string `json:"tree" description:"关系"`
Sort int `json:"sort" description:"排序"`
Status int `json:"status" description:"状态"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
}

View File

@@ -0,0 +1,24 @@
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/os/gtime"
)
// SysServeLog is the golang structure for table sys_serve_log.
type SysServeLog struct {
Id int64 `json:"id" description:"日志ID"`
TraceId string `json:"traceId" description:"链路ID"`
LevelFormat string `json:"levelFormat" description:"日志级别"`
Content string `json:"content" description:"日志内容"`
Stack *gjson.Json `json:"stack" description:"打印堆栈"`
Line string `json:"line" description:"调用行"`
TriggerNs int64 `json:"triggerNs" description:"触发时间(ns)"`
Status int `json:"status" description:"状态"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"`
}

View File

@@ -0,0 +1,22 @@
// =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/os/gtime"
)
// SysSmsLog is the golang structure for table sys_sms_log.
type SysSmsLog struct {
Id int64 `json:"id" description:"主键"`
Event string `json:"event" description:"事件"`
Mobile string `json:"mobile" description:"手机号"`
Code string `json:"code" description:"验证码或短信内容"`
Times int64 `json:"times" description:"验证次数"`
Ip string `json:"ip" description:"ip地址"`
Status int `json:"status" description:"状态(1未验证,2已验证)"`
CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"`
}

View File

@@ -46,7 +46,7 @@ func DefaultPage(ctx context.Context) int {
// PageReq 分页
type PageReq struct {
Page int `json:"page" example:"10" d:"1" v:"min:1#页码最小值不能低于1" dc:"当前页码"`
PerPage int `json:"pageSize" example:"1" d:"10" v:"min:1|max:100#|每页数量最小值不能低于1|最大值不能大于100" dc:"每页数量"`
PerPage int `json:"pageSize" example:"1" d:"10" v:"min:1|max:200#|每页数量最小值不能低于1|最大值不能大于200" dc:"每页数量"`
}
type PageRes struct {
PageReq

View File

@@ -59,3 +59,9 @@ type CronStatusInp struct {
entity.SysCron
}
type CronStatusModel struct{}
// OnlineExecInp 在线执行
type OnlineExecInp struct {
entity.SysCron
}
type OnlineExecModel struct{}

View File

@@ -0,0 +1,90 @@
// Package sysin
// @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 sysin
import (
"context"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/adminin"
"hotgo/internal/model/input/form"
)
// LoginLogDeleteInp 删除登录日志
type LoginLogDeleteInp struct {
Id interface{} `json:"id" v:"required#日志ID不能为空" dc:"日志ID"`
}
type LoginLogDeleteModel struct{}
// LoginLogViewInp 获取指定登录日志信息
type LoginLogViewInp struct {
Id int64 `json:"id" v:"required#日志ID不能为空" dc:"日志ID"`
}
type LoginLogViewModel struct {
entity.Test
}
// LoginLogListInp 获取登录日志列表
type LoginLogListInp struct {
form.PageReq
Username string `json:"username" dc:"用户名"`
Status int `json:"status" dc:"状态"`
LoginAt []*gtime.Time `json:"loginAt" dc:"登录时间"`
SysLogIp string `json:"sysLogIp" dc:"IP地址"`
}
type LoginLogListModel struct {
Id int64 `json:"id" dc:"日志ID"`
ReqId string `json:"reqId" dc:"请求ID"`
MemberId int64 `json:"memberId" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
LoginAt *gtime.Time `json:"loginAt" dc:"登录时间"`
ErrMsg string `json:"errMsg" dc:"错误提示"`
Status int `json:"status" dc:"状态"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
SysLogId int64 `json:"sysLogId" dc:"日志ID"`
SysLogIp string `json:"sysLogIp" dc:"IP地址"`
SysLogProvinceId int64 `json:"sysLogProvinceId" dc:"省编码"`
SysLogCityId int64 `json:"sysLogCityId" dc:"市编码"`
SysLogErrorCode int `json:"sysLogErrorCode" dc:"报错code"`
SysLogUserAgent string `json:"sysLogUserAgent" dc:"UA信息"`
Region string `json:"region" dc:"地区"`
Os string `json:"os" dc:"系统信息"`
Browser string `json:"browser" dc:"浏览器信息"`
}
func (in *LoginLogListInp) Filter(ctx context.Context) (err error) {
return
}
// LoginLogExportModel 导出登录日志
type LoginLogExportModel struct {
Id int64 `json:"id" dc:"日志ID"`
ReqId string `json:"reqId" dc:"请求ID"`
MemberId int64 `json:"memberId" dc:"用户ID"`
Username string `json:"username" dc:"用户名"`
LoginAt int64 `json:"loginAt" dc:"登录时间"`
ErrMsg string `json:"errMsg" dc:"错误提示"`
Status int `json:"status" dc:"状态"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
SysLogIp string `json:"sysLogIp" dc:"IP地址"`
SysLogProvinceId int64 `json:"sysLogProvinceId" dc:"省编码"`
SysLogCityId int64 `json:"sysLogCityId" dc:"市编码"`
SysLogErrorCode int `json:"sysLogErrorCode" dc:"报错code"`
SysLogUserAgent string `json:"sysLogUserAgent" dc:"UA信息"`
}
// LoginLogPushInp 解推送登录日志
type LoginLogPushInp struct {
Input adminin.MemberLoginInp
Response *adminin.MemberLoginModel
Err error
}

View File

@@ -13,11 +13,10 @@ import (
// ProvincesMaxSortInp 最大排序
type ProvincesMaxSortInp struct {
Id int64
}
type ProvincesMaxSortModel struct {
Sort int
Sort int `json:"sort" dc:"排序"`
}
// ProvincesEditInp 修改/新增字典数据
@@ -28,7 +27,7 @@ type ProvincesEditModel struct{}
// ProvincesDeleteInp 删除字典类型
type ProvincesDeleteInp struct {
Id interface{}
Id interface{} `json:"id" v:"required#省市区ID不能为空" dc:"省市区ID"`
}
type ProvincesDeleteModel struct{}
@@ -59,3 +58,26 @@ type ProvincesStatusInp struct {
entity.SysProvinces
}
type ProvincesStatusModel struct{}
// ProvincesChildrenListInp 获取省市区下级列表
type ProvincesChildrenListInp struct {
form.PageReq
form.StatusReq
Pid int64 `json:"pid" dc:"上级ID"`
Id int64 `json:"id" dc:"地区ID"`
Title string `json:"title" dc:"地区名称"`
}
type ProvincesChildrenListModel struct {
entity.SysProvinces
}
// ProvincesUniqueIdInp 获取省市区下级列表
type ProvincesUniqueIdInp struct {
OldId int64 `json:"oldId" dc:"原始ID"`
NewId int64 `json:"newId" dc:"新的ID"`
}
type ProvincesUniqueIdModel struct {
IsUnique bool `json:"unique" dc:"是否唯一"`
}

View File

@@ -0,0 +1,69 @@
// Package sysin
// @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 sysin
import (
"context"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/form"
)
// ServeLogDeleteInp 删除服务日志
type ServeLogDeleteInp struct {
Id interface{} `json:"id" v:"required#日志ID不能为空" dc:"日志ID"`
}
type ServeLogDeleteModel struct{}
// ServeLogViewInp 获取指定服务日志信息
type ServeLogViewInp struct {
Id int64 `json:"id" v:"required#日志ID不能为空" dc:"日志ID"`
}
type ServeLogViewModel struct {
entity.Test
}
// ServeLogListInp 获取服务日志列表
type ServeLogListInp struct {
form.PageReq
TraceId string `json:"traceId" dc:"链路ID"`
LevelFormat string `json:"levelFormat" dc:"日志级别"`
TriggerNs []int64 `json:"triggerNs" dc:"触发时间(ns)"`
CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"`
}
type ServeLogListModel struct {
Id int64 `json:"id" dc:"日志ID"`
TraceId string `json:"traceId" dc:"链路ID"`
LevelFormat string `json:"levelFormat" dc:"日志级别"`
Content string `json:"content" dc:"日志内容"`
Stack string `json:"stack" dc:"堆栈"`
Line string `json:"line" dc:"调用行"`
TriggerNs int64 `json:"triggerNs" dc:"触发时间(ns)"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
SysLogId int64 `json:"sysLogId" dc:"访问日志ID"`
}
func (in *ServeLogListInp) Filter(ctx context.Context) (err error) {
return
}
// ServeLogExportModel 导出服务日志
type ServeLogExportModel struct {
Id int64 `json:"id" dc:"日志ID"`
Env string `json:"env" dc:"环境"`
TraceId string `json:"traceId" dc:"链路ID"`
LevelFormat string `json:"levelFormat" dc:"日志级别"`
Content string `json:"content" dc:"日志内容"`
Line string `json:"line" dc:"调用行"`
TriggerNs int64 `json:"triggerNs" dc:"触发时间(ns)"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"`
}

View File

@@ -0,0 +1,76 @@
// Package sysin
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package sysin
import (
"hotgo/internal/model/entity"
"hotgo/internal/model/input/form"
)
// SmsLogMaxSortInp 最大排序
type SmsLogMaxSortInp struct {
Id int64
}
type SmsLogMaxSortModel struct {
Sort int
}
// SmsLogEditInp 修改/新增数据
type SmsLogEditInp struct {
entity.SysSmsLog
}
type SmsLogEditModel struct{}
// SmsLogDeleteInp 删除
type SmsLogDeleteInp struct {
Id interface{}
}
type SmsLogDeleteModel struct{}
// SmsLogViewInp 获取信息
type SmsLogViewInp struct {
Id int64
}
type SmsLogViewModel struct {
entity.SysSmsLog
}
// SmsLogListInp 获取列表
type SmsLogListInp struct {
form.PageReq
form.RangeDateReq
form.StatusReq
Title string
Content string
}
type SmsLogListModel struct {
entity.SysSmsLog
}
// SmsLogStatusInp 更新状态
type SmsLogStatusInp struct {
entity.SysSmsLog
}
type SmsLogStatusModel struct{}
// SendCodeInp 发送验证码
type SendCodeInp struct {
Event string `json:"event" description:"事件"` // 必填
Mobile string `json:"mobile" description:"手机号"` // 必填
Code string `json:"code" description:"验证码或短信内容"`
Template string `json:"-" description:"发信模板 "`
}
// VerifyCodeInp 效验验证码
type VerifyCodeInp struct {
Event string `json:"event" description:"事件"` // 必填
Mobile string `json:"mobile" description:"手机号"` // 必填
Code string `json:"code" description:"验证码或短信内容"` // 必填
}

View File

@@ -8,22 +8,63 @@ package queues
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/library/queue"
)
type jobStrategy interface {
Listen(ctx context.Context)
getTopic() string
handle(ctx context.Context, mqMsg queue.MqMsg) (err error)
}
var (
jobList = []jobStrategy{
SysLog,
}
)
var jobList []jobStrategy
func Run(ctx context.Context) {
for _, job := range jobList {
job.Listen(ctx)
for _, job := range uniqueJob(jobList) {
go func(job jobStrategy) {
listen(ctx, job)
}(job)
}
}
func listen(ctx context.Context, job jobStrategy) {
var (
topic = job.getTopic()
consumer, err = queue.InstanceConsumer()
)
if err != nil {
g.Log().Fatalf(ctx, "InstanceConsumer %s err:%+v", topic, err)
return
}
// 访问日志
if listenErr := consumer.ListenReceiveMsgDo(topic, func(mqMsg queue.MqMsg) {
err = job.handle(ctx, mqMsg)
if err != nil {
// 遇到错误,重新加入到队列
//queue.Push(topic, mqMsg.Body)
}
// 记录队列日志
queue.ConsumerLog(ctx, topic, mqMsg, err)
}); listenErr != nil {
g.Log().Fatalf(ctx, "队列:%s 监听失败, err:%+v", topic, listenErr)
}
}
// uniqueJob 去重
func uniqueJob(languages []jobStrategy) []jobStrategy {
result := make([]jobStrategy, 0, len(languages))
temp := map[jobStrategy]struct{}{}
for _, item := range languages {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}

View File

@@ -0,0 +1,39 @@
// Package queues
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package queues
import (
"context"
"encoding/json"
"hotgo/internal/consts"
"hotgo/internal/library/queue"
"hotgo/internal/model/entity"
"hotgo/internal/service"
)
func init() {
jobList = append(jobList, LoginLog)
}
// LoginLog 登录日志
var LoginLog = &qLoginLog{}
type qLoginLog struct{}
// getTopic 主题
func (q *qLoginLog) getTopic() string {
return consts.QueueLoginLogTopic
}
// handle 处理消息
func (q *qLoginLog) handle(ctx context.Context, mqMsg queue.MqMsg) (err error) {
var data entity.SysLoginLog
if err = json.Unmarshal(mqMsg.Body, &data); err != nil {
return err
}
return service.SysLoginLog().RealWrite(ctx, data)
}

View File

@@ -0,0 +1,39 @@
// Package queues
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package queues
import (
"context"
"encoding/json"
"hotgo/internal/consts"
"hotgo/internal/library/queue"
"hotgo/internal/model/entity"
"hotgo/internal/service"
)
func init() {
jobList = append(jobList, ServeLog)
}
// ServeLog 登录日志
var ServeLog = &qServeLog{}
type qServeLog struct{}
// getTopic 主题
func (q *qServeLog) getTopic() string {
return consts.QueueServeLogTopic
}
// handle 处理消息
func (q *qServeLog) handle(ctx context.Context, mqMsg queue.MqMsg) (err error) {
var data entity.SysServeLog
if err = json.Unmarshal(mqMsg.Body, &data); err != nil {
return err
}
return service.SysServeLog().RealWrite(ctx, data)
}

View File

@@ -8,40 +8,32 @@ package queues
import (
"context"
"encoding/json"
"hotgo/internal/consts"
"hotgo/internal/library/queue"
"hotgo/internal/model/entity"
"hotgo/internal/service"
)
// SysLog 系统日志
var SysLog = &qSysLog{topic: consts.QueueLogTopic}
func init() {
jobList = append(jobList, SysLog)
}
type qSysLog struct {
topic string
// SysLog 系统日志
var SysLog = &qSysLog{}
type qSysLog struct{}
// getTopic 主题
func (q *qSysLog) getTopic() string {
return consts.QueueLogTopic
}
// handle 处理消息
func (q *qSysLog) handle(ctx context.Context, mqMsg queue.MqMsg) (err error) {
return service.SysLog().QueueJob(ctx, mqMsg)
}
// Listen 监听
func (q *qSysLog) Listen(ctx context.Context) {
consumer, err := queue.InstanceConsumer()
if err != nil {
queue.FatalLog(ctx, "InstanceConsumer "+q.topic+"异常:", err)
return
var data entity.SysLog
if err = json.Unmarshal(mqMsg.Body, &data); err != nil {
return err
}
// 全局日志
if listenErr := consumer.ListenReceiveMsgDo(q.topic, func(mqMsg queue.MqMsg) {
err = q.handle(ctx, mqMsg)
// 记录队列日志
queue.ConsumerLog(ctx, q.topic, mqMsg, err)
}); listenErr != nil {
queue.FatalLog(ctx, "队列:"+q.topic+" 监听失败", listenErr)
}
return service.SysLog().RealWrite(ctx, data)
}

View File

@@ -30,8 +30,8 @@ func Admin(ctx context.Context, group *ghttp.RouterGroup) {
common.Site, // 基础
common.Console, // 控制台
common.Ems, // 邮件
common.Sms, // 短信
common.Upload, // 上传
sys.Log, // 日志
sys.Config, // 配置
sys.DictType, // 字典类型
sys.DictData, // 字典数据
@@ -41,6 +41,10 @@ func Admin(ctx context.Context, group *ghttp.RouterGroup) {
sys.CronGroup, // 定时任务分组
sys.Blacklist, // 黑名单
sys.GenCodes, // 生成代码
sys.Log, // 访问日志
sys.LoginLog, // 登录日志
sys.ServeLog, // 服务日志
sys.SmsLog, // 短信记录
admin.Member, // 用户
admin.Monitor, // 监控
admin.Role, // 路由

View File

@@ -14,12 +14,45 @@ import (
"hotgo/internal/model/input/form"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
type (
IAdminMenu interface {
RoleList(ctx context.Context, in adminin.MenuRoleListInp) (*adminin.MenuRoleListModel, error)
SearchList(ctx context.Context, req *menu.SearchListReq) (*menu.SearchListRes, error)
MaxSort(ctx context.Context, req *menu.MaxSortReq) (*menu.MaxSortRes, error)
NameUnique(ctx context.Context, req *menu.NameUniqueReq) (*menu.NameUniqueRes, error)
CodeUnique(ctx context.Context, req *menu.CodeUniqueReq) (*menu.CodeUniqueRes, error)
Delete(ctx context.Context, req *menu.DeleteReq) 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) (lists role.DynamicRes, err error)
LoginPermissions(ctx context.Context, memberId int64) (lists []*adminin.MemberLoginPermissions, err error)
}
IAdminNotice interface {
Delete(ctx context.Context, in adminin.NoticeDeleteInp) 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) (*adminin.NoticeMaxSortModel, 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)
}
IAdminPost interface {
Delete(ctx context.Context, in adminin.PostDeleteInp) error
Edit(ctx context.Context, in adminin.PostEditInp) (err error)
MaxSort(ctx context.Context, in adminin.PostMaxSortInp) (*adminin.PostMaxSortModel, error)
NameUnique(ctx context.Context, in adminin.PostNameUniqueInp) (*adminin.PostNameUniqueModel, error)
CodeUnique(ctx context.Context, in adminin.PostCodeUniqueInp) (*adminin.PostCodeUniqueModel, error)
View(ctx context.Context, in adminin.PostViewInp) (res *adminin.PostViewModel, err error)
List(ctx context.Context, in adminin.PostListInp) (list []*adminin.PostListModel, totalCount int, err error)
GetMemberByStartName(ctx context.Context, memberId int64) (name string, err error)
Status(ctx context.Context, in adminin.PostStatusInp) (err error)
}
IAdminRole interface {
Verify(ctx context.Context, path, method string) bool
List(ctx context.Context, in adminin.RoleListInp) (list []*adminin.RoleListModel, totalCount int, err error)
List(ctx context.Context, in adminin.RoleListInp) (list []g.Map, totalCount int, err error)
GetName(ctx context.Context, RoleId int64) (name string, err error)
GetMemberList(ctx context.Context, RoleId int64) (list []*adminin.RoleListModel, err error)
GetPermissions(ctx context.Context, reqInfo *role.GetPermissionsReq) (MenuIds []int64, err error)
@@ -74,38 +107,6 @@ type (
UpdatePostIds(ctx context.Context, member_id int64, post_ids []int64) (err error)
GetMemberByIds(ctx context.Context, member_id int64) (post_ids []int64, err error)
}
IAdminMenu interface {
RoleList(ctx context.Context, in adminin.MenuRoleListInp) (*adminin.MenuRoleListModel, error)
SearchList(ctx context.Context, req *menu.SearchListReq) (*menu.SearchListRes, error)
MaxSort(ctx context.Context, req *menu.MaxSortReq) (*menu.MaxSortRes, error)
NameUnique(ctx context.Context, req *menu.NameUniqueReq) (*menu.NameUniqueRes, error)
CodeUnique(ctx context.Context, req *menu.CodeUniqueReq) (*menu.CodeUniqueRes, error)
Delete(ctx context.Context, req *menu.DeleteReq) 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) (lists role.DynamicRes, err error)
LoginPermissions(ctx context.Context, memberId int64) (lists []*adminin.MemberLoginPermissions, err error)
}
IAdminNotice interface {
Delete(ctx context.Context, in adminin.NoticeDeleteInp) 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) (*adminin.NoticeMaxSortModel, 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)
}
IAdminPost interface {
Delete(ctx context.Context, in adminin.PostDeleteInp) error
Edit(ctx context.Context, in adminin.PostEditInp) (err error)
MaxSort(ctx context.Context, in adminin.PostMaxSortInp) (*adminin.PostMaxSortModel, error)
NameUnique(ctx context.Context, in adminin.PostNameUniqueInp) (*adminin.PostNameUniqueModel, error)
CodeUnique(ctx context.Context, in adminin.PostCodeUniqueInp) (*adminin.PostCodeUniqueModel, error)
View(ctx context.Context, in adminin.PostViewInp) (res *adminin.PostViewModel, err error)
List(ctx context.Context, in adminin.PostListInp) (list []*adminin.PostListModel, totalCount int, err error)
GetMemberByStartName(ctx context.Context, memberId int64) (name string, err error)
Status(ctx context.Context, in adminin.PostStatusInp) (err error)
}
)
var (
@@ -119,39 +120,6 @@ var (
localAdminMember IAdminMember
)
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?")
}
return localAdminMember
}
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?")
@@ -206,3 +174,36 @@ func AdminTest() IAdminTest {
func RegisterAdminTest(i IAdminTest) {
localAdminTest = 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?")
}
return localAdminMember
}
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
}

View File

@@ -16,6 +16,7 @@ type (
Ctx(r *ghttp.Request)
CORS(r *ghttp.Request)
DemoLimit(r *ghttp.Request)
Blacklist(r *ghttp.Request)
ResponseHandler(r *ghttp.Request)
WebSocketToken(r *ghttp.Request)
}

View File

@@ -7,7 +7,6 @@ package service
import (
"context"
"hotgo/internal/library/queue"
"hotgo/internal/model"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/sysin"
@@ -17,24 +16,6 @@ import (
)
type (
ISysLog interface {
Export(ctx context.Context, in sysin.LogListInp) (err error)
RealWrite(ctx context.Context, commonLog entity.SysLog) error
AutoLog(ctx context.Context) (err error)
QueueJob(ctx context.Context, mqMsg queue.MqMsg) (err 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) error
List(ctx context.Context, in sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
}
ISysProvinces interface {
Delete(ctx context.Context, in sysin.ProvincesDeleteInp) 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) (*sysin.ProvincesMaxSortModel, 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)
}
ISysAttachment interface {
Delete(ctx context.Context, in sysin.AttachmentDeleteInp) error
Edit(ctx context.Context, in sysin.AttachmentEditInp) (err error)
@@ -44,22 +25,48 @@ type (
List(ctx context.Context, in sysin.AttachmentListInp) (list []*sysin.AttachmentListModel, totalCount int, err error)
Add(ctx context.Context, meta *sysin.UploadFileMeta, fullPath, drive string) (data *entity.SysAttachment, 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)
}
ISysProvinces interface {
Tree(ctx context.Context) (list []g.Map, err error)
Delete(ctx context.Context, in sysin.ProvincesDeleteInp) 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)
}
ISysBlacklist interface {
Delete(ctx context.Context, in sysin.BlacklistDeleteInp) error
Delete(ctx context.Context, in sysin.BlacklistDeleteInp) (err error)
Edit(ctx context.Context, in sysin.BlacklistEditInp) (err error)
Status(ctx context.Context, in sysin.BlacklistStatusInp) (err error)
MaxSort(ctx context.Context, in sysin.BlacklistMaxSortInp) (*sysin.BlacklistMaxSortModel, error)
View(ctx context.Context, in sysin.BlacklistViewInp) (res *sysin.BlacklistViewModel, err error)
List(ctx context.Context, in sysin.BlacklistListInp) (list []*sysin.BlacklistListModel, totalCount int, err error)
VariableLoad(ctx context.Context, err error)
Load(ctx context.Context)
}
ISysCron interface {
StartCron(ctx context.Context)
Delete(ctx context.Context, in sysin.CronDeleteInp) 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) (*sysin.CronMaxSortModel, 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)
ISysConfig interface {
GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
GetLoadServeLog(ctx context.Context) (conf *model.ServeLogConfig, err error)
GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (*sysin.GetConfigModel, error)
ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) error
}
ISysCronGroup interface {
Delete(ctx context.Context, in sysin.CronGroupDeleteInp) error
@@ -87,17 +94,44 @@ type (
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)
}
ISysConfig interface {
GetLoadGenerate(ctx context.Context) (conf *model.GenerateConfig, err error)
GetSms(ctx context.Context) (conf *model.SmsConfig, err error)
GetGeo(ctx context.Context) (conf *model.GeoConfig, err error)
GetUpload(ctx context.Context) (conf *model.UploadConfig, err error)
GetSmtp(ctx context.Context) (conf *model.EmailConfig, err error)
GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error)
GetLoadLog(ctx context.Context) (conf *model.LogConfig, err error)
GetConfigByGroup(ctx context.Context, in sysin.GetConfigInp) (*sysin.GetConfigModel, error)
ConversionType(ctx context.Context, models *entity.SysConfig) (value interface{}, err error)
UpdateConfigByGroup(ctx context.Context, in sysin.UpdateConfigInp) error
ISysLog interface {
Export(ctx context.Context, in sysin.LogListInp) (err error)
RealWrite(ctx context.Context, commonLog entity.SysLog) (err error)
AutoLog(ctx context.Context) (err 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) 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)
}
ISysSmsLog interface {
Delete(ctx context.Context, in sysin.SmsLogDeleteInp) 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) (*sysin.SmsLogMaxSortModel, 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)
}
ISysCron interface {
StartCron(ctx context.Context)
Delete(ctx context.Context, in sysin.CronDeleteInp) 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) (*sysin.CronMaxSortModel, 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)
}
ISysDictType interface {
Tree(ctx context.Context) (list []g.Map, err error)
@@ -123,28 +157,75 @@ type (
)
var (
localSysBlacklist ISysBlacklist
localSysCron ISysCron
localSysCronGroup ISysCronGroup
localSysBlacklist ISysBlacklist
localSysConfig ISysConfig
localSysCurdDemo ISysCurdDemo
localSysDictData ISysDictData
localSysGenCodes ISysGenCodes
localSysLog ISysLog
localSysServeLog ISysServeLog
localSysSmsLog ISysSmsLog
localSysCron ISysCron
localSysDictType ISysDictType
localSysProvinces ISysProvinces
localSysAttachment ISysAttachment
localSysDictType ISysDictType
localSysGenCodes ISysGenCodes
localSysConfig ISysConfig
localSysLoginLog ISysLoginLog
)
func SysBlacklist() ISysBlacklist {
if localSysBlacklist == nil {
panic("implement not found for interface ISysBlacklist, forgot register?")
func SysDictType() ISysDictType {
if localSysDictType == nil {
panic("implement not found for interface ISysDictType, forgot register?")
}
return localSysBlacklist
return localSysDictType
}
func RegisterSysBlacklist(i ISysBlacklist) {
localSysBlacklist = i
func RegisterSysDictType(i ISysDictType) {
localSysDictType = i
}
func SysGenCodes() ISysGenCodes {
if localSysGenCodes == nil {
panic("implement not found for interface ISysGenCodes, forgot register?")
}
return localSysGenCodes
}
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 SysServeLog() ISysServeLog {
if localSysServeLog == nil {
panic("implement not found for interface ISysServeLog, forgot register?")
}
return localSysServeLog
}
func RegisterSysServeLog(i ISysServeLog) {
localSysServeLog = 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 SysCron() ISysCron {
@@ -158,48 +239,15 @@ func RegisterSysCron(i ISysCron) {
localSysCron = i
}
func SysCronGroup() ISysCronGroup {
if localSysCronGroup == nil {
panic("implement not found for interface ISysCronGroup, forgot register?")
func SysLoginLog() ISysLoginLog {
if localSysLoginLog == nil {
panic("implement not found for interface ISysLoginLog, forgot register?")
}
return localSysCronGroup
return localSysLoginLog
}
func RegisterSysCronGroup(i ISysCronGroup) {
localSysCronGroup = i
}
func SysCurdDemo() ISysCurdDemo {
if localSysCurdDemo == nil {
panic("implement not found for interface ISysCurdDemo, forgot register?")
}
return localSysCurdDemo
}
func RegisterSysCurdDemo(i ISysCurdDemo) {
localSysCurdDemo = 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 SysLog() ISysLog {
if localSysLog == nil {
panic("implement not found for interface ISysLog, forgot register?")
}
return localSysLog
}
func RegisterSysLog(i ISysLog) {
localSysLog = i
func RegisterSysLoginLog(i ISysLoginLog) {
localSysLoginLog = i
}
func SysProvinces() ISysProvinces {
@@ -224,28 +272,6 @@ func RegisterSysAttachment(i ISysAttachment) {
localSysAttachment = 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 SysGenCodes() ISysGenCodes {
if localSysGenCodes == nil {
panic("implement not found for interface ISysGenCodes, forgot register?")
}
return localSysGenCodes
}
func RegisterSysGenCodes(i ISysGenCodes) {
localSysGenCodes = i
}
func SysConfig() ISysConfig {
if localSysConfig == nil {
panic("implement not found for interface ISysConfig, forgot register?")
@@ -256,3 +282,47 @@ func SysConfig() ISysConfig {
func RegisterSysConfig(i ISysConfig) {
localSysConfig = 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 SysBlacklist() ISysBlacklist {
if localSysBlacklist == nil {
panic("implement not found for interface ISysBlacklist, forgot register?")
}
return localSysBlacklist
}
func RegisterSysBlacklist(i ISysBlacklist) {
localSysBlacklist = 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 SysCurdDemo() ISysCurdDemo {
if localSysCurdDemo == nil {
panic("implement not found for interface ISysCurdDemo, forgot register?")
}
return localSysCurdDemo
}
func RegisterSysCurdDemo(i ISysCurdDemo) {
localSysCurdDemo = i
}