mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-08-28 10:09:54 +08:00
版本预发布
This commit is contained in:
@@ -9,25 +9,26 @@ package admin
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/crypto/gmd5"
|
||||
"github.com/gogf/gf/v2/encoding/gbase64"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
"hotgo/api/backend/member"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/library/hgorm/hook"
|
||||
"hotgo/internal/library/jwt"
|
||||
"hotgo/internal/library/location"
|
||||
"hotgo/internal/model"
|
||||
"hotgo/internal/model/do"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/adminin"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/encrypt"
|
||||
"hotgo/utility/simple"
|
||||
"hotgo/utility/tree"
|
||||
"hotgo/utility/validate"
|
||||
)
|
||||
@@ -42,7 +43,148 @@ func init() {
|
||||
service.RegisterAdminMember(NewAdminMember())
|
||||
}
|
||||
|
||||
// UpdateProfile 更新会员资料
|
||||
// UpdateCash 修改提现信息
|
||||
func (s *sAdminMember) UpdateCash(ctx context.Context, in adminin.MemberUpdateCashInp) (err error) {
|
||||
memberId := contexts.Get(ctx).User.Id
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
|
||||
var memberInfo entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
|
||||
if gmd5.MustEncryptString(in.Password+memberInfo.Salt) != memberInfo.PasswordHash {
|
||||
err = gerror.New("登录密码不正确")
|
||||
return
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).
|
||||
Where("id", memberId).
|
||||
Data(g.Map{
|
||||
"cash": adminin.MemberCash{
|
||||
Name: in.Name,
|
||||
Account: in.Account,
|
||||
PayeeCode: in.PayeeCode,
|
||||
},
|
||||
}).
|
||||
Update()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateEmail 换绑邮箱
|
||||
func (s *sAdminMember) UpdateEmail(ctx context.Context, in adminin.MemberUpdateEmailInp) (err error) {
|
||||
memberId := contexts.Get(ctx).User.Id
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return err
|
||||
}
|
||||
|
||||
var memberInfo *entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo == nil {
|
||||
err = gerror.New("用户信息不存在")
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo.Email == in.Email {
|
||||
err = gerror.New("新旧邮箱不能一样")
|
||||
return
|
||||
}
|
||||
|
||||
if !validate.IsEmail(in.Email) {
|
||||
err = gerror.New("邮箱地址不正确")
|
||||
return
|
||||
}
|
||||
|
||||
// 存在原绑定号码,需要进行验证
|
||||
if memberInfo.Email != "" {
|
||||
err = service.SysEmsLog().VerifyCode(ctx, sysin.VerifyEmsCodeInp{
|
||||
Event: consts.EmsTemplateBind,
|
||||
Email: memberInfo.Email,
|
||||
Code: in.Code,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
update := g.Map{
|
||||
dao.AdminMember.Columns().Email: in.Email,
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMobile 换绑手机号
|
||||
func (s *sAdminMember) UpdateMobile(ctx context.Context, in adminin.MemberUpdateMobileInp) (err error) {
|
||||
memberId := contexts.Get(ctx).User.Id
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return err
|
||||
}
|
||||
|
||||
var memberInfo *entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo == nil {
|
||||
err = gerror.New("用户信息不存在")
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo.Mobile == in.Mobile {
|
||||
err = gerror.New("新旧手机号不能一样")
|
||||
return
|
||||
}
|
||||
|
||||
if !validate.IsMobile(in.Mobile) {
|
||||
err = gerror.New("手机号码不正确")
|
||||
return
|
||||
}
|
||||
|
||||
// 存在原绑定号码,需要进行验证
|
||||
if memberInfo.Mobile != "" {
|
||||
err = service.SysSmsLog().VerifyCode(ctx, sysin.VerifyCodeInp{
|
||||
Event: consts.SmsTemplateBind,
|
||||
Mobile: memberInfo.Mobile,
|
||||
Code: in.Code,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
update := g.Map{
|
||||
dao.AdminMember.Columns().Mobile: in.Mobile,
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateProfile 更新用户资料
|
||||
func (s *sAdminMember) UpdateProfile(ctx context.Context, in adminin.MemberUpdateProfileInp) (err error) {
|
||||
memberId := contexts.Get(ctx).User.Id
|
||||
if memberId <= 0 {
|
||||
@@ -50,21 +192,28 @@ func (s *sAdminMember) UpdateProfile(ctx context.Context, in adminin.MemberUpdat
|
||||
return err
|
||||
}
|
||||
|
||||
var memberInfo entity.AdminMember
|
||||
var memberInfo *entity.AdminMember
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).
|
||||
Where("id", memberId).
|
||||
Data(g.Map{
|
||||
"mobile": in.Mobile,
|
||||
"email": in.Email,
|
||||
"real_name": in.Realname,
|
||||
}).
|
||||
Update()
|
||||
if memberInfo == nil {
|
||||
err = gerror.New("用户信息不存在")
|
||||
return err
|
||||
}
|
||||
|
||||
update := g.Map{
|
||||
dao.AdminMember.Columns().Avatar: in.Avatar,
|
||||
dao.AdminMember.Columns().RealName: in.RealName,
|
||||
dao.AdminMember.Columns().Qq: in.Qq,
|
||||
dao.AdminMember.Columns().Birthday: in.Birthday,
|
||||
dao.AdminMember.Columns().Sex: in.Sex,
|
||||
dao.AdminMember.Columns().CityId: in.CityId,
|
||||
dao.AdminMember.Columns().Address: in.Address,
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
@@ -104,19 +253,25 @@ func (s *sAdminMember) UpdatePwd(ctx context.Context, in adminin.MemberUpdatePwd
|
||||
// ResetPwd 重置密码
|
||||
func (s *sAdminMember) ResetPwd(ctx context.Context, in adminin.MemberResetPwdInp) (err error) {
|
||||
var (
|
||||
memberInfo entity.AdminMember
|
||||
memberInfo *entity.AdminMember
|
||||
memberId = contexts.GetUserId(ctx)
|
||||
)
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", in.Id).Scan(&memberInfo); err != nil {
|
||||
if err = s.FilterAuthModel(ctx, memberId).Where("id", in.Id).Scan(&memberInfo); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo == nil {
|
||||
err = gerror.New("用户信息不存在")
|
||||
return err
|
||||
}
|
||||
|
||||
if memberInfo.Pid != memberId && !s.VerifySuperId(ctx, memberId) {
|
||||
err = gerror.New("操作非法")
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = dao.AdminMember.Ctx(ctx).
|
||||
_, err = s.FilterAuthModel(ctx, memberId).
|
||||
Where("id", in.Id).
|
||||
Data(g.Map{
|
||||
"password_hash": gmd5.MustEncryptString(in.Password + memberInfo.Salt),
|
||||
@@ -192,7 +347,7 @@ func (s *sAdminMember) Delete(ctx context.Context, in adminin.MemberDeleteInp) e
|
||||
return gerror.New("获取用户信息失败!")
|
||||
}
|
||||
|
||||
_, err := dao.AdminMember.Ctx(ctx).Where("id", in.Id).Where("pid", memberId).Delete()
|
||||
_, err := s.FilterAuthModel(ctx, memberId).Where("id", in.Id).Delete()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
@@ -246,11 +401,7 @@ func (s *sAdminMember) Edit(ctx context.Context, in adminin.MemberEditInp) (err
|
||||
}
|
||||
|
||||
// 权限验证
|
||||
var mm = dao.AdminMember.Ctx(ctx).Where("id", in.Id)
|
||||
if !s.VerifySuperId(ctx, opMemberId) {
|
||||
mm = mm.Where("pid", opMemberId)
|
||||
}
|
||||
|
||||
var mm = s.FilterAuthModel(ctx, opMemberId).Where("id", in.Id)
|
||||
_, err = mm.Data(in).Update()
|
||||
if err != nil {
|
||||
return gerror.Wrap(err, consts.ErrorORM)
|
||||
@@ -307,7 +458,7 @@ func (s *sAdminMember) MaxSort(ctx context.Context, in adminin.MemberMaxSortInp)
|
||||
|
||||
// View 获取信息
|
||||
func (s *sAdminMember) View(ctx context.Context, in adminin.MemberViewInp) (res *adminin.MemberViewModel, err error) {
|
||||
if err = dao.AdminMember.Ctx(ctx).Where("id", in.Id).Scan(&res); err != nil {
|
||||
if err = s.FilterAuthModel(ctx, contexts.GetUserId(ctx)).Hook(hook.MemberInfo).Where("id", in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
@@ -317,10 +468,9 @@ func (s *sAdminMember) View(ctx context.Context, in adminin.MemberViewInp) (res
|
||||
|
||||
// List 获取列表
|
||||
func (s *sAdminMember) List(ctx context.Context, in adminin.MemberListInp) (list []*adminin.MemberListModel, totalCount int, err error) {
|
||||
g.Log().Printf(ctx, "in:%#v", in)
|
||||
mod := dao.AdminMember.Ctx(ctx)
|
||||
if in.Realname != "" {
|
||||
mod = mod.WhereLike("real_name", "%"+in.Realname+"%")
|
||||
mod := s.FilterAuthModel(ctx, contexts.GetUserId(ctx))
|
||||
if in.RealName != "" {
|
||||
mod = mod.WhereLike("real_name", "%"+in.RealName+"%")
|
||||
}
|
||||
if in.Username != "" {
|
||||
mod = mod.WhereLike("username", "%"+in.Username+"%")
|
||||
@@ -349,32 +499,11 @@ func (s *sAdminMember) List(ctx context.Context, in adminin.MemberListInp) (list
|
||||
return list, totalCount, nil
|
||||
}
|
||||
|
||||
if err = mod.Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
|
||||
if err = mod.Hook(hook.MemberInfo).Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
|
||||
return nil, 0, gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
|
||||
// 重写树入参
|
||||
for i := 0; i < len(list); i++ {
|
||||
// 部门
|
||||
deptName, err := dao.AdminDept.Ctx(ctx).
|
||||
Fields("name").
|
||||
Where("id", list[i].DeptId).
|
||||
Value()
|
||||
if err != nil {
|
||||
return nil, 0, gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
list[i].DeptName = deptName.String()
|
||||
|
||||
// 角色
|
||||
roleName, err := dao.AdminRole.Ctx(ctx).
|
||||
Fields("name").
|
||||
Where("id", list[i].RoleId).
|
||||
Value()
|
||||
if err != nil {
|
||||
return nil, 0, gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
list[i].RoleName = roleName.String()
|
||||
|
||||
// 岗位
|
||||
posts, err := dao.AdminMemberPost.Ctx(ctx).
|
||||
Fields("post_id").
|
||||
@@ -414,27 +543,43 @@ func (s *sAdminMember) genTree(ctx context.Context, pid int64) (level int, newTr
|
||||
}
|
||||
|
||||
// LoginMemberInfo 获取登录用户信息
|
||||
func (s *sAdminMember) LoginMemberInfo(ctx context.Context, req *member.InfoReq) (res *adminin.MemberLoginModel, err error) {
|
||||
identity := contexts.Get(ctx).User
|
||||
if identity == nil {
|
||||
func (s *sAdminMember) LoginMemberInfo(ctx context.Context) (res *adminin.LoginMemberInfoModel, err error) {
|
||||
var memberId = contexts.GetUserId(ctx)
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("用户身份异常,请重新登录!")
|
||||
return
|
||||
}
|
||||
|
||||
permissions, err := service.AdminMenu().LoginPermissions(ctx, identity.Id)
|
||||
err = dao.AdminMember.Ctx(ctx).
|
||||
Hook(hook.MemberInfo).
|
||||
Where("id", memberId).
|
||||
Scan(&res)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
|
||||
res = &adminin.MemberLoginModel{
|
||||
UserId: identity.Id,
|
||||
Username: identity.Username,
|
||||
RealName: identity.RealName,
|
||||
Avatar: identity.Avatar,
|
||||
Permissions: permissions,
|
||||
Token: jwt.GetAuthorization(ghttp.RequestFromCtx(ctx)),
|
||||
if res == nil {
|
||||
err = gerror.New("用户不存在!")
|
||||
return
|
||||
}
|
||||
|
||||
// 细粒度权限
|
||||
permissions, err := service.AdminMenu().LoginPermissions(ctx, memberId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res.Permissions = permissions
|
||||
|
||||
// 登录统计
|
||||
stat, err := s.MemberLoginStat(ctx, adminin.MemberLoginStatInp{MemberId: memberId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res.MemberLoginStatModel = stat
|
||||
|
||||
res.Mobile = gstr.HideStr(res.Mobile, 40, `*`)
|
||||
res.Email = gstr.HideStr(res.Email, 40, `*`)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -443,11 +588,7 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
|
||||
var (
|
||||
roleInfo *entity.AdminRole
|
||||
memberInfo *entity.AdminMember
|
||||
identity *model.Identity
|
||||
timestamp = gtime.Timestamp()
|
||||
expires = g.Cfg().MustGet(ctx, "jwt.expires", 1).Int64()
|
||||
exp = gconv.Int64(timestamp) + expires
|
||||
lastIp = location.GetClientIp(ghttp.RequestFromCtx(ctx))
|
||||
)
|
||||
|
||||
err = dao.AdminMember.Ctx(ctx).Where("username", in.Username).Scan(&memberInfo)
|
||||
@@ -465,18 +606,13 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
|
||||
return
|
||||
}
|
||||
|
||||
// 解密密码
|
||||
password, err := gbase64.Decode([]byte(in.Password))
|
||||
err = simple.CheckPassword(in.Password, memberInfo.Salt, memberInfo.PasswordHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
password, err = encrypt.AesECBDecrypt(password, consts.RequestEncryptKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
if memberInfo.PasswordHash != gmd5.MustEncryptString(string(password)+memberInfo.Salt) {
|
||||
err = gerror.New("用户密码不正确")
|
||||
if memberInfo.Status != consts.StatusEnabled {
|
||||
err = gerror.New("账号已被禁用")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -494,27 +630,24 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
|
||||
}
|
||||
|
||||
if roleInfo.Status != consts.StatusEnabled {
|
||||
err = gerror.New("角色权限已被禁用")
|
||||
err = gerror.New("角色已被禁用")
|
||||
return
|
||||
}
|
||||
|
||||
identity = &model.Identity{
|
||||
Id: memberInfo.Id,
|
||||
Pid: memberInfo.Pid,
|
||||
DeptId: memberInfo.DeptId,
|
||||
RoleId: roleInfo.Id,
|
||||
RoleKey: roleInfo.Key,
|
||||
Username: memberInfo.Username,
|
||||
RealName: memberInfo.RealName,
|
||||
Avatar: memberInfo.Avatar,
|
||||
Email: memberInfo.Email,
|
||||
Mobile: memberInfo.Mobile,
|
||||
VisitCount: memberInfo.VisitCount,
|
||||
LastTime: memberInfo.LastTime,
|
||||
LastIp: lastIp,
|
||||
Exp: exp,
|
||||
Expires: expires,
|
||||
App: consts.AppAdmin,
|
||||
identity := &model.Identity{
|
||||
Id: memberInfo.Id,
|
||||
Pid: memberInfo.Pid,
|
||||
DeptId: memberInfo.DeptId,
|
||||
RoleId: roleInfo.Id,
|
||||
RoleKey: roleInfo.Key,
|
||||
Username: memberInfo.Username,
|
||||
RealName: memberInfo.RealName,
|
||||
Avatar: memberInfo.Avatar,
|
||||
Email: memberInfo.Email,
|
||||
Mobile: memberInfo.Mobile,
|
||||
Exp: gtime.Timestamp() + expires,
|
||||
Expires: expires,
|
||||
App: consts.AppAdmin,
|
||||
}
|
||||
|
||||
token, err := jwt.GenerateLoginToken(ctx, identity, false)
|
||||
@@ -524,14 +657,10 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
|
||||
}
|
||||
|
||||
// 更新登录信息
|
||||
_, err = dao.AdminMember.Ctx(ctx).Data(do.AdminMember{
|
||||
AuthKey: gmd5.MustEncryptString(token),
|
||||
VisitCount: memberInfo.VisitCount + 1,
|
||||
LastTime: timestamp,
|
||||
LastIp: lastIp,
|
||||
}).Where(do.AdminMember{
|
||||
Id: memberInfo.Id,
|
||||
}).Update()
|
||||
_, err = dao.AdminMember.Ctx(ctx).
|
||||
Data(do.AdminMember{AuthKey: gmd5.MustEncryptString(token)}).
|
||||
Where(do.AdminMember{Id: memberInfo.Id}).
|
||||
Update()
|
||||
|
||||
if err != nil {
|
||||
err = gerror.New(err.Error())
|
||||
@@ -539,17 +668,15 @@ func (s *sAdminMember) Login(ctx context.Context, in adminin.MemberLoginInp) (re
|
||||
}
|
||||
|
||||
res = &adminin.MemberLoginModel{
|
||||
UserId: identity.Id,
|
||||
Username: identity.Username,
|
||||
RealName: identity.RealName,
|
||||
Avatar: identity.Avatar,
|
||||
Token: token,
|
||||
Id: identity.Id,
|
||||
Token: token,
|
||||
Expires: expires,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// RoleMemberList 获取角色下的会员列表
|
||||
// RoleMemberList 获取角色下的用户列表
|
||||
func (s *sAdminMember) RoleMemberList(ctx context.Context, in adminin.RoleMemberListInp) (list []*adminin.MemberListModel, totalCount int, err error) {
|
||||
mod := dao.AdminMember.Ctx(ctx)
|
||||
if in.Role > 0 {
|
||||
@@ -594,7 +721,7 @@ func (s *sAdminMember) Status(ctx context.Context, in adminin.MemberStatusInp) (
|
||||
|
||||
// 修改
|
||||
in.UpdatedAt = gtime.Now()
|
||||
_, err = dao.AdminMember.Ctx(ctx).Where("id", in.Id).Data("status", in.Status).Update()
|
||||
_, err = s.FilterAuthModel(ctx, contexts.GetUserId(ctx)).Where("id", in.Id).Data("status", in.Status).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
@@ -603,7 +730,7 @@ func (s *sAdminMember) Status(ctx context.Context, in adminin.MemberStatusInp) (
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetIdByCode 通过邀请码获取会员ID
|
||||
// GetIdByCode 通过邀请码获取用户ID
|
||||
func (s *sAdminMember) GetIdByCode(ctx context.Context, in adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) {
|
||||
if err = dao.AdminMember.Ctx(ctx).
|
||||
Fields("invite_code").
|
||||
@@ -615,3 +742,53 @@ func (s *sAdminMember) GetIdByCode(ctx context.Context, in adminin.GetIdByCodeIn
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Select 获取可选的用户选项
|
||||
func (s *sAdminMember) Select(ctx context.Context, in adminin.MemberSelectInp) (res []*adminin.MemberSelectModel, err error) {
|
||||
err = dao.AdminMember.Ctx(ctx).
|
||||
Fields("id as value,real_name as label,username,avatar").
|
||||
Handler(handler.FilterAuthWithField("id")).
|
||||
Scan(&res)
|
||||
if err != nil {
|
||||
return nil, gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *sAdminMember) FilterAuthModel(ctx context.Context, memberId int64) *gdb.Model {
|
||||
m := dao.AdminMember.Ctx(ctx)
|
||||
if !s.VerifySuperId(ctx, memberId) {
|
||||
m = m.Where("id <> ?", memberId)
|
||||
}
|
||||
return m.Handler(handler.FilterAuthWithField("id"))
|
||||
}
|
||||
|
||||
// MemberLoginStat 用户登录统计
|
||||
func (s *sAdminMember) MemberLoginStat(ctx context.Context, in adminin.MemberLoginStatInp) (res *adminin.MemberLoginStatModel, err error) {
|
||||
var models *entity.SysLoginLog
|
||||
err = dao.SysLoginLog.Ctx(ctx).
|
||||
Fields("login_at,login_ip").
|
||||
Where("member_id", in.MemberId).
|
||||
Where("status", consts.StatusEnabled).
|
||||
Scan(&models)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = new(adminin.MemberLoginStatModel)
|
||||
if models == nil {
|
||||
return
|
||||
}
|
||||
|
||||
res.LastLoginAt = models.LoginAt
|
||||
res.LastLoginIp = models.LoginIp
|
||||
|
||||
res.LoginCount, err = dao.SysLoginLog.Ctx(ctx).
|
||||
Where("member_id", in.MemberId).
|
||||
Where("status", consts.StatusEnabled).Count()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ func (s *sAdminMemberPost) UpdatePostIds(ctx context.Context, member_id int64, p
|
||||
PostId: post_ids[i],
|
||||
})
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "插入会员岗位失败")
|
||||
err = gerror.Wrap(err, "插入用户岗位失败")
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (s *sAdminMemberPost) UpdatePostIds(ctx context.Context, member_id int64, p
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetMemberByIds 获取指定会员的岗位ids
|
||||
// GetMemberByIds 获取指定用户的岗位ids
|
||||
func (s *sAdminMemberPost) GetMemberByIds(ctx context.Context, member_id int64) (post_ids []int64, err error) {
|
||||
var list []*entity.AdminMemberPost
|
||||
err = dao.AdminMemberPost.Ctx(ctx).
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/adminin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/convert"
|
||||
"hotgo/utility/tree"
|
||||
)
|
||||
|
||||
@@ -369,13 +370,8 @@ func (s *sAdminMenu) GetMenuList(ctx context.Context, memberId int64) (lists rol
|
||||
return
|
||||
}
|
||||
|
||||
// LoginPermissions 获取登录成功后的细分权限
|
||||
func (s *sAdminMenu) LoginPermissions(ctx context.Context, memberId int64) (lists []*adminin.MemberLoginPermissions, err error) {
|
||||
// 空跑
|
||||
lists = append(lists, &adminin.MemberLoginPermissions{
|
||||
Value: "value",
|
||||
})
|
||||
|
||||
// LoginPermissions 获取登录成功后的细粒度权限
|
||||
func (s *sAdminMenu) LoginPermissions(ctx context.Context, memberId int64) (lists adminin.MemberLoginPermissions, err error) {
|
||||
type Permissions struct {
|
||||
Permissions string `json:"permissions"`
|
||||
}
|
||||
@@ -401,17 +397,18 @@ func (s *sAdminMenu) LoginPermissions(ctx context.Context, memberId int64) (list
|
||||
return lists, err
|
||||
}
|
||||
|
||||
// 无权限
|
||||
if len(allPermissions) == 0 {
|
||||
lists = append(lists, "value")
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range allPermissions {
|
||||
for _, p := range gstr.Explode(`,`, v.Permissions) {
|
||||
lists = append(lists, &adminin.MemberLoginPermissions{
|
||||
Value: p,
|
||||
})
|
||||
lists = append(lists, p)
|
||||
}
|
||||
}
|
||||
|
||||
lists = convert.UniqueSliceString(lists)
|
||||
return
|
||||
}
|
||||
|
@@ -8,17 +8,22 @@ package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/adminin"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/internal/websocket"
|
||||
"hotgo/utility/charset"
|
||||
"hotgo/utility/simple"
|
||||
"hotgo/utility/validate"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type sAdminNotice struct{}
|
||||
@@ -31,9 +36,14 @@ func init() {
|
||||
service.RegisterAdminNotice(NewAdminNotice())
|
||||
}
|
||||
|
||||
// Model Orm模型
|
||||
func (s *sAdminNotice) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
return handler.Model(dao.AdminNotice.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
func (s *sAdminNotice) Delete(ctx context.Context, in adminin.NoticeDeleteInp) error {
|
||||
_, err := dao.AdminNotice.Ctx(ctx).Where("id", in.Id).Delete()
|
||||
_, err := s.Model(ctx).Where("id", in.Id).Delete()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
@@ -44,44 +54,64 @@ func (s *sAdminNotice) Delete(ctx context.Context, in adminin.NoticeDeleteInp) e
|
||||
|
||||
// Edit 修改/新增
|
||||
func (s *sAdminNotice) Edit(ctx context.Context, in adminin.NoticeEditInp) (err error) {
|
||||
var member = contexts.Get(ctx).User
|
||||
if member == nil {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
|
||||
if in.Title == "" {
|
||||
err = gerror.New("标题不能为空")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
if in.Type == consts.NoticeTypeLetter && len(in.Receiver) == 0 {
|
||||
err = gerror.New("私信类型必须选择接收人")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查选项接收人是否合法
|
||||
if in.Type == consts.NoticeTypeLetter {
|
||||
count, _ := dao.AdminMember.Ctx(ctx).Handler(handler.FilterAuthWithField("id")).WhereIn("id", in.Receiver).Count()
|
||||
if count != len(in.Receiver) {
|
||||
err = gerror.New("接收人不合法")
|
||||
return
|
||||
}
|
||||
in.SenderAvatar = member.Avatar
|
||||
}
|
||||
|
||||
// 修改
|
||||
in.UpdatedAt = gtime.Now()
|
||||
if in.Id > 0 {
|
||||
_, err = dao.AdminNotice.Ctx(ctx).Where("id", in.Id).Data(in).Update()
|
||||
in.UpdatedBy = member.Id
|
||||
_, err = s.Model(ctx).Where("id", in.Id).Data(in).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 新增
|
||||
in.CreatedBy = member.Id
|
||||
in.CreatedAt = gtime.Now()
|
||||
_, err = dao.AdminNotice.Ctx(ctx).Data(in).Insert()
|
||||
in.Id, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).InsertAndGetId()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
// 推送通知
|
||||
memberIds := charset.SplitMemberIds(in.Receiver, ",")
|
||||
response := &websocket.WResponse{
|
||||
Event: "notice",
|
||||
Data: in,
|
||||
}
|
||||
simple.SafeGo(ctx, func(ctx context.Context) {
|
||||
if len(memberIds) == 0 {
|
||||
websocket.SendToAll(response)
|
||||
} else {
|
||||
for _, memberId := range memberIds {
|
||||
websocket.SendToUser(memberId, response)
|
||||
if in.Type == consts.NoticeTypeLetter {
|
||||
for _, receiverId := range in.Receiver {
|
||||
websocket.SendToUser(receiverId, response)
|
||||
}
|
||||
} else {
|
||||
websocket.SendToAll(response)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -106,8 +136,7 @@ func (s *sAdminNotice) Status(ctx context.Context, in adminin.NoticeStatusInp) (
|
||||
}
|
||||
|
||||
// 修改
|
||||
in.UpdatedAt = gtime.Now()
|
||||
_, err = dao.AdminNotice.Ctx(ctx).Where("id", in.Id).Data("status", in.Status).Update()
|
||||
_, err = s.Model(ctx).Where("id", in.Id).Data("status", in.Status).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
@@ -119,19 +148,17 @@ func (s *sAdminNotice) Status(ctx context.Context, in adminin.NoticeStatusInp) (
|
||||
// MaxSort 最大排序
|
||||
func (s *sAdminNotice) MaxSort(ctx context.Context, in adminin.NoticeMaxSortInp) (*adminin.NoticeMaxSortModel, error) {
|
||||
var res adminin.NoticeMaxSortModel
|
||||
if in.Id > 0 {
|
||||
if err := dao.AdminNotice.Ctx(ctx).Where("id", in.Id).Order("sort desc").Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
if err := s.Model(ctx).Order("sort desc").Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
res.Sort = res.Sort + 10
|
||||
res.Sort = form.DefaultMaxSort(ctx, res.Sort)
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// View 获取指定字典类型信息
|
||||
func (s *sAdminNotice) View(ctx context.Context, in adminin.NoticeViewInp) (res *adminin.NoticeViewModel, err error) {
|
||||
if err = dao.AdminNotice.Ctx(ctx).Where("id", in.Id).Scan(&res); err != nil {
|
||||
if err = s.Model(ctx).Where("id", in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
@@ -141,19 +168,26 @@ func (s *sAdminNotice) View(ctx context.Context, in adminin.NoticeViewInp) (res
|
||||
|
||||
// List 获取列表
|
||||
func (s *sAdminNotice) List(ctx context.Context, in adminin.NoticeListInp) (list []*adminin.NoticeListModel, totalCount int, err error) {
|
||||
mod := dao.AdminNotice.Ctx(ctx)
|
||||
var memberId = contexts.GetUserId(ctx)
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
|
||||
mod := s.Model(ctx)
|
||||
|
||||
// 访问路径
|
||||
if in.Title != "" {
|
||||
mod = mod.WhereLike("title", "%"+in.Title+"%")
|
||||
}
|
||||
|
||||
// 模块
|
||||
if in.Content != "" {
|
||||
mod = mod.WhereLike("content", "%"+in.Content+"%")
|
||||
}
|
||||
|
||||
// 请求方式
|
||||
if in.Type > 0 {
|
||||
mod = mod.Where("type", in.Type)
|
||||
}
|
||||
|
||||
if in.Status > 0 {
|
||||
mod = mod.Where("status", in.Status)
|
||||
}
|
||||
@@ -173,8 +207,291 @@ func (s *sAdminNotice) List(ctx context.Context, in adminin.NoticeListInp) (list
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
for k, v := range list {
|
||||
list[k].ReceiveNum = len(strings.Split(v.Reader, ","))
|
||||
for _, v := range list {
|
||||
// 接收人头像组
|
||||
if v.Type == consts.NoticeTypeLetter {
|
||||
err = dao.AdminMember.Ctx(ctx).
|
||||
Fields("real_name as name,avatar as src").
|
||||
WhereIn("id", v.Receiver.Var().Int64s()).
|
||||
Scan(&v.ReceiverGroup)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if v.ReceiverGroup == nil || len(v.ReceiverGroup) == 0 {
|
||||
v.ReceiverGroup = make([]form.AvatarGroup, 0)
|
||||
}
|
||||
|
||||
// 阅读次数
|
||||
v.ReadCount, err = dao.AdminNoticeRead.Ctx(ctx).Where("notice_id", v.Id).Sum("clicks")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
// PullMessages 拉取未读消息列表
|
||||
func (s *sAdminNotice) PullMessages(ctx context.Context, in adminin.PullMessagesInp) (res *adminin.PullMessagesModel, err error) {
|
||||
var memberId = contexts.GetUserId(ctx)
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
|
||||
messageIds, err := s.messageIds(ctx, memberId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res = new(adminin.PullMessagesModel)
|
||||
unread, err := s.UnreadCount(ctx, adminin.NoticeUnreadCountInp{MemberId: memberId, MessageIds: messageIds})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if unread != nil {
|
||||
res.NoticeUnreadCountModel = unread
|
||||
}
|
||||
|
||||
if err = s.Model(ctx).WhereIn("id", messageIds).Limit(in.Limit).Order("id desc").Scan(&res.List); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range res.List {
|
||||
count, _ := dao.AdminNoticeRead.Ctx(ctx).Where("notice_id", v.Id).Where("member_id", memberId).Count()
|
||||
if count > 0 {
|
||||
v.IsRead = true
|
||||
}
|
||||
|
||||
if v.Type == consts.NoticeTypeLetter {
|
||||
val, err := dao.AdminMember.Ctx(ctx).Fields("avatar").Where("id", v.CreatedBy).Value()
|
||||
if err == nil {
|
||||
v.SenderAvatar = val.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UnreadCount 获取所有类型消息的未读数量
|
||||
func (s *sAdminNotice) UnreadCount(ctx context.Context, in adminin.NoticeUnreadCountInp) (res *adminin.NoticeUnreadCountModel, err error) {
|
||||
if in.MemberId <= 0 {
|
||||
if in.MemberId = contexts.GetUserId(ctx); in.MemberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(in.MessageIds) == 0 {
|
||||
in.MessageIds, err = s.messageIds(ctx, in.MemberId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(in.MessageIds) == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
stat := func(t int) (count int) {
|
||||
all, err := dao.AdminNotice.Ctx(ctx).As("nr").
|
||||
Where("type =? and id IN(?)", t, in.MessageIds).
|
||||
Count()
|
||||
if err != nil {
|
||||
g.Log().Infof(ctx, "UnreadCount stat err:%+v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if all == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
read, err := dao.AdminNoticeRead.Ctx(ctx).As("nr").
|
||||
LeftJoin("admin_notice n", "nr.notice_id=n.id").
|
||||
Where("n.type = ? and n.id IN(?)", t, in.MessageIds).
|
||||
Where("nr.member_id", in.MemberId).
|
||||
Count()
|
||||
if err != nil {
|
||||
g.Log().Infof(ctx, "UnreadCount stat2 err:%+v", err)
|
||||
return
|
||||
}
|
||||
count = all - read
|
||||
return
|
||||
}
|
||||
|
||||
res = new(adminin.NoticeUnreadCountModel)
|
||||
res.NotifyCount = stat(consts.NoticeTypeNotify)
|
||||
res.NoticeCount = stat(consts.NoticeTypeNotice)
|
||||
res.LetterCount = stat(consts.NoticeTypeLetter)
|
||||
return
|
||||
}
|
||||
|
||||
// messageIds 获取我的消息所有的消息ID
|
||||
func (s *sAdminNotice) messageIds(ctx context.Context, memberId int64) (ids []int64, err error) {
|
||||
mod := s.Model(ctx, &handler.Option{FilterAuth: false}).
|
||||
Fields("id").
|
||||
Where("status", consts.StatusEnabled).
|
||||
Where("(`type` IN(?) OR (`type` = ? and JSON_CONTAINS(`receiver`,'"+gconv.String(memberId)+"')))",
|
||||
[]int{consts.NoticeTypeNotify, consts.NoticeTypeNotice}, consts.NoticeTypeLetter,
|
||||
)
|
||||
|
||||
array, err := mod.Array()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, v := range array {
|
||||
ids = append(ids, v.Int64())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpRead 更新已读
|
||||
func (s *sAdminNotice) UpRead(ctx context.Context, in adminin.NoticeUpReadInp) (err error) {
|
||||
var (
|
||||
data *entity.AdminNotice
|
||||
memberId = contexts.GetUserId(ctx)
|
||||
)
|
||||
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
if err = dao.AdminNotice.Ctx(ctx).Where("id", in.Id).Scan(&data); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
if data == nil {
|
||||
return gerror.New("公告不存在")
|
||||
}
|
||||
|
||||
return s.updatedReadClicks(ctx, in.Id, memberId)
|
||||
}
|
||||
|
||||
// ReadAll 已读全部
|
||||
func (s *sAdminNotice) ReadAll(ctx context.Context, in adminin.NoticeReadAllInp) (err error) {
|
||||
var memberId = contexts.GetUserId(ctx)
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
|
||||
allMessageIds, err := s.messageIds(ctx, memberId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(allMessageIds) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
array, err := dao.AdminNotice.Ctx(ctx).
|
||||
Fields("id").
|
||||
Where("type = ? and id IN(?)", in.Type, allMessageIds).
|
||||
Array()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var messageIds []int64
|
||||
for _, v := range array {
|
||||
messageIds = append(messageIds, v.Int64())
|
||||
}
|
||||
|
||||
array, err = dao.AdminNoticeRead.Ctx(ctx).As("nr").
|
||||
Fields("nr.notice_id").
|
||||
LeftJoin("admin_notice n", "nr.notice_id=n.id").
|
||||
Where("n.type = ? and n.id IN(?)", in.Type, messageIds).
|
||||
Where("nr.member_id", memberId).
|
||||
Array()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var readIds []int64
|
||||
for _, v := range array {
|
||||
readIds = append(readIds, v.Int64())
|
||||
}
|
||||
|
||||
for _, messageId := range messageIds {
|
||||
if !validate.InSliceInt64(readIds, messageId) {
|
||||
if err = s.updatedReadClicks(ctx, messageId, memberId); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// updatedReadClicks 更新公告已读次数
|
||||
func (s *sAdminNotice) updatedReadClicks(ctx context.Context, noticeId, memberId int64) (err error) {
|
||||
var (
|
||||
models *entity.AdminNoticeRead
|
||||
)
|
||||
err = dao.AdminNoticeRead.Ctx(ctx).
|
||||
Where(dao.AdminNoticeRead.Columns().NoticeId, noticeId).
|
||||
Where(dao.AdminNoticeRead.Columns().MemberId, memberId).
|
||||
Scan(&models)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
_, err = dao.AdminNoticeRead.Ctx(ctx).Data(entity.AdminNoticeRead{NoticeId: noticeId, MemberId: memberId}).Insert()
|
||||
return
|
||||
}
|
||||
_, err = dao.AdminNoticeRead.Ctx(ctx).Where(dao.AdminNoticeRead.Columns().Id, models.Id).Increment("clicks", 1)
|
||||
return
|
||||
}
|
||||
|
||||
// MessageList 我的消息列表
|
||||
func (s *sAdminNotice) MessageList(ctx context.Context, in adminin.NoticeMessageListInp) (list []*adminin.NoticeMessageListModel, totalCount int, err error) {
|
||||
var memberId = contexts.GetUserId(ctx)
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
|
||||
allMessageIds, err := s.messageIds(ctx, memberId)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(allMessageIds) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
mod := s.Model(ctx, &handler.Option{FilterAuth: false}).WhereIn("id", allMessageIds).Where("type", in.Type)
|
||||
totalCount, err = mod.Count()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
if totalCount == 0 {
|
||||
return list, totalCount, nil
|
||||
}
|
||||
|
||||
if err = mod.Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
for _, v := range list {
|
||||
count, _ := dao.AdminNoticeRead.Ctx(ctx).Where("notice_id", v.Id).Where("member_id", memberId).Count()
|
||||
if count > 0 {
|
||||
v.IsRead = true
|
||||
}
|
||||
|
||||
if v.Type == consts.NoticeTypeLetter {
|
||||
val, err := dao.AdminMember.Ctx(ctx).Fields("avatar").Where("id", v.CreatedBy).Value()
|
||||
if err == nil {
|
||||
v.SenderAvatar = val.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ import (
|
||||
"hotgo/utility/convert"
|
||||
"hotgo/utility/tree"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type sAdminRole struct{}
|
||||
@@ -60,7 +61,7 @@ func (s *sAdminRole) Verify(ctx context.Context, path, method string) bool {
|
||||
}
|
||||
ok, err := casbin.Enforcer.Enforce(user.RoleKey, path, method)
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "admin Verify Enforce err:%v", err)
|
||||
g.Log().Warningf(ctx, "admin Verify Enforce err:%+v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -86,6 +87,12 @@ func (s *sAdminRole) List(ctx context.Context, in adminin.RoleListInp) (list []g
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
for _, v := range models {
|
||||
v.Label = v.Name
|
||||
v.Value = v.Id
|
||||
v.Key = strconv.FormatInt(v.Id, 10)
|
||||
}
|
||||
|
||||
return tree.GenTree(gconv.SliceMap(models)), totalCount, err
|
||||
}
|
||||
|
||||
@@ -104,7 +111,7 @@ func (s *sAdminRole) GetName(ctx context.Context, RoleId int64) (name string, er
|
||||
return roleName.String(), nil
|
||||
}
|
||||
|
||||
// GetMemberList 获取指定会员的岗位列表
|
||||
// GetMemberList 获取指定用户的岗位列表
|
||||
func (s *sAdminRole) GetMemberList(ctx context.Context, RoleId int64) (list []*adminin.RoleListModel, err error) {
|
||||
err = dao.AdminRole.Ctx(ctx).
|
||||
Where("id", RoleId).
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/model/input/adminin"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/service"
|
||||
@@ -37,13 +38,13 @@ func init() {
|
||||
}
|
||||
|
||||
// Model Orm模型
|
||||
func (s *sAdminTest) Model(ctx context.Context) *gdb.Model {
|
||||
return dao.Test.Ctx(ctx)
|
||||
func (s *sAdminTest) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
return handler.Model(dao.Test.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
// List 获取列表
|
||||
func (s *sAdminTest) List(ctx context.Context, in adminin.TestListInp) (list []*adminin.TestListModel, totalCount int, err error) {
|
||||
mod := dao.Test.Ctx(ctx)
|
||||
mod := s.Model(ctx)
|
||||
|
||||
if in.Title != "" {
|
||||
mod = mod.WhereLike(dao.Test.Columns().Title, "%"+in.Title+"%")
|
||||
@@ -98,11 +99,11 @@ func (s *sAdminTest) List(ctx context.Context, in adminin.TestListInp) (list []*
|
||||
totalCount, err = mod.Clone().Count(1)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
return
|
||||
}
|
||||
|
||||
if totalCount == 0 {
|
||||
return list, totalCount, nil
|
||||
return
|
||||
}
|
||||
|
||||
////关联表select
|
||||
@@ -113,28 +114,27 @@ func (s *sAdminTest) List(ctx context.Context, in adminin.TestListInp) (list []*
|
||||
|
||||
fields, err := hgorm.GenSelect(ctx, adminin.TestListModel{}, dao.Test)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return
|
||||
}
|
||||
|
||||
if err = mod.Fields(fields).Handler(hgorm.HandlerFilterAuth, hgorm.HandlerForceCache).Page(in.Page, in.PerPage).OrderAsc(dao.Test.Columns().Sort).OrderDesc(dao.Test.Columns().Id).Scan(&list); err != nil {
|
||||
if err = mod.Fields(fields).Handler(handler.FilterAuth, handler.ForceCache).Page(in.Page, in.PerPage).OrderAsc(dao.Test.Columns().Sort).OrderDesc(dao.Test.Columns().Id).Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
return
|
||||
}
|
||||
|
||||
return list, totalCount, err
|
||||
return
|
||||
}
|
||||
|
||||
// Export 导出
|
||||
func (s *sAdminTest) Export(ctx context.Context, in adminin.TestListInp) (err error) {
|
||||
list, totalCount, err := s.List(ctx, in)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
// 字段的排序是依据tags的字段顺序,如果你不想使用默认的排序方式,可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
|
||||
tags, err := convert.GetEntityDescTags(adminin.TestExportModel{})
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -143,10 +143,10 @@ func (s *sAdminTest) Export(ctx context.Context, in adminin.TestListInp) (err er
|
||||
exports []adminin.TestExportModel
|
||||
)
|
||||
|
||||
err = gconv.Scan(list, &exports)
|
||||
if err != nil {
|
||||
return err
|
||||
if err = gconv.Scan(list, &exports); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName); err != nil {
|
||||
return
|
||||
}
|
||||
@@ -156,70 +156,51 @@ func (s *sAdminTest) Export(ctx context.Context, in adminin.TestListInp) (err er
|
||||
// Edit 修改/新增
|
||||
func (s *sAdminTest) Edit(ctx context.Context, in adminin.TestEditInp) (err error) {
|
||||
if err = hgorm.IsUnique(ctx, dao.Test, g.Map{dao.Test.Columns().Qq: in.Qq}, "QQ号码已存在,请换一个", in.Id); err != nil {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 修改
|
||||
if in.Id > 0 {
|
||||
in.UpdatedBy = contexts.GetUserId(ctx)
|
||||
_, err = dao.Test.Ctx(ctx).Where(dao.Test.Columns().Id, in.Id).Data(in).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx).Where(dao.Test.Columns().Id, in.Id).Data(in).Update()
|
||||
return
|
||||
}
|
||||
|
||||
// 新增
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
_, err = dao.Test.Ctx(ctx).Data(in).Insert()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).Insert()
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
func (s *sAdminTest) Delete(ctx context.Context, in adminin.TestDeleteInp) (err error) {
|
||||
_, err = dao.Test.Ctx(ctx).Where(dao.Test.Columns().Id, in.Id).Delete()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx).Where(dao.Test.Columns().Id, in.Id).Delete()
|
||||
return
|
||||
}
|
||||
|
||||
// Status 更新状态
|
||||
func (s *sAdminTest) Status(ctx context.Context, in adminin.TestStatusInp) (err error) {
|
||||
if in.Id <= 0 {
|
||||
err = gerror.New("ID不能为空")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
if in.Status <= 0 {
|
||||
err = gerror.New("状态不能为空")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
if !validate.InSliceInt(consts.StatusMap, in.Status) {
|
||||
err = gerror.New("状态不正确")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
// 修改
|
||||
_, err = dao.Test.Ctx(ctx).Where(dao.Test.Columns().Id, in.Id).Data(dao.Test.Columns().Status, in.Status).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx).Where(dao.Test.Columns().Id, in.Id).Data(g.Map{
|
||||
dao.Test.Columns().Status: in.Status,
|
||||
dao.Test.Columns().UpdatedBy: contexts.GetUserId(ctx),
|
||||
}).Update()
|
||||
return
|
||||
}
|
||||
|
||||
// Switch 更新开关状态
|
||||
@@ -231,36 +212,34 @@ func (s *sAdminTest) Switch(ctx context.Context, in adminin.TestSwitchInp) (err
|
||||
|
||||
if !validate.InSliceString(fields, in.Key) {
|
||||
err = gerror.New("开关键名不在白名单")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
// 修改
|
||||
_, err = dao.Test.Ctx(ctx).Where(dao.Test.Columns().Id, in.Id).Data(in.Key, in.Value).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx).Where(dao.Test.Columns().Id, in.Id).Data(g.Map{
|
||||
in.Key: in.Value,
|
||||
dao.Test.Columns().UpdatedBy: contexts.GetUserId(ctx),
|
||||
}).Update()
|
||||
return
|
||||
}
|
||||
|
||||
// MaxSort 最大排序
|
||||
func (s *sAdminTest) MaxSort(ctx context.Context, in adminin.TestMaxSortInp) (res *adminin.TestMaxSortModel, err error) {
|
||||
if err = dao.Test.Ctx(ctx).Fields(dao.Test.Columns().Sort).OrderDesc(dao.Test.Columns().Sort).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
res.Sort = res.Sort + g.Cfg().MustGet(ctx, "hotgo.admin.maxSortIncrement").Int()
|
||||
return res, nil
|
||||
if res == nil {
|
||||
res = new(adminin.TestMaxSortModel)
|
||||
}
|
||||
|
||||
res.Sort = form.DefaultMaxSort(ctx, res.Sort)
|
||||
return
|
||||
}
|
||||
|
||||
// View 获取指定字典类型信息
|
||||
func (s *sAdminTest) View(ctx context.Context, in adminin.TestViewInp) (res *adminin.TestViewModel, err error) {
|
||||
if err = dao.Test.Ctx(ctx).Where(dao.Test.Columns().Id, in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
err = s.Model(ctx).Where(dao.Test.Columns().Id, in.Id).Scan(&res)
|
||||
return
|
||||
}
|
||||
|
@@ -205,8 +205,6 @@ func (s *sCommonUpload) UploadUCloud(ctx context.Context, conf *model.UploadConf
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g.Log().Warningf(ctx, "ras:%+v", string(req.LastResponseBody))
|
||||
|
||||
attachment, err := service.SysAttachment().Add(ctx, meta, fullPath, consts.UploadDriveUCloud)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -14,8 +14,8 @@ import (
|
||||
"hotgo/internal/service"
|
||||
)
|
||||
|
||||
// GlobalLog 访问日志
|
||||
func (s *sHook) GlobalLog(r *ghttp.Request) {
|
||||
// AccessLog 访问日志
|
||||
func (s *sHook) AccessLog(r *ghttp.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
)
|
||||
@@ -31,7 +31,7 @@ func (s *sHook) GlobalLog(r *ghttp.Request) {
|
||||
|
||||
go func() {
|
||||
if err := service.SysLog().AutoLog(ctx); err != nil {
|
||||
g.Log().Info(ctx, "GlobalLog AutoLog err:", err)
|
||||
g.Log().Info(ctx, "hook AccessLog err:", err)
|
||||
}
|
||||
}()
|
||||
}
|
80
server/internal/logic/hook/last_active.go
Normal file
80
server/internal/logic/hook/last_active.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package hook
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/os/gtimer"
|
||||
"hotgo/internal/library/contexts"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type visitor struct {
|
||||
lastSeen *gtime.Time
|
||||
}
|
||||
|
||||
var (
|
||||
visitors = make(map[int64]*visitor)
|
||||
mtx sync.Mutex
|
||||
)
|
||||
|
||||
// Run a background goroutine to remove old entries from the visitors map.
|
||||
func init() {
|
||||
go cleanupVisitors()
|
||||
}
|
||||
|
||||
// Every minute check the map for visitors that haven't been seen for
|
||||
// more than 3 minutes and delete the entries.
|
||||
func cleanupVisitors() {
|
||||
gtimer.AddSingleton(gctx.New(), time.Minute, func(ctx context.Context) {
|
||||
mtx.Lock()
|
||||
for memberId, v := range visitors {
|
||||
if gtime.Now().Sub(v.lastSeen) > 3*time.Minute {
|
||||
delete(visitors, memberId)
|
||||
}
|
||||
}
|
||||
mtx.Unlock()
|
||||
})
|
||||
}
|
||||
|
||||
func allow(memberId int64) bool {
|
||||
mtx.Lock()
|
||||
defer mtx.Unlock()
|
||||
v, exists := visitors[memberId]
|
||||
if !exists {
|
||||
visitors[memberId] = &visitor{gtime.Now()}
|
||||
return true
|
||||
}
|
||||
|
||||
if gtime.Now().Sub(v.lastSeen) > time.Second*3 {
|
||||
v.lastSeen = gtime.Now()
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// LastActive 更新用户最后活跃
|
||||
func (s *sHook) LastActive(r *ghttp.Request) {
|
||||
var (
|
||||
ctx = r.Context()
|
||||
memberId = contexts.GetUserId(ctx)
|
||||
)
|
||||
|
||||
if memberId == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if allow(memberId) {
|
||||
_, err := g.Model("admin_member").Ctx(ctx).
|
||||
Where("id", memberId).
|
||||
Data(g.Map{"last_active_at": gtime.Now()}).
|
||||
Update()
|
||||
if err != nil {
|
||||
g.Log().Warningf(ctx, "hook LastActive err:%+v, memberId:%v", err, memberId)
|
||||
}
|
||||
}
|
||||
}
|
@@ -42,7 +42,7 @@ func (s *sMiddleware) AdminAuth(r *ghttp.Request) {
|
||||
|
||||
// 验证路由访问权限
|
||||
if !service.AdminRole().Verify(ctx, path, r.Method) {
|
||||
g.Log().Warningf(ctx, "AdminAuth fail path:%+v, GetRoleKey:%+v, r.Method:%+v", path, contexts.GetRoleKey(ctx), r.Method)
|
||||
g.Log().Debugf(ctx, "AdminAuth fail path:%+v, GetRoleKey:%+v, r.Method:%+v", path, contexts.GetRoleKey(ctx), r.Method)
|
||||
response.JsonExit(r, gcode.CodeSecurityReason.Code(), "你没有访问权限!")
|
||||
return
|
||||
}
|
||||
|
@@ -151,22 +151,19 @@ func inspectAuth(r *ghttp.Request, appName string) error {
|
||||
// 保存到上下文
|
||||
if user != nil {
|
||||
customCtx.User = &model.Identity{
|
||||
Id: user.Id,
|
||||
Pid: user.Pid,
|
||||
DeptId: user.DeptId,
|
||||
RoleId: user.RoleId,
|
||||
RoleKey: user.RoleKey,
|
||||
Username: user.Username,
|
||||
RealName: user.RealName,
|
||||
Avatar: user.Avatar,
|
||||
Email: user.Email,
|
||||
Mobile: user.Mobile,
|
||||
VisitCount: user.VisitCount,
|
||||
LastTime: user.LastTime,
|
||||
LastIp: user.LastIp,
|
||||
Exp: user.Exp,
|
||||
Expires: user.Expires,
|
||||
App: user.App,
|
||||
Id: user.Id,
|
||||
Pid: user.Pid,
|
||||
DeptId: user.DeptId,
|
||||
RoleId: user.RoleId,
|
||||
RoleKey: user.RoleKey,
|
||||
Username: user.Username,
|
||||
RealName: user.RealName,
|
||||
Avatar: user.Avatar,
|
||||
Email: user.Email,
|
||||
Mobile: user.Mobile,
|
||||
Exp: user.Exp,
|
||||
Expires: user.Expires,
|
||||
App: user.App,
|
||||
}
|
||||
}
|
||||
contexts.SetUser(ctx, customCtx.User)
|
||||
|
36
server/internal/logic/middleware/limit_develop.go
Normal file
36
server/internal/logic/middleware/limit_develop.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"hotgo/internal/library/location"
|
||||
"hotgo/internal/library/response"
|
||||
)
|
||||
|
||||
// Develop 开发工具白名单过滤
|
||||
func (s *sMiddleware) Develop(r *ghttp.Request) {
|
||||
ips := g.Cfg().MustGet(r.Context(), "hggen.allowedIPs").Strings()
|
||||
if len(ips) == 0 {
|
||||
response.JsonExit(r, gcode.CodeNotSupported.Code(), "请配置生成白名单!")
|
||||
}
|
||||
|
||||
if !gstr.InArray(ips, "*") {
|
||||
cuIp := location.GetClientIp(r)
|
||||
ok := false
|
||||
for _, ip := range ips {
|
||||
if ip == cuIp {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
response.JsonExit(r, gcode.CodeNotSupported.Code(), fmt.Sprintf("当前IP[%s]没有配置生成白名单!", cuIp))
|
||||
}
|
||||
}
|
||||
|
||||
r.Middleware.Next()
|
||||
}
|
@@ -96,6 +96,19 @@ func (s *sSysConfig) GetSmtp(ctx context.Context) (conf *model.EmailConfig, err
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
// GetBasic 获取基础配置
|
||||
func (s *sSysConfig) GetBasic(ctx context.Context) (conf *model.BasicConfig, err error) {
|
||||
models, err := s.GetConfigByGroup(ctx, sysin.GetConfigInp{Group: "basic"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = gconv.Struct(models.List, &conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
// GetLoadSSL 获取本地日志配置
|
||||
func (s *sSysConfig) GetLoadSSL(ctx context.Context) (conf *model.SSLConfig, err error) {
|
||||
if err = g.Cfg().MustGet(ctx, "hotgo.ssl").Struct(&conf); err != nil {
|
||||
|
@@ -8,14 +8,15 @@ package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/crons"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/validate"
|
||||
@@ -33,10 +34,7 @@ func init() {
|
||||
}
|
||||
|
||||
func (s *sSysCron) StartCron(ctx context.Context) {
|
||||
var (
|
||||
list []*entity.SysCron
|
||||
)
|
||||
|
||||
var list []*entity.SysCron
|
||||
if err := dao.SysCron.Ctx(ctx).
|
||||
Where("status", consts.StatusEnabled).
|
||||
Order("sort asc,id desc").
|
||||
@@ -49,17 +47,30 @@ func (s *sSysCron) StartCron(ctx context.Context) {
|
||||
g.Log().Fatalf(ctx, "定时任务启动失败, err . %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
func (s *sSysCron) Delete(ctx context.Context, in sysin.CronDeleteInp) error {
|
||||
_, err := dao.SysCron.Ctx(ctx).Where("id", in.Id).Delete()
|
||||
if err != nil {
|
||||
func (s *sSysCron) Delete(ctx context.Context, in sysin.CronDeleteInp) (err error) {
|
||||
var models *entity.SysCron
|
||||
if err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Scan(&models); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
err = gerror.New("定时任务不存在或已被删除")
|
||||
return
|
||||
}
|
||||
|
||||
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
_, err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Delete()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return crons.Delete(models)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -67,34 +78,30 @@ func (s *sSysCron) Delete(ctx context.Context, in sysin.CronDeleteInp) error {
|
||||
func (s *sSysCron) Edit(ctx context.Context, in sysin.CronEditInp) (err error) {
|
||||
if in.Name == "" {
|
||||
err = gerror.New("标题不能为空")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
// 修改
|
||||
in.UpdatedAt = gtime.Now()
|
||||
if in.Id > 0 {
|
||||
_, err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Data(in).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
_, err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Data(in).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return crons.RefreshStatus(&in.SysCron)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 新增
|
||||
in.CreatedAt = gtime.Now()
|
||||
_, err = dao.SysCron.Ctx(ctx).Data(in).Insert()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
// Status 更新部门状态
|
||||
func (s *sSysCron) Status(ctx context.Context, in sysin.CronStatusInp) (err error) {
|
||||
|
||||
if in.Id <= 0 {
|
||||
err = gerror.New("ID不能为空")
|
||||
return err
|
||||
@@ -110,36 +117,46 @@ func (s *sSysCron) Status(ctx context.Context, in sysin.CronStatusInp) (err erro
|
||||
return err
|
||||
}
|
||||
|
||||
// 修改
|
||||
in.UpdatedAt = gtime.Now()
|
||||
_, err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Data("status", in.Status).Update()
|
||||
if err != nil {
|
||||
var models *entity.SysCron
|
||||
if err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Scan(&models); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
if models == nil {
|
||||
err = gerror.New("定时任务不存在")
|
||||
return
|
||||
}
|
||||
|
||||
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
_, err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Data("status", in.Status).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
models.Status = in.Status
|
||||
return crons.RefreshStatus(models)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// MaxSort 最大排序
|
||||
func (s *sSysCron) MaxSort(ctx context.Context, in sysin.CronMaxSortInp) (*sysin.CronMaxSortModel, error) {
|
||||
var res sysin.CronMaxSortModel
|
||||
|
||||
if in.Id > 0 {
|
||||
if err := dao.SysCron.Ctx(ctx).Where("id", in.Id).Order("sort desc").Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
func (s *sSysCron) MaxSort(ctx context.Context, in sysin.CronMaxSortInp) (res *sysin.CronMaxSortModel, err error) {
|
||||
if err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Order("sort desc").Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
if res == nil {
|
||||
res = new(sysin.CronMaxSortModel)
|
||||
}
|
||||
|
||||
res.Sort = res.Sort + 10
|
||||
|
||||
return &res, nil
|
||||
res.Sort = form.DefaultMaxSort(ctx, res.Sort)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// View 获取指定字典类型信息
|
||||
func (s *sSysCron) View(ctx context.Context, in sysin.CronViewInp) (res *sysin.CronViewModel, err error) {
|
||||
|
||||
if err = dao.SysCron.Ctx(ctx).Where("id", in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
@@ -152,12 +169,10 @@ func (s *sSysCron) View(ctx context.Context, in sysin.CronViewInp) (res *sysin.C
|
||||
func (s *sSysCron) List(ctx context.Context, in sysin.CronListInp) (list []*sysin.CronListModel, totalCount int, err error) {
|
||||
mod := dao.SysCron.Ctx(ctx)
|
||||
|
||||
// 访问路径
|
||||
if in.Name != "" {
|
||||
mod = mod.WhereLike("name", "%"+in.Name+"%")
|
||||
}
|
||||
|
||||
// 请求方式
|
||||
if in.Status > 0 {
|
||||
mod = mod.Where("status", in.Status)
|
||||
}
|
||||
@@ -180,7 +195,6 @@ func (s *sSysCron) List(ctx context.Context, in sysin.CronListInp) (list []*sysi
|
||||
for _, v := range list {
|
||||
v.GroupName, _ = dao.SysCronGroup.GetName(ctx, v.GroupId)
|
||||
}
|
||||
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
@@ -197,6 +211,5 @@ func (s *sSysCron) OnlineExec(ctx context.Context, in sysin.OnlineExecInp) (err
|
||||
}
|
||||
|
||||
newCtx := context.WithValue(gctx.New(), consts.ContextKeyCronArgs, strings.Split(data.Params, consts.CronSplitStr))
|
||||
|
||||
return crons.Once(newCtx, data)
|
||||
}
|
||||
|
@@ -3,8 +3,8 @@
|
||||
// @Copyright Copyright (c) 2023 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
// @AutoGenerate Version 2.1.0
|
||||
// @AutoGenerate Date 2023-01-18 15:19:42
|
||||
// @AutoGenerate Version 2.1.2
|
||||
// @AutoGenerate Date 2023-02-08 17:47:32
|
||||
//
|
||||
package sys
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
@@ -39,14 +40,14 @@ func init() {
|
||||
service.RegisterSysCurdDemo(NewSysCurdDemo())
|
||||
}
|
||||
|
||||
// Model 生成演示Orm模型
|
||||
func (s *sSysCurdDemo) Model(ctx context.Context) *gdb.Model {
|
||||
return dao.SysGenCurdDemo.Ctx(ctx)
|
||||
// Model 生成演示ORM模型
|
||||
func (s *sSysCurdDemo) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
return handler.Model(dao.SysGenCurdDemo.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
// List 获取生成演示列表
|
||||
func (s *sSysCurdDemo) List(ctx context.Context, in sysin.CurdDemoListInp) (list []*sysin.CurdDemoListModel, totalCount int, err error) {
|
||||
mod := dao.SysGenCurdDemo.Ctx(ctx)
|
||||
mod := s.Model(ctx)
|
||||
|
||||
// 查询ID
|
||||
if in.Id > 0 {
|
||||
@@ -77,36 +78,37 @@ func (s *sSysCurdDemo) List(ctx context.Context, in sysin.CurdDemoListInp) (list
|
||||
totalCount, err = mod.Clone().Count(1)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
return
|
||||
}
|
||||
|
||||
if totalCount == 0 {
|
||||
return list, totalCount, nil
|
||||
return
|
||||
}
|
||||
|
||||
//关联表select
|
||||
fields, err := hgorm.GenJoinSelect(ctx, sysin.CurdDemoListModel{}, dao.SysGenCurdDemo, []*hgorm.Join{
|
||||
{Dao: dao.TestCategory, Alias: "testCategory"},
|
||||
})
|
||||
if err = mod.Fields(fields).Handler(hgorm.HandlerFilterAuth).Page(in.Page, in.PerPage).OrderAsc(dao.SysGenCurdDemo.Columns().Sort).OrderDesc(dao.SysGenCurdDemo.Columns().Id).Scan(&list); err != nil {
|
||||
|
||||
if err = mod.Fields(fields).Page(in.Page, in.PerPage).OrderAsc(dao.SysGenCurdDemo.Columns().Sort).OrderDesc(dao.SysGenCurdDemo.Columns().Id).Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
return
|
||||
}
|
||||
|
||||
return list, totalCount, err
|
||||
return
|
||||
}
|
||||
|
||||
// Export 导出生成演示
|
||||
func (s *sSysCurdDemo) Export(ctx context.Context, in sysin.CurdDemoListInp) (err error) {
|
||||
list, totalCount, err := s.List(ctx, in)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
// 字段的排序是依据tags的字段顺序,如果你不想使用默认的排序方式,可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
|
||||
tags, err := convert.GetEntityDescTags(sysin.CurdDemoExportModel{})
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -115,13 +117,11 @@ func (s *sSysCurdDemo) Export(ctx context.Context, in sysin.CurdDemoListInp) (er
|
||||
exports []sysin.CurdDemoExportModel
|
||||
)
|
||||
|
||||
err = gconv.Scan(list, &exports)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName); err != nil {
|
||||
if err = gconv.Scan(list, &exports); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ func (s *sSysCurdDemo) Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err
|
||||
// 修改
|
||||
if in.Id > 0 {
|
||||
in.UpdatedBy = contexts.GetUserId(ctx)
|
||||
_, err = dao.SysGenCurdDemo.Ctx(ctx).
|
||||
_, err = s.Model(ctx).
|
||||
FieldsEx(
|
||||
dao.SysGenCurdDemo.Columns().Id,
|
||||
dao.SysGenCurdDemo.Columns().CreatedBy,
|
||||
@@ -138,85 +138,70 @@ func (s *sSysCurdDemo) Edit(ctx context.Context, in sysin.CurdDemoEditInp) (err
|
||||
dao.SysGenCurdDemo.Columns().DeletedAt,
|
||||
).
|
||||
Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Data(in).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
// 新增
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
_, err = dao.SysGenCurdDemo.Ctx(ctx).
|
||||
_, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
|
||||
FieldsEx(
|
||||
dao.SysGenCurdDemo.Columns().Id,
|
||||
dao.SysGenCurdDemo.Columns().UpdatedBy,
|
||||
dao.SysGenCurdDemo.Columns().DeletedAt,
|
||||
).
|
||||
Data(in).Insert()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除生成演示
|
||||
func (s *sSysCurdDemo) Delete(ctx context.Context, in sysin.CurdDemoDeleteInp) (err error) {
|
||||
_, err = dao.SysGenCurdDemo.Ctx(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Delete()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Delete()
|
||||
return
|
||||
}
|
||||
|
||||
// MaxSort 获取生成演示最大排序
|
||||
func (s *sSysCurdDemo) MaxSort(ctx context.Context, in sysin.CurdDemoMaxSortInp) (res *sysin.CurdDemoMaxSortModel, err error) {
|
||||
if err = dao.SysGenCurdDemo.Ctx(ctx).Fields(dao.SysGenCurdDemo.Columns().Sort).OrderDesc(dao.SysGenCurdDemo.Columns().Sort).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
return
|
||||
}
|
||||
|
||||
res.Sort = res.Sort + g.Cfg().MustGet(ctx, "hotgo.admin.maxSortIncrement").Int()
|
||||
return res, nil
|
||||
if res == nil {
|
||||
res = new(sysin.CurdDemoMaxSortModel)
|
||||
}
|
||||
|
||||
res.Sort = form.DefaultMaxSort(ctx, res.Sort)
|
||||
return
|
||||
}
|
||||
|
||||
// View 获取生成演示指定信息
|
||||
func (s *sSysCurdDemo) View(ctx context.Context, in sysin.CurdDemoViewInp) (res *sysin.CurdDemoViewModel, err error) {
|
||||
if err = dao.SysGenCurdDemo.Ctx(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
err = s.Model(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Scan(&res)
|
||||
return
|
||||
}
|
||||
|
||||
// Status 更新生成演示状态
|
||||
func (s *sSysCurdDemo) Status(ctx context.Context, in sysin.CurdDemoStatusInp) (err error) {
|
||||
if in.Id <= 0 {
|
||||
err = gerror.New("ID不能为空")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
if in.Status <= 0 {
|
||||
err = gerror.New("状态不能为空")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
if !validate.InSliceInt(consts.StatusMap, in.Status) {
|
||||
err = gerror.New("状态不正确")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
_, err = dao.SysGenCurdDemo.Ctx(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Data(dao.SysGenCurdDemo.Columns().Status, in.Status).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Data(g.Map{
|
||||
dao.SysGenCurdDemo.Columns().Status: in.Status,
|
||||
dao.SysGenCurdDemo.Columns().UpdatedBy: contexts.GetUserId(ctx),
|
||||
}).Update()
|
||||
return
|
||||
}
|
||||
|
||||
// Switch 更新生成演示开关
|
||||
@@ -229,14 +214,12 @@ func (s *sSysCurdDemo) Switch(ctx context.Context, in sysin.CurdDemoSwitchInp) (
|
||||
|
||||
if !validate.InSliceString(fields, in.Key) {
|
||||
err = gerror.New("开关键名不在白名单")
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
_, err = dao.SysGenCurdDemo.Ctx(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Data(in.Key, in.Value).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = s.Model(ctx).Where(dao.SysGenCurdDemo.Columns().Id, in.Id).Data(g.Map{
|
||||
in.Key: in.Value,
|
||||
dao.SysGenCurdDemo.Columns().UpdatedBy: contexts.GetUserId(ctx),
|
||||
}).Update()
|
||||
return
|
||||
}
|
||||
|
443
server/internal/logic/sys/ems_log.go
Normal file
443
server/internal/logic/sys/ems_log.go
Normal file
@@ -0,0 +1,443 @@
|
||||
// Package sys
|
||||
// @Link https://github.com/bufanyun/hotgo
|
||||
// @Copyright Copyright (c) 2022 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
//
|
||||
package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/os/gview"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/ems"
|
||||
"hotgo/internal/library/location"
|
||||
"hotgo/internal/model"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/charset"
|
||||
"hotgo/utility/useragent"
|
||||
"hotgo/utility/validate"
|
||||
"time"
|
||||
)
|
||||
|
||||
type sSysEmsLog struct{}
|
||||
|
||||
func NewSysEmsLog() *sSysEmsLog {
|
||||
return &sSysEmsLog{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterSysEmsLog(NewSysEmsLog())
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
func (s *sSysEmsLog) Delete(ctx context.Context, in sysin.EmsLogDeleteInp) error {
|
||||
_, err := dao.SysEmsLog.Ctx(ctx).Where("id", in.Id).Delete()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Edit 修改/新增
|
||||
func (s *sSysEmsLog) Edit(ctx context.Context, in sysin.EmsLogEditInp) (err error) {
|
||||
if in.Ip == "" {
|
||||
err = gerror.New("ip不能为空")
|
||||
return err
|
||||
}
|
||||
|
||||
// 修改
|
||||
if in.Id > 0 {
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Where("id", in.Id).Data(in).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 新增
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Data(in).Insert()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Status 更新部门状态
|
||||
func (s *sSysEmsLog) Status(ctx context.Context, in sysin.EmsLogStatusInp) (err error) {
|
||||
if in.Id <= 0 {
|
||||
err = gerror.New("ID不能为空")
|
||||
return err
|
||||
}
|
||||
|
||||
if in.Status <= 0 {
|
||||
err = gerror.New("状态不能为空")
|
||||
return err
|
||||
}
|
||||
|
||||
if !validate.InSliceInt(consts.StatusMap, in.Status) {
|
||||
err = gerror.New("状态不正确")
|
||||
return err
|
||||
}
|
||||
|
||||
// 修改
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Where("id", in.Id).Data("status", in.Status).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// View 获取指定字典类型信息
|
||||
func (s *sSysEmsLog) View(ctx context.Context, in sysin.EmsLogViewInp) (res *sysin.EmsLogViewModel, err error) {
|
||||
if err = dao.SysEmsLog.Ctx(ctx).Where("id", in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// List 获取列表
|
||||
func (s *sSysEmsLog) List(ctx context.Context, in sysin.EmsLogListInp) (list []*sysin.EmsLogListModel, totalCount int, err error) {
|
||||
mod := dao.SysEmsLog.Ctx(ctx)
|
||||
|
||||
if in.Status > 0 {
|
||||
mod = mod.Where("status", in.Status)
|
||||
}
|
||||
|
||||
totalCount, err = mod.Count()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
if totalCount == 0 {
|
||||
return list, totalCount, nil
|
||||
}
|
||||
|
||||
if err = mod.Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
// Send 发送邮件
|
||||
func (s *sSysEmsLog) Send(ctx context.Context, in sysin.SendEmsInp) (err error) {
|
||||
var models *entity.SysEmsLog
|
||||
if err = dao.SysEmsLog.Ctx(ctx).Where("event", in.Event).Where("email", in.Email).Scan(&models); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
config, err := service.SysConfig().GetSmtp(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
in.Template, err = s.GetTemplate(ctx, in.Event, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = s.AllowSend(ctx, models, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if consts.IsCodeEmsTemplate(in.Event) && in.Code == "" {
|
||||
in.Code = grand.Digits(4)
|
||||
}
|
||||
|
||||
view, err := s.newView(ctx, in, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in.TplData == nil {
|
||||
in.TplData = make(g.Map)
|
||||
}
|
||||
|
||||
switch in.Event {
|
||||
// 富文本
|
||||
case consts.EmsTemplateText:
|
||||
if in.Content == "" {
|
||||
err = gerror.New("富文本类型邮件内容不能为空")
|
||||
return
|
||||
}
|
||||
in.TplData["content"] = in.Content
|
||||
in.Content, err = view.Parse(ctx, in.Template, in.TplData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 验证码、重置密码类
|
||||
default:
|
||||
in.Content, err = view.Parse(ctx, in.Template, in.TplData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
subject, ok := consts.EmsSubjectMap[in.Event]
|
||||
if !ok {
|
||||
subject = "HotGo"
|
||||
}
|
||||
|
||||
err = ems.Send(config, in.Email, subject, in.Content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var data = new(entity.SysEmsLog)
|
||||
data.Event = in.Event
|
||||
data.Email = in.Email
|
||||
data.Content = in.Content
|
||||
data.Code = in.Code
|
||||
data.Ip = location.GetClientIp(ghttp.RequestFromCtx(ctx))
|
||||
data.Status = consts.EmsStatusNotUsed
|
||||
data.CreatedAt = gtime.Now()
|
||||
data.UpdatedAt = gtime.Now()
|
||||
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Data(data).Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sSysEmsLog) newView(ctx context.Context, in sysin.SendEmsInp, config *model.EmailConfig) (view *gview.View, err error) {
|
||||
view = gview.New()
|
||||
err = view.SetConfig(gview.Config{
|
||||
Delimiters: g.Cfg().MustGet(ctx, "viewer.delimiters").Strings(),
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 富文本为自定义内容,可能不需要变量
|
||||
if in.Event == consts.EmsTemplateText {
|
||||
return
|
||||
}
|
||||
var (
|
||||
username string
|
||||
user = contexts.GetUser(ctx)
|
||||
request = ghttp.RequestFromCtx(ctx)
|
||||
ip = location.GetClientIp(request)
|
||||
)
|
||||
|
||||
loc, err := location.GetLocation(ctx, ip)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if loc == nil {
|
||||
loc = new(location.IpLocationData)
|
||||
}
|
||||
|
||||
cityLabel, err := location.ParseRegion(ctx, loc.ProvinceCode, loc.CityCode, 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
basic, err := service.SysConfig().GetBasic(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if basic == nil {
|
||||
basic = new(model.BasicConfig)
|
||||
basic.Name = "HotGo"
|
||||
basic.Domain = "https://hotgo.facms.cn"
|
||||
basic.Logo = "http://bufanyun.cn-bj.ufileos.com/haoka/attachment/images/2023-02-04/cq9kf7s66jt7hkpvbh.png"
|
||||
basic.SystemOpen = true
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
username = user.Username
|
||||
}
|
||||
|
||||
// 公共变量
|
||||
view.Assigns(gview.Params{
|
||||
"code": in.Code, // 验证码
|
||||
"expires": config.CodeExpire / 60, // 验证码有效期(分钟)
|
||||
"username": username, // 发送者用户名
|
||||
"name": basic.Name, // 网站名称
|
||||
"logo": basic.Logo, // 网站logo
|
||||
"domain": basic.Domain, // 网站域名
|
||||
"github": "https://github.com/bufanyun/hotgo", // github
|
||||
"os": useragent.GetOs(request.Header.Get("User-Agent")), // 发送者操作系统
|
||||
"ip": gstr.HideStr(ip, 30, `*`), // 发送者IP
|
||||
"cityLabel": cityLabel, // IP归属地
|
||||
})
|
||||
|
||||
// 重置密码
|
||||
if in.Event == consts.EmsTemplateResetPwd {
|
||||
var (
|
||||
passwordResetLink string
|
||||
resetToken = charset.RandomCreateBytes(32)
|
||||
)
|
||||
if user != nil {
|
||||
switch user.App {
|
||||
// 后台用户
|
||||
case consts.AppAdmin:
|
||||
_, err = g.Model("admin_member").Ctx(ctx).Where("id", user.Id).Data(g.Map{"password_reset_token": resetToken}).Update()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
passwordResetLink = fmt.Sprintf("%s/admin/passwordReset?token=%s", basic.Domain, resetToken)
|
||||
// 前台用户
|
||||
case consts.AppApi:
|
||||
// ...
|
||||
}
|
||||
}
|
||||
view.Assign("passwordResetLink", passwordResetLink)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetTemplate 获取指定邮件模板
|
||||
func (s *sSysEmsLog) GetTemplate(ctx context.Context, template string, config *model.EmailConfig) (val string, err error) {
|
||||
if template == "" {
|
||||
return "", gerror.New("模板不能为空")
|
||||
}
|
||||
if config == nil {
|
||||
config, err = service.SysConfig().GetSmtp(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if len(config.Template) == 0 {
|
||||
return "", gerror.New("管理员还没有配置任何模板!")
|
||||
}
|
||||
|
||||
for _, v := range config.Template {
|
||||
if v.Key == template {
|
||||
return v.Value, nil
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// AllowSend 是否允许发送
|
||||
func (s *sSysEmsLog) AllowSend(ctx context.Context, models *entity.SysEmsLog, config *model.EmailConfig) (err error) {
|
||||
if models == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 富文本事件不限制
|
||||
if models.Event == consts.EmsTemplateText {
|
||||
return nil
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
config, err = service.SysConfig().GetSmtp(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if gtime.Now().Before(models.CreatedAt.Add(time.Second * time.Duration(config.MinInterval))) {
|
||||
return gerror.New("发送频繁,请稍后再试!")
|
||||
}
|
||||
|
||||
if config.MaxIpLimit > 0 {
|
||||
count, err := dao.SysEmsLog.NowDayCount(ctx, models.Event, models.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count >= config.MaxIpLimit {
|
||||
return gerror.New("今天发送短信过多,请次日后再试!")
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// VerifyCode 效验验证码
|
||||
func (s *sSysEmsLog) VerifyCode(ctx context.Context, in sysin.VerifyEmsCodeInp) (err error) {
|
||||
if in.Event == "" {
|
||||
return gerror.New("事件不能为空")
|
||||
}
|
||||
if in.Email == "" {
|
||||
return gerror.New("邮箱不能为空")
|
||||
}
|
||||
if in.Event == consts.EmsTemplateResetPwd || in.Event == consts.EmsTemplateText {
|
||||
return gerror.Newf("事件类型无需验证:%v", in.Event)
|
||||
}
|
||||
|
||||
config, err := service.SysConfig().GetSmtp(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
models *entity.SysEmsLog
|
||||
)
|
||||
if err = dao.SysEmsLog.Ctx(ctx).Where("event", in.Event).Where("email", in.Email).Order("id desc").Scan(&models); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
return gerror.New("验证码错误")
|
||||
}
|
||||
|
||||
if models.Times >= 10 {
|
||||
return gerror.New("验证码错误次数过多,请重新发送!")
|
||||
}
|
||||
|
||||
if in.Event != consts.EmsTemplateCode {
|
||||
if models.Status == consts.EmsStatusUsed {
|
||||
return gerror.New("验证码已使用,请重新发送!")
|
||||
}
|
||||
}
|
||||
|
||||
if gtime.Now().After(models.CreatedAt.Add(time.Second * time.Duration(config.CodeExpire))) {
|
||||
return gerror.New("验证码已过期,请重新发送")
|
||||
}
|
||||
|
||||
if models.Code != in.Code {
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Where("id", models.Id).Increment("times", 1)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
return gerror.New("验证码错误!")
|
||||
}
|
||||
|
||||
_, err = dao.SysEmsLog.Ctx(ctx).Where("id", models.Id).Data(g.Map{
|
||||
"times": models.Times + 1,
|
||||
"status": consts.EmsStatusUsed,
|
||||
"updated_at": gtime.Now(),
|
||||
}).Update()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
@@ -20,6 +20,7 @@ import (
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm/hook"
|
||||
"hotgo/internal/library/location"
|
||||
"hotgo/internal/library/queue"
|
||||
"hotgo/internal/model/entity"
|
||||
@@ -54,7 +55,7 @@ func (s *sSysLog) Export(ctx context.Context, in sysin.LogListInp) (err error) {
|
||||
ReqId string `json:"req_id" description:"对外id"`
|
||||
TakeUpTime int64 `json:"take_up_time" description:"请求耗时"`
|
||||
CreatedAt *gtime.Time `json:"created_at" description:"创建时间"`
|
||||
MemberName string `json:"member_name"`
|
||||
MemberName string `json:"memberName"`
|
||||
Region string `json:"region"`
|
||||
}
|
||||
|
||||
@@ -222,7 +223,7 @@ func (s *sSysLog) AnalysisLog(ctx context.Context) entity.SysLog {
|
||||
// View 获取指定字典类型信息
|
||||
func (s *sSysLog) View(ctx context.Context, in sysin.LogViewInp) (res *sysin.LogViewModel, err error) {
|
||||
|
||||
if err = dao.SysLog.Ctx(ctx).Where("id", in.Id).Scan(&res); err != nil {
|
||||
if err = dao.SysLog.Ctx(ctx).Hook(hook.CityLabel).Where("id", in.Id).Scan(&res); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -13,12 +13,16 @@ import (
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/library/hgorm/hook"
|
||||
"hotgo/internal/library/location"
|
||||
"hotgo/internal/library/queue"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/form"
|
||||
@@ -89,18 +93,19 @@ func (s *sSysLoginLog) List(ctx context.Context, in sysin.LoginLogListInp) (list
|
||||
{Dao: dao.SysLog, Alias: "sysLog"},
|
||||
})
|
||||
|
||||
if err = mod.Fields(fields).Handler(hgorm.HandlerFilterAuth).Page(in.Page, in.PerPage).OrderDesc(dao.SysLoginLog.Columns().Id).Scan(&list); err != nil {
|
||||
if err = mod.Fields(fields).Hook(hook.CityLabel).Handler(handler.FilterAuth).Page(in.Page, in.PerPage).OrderDesc(dao.SysLoginLog.Columns().Id).Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
||||
for _, v := range list {
|
||||
// 获取省市编码对应的地区名称
|
||||
region, err := dao.SysProvinces.GetRegion(ctx, v.SysLogProvinceId, v.SysLogCityId)
|
||||
if err != nil {
|
||||
return list, totalCount, err
|
||||
}
|
||||
v.Region = region
|
||||
g.DumpWithType(v)
|
||||
//// 获取省市编码对应的地区名称
|
||||
//region, err := location.ParseRegion(ctx, v.SysLogProvinceId, v.SysLogCityId, 0)
|
||||
//if err != nil {
|
||||
// return list, totalCount, err
|
||||
//}
|
||||
//v.Region = region
|
||||
v.Os = useragent.GetOs(v.SysLogUserAgent)
|
||||
v.Browser = useragent.GetBrowser(v.SysLogUserAgent)
|
||||
}
|
||||
@@ -162,9 +167,10 @@ func (s *sSysLoginLog) View(ctx context.Context, in sysin.LoginLogViewInp) (res
|
||||
func (s *sSysLoginLog) Push(ctx context.Context, in sysin.LoginLogPushInp) {
|
||||
var models entity.SysLoginLog
|
||||
models.ReqId = gctx.CtxId(ctx)
|
||||
models.MemberId = in.Response.UserId
|
||||
models.MemberId = in.Response.Id
|
||||
models.Username = in.Input.Username
|
||||
models.LoginAt = gtime.Now()
|
||||
models.LoginIp = location.GetClientIp(ghttp.RequestFromCtx(ctx))
|
||||
models.Status = consts.StatusEnabled
|
||||
|
||||
if in.Err != nil {
|
||||
@@ -173,7 +179,7 @@ func (s *sSysLoginLog) Push(ctx context.Context, in sysin.LoginLogPushInp) {
|
||||
}
|
||||
|
||||
models.Response = gjson.New(consts.NilJsonToString)
|
||||
if in.Response != nil && in.Response.UserId > 0 {
|
||||
if in.Response != nil && in.Response.Id > 0 {
|
||||
models.Response = gjson.New(in.Response)
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@ import (
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/tree"
|
||||
@@ -165,7 +166,7 @@ func (s *sSysProvinces) MaxSort(ctx context.Context, in sysin.ProvincesMaxSortIn
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res.Sort = res.Sort + g.Cfg().MustGet(ctx, "hotgo.admin.maxSortIncrement").Int()
|
||||
res.Sort = form.DefaultMaxSort(ctx, res.Sort)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -258,3 +259,34 @@ func (s *sSysProvinces) UniqueId(ctx context.Context, in sysin.ProvincesUniqueId
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Select 省市区选项
|
||||
func (s *sSysProvinces) Select(ctx context.Context, in sysin.ProvincesSelectInp) (res *sysin.ProvincesSelectModel, err error) {
|
||||
res = new(sysin.ProvincesSelectModel)
|
||||
mod := dao.SysProvinces.Ctx(ctx).
|
||||
Fields("id as value, title as label, level").
|
||||
Where("pid", in.Value)
|
||||
|
||||
if err = mod.Order("sort asc,id asc").Scan(&res.List); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range res.List {
|
||||
if in.DataType == "p" {
|
||||
v.IsLeaf = true
|
||||
continue
|
||||
}
|
||||
if in.DataType == "pc" && v.Level >= 2 {
|
||||
v.IsLeaf = true
|
||||
continue
|
||||
}
|
||||
|
||||
if in.DataType == "pca" && v.Level >= 3 {
|
||||
v.IsLeaf = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ import (
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/form"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
@@ -83,7 +84,7 @@ func (s *sSysServeLog) List(ctx context.Context, in sysin.ServeLogListInp) (list
|
||||
fields, err := hgorm.GenJoinSelect(ctx, sysin.ServeLogListModel{}, dao.SysServeLog, []*hgorm.Join{
|
||||
{Dao: dao.SysLog, Alias: "sysLog"},
|
||||
})
|
||||
if err = mod.Fields(fields).Handler(hgorm.HandlerFilterAuth).Page(in.Page, in.PerPage).OrderDesc(dao.SysServeLog.Columns().Id).Scan(&list); err != nil {
|
||||
if err = mod.Fields(fields).Handler(handler.FilterAuth).Page(in.Page, in.PerPage).OrderDesc(dao.SysServeLog.Columns().Id).Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
@@ -143,7 +143,7 @@ func (s *sSysSmsLog) List(ctx context.Context, in sysin.SmsLogListInp) (list []*
|
||||
return list, totalCount, nil
|
||||
}
|
||||
|
||||
if err = mod.Page(int(in.Page), int(in.PerPage)).Order("id desc").Scan(&list); err != nil {
|
||||
if err = mod.Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return list, totalCount, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user