mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-09-23 19:56:40 +08:00
更新2.1.2版本,优化部门、角色权限,增加上下级关系;增加登录、系统、短信日志;优化省市区编码
This commit is contained in:
parent
11fad0132d
commit
93e0fe7250
@ -27,11 +27,11 @@
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
## 平台简介
|
||||
* 基于全新Go Frame 2+Vue3+Naive UI开发的全栈前后端分离的管理系统
|
||||
* 前端采用naive-ui-admin 、Vue、Naive UI。
|
||||
|
||||
|
||||
## 特征
|
||||
* 高生产率:几分钟即可搭建一个后台管理系统
|
||||
* 模块化:单应用多系统的模式,将一个完整的应用拆分为多个系统,后续扩展更加便捷,增加代码复用性。
|
||||
@ -153,7 +153,7 @@ VITE_PROXY=[["/admin","http://你的IP:8000/admin"]]
|
||||
|
||||
web端:
|
||||
```shell script
|
||||
cd views
|
||||
cd web
|
||||
# 首先确定你以安装node16.0以上版本并安装了包[npm、yarn],否则可能会出现一些未知报错
|
||||
|
||||
# 安装依赖
|
||||
|
@ -32,12 +32,12 @@ type LoginReq struct {
|
||||
g.Meta `path:"/site/login" method:"post" tags:"后台基础" summary:"账号登录"`
|
||||
Username string `json:"username" v:"required#用户名不能为空" dc:"用户名"`
|
||||
Password string `json:"password" v:"required#密码不能为空" dc:"密码"`
|
||||
//Cid string `json:"cid" v:"required#验证码ID不能为空" dc:"验证码ID"`
|
||||
//Code string `json:"code" v:"required#验证码不能为空" dc:"验证码"`
|
||||
//Device string `json:"device" dc:"登录设备"`
|
||||
Cid string `json:"cid" dc:"验证码ID"`
|
||||
Code string `json:"code" dc:"验证码"`
|
||||
IsLock bool `json:"isLock" dc:"是否为锁屏状态"`
|
||||
}
|
||||
type LoginRes struct {
|
||||
adminin.MemberLoginModel
|
||||
*adminin.MemberLoginModel
|
||||
}
|
||||
|
||||
// SiteConfigReq 获取配置
|
||||
|
19
server/api/backend/common/sms.go
Normal file
19
server/api/backend/common/sms.go
Normal file
@ -0,0 +1,19 @@
|
||||
// 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 "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
// SendTestSmsReq 发送测试短信
|
||||
type SendTestSmsReq struct {
|
||||
Event string `json:"event" v:"required#事件模板不能为空" dc:"事件模板"`
|
||||
Mobile string `json:"mobile" v:"required#接收手机号不能为空" dc:"接收手机号"`
|
||||
Code string `json:"code" v:"required#接收验证码不能为空" dc:"接收验证码"`
|
||||
g.Meta `path:"/sms/sendTest" tags:"短信" method:"post" summary:"发送测试短信"`
|
||||
}
|
||||
type SendTestSmsRes struct {
|
||||
}
|
@ -66,3 +66,10 @@ type StatusReq struct {
|
||||
g.Meta `path:"/cron/status" method:"post" tags:"定时任务" summary:"更新定时任务状态"`
|
||||
}
|
||||
type StatusRes struct{}
|
||||
|
||||
// OnlineExecReq 在线执行
|
||||
type OnlineExecReq struct {
|
||||
g.Meta `path:"/cron/onlineExec" method:"post" tags:"定时任务" summary:"在线执行"`
|
||||
sysin.OnlineExecInp
|
||||
}
|
||||
type OnlineExecRes struct{}
|
||||
|
@ -20,7 +20,7 @@ type GroupListReq struct {
|
||||
form.StatusReq
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
g.Meta `path:"/cron_group/list" method:"get" tags:"定时任务分组" summary:"获取定时任务分组列表"`
|
||||
g.Meta `path:"/cronGroup/list" method:"get" tags:"定时任务分组" summary:"获取定时任务分组列表"`
|
||||
}
|
||||
|
||||
type GroupListRes struct {
|
||||
@ -31,7 +31,7 @@ type GroupListRes struct {
|
||||
// GroupViewReq 获取信息
|
||||
type GroupViewReq struct {
|
||||
Id int64 `json:"id" v:"required#定时任务分组ID不能为空" dc:"定时任务分组ID"`
|
||||
g.Meta `path:"/cron_group/view" method:"get" tags:"定时任务分组" summary:"获取指定信息"`
|
||||
g.Meta `path:"/cronGroup/view" method:"get" tags:"定时任务分组" summary:"获取指定信息"`
|
||||
}
|
||||
type GroupViewRes struct {
|
||||
*sysin.CronGroupViewModel
|
||||
@ -40,21 +40,21 @@ type GroupViewRes struct {
|
||||
// GroupEditReq 修改/新增
|
||||
type GroupEditReq struct {
|
||||
entity.SysCronGroup
|
||||
g.Meta `path:"/cron_group/edit" method:"post" tags:"定时任务分组" summary:"修改/新增定时任务分组"`
|
||||
g.Meta `path:"/cronGroup/edit" method:"post" tags:"定时任务分组" summary:"修改/新增定时任务分组"`
|
||||
}
|
||||
type GroupEditRes struct{}
|
||||
|
||||
// GroupDeleteReq 删除
|
||||
type GroupDeleteReq struct {
|
||||
Id interface{} `json:"id" v:"required#定时任务分组ID不能为空" dc:"定时任务分组ID"`
|
||||
g.Meta `path:"/cron_group/delete" method:"post" tags:"定时任务分组" summary:"删除定时任务分组"`
|
||||
g.Meta `path:"/cronGroup/delete" method:"post" tags:"定时任务分组" summary:"删除定时任务分组"`
|
||||
}
|
||||
type GroupDeleteRes struct{}
|
||||
|
||||
// GroupMaxSortReq 最大排序
|
||||
type GroupMaxSortReq struct {
|
||||
Id int64 `json:"id" dc:"定时任务分组ID"`
|
||||
g.Meta `path:"/cron_group/max_sort" method:"get" tags:"定时任务分组" summary:"定时任务分组最大排序"`
|
||||
g.Meta `path:"/cronGroup/max_sort" method:"get" tags:"定时任务分组" summary:"定时任务分组最大排序"`
|
||||
}
|
||||
type GroupMaxSortRes struct {
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
@ -63,13 +63,13 @@ type GroupMaxSortRes struct {
|
||||
// GroupStatusReq 更新状态
|
||||
type GroupStatusReq struct {
|
||||
entity.SysCronGroup
|
||||
g.Meta `path:"/cron_group/status" method:"post" tags:"定时任务分组" summary:"更新定时任务分组状态"`
|
||||
g.Meta `path:"/cronGroup/status" method:"post" tags:"定时任务分组" summary:"更新定时任务分组状态"`
|
||||
}
|
||||
type GroupStatusRes struct{}
|
||||
|
||||
// GroupSelectReq 定时任务分组选项
|
||||
type GroupSelectReq struct {
|
||||
g.Meta `path:"/cron_group/select" method:"get" tags:"定时任务分组" summary:"定时任务分组选项"`
|
||||
g.Meta `path:"/cronGroup/select" method:"get" tags:"定时任务分组" summary:"定时任务分组选项"`
|
||||
}
|
||||
|
||||
type GroupSelectRes sysin.DictTypeSelectModel
|
||||
|
50
server/api/backend/loginlog/loginlog.go
Normal file
50
server/api/backend/loginlog/loginlog.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Package loginlog
|
||||
// @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 loginlog
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
)
|
||||
|
||||
// ListReq 查询登录日志列表
|
||||
type ListReq struct {
|
||||
g.Meta `path:"/loginLog/list" method:"get" tags:"登录日志" summary:"获取登录日志列表"`
|
||||
sysin.LoginLogListInp
|
||||
}
|
||||
|
||||
type ListRes struct {
|
||||
form.PageRes
|
||||
List []*sysin.LoginLogListModel `json:"list" dc:"数据列表"`
|
||||
}
|
||||
|
||||
// ExportReq 导出登录日志列表
|
||||
type ExportReq struct {
|
||||
g.Meta `path:"/loginLog/export" method:"get" tags:"登录日志" summary:"导出登录日志列表"`
|
||||
sysin.LoginLogListInp
|
||||
}
|
||||
|
||||
type ExportRes struct{}
|
||||
|
||||
// ViewReq 获取登录日志指定信息
|
||||
type ViewReq struct {
|
||||
g.Meta `path:"/loginLog/view" method:"get" tags:"登录日志" summary:"获取登录日志指定信息"`
|
||||
sysin.LoginLogViewInp
|
||||
}
|
||||
|
||||
type ViewRes struct {
|
||||
*sysin.LoginLogViewModel
|
||||
}
|
||||
|
||||
// DeleteReq 删除登录日志
|
||||
type DeleteReq struct {
|
||||
g.Meta `path:"/loginLog/delete" method:"post" tags:"登录日志" summary:"删除登录日志"`
|
||||
sysin.LoginLogDeleteInp
|
||||
}
|
||||
|
||||
type DeleteRes struct{}
|
@ -106,7 +106,7 @@ type ListRes struct {
|
||||
// ViewReq 获取指定信息
|
||||
type ViewReq struct {
|
||||
g.Meta `path:"/member/view" method:"get" tags:"会员" summary:"获取指定信息"`
|
||||
Id int64 `json:"id" dc:"会员ID"` // v:"required#会员ID不能为空"
|
||||
Id int64 `json:"id" dc:"会员ID"`
|
||||
}
|
||||
type ViewRes struct {
|
||||
*adminin.MemberViewModel
|
||||
|
@ -24,7 +24,8 @@ type OnlineListReq struct {
|
||||
form.PageReq
|
||||
form.RangeDateReq
|
||||
form.StatusReq
|
||||
UserId int64 `json:"userId" description:"用户ID"`
|
||||
UserId int64 `json:"userId" description:"用户ID"`
|
||||
Addr string `json:"addr" description:"登录地址"`
|
||||
}
|
||||
|
||||
type OnlineListRes struct {
|
||||
|
@ -39,25 +39,24 @@ type ViewRes struct {
|
||||
|
||||
// EditReq 修改/新增
|
||||
type EditReq struct {
|
||||
entity.SysProvinces
|
||||
g.Meta `path:"/provinces/edit" method:"post" tags:"省市区" summary:"修改/新增省市区"`
|
||||
sysin.ProvincesEditInp
|
||||
}
|
||||
type EditRes struct{}
|
||||
|
||||
// DeleteReq 删除
|
||||
type DeleteReq struct {
|
||||
Id interface{} `json:"id" v:"required#省市区ID不能为空" dc:"省市区ID"`
|
||||
g.Meta `path:"/provinces/delete" method:"post" tags:"省市区" summary:"删除省市区"`
|
||||
sysin.ProvincesDeleteInp
|
||||
}
|
||||
type DeleteRes struct{}
|
||||
|
||||
// MaxSortReq 最大排序
|
||||
type MaxSortReq struct {
|
||||
Id int64 `json:"id" dc:"省市区ID"`
|
||||
g.Meta `path:"/provinces/max_sort" method:"get" tags:"省市区" summary:"省市区最大排序"`
|
||||
g.Meta `path:"/provinces/maxSort" method:"get" tags:"省市区" summary:"省市区最大排序"`
|
||||
}
|
||||
type MaxSortRes struct {
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
*sysin.ProvincesMaxSortModel
|
||||
}
|
||||
|
||||
// StatusReq 更新状态
|
||||
@ -66,3 +65,31 @@ type StatusReq struct {
|
||||
g.Meta `path:"/provinces/status" method:"post" tags:"省市区" summary:"更新省市区状态"`
|
||||
}
|
||||
type StatusRes struct{}
|
||||
|
||||
// TreeReq 关系树选项列表
|
||||
type TreeReq struct {
|
||||
g.Meta `path:"/provinces/tree" tags:"省市区" method:"get" summary:"省市区关系树选项列表"`
|
||||
}
|
||||
type TreeRes struct {
|
||||
List []map[string]interface{} `json:"list" dc:"数据列表"`
|
||||
}
|
||||
|
||||
// ChildrenListReq 获取省市区下级列表
|
||||
type ChildrenListReq struct {
|
||||
g.Meta `path:"/provinces/childrenList" method:"get" tags:"省市区" summary:"获取省市区下级列表"`
|
||||
sysin.ProvincesChildrenListInp
|
||||
}
|
||||
|
||||
type ChildrenListRes struct {
|
||||
List []*sysin.ProvincesChildrenListModel `json:"list" dc:"数据列表"`
|
||||
form.PageRes
|
||||
}
|
||||
|
||||
// UniqueIdReq 地区ID是否唯一
|
||||
type UniqueIdReq struct {
|
||||
g.Meta `path:"/provinces/uniqueId" method:"get" tags:"省市区" summary:"地区ID是否唯一"`
|
||||
sysin.ProvincesUniqueIdInp
|
||||
}
|
||||
type UniqueIdRes struct {
|
||||
*sysin.ProvincesUniqueIdModel
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ type ListReq struct {
|
||||
}
|
||||
|
||||
type ListRes struct {
|
||||
List []*adminin.RoleListModel `json:"list" description:"数据列表"`
|
||||
List []g.Map `json:"list" description:"数据列表"`
|
||||
form.PageRes
|
||||
}
|
||||
|
||||
|
50
server/api/backend/servelog/servelog.go
Normal file
50
server/api/backend/servelog/servelog.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Package servelog
|
||||
// @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 servelog
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
)
|
||||
|
||||
// ListReq 查询服务日志列表
|
||||
type ListReq struct {
|
||||
g.Meta `path:"/serveLog/list" method:"get" tags:"服务日志" summary:"获取服务日志列表"`
|
||||
sysin.ServeLogListInp
|
||||
}
|
||||
|
||||
type ListRes struct {
|
||||
form.PageRes
|
||||
List []*sysin.ServeLogListModel `json:"list" dc:"数据列表"`
|
||||
}
|
||||
|
||||
// ExportReq 导出服务日志列表
|
||||
type ExportReq struct {
|
||||
g.Meta `path:"/serveLog/export" method:"get" tags:"服务日志" summary:"导出服务日志列表"`
|
||||
sysin.ServeLogListInp
|
||||
}
|
||||
|
||||
type ExportRes struct{}
|
||||
|
||||
// ViewReq 获取服务日志指定信息
|
||||
type ViewReq struct {
|
||||
g.Meta `path:"/serveLog/view" method:"get" tags:"服务日志" summary:"获取服务日志指定信息"`
|
||||
sysin.ServeLogViewInp
|
||||
}
|
||||
|
||||
type ViewRes struct {
|
||||
*sysin.ServeLogViewModel
|
||||
}
|
||||
|
||||
// DeleteReq 删除服务日志
|
||||
type DeleteReq struct {
|
||||
g.Meta `path:"/serveLog/delete" method:"post" tags:"服务日志" summary:"删除服务日志"`
|
||||
sysin.ServeLogDeleteInp
|
||||
}
|
||||
|
||||
type DeleteRes struct{}
|
69
server/api/backend/smslog/smslog.go
Normal file
69
server/api/backend/smslog/smslog.go
Normal file
@ -0,0 +1,69 @@
|
||||
package smslog
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
)
|
||||
|
||||
// ListReq 查询列表
|
||||
type ListReq struct {
|
||||
form.PageReq
|
||||
form.RangeDateReq
|
||||
form.StatusReq
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
g.Meta `path:"/smsLog/list" method:"get" tags:"短信记录" summary:"获取短信记录列表"`
|
||||
}
|
||||
|
||||
type ListRes struct {
|
||||
List []*sysin.SmsLogListModel `json:"list" dc:"数据列表"`
|
||||
form.PageRes
|
||||
}
|
||||
|
||||
// ViewReq 获取指定信息
|
||||
type ViewReq struct {
|
||||
Id int64 `json:"id" v:"required#短信记录ID不能为空" dc:"短信记录ID"`
|
||||
g.Meta `path:"/smsLog/view" method:"get" tags:"短信记录" summary:"获取指定信息"`
|
||||
}
|
||||
type ViewRes struct {
|
||||
*sysin.SmsLogViewModel
|
||||
}
|
||||
|
||||
// EditReq 修改/新增数据
|
||||
type EditReq struct {
|
||||
entity.SysSmsLog
|
||||
g.Meta `path:"/smsLog/edit" method:"post" tags:"短信记录" summary:"修改/新增短信记录"`
|
||||
}
|
||||
type EditRes struct{}
|
||||
|
||||
// DeleteReq 删除
|
||||
type DeleteReq struct {
|
||||
Id interface{} `json:"id" v:"required#短信记录ID不能为空" dc:"短信记录ID"`
|
||||
g.Meta `path:"/smsLog/delete" method:"post" tags:"短信记录" summary:"删除短信记录"`
|
||||
}
|
||||
type DeleteRes struct{}
|
||||
|
||||
// MaxSortReq 最大排序
|
||||
type MaxSortReq struct {
|
||||
Id int64 `json:"id" dc:"短信记录ID"`
|
||||
g.Meta `path:"/smsLog/maxSort" method:"get" tags:"短信记录" summary:"短信记录最大排序"`
|
||||
}
|
||||
type MaxSortRes struct {
|
||||
Sort int `json:"sort" dc:"排序"`
|
||||
}
|
||||
|
||||
// StatusReq 更新状态
|
||||
type StatusReq struct {
|
||||
entity.SysSmsLog
|
||||
g.Meta `path:"/smsLog/status" method:"post" tags:"短信记录" summary:"更新短信记录状态"`
|
||||
}
|
||||
type StatusRes struct{}
|
||||
|
||||
// SendTestReq 更新状态
|
||||
type SendTestReq struct {
|
||||
entity.SysSmsLog
|
||||
g.Meta `path:"/smsLog/sendTest" method:"post" tags:"短信记录" summary:"发送测试短信"`
|
||||
}
|
||||
type SendTestRes struct{}
|
@ -4,6 +4,10 @@ go 1.15
|
||||
|
||||
require (
|
||||
github.com/Shopify/sarama v1.34.1
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2
|
||||
github.com/alibabacloud-go/dysmsapi-20170525/v3 v3.0.5
|
||||
github.com/alibabacloud-go/tea v1.1.20
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.1
|
||||
github.com/apache/rocketmq-client-go/v2 v2.1.0
|
||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
|
||||
github.com/bufanyun/pool v0.2.1
|
||||
@ -13,7 +17,7 @@ require (
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.0-beta2
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.0
|
||||
github.com/gogf/gf/v2 v2.3.0
|
||||
github.com/gogf/gf/v2 v2.3.1
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/gomodule/redigo v1.8.8
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
|
@ -47,6 +47,35 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 h1:iC9YFYKDGEy3n/FtqJnOkZsene9olVspKmkX5A2YBEo=
|
||||
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2 h1:2kR1YkvQloHUstmPcG0Sjk24zTKbza7izzJfJNwBFSs=
|
||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2/go.mod h1:5JHVmnHvGzR2wNdgaW1zDLQG8kOC4Uec8ubkMogW7OQ=
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 h1:NqugFkGxx1TXSh/pBcU00Y6bljgDPaFdh5MUSeJ7e50=
|
||||
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
|
||||
github.com/alibabacloud-go/dysmsapi-20170525/v3 v3.0.5 h1:/c+eQK0o7Lf8EIZ0ovB0cU+L82rVu1r3v91icUYnsdM=
|
||||
github.com/alibabacloud-go/dysmsapi-20170525/v3 v3.0.5/go.mod h1:CT6UkI74Or2t3NSDgGyY6hkKid3fW7VvN4l+mda+HSw=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=
|
||||
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
|
||||
github.com/alibabacloud-go/openapi-util v0.0.11/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY=
|
||||
github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
|
||||
github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
|
||||
github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
|
||||
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.1.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea v1.1.20 h1:wFK4xEbvGYMtzTyHhIju9D7ecWxvSUdoLO6y4vDLFik=
|
||||
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1 h1:iWQeRzRheqCMuiF3+XkfybB3kTgUXkXX+JMrqfLeB2I=
|
||||
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.0/go.mod h1:U5MTY10WwlquGPS34DOeomUGBB0gXbLueiq5Trwu0C4=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.1 h1:K6kwgo+UiYx+/kr6CO0PN5ACZDzE3nnn9d77215AkTs=
|
||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.1/go.mod h1:U5MTY10WwlquGPS34DOeomUGBB0gXbLueiq5Trwu0C4=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.2 h1:oLxa7JUXm2EDFzMg+7oRsYc+kutgCVwm+bZlhhmvW5M=
|
||||
github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
|
||||
github.com/aliyun/credentials-go v1.1.2 h1:qU1vwGIBb3UJ8BwunHDRFtAhS6jnQLnde/yk0+Ih2GY=
|
||||
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
|
||||
github.com/apache/rocketmq-client-go/v2 v2.1.0 h1:3eABKfxc1WmS2lLTTbKMe1gZfZV6u1Sx9orFnOfABV0=
|
||||
github.com/apache/rocketmq-client-go/v2 v2.1.0/go.mod h1:oEZKFDvS7sz/RWU0839+dQBupazyBV7WX5cP6nrio0Q=
|
||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
|
||||
@ -131,8 +160,8 @@ github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.0-beta2/go.mod h1:z+/0qiOwMroAn
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.0 h1:r2q8MLwF6yUIEm6Hhwsfo/ixaJTKluTXSjU8rSeXo3c=
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.0/go.mod h1:V9o2BF9ovJnaZhHImHAanqUgjX4kI51lgU45u5rPqvw=
|
||||
github.com/gogf/gf/v2 v2.0.0/go.mod h1:apktt6TleWtCIwpz63vBqUnw8MX8gWKoZyxgDpXFtgM=
|
||||
github.com/gogf/gf/v2 v2.3.0 h1:Uz4z6tMqnpH9azLFrfBX1R1k/73d7QPC2E4Ab8L3y4g=
|
||||
github.com/gogf/gf/v2 v2.3.0/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
|
||||
github.com/gogf/gf/v2 v2.3.1 h1:uptCJK47N6KSRwTBnFAqBWYnYa/OXBkZ0OlhO9CK7bQ=
|
||||
github.com/gogf/gf/v2 v2.3.1/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
@ -200,8 +229,9 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
@ -288,6 +318,7 @@ github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4Pfo
|
||||
github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
@ -353,12 +384,15 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zpk/UcpNGnfJt2y/3lRWASHNTUET8owPYCgYI=
|
||||
github.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0=
|
||||
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@ -373,6 +407,8 @@ github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
||||
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
||||
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 h1:rQ229MBgvW68s1/g6f1/63TgYwYxfF4E+bi/KC19P8g=
|
||||
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
|
||||
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
|
||||
@ -391,6 +427,7 @@ github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Q
|
||||
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
@ -419,6 +456,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
@ -549,6 +588,7 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -623,6 +663,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
@ -719,10 +760,13 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/ini.v1 v1.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
|
||||
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@ -730,6 +774,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
@ -44,6 +44,7 @@ var (
|
||||
group.Middleware(
|
||||
service.Middleware().Ctx, //必须第一个加载
|
||||
service.Middleware().CORS,
|
||||
service.Middleware().Blacklist,
|
||||
service.Middleware().DemoLimit,
|
||||
service.Middleware().ResponseHandler,
|
||||
)
|
||||
|
@ -8,6 +8,9 @@ package consts
|
||||
|
||||
import "github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
// RequestEncryptKey 请求加密密钥用于敏感数据加密,16位字符,前后端需保持一致。安全起见请修改此值
|
||||
var RequestEncryptKey = []byte("f080a463654b2279")
|
||||
|
||||
// 配置数据类型
|
||||
const (
|
||||
ConfigTypeString = "string"
|
||||
|
@ -8,5 +8,6 @@ package consts
|
||||
|
||||
// ContextKey 上下文
|
||||
const (
|
||||
ContextKey = "HotGoContext"
|
||||
ContextKey = "HotGoContext" // http上下文变量名称
|
||||
ContextKeyCronArgs = "args" // 定时任务参数上下文变量名称
|
||||
)
|
||||
|
@ -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 // 多次策略
|
||||
)
|
||||
|
@ -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` // 服务日志
|
||||
)
|
||||
|
24
server/internal/consts/sms.go
Normal file
24
server/internal/consts/sms.go
Normal 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 // 已使用
|
||||
)
|
@ -8,5 +8,5 @@ package consts
|
||||
|
||||
// VersionApp HotGo版本
|
||||
const (
|
||||
VersionApp = "2.1.1"
|
||||
VersionApp = "2.1.2"
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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++
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
37
server/internal/controller/backend/common/sms.go
Normal file
37
server/internal/controller/backend/common/sms.go
Normal 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
|
||||
}
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
104
server/internal/controller/backend/sys/login_log.go
Normal file
104
server/internal/controller/backend/sys/login_log.go
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
102
server/internal/controller/backend/sys/serve_log.go
Normal file
102
server/internal/controller/backend/sys/serve_log.go
Normal 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
|
||||
}
|
113
server/internal/controller/backend/sys/sms_log.go
Normal file
113
server/internal/controller/backend/sys/sms_log.go
Normal 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
|
||||
}
|
@ -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 删除任务
|
||||
|
@ -18,6 +18,10 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cronList = append(cronList, Monitor)
|
||||
}
|
||||
|
||||
// Monitor 监控
|
||||
var Monitor = &cMonitor{name: "monitor"}
|
||||
|
||||
|
@ -12,6 +12,10 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cronList = append(cronList, Test)
|
||||
}
|
||||
|
||||
// Test 测试任务
|
||||
var Test = &cTest{name: "test"}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
}
|
@ -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",
|
||||
|
91
server/internal/dao/internal/sys_login_log.go
Normal file
91
server/internal/dao/internal/sys_login_log.go
Normal 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)
|
||||
}
|
@ -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.
|
||||
|
91
server/internal/dao/internal/sys_serve_log.go
Normal file
91
server/internal/dao/internal/sys_serve_log.go
Normal 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)
|
||||
}
|
89
server/internal/dao/internal/sys_sms_log.go
Normal file
89
server/internal/dao/internal/sys_sms_log.go
Normal 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)
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}
|
||||
)
|
||||
|
@ -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)
|
||||
|
27
server/internal/dao/sys_serve_log.go
Normal file
27
server/internal/dao/sys_serve_log.go
Normal 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.
|
43
server/internal/dao/sys_sms_log.go
Normal file
43
server/internal/dao/sys_sms_log.go
Normal 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
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -18,4 +18,6 @@ var (
|
||||
SysType = runtime.GOOS
|
||||
// MonitorData 监控数据
|
||||
MonitorData model.MonitorData
|
||||
// Blacklists 黑名单列表
|
||||
Blacklists map[string]struct{}
|
||||
)
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
|
||||
|
@ -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()
|
||||
})
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
18
server/internal/library/queue/push.go
Normal file
18
server/internal/library/queue/push.go
Normal 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
|
||||
}
|
@ -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) {
|
||||
|
@ -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 注册并启动生产者接口实现
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
112
server/internal/library/sms/aliyun/handle.go
Normal file
112
server/internal/library/sms/aliyun/handle.go
Normal 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
|
||||
}
|
1
server/internal/library/sms/aliyun/init.go
Normal file
1
server/internal/library/sms/aliyun/init.go
Normal file
@ -0,0 +1 @@
|
||||
package aliyun
|
1
server/internal/library/sms/aliyun/model.go
Normal file
1
server/internal/library/sms/aliyun/model.go
Normal file
@ -0,0 +1 @@
|
||||
package aliyun
|
2
server/internal/library/sms/sms.go
Normal file
2
server/internal/library/sms/sms.go
Normal file
@ -0,0 +1,2 @@
|
||||
package sms
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
"hotgo/internal/service"
|
||||
)
|
||||
|
||||
// GlobalLog 全局日志
|
||||
// GlobalLog 访问日志
|
||||
func (s *sHook) GlobalLog(r *ghttp.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
|
@ -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{}{}, // 预览代码
|
||||
},
|
||||
}
|
||||
}
|
||||
|
23
server/internal/logic/middleware/limit_blacklist.go
Normal file
23
server/internal/logic/middleware/limit_blacklist.go
Normal 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()
|
||||
}
|
@ -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()
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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 == "" {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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("数据不存在或已删除!")
|
||||
}
|
||||
|
||||
|
@ -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{
|
||||
|
190
server/internal/logic/sys/login_log.go
Normal file
190
server/internal/logic/sys/login_log.go
Normal 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
|
||||
}
|
@ -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
|
||||
}
|
||||
|
148
server/internal/logic/sys/serve_log.go
Normal file
148
server/internal/logic/sys/serve_log.go
Normal 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
|
||||
}
|
343
server/internal/logic/sys/sms_log.go
Normal file
343
server/internal/logic/sys/sms_log.go
Normal 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
|
||||
}
|
@ -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"`
|
||||
|
@ -20,6 +20,8 @@ type AdminDept struct {
|
||||
Leader interface{} // 负责人
|
||||
Phone interface{} // 联系电话
|
||||
Email interface{} // 邮箱
|
||||
Level interface{} // 关系树等级
|
||||
Tree interface{} // 关系树
|
||||
Sort interface{} // 排序
|
||||
Status interface{} // 部门状态
|
||||
CreatedAt *gtime.Time // 创建时间
|
||||
|
@ -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 // 修改时间
|
||||
|
26
server/internal/model/do/sys_login_log.go
Normal file
26
server/internal/model/do/sys_login_log.go
Normal 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 // 修改时间
|
||||
}
|
@ -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 // 更新时间
|
||||
}
|
||||
|
26
server/internal/model/do/sys_serve_log.go
Normal file
26
server/internal/model/do/sys_serve_log.go
Normal 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 // 修改时间
|
||||
}
|
24
server/internal/model/do/sys_sms_log.go
Normal file
24
server/internal/model/do/sys_sms_log.go
Normal 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 // 更新时间
|
||||
}
|
@ -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:"创建时间"`
|
||||
|
@ -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:"修改时间"`
|
||||
|
24
server/internal/model/entity/sys_login_log.go
Normal file
24
server/internal/model/entity/sys_login_log.go
Normal 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:"修改时间"`
|
||||
}
|
@ -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:"更新时间"`
|
||||
}
|
||||
|
24
server/internal/model/entity/sys_serve_log.go
Normal file
24
server/internal/model/entity/sys_serve_log.go
Normal 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:"修改时间"`
|
||||
}
|
22
server/internal/model/entity/sys_sms_log.go
Normal file
22
server/internal/model/entity/sys_sms_log.go
Normal 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:"更新时间"`
|
||||
}
|
@ -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
|
||||
|
@ -59,3 +59,9 @@ type CronStatusInp struct {
|
||||
entity.SysCron
|
||||
}
|
||||
type CronStatusModel struct{}
|
||||
|
||||
// OnlineExecInp 在线执行
|
||||
type OnlineExecInp struct {
|
||||
entity.SysCron
|
||||
}
|
||||
type OnlineExecModel struct{}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user