mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-01-23 02:40:23 +08:00
fix 修复websocket在某些情况下不重连问题
fix 修复登录日志查看权限 feat 访问日志增加接口信息显示 perf 为所有orm的Insert操作增加OmitEmptyData选项
This commit is contained in:
parent
269b2f9e43
commit
dc20a86b33
@ -153,7 +153,7 @@ func (s *sSysTable) Edit(ctx context.Context, in *sysin.TableEditInp) (err error
|
||||
|
||||
// 新增
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).Insert(); err != nil {
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增表格失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ func (s *sSysTreeTable) Edit(ctx context.Context, in *sysin.TableEditInp) (err e
|
||||
}
|
||||
} else {
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).Insert(); err != nil {
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增表格失败,请稍后重试!")
|
||||
return err
|
||||
}
|
||||
|
@ -30,16 +30,6 @@ type ExportReq struct {
|
||||
|
||||
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:"删除登录日志"`
|
||||
|
@ -5,9 +5,56 @@
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
package consts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"hotgo/internal/library/dict"
|
||||
"hotgo/internal/model"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dict.RegisterEnums("HTTPMethod", "HTTP请求方式选项", HTTPMethodOptions)
|
||||
dict.RegisterEnums("HTTPHandlerTime", "HTTP处理耗时选项", HTTPHandlerTimeOptions)
|
||||
dict.RegisterEnums("HTTPApiCode", "HTTP接口状态码选项", HTTPApiCodeOptions)
|
||||
}
|
||||
|
||||
const (
|
||||
HTTPContentTypeXml = "text/xml"
|
||||
HTTPContentTypeHtml = "text/html"
|
||||
HTTPContentTypeStream = "text/event-stream"
|
||||
HTTPContentTypeJson = "application/json"
|
||||
)
|
||||
|
||||
// HTTPMethodOptions HTTP请求方式选项
|
||||
var HTTPMethodOptions = []*model.Option{
|
||||
dict.GenSuccessOption(http.MethodGet, "GET"),
|
||||
dict.GenInfoOption(http.MethodPost, "POST"),
|
||||
dict.GenSuccessOption(http.MethodPut, "PUT"),
|
||||
dict.GenInfoOption(http.MethodDelete, "DELETE"),
|
||||
}
|
||||
|
||||
const (
|
||||
HTTPHandlerTime50 = "< 50"
|
||||
HTTPHandlerTime200 = "< 200"
|
||||
HTTPHandlerTime200To500 = "BETWEEN 200 AND 500"
|
||||
HTTPHandlerTime500To1000 = "BETWEEN 500 AND 1000"
|
||||
HTTPHandlerTime1000To10000 = "BETWEEN 1000 AND 10000"
|
||||
HTTPHandlerTime10000UP = "> 10000"
|
||||
)
|
||||
|
||||
// HTTPHandlerTimeOptions HTTP处理耗时选项
|
||||
var HTTPHandlerTimeOptions = []*model.Option{
|
||||
dict.GenSuccessOption(HTTPHandlerTime50, "50ms以内"),
|
||||
dict.GenInfoOption(HTTPHandlerTime200, "200ms以内"),
|
||||
dict.GenSuccessOption(HTTPHandlerTime200To500, "200~500ms"),
|
||||
dict.GenSuccessOption(HTTPHandlerTime500To1000, "500~1000ms"),
|
||||
dict.GenInfoOption(HTTPHandlerTime1000To10000, "1000~10000ms"),
|
||||
dict.GenInfoOption(HTTPHandlerTime10000UP, "10000ms以上"),
|
||||
}
|
||||
|
||||
// HTTPApiCodeOptions HTTP接口状态码选项
|
||||
var HTTPApiCodeOptions = []*model.Option{
|
||||
dict.GenSuccessOption(gcode.CodeOK.Code(), fmt.Sprintf("%v %v", gcode.CodeOK.Code(), "成功")),
|
||||
dict.GenWarningOption(gcode.CodeNil.Code(), fmt.Sprintf("%v %v", gcode.CodeNil.Code(), "失败")),
|
||||
}
|
||||
|
@ -38,18 +38,6 @@ func (c *cLoginLog) Export(ctx context.Context, req *loginlog.ExportReq) (res *l
|
||||
return
|
||||
}
|
||||
|
||||
// View 获取指定登录日志信息
|
||||
func (c *cLoginLog) View(ctx context.Context, req *loginlog.ViewReq) (res *loginlog.ViewRes, err error) {
|
||||
data, err := service.SysLoginLog().View(ctx, &req.LoginLogViewInp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res = new(loginlog.ViewRes)
|
||||
res.LoginLogViewModel = data
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除登录日志
|
||||
func (c *cLoginLog) Delete(ctx context.Context, req *loginlog.DeleteReq) (res *loginlog.DeleteRes, err error) {
|
||||
err = service.SysLoginLog().Delete(ctx, &req.LoginLogDeleteInp)
|
||||
|
125
server/internal/global/httproutes.go
Normal file
125
server/internal/global/httproutes.go
Normal file
@ -0,0 +1,125 @@
|
||||
// Package global
|
||||
// @Link https://github.com/bufanyun/hotgo
|
||||
// @Copyright Copyright (c) 2024 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
package global
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/util/gmeta"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// HTTPRouter http路由
|
||||
type HTTPRouter struct {
|
||||
ghttp.RouterItem
|
||||
Tags string `json:"tags" dc:"接口所属的标签,用于接口分类"`
|
||||
Summary string `json:"summary" dc:"接口/参数概要描述"`
|
||||
Description string `json:"description" dc:"接口/参数详细描述"`
|
||||
}
|
||||
|
||||
var (
|
||||
httpRoutes map[string]*HTTPRouter
|
||||
routeMutex sync.Mutex
|
||||
shortTypeMapForTag = map[string]string{
|
||||
gtag.SummaryShort: gtag.Summary,
|
||||
gtag.SummaryShort2: gtag.Summary,
|
||||
gtag.DescriptionShort: gtag.Description,
|
||||
gtag.DescriptionShort2: gtag.Description,
|
||||
}
|
||||
)
|
||||
|
||||
// GetRequestRoute 获取当前请求路由属性
|
||||
func GetRequestRoute(r *ghttp.Request) *HTTPRouter {
|
||||
key := GenFilterRequestKey(r)
|
||||
routes := LoadHTTPRoutes(r)
|
||||
router, ok := routes[key]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return router
|
||||
}
|
||||
|
||||
// GenFilterRequestKey 根据请求生成唯一key
|
||||
func GenFilterRequestKey(r *ghttp.Request) string {
|
||||
return GenRouteKey(r.Method, r.Request.URL.Path)
|
||||
}
|
||||
|
||||
// GenFilterRouteKey 根据路由生成唯一key
|
||||
func GenFilterRouteKey(r *ghttp.Router) string {
|
||||
return GenRouteKey(r.Method, r.Uri)
|
||||
}
|
||||
|
||||
// GenRouteKey 生成唯一key
|
||||
func GenRouteKey(method, path string) string {
|
||||
return strings.ToUpper(method) + " " + path
|
||||
}
|
||||
|
||||
func LoadHTTPRoutes(r *ghttp.Request) map[string]*HTTPRouter {
|
||||
if httpRoutes == nil {
|
||||
routeMutex.Lock()
|
||||
defer routeMutex.Unlock()
|
||||
|
||||
if httpRoutes != nil {
|
||||
return httpRoutes
|
||||
}
|
||||
|
||||
httpRoutes = make(map[string]*HTTPRouter, len(r.Server.GetRoutes()))
|
||||
for _, v := range r.Server.GetRoutes() {
|
||||
key := GenFilterRouteKey(v.Handler.Router)
|
||||
if _, ok := httpRoutes[key]; !ok {
|
||||
router := new(HTTPRouter)
|
||||
router.RouterItem = v
|
||||
httpRoutes[key] = setRouterMeta(router)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return httpRoutes
|
||||
}
|
||||
|
||||
func setRouterMeta(router *HTTPRouter) *HTTPRouter {
|
||||
if !router.RouterItem.Handler.Info.IsStrictRoute {
|
||||
return router
|
||||
}
|
||||
|
||||
var reflectValue = reflect.ValueOf(router.Handler.Info.Value.Interface())
|
||||
for reflectValue.Kind() == reflect.Ptr {
|
||||
reflectValue = reflectValue.Elem()
|
||||
}
|
||||
|
||||
if reflectValue.Kind() != reflect.Func {
|
||||
return router
|
||||
}
|
||||
|
||||
var reflectType = reflect.TypeOf(router.Handler.Info.Value.Interface())
|
||||
if reflectType.NumIn() != 2 || reflectType.NumOut() != 2 {
|
||||
return router
|
||||
}
|
||||
|
||||
var inputObject reflect.Value
|
||||
if reflectType.In(1).Kind() == reflect.Ptr {
|
||||
inputObject = reflect.New(reflectType.In(1).Elem()).Elem()
|
||||
} else {
|
||||
inputObject = reflect.New(reflectType.In(1)).Elem()
|
||||
}
|
||||
|
||||
inputMetaMap := fillMapWithShortTags(gmeta.Data(inputObject.Interface()))
|
||||
router.Tags = inputMetaMap["tags"]
|
||||
router.Summary = inputMetaMap[gtag.Summary]
|
||||
router.Description = inputMetaMap[gtag.Description]
|
||||
return router
|
||||
}
|
||||
|
||||
func fillMapWithShortTags(m map[string]string) map[string]string {
|
||||
for k, v := range shortTypeMapForTag {
|
||||
if m[v] == "" && m[k] != "" {
|
||||
m[v] = m[k]
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
@ -65,7 +65,7 @@ func Install(m Module) (err error) {
|
||||
_, _ = GetModel(m.Ctx()).Where("id", record.Id).Delete()
|
||||
}
|
||||
|
||||
if _, err = GetModel(m.Ctx()).Data(data).Insert(); err != nil {
|
||||
if _, err = GetModel(m.Ctx()).Data(data).OmitEmptyData().Insert(); err != nil {
|
||||
return err
|
||||
}
|
||||
return m.Install(ctx)
|
||||
|
@ -151,7 +151,7 @@ func (a *adapter) SavePolicy(model model.Model) (err error) {
|
||||
}
|
||||
|
||||
if count := len(policyRules); count > 0 {
|
||||
if _, err = a.model().Insert(policyRules); err != nil {
|
||||
if _, err = a.model().OmitEmptyData().Insert(policyRules); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -160,7 +160,7 @@ func (a *adapter) SavePolicy(model model.Model) (err error) {
|
||||
|
||||
// AddPolicy adds a policy rule to the storage.
|
||||
func (a *adapter) AddPolicy(sec string, ptype string, rule []string) (err error) {
|
||||
_, err = a.model().Insert(a.buildPolicyRule(ptype, rule))
|
||||
_, err = a.model().OmitEmptyData().Insert(a.buildPolicyRule(ptype, rule))
|
||||
return
|
||||
}
|
||||
|
||||
@ -176,7 +176,7 @@ func (a *adapter) AddPolicies(sec string, ptype string, rules [][]string) (err e
|
||||
policyRules = append(policyRules, a.buildPolicyRule(ptype, rule))
|
||||
}
|
||||
|
||||
_, err = a.model().Insert(policyRules)
|
||||
_, err = a.model().OmitEmptyData().Insert(policyRules)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,7 @@ const (
|
||||
LogicWhereComments = "\n\t// 查询%s\n"
|
||||
LogicWhereNoSupport = "\t// TODO 暂不支持生成[ %s ]查询方式,请自行补充此处代码!"
|
||||
LogicEditUpdate = "\tif _, err = s.Model(ctx%s).\n\t\t\tFields(%sin.%sUpdateFields{}).\n\t\t\tWherePri(in.%s).Data(in).Update(); err != nil {\n\t\t\terr = gerror.Wrap(err, \"修改%s失败,请稍后重试!\")\n\t\t}\n\t\treturn"
|
||||
LogicEditInsert = "\tif _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).\n\t\tFields(%sin.%sInsertFields{}).\n\t\tData(in).Insert(); err != nil {\n\t\terr = gerror.Wrap(err, \"新增%s失败,请稍后重试!\")\n\t}"
|
||||
LogicEditInsert = "\tif _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).\n\t\tFields(%sin.%sInsertFields{}).\n\t\tData(in).OmitEmptyData().Insert(); err != nil {\n\t\terr = gerror.Wrap(err, \"新增%s失败,请稍后重试!\")\n\t}"
|
||||
LogicEditUnique = "\t// 验证'%s'唯一\n\tif err = hgorm.IsUnique(ctx, &dao.%s, g.Map{dao.%s.Columns().%s: in.%s}, \"%s已存在\", in.Id); err != nil {\n\t\treturn\n\t}\n"
|
||||
LogicSwitchUpdate = "g.Map{\n\t\tin.Key: in.Value,\n%s}"
|
||||
LogicStatusUpdate = "g.Map{\n\t\tdao.%s.Columns().Status: in.Status,\n%s}"
|
||||
|
@ -50,7 +50,7 @@ func TestSaveTenant_User(t *testing.T) {
|
||||
cols.Status: consts.PayStatusWait,
|
||||
}
|
||||
|
||||
_, err := dao.AddonHgexampleTenantOrder.Ctx(ctx).Data(data).Hook(hook.SaveTenant).Insert()
|
||||
_, err := dao.AddonHgexampleTenantOrder.Ctx(ctx).Data(data).Hook(hook.SaveTenant).OmitEmptyData().Insert()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ func write(ctx context.Context, meta *FileMeta, fullPath string) (models *entity
|
||||
Status: consts.StatusEnabled,
|
||||
}
|
||||
|
||||
id, err := GetModel(ctx).Data(models).InsertAndGetId()
|
||||
id, err := GetModel(ctx).Data(models).OmitEmptyData().InsertAndGetId()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ func (s *sAdminCash) Apply(ctx context.Context, in *adminin.CashApplyInp) (err e
|
||||
"status": consts.CashStatusWait,
|
||||
"msg": "",
|
||||
"ip": location.GetClientIp(ghttp.RequestFromCtx(ctx)),
|
||||
}).InsertAndGetId()
|
||||
}).OmitEmptyData().InsertAndGetId()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ func (s *sAdminCreditsLog) SaveBalance(ctx context.Context, in *adminin.CreditsL
|
||||
data.Ip = in.Ip
|
||||
data.MapId = in.MapId
|
||||
|
||||
_, err = dao.AdminCreditsLog.Ctx(ctx).Data(data).Insert()
|
||||
_, err = dao.AdminCreditsLog.Ctx(ctx).Data(data).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ func (s *sAdminCreditsLog) SaveIntegral(ctx context.Context, in *adminin.Credits
|
||||
data.Ip = in.Ip
|
||||
data.MapId = in.MapId
|
||||
|
||||
_, err = dao.AdminCreditsLog.Ctx(ctx).Data(data).Insert()
|
||||
_, err = dao.AdminCreditsLog.Ctx(ctx).Data(data).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ func (s *sAdminDept) Edit(ctx context.Context, in *adminin.DeptEditInp) (err err
|
||||
}
|
||||
|
||||
// 新增
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).Insert(); err != nil {
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增部门管理失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
|
@ -564,7 +564,7 @@ func (s *sAdminMember) Edit(ctx context.Context, in *adminin.MemberEditInp) (err
|
||||
}
|
||||
|
||||
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
id, err := dao.AdminMember.Ctx(ctx).Data(data).InsertAndGetId()
|
||||
id, err := dao.AdminMember.Ctx(ctx).Data(data).OmitEmptyData().InsertAndGetId()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "新增用户失败,请稍后重试!")
|
||||
return
|
||||
|
@ -31,7 +31,7 @@ func (s *sAdminMemberPost) UpdatePostIds(ctx context.Context, memberId int64, po
|
||||
}
|
||||
|
||||
for i := 0; i < len(postIds); i++ {
|
||||
_, err = dao.AdminMemberPost.Ctx(ctx).Insert(entity.AdminMemberPost{
|
||||
_, err = dao.AdminMemberPost.Ctx(ctx).OmitEmptyData().Insert(entity.AdminMemberPost{
|
||||
MemberId: memberId,
|
||||
PostId: postIds[i],
|
||||
})
|
||||
|
@ -110,7 +110,7 @@ func (s *sAdminMenu) Edit(ctx context.Context, in *adminin.MenuEditInp) (err err
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err = dao.AdminMenu.Ctx(ctx).Data(in).Insert(); err != nil {
|
||||
if _, err = dao.AdminMenu.Ctx(ctx).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增菜单失败!")
|
||||
return err
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ func (s *sAdminNotice) Edit(ctx context.Context, in *adminin.NoticeEditInp) (err
|
||||
// 新增
|
||||
in.CreatedBy = member.Id
|
||||
in.CreatedAt = gtime.Now()
|
||||
in.Id, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).InsertAndGetId()
|
||||
in.Id, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).OmitEmptyData().InsertAndGetId()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
@ -426,7 +426,7 @@ func (s *sAdminNotice) updatedReadClicks(ctx context.Context, noticeId, memberId
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
_, err = dao.AdminNoticeRead.Ctx(ctx).Data(entity.AdminNoticeRead{NoticeId: noticeId, MemberId: memberId}).Insert()
|
||||
_, err = dao.AdminNoticeRead.Ctx(ctx).Data(entity.AdminNoticeRead{NoticeId: noticeId, MemberId: memberId}).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
_, err = dao.AdminNoticeRead.Ctx(ctx).Where(dao.AdminNoticeRead.Columns().Id, models.Id).Increment(dao.AdminNoticeRead.Columns().Clicks, 1)
|
||||
|
@ -224,7 +224,7 @@ func (s *sAdminOrder) Create(ctx context.Context, in *adminin.OrderCreateInp) (r
|
||||
Money: in.Money,
|
||||
Remark: in.Remark,
|
||||
Status: consts.OrderStatusNotPay,
|
||||
}).Insert()
|
||||
}).OmitEmptyData().Insert()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -348,7 +348,7 @@ func (s *sAdminOrder) Edit(ctx context.Context, in *adminin.OrderEditInp) (err e
|
||||
FieldsEx(
|
||||
dao.AdminOrder.Columns().Id,
|
||||
).
|
||||
Data(in).Insert()
|
||||
Data(in).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ func (s *sAdminPost) Edit(ctx context.Context, in *adminin.PostEditInp) (err err
|
||||
}
|
||||
|
||||
// 新增
|
||||
_, err = dao.AdminPost.Ctx(ctx).Data(in).Insert()
|
||||
_, err = dao.AdminPost.Ctx(ctx).Data(in).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ func (s *sAdminRole) UpdatePermissions(ctx context.Context, in *adminin.UpdatePe
|
||||
})
|
||||
}
|
||||
|
||||
if _, err = dao.AdminRoleMenu.Ctx(ctx).Data(list).Insert(); err != nil {
|
||||
if _, err = dao.AdminRoleMenu.Ctx(ctx).Data(list).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
@ -189,7 +189,7 @@ func (s *sAdminRole) Edit(ctx context.Context, in *adminin.RoleEditInp) (err err
|
||||
}
|
||||
|
||||
// 新增
|
||||
if _, err = dao.AdminRole.Ctx(ctx).Fields(adminin.RoleInsertFields{}).Data(in).Insert(); err != nil {
|
||||
if _, err = dao.AdminRole.Ctx(ctx).Fields(adminin.RoleInsertFields{}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (s *sAdminSite) Register(ctx context.Context, in *adminin.RegisterInp) (err
|
||||
|
||||
// 提交注册信息
|
||||
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
id, err := dao.AdminMember.Ctx(ctx).Data(data).InsertAndGetId()
|
||||
id, err := dao.AdminMember.Ctx(ctx).Data(data).OmitEmptyData().InsertAndGetId()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
|
@ -27,15 +27,12 @@ import (
|
||||
"hotgo/utility/validate"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type sMiddleware struct {
|
||||
LoginUrl string // 登录路由地址
|
||||
DemoWhiteList g.Map // 演示模式放行的路由白名单
|
||||
NotRecordRequest g.Map // 不记录请求数据的路由(当前请求数据过大时会影响响应效率,可以将路径放到该选项中改善)
|
||||
FilterRoutes map[string]ghttp.RouterItem // 支持预处理的web路由
|
||||
routeMutex sync.Mutex
|
||||
LoginUrl string // 登录路由地址
|
||||
DemoWhiteList g.Map // 演示模式放行的路由白名单
|
||||
NotRecordRequest g.Map // 不记录请求数据的路由(当前请求数据过大时会影响响应效率,可以将路径放到该选项中改善)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -9,58 +9,17 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/global"
|
||||
"hotgo/internal/library/response"
|
||||
"hotgo/utility/validate"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// GetFilterRoutes 获取支持预处理的web路由
|
||||
func (s *sMiddleware) GetFilterRoutes(r *ghttp.Request) map[string]ghttp.RouterItem {
|
||||
// 首次访问时加载
|
||||
if s.FilterRoutes == nil {
|
||||
s.routeMutex.Lock()
|
||||
defer s.routeMutex.Unlock()
|
||||
|
||||
if s.FilterRoutes != nil {
|
||||
return s.FilterRoutes
|
||||
}
|
||||
|
||||
s.FilterRoutes = make(map[string]ghttp.RouterItem)
|
||||
for _, v := range r.Server.GetRoutes() {
|
||||
// 非规范路由不加载
|
||||
if v.Handler.Info.Type.NumIn() != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := s.GenFilterRouteKey(v.Handler.Router)
|
||||
if _, ok := s.FilterRoutes[key]; !ok {
|
||||
s.FilterRoutes[key] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.FilterRoutes
|
||||
}
|
||||
|
||||
// GenFilterRequestKey 根据请求生成唯一key
|
||||
func (s *sMiddleware) GenFilterRequestKey(r *ghttp.Request) string {
|
||||
return s.GenRouteKey(r.Method, r.Request.URL.Path)
|
||||
}
|
||||
|
||||
// GenFilterRouteKey 根据路由生成唯一key
|
||||
func (s *sMiddleware) GenFilterRouteKey(r *ghttp.Router) string {
|
||||
return s.GenRouteKey(r.Method, r.Uri)
|
||||
}
|
||||
|
||||
// GenRouteKey 生成唯一key
|
||||
func (s *sMiddleware) GenRouteKey(method, path string) string {
|
||||
return method + " " + path
|
||||
}
|
||||
|
||||
// PreFilter 请求输入预处理
|
||||
// api使用gf规范路由并且XxxReq结构体实现了validate.Filter接口即可
|
||||
func (s *sMiddleware) PreFilter(r *ghttp.Request) {
|
||||
router, ok := s.GetFilterRoutes(r)[s.GenFilterRequestKey(r)]
|
||||
if !ok {
|
||||
router := global.GetRequestRoute(r)
|
||||
if router == nil {
|
||||
r.Middleware.Next()
|
||||
return
|
||||
}
|
||||
@ -89,7 +48,7 @@ func (s *sMiddleware) PreFilter(r *ghttp.Request) {
|
||||
}
|
||||
|
||||
// 没有实现预处理
|
||||
if _, ok = inputObject.Interface().(validate.Filter); !ok {
|
||||
if _, ok := inputObject.Interface().(validate.Filter); !ok {
|
||||
r.Middleware.Next()
|
||||
return
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ func (s *sPay) Create(ctx context.Context, in payin.PayCreateInp) (res *payin.Pa
|
||||
}
|
||||
|
||||
// 创建支付记录
|
||||
if _, err = s.Model(ctx).Data(data).Insert(); err != nil {
|
||||
if _, err = s.Model(ctx).Data(data).OmitEmptyData().Insert(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ func (s *sPay) Edit(ctx context.Context, in payin.PayEditInp) (err error) {
|
||||
}
|
||||
|
||||
// 新增
|
||||
_, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).Insert()
|
||||
_, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ func (s *sPayRefund) Refund(ctx context.Context, in *payin.PayRefundInp) (res *p
|
||||
}
|
||||
|
||||
// 创建退款记录
|
||||
if _, err = s.Model(ctx).Data(data).Insert(); err != nil {
|
||||
if _, err = s.Model(ctx).Data(data).OmitEmptyData().Insert(); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
|
@ -60,7 +60,7 @@ func (s *sSysBlacklist) Edit(ctx context.Context, in *sysin.BlacklistEditInp) (e
|
||||
}
|
||||
|
||||
// 新增
|
||||
_, err = dao.SysBlacklist.Ctx(ctx).Data(in).Insert()
|
||||
_, err = dao.SysBlacklist.Ctx(ctx).Data(in).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ func (s *sSysCron) Edit(ctx context.Context, in *sysin.CronEditInp) (err error)
|
||||
}
|
||||
|
||||
// 新增
|
||||
in.SysCron.Id, err = dao.SysCron.Ctx(ctx).Data(in).InsertAndGetId()
|
||||
in.SysCron.Id, err = dao.SysCron.Ctx(ctx).Data(in).OmitEmptyData().InsertAndGetId()
|
||||
if err != nil || in.SysCron.Id < 1 {
|
||||
return
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func (s *sSysCronGroup) Edit(ctx context.Context, in *sysin.CronGroupEditInp) (e
|
||||
}
|
||||
|
||||
// 新增
|
||||
if _, err = dao.SysCronGroup.Ctx(ctx).Fields(sysin.CronGroupInsertFields{}).Data(in).Insert(); err != nil {
|
||||
if _, err = dao.SysCronGroup.Ctx(ctx).Fields(sysin.CronGroupInsertFields{}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
return
|
||||
|
@ -161,7 +161,7 @@ func (s *sSysCurdDemo) Edit(ctx context.Context, in *sysin.CurdDemoEditInp) (err
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
||||
Fields(sysin.CurdDemoInsertFields{}).
|
||||
Data(in).Insert(); err != nil {
|
||||
Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增CURD列表失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
|
@ -60,7 +60,7 @@ func (s *sSysDictData) Edit(ctx context.Context, in *sysin.DictDataEditInp) (err
|
||||
return gerror.Wrap(err, "类型选择无效,请检查")
|
||||
}
|
||||
|
||||
_, err = dao.SysDictData.Ctx(ctx).Fields(sysin.DictDataInsertFields{}).Data(in).Insert()
|
||||
_, err = dao.SysDictData.Ctx(ctx).Fields(sysin.DictDataInsertFields{}).Data(in).OmitEmptyData().Insert()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
|
@ -96,7 +96,7 @@ func (s *sSysDictType) Edit(ctx context.Context, in *sysin.DictTypeEditInp) (err
|
||||
}
|
||||
|
||||
// 新增
|
||||
if _, err = dao.SysDictType.Ctx(ctx).Fields(sysin.DictTypeInsertFields{}).Data(in).Insert(); err != nil {
|
||||
if _, err = dao.SysDictType.Ctx(ctx).Fields(sysin.DictTypeInsertFields{}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
return
|
||||
|
@ -61,7 +61,7 @@ func (s *sSysEmsLog) Edit(ctx context.Context, in *sysin.EmsLogEditInp) (err err
|
||||
}
|
||||
|
||||
// 新增
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Data(in).Insert()
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Data(in).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
@ -190,7 +190,7 @@ func (s *sSysEmsLog) Send(ctx context.Context, in *sysin.SendEmsInp) (err error)
|
||||
data.CreatedAt = gtime.Now()
|
||||
data.UpdatedAt = gtime.Now()
|
||||
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Data(data).Insert()
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Data(data).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ func (s *sSysGenCodes) Edit(ctx context.Context, in *sysin.GenCodesEditInp) (res
|
||||
in.MasterColumns = gjson.New("[]")
|
||||
in.Status = consts.GenCodesStatusWait
|
||||
in.CreatedAt = gtime.Now()
|
||||
id, err := dao.SysGenCodes.Ctx(ctx).Data(in).InsertAndGetId()
|
||||
id, err := dao.SysGenCodes.Ctx(ctx).Data(in).OmitEmptyData().InsertAndGetId()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
|
@ -7,6 +7,8 @@ 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"
|
||||
@ -17,7 +19,9 @@ import (
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/global"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/dict"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/library/hgorm/hook"
|
||||
"hotgo/internal/library/location"
|
||||
@ -40,6 +44,11 @@ func init() {
|
||||
service.RegisterSysLog(NewSysLog())
|
||||
}
|
||||
|
||||
// Model 请求日志Orm模型
|
||||
func (s *sSysLog) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
return handler.Model(dao.SysLog.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
// Export 导出
|
||||
func (s *sSysLog) Export(ctx context.Context, in *sysin.LogListInp) (err error) {
|
||||
// 导出格式
|
||||
@ -96,7 +105,7 @@ func (s *sSysLog) Export(ctx context.Context, in *sysin.LogListInp) (err error)
|
||||
|
||||
// RealWrite 真实写入
|
||||
func (s *sSysLog) RealWrite(ctx context.Context, log entity.SysLog) (err error) {
|
||||
_, err = dao.SysLog.Ctx(ctx).FieldsEx(dao.SysLog.Columns().Id).Data(log).Insert()
|
||||
_, err = dao.SysLog.Ctx(ctx).FieldsEx(dao.SysLog.Columns().Id).Data(log).Unscoped().OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
@ -171,6 +180,10 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
|
||||
}
|
||||
}
|
||||
|
||||
if timestamp == 0 {
|
||||
timestamp = gtime.Timestamp()
|
||||
}
|
||||
|
||||
// 请求头
|
||||
if reqHeadersBytes, _ := gjson.New(request.Header).MarshalJSON(); len(reqHeadersBytes) > 0 {
|
||||
headerData = gjson.New(reqHeadersBytes)
|
||||
@ -213,6 +226,8 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
|
||||
takeUpTime = tt
|
||||
}
|
||||
|
||||
headerData.MustSet("qqq", request.EnterTime.String())
|
||||
|
||||
data = entity.SysLog{
|
||||
AppId: appId,
|
||||
MerchantId: 0,
|
||||
@ -234,13 +249,28 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
|
||||
UserAgent: request.Header.Get("User-Agent"),
|
||||
Status: consts.StatusEnabled,
|
||||
TakeUpTime: takeUpTime,
|
||||
UpdatedAt: gtime.Now(),
|
||||
CreatedAt: request.EnterTime,
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// View 获取指定字典类型信息
|
||||
// View 获取指定请求日志信息
|
||||
func (s *sSysLog) View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.LogViewModel, err error) {
|
||||
if err = dao.SysLog.Ctx(ctx).Handler(handler.FilterAuth).Hook(hook.CityLabel).Where("id", in.Id).Scan(&res); err != nil {
|
||||
mod := s.Model(ctx)
|
||||
|
||||
count, err := service.SysLoginLog().Model(ctx).
|
||||
LeftJoinOnFields(dao.SysLog.Table(), dao.SysLoginLog.Columns().ReqId, "=", dao.SysLog.Columns().ReqId).
|
||||
WherePrefix(dao.SysLog.Table(), dao.SysLog.Columns().Id, in.Id).Count()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
mod = dao.SysLog.Ctx(ctx)
|
||||
}
|
||||
|
||||
if err = mod.Hook(hook.CityLabel).WherePri(in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
@ -249,6 +279,15 @@ func (s *sSysLog) View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.Lo
|
||||
return
|
||||
}
|
||||
|
||||
routes := global.LoadHTTPRoutes(ghttp.RequestFromCtx(ctx))
|
||||
key := global.GenRouteKey(res.Method, res.Url)
|
||||
route, ok := routes[key]
|
||||
if ok {
|
||||
res.Tags = route.Tags
|
||||
res.Summary = route.Summary
|
||||
res.Description = route.Description
|
||||
}
|
||||
|
||||
if simple.IsDemo(ctx) {
|
||||
res.HeaderData = gjson.New(`{
|
||||
"none": [
|
||||
@ -259,15 +298,15 @@ func (s *sSysLog) View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.Lo
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
// Delete 删除请求日志
|
||||
func (s *sSysLog) Delete(ctx context.Context, in *sysin.LogDeleteInp) (err error) {
|
||||
_, err = dao.SysLog.Ctx(ctx).Handler(handler.FilterAuth).Where("id", in.Id).Delete()
|
||||
_, err = s.Model(ctx).WherePri(in.Id).Delete()
|
||||
return
|
||||
}
|
||||
|
||||
// List 列表
|
||||
// List 请求日志列表
|
||||
func (s *sSysLog) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error) {
|
||||
mod := dao.SysLog.Ctx(ctx).Handler(handler.FilterAuth).FieldsEx("get_data", "header_data", "post_data")
|
||||
mod := s.Model(ctx).FieldsEx("get_data", "header_data", "post_data")
|
||||
|
||||
// 访问路径
|
||||
if in.Url != "" {
|
||||
@ -279,6 +318,11 @@ func (s *sSysLog) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin
|
||||
mod = mod.Where("module", in.Module)
|
||||
}
|
||||
|
||||
// 链路ID
|
||||
if in.ReqId != "" {
|
||||
mod = mod.Where("req_id", in.ReqId)
|
||||
}
|
||||
|
||||
// 请求方式
|
||||
if in.Method != "" {
|
||||
mod = mod.Where("method", in.Method)
|
||||
@ -305,8 +349,8 @@ func (s *sSysLog) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin
|
||||
}
|
||||
|
||||
// 请求耗时
|
||||
if in.TakeUpTime > 0 {
|
||||
mod = mod.WhereGTE("take_up_time", in.TakeUpTime)
|
||||
if dict.HasOptionKey(consts.HTTPHandlerTimeOptions, in.TakeUpTime) {
|
||||
mod = mod.Where(fmt.Sprintf("`take_up_time` %v", in.TakeUpTime))
|
||||
}
|
||||
|
||||
totalCount, err = mod.Count()
|
||||
@ -314,35 +358,40 @@ func (s *sSysLog) List(ctx context.Context, in *sysin.LogListInp) (list []*sysin
|
||||
return
|
||||
}
|
||||
|
||||
if err = mod.Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
|
||||
if err = mod.Page(in.Page, in.PerPage).Hook(hook.CityLabel).Order("id desc").Scan(&list); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < len(list); i++ {
|
||||
// 管理员
|
||||
if list[i].AppId == consts.AppAdmin {
|
||||
memberName, err := dao.AdminMember.Ctx(ctx).Fields("realname").Where("id", list[i].MemberId).Value()
|
||||
routes := global.LoadHTTPRoutes(ghttp.RequestFromCtx(ctx))
|
||||
for _, v := range list {
|
||||
if v.AppId == consts.AppAdmin {
|
||||
memberName, err := dao.AdminMember.Ctx(ctx).Fields("realname").WherePri(v.MemberId).Value()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
list[i].MemberName = memberName.String()
|
||||
v.MemberName = memberName.String()
|
||||
}
|
||||
|
||||
// 接口
|
||||
// ...
|
||||
|
||||
if list[i].MemberName == "" {
|
||||
list[i].MemberName = "游客"
|
||||
if v.MemberName == "" {
|
||||
v.MemberName = "游客"
|
||||
}
|
||||
|
||||
// 截取请求url路径
|
||||
if gstr.Contains(list[i].Url, "?") {
|
||||
list[i].Url = gstr.StrTillEx(list[i].Url, "?")
|
||||
if gstr.Contains(v.Url, "?") {
|
||||
v.Url = gstr.StrTillEx(v.Url, "?")
|
||||
}
|
||||
|
||||
key := global.GenRouteKey(v.Method, v.Url)
|
||||
route, ok := routes[key]
|
||||
if ok {
|
||||
v.Tags = route.Tags
|
||||
v.Summary = route.Summary
|
||||
v.Description = route.Description
|
||||
}
|
||||
|
||||
if simple.IsDemo(ctx) {
|
||||
list[i].HeaderData = gjson.New(`{
|
||||
v.HeaderData = gjson.New(`{
|
||||
"none": [
|
||||
"` + consts.DemoTips + `"
|
||||
]
|
||||
|
@ -43,13 +43,13 @@ func init() {
|
||||
}
|
||||
|
||||
// Model 登录日志Orm模型
|
||||
func (s *sSysLoginLog) Model(ctx context.Context) *gdb.Model {
|
||||
return dao.SysLoginLog.Ctx(ctx)
|
||||
func (s *sSysLoginLog) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
return handler.Model(dao.SysLoginLog.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
// List 获取登录日志列表
|
||||
func (s *sSysLoginLog) List(ctx context.Context, in *sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error) {
|
||||
mod := dao.SysLoginLog.Ctx(ctx)
|
||||
mod := s.Model(ctx)
|
||||
|
||||
// 查询状态
|
||||
if in.Status > 0 {
|
||||
@ -76,7 +76,7 @@ func (s *sSysLoginLog) List(ctx context.Context, in *sysin.LoginLogListInp) (lis
|
||||
return
|
||||
}
|
||||
|
||||
if err = mod.Fields(sysin.LoginLogListModel{}).Hook(hook.CityLabel).Handler(handler.FilterAuth).Page(in.Page, in.PerPage).OrderDesc(dao.SysLoginLog.Columns().Id).Scan(&list); err != nil {
|
||||
if err = mod.Fields(sysin.LoginLogListModel{}).Hook(hook.CityLabel).Page(in.Page, in.PerPage).OrderDesc(dao.SysLoginLog.Columns().Id).Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
@ -121,13 +121,7 @@ func (s *sSysLoginLog) Export(ctx context.Context, in *sysin.LoginLogListInp) (e
|
||||
|
||||
// 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()
|
||||
return
|
||||
}
|
||||
|
||||
// View 获取登录日志指定信息
|
||||
func (s *sSysLoginLog) View(ctx context.Context, in *sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error) {
|
||||
err = dao.SysLoginLog.Ctx(ctx).Where(dao.SysLoginLog.Columns().Id, in.Id).Scan(&res)
|
||||
_, err = s.Model(ctx).WherePri(in.Id).Delete()
|
||||
return
|
||||
}
|
||||
|
||||
@ -181,6 +175,6 @@ func (s *sSysLoginLog) Push(ctx context.Context, in *sysin.LoginLogPushInp) {
|
||||
|
||||
// RealWrite 真实写入
|
||||
func (s *sSysLoginLog) RealWrite(ctx context.Context, models entity.SysLoginLog) (err error) {
|
||||
_, err = dao.SysLoginLog.Ctx(ctx).FieldsEx(dao.SysLog.Columns().Id).Data(models).Insert()
|
||||
_, err = dao.SysLoginLog.Ctx(ctx).Data(models).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ func (s *sSysNormalTreeDemo) Edit(ctx context.Context, in *sysin.NormalTreeDemoE
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
||||
Fields(sysin.NormalTreeDemoInsertFields{}).
|
||||
Data(in).Insert(); err != nil {
|
||||
Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增普通树表失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
@ -173,4 +173,4 @@ func (s *sSysNormalTreeDemo) TreeOption(ctx context.Context) (nodes []tree.Node,
|
||||
nodes[i] = v
|
||||
}
|
||||
return tree.ListToTree(0, nodes)
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ func (s *sSysOptionTreeDemo) Edit(ctx context.Context, in *sysin.OptionTreeDemoE
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
||||
Fields(sysin.OptionTreeDemoInsertFields{}).
|
||||
Data(in).Insert(); err != nil {
|
||||
Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增选项树表失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
@ -173,4 +173,4 @@ func (s *sSysOptionTreeDemo) TreeOption(ctx context.Context) (nodes []tree.Node,
|
||||
nodes[i] = v
|
||||
}
|
||||
return tree.ListToTree(0, nodes)
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ func (s *sSysProvinces) Edit(ctx context.Context, in *sysin.ProvincesEditInp) (e
|
||||
}
|
||||
|
||||
// 新增
|
||||
if _, err = dao.SysProvinces.Ctx(ctx).Fields(sysin.ProvincesInsertFields{}).Data(in).Insert(); err != nil {
|
||||
if _, err = dao.SysProvinces.Ctx(ctx).Fields(sysin.ProvincesInsertFields{}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增省市区数据失败!")
|
||||
}
|
||||
return
|
||||
|
@ -142,7 +142,7 @@ func (s *sSysServeLicense) Edit(ctx context.Context, in *sysin.ServeLicenseEditI
|
||||
}
|
||||
|
||||
// 新增
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Fields(sysin.ServeLicenseInsertFields{}).Data(in).Insert(); err != nil {
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Fields(sysin.ServeLicenseInsertFields{}).Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增服务许可证失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
|
@ -126,6 +126,6 @@ func (s *sSysServeLog) View(ctx context.Context, in *sysin.ServeLogViewInp) (res
|
||||
|
||||
// RealWrite 真实写入
|
||||
func (s *sSysServeLog) RealWrite(ctx context.Context, models entity.SysServeLog) (err error) {
|
||||
_, err = dao.SysServeLog.Ctx(ctx).FieldsEx(dao.SysLog.Columns().Id).Data(models).Insert()
|
||||
_, err = dao.SysServeLog.Ctx(ctx).FieldsEx(dao.SysLog.Columns().Id).Data(models).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ func (s *sSysSmsLog) SendCode(ctx context.Context, in *sysin.SendCodeInp) (err e
|
||||
data.CreatedAt = gtime.Now()
|
||||
data.UpdatedAt = gtime.Now()
|
||||
|
||||
_, err = dao.SysSmsLog.Ctx(ctx).Data(data).Insert()
|
||||
_, err = dao.SysSmsLog.Ctx(ctx).Data(data).OmitEmptyData().Insert()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ func (s *sSysTestCategory) Edit(ctx context.Context, in *sysin.TestCategoryEditI
|
||||
// 新增
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
||||
Fields(sysin.TestCategoryInsertFields{}).
|
||||
Data(in).Insert(); err != nil {
|
||||
Data(in).OmitEmptyData().Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增测试分类失败,请稍后重试!")
|
||||
}
|
||||
return
|
||||
@ -164,4 +164,4 @@ func (s *sSysTestCategory) Option(ctx context.Context) (opts []*model.Option, er
|
||||
opts[k] = dict.GenHashOption(v.Id, gconv.String(v.Name))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ type MemberAddInp struct {
|
||||
}
|
||||
|
||||
func (in *MemberEditInp) Filter(ctx context.Context) (err error) {
|
||||
if in.Password != "" {
|
||||
if in.Id < 1 || in.Password != "" {
|
||||
if err := g.Validator().
|
||||
Rules("length:6,16").
|
||||
Messages("新密码不能为空#新密码需在6~16之间").
|
||||
|
@ -14,20 +14,25 @@ import (
|
||||
type LogListInp struct {
|
||||
form.PageReq
|
||||
form.StatusReq
|
||||
ReqId string `json:"reqId" dc:"对外ID"`
|
||||
Module string `json:"module" dc:"应用端口"`
|
||||
MemberId int `json:"member_id" dc:"用户ID"`
|
||||
TakeUpTime int `json:"take_up_time" dc:"请求耗时"`
|
||||
MemberId int `json:"memberId" dc:"用户ID"`
|
||||
TakeUpTime string `json:"takeUpTime" dc:"请求耗时"`
|
||||
Method string `json:"method" dc:"请求方式"`
|
||||
Url string `json:"url" dc:"请求路径"`
|
||||
Ip string `json:"ip" dc:"访问IP"`
|
||||
ErrorCode string `json:"error_code" dc:"状态码"`
|
||||
CreatedAt []int64 `json:"created_at" dc:"创建时间"`
|
||||
ErrorCode string `json:"errorCode" dc:"状态码"`
|
||||
CreatedAt []int64 `json:"createdAt" dc:"创建时间"`
|
||||
}
|
||||
|
||||
type LogListModel struct {
|
||||
entity.SysLog
|
||||
MemberName string `json:"memberName"`
|
||||
Region string `json:"region"`
|
||||
MemberName string `json:"memberName"`
|
||||
Region string `json:"region"`
|
||||
CityLabel string `json:"cityLabel" dc:"城市标签"`
|
||||
Tags string `json:"tags" dc:"接口所属的标签,用于接口分类"`
|
||||
Summary string `json:"summary" dc:"接口/参数概要描述"`
|
||||
Description string `json:"description" dc:"接口/参数详细描述"`
|
||||
}
|
||||
|
||||
// LogViewInp 获取信息
|
||||
@ -37,7 +42,10 @@ type LogViewInp struct {
|
||||
|
||||
type LogViewModel struct {
|
||||
entity.SysLog
|
||||
CityLabel string `json:"cityLabel" description:"城市标签"`
|
||||
CityLabel string `json:"cityLabel" dc:"城市标签"`
|
||||
Tags string `json:"tags" dc:"接口所属的标签,用于接口分类"`
|
||||
Summary string `json:"summary" dc:"接口/参数概要描述"`
|
||||
Description string `json:"description" dc:"接口/参数详细描述"`
|
||||
}
|
||||
|
||||
// LogDeleteInp 删除
|
||||
|
@ -37,14 +37,6 @@ type (
|
||||
Blacklist(r *ghttp.Request)
|
||||
// Develop 开发工具白名单过滤
|
||||
Develop(r *ghttp.Request)
|
||||
// GetFilterRoutes 获取支持预处理的web路由
|
||||
GetFilterRoutes(r *ghttp.Request) map[string]ghttp.RouterItem
|
||||
// GenFilterRequestKey 根据请求生成唯一key
|
||||
GenFilterRequestKey(r *ghttp.Request) string
|
||||
// GenFilterRouteKey 根据路由生成唯一key
|
||||
GenFilterRouteKey(r *ghttp.Router) string
|
||||
// GenRouteKey 生成唯一key
|
||||
GenRouteKey(method, path string) string
|
||||
// PreFilter 请求输入预处理
|
||||
// api使用gf规范路由并且XxxReq结构体实现了validate.Filter接口即可
|
||||
PreFilter(r *ghttp.Request)
|
||||
|
@ -243,6 +243,8 @@ type (
|
||||
Build(ctx context.Context, in *sysin.GenCodesBuildInp) (err error)
|
||||
}
|
||||
ISysLog interface {
|
||||
// Model 请求日志Orm模型
|
||||
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
|
||||
// Export 导出
|
||||
Export(ctx context.Context, in *sysin.LogListInp) (err error)
|
||||
// RealWrite 真实写入
|
||||
@ -251,24 +253,22 @@ type (
|
||||
AutoLog(ctx context.Context) error
|
||||
// AnalysisLog 解析日志数据
|
||||
AnalysisLog(ctx context.Context) entity.SysLog
|
||||
// View 获取指定字典类型信息
|
||||
// View 获取指定请求日志信息
|
||||
View(ctx context.Context, in *sysin.LogViewInp) (res *sysin.LogViewModel, err error)
|
||||
// Delete 删除
|
||||
// Delete 删除请求日志
|
||||
Delete(ctx context.Context, in *sysin.LogDeleteInp) (err error)
|
||||
// List 列表
|
||||
// List 请求日志列表
|
||||
List(ctx context.Context, in *sysin.LogListInp) (list []*sysin.LogListModel, totalCount int, err error)
|
||||
}
|
||||
ISysLoginLog interface {
|
||||
// Model 登录日志Orm模型
|
||||
Model(ctx context.Context) *gdb.Model
|
||||
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
|
||||
// List 获取登录日志列表
|
||||
List(ctx context.Context, in *sysin.LoginLogListInp) (list []*sysin.LoginLogListModel, totalCount int, err error)
|
||||
// Export 导出登录日志
|
||||
Export(ctx context.Context, in *sysin.LoginLogListInp) (err error)
|
||||
// Delete 删除登录日志
|
||||
Delete(ctx context.Context, in *sysin.LoginLogDeleteInp) (err error)
|
||||
// View 获取登录日志指定信息
|
||||
View(ctx context.Context, in *sysin.LoginLogViewInp) (res *sysin.LoginLogViewModel, err error)
|
||||
// Push 推送登录日志
|
||||
Push(ctx context.Context, in *sysin.LoginLogPushInp)
|
||||
// RealWrite 真实写入
|
||||
|
@ -97,7 +97,7 @@
|
||||
"stylelint-config-standard": "^29.0.0",
|
||||
"stylelint-order": "^5.0.0",
|
||||
"stylelint-scss": "^4.7.0",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"tailwindcss": "^2.2.19",
|
||||
"typescript": "^5.3.0",
|
||||
"unplugin-vue-components": "^0.22.12",
|
||||
"vite": "^4.5.3",
|
||||
|
@ -18,15 +18,6 @@ export function Delete(params) {
|
||||
});
|
||||
}
|
||||
|
||||
// 获取登录日志指定详情
|
||||
export function View(params) {
|
||||
return http.request({
|
||||
url: '/loginLog/view',
|
||||
method: 'GET',
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
// 导出登录日志
|
||||
export function Export(params) {
|
||||
jumpExport('/loginLog/export', params);
|
||||
|
@ -49,21 +49,29 @@ export default () => {
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
const createSocket = () => {
|
||||
console.log('[WebSocket] createSocket...');
|
||||
if (useUserStore.token === '') {
|
||||
if (useUserStore.token === '' || useUserStore.config?.wsAddr == '') {
|
||||
console.error('[WebSocket] 用户未登录,稍后重试...');
|
||||
reconnect();
|
||||
resetReconnect();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
socket = new WebSocket(`${useUserStore.config?.wsAddr}?authorization=${useUserStore.token}`);
|
||||
init();
|
||||
if (lockReconnect) {
|
||||
lockReconnect = false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`[WebSocket] createSocket err: ${e}`);
|
||||
reconnect();
|
||||
resetReconnect();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const resetReconnect = () => {
|
||||
if (lockReconnect) {
|
||||
lockReconnect = false;
|
||||
}
|
||||
reconnect();
|
||||
};
|
||||
|
||||
const reconnect = () => {
|
||||
@ -73,7 +81,7 @@ export default () => {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
createSocket();
|
||||
}, SocketEnum.HeartBeatInterval);
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
|
@ -64,9 +64,9 @@
|
||||
{
|
||||
field: 'url',
|
||||
component: 'NInput',
|
||||
label: '访问路径',
|
||||
label: '接口路径',
|
||||
componentProps: {
|
||||
placeholder: '请输入访问路径',
|
||||
placeholder: '请输入接口路径',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
|
@ -1,84 +1,147 @@
|
||||
import { h } from 'vue';
|
||||
import { NTag } from 'naive-ui';
|
||||
import { NTag, NEllipsis, NSpace } from 'naive-ui';
|
||||
import { timestampToTime } from '@/utils/dateUtil';
|
||||
import { renderHtmlTooltip } from '@/utils';
|
||||
|
||||
export const columns = [
|
||||
{
|
||||
title: '模块',
|
||||
key: 'module',
|
||||
render(row) {
|
||||
return h(
|
||||
NTag,
|
||||
{
|
||||
style: {
|
||||
marginRight: '6px',
|
||||
},
|
||||
type: row.module == 'admin' ? 'info' : 'success',
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () => row.module,
|
||||
}
|
||||
);
|
||||
},
|
||||
title: '记录ID',
|
||||
key: 'id',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '操作人',
|
||||
key: 'memberName',
|
||||
render(row) {
|
||||
if (row.memberId === 0) {
|
||||
return row.memberName;
|
||||
}
|
||||
return row.memberName + '(' + row.memberId + ')';
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '请求方式',
|
||||
key: 'method',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '请求路径',
|
||||
key: 'url',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '访问IP',
|
||||
key: 'ip',
|
||||
width: 150,
|
||||
},
|
||||
// {
|
||||
// title: 'IP地区',
|
||||
// key: 'region',
|
||||
// },
|
||||
{
|
||||
title: '状态码',
|
||||
key: 'errorCode',
|
||||
title: '访客',
|
||||
key: 'name',
|
||||
width: 180,
|
||||
render(row) {
|
||||
const operator =
|
||||
row.memberId === 0 ? row.memberName : row.memberName + '(' + row.memberId + ')';
|
||||
|
||||
return h(
|
||||
NTag,
|
||||
NEllipsis,
|
||||
{
|
||||
style: {
|
||||
marginRight: '6px',
|
||||
maxWidth: '180px',
|
||||
},
|
||||
type: row.errorCode == 0 ? 'success' : 'warning',
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () => row.errorMsg + '(' + row.errorCode + ')',
|
||||
default: () =>
|
||||
h(
|
||||
NSpace,
|
||||
{ vertical: true },
|
||||
{
|
||||
default: () => [
|
||||
h('div', {
|
||||
innerHTML: '<div><p>' + operator + '</p></div>',
|
||||
}),
|
||||
h('div', {
|
||||
innerHTML: '<div><p>IP:' + row.ip + '</p></div>',
|
||||
}),
|
||||
row.cityLabel != ''
|
||||
? h(
|
||||
NTag,
|
||||
{
|
||||
style: {
|
||||
marginRight: '6px',
|
||||
},
|
||||
type: 'primary',
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () => row.cityLabel,
|
||||
}
|
||||
)
|
||||
: null,
|
||||
],
|
||||
}
|
||||
),
|
||||
}
|
||||
);
|
||||
},
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '处理耗时',
|
||||
key: 'takeUpTime',
|
||||
title: '请求接口',
|
||||
key: 'name',
|
||||
width: 260,
|
||||
render(row) {
|
||||
return row.takeUpTime + ' ms';
|
||||
return h(
|
||||
NEllipsis,
|
||||
{
|
||||
style: {
|
||||
maxWidth: '260px',
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () =>
|
||||
h(
|
||||
NSpace,
|
||||
{ vertical: true },
|
||||
{
|
||||
default: () => [
|
||||
h(
|
||||
NTag,
|
||||
{
|
||||
style: {
|
||||
marginRight: '6px',
|
||||
},
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () => row.method,
|
||||
}
|
||||
),
|
||||
h('div', {
|
||||
innerHTML: '<div><p>接口:' + row.url + '</p></div>',
|
||||
}),
|
||||
h('div', {
|
||||
innerHTML: '<div><p>名称:' + row.tags + ' / ' + row.summary + '</p></div>',
|
||||
}),
|
||||
],
|
||||
}
|
||||
),
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '接口响应',
|
||||
key: 'name',
|
||||
width: 260,
|
||||
render(row) {
|
||||
return h(
|
||||
NEllipsis,
|
||||
{
|
||||
style: {
|
||||
maxWidth: '260px',
|
||||
},
|
||||
},
|
||||
{
|
||||
default: () =>
|
||||
h(
|
||||
NSpace,
|
||||
{ vertical: true },
|
||||
{
|
||||
default: () => [
|
||||
renderHtmlTooltip(
|
||||
'<div style="width: 240px"><p>状态码:' +
|
||||
row.errorMsg +
|
||||
'(' +
|
||||
row.errorCode +
|
||||
')' +
|
||||
'</p></div>'
|
||||
),
|
||||
h('div', {
|
||||
innerHTML: '<div><p>处理耗时:' + row.takeUpTime + 'ms</p></div>',
|
||||
}),
|
||||
h('div', {
|
||||
innerHTML: '<div><p>响应时间:' + timestampToTime(row.timestamp) + '</p></div>',
|
||||
}),
|
||||
],
|
||||
}
|
||||
),
|
||||
}
|
||||
);
|
||||
},
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '访问时间',
|
||||
|
@ -39,150 +39,26 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, h, reactive, ref } from 'vue';
|
||||
import { computed, h, onMounted, reactive, ref } from 'vue';
|
||||
import { useDialog, useMessage } from 'naive-ui';
|
||||
import { BasicTable, TableAction } from '@/components/Table';
|
||||
import { BasicForm, FormSchema, useForm } from '@/components/Form/index';
|
||||
import { BasicForm, useForm } from '@/components/Form/index';
|
||||
import { getLogList, Delete } from '@/api/log/log';
|
||||
import { columns } from './columns';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { DeleteOutlined } from '@vicons/antd';
|
||||
import { adaTableScrollX } from '@/utils/hotgo';
|
||||
import { loadOptions, schemas } from './model';
|
||||
|
||||
const dialog = useDialog();
|
||||
const batchDeleteDisabled = ref(true);
|
||||
const checkedIds = ref([]);
|
||||
|
||||
const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'member_id',
|
||||
component: 'NInput',
|
||||
label: '操作人',
|
||||
componentProps: {
|
||||
placeholder: '请输入操作人ID',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
rules: [{ trigger: ['blur'] }],
|
||||
},
|
||||
{
|
||||
field: 'url',
|
||||
component: 'NInput',
|
||||
label: '访问路径',
|
||||
componentProps: {
|
||||
placeholder: '请输入访问路径',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'ip',
|
||||
component: 'NInput',
|
||||
label: '访问IP',
|
||||
componentProps: {
|
||||
placeholder: '请输入IP地址',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'method',
|
||||
component: 'NSelect',
|
||||
label: '请求方式',
|
||||
componentProps: {
|
||||
placeholder: '请选择请求方式',
|
||||
options: [
|
||||
{
|
||||
label: 'GET',
|
||||
value: 'GET',
|
||||
},
|
||||
{
|
||||
label: 'POST',
|
||||
value: 'POST',
|
||||
},
|
||||
],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'created_at',
|
||||
component: 'NDatePicker',
|
||||
label: '访问时间',
|
||||
componentProps: {
|
||||
type: 'datetimerange',
|
||||
clearable: true,
|
||||
// defaultValue: [new Date() - 86400000 * 30, new Date()],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'take_up_time',
|
||||
component: 'NSelect',
|
||||
label: '请求耗时',
|
||||
componentProps: {
|
||||
placeholder: '请选择请求耗时',
|
||||
options: [
|
||||
{
|
||||
label: '50ms内',
|
||||
value: '50',
|
||||
},
|
||||
{
|
||||
label: '100ms内',
|
||||
value: '100',
|
||||
},
|
||||
{
|
||||
label: '200ms内',
|
||||
value: '200',
|
||||
},
|
||||
{
|
||||
label: '500ms内',
|
||||
value: '500',
|
||||
},
|
||||
],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'error_code',
|
||||
component: 'NSelect',
|
||||
label: '状态码',
|
||||
componentProps: {
|
||||
placeholder: '请选择状态码',
|
||||
options: [
|
||||
{
|
||||
label: '0 成功',
|
||||
value: '0',
|
||||
},
|
||||
{
|
||||
label: '-1 失败',
|
||||
value: '-1',
|
||||
},
|
||||
],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const router = useRouter();
|
||||
const message = useMessage();
|
||||
const actionRef = ref();
|
||||
const formParams = ref({});
|
||||
|
||||
const params = ref({
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 160,
|
||||
title: '操作',
|
||||
@ -233,9 +109,6 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@ -251,14 +124,11 @@
|
||||
reloadTable();
|
||||
});
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
// message.error('取消');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const loadDataTable = async (res) => {
|
||||
return await getLogList({ ...formParams.value, ...params.value, ...res });
|
||||
return await getLogList({ ...formParams.value, ...res });
|
||||
};
|
||||
|
||||
function reloadTable() {
|
||||
@ -278,6 +148,10 @@
|
||||
formParams.value = {};
|
||||
reloadTable();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadOptions();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
134
web/src/views/log/log/model.ts
Normal file
134
web/src/views/log/log/model.ts
Normal file
@ -0,0 +1,134 @@
|
||||
import { FormSchema } from '@/components/Form';
|
||||
import { ref } from 'vue';
|
||||
import { defRangeShortcuts } from '@/utils/dateUtil';
|
||||
import { Option } from '@/utils/hotgo';
|
||||
import { Dicts } from '@/api/dict/dict';
|
||||
|
||||
export const schemas = ref<FormSchema[]>([
|
||||
{
|
||||
field: 'reqId',
|
||||
component: 'NInput',
|
||||
label: '链路ID',
|
||||
componentProps: {
|
||||
placeholder: '请输入链路ID',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'memberId',
|
||||
component: 'NInput',
|
||||
label: '操作人',
|
||||
componentProps: {
|
||||
placeholder: '请输入操作人ID',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
rules: [{ trigger: ['blur'] }],
|
||||
},
|
||||
{
|
||||
field: 'url',
|
||||
component: 'NInput',
|
||||
label: '接口路径',
|
||||
componentProps: {
|
||||
placeholder: '请输入接口路径',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'ip',
|
||||
component: 'NInput',
|
||||
label: '访问IP',
|
||||
componentProps: {
|
||||
placeholder: '请输入IP地址',
|
||||
onInput: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'method',
|
||||
component: 'NSelect',
|
||||
label: '请求方式',
|
||||
componentProps: {
|
||||
placeholder: '请选择请求方式',
|
||||
options: [],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'createdAt',
|
||||
component: 'NDatePicker',
|
||||
label: '访问时间',
|
||||
componentProps: {
|
||||
type: 'datetimerange',
|
||||
clearable: true,
|
||||
shortcuts: defRangeShortcuts(),
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'takeUpTime',
|
||||
component: 'NSelect',
|
||||
label: '请求耗时',
|
||||
componentProps: {
|
||||
placeholder: '请选择请求耗时',
|
||||
options: [],
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'errorCode',
|
||||
component: 'NSelect',
|
||||
label: '状态码',
|
||||
labelMessage: '支持填入自定义状态码',
|
||||
componentProps: {
|
||||
placeholder: '请选择状态码',
|
||||
options: [],
|
||||
filterable: true,
|
||||
tag: true,
|
||||
onUpdateValue: (e: any) => {
|
||||
console.log(e);
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
// 字典数据选项
|
||||
export const options = ref({
|
||||
HTTPMethod: [] as Option[],
|
||||
HTTPHandlerTime: [] as Option[],
|
||||
HTTPApiCode: [] as Option[],
|
||||
});
|
||||
|
||||
// 加载字典数据选项
|
||||
export function loadOptions() {
|
||||
Dicts({
|
||||
types: ['HTTPMethod', 'HTTPHandlerTime', 'HTTPApiCode'],
|
||||
}).then((res) => {
|
||||
options.value = res;
|
||||
for (const item of schemas.value) {
|
||||
switch (item.field) {
|
||||
case 'method':
|
||||
item.componentProps.options = options.value.HTTPMethod;
|
||||
break;
|
||||
case 'takeUpTime':
|
||||
item.componentProps.options = options.value.HTTPHandlerTime;
|
||||
break;
|
||||
case 'errorCode':
|
||||
item.componentProps.options = options.value.HTTPApiCode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
@ -14,15 +14,18 @@
|
||||
<template #label>请求地址</template>
|
||||
{{ data.url }}
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="请求耗时">{{ data.takeUpTime }} ms</n-descriptions-item>
|
||||
<n-descriptions-item label="接口名称"
|
||||
>{{ data.tags }} / {{ data.summary }}</n-descriptions-item
|
||||
>
|
||||
<n-descriptions-item label="访问IP">{{ data.ip }}</n-descriptions-item>
|
||||
<n-descriptions-item label="IP归属地">{{ data.cityLabel }}</n-descriptions-item>
|
||||
<n-descriptions-item label="链路ID">{{ data.reqId }}</n-descriptions-item>
|
||||
<n-descriptions-item label="请求耗时">{{ data.takeUpTime }} ms</n-descriptions-item>
|
||||
<n-descriptions-item label="响应时间">{{
|
||||
timestampToTime(data.timestamp)
|
||||
data.timestamp > 0 ? timestampToTime(data.timestamp) : '--'
|
||||
}}</n-descriptions-item>
|
||||
|
||||
<n-descriptions-item label="创建时间">{{ data.createdAt }}</n-descriptions-item>
|
||||
<n-descriptions-item label="访问时间">{{ data.createdAt }}</n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
<n-card
|
||||
@ -131,22 +134,13 @@
|
||||
|
||||
const message = useMessage();
|
||||
const router = useRouter();
|
||||
const logId = Number(router.currentRoute.value.params.id);
|
||||
const params = router.currentRoute.value.params;
|
||||
const loading = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
if (logId === undefined || logId < 1) {
|
||||
message.error('ID不正确,请检查!');
|
||||
return;
|
||||
}
|
||||
getInfo();
|
||||
});
|
||||
|
||||
const data = ref({});
|
||||
|
||||
const getInfo = () => {
|
||||
loading.value = true;
|
||||
View({ id: logId })
|
||||
View(params)
|
||||
.then((res) => {
|
||||
data.value = res;
|
||||
})
|
||||
@ -154,6 +148,14 @@
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (!params.id) {
|
||||
message.error('日志ID不正确,请检查!');
|
||||
return;
|
||||
}
|
||||
getInfo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
@ -77,7 +77,7 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||||
cssTarget: 'chrome80',
|
||||
outDir: OUTPUT_DIR,
|
||||
reportCompressedSize: false,
|
||||
chunkSizeWarningLimit: 2000,
|
||||
chunkSizeWarningLimit: 3000,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user