mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-01-23 10:50:24 +08:00
commit
406e3ef168
@ -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
|
||||
}
|
||||
|
||||
|
@ -75,8 +75,10 @@ func GenHashOption(key interface{}, label string) *model.Option {
|
||||
tag := "default"
|
||||
if _, err := hash.Write(gconv.Bytes(label)); err == nil {
|
||||
index := int(hash.Sum32()) % len(strings)
|
||||
if index < len(strings) {
|
||||
tag = strings[index]
|
||||
}
|
||||
}
|
||||
return &model.Option{
|
||||
Key: key,
|
||||
Label: label,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ func (m *MsgParser) RegisterRPCRouter(routers ...interface{}) (err error) {
|
||||
|
||||
// RegisterInterceptor 注册拦截器
|
||||
func (m *MsgParser) RegisterInterceptor(interceptors ...Interceptor) {
|
||||
m.interceptors = append(interceptors, interceptors...)
|
||||
m.interceptors = append(m.interceptors, interceptors...)
|
||||
}
|
||||
|
||||
// Encoding 消息编码
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -111,7 +120,11 @@ func (s *sSysLog) AutoLog(ctx context.Context) error {
|
||||
}()
|
||||
|
||||
config, err := service.SysConfig().GetLoadLog(ctx)
|
||||
if err != nil || !config.Switch {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if config == nil || !config.Switch {
|
||||
return
|
||||
}
|
||||
|
||||
@ -167,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)
|
||||
@ -209,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,
|
||||
@ -230,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
|
||||
}
|
||||
@ -245,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": [
|
||||
@ -255,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 != "" {
|
||||
@ -275,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)
|
||||
@ -301,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()
|
||||
@ -310,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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"`
|
||||
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 删除
|
||||
|
File diff suppressed because one or more lines are too long
@ -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 真实写入
|
||||
|
@ -45,7 +45,7 @@ module.exports = defineConfig({
|
||||
{ varsIgnorePattern: '.*', args: 'none' },
|
||||
],
|
||||
'space-before-function-paren': 'off',
|
||||
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
'vue/html-closing-bracket-newline': 'off',
|
||||
|
@ -68,38 +68,38 @@
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"@vitejs/plugin-vue": "^3.2.0",
|
||||
"@vitejs/plugin-vue-jsx": "^2.1.1",
|
||||
"@vue/compiler-sfc": "^3.2.33",
|
||||
"@vue/eslint-config-typescript": "^7.0.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"commitizen": "^4.2.4",
|
||||
"core-js": "^3.22.5",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-define-config": "1.0.9",
|
||||
"eslint-plugin-jest": "^24.7.0",
|
||||
"eslint-plugin-prettier": "^3.4.1",
|
||||
"eslint-plugin-vue": "^7.20.0",
|
||||
"esno": "^0.7.3",
|
||||
"gh-pages": "^3.2.3",
|
||||
"husky": "^6.0.0",
|
||||
"jest": "^27.5.1",
|
||||
"less": "^4.1.2",
|
||||
"less-loader": "^9.1.0",
|
||||
"lint-staged": "^11.2.6",
|
||||
"@vue/compiler-sfc": "^3.4.21",
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"commitizen": "^4.3.0",
|
||||
"core-js": "^3.36.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"eslint-define-config": "1.12.0",
|
||||
"eslint-plugin-jest": "^27.9.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.24.1",
|
||||
"esno": "^0.16.3",
|
||||
"gh-pages": "^4.0.0",
|
||||
"husky": "^8.0.3",
|
||||
"jest": "^29.7.0",
|
||||
"less": "^4.2.0",
|
||||
"less-loader": "^11.1.4",
|
||||
"lint-staged": "^13.3.0",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^2.6.2",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"prettier": "^2.8.8",
|
||||
"pretty-quick": "^3.3.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-prettier": "^8.0.2",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"stylelint-scss": "^3.21.0",
|
||||
"stylelint": "^14.16.1",
|
||||
"stylelint-config-prettier": "^9.0.5",
|
||||
"stylelint-config-standard": "^29.0.0",
|
||||
"stylelint-order": "^5.0.0",
|
||||
"stylelint-scss": "^4.7.0",
|
||||
"tailwindcss": "^2.2.19",
|
||||
"typescript": "^5.3.0",
|
||||
"unplugin-vue-components": "^0.17.21",
|
||||
"unplugin-vue-components": "^0.22.12",
|
||||
"vite": "^4.5.3",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-html": "^2.1.2",
|
||||
|
@ -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);
|
||||
|
@ -1,13 +1,15 @@
|
||||
<template>
|
||||
<RouterView>
|
||||
<template #default="{ Component, route }">
|
||||
{{ retryKeepAlive(route) }}
|
||||
{{ setKeepAlive(route) }}
|
||||
<template v-if="mode === 'production'">
|
||||
<transition :name="getTransitionName" appear mode="out-in">
|
||||
<div>
|
||||
<keep-alive v-if="keepAliveComponents.length" :include="keepAliveComponents">
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
</keep-alive>
|
||||
<component :is="Component" v-else :key="route.fullPath" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
<template v-else>
|
||||
@ -40,12 +42,11 @@
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const mode = import.meta.env.MODE;
|
||||
const router = useRouter();
|
||||
const { getIsPageAnimate, getPageAnimateType } = useProjectSetting();
|
||||
const asyncRouteStore = useAsyncRouteStore();
|
||||
// 需要缓存的路由组件
|
||||
const keepAliveComponents = computed(() => asyncRouteStore.keepAliveComponents);
|
||||
|
||||
const getTransitionName = computed(() => {
|
||||
return unref(getIsPageAnimate) ? unref(getPageAnimateType) : '';
|
||||
});
|
||||
@ -56,7 +57,7 @@
|
||||
return currentComponent.name || currentComponent.__name;
|
||||
}
|
||||
|
||||
function retryKeepAlive(route) {
|
||||
function setKeepAlive(route) {
|
||||
if (!route?.meta?.keepAlive) {
|
||||
return;
|
||||
}
|
||||
@ -65,26 +66,15 @@
|
||||
if (currentName === undefined || route.name === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = keepAliveComponents.value.findIndex((name) => name === route.name);
|
||||
if (index > -1 && currentName !== route.name) {
|
||||
const index2 = keepAliveComponents.value.findIndex((name) => name === currentName);
|
||||
if (index2 === -1) {
|
||||
console.warn(
|
||||
`the routing name configured on the backend is inconsistent with the component name in the. vue file. KeepAlive has been retried based on the actual component name, but this may cause unexpected issues.\n routeName:` +
|
||||
route.name +
|
||||
',currentName:' +
|
||||
currentName
|
||||
);
|
||||
if (!keepAliveComponents.value.includes(currentName)) {
|
||||
asyncRouteStore.keepAliveComponents.push(currentName);
|
||||
}
|
||||
}
|
||||
}
|
||||
const mode = import.meta.env.MODE;
|
||||
|
||||
return {
|
||||
keepAliveComponents,
|
||||
getTransitionName,
|
||||
retryKeepAlive,
|
||||
setKeepAlive,
|
||||
mode,
|
||||
};
|
||||
},
|
||||
|
@ -102,21 +102,6 @@ export function createRouterGuards(router: Router) {
|
||||
if (isNavigationFailure(failure)) {
|
||||
//console.log('failed navigation', failure)
|
||||
}
|
||||
const asyncRouteStore = useAsyncRouteStoreWidthOut();
|
||||
// 在这里设置需要缓存的组件名称
|
||||
const keepAliveComponents = asyncRouteStore.keepAliveComponents;
|
||||
const currentComName: any = to.matched.find((item) => item.name == to.name)?.name;
|
||||
if (currentComName && !keepAliveComponents.includes(currentComName) && to.meta?.keepAlive) {
|
||||
// 需要缓存的组件
|
||||
keepAliveComponents.push(currentComName);
|
||||
} else if (!to.meta?.keepAlive || to.name == 'Redirect') {
|
||||
// 不需要缓存的组件
|
||||
const index = asyncRouteStore.keepAliveComponents.findIndex((name) => name == currentComName);
|
||||
if (index != -1) {
|
||||
keepAliveComponents.splice(index, 1);
|
||||
}
|
||||
}
|
||||
asyncRouteStore.setKeepAliveComponents(keepAliveComponents);
|
||||
const Loading = window['$loading'] || null;
|
||||
Loading && Loading.finish();
|
||||
});
|
||||
|
@ -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();
|
||||
} catch (e) {
|
||||
console.error(`[WebSocket] createSocket err: ${e}`);
|
||||
reconnect();
|
||||
}
|
||||
if (lockReconnect) {
|
||||
lockReconnect = false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`[WebSocket] createSocket err: ${e}`);
|
||||
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(
|
||||
NEllipsis,
|
||||
{
|
||||
style: {
|
||||
maxWidth: '180px',
|
||||
},
|
||||
},
|
||||
{
|
||||
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: row.errorCode == 0 ? 'success' : 'warning',
|
||||
type: 'primary',
|
||||
bordered: false,
|
||||
},
|
||||
{
|
||||
default: () => row.errorMsg + '(' + row.errorCode + ')',
|
||||
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