From 1ddb1171728a0360cf2b9efae20615a4f1e33ba2 Mon Sep 17 00:00:00 2001 From: yxh Date: Tue, 2 Jan 2024 17:50:07 +0800 Subject: [PATCH] =?UTF-8?q?add=20=E7=AB=99=E5=86=85=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E3=80=81=E7=A7=81=E4=BF=A1=E3=80=81websocket=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/v1/system/sys_notice.go | 133 +++++++ api/v1/system/sys_notice_read.go | 90 +++++ internal/app/common/controller/ping.go | 20 + .../app/common/logic/bigUpload/big_upload.go | 2 +- internal/app/common/logic/cache/cache.go | 2 +- internal/app/common/logic/captcha/captcha.go | 2 +- .../app/common/logic/middleware/middleware.go | 2 +- .../app/common/logic/sysConfig/sys_config.go | 2 +- .../common/logic/sysDictData/sys_dict_data.go | 4 +- .../common/logic/sysDictType/sys_dict_type.go | 2 +- internal/app/common/logic/upload/upload.go | 2 +- internal/app/system/consts/consts.go | 7 +- internal/app/system/controller/sys_notice.go | 88 +++++ .../app/system/controller/sys_notice_read.go | 61 +++ .../app/system/dao/internal/sys_notice.go | 103 +++++ .../system/dao/internal/sys_notice_read.go | 85 +++++ internal/app/system/dao/sys_notice.go | 29 ++ internal/app/system/dao/sys_notice_read.go | 29 ++ internal/app/system/logic/logic.go | 38 +- .../app/system/logic/sysNotice/sys_notice.go | 359 ++++++++++++++++++ .../logic/sysNoticeRead/sys_notice_read.go | 128 +++++++ internal/app/system/model/do/sys_notice.go | 34 ++ .../app/system/model/do/sys_notice_read.go | 26 ++ .../app/system/model/entity/sys_notice.go | 33 ++ .../system/model/entity/sys_notice_read.go | 25 ++ internal/app/system/model/sys_notice.go | 120 ++++++ internal/app/system/model/sys_notice_read.go | 63 +++ internal/app/system/router/sys_notice.go | 25 ++ internal/app/system/router/sys_notice_read.go | 25 ++ internal/app/system/service/sys_notice.go | 48 +++ .../app/system/service/sys_notice_read.go | 38 ++ internal/app/websocket/router/router.go | 82 ++++ internal/router/websocket.go | 11 + library/libWebsocket/client.go | 172 +++++++++ library/libWebsocket/client_manager.go | 321 ++++++++++++++++ library/libWebsocket/init.go | 30 ++ library/libWebsocket/model.go | 38 ++ library/libWebsocket/router.go | 59 +++ 38 files changed, 2311 insertions(+), 27 deletions(-) create mode 100644 api/v1/system/sys_notice.go create mode 100644 api/v1/system/sys_notice_read.go create mode 100644 internal/app/common/controller/ping.go create mode 100644 internal/app/system/controller/sys_notice.go create mode 100644 internal/app/system/controller/sys_notice_read.go create mode 100644 internal/app/system/dao/internal/sys_notice.go create mode 100644 internal/app/system/dao/internal/sys_notice_read.go create mode 100644 internal/app/system/dao/sys_notice.go create mode 100644 internal/app/system/dao/sys_notice_read.go create mode 100644 internal/app/system/logic/sysNotice/sys_notice.go create mode 100644 internal/app/system/logic/sysNoticeRead/sys_notice_read.go create mode 100644 internal/app/system/model/do/sys_notice.go create mode 100644 internal/app/system/model/do/sys_notice_read.go create mode 100644 internal/app/system/model/entity/sys_notice.go create mode 100644 internal/app/system/model/entity/sys_notice_read.go create mode 100644 internal/app/system/model/sys_notice.go create mode 100644 internal/app/system/model/sys_notice_read.go create mode 100644 internal/app/system/router/sys_notice.go create mode 100644 internal/app/system/router/sys_notice_read.go create mode 100644 internal/app/system/service/sys_notice.go create mode 100644 internal/app/system/service/sys_notice_read.go create mode 100644 internal/app/websocket/router/router.go create mode 100644 internal/router/websocket.go create mode 100644 library/libWebsocket/client.go create mode 100644 library/libWebsocket/client_manager.go create mode 100644 library/libWebsocket/init.go create mode 100644 library/libWebsocket/model.go create mode 100644 library/libWebsocket/router.go diff --git a/api/v1/system/sys_notice.go b/api/v1/system/sys_notice.go new file mode 100644 index 0000000..a1e6574 --- /dev/null +++ b/api/v1/system/sys_notice.go @@ -0,0 +1,133 @@ +// ========================================================================== +// GFast自动生成api操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: api/v1/system/sys_notice.go +// 生成人:gfast +// desc:通知公告相关参数 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package system + +import ( + "github.com/gogf/gf/v2/frame/g" + commonApi "github.com/tiger1103/gfast/v3/api/v1/common" + "github.com/tiger1103/gfast/v3/internal/app/system/model" +) + +// SysNoticeSearchReq 分页请求参数 +type SysNoticeSearchReq struct { + g.Meta `path:"/list" tags:"通知私信" method:"get" summary:"通知公告列表(管理)"` + commonApi.Author + model.SysNoticeSearchReq +} + +// SysNoticeSearchRes 列表返回结果 +type SysNoticeSearchRes struct { + g.Meta `mime:"application/json"` + *model.SysNoticeSearchRes +} + +// SysNoticeSearchReq 分页请求参数 +type SysNoticeShowSearchReq struct { + g.Meta `path:"/listShow" tags:"通知私信" method:"get" summary:"通知公告列表(浏览)"` + commonApi.Author + model.SysNoticeSearchReq +} + +// SysNoticeSearchRes 列表返回结果 +type SysNoticeShowSearchRes struct { + g.Meta `mime:"application/json"` + *model.SysNoticeSearchRes +} + +// SysNoticeAddReq 添加操作请求参数 +type SysNoticeAddReq struct { + g.Meta `path:"/add" tags:"通知私信" method:"post" summary:"通知公告添加"` + commonApi.Author + *model.SysNoticeAddReq +} + +// SysNoticeAddRes 添加操作返回结果 +type SysNoticeAddRes struct { + commonApi.EmptyRes +} + +// SysNoticeEditReq 修改操作请求参数 +type SysNoticeEditReq struct { + g.Meta `path:"/edit" tags:"通知私信" method:"put" summary:"通知公告修改"` + commonApi.Author + *model.SysNoticeEditReq +} + +// SysNoticeEditRes 修改操作返回结果 +type SysNoticeEditRes struct { + commonApi.EmptyRes +} + +// SysNoticeGetReq 获取一条数据请求 +type SysNoticeGetReq struct { + g.Meta `path:"/get" tags:"通知私信" method:"get" summary:"获取通知公告信息"` + commonApi.Author + Id int64 `p:"id" v:"required#主键必须"` //通过主键获取 +} + +// SysNoticeGetRes 获取一条数据结果 +type SysNoticeGetRes struct { + g.Meta `mime:"application/json"` + *model.SysNoticeInfoRes +} + +// SysNoticeDeleteReq 删除数据请求 +type SysNoticeDeleteReq struct { + g.Meta `path:"/delete" tags:"通知私信" method:"delete" summary:"删除通知公告"` + commonApi.Author + Ids []int64 `p:"ids" v:"required#主键必须"` //通过主键删除 +} + +// SysNoticeDeleteRes 删除数据返回 +type SysNoticeDeleteRes struct { + commonApi.EmptyRes +} + +type SysNoticeIndexDataReq struct { + g.Meta `path:"getIndexData" tags:"通知私信" method:"get" summary:"获取首页通知预览数据"` + commonApi.Author +} +type SysNoticeIndexDataRes struct { + g.Meta `mime:"application/json"` + *model.SysNoticeIndexRes +} +type SysNoticeUnReadCountReq struct { + g.Meta `path:"unReadCount" tags:"通知私信" method:"get" summary:"获取未读数量"` + commonApi.Author +} +type SysNoticeUnReadCountRes struct { + g.Meta `mime:"application/json"` + *model.SysNoticeUnreadCount +} + +// SysNoticeShowSearchReq 通知展示分页请求参数 +type SysNoticeUserSearchReq struct { + g.Meta `path:"/userList" tags:"通知私信" method:"get" summary:"获取待指定的用户"` + commonApi.Author + UserNickName string `p:"userNickname"` +} + +// SysNoticeSearchRes 通知展示列表返回结果 +type SysNoticeUserSearchRes struct { + g.Meta `mime:"application/json"` + UserList []*model.SysNoticeUserNickname `json:"userList"` +} + +// SysNoticeShowSearchReq 通知展示分页请求参数 +type SysNoticeUserReadReq struct { + g.Meta `path:"/userList" tags:"通知私信" method:"get" summary:"获取待指定的用户"` + commonApi.Author + string `p:"userNickName"` +} + +// SysNoticeSearchRes 通知展示列表返回结果 +type SysNoticeUserReadRes struct { + commonApi.EmptyRes +} diff --git a/api/v1/system/sys_notice_read.go b/api/v1/system/sys_notice_read.go new file mode 100644 index 0000000..0bbef44 --- /dev/null +++ b/api/v1/system/sys_notice_read.go @@ -0,0 +1,90 @@ +// ========================================================================== +// GFast自动生成api操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: api/v1/system/sys_notice_read.go +// 生成人:gfast +// desc:已读记录相关参数 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package system + +import ( + "github.com/gogf/gf/v2/frame/g" + commonApi "github.com/tiger1103/gfast/v3/api/v1/common" + "github.com/tiger1103/gfast/v3/internal/app/system/model" +) + +// SysNoticeReadSearchReq 分页请求参数 +type SysNoticeReadSearchReq struct { + g.Meta `path:"/list" tags:"已读记录" method:"get" summary:"已读记录列表"` + commonApi.Author + model.SysNoticeReadSearchReq +} + +// SysNoticeReadSearchRes 列表返回结果 +type SysNoticeReadSearchRes struct { + g.Meta `mime:"application/json"` + *model.SysNoticeReadSearchRes +} + +// SysNoticeReadAddReq 添加操作请求参数 +type SysNoticeReadAddReq struct { + g.Meta `path:"/add" tags:"已读记录" method:"post" summary:"已读记录添加"` + commonApi.Author + *model.SysNoticeReadAddReq +} + +// SysNoticeReadAddRes 添加操作返回结果 +type SysNoticeReadAddRes struct { + commonApi.EmptyRes +} + +// SysNoticeReadAddReq 添加操作请求参数 +type SysNoticeReadNoticeAddReq struct { + g.Meta `path:"/readNotice" tags:"已读记录" method:"post" summary:"已读记录"` + commonApi.Author + *model.SysNoticeReadNoticeReq +} + +// SysNoticeReadAddRes 添加操作返回结果 +type SysNoticeReadNoticeAddRes struct { + commonApi.EmptyRes +} + +// SysNoticeReadEditReq 修改操作请求参数 +type SysNoticeReadEditReq struct { + g.Meta `path:"/edit" tags:"已读记录" method:"put" summary:"已读记录修改"` + commonApi.Author + *model.SysNoticeReadEditReq +} + +// SysNoticeReadEditRes 修改操作返回结果 +type SysNoticeReadEditRes struct { + commonApi.EmptyRes +} + +// SysNoticeReadGetReq 获取一条数据请求 +type SysNoticeReadGetReq struct { + g.Meta `path:"/get" tags:"已读记录" method:"get" summary:"获取已读记录信息"` + commonApi.Author + Id int64 `p:"id" v:"required#主键必须"` //通过主键获取 +} + +// SysNoticeReadGetRes 获取一条数据结果 +type SysNoticeReadGetRes struct { + g.Meta `mime:"application/json"` + *model.SysNoticeReadInfoRes +} + +// SysNoticeReadDeleteReq 删除数据请求 +type SysNoticeReadDeleteReq struct { + g.Meta `path:"/delete" tags:"已读记录" method:"delete" summary:"删除已读记录"` + commonApi.Author + Ids []int64 `p:"ids" v:"required#主键必须"` //通过主键删除 +} + +// SysNoticeReadDeleteRes 删除数据返回 +type SysNoticeReadDeleteRes struct { + commonApi.EmptyRes +} diff --git a/internal/app/common/controller/ping.go b/internal/app/common/controller/ping.go new file mode 100644 index 0000000..b80969a --- /dev/null +++ b/internal/app/common/controller/ping.go @@ -0,0 +1,20 @@ +/* +* @desc:ping +* @company:云南奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2023/11/30 15:59 + */ + +package controller + +import ( + "github.com/tiger1103/gfast/v3/library/libWebsocket" +) + +var Ping = new(pingController) + +type pingController struct{} + +func (c *pingController) Ping(client *libWebsocket.Client, req *libWebsocket.WRequest) { + libWebsocket.SendSuccess(client, req.Event) +} diff --git a/internal/app/common/logic/bigUpload/big_upload.go b/internal/app/common/logic/bigUpload/big_upload.go index 02ad9bc..9229c31 100644 --- a/internal/app/common/logic/bigUpload/big_upload.go +++ b/internal/app/common/logic/bigUpload/big_upload.go @@ -18,7 +18,7 @@ func init() { service.RegisterBigUpload(New()) } -func New() *sBigUpload { +func New() service.IBigUpload { return &sBigUpload{} } diff --git a/internal/app/common/logic/cache/cache.go b/internal/app/common/logic/cache/cache.go index f9184e0..4ab2c18 100644 --- a/internal/app/common/logic/cache/cache.go +++ b/internal/app/common/logic/cache/cache.go @@ -19,7 +19,7 @@ func init() { service.RegisterCache(New()) } -func New() *sCache { +func New() service.ICache { var ( ctx = gctx.New() cacheContainer *cache.GfCache diff --git a/internal/app/common/logic/captcha/captcha.go b/internal/app/common/logic/captcha/captcha.go index e8058d7..c2781e0 100644 --- a/internal/app/common/logic/captcha/captcha.go +++ b/internal/app/common/logic/captcha/captcha.go @@ -24,7 +24,7 @@ func init() { service.RegisterCaptcha(New()) } -func New() *sCaptcha { +func New() service.ICaptcha { return &sCaptcha{ driver: &base64Captcha.DriverString{ Height: 80, diff --git a/internal/app/common/logic/middleware/middleware.go b/internal/app/common/logic/middleware/middleware.go index 7d25fa4..3d71b8d 100644 --- a/internal/app/common/logic/middleware/middleware.go +++ b/internal/app/common/logic/middleware/middleware.go @@ -16,7 +16,7 @@ func init() { service.RegisterMiddleware(New()) } -func New() *sMiddleware { +func New() service.IMiddleware { return &sMiddleware{} } diff --git a/internal/app/common/logic/sysConfig/sys_config.go b/internal/app/common/logic/sysConfig/sys_config.go index 65eb167..0a12aaa 100644 --- a/internal/app/common/logic/sysConfig/sys_config.go +++ b/internal/app/common/logic/sysConfig/sys_config.go @@ -27,7 +27,7 @@ func init() { service.RegisterSysConfig(New()) } -func New() *sSysConfig { +func New() service.ISysConfig { return &sSysConfig{} } diff --git a/internal/app/common/logic/sysDictData/sys_dict_data.go b/internal/app/common/logic/sysDictData/sys_dict_data.go index 2cd5b3c..a533f74 100644 --- a/internal/app/common/logic/sysDictData/sys_dict_data.go +++ b/internal/app/common/logic/sysDictData/sys_dict_data.go @@ -26,7 +26,7 @@ func init() { service.RegisterSysDictData(New()) } -func New() *sSysDictData { +func New() service.ISysDictData { return &sSysDictData{} } @@ -47,7 +47,7 @@ func (s *sSysDictData) GetDictWithDataByType(ctx context.Context, dictType, defa err = dao.SysDictType.Ctx(ctx).Where(dao.SysDictType.Columns().DictType, dictType). Where(dao.SysDictType.Columns().Status, 1).Fields(model.DictTypeRes{}).Scan(&dict.Info) liberr.ErrIsNil(ctx, err, "获取字典类型失败") - if dict.Info==nil{ + if dict.Info == nil { return } err = dao.SysDictData.Ctx(ctx).Fields(model.DictDataRes{}). diff --git a/internal/app/common/logic/sysDictType/sys_dict_type.go b/internal/app/common/logic/sysDictType/sys_dict_type.go index 9657106..9c120bc 100644 --- a/internal/app/common/logic/sysDictType/sys_dict_type.go +++ b/internal/app/common/logic/sysDictType/sys_dict_type.go @@ -29,7 +29,7 @@ func init() { service.RegisterSysDictType(New()) } -func New() *sSysDictType { +func New() service.ISysDictType { return &sSysDictType{} } diff --git a/internal/app/common/logic/upload/upload.go b/internal/app/common/logic/upload/upload.go index 8e5e1c4..b42548e 100644 --- a/internal/app/common/logic/upload/upload.go +++ b/internal/app/common/logic/upload/upload.go @@ -28,7 +28,7 @@ func init() { service.RegisterUpload(New()) } -func New() *sUpload { +func New() service.IUpload { return &sUpload{} } diff --git a/internal/app/system/consts/consts.go b/internal/app/system/consts/consts.go index c0c0da5..f87f797 100644 --- a/internal/app/system/consts/consts.go +++ b/internal/app/system/consts/consts.go @@ -1,5 +1,10 @@ package consts const ( - PageSize = 10 //分页长度 + // PageSize 分页长度 + PageSize = 10 + // SysNoticeType 系统通知 + SysNoticeType = 1 + // SysLetterType 系统私信 + SysLetterType = 2 ) diff --git a/internal/app/system/controller/sys_notice.go b/internal/app/system/controller/sys_notice.go new file mode 100644 index 0000000..612ced3 --- /dev/null +++ b/internal/app/system/controller/sys_notice.go @@ -0,0 +1,88 @@ +// ========================================================================== +// GFast自动生成controller操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/controller/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package controller + +import ( + "context" + "fmt" + "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/system/service" +) + +type sysNoticeController struct { + BaseController +} + +var SysNotice = new(sysNoticeController) + +// List 列表(管理) +func (c *sysNoticeController) List(ctx context.Context, req *system.SysNoticeSearchReq) (res *system.SysNoticeSearchRes, err error) { + res = new(system.SysNoticeSearchRes) + res.SysNoticeSearchRes, err = service.SysNotice().List(ctx, &req.SysNoticeSearchReq) + return +} + +// ShoWList(展示) +func (c *sysNoticeController) ShowList(ctx context.Context, req *system.SysNoticeShowSearchReq) (res *system.SysNoticeShowSearchRes, err error) { + res = new(system.SysNoticeShowSearchRes) + res.SysNoticeSearchRes, err = service.SysNotice().ListShow(ctx, &req.SysNoticeSearchReq) + return +} + +// Get 获取通知公告 +func (c *sysNoticeController) Get(ctx context.Context, req *system.SysNoticeGetReq) (res *system.SysNoticeGetRes, err error) { + res = new(system.SysNoticeGetRes) + res.SysNoticeInfoRes, err = service.SysNotice().GetById(ctx, req.Id) + return +} + +// Add 添加通知公告 +func (c *sysNoticeController) Add(ctx context.Context, req *system.SysNoticeAddReq) (res *system.SysNoticeAddRes, err error) { + req.CreatedBy = service.Context().GetUserId(ctx) + err = service.SysNotice().Add(ctx, req.SysNoticeAddReq) + return +} + +// Edit 修改通知公告 +func (c *sysNoticeController) Edit(ctx context.Context, req *system.SysNoticeEditReq) (res *system.SysNoticeEditRes, err error) { + req.UpdatedBy = service.Context().GetUserId(ctx) + err = service.SysNotice().Edit(ctx, req.SysNoticeEditReq) + return +} + +// Delete 删除通知公告 +func (c *sysNoticeController) Delete(ctx context.Context, req *system.SysNoticeDeleteReq) (res *system.SysNoticeDeleteRes, err error) { + err = service.SysNotice().Delete(ctx, req.Ids) + return +} + +// IndexData 获取首页数据 +func (c *sysNoticeController) IndexData(ctx context.Context, req *system.SysNoticeIndexDataReq) (res *system.SysNoticeIndexDataRes, err error) { + //res.SysNoticeIndexRes, err = service.SysNotice().IndexData(ctx) + return +} + +// UnReadCount +func (c *sysNoticeController) UnReadCount(ctx context.Context, req *system.SysNoticeUnReadCountReq) (res *system.SysNoticeUnReadCountRes, err error) { + res = new(system.SysNoticeUnReadCountRes) + currentUser := service.Context().Get(ctx).User.Id + //noticeids, err := service.SysNotice().CurrentUseWithIds(ctx, currentUser) + res.SysNoticeUnreadCount, err = service.SysNotice().UnReadCount(ctx, currentUser) + fmt.Println(res) + return +} + +// GetUserNameList 得到供选择用户列表 +func (c *sysNoticeController) GetUserNameList(ctx context.Context, req *system.SysNoticeUserSearchReq) (res *system.SysNoticeUserSearchRes, err error) { + res = new(system.SysNoticeUserSearchRes) + list, err := service.SysNotice().GetUserNameList(ctx, req.UserNickName) + res.UserList = list + return +} diff --git a/internal/app/system/controller/sys_notice_read.go b/internal/app/system/controller/sys_notice_read.go new file mode 100644 index 0000000..80de393 --- /dev/null +++ b/internal/app/system/controller/sys_notice_read.go @@ -0,0 +1,61 @@ +// ========================================================================== +// GFast自动生成controller操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/controller/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package controller + +import ( + "context" + + "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/system/service" +) + +type sysNoticeReadController struct { + BaseController +} + +var SysNoticeRead = new(sysNoticeReadController) + +// List 列表 +func (c *sysNoticeReadController) List(ctx context.Context, req *system.SysNoticeReadSearchReq) (res *system.SysNoticeReadSearchRes, err error) { + res = new(system.SysNoticeReadSearchRes) + res.SysNoticeReadSearchRes, err = service.SysNoticeRead().List(ctx, &req.SysNoticeReadSearchReq) + return +} + +// Get 获取已读记录 +func (c *sysNoticeReadController) Get(ctx context.Context, req *system.SysNoticeReadGetReq) (res *system.SysNoticeReadGetRes, err error) { + res = new(system.SysNoticeReadGetRes) + res.SysNoticeReadInfoRes, err = service.SysNoticeRead().GetById(ctx, req.Id) + return +} + +// Add 添加已读记录 +func (c *sysNoticeReadController) Add(ctx context.Context, req *system.SysNoticeReadAddReq) (res *system.SysNoticeReadAddRes, err error) { + err = service.SysNoticeRead().Add(ctx, req.SysNoticeReadAddReq) + return +} + +// Add 添加已读记录 +func (c *sysNoticeReadController) ReadNotice(ctx context.Context, req *system.SysNoticeReadNoticeAddReq) (res *system.SysNoticeReadNoticeAddRes, err error) { + err = service.SysNoticeRead().ReadNotice(ctx, req.SysNoticeReadNoticeReq) + return +} + +// Edit 修改已读记录 +func (c *sysNoticeReadController) Edit(ctx context.Context, req *system.SysNoticeReadEditReq) (res *system.SysNoticeReadEditRes, err error) { + err = service.SysNoticeRead().Edit(ctx, req.SysNoticeReadEditReq) + return +} + +// Delete 删除已读记录 +func (c *sysNoticeReadController) Delete(ctx context.Context, req *system.SysNoticeReadDeleteReq) (res *system.SysNoticeReadDeleteRes, err error) { + err = service.SysNoticeRead().Delete(ctx, req.Ids) + return +} diff --git a/internal/app/system/dao/internal/sys_notice.go b/internal/app/system/dao/internal/sys_notice.go new file mode 100644 index 0000000..073a3ec --- /dev/null +++ b/internal/app/system/dao/internal/sys_notice.go @@ -0,0 +1,103 @@ +// ========================================================================== +// GFast自动生成dao internal操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/dao/internal/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// SysNoticeDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysNoticeDao struct { + table string // Table is the underlying table name of the DAO. + group string // Group is the database configuration group name of current DAO. + columns SysNoticeColumns // Columns is the short type for Columns, which contains all the column names of Table for convenient usage. +} + +// SysNoticeColumns defines and stores column names for table sys_notice. +type SysNoticeColumns struct { + Id string // ID + Title string // 标题 + Type string // 类型 + Tag string // 标签 + Content string // 内容 + Remark string // 备注 + Sort string // 排序 + Status string // 状态 + Receiver string //接收者 + CreatedBy string // 发送人 + UpdatedBy string // 修改人 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 删除时间 +} + +var sysNoticeColumns = SysNoticeColumns{ + Id: "id", + Title: "title", + Type: "type", + Tag: "tag", + Content: "content", + Remark: "remark", + Sort: "sort", + Status: "status", + Receiver: "receiver", + CreatedBy: "created_by", + UpdatedBy: "updated_by", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", +} + +// NewSysNoticeDao creates and returns a new DAO object for table data access. +func NewSysNoticeDao() *SysNoticeDao { + return &SysNoticeDao{ + group: "default", + table: "sys_notice", + columns: sysNoticeColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of current DAO. +func (dao *SysNoticeDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of current dao. +func (dao *SysNoticeDao) Table() string { + return dao.table +} + +// Columns returns all column names of current dao. +func (dao *SysNoticeDao) Columns() SysNoticeColumns { + return dao.columns +} + +// Group returns the configuration group name of database of current dao. +func (dao *SysNoticeDao) Group() string { + return dao.group +} + +// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. +func (dao *SysNoticeDao) Ctx(ctx context.Context) *gdb.Model { + return dao.DB().Model(dao.table).Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rollbacks the transaction and returns the error from function f if it returns non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note that, you should not Commit or Rollback the transaction in function f +// as it is automatically handled by this function. +func (dao *SysNoticeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/internal/app/system/dao/internal/sys_notice_read.go b/internal/app/system/dao/internal/sys_notice_read.go new file mode 100644 index 0000000..b7153e5 --- /dev/null +++ b/internal/app/system/dao/internal/sys_notice_read.go @@ -0,0 +1,85 @@ +// ========================================================================== +// GFast自动生成dao internal操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/dao/internal/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// SysNoticeReadDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysNoticeReadDao struct { + table string // Table is the underlying table name of the DAO. + group string // Group is the database configuration group name of current DAO. + columns SysNoticeReadColumns // Columns is the short type for Columns, which contains all the column names of Table for convenient usage. +} + +// SysNoticeReadColumns defines and stores column names for table sys_notice_read. +type SysNoticeReadColumns struct { + Id string // id + NoticeId string // 信息id + UserId string // 用户id + UpdatedAt string // 更新时间 + CreatedAt string // 阅读时间 +} + +var sysNoticeReadColumns = SysNoticeReadColumns{ + Id: "id", + NoticeId: "notice_id", + UserId: "user_id", + UpdatedAt: "updated_at", + CreatedAt: "created_at", +} + +// NewSysNoticeReadDao creates and returns a new DAO object for table data access. +func NewSysNoticeReadDao() *SysNoticeReadDao { + return &SysNoticeReadDao{ + group: "default", + table: "sys_notice_read", + columns: sysNoticeReadColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of current DAO. +func (dao *SysNoticeReadDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of current dao. +func (dao *SysNoticeReadDao) Table() string { + return dao.table +} + +// Columns returns all column names of current dao. +func (dao *SysNoticeReadDao) Columns() SysNoticeReadColumns { + return dao.columns +} + +// Group returns the configuration group name of database of current dao. +func (dao *SysNoticeReadDao) Group() string { + return dao.group +} + +// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. +func (dao *SysNoticeReadDao) Ctx(ctx context.Context) *gdb.Model { + return dao.DB().Model(dao.table).Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rollbacks the transaction and returns the error from function f if it returns non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note that, you should not Commit or Rollback the transaction in function f +// as it is automatically handled by this function. +func (dao *SysNoticeReadDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/internal/app/system/dao/sys_notice.go b/internal/app/system/dao/sys_notice.go new file mode 100644 index 0000000..e7653c0 --- /dev/null +++ b/internal/app/system/dao/sys_notice.go @@ -0,0 +1,29 @@ +// ========================================================================== +// GFast自动生成dao操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/dao/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package dao + +import ( + "github.com/tiger1103/gfast/v3/internal/app/system/dao/internal" +) + +// sysNoticeDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysNoticeDao struct { + *internal.SysNoticeDao +} + +var ( + // SysNotice is globally public accessible object for table tools_gen_table operations. + SysNotice = sysNoticeDao{ + internal.NewSysNoticeDao(), + } +) + +// Fill with you ideas below. diff --git a/internal/app/system/dao/sys_notice_read.go b/internal/app/system/dao/sys_notice_read.go new file mode 100644 index 0000000..0bb4552 --- /dev/null +++ b/internal/app/system/dao/sys_notice_read.go @@ -0,0 +1,29 @@ +// ========================================================================== +// GFast自动生成dao操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/dao/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package dao + +import ( + "github.com/tiger1103/gfast/v3/internal/app/system/dao/internal" +) + +// sysNoticeReadDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysNoticeReadDao struct { + *internal.SysNoticeReadDao +} + +var ( + // SysNoticeRead is globally public accessible object for table tools_gen_table operations. + SysNoticeRead = sysNoticeReadDao{ + internal.NewSysNoticeReadDao(), + } +) + +// Fill with you ideas below. diff --git a/internal/app/system/logic/logic.go b/internal/app/system/logic/logic.go index a519401..89c7e66 100644 --- a/internal/app/system/logic/logic.go +++ b/internal/app/system/logic/logic.go @@ -1,19 +1,23 @@ package logic -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/context" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/middleware" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/personal" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysAuthRule" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysDept" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysJob" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysJobLog" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysLoginLog" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysOperLog" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysPost" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysRole" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysUser" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysUserOnline" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/token" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/toolsGenTable" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/toolsGenTableColumn" -import _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/timeTask" +import ( + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/context" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/middleware" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/personal" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysAuthRule" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysDept" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysJob" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysJobLog" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysLoginLog" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysNotice" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysNoticeRead" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysOperLog" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysPost" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysRole" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysUser" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/sysUserOnline" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/timeTask" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/token" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/toolsGenTable" + _ "github.com/tiger1103/gfast/v3/internal/app/system/logic/toolsGenTableColumn" +) diff --git a/internal/app/system/logic/sysNotice/sys_notice.go b/internal/app/system/logic/sysNotice/sys_notice.go new file mode 100644 index 0000000..088aaed --- /dev/null +++ b/internal/app/system/logic/sysNotice/sys_notice.go @@ -0,0 +1,359 @@ +// ========================================================================== +// GFast自动生成logic操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/logic/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package logic + +import ( + "context" + "database/sql" + "errors" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gconv" + "github.com/tiger1103/gfast/v3/internal/app/system/consts" + "github.com/tiger1103/gfast/v3/internal/app/system/dao" + sysDao "github.com/tiger1103/gfast/v3/internal/app/system/dao" + "github.com/tiger1103/gfast/v3/internal/app/system/model" + "github.com/tiger1103/gfast/v3/internal/app/system/model/do" + "github.com/tiger1103/gfast/v3/internal/app/system/service" + "github.com/tiger1103/gfast/v3/library/libWebsocket" + "github.com/tiger1103/gfast/v3/library/liberr" + "strconv" +) + +func init() { + service.RegisterSysNotice(New()) +} + +func New() service.ISysNotice { + return &sSysNotice{} +} + +type sSysNotice struct{} + +func (s *sSysNotice) List(ctx context.Context, req *model.SysNoticeSearchReq) (listRes *model.SysNoticeSearchRes, err error) { + listRes = new(model.SysNoticeSearchRes) + currentUserId := service.Context().GetUserId(ctx) + if currentUserId <= 0 { + err = errors.New("用户信息查询失败") + return + } + err = g.Try(ctx, func(ctx context.Context) { + m := dao.SysNotice.Ctx(ctx).WithAll().As("n") + if req.Id != "" { + m = m.Where("n."+dao.SysNotice.Columns().Id+" = ?", req.Id) + } + if req.Title != "" { + m = m.Where("n."+dao.SysNotice.Columns().Title+" = ?", req.Title) + } + if req.Type != "" { + m = m.Where("n."+dao.SysNotice.Columns().Type+" = ?", gconv.Int64(req.Type)) + } + if req.Tag != "" { + m = m.Where("n."+dao.SysNotice.Columns().Tag+" = ?", gconv.Int(req.Tag)) + } + if req.Status != "" { + m = m.Where("n."+dao.SysNotice.Columns().Status+" = ?", gconv.Int(req.Status)) + } + if len(req.DateRange) != 0 { + m = m.Where("n."+dao.SysNotice.Columns().CreatedAt+" >=? AND "+dao.SysNotice.Columns().CreatedAt+" <=?", req.DateRange[0], req.DateRange[1]) + } + listRes.Total, err = m.Count() + liberr.ErrIsNil(ctx, err, "获取总行数失败") + if req.PageNum == 0 { + req.PageNum = 1 + } + listRes.CurrentPage = req.PageNum + if req.PageSize == 0 { + req.PageSize = consts.PageSize + } + order := "n.id desc" + if req.OrderBy != "" { + order = req.OrderBy + } + m = m.LeftJoin("sys_notice_read as nr", "nr.notice_id=n.id") + //Where("nr.user_id=?", currentUserId) + var res []*model.SysNoticeListRes + + err = m.Page(req.PageNum, req.PageSize).Fields("" + + "n.*," + + "SUM(nr.clicks) as clickNumber" + + //"(nr.user_id=" + strconv.FormatUint(currentUserId, 10) + ") as isRead" + + "").Order(order).Group("n.id").Scan(&res) + liberr.ErrIsNil(ctx, err, "获取数据失败") + listRes.List = res + + }) + return +} +func (s *sSysNotice) ListShow(ctx context.Context, req *model.SysNoticeSearchReq) (listRes *model.SysNoticeSearchRes, err error) { + listRes = new(model.SysNoticeSearchRes) + currentUserId := service.Context().GetUserId(ctx) + if currentUserId <= 0 { + err = errors.New("用户信息查询失败") + return + } + err = g.Try(ctx, func(ctx context.Context) { + m := dao.SysNotice.Ctx(ctx).WithAll().As("n") + if req.Id != "" { + m = m.Where("n."+dao.SysNotice.Columns().Id+" = ?", req.Id) + } + if req.Title != "" { + m = m.Where("n."+dao.SysNotice.Columns().Title+" = ?", req.Title) + } + if req.Type != "" { + m = m.Where("n."+dao.SysNotice.Columns().Type+" = ?", gconv.Int64(req.Type)) + if req.Type == "2" { + ids, _ := s.CurrentUseWithIds(ctx, currentUserId, 2) + m = m.WhereIn("n."+dao.SysNotice.Columns().Id, ids) + } + } + if req.Tag != "" { + m = m.Where("n."+dao.SysNotice.Columns().Tag+" = ?", gconv.Int(req.Tag)) + } + if req.Status != "" { + m = m.Where("n."+dao.SysNotice.Columns().Status+" = ?", gconv.Int(req.Status)) + } + if len(req.DateRange) != 0 { + m = m.Where("n."+dao.SysNotice.Columns().CreatedAt+" >=? AND "+dao.SysNotice.Columns().CreatedAt+" <=?", req.DateRange[0], req.DateRange[1]) + } + listRes.Total, err = m.Count() + liberr.ErrIsNil(ctx, err, "获取总行数失败") + if req.PageNum == 0 { + req.PageNum = 1 + } + listRes.CurrentPage = req.PageNum + if req.PageSize == 0 { + req.PageSize = consts.PageSize + } + order := "n.id desc" + if req.OrderBy != "" { + order = req.OrderBy + } + m = m.LeftJoin("sys_notice_read as nr", "nr.notice_id=n.id") + /*Where("nr.user_id=?", currentUserId)*/ + var res []*model.SysNoticeListRes + + err = m.Page(req.PageNum, req.PageSize).Fields("" + + "n.*," + + "(nr.user_id=" + strconv.FormatUint(currentUserId, 10) + ") as isRead" + //查询是否已读 + "").Order(order).Group("n.id").Scan(&res) + liberr.ErrIsNil(ctx, err, "获取数据失败") + listRes.List = res + }) + return +} +func (s *sSysNotice) GetById(ctx context.Context, id int64) (res *model.SysNoticeInfoRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + err = dao.SysNotice.Ctx(ctx).WithAll().Where(dao.SysNotice.Columns().Id, id).Scan(&res) + liberr.ErrIsNil(ctx, err, "获取信息失败") + }) + return +} + +func (s *sSysNotice) Add(ctx context.Context, req *model.SysNoticeAddReq) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + data := do.SysNotice{ + Title: req.Title, + Type: req.Type, + Tag: req.Tag, + Content: req.Content, + Remark: req.Remark, + Receiver: req.Receiver, + Sort: req.Sort, + Status: req.Status, + CreatedBy: req.CreatedBy, + } + var rows sql.Result + rows, err = dao.SysNotice.Ctx(ctx).Insert(data) + liberr.ErrIsNil(ctx, err, "添加失败") + data.Id, err = rows.LastInsertId() + liberr.ErrIsNil(ctx, err, "获取ID失败") + response := &libWebsocket.WResponse{ + Event: "notice", + Data: data, + } + if req.Type == consts.SysLetterType { + //系统私信 + if len(req.Receiver) > 0 { + for _, id := range req.Receiver { + libWebsocket.SendToUser(id, response) + } + } + } else { + //系统通知 + libWebsocket.SendToAll(response) + } + }) + return +} + +func (s *sSysNotice) Edit(ctx context.Context, req *model.SysNoticeEditReq) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + data := do.SysNotice{ + Title: req.Title, + Tag: req.Tag, + Content: req.Content, + Remark: req.Remark, + Sort: req.Sort, + Status: req.Status, + Receiver: req.Receiver, + UpdatedBy: req.UpdatedBy, + } + _, err = dao.SysNotice.Ctx(ctx).WherePri(req.Id).Update(data) + liberr.ErrIsNil(ctx, err, "修改失败") + data.Id = req.Id + data.Type = req.Type + response := &libWebsocket.WResponse{ + Event: "notice", + Data: data, + } + if data.Type == consts.SysLetterType { + //系统私信 + if len(req.Receiver) > 0 { + for _, id := range req.Receiver { + libWebsocket.SendToUser(id, response) + } + } + } else { + //系统通知 + libWebsocket.SendToAll(response) + } + }) + return +} + +func (s *sSysNotice) Delete(ctx context.Context, ids []int64) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysNotice.Ctx(ctx).Delete(dao.SysNotice.Columns().Id+" in (?)", ids) + liberr.ErrIsNil(ctx, err, "删除失败") + }) + return +} + +/* + func (s *sSysNotice) IndexData(ctx context.Context) (res *model.SysNoticeIndexRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + userInfo := service.Context().GetLoginUser(ctx) + readIdMap, err := dao.SysNoticeRead.Ctx(ctx).Where(dao.SysNoticeRead.Columns().UserId, userInfo.Id).Fields(dao.SysNoticeRead.Columns().NoticeId).All() + fmt.Println(readIdMap, err) + dao.SysNotice.Ctx(ctx).Where(dao.SysNotice.Columns().Type, "1").Order("id desc").Scan(res.Type1List) + dao.SysNotice.Ctx(ctx) + + }) + return + } +*/ +//未读消息列表 +func (s *sSysNotice) UnReadList(ctx context.Context) (res *model.SysNoticeListRes, err error) { + //TODO implement me + panic("implement me") +} + +func (s *sSysNotice) UnReadCount(ctx context.Context, currentUserId uint64) (sysNoticeUnreadCount *model.SysNoticeUnreadCount, err error) { + if currentUserId <= 0 { + err = errors.New("获取用户信息失败") + return + } + countFunc := func(t int) (count int) { + noticeIds, serr := s.CurrentUseWithIds(ctx, currentUserId, t) + if serr != nil { + return 0 + } + all, serr := dao.SysNotice.Ctx(ctx). + WhereIn(dao.SysNotice.Columns().Id, noticeIds). + Where(dao.SysNotice.Columns().Type, t).Count() + if serr != nil { + return 0 + } + read, serr := dao.SysNoticeRead.Ctx(ctx). + WhereIn(dao.SysNoticeRead.Columns().NoticeId, noticeIds). + Where(dao.SysNoticeRead.Columns().UserId, currentUserId). + Count() + if serr != nil { + return 0 + } + count = all - read + return + } + sysNoticeUnreadCount = new(model.SysNoticeUnreadCount) + sysNoticeUnreadCount.NotifyCount = countFunc(1) //获取未读通知数量 + sysNoticeUnreadCount.NoticeCount = countFunc(2) //获取未读私信数量 + return +} + +func (s *sSysNotice) ReadAll(ctx context.Context, nType string) (err error) { + currentUserId := service.Context().GetUserId(ctx) + if currentUserId <= 0 { + err = errors.New("获取当前用户信息失败") + return + } + subQuery := g.Model("sys_notice_read").Where("user_id=?", currentUserId).Fields("id") + /* dao.SysNoticeRead.Ctx(ctx).Where(dao.SysNoticeRead.Columns().UserId, currentUserId)*/ + unReadIdMap, err := dao.SysNotice.Ctx(ctx).WhereNotIn("id", subQuery).Fields("id").All() + if unReadIdMap != nil { + insertList := make([]*model.SysNoticeReadAddReq, 0) + for _, record := range unReadIdMap { + insertList = append(insertList, &model.SysNoticeReadAddReq{ + NoticeId: record["id"].Int64(), + UserId: int64(currentUserId), + CreatedAt: gtime.Now(), + }) + } + _, err = dao.SysNoticeRead.Ctx(ctx).Data(insertList).Insert() + if err != nil { + return + } + } + return +} + +func (s *sSysNotice) GetUserNameList(ctx context.Context, search string) (res []*model.SysNoticeUserNickname, err error) { + res = make([]*model.SysNoticeUserNickname, 0) + err = sysDao.SysUser.Ctx(ctx).Where("user_nickname like ?", "%"+search+"%").Fields("id,user_nickname").Page(1, 6).Scan(&res) + return +} + +/*func (s *sSysNotice) NoticeReadLengthAdd(ctx context.Context, id int64) (err error) { + _, err = g.DB().Exec(ctx, "update sys_notice set read_len=(read_len+1) where id = ?", id) + return +} +*/ + +func (s *sSysNotice) NoticeReadAddUserId(ctx context.Context, req *model.SysNoticeReadAddUserReq) (err error) { + + return +} + +func (s *sSysNotice) CurrentUseWithIds(ctx context.Context, currentUserId uint64, noticeType int) (ids []int64, err error) { + /* columns, err := 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() + if err != nil { + err = gerror.Wrap(err, "获取我的消息失败!") + return + } + + ids = g.NewVar(columns).Int64s()*/ + m := dao.SysNotice.Ctx(ctx) + m = m.Where("status =?", 1). + Where("type=?", noticeType). + Where("(`type` IN(?) OR (`type` = ? and JSON_CONTAINS(`receiver`,'"+gconv.String(currentUserId)+"')))", 1, 2) + all, err := m.Fields("id").All() + if err != nil { + return + } + for _, record := range all { + ids = append(ids, record["id"].Int64()) + } + return +} diff --git a/internal/app/system/logic/sysNoticeRead/sys_notice_read.go b/internal/app/system/logic/sysNoticeRead/sys_notice_read.go new file mode 100644 index 0000000..4b6f96f --- /dev/null +++ b/internal/app/system/logic/sysNoticeRead/sys_notice_read.go @@ -0,0 +1,128 @@ +// ========================================================================== +// GFast自动生成logic操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/logic/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package logic + +import ( + "context" + "github.com/gogf/gf/v2/os/gtime" + + "github.com/gogf/gf/v2/frame/g" + "github.com/tiger1103/gfast/v3/internal/app/system/consts" + "github.com/tiger1103/gfast/v3/internal/app/system/dao" + "github.com/tiger1103/gfast/v3/internal/app/system/model" + "github.com/tiger1103/gfast/v3/internal/app/system/model/do" + "github.com/tiger1103/gfast/v3/internal/app/system/service" + "github.com/tiger1103/gfast/v3/library/liberr" +) + +func init() { + service.RegisterSysNoticeRead(New()) +} + +func New() service.ISysNoticeRead { + return &sSysNoticeRead{} +} + +type sSysNoticeRead struct{} + +func (s *sSysNoticeRead) List(ctx context.Context, req *model.SysNoticeReadSearchReq) (listRes *model.SysNoticeReadSearchRes, err error) { + listRes = new(model.SysNoticeReadSearchRes) + err = g.Try(ctx, func(ctx context.Context) { + m := dao.SysNoticeRead.Ctx(ctx).WithAll() + listRes.Total, err = m.Count() + liberr.ErrIsNil(ctx, err, "获取总行数失败") + if req.PageNum == 0 { + req.PageNum = 1 + } + listRes.CurrentPage = req.PageNum + if req.PageSize == 0 { + req.PageSize = consts.PageSize + } + order := "id desc" + if req.OrderBy != "" { + order = req.OrderBy + } + var res []*model.SysNoticeReadListRes + err = m.Page(req.PageNum, req.PageSize).Order(order).Scan(&res) + liberr.ErrIsNil(ctx, err, "获取数据失败") + listRes.List = make([]*model.SysNoticeReadListRes, len(res)) + for k, v := range res { + listRes.List[k] = &model.SysNoticeReadListRes{ + Id: v.Id, + NoticeId: v.NoticeId, + UserId: v.UserId, + CreatedAt: v.CreatedAt, + } + } + }) + return +} + +func (s *sSysNoticeRead) GetById(ctx context.Context, id int64) (res *model.SysNoticeReadInfoRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + err = dao.SysNoticeRead.Ctx(ctx).WithAll().Where(dao.SysNoticeRead.Columns().Id, id).Scan(&res) + liberr.ErrIsNil(ctx, err, "获取信息失败") + }) + return +} + +func (s *sSysNoticeRead) Add(ctx context.Context, req *model.SysNoticeReadAddReq) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysNoticeRead.Ctx(ctx).Insert(do.SysNoticeRead{}) + liberr.ErrIsNil(ctx, err, "添加失败") + }) + return +} + +func (s *sSysNoticeRead) ReadNotice(ctx context.Context, req *model.SysNoticeReadNoticeReq) (err error) { + currentUser := service.Context().Get(ctx).User.Id + + err = g.Try(ctx, func(ctx context.Context) { + //判断是否有数据 + count, err := dao.SysNoticeRead.Ctx(ctx).Where(dao.SysNoticeRead.Columns().NoticeId, req.NoticeId). + Where(dao.SysNoticeRead.Columns().UserId, currentUser).Count() + if err != nil { + return + } + if count > 0 { + _, err := g.DB().Exec(ctx, " update sys_notice_read set clicks=(clicks+1) where user_id =? and notice_id=?", currentUser, req.NoticeId) + if err != nil { + return + } + } else { + _, err = dao.SysNoticeRead.Ctx(ctx).Insert(do.SysNoticeRead{ + NoticeId: req.NoticeId, + UserId: currentUser, + CreatedAt: gtime.Now(), + Clicks: 0, + }) + if err != nil { + return + } + } + liberr.ErrIsNil(ctx, err, "添加失败") + }) + return +} +func (s *sSysNoticeRead) Edit(ctx context.Context, req *model.SysNoticeReadEditReq) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysNoticeRead.Ctx(ctx).WherePri(req.Id).Update(do.SysNoticeRead{}) + liberr.ErrIsNil(ctx, err, "修改失败") + }) + return +} + +func (s *sSysNoticeRead) Delete(ctx context.Context, ids []int64) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysNoticeRead.Ctx(ctx).Delete(dao.SysNoticeRead.Columns().Id+" in (?)", ids) + liberr.ErrIsNil(ctx, err, "删除失败") + }) + return +} diff --git a/internal/app/system/model/do/sys_notice.go b/internal/app/system/model/do/sys_notice.go new file mode 100644 index 0000000..04ee892 --- /dev/null +++ b/internal/app/system/model/do/sys_notice.go @@ -0,0 +1,34 @@ +// ========================================================================== +// GFast自动生成model entity操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/model/entity/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package do + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" +) + +// SysNotice is the golang structure for table sys_notice. +type SysNotice struct { + gmeta.Meta `orm:"table:sys_notice, do:true"` + Id interface{} `orm:"id,primary" json:"id"` // ID + Title interface{} `orm:"title" json:"title"` // 标题 + Type interface{} `orm:"type" json:"type"` // 类型 + Tag interface{} `orm:"tag" json:"tag"` // 标签 + Content interface{} `orm:"content" json:"content"` // 内容 + Remark interface{} `orm:"remark" json:"remark"` // 备注 + Sort interface{} `orm:"sort" json:"sort"` // 排序 + Status interface{} `orm:"status" json:"status"` // 状态 + Receiver interface{} `orm:"receiver" json:"receiver"` //接收者 + CreatedBy interface{} `orm:"created_by" json:"createdBy"` // 发送人 + UpdatedBy interface{} `orm:"updated_by" json:"updatedBy"` // 修改人 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 更新时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} diff --git a/internal/app/system/model/do/sys_notice_read.go b/internal/app/system/model/do/sys_notice_read.go new file mode 100644 index 0000000..5412ef7 --- /dev/null +++ b/internal/app/system/model/do/sys_notice_read.go @@ -0,0 +1,26 @@ +// ========================================================================== +// GFast自动生成model entity操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/model/entity/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package do + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" +) + +// SysNoticeRead is the golang structure for table sys_notice_read. +type SysNoticeRead struct { + gmeta.Meta `orm:"table:sys_notice_read, do:true"` + Id interface{} `orm:"id,primary" json:"id"` // id + NoticeId interface{} `orm:"notice_id" json:"noticeId"` // 信息id + UserId interface{} `orm:"user_id" json:"userId"` // 用户id + Clicks interface{} `orm:"clicks" json:"clicks"` //点击次数 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 更新时间 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 阅读时间 +} diff --git a/internal/app/system/model/entity/sys_notice.go b/internal/app/system/model/entity/sys_notice.go new file mode 100644 index 0000000..df6e268 --- /dev/null +++ b/internal/app/system/model/entity/sys_notice.go @@ -0,0 +1,33 @@ +// ========================================================================== +// GFast自动生成model entity操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/model/entity/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" +) + +// SysNotice is the golang structure for table sys_notice. +type SysNotice struct { + gmeta.Meta `orm:"table:sys_notice"` + Id int64 `orm:"id,primary" json:"id"` // ID + Title string `orm:"title" json:"title"` // 标题 + Type int64 `orm:"type" json:"type"` // 类型 + Tag int `orm:"tag" json:"tag"` // 标签 + Content string `orm:"content" json:"content"` // 内容 + Remark string `orm:"remark" json:"remark"` // 备注 + Sort int `orm:"sort" json:"sort"` // 排序 + Status int `orm:"status" json:"status"` // 状态 + CreatedBy int64 `orm:"created_by" json:"createdBy"` // 发送人 + UpdatedBy int64 `orm:"updated_by" json:"updatedBy"` // 修改人 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 更新时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} diff --git a/internal/app/system/model/entity/sys_notice_read.go b/internal/app/system/model/entity/sys_notice_read.go new file mode 100644 index 0000000..6ff0651 --- /dev/null +++ b/internal/app/system/model/entity/sys_notice_read.go @@ -0,0 +1,25 @@ +// ========================================================================== +// GFast自动生成model entity操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/model/entity/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" +) + +// SysNoticeRead is the golang structure for table sys_notice_read. +type SysNoticeRead struct { + gmeta.Meta `orm:"table:sys_notice_read"` + Id int64 `orm:"id,primary" json:"id"` // id + NoticeId int64 `orm:"notice_id" json:"noticeId"` // 信息id + UserId int64 `orm:"user_id" json:"userId"` // 用户id + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 更新时间 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 阅读时间 +} diff --git a/internal/app/system/model/sys_notice.go b/internal/app/system/model/sys_notice.go new file mode 100644 index 0000000..89fe855 --- /dev/null +++ b/internal/app/system/model/sys_notice.go @@ -0,0 +1,120 @@ +// ========================================================================== +// GFast自动生成model操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/model/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package model + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" + comModel "github.com/tiger1103/gfast/v3/internal/app/common/model" +) + +// SysNoticeInfoRes is the golang structure for table sys_notice. +type SysNoticeInfoRes struct { + gmeta.Meta `orm:"table:sys_notice"` + Id int64 `orm:"id,primary" json:"id" dc:"ID"` // ID + Title string `orm:"title" json:"title" dc:"标题"` // 标题 + Type int64 `orm:"type" json:"type" dc:"类型"` // 类型 + Tag int `orm:"tag" json:"tag" dc:"标签"` // 标签 + Content string `orm:"content" json:"content" dc:"内容"` // 内容 + Remark string `orm:"remark" json:"remark" dc:"备注"` // 备注 + Sort int `orm:"sort" json:"sort" dc:"排序"` // 排序 + Status int `orm:"status" json:"status" dc:"状态"` // 状态 + CreatedBy int64 `orm:"created_by" json:"createdBy" dc:"发送人"` // 发送人 + CreatedUser *LinkUserRes `orm:"with:id=created_by" json:"createdUser"` + UpdatedBy int64 `orm:"updated_by" json:"updatedBy" dc:"修改人"` // 修改人 + UpdatedUser *LinkUserRes `orm:"with:id=updated_by" json:"updatedUser"` + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt" dc:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt" dc:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt" dc:"删除时间"` // 删除时间 + Receiver []uint64 `json:"receiver" orm:"receiver"` + ReceiverUser []*LinkUserRes `orm:"with:id=receiver" json:"receiverUser"` +} + +type SysNoticeListRes struct { + Id int64 `json:"id" dc:"ID"` + Title string `json:"title" dc:"标题"` + Type int64 `json:"type" dc:"类型"` + Tag int `json:"tag" dc:"标签"` + Content string `json:"content" dc:"内容"` + Remark string `json:"remark" dc:"备注"` + Sort int `json:"sort" dc:"排序"` + Status int `json:"status" dc:"状态"` + IsRead bool `json:"isRead" dc:"当前用户是否已读"` + ClickNumber int `json:"clickNumber"` + CreatedUser *LinkUserRes `orm:"with:id=created_by" json:"createdUser"` + CreatedBy int64 `json:"createdBy" dc:"发送人"` + CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"` +} + +// SysNoticeSearchReq 分页请求参数 +type SysNoticeSearchReq struct { + comModel.PageReq + Id string `p:"id" dc:"ID"` //ID + Title string `p:"title" dc:"标题"` //标题 + Type string `p:"type" v:"type@integer#类型需为整数" dc:"类型"` //类型 + Tag string `p:"tag" v:"tag@integer#标签需为整数" dc:"标签"` //标签 + Status string `p:"status" v:"status@integer#状态需为整数" dc:"状态"` //状态 + CreatedAt string `p:"createdAt" v:"createdAt@datetime#创建时间需为YYYY-MM-DD hh:mm:ss格式" dc:"创建时间"` //创建时间 +} + +// SysNoticeSearchRes 列表返回结果 +type SysNoticeSearchRes struct { + comModel.ListRes + List []*SysNoticeListRes `json:"list"` +} + +type SysNoticeUserNickname struct { + Id int64 `json:"id"` + UserNickName string `json:"userNickname"` +} + +// SysNoticeAddReq 添加操作请求参数 +type SysNoticeAddReq struct { + Title string `p:"title" v:"required#标题不能为空" dc:"标题"` + Type int64 `p:"type" v:"required#类型不能为空" dc:"类型"` + Tag int `p:"tag" dc:"标签"` + Content string `p:"content" v:"required#内容不能为空" dc:"内容"` + Remark string `p:"remark" dc:"备注"` + Sort int `p:"sort" dc:"排序"` + Status int `p:"status" v:"required#状态不能为空" dc:"状态"` + Receiver []uint64 `p:"receiver"` + CreatedBy uint64 +} + +// SysNoticeEditReq 修改操作请求参数 +type SysNoticeEditReq struct { + Id int64 `p:"id" v:"required#主键ID不能为空" dc:"ID"` + Title string `p:"title" v:"required#标题不能为空" dc:"标题"` + Type int64 `p:"type" v:"required#类型不能为空" dc:"类型"` + Tag int `p:"tag" dc:"标签"` + Content string `p:"content" v:"required#内容不能为空" dc:"内容"` + Remark string `p:"remark" dc:"备注"` + Sort int `p:"sort" dc:"排序"` + Status int `p:"status" v:"required#状态不能为空" dc:"状态"` + Receiver []uint64 `p:"receiver"` + UpdatedBy uint64 +} + +type SysNoticeIndexRes struct { + Type1Total int `json:"type1Total"` + Type2Total int `json:"type2Total"` + Type1List *SysNoticeListRes `json:"type1List"` + Type2List *SysNoticeListRes `json:"type2List"` +} + +type SysNoticeUnreadCount struct { + NotifyCount int `json:"notifyCount"` + NoticeCount int `json:"noticeCount"` +} + +type SysNoticeReadAddUserReq struct { + UserId int64 + NoticeId int64 `p:"noticeId"` +} diff --git a/internal/app/system/model/sys_notice_read.go b/internal/app/system/model/sys_notice_read.go new file mode 100644 index 0000000..8d6a42f --- /dev/null +++ b/internal/app/system/model/sys_notice_read.go @@ -0,0 +1,63 @@ +// ========================================================================== +// GFast自动生成model操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/model/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package model + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" + comModel "github.com/tiger1103/gfast/v3/internal/app/common/model" +) + +// SysNoticeReadInfoRes is the golang structure for table sys_notice_read. +type SysNoticeReadInfoRes struct { + gmeta.Meta `orm:"table:sys_notice_read"` + Id int64 `orm:"id,primary" json:"id" dc:"id"` // id + NoticeId int64 `orm:"notice_id" json:"noticeId" dc:"信息id"` // 信息id + UserId int64 `orm:"user_id" json:"userId" dc:"用户id"` // 用户id + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt" dc:"更新时间"` // 更新时间 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt" dc:"阅读时间"` // 阅读时间 +} + +type SysNoticeReadListRes struct { + Id int64 `json:"id" dc:"id"` + NoticeId int64 `json:"noticeId" dc:"信息id"` + UserId int64 `json:"userId" dc:"用户id"` + CreatedAt *gtime.Time `json:"createdAt" dc:"阅读时间"` +} + +// SysNoticeReadSearchReq 分页请求参数 +type SysNoticeReadSearchReq struct { + comModel.PageReq +} + +// SysNoticeReadSearchRes 列表返回结果 +type SysNoticeReadSearchRes struct { + comModel.ListRes + List []*SysNoticeReadListRes `json:"list"` +} + +// SysNoticeReadAddReq 添加操作请求参数 +type SysNoticeReadAddReq struct { + NoticeId int64 `json:"noticeId" dc:"信息id"` + UserId int64 `json:"userId" dc:"用户id"` + CreatedAt *gtime.Time `json:"createdAt" dc:"阅读时间"` +} + +// SysNoticeReadAddReq 添加操作请求参数 +type SysNoticeReadNoticeReq struct { + NoticeId int64 `p:"noticeId" dc:"信息id"` + UserId int64 + CreatedAt *gtime.Time +} + +// SysNoticeReadEditReq 修改操作请求参数 +type SysNoticeReadEditReq struct { + Id int64 `p:"id" v:"required#主键ID不能为空" dc:"id"` +} diff --git a/internal/app/system/router/sys_notice.go b/internal/app/system/router/sys_notice.go new file mode 100644 index 0000000..fa59310 --- /dev/null +++ b/internal/app/system/router/sys_notice.go @@ -0,0 +1,25 @@ +// ========================================================================== +// GFast自动生成router操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/router/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package router + +import ( + "context" + + "github.com/gogf/gf/v2/net/ghttp" + "github.com/tiger1103/gfast/v3/internal/app/system/controller" +) + +func (router *Router) BindSysNoticeController(ctx context.Context, group *ghttp.RouterGroup) { + group.Group("/sysNotice", func(group *ghttp.RouterGroup) { + group.Bind( + controller.SysNotice, + ) + }) +} diff --git a/internal/app/system/router/sys_notice_read.go b/internal/app/system/router/sys_notice_read.go new file mode 100644 index 0000000..cf030b2 --- /dev/null +++ b/internal/app/system/router/sys_notice_read.go @@ -0,0 +1,25 @@ +// ========================================================================== +// GFast自动生成router操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/router/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package router + +import ( + "context" + + "github.com/gogf/gf/v2/net/ghttp" + "github.com/tiger1103/gfast/v3/internal/app/system/controller" +) + +func (router *Router) BindSysNoticeReadController(ctx context.Context, group *ghttp.RouterGroup) { + group.Group("/sysNoticeRead", func(group *ghttp.RouterGroup) { + group.Bind( + controller.SysNoticeRead, + ) + }) +} diff --git a/internal/app/system/service/sys_notice.go b/internal/app/system/service/sys_notice.go new file mode 100644 index 0000000..c2c7cbb --- /dev/null +++ b/internal/app/system/service/sys_notice.go @@ -0,0 +1,48 @@ +// ========================================================================== +// GFast自动生成service操作代码。 +// 生成日期:2023-11-09 11:41:17 +// 生成路径: internal/app/system/service/sys_notice.go +// 生成人:gfast +// desc:通知公告 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package service + +import ( + "context" + "github.com/tiger1103/gfast/v3/internal/app/system/model" +) + +type ISysNotice interface { + List(ctx context.Context, req *model.SysNoticeSearchReq) (res *model.SysNoticeSearchRes, err error) + ListShow(ctx context.Context, req *model.SysNoticeSearchReq) (res *model.SysNoticeSearchRes, err error) + + GetById(ctx context.Context, Id int64) (res *model.SysNoticeInfoRes, err error) + Add(ctx context.Context, req *model.SysNoticeAddReq) (err error) + Edit(ctx context.Context, req *model.SysNoticeEditReq) (err error) + Delete(ctx context.Context, Id []int64) (err error) + //IndexData(ctx context.Context) (res *model.SysNoticeIndexRes, err error) + /*首页相关数据接口*/ + UnReadList(ctx context.Context) (res *model.SysNoticeListRes, err error) + UnReadCount(ctx context.Context, currentUser uint64) (sysNoticeUnreadIds *model.SysNoticeUnreadCount, err error) + ReadAll(ctx context.Context, nType string) (err error) + GetUserNameList(ctx context.Context, search string) (res []*model.SysNoticeUserNickname, err error) + //NoticeReadLengthAdd(ctx context.Context, id int64) (err error) + NoticeReadAddUserId(ctx context.Context, req *model.SysNoticeReadAddUserReq) (err error) + //获取有我的消息的所有私信 + //CurrentUseWithIds(ctx context.Context, currentUserId uint64) (ids []int64, err error) +} + +var localSysNotice ISysNotice + +func SysNotice() ISysNotice { + if localSysNotice == nil { + panic("implement not found for interface ISysNotice, forgot register?") + } + return localSysNotice +} + +func RegisterSysNotice(i ISysNotice) { + localSysNotice = i +} diff --git a/internal/app/system/service/sys_notice_read.go b/internal/app/system/service/sys_notice_read.go new file mode 100644 index 0000000..167f95b --- /dev/null +++ b/internal/app/system/service/sys_notice_read.go @@ -0,0 +1,38 @@ +// ========================================================================== +// GFast自动生成service操作代码。 +// 生成日期:2023-11-09 17:37:25 +// 生成路径: internal/app/system/service/sys_notice_read.go +// 生成人:gfast +// desc:已读记录 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package service + +import ( + "context" + + "github.com/tiger1103/gfast/v3/internal/app/system/model" +) + +type ISysNoticeRead interface { + List(ctx context.Context, req *model.SysNoticeReadSearchReq) (res *model.SysNoticeReadSearchRes, err error) + ReadNotice(ctx context.Context, req *model.SysNoticeReadNoticeReq) (err error) + GetById(ctx context.Context, Id int64) (res *model.SysNoticeReadInfoRes, err error) + Add(ctx context.Context, req *model.SysNoticeReadAddReq) (err error) + Edit(ctx context.Context, req *model.SysNoticeReadEditReq) (err error) + Delete(ctx context.Context, Id []int64) (err error) +} + +var localSysNoticeRead ISysNoticeRead + +func SysNoticeRead() ISysNoticeRead { + if localSysNoticeRead == nil { + panic("implement not found for interface ISysNoticeRead, forgot register?") + } + return localSysNoticeRead +} + +func RegisterSysNoticeRead(i ISysNoticeRead) { + localSysNoticeRead = i +} diff --git a/internal/app/websocket/router/router.go b/internal/app/websocket/router/router.go new file mode 100644 index 0000000..a4aa972 --- /dev/null +++ b/internal/app/websocket/router/router.go @@ -0,0 +1,82 @@ +/* +* @desc:websocket路由 +* @company:云南奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2023/11/30 15:06 + */ + +package router + +import ( + "context" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/guid" + "github.com/gorilla/websocket" + commonController "github.com/tiger1103/gfast/v3/internal/app/common/controller" + "github.com/tiger1103/gfast/v3/internal/app/system/service" + "github.com/tiger1103/gfast/v3/library/libUtils" + "github.com/tiger1103/gfast/v3/library/libWebsocket" + "net/http" +) + +var R = new(Router) + +type Router struct{} + +// WsPage ws入口 +func WsPage(r *ghttp.Request) { + upGrader := websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { + return true + }, + } + conn, err := upGrader.Upgrade(r.Response.ResponseWriter, r.Request, nil) + if err != nil { + return + } + currentTime := uint64(gtime.Now().Unix()) + client := NewClient(r, conn, currentTime) + go client.Read() + go client.Write() + // 用户连接事件 + libWebsocket.Register(client) +} + +// NewClient 初始化 +func NewClient(r *ghttp.Request, socket *websocket.Conn, firstTime uint64) (client *libWebsocket.Client) { + client = &libWebsocket.Client{ + Addr: socket.RemoteAddr().String(), + ID: guid.S(), + Socket: socket, + Send: make(chan *libWebsocket.WResponse, 100), + SendClose: false, + CloseSignal: make(chan struct{}, 1), + FirstTime: firstTime, + HeartbeatTime: firstTime, + User: service.Context().GetLoginUser(r.Context()), + IP: libUtils.GetClientIp(r.Context()), + UserAgent: r.UserAgent(), + } + return +} + +func (router *Router) BindController(ctx context.Context, group *ghttp.RouterGroup) { + group.Group("/websocket", func(group *ghttp.RouterGroup) { + //登录验证拦截 + service.GfToken().Middleware(group) + //context拦截器 + group.Middleware(service.Middleware().Ctx) + + group.GET("/", WsPage) + }) + // 启动websocket监听 + libWebsocket.Start() + + // 注册消息路由 + libWebsocket.RegisterMsg(libWebsocket.EventHandlers{ + "ping": commonController.Ping.Ping, // 心跳 + }) +} diff --git a/internal/router/websocket.go b/internal/router/websocket.go new file mode 100644 index 0000000..7564488 --- /dev/null +++ b/internal/router/websocket.go @@ -0,0 +1,11 @@ +package router + +import ( + "context" + "github.com/gogf/gf/v2/net/ghttp" + websocketRouter "github.com/tiger1103/gfast/v3/internal/app/websocket/router" +) + +func (router *Router) BindWebsocketModuleController(ctx context.Context, group *ghttp.RouterGroup) { + websocketRouter.R.BindController(ctx, group) +} diff --git a/library/libWebsocket/client.go b/library/libWebsocket/client.go new file mode 100644 index 0000000..dd49580 --- /dev/null +++ b/library/libWebsocket/client.go @@ -0,0 +1,172 @@ +package libWebsocket + +import ( + "context" + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gorilla/websocket" + systemModel "github.com/tiger1103/gfast/v3/internal/app/system/model" + "runtime/debug" +) + +const ( + // 用户连接超时时间 + heartbeatExpirationTime = 5 * 60 +) + +// 用户登录 +type login struct { + UserId uint64 + Client *Client +} + +// GetKey 读取客户端数据 +func (l *login) GetKey() string { + return GetUserKey(l.UserId) +} + +// Client 客户端连接 +type Client struct { + Addr string // 客户端地址 + ID string // 连接唯一标识 + Socket *websocket.Conn // 用户连接 + Send chan *WResponse // 待发送的数据 + SendClose bool // 发送是否关闭 + CloseSignal chan struct{} // 关闭信号 + FirstTime uint64 // 首次连接时间 + HeartbeatTime uint64 // 用户上次心跳时间 + Tags garray.StrArray // 标签 + User *systemModel.ContextUser // 用户信息 + context context.Context // Custom context for internal usage purpose. + IP string // 客户端IP + UserAgent string // 用户代理 +} + +// 读取客户端数据 +func (c *Client) Read() { + defer func() { + if r := recover(); r != nil { + g.Log().Warningf(mctx, "client read err: %+v, stack:%+v, user:%+v", r, string(debug.Stack()), c.User) + } + }() + + defer c.close() + + for { + _, message, err := c.Socket.ReadMessage() + if err != nil { + return + } + // 处理消息 + handlerMsg(c, message) + } +} + +// 向客户端写数据 +func (c *Client) Write() { + defer func() { + if r := recover(); r != nil { + g.Log().Warningf(mctx, "client write err: %+v, stack:%+v, user:%+v", r, string(debug.Stack()), c.User) + } + }() + defer func() { + clientManager.Unregister <- c + _ = c.Socket.Close() + }() + for { + select { + case <-c.CloseSignal: + g.Log().Infof(mctx, "websocket client quit, user:%+v", c.User) + return + case message, ok := <-c.Send: + if !ok { + // 发送数据错误 关闭连接 + g.Log().Warningf(mctx, "client write message, user:%+v", c.User) + return + } + _ = c.Socket.WriteJSON(message) + } + } +} + +// SendMsg 发送数据 +func (c *Client) SendMsg(msg *WResponse) { + if c == nil || c.SendClose { + return + } + defer func() { + if r := recover(); r != nil { + g.Log().Infof(mctx, "SendMsg err:%+v, stack:%+v", r, string(debug.Stack())) + } + }() + c.Send <- msg +} + +// Context is alias for function GetCtx. +func (c *Client) Context() context.Context { + if c.context == nil { + c.context = gctx.New() + } + return c.context +} + +// Heartbeat 心跳更新 +func (c *Client) Heartbeat(currentTime uint64) { + c.HeartbeatTime = currentTime +} + +// IsHeartbeatTimeout 心跳是否超时 +func (c *Client) IsHeartbeatTimeout(currentTime uint64) (timeout bool) { + if c.HeartbeatTime+heartbeatExpirationTime <= currentTime { + timeout = true + } + return +} + +// 关闭客户端 +func (c *Client) close() { + if c.SendClose { + return + } + c.SendClose = true + c.CloseSignal <- struct{}{} +} + +// Close 关闭指定客户端连接 +func Close(client *Client) { + client.close() +} + +// SendSuccess 发送成功消息 +func SendSuccess(client *Client, event string, data ...interface{}) { + d := interface{}(nil) + if len(data) > 0 { + d = data[0] + } + client.SendMsg(&WResponse{ + Event: event, + Data: d, + Code: gcode.CodeOK.Code(), + Timestamp: gtime.Now().Unix(), + }) + before(client) +} + +// SendError 发送错误消息 +func SendError(client *Client, event string, err error) { + client.SendMsg(&WResponse{ + Event: event, + Code: gcode.CodeNil.Code(), + ErrorMsg: err.Error(), + Timestamp: gtime.Now().Unix(), + }) + before(client) +} + +// before +func before(client *Client) { + client.Heartbeat(uint64(gtime.Now().Unix())) +} diff --git a/library/libWebsocket/client_manager.go b/library/libWebsocket/client_manager.go new file mode 100644 index 0000000..e14a1c2 --- /dev/null +++ b/library/libWebsocket/client_manager.go @@ -0,0 +1,321 @@ +package libWebsocket + +import ( + "context" + "fmt" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gcron" + "github.com/gogf/gf/v2/os/gtime" + "runtime/debug" + "sync" +) + +// ClientManager 客户端管理 +type ClientManager struct { + Clients map[*Client]bool // 全部的连接 + ClientsLock sync.RWMutex // 读写锁 + Users map[string][]*Client // 登录的用户 + UserLock sync.RWMutex // 读写锁 + Register chan *Client // 连接连接处理 + Login chan *login // 用户登录处理 + Unregister chan *Client // 断开连接处理程序 + Broadcast chan *WResponse // 广播 向全部成员发送数据 + ClientBroadcast chan *ClientWResponse // 广播 向某个客户端发送数据 + TagBroadcast chan *TagWResponse // 广播 向某个标签成员发送数据 + UserBroadcast chan *UserWResponse // 广播 向某个用户的所有链接发送数据 + closeSignal chan struct{} // 关闭信号 +} + +func NewClientManager() (clientManager *ClientManager) { + clientManager = &ClientManager{ + Clients: make(map[*Client]bool), + Users: make(map[string][]*Client), + Register: make(chan *Client, 1000), + Unregister: make(chan *Client, 1000), + Broadcast: make(chan *WResponse, 1000), + TagBroadcast: make(chan *TagWResponse, 1000), + UserBroadcast: make(chan *UserWResponse, 1000), + closeSignal: make(chan struct{}, 1), + } + return +} + +func Manager() *ClientManager { + return clientManager +} + +// GetUserKey 获取用户key +func GetUserKey(userId uint64) (key string) { + key = fmt.Sprintf("%s_%d", "ws", userId) + return +} + +// InClient 客户端是否存在 +func (manager *ClientManager) InClient(client *Client) (ok bool) { + manager.ClientsLock.RLock() + defer manager.ClientsLock.RUnlock() + _, ok = manager.Clients[client] + return +} + +// GetClients 获取所有客户端 +func (manager *ClientManager) GetClients() (clients map[*Client]bool) { + clients = make(map[*Client]bool) + manager.ClientsRange(func(client *Client, value bool) (result bool) { + clients[client] = value + return true + }) + return +} + +// ClientsRange 遍历 +func (manager *ClientManager) ClientsRange(f func(client *Client, value bool) (result bool)) { + manager.ClientsLock.RLock() + defer manager.ClientsLock.RUnlock() + for key, value := range manager.Clients { + if !f(key, value) { + return + } + } +} + +// GetClientsLen 获取客户端总数 +func (manager *ClientManager) GetClientsLen() (clientsLen int) { + clientsLen = len(manager.Clients) + return +} + +// AddClients 添加客户端 +func (manager *ClientManager) AddClients(client *Client) { + manager.ClientsLock.Lock() + defer manager.ClientsLock.Unlock() + manager.Clients[client] = true +} + +// DelClients 删除客户端 +func (manager *ClientManager) DelClients(client *Client) { + manager.ClientsLock.Lock() + defer manager.ClientsLock.Unlock() + delete(manager.Clients, client) +} + +// GetClient 通过socket ID获取客户端的连接 +func (manager *ClientManager) GetClient(id string) (client *Client) { + for c := range manager.Clients { + if c.ID == id { + return c + } + } + return +} + +// GetUserClient 获取用户的连接 +func (manager *ClientManager) GetUserClient(userId uint64) (clients []*Client) { + manager.UserLock.RLock() + defer manager.UserLock.RUnlock() + userKey := GetUserKey(userId) + if value, ok := manager.Users[userKey]; ok { + clients = value + } + return +} + +// AddUsers 添加用户 +func (manager *ClientManager) AddUsers(key string, client *Client) { + manager.UserLock.Lock() + defer manager.UserLock.Unlock() + manager.Users[key] = append(manager.Users[key], client) +} + +// DelUsers 删除用户 +func (manager *ClientManager) DelUsers(client *Client) (result bool) { + manager.UserLock.Lock() + defer manager.UserLock.Unlock() + key := GetUserKey(client.User.Id) + if clients, ok := manager.Users[key]; ok { + for _, value := range clients { + // 判断是否为相同的用户 + if value.Addr != client.Addr { + return + } + delete(manager.Users, key) + result = true + } + } + return +} + +// GetUsersLen 已登录用户数 +func (manager *ClientManager) GetUsersLen() (userLen int) { + userLen = len(manager.Users) + return +} + +// EventRegister 用户建立连接事件 +func (manager *ClientManager) EventRegister(client *Client) { + manager.AddClients(client) + // 用户登录 + manager.EventLogin(&login{ + UserId: client.User.Id, + Client: client, + }) + // 发送当前客户端标识 + // SendSuccess(client, "connected", g.Map{"id": client.ID, "userInfo": client.User}) +} + +// EventLogin 用户登录事件 +func (manager *ClientManager) EventLogin(login *login) { + client := login.Client + if manager.InClient(client) { + userKey := login.GetKey() + manager.AddUsers(userKey, login.Client) + } +} + +// EventUnregister 用户断开连接事件 +func (manager *ClientManager) EventUnregister(client *Client) { + manager.DelClients(client) + // 删除用户连接 + deleteResult := manager.DelUsers(client) + if !deleteResult { + // 不是当前连接的客户端 + return + } + + client.close() +} + +// ClearTimeoutConnections 定时清理超时连接 +func (manager *ClientManager) clearTimeoutConnections() { + currentTime := uint64(gtime.Now().Unix()) + clients := clientManager.GetClients() + for client := range clients { + if client.IsHeartbeatTimeout(currentTime) { + _ = client.Socket.Close() + } + } +} + +// WebsocketPing 心跳处理 +func (manager *ClientManager) ping() { + defer func() { + if r := recover(); r != nil { + g.Log().Warningf(mctx, "websocket gcron ping recover:%+v, stack:%+v", r, string(debug.Stack())) + return + } + }() + + // 定时任务,发送心跳包 + // gcron.Add(ctx, "0 */1 * * * *", func(ctx context.Context) { + // res := &WResponse{ + // Event: "ping", + // Timestamp: gtime.Now().Unix(), + // } + // SendToAll(res) + // }) + + // 定时任务,清理超时连接 + _, _ = gcron.Add(mctx, "*/30 * * * * *", func(ctx context.Context) { + manager.clearTimeoutConnections() + }) +} + +// 管道处理程序 +func (manager *ClientManager) start() { + defer func() { + if r := recover(); r != nil { + g.Log().Warningf(mctx, "websocket start recover:%+v, stack:%+v", r, string(debug.Stack())) + return + } + }() + for { + select { + case conn := <-manager.Register: + // 建立连接事件 + manager.EventRegister(conn) + case login := <-manager.Login: + // 用户登录 + manager.EventLogin(login) + + case conn := <-manager.Unregister: + // 断开连接事件 + manager.EventUnregister(conn) + + case message := <-manager.Broadcast: + // 全部客户端广播事件 + clients := manager.GetClients() + for conn := range clients { + conn.SendMsg(message) + } + case message := <-manager.TagBroadcast: + // 标签广播事件 + clients := manager.GetClients() + for conn := range clients { + if conn.Tags.Contains(message.Tag) { + if message.WResponse.Timestamp == 0 { + message.WResponse.Timestamp = gtime.Now().Timestamp() + } + conn.SendMsg(message.WResponse) + } + } + case message := <-manager.UserBroadcast: + // 用户广播事件 + clients := manager.GetClients() + + for conn := range clients { + if conn.User.Id == message.UserID { + if message.WResponse.Timestamp == 0 { + message.WResponse.Timestamp = gtime.Now().Timestamp() + } + conn.SendMsg(message.WResponse) + } + } + case message := <-manager.ClientBroadcast: + // 单个客户端广播事件 + clients := manager.GetClients() + for conn := range clients { + if conn.ID == message.ID { + if message.WResponse.Timestamp == 0 { + message.WResponse.Timestamp = gtime.Now().Timestamp() + } + conn.SendMsg(message.WResponse) + } + } + case <-manager.closeSignal: + g.Log().Debug(mctx, "websocket CloseSignal quit..") + return + } + } +} + +// SendToAll 发送全部客户端 +func SendToAll(response *WResponse) { + clientManager.Broadcast <- response +} + +// SendToClientID 发送单个客户端 +func SendToClientID(id string, response *WResponse) { + clientRes := &ClientWResponse{ + ID: id, + WResponse: response, + } + clientManager.ClientBroadcast <- clientRes +} + +// SendToUser 发送单个用户 +func SendToUser(userID uint64, response *WResponse) { + userRes := &UserWResponse{ + UserID: userID, + WResponse: response, + } + clientManager.UserBroadcast <- userRes +} + +// SendToTag 发送某个标签 +func SendToTag(tag string, response *WResponse) { + tagRes := &TagWResponse{ + Tag: tag, + WResponse: response, + } + clientManager.TagBroadcast <- tagRes +} diff --git a/library/libWebsocket/init.go b/library/libWebsocket/init.go new file mode 100644 index 0000000..4fdad89 --- /dev/null +++ b/library/libWebsocket/init.go @@ -0,0 +1,30 @@ +package libWebsocket + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/os/grpool" +) + +var ( + mctx = gctx.GetInitCtx() // 上下文 + clientManager = NewClientManager() // 客户端管理 + routers = make(map[string]EventHandler) // 消息路由 + msgGo = grpool.New(20) // 消息处理协程池 +) + +// Start 启动 +func Start() { + go clientManager.start() + go clientManager.ping() + g.Log().Debug(mctx, "start websocket..") +} + +// Stop 关闭 +func Stop() { + clientManager.closeSignal <- struct{}{} +} + +func Register(client *Client) { + clientManager.Register <- client +} diff --git a/library/libWebsocket/model.go b/library/libWebsocket/model.go new file mode 100644 index 0000000..c443d4b --- /dev/null +++ b/library/libWebsocket/model.go @@ -0,0 +1,38 @@ +package libWebsocket + +import "github.com/gogf/gf/v2/frame/g" + +// WRequest 输入对象 +type WRequest struct { + Event string `json:"event"` // 事件名称 + Data g.Map `json:"data"` // 数据 +} + +// WResponse 输出对象 +type WResponse struct { + Event string `json:"event"` // 事件名称 + Data interface{} `json:"data,omitempty"` // 数据 + Code int `json:"code"` // 状态码 + ErrorMsg string `json:"errorMsg,omitempty"` // 错误消息 + Timestamp int64 `json:"timestamp"` // 服务器时间 +} + +type TagWResponse struct { + Tag string + WResponse *WResponse +} + +type UserWResponse struct { + UserID uint64 + WResponse *WResponse +} + +type ClientWResponse struct { + ID string + WResponse *WResponse +} + +// EventHandler 消息处理器 +type EventHandler func(client *Client, req *WRequest) + +type EventHandlers map[string]EventHandler diff --git a/library/libWebsocket/router.go b/library/libWebsocket/router.go new file mode 100644 index 0000000..9b26543 --- /dev/null +++ b/library/libWebsocket/router.go @@ -0,0 +1,59 @@ +package libWebsocket + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/util/gconv" + "runtime/debug" +) + +// handlerMsg 处理消息 +func handlerMsg(client *Client, message []byte) { + defer func() { + if r := recover(); r != nil { + g.Log().Warningf(mctx, "handlerMsg recover, err:%+v, stack:%+v", r, string(debug.Stack())) + } + }() + + var request *WRequest + if err := gconv.Struct(message, &request); err != nil { + g.Log().Warningf(mctx, "handlerMsg 数据解析失败,err:%+v, message:%+v", err, string(message)) + return + } + + if request.Event == "" { + g.Log().Warning(mctx, "handlerMsg request.Event is null") + return + } + + fun, ok := routers[request.Event] + if !ok { + g.Log().Warningf(mctx, "handlerMsg function id %v: not registered", request.Event) + return + } + + err := msgGo.AddWithRecover(mctx, + func(ctx context.Context) { + fun(client, request) + }, + func(ctx context.Context, err error) { + g.Log().Warningf(mctx, "handlerMsg msgGo exec err:%+v", err) + }, + ) + + if err != nil { + g.Log().Warningf(mctx, "handlerMsg msgGo Add err:%+v", err) + return + } +} + +// RegisterMsg 注册消息 +func RegisterMsg(handlers EventHandlers) { + for id, f := range handlers { + if _, ok := routers[id]; ok { + g.Log().Fatalf(mctx, "RegisterMsg function id %v: already registered", id) + return + } + routers[id] = f + } +}