作者 Administrator

合并分支 'test' 到 'master'

Test



查看合并请求 !13
正在显示 48 个修改的文件 包含 2295 行增加140 行删除
@@ -60,6 +60,7 @@ type ( @@ -60,6 +60,7 @@ type (
60 Page int `json:"page"` 60 Page int `json:"page"`
61 Size int `json:"size"` 61 Size int `json:"size"`
62 IncludeRootCompany bool `json:"includeRootCompany,optional"` // 包含公司(把公司当作部门作为顶级节点 部门ID:0) 62 IncludeRootCompany bool `json:"includeRootCompany,optional"` // 包含公司(把公司当作部门作为顶级节点 部门ID:0)
  63 + IncludeDefaultDepartment bool `json:"includeDefaultDepartment,optional"` // 包含默认分组
63 } 64 }
64 65
65 DepartmentListResponse { 66 DepartmentListResponse {
@@ -26,6 +26,14 @@ service Core { @@ -26,6 +26,14 @@ service Core {
26 @doc "点赞消息" 26 @doc "点赞消息"
27 @handler miniLike 27 @handler miniLike
28 post /mini/message/like (MessageRequest) returns (MessageBusinessResponse) 28 post /mini/message/like (MessageRequest) returns (MessageBusinessResponse)
  29 +
  30 + @doc "增加订阅消息次数"
  31 + @handler miniMessageSubscribeAdd
  32 + post /mini/message/subscribe/add (MessageSubscribeAddRequest) returns (MessageSubscribeAddResponse)
  33 +
  34 + @doc "获取订阅消息次数"
  35 + @handler miniMessageSubscribeList
  36 + post /mini/message/subscribe/list (MessageSubscribeListRequest) returns (MessageSubscribeListResponse)
29 } 37 }
30 38
31 type ( 39 type (
@@ -86,4 +94,25 @@ type ( @@ -86,4 +94,25 @@ type (
86 CountComment int `json:"countComment"` // 评论数量 94 CountComment int `json:"countComment"` // 评论数量
87 Show int `json:"show"` // 文章的展示状态(0显示、1不显示) 95 Show int `json:"show"` // 文章的展示状态(0显示、1不显示)
88 } 96 }
  97 +
  98 + // 增加消息订阅次数
  99 + MessageSubscribeAddRequest {
  100 + Types []int `json:"types"` // 订阅消息类型
  101 + }
  102 + MessageSubscribeAddResponse {
  103 + Items []MessageSubscribeItem `json:"items"`
  104 + }
  105 + MessageSubscribeItem {
  106 + Type int `json:"type"` // 订阅消息类型
  107 + Count int `json:"count"` // 订阅次数
  108 + UserId int64 `json:"userId"` // 用户ID
  109 + CompanyId int64 `json:"companyId"` // 公司ID
  110 + }
  111 + //订阅消息次数详情
  112 + MessageSubscribeListRequest {
  113 +
  114 + }
  115 + MessageSubscribeListResponse {
  116 + Items []MessageSubscribeItem `json:"items"`
  117 + }
89 ) 118 )
@@ -95,6 +95,13 @@ service Core { @@ -95,6 +95,13 @@ service Core {
95 @doc "个人主页-用户发布的信息" 95 @doc "个人主页-用户发布的信息"
96 @handler miniHomepageUserNews 96 @handler miniHomepageUserNews
97 post /mini/homepage/user_news (MiniHomepageUserNewsRequest)returns(MiniHomepageUserNewsResposne) 97 post /mini/homepage/user_news (MiniHomepageUserNewsRequest)returns(MiniHomepageUserNewsResposne)
  98 +
  99 + @doc "检测是否绑定微信"
  100 + @handler miniWechatInfo
  101 + get /mini/wechat/info (MiniWechatInfoRequest) returns (MiniWechatInfoResponse)
  102 + @doc "绑定微信"
  103 + @handler miniWechatBind
  104 + post /mini/wechat/bind (MiniWechatBindRequest) returns (MiniWechatBindResponse)
98 } 105 }
99 106
100 type( 107 type(
@@ -279,6 +286,7 @@ type( @@ -279,6 +286,7 @@ type(
279 ParentId int64 `json:"parentId"` // 父级ID 286 ParentId int64 `json:"parentId"` // 父级ID
280 Name string `json:"name"` // 部门名称 287 Name string `json:"name"` // 部门名称
281 UserIds []int64 `json:"userIds"` // 部门下的用户 288 UserIds []int64 `json:"userIds"` // 部门下的用户
  289 + TotalUser int `json:"totalUser"` // 累计用户
282 } 290 }
283 UserSearchRequest{ 291 UserSearchRequest{
284 Page int `json:"page,optional"` 292 Page int `json:"page,optional"`
@@ -471,7 +479,7 @@ type( @@ -471,7 +479,7 @@ type(
471 Phone string `json:"phone,optional"` // 手机号 唯一 479 Phone string `json:"phone,optional"` // 手机号 唯一
472 Position string `json:"position,optional"` // 职位 480 Position string `json:"position,optional"` // 职位
473 Enable int `json:"enable,optional"` // 启用状态 1:启用 2:禁用 481 Enable int `json:"enable,optional"` // 启用状态 1:启用 2:禁用
474 - DepartmentId int64 `json:"departmentId,optional"` // 所属部门 482 + DepartmentId *int64 `json:"departmentId,optional"` // 所属部门
475 } 483 }
476 SystemUserSearchResponse{ 484 SystemUserSearchResponse{
477 List []SystemUser `json:"list"` 485 List []SystemUser `json:"list"`
@@ -523,4 +531,30 @@ type( @@ -523,4 +531,30 @@ type(
523 List []SystemUser `json:"list"` 531 List []SystemUser `json:"list"`
524 Total int64 `json:"total"` 532 Total int64 `json:"total"`
525 } 533 }
  534 +)
  535 +
  536 +// 检测微信绑定信息
  537 +type (
  538 + MiniWechatInfoRequest {
  539 +
  540 + }
  541 + MiniWechatInfoResponse {
  542 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  543 + OpenId string `json:"openId"` // 绑定的微信openId
  544 + Phone string `json:"phone"` // 绑定手机号
  545 + }
  546 +)
  547 +
  548 +// 绑定微信账号
  549 +type (
  550 + MiniWechatBindRequest {
  551 + WechatAuthCode string `json:"wechatAuthcode"` // 微信登录 授权码
  552 + WechatEncryptedData string `json:"wechatEncryptedData"` // 微信登录 加密数据
  553 + WechatIV string `json:"wechatIV"` // 微信登录 加密算法初始向量
  554 + }
  555 + MiniWechatBindResponse {
  556 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  557 + OpenId string `json:"openId"` // 绑定的微信openId
  558 + Phone string `json:"phone"` // 绑定手机号
  559 + }
526 ) 560 )
  1 +package message
  2 +
  3 +import (
  4 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result"
  5 + "net/http"
  6 +
  7 + "github.com/zeromicro/go-zero/rest/httpx"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  11 +)
  12 +
  13 +func MiniMessageSubscribeAddHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  14 + return func(w http.ResponseWriter, r *http.Request) {
  15 + var req types.MessageSubscribeAddRequest
  16 + if err := httpx.Parse(r, &req); err != nil {
  17 + httpx.ErrorCtx(r.Context(), w, err)
  18 + return
  19 + }
  20 +
  21 + l := message.NewMiniMessageSubscribeAddLogic(r.Context(), svcCtx)
  22 + resp, err := l.MiniMessageSubscribeAdd(&req)
  23 + result.HttpResult(r, w, resp, err)
  24 + }
  25 +}
  1 +package message
  2 +
  3 +import (
  4 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result"
  5 + "net/http"
  6 +
  7 + "github.com/zeromicro/go-zero/rest/httpx"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  11 +)
  12 +
  13 +func MiniMessageSubscribeListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  14 + return func(w http.ResponseWriter, r *http.Request) {
  15 + var req types.MessageSubscribeListRequest
  16 + if err := httpx.Parse(r, &req); err != nil {
  17 + httpx.ErrorCtx(r.Context(), w, err)
  18 + return
  19 + }
  20 +
  21 + l := message.NewMiniMessageSubscribeListLogic(r.Context(), svcCtx)
  22 + resp, err := l.MiniMessageSubscribeList(&req)
  23 + result.HttpResult(r, w, resp, err)
  24 + }
  25 +}
@@ -163,6 +163,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { @@ -163,6 +163,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
163 Path: "/mini/message/like", 163 Path: "/mini/message/like",
164 Handler: message.MiniLikeHandler(serverCtx), 164 Handler: message.MiniLikeHandler(serverCtx),
165 }, 165 },
  166 + {
  167 + Method: http.MethodPost,
  168 + Path: "/mini/message/subscribe/add",
  169 + Handler: message.MiniMessageSubscribeAddHandler(serverCtx),
  170 + },
  171 + {
  172 + Method: http.MethodPost,
  173 + Path: "/mini/message/subscribe/list",
  174 + Handler: message.MiniMessageSubscribeListHandler(serverCtx),
  175 + },
166 }..., 176 }...,
167 ), 177 ),
168 rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret), 178 rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret),
@@ -339,6 +349,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { @@ -339,6 +349,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
339 Path: "/mini/homepage/user_news", 349 Path: "/mini/homepage/user_news",
340 Handler: user.MiniHomepageUserNewsHandler(serverCtx), 350 Handler: user.MiniHomepageUserNewsHandler(serverCtx),
341 }, 351 },
  352 + {
  353 + Method: http.MethodGet,
  354 + Path: "/mini/wechat/info",
  355 + Handler: user.MiniWechatInfoHandler(serverCtx),
  356 + },
  357 + {
  358 + Method: http.MethodPost,
  359 + Path: "/mini/wechat/bind",
  360 + Handler: user.MiniWechatBindHandler(serverCtx),
  361 + },
342 }..., 362 }...,
343 ), 363 ),
344 rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret), 364 rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret),
  1 +package user
  2 +
  3 +import (
  4 + "net/http"
  5 +
  6 + "github.com/zeromicro/go-zero/rest/httpx"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/user"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  10 +)
  11 +
  12 +func MiniWechatBindHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  13 + return func(w http.ResponseWriter, r *http.Request) {
  14 + var req types.MiniWechatBindRequest
  15 + if err := httpx.Parse(r, &req); err != nil {
  16 + httpx.ErrorCtx(r.Context(), w, err)
  17 + return
  18 + }
  19 +
  20 + l := user.NewMiniWechatBindLogic(r.Context(), svcCtx)
  21 + resp, err := l.MiniWechatBind(&req)
  22 + if err != nil {
  23 + httpx.ErrorCtx(r.Context(), w, err)
  24 + } else {
  25 + httpx.OkJsonCtx(r.Context(), w, resp)
  26 + }
  27 + }
  28 +}
  1 +package user
  2 +
  3 +import (
  4 + "net/http"
  5 +
  6 + "github.com/zeromicro/go-zero/rest/httpx"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/user"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  10 +)
  11 +
  12 +func MiniWechatInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  13 + return func(w http.ResponseWriter, r *http.Request) {
  14 + var req types.MiniWechatInfoRequest
  15 + if err := httpx.Parse(r, &req); err != nil {
  16 + httpx.ErrorCtx(r.Context(), w, err)
  17 + return
  18 + }
  19 +
  20 + l := user.NewMiniWechatInfoLogic(r.Context(), svcCtx)
  21 + resp, err := l.MiniWechatInfo(&req)
  22 + if err != nil {
  23 + httpx.ErrorCtx(r.Context(), w, err)
  24 + } else {
  25 + httpx.OkJsonCtx(r.Context(), w, resp)
  26 + }
  27 + }
  28 +}
@@ -87,6 +87,7 @@ func (l *MiniArticleBackupSearchLogic) MiniArticleBackupSearch(req *types.MiniAr @@ -87,6 +87,7 @@ func (l *MiniArticleBackupSearchLogic) MiniArticleBackupSearch(req *types.MiniAr
87 changeFiled = append(changeFiled, "修改了评论范围") 87 changeFiled = append(changeFiled, "修改了评论范围")
88 case "Section": 88 case "Section":
89 { 89 {
  90 + changeFiled = append(changeFiled, "修改了文章内容")
90 item.Title = backupList[i].Title 91 item.Title = backupList[i].Title
91 item.Content = content.String() 92 item.Content = content.String()
92 item.Images = images 93 item.Images = images
@@ -2,6 +2,7 @@ package article @@ -2,6 +2,7 @@ package article
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
5 "strconv" 6 "strconv"
6 "strings" 7 "strings"
7 "text/template" 8 "text/template"
@@ -198,6 +199,12 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -198,6 +199,12 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
198 if err != nil { 199 if err != nil {
199 return xerr.NewErrMsgErr("创建文章失败", err) 200 return xerr.NewErrMsgErr("创建文章失败", err)
200 } 201 }
  202 +
  203 + //发送订阅消息
  204 + err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).FollowArticle(conn, newArticle)
  205 + if err != nil {
  206 + return xerr.NewErrMsgErr("创建文章失败", err)
  207 + }
201 return nil 208 return nil
202 }, true) 209 }, true)
203 if err != nil { 210 if err != nil {
@@ -271,6 +271,11 @@ func (l *MiniSetUserLikeLogic) setUserLikeArticle(req *types.MiniSetUserLikeRequ @@ -271,6 +271,11 @@ func (l *MiniSetUserLikeLogic) setUserLikeArticle(req *types.MiniSetUserLikeRequ
271 return err 271 return err
272 } 272 }
273 273
  274 + //发送订阅消息
  275 + err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).LikeArticle(c, articleInfo, userInfo)
  276 + if err != nil {
  277 + return err
  278 + }
274 return nil 279 return nil
275 }, true) 280 }, true)
276 if err != nil { 281 if err != nil {
@@ -362,6 +367,11 @@ func (l *MiniSetUserLikeLogic) setUserLikeComment(req *types.MiniSetUserLikeRequ @@ -362,6 +367,11 @@ func (l *MiniSetUserLikeLogic) setUserLikeComment(req *types.MiniSetUserLikeRequ
362 return err 367 return err
363 } 368 }
364 369
  370 + // 订阅消息
  371 + err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).LikeComment(c, commentInfo, userInfo)
  372 + if err != nil {
  373 + return err
  374 + }
365 return nil 375 return nil
366 }, true) 376 }, true)
367 if err != nil { 377 if err != nil {
@@ -4,6 +4,7 @@ import ( @@ -4,6 +4,7 @@ import (
4 "context" 4 "context"
5 "github.com/pkg/errors" 5 "github.com/pkg/errors"
6 "github.com/samber/lo" 6 "github.com/samber/lo"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction" 8 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
8 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" 9 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
9 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/authlib" 10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/authlib"
@@ -154,6 +155,11 @@ func (l *SystemCreateArticleLogic) SystemCreateArticle(req *types.SystemArticleC @@ -154,6 +155,11 @@ func (l *SystemCreateArticleLogic) SystemCreateArticle(req *types.SystemArticleC
154 return xerr.NewErrMsg("删除草稿失败") 155 return xerr.NewErrMsg("删除草稿失败")
155 } 156 }
156 } 157 }
  158 + //发送订阅消息
  159 + err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).FollowArticle(conn, article)
  160 + if err != nil {
  161 + return xerr.NewErrMsgErr("创建文章失败", err)
  162 + }
157 return nil 163 return nil
158 }, true) 164 }, true)
159 if err != nil { 165 if err != nil {
@@ -206,7 +206,11 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini @@ -206,7 +206,11 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini
206 if err != nil { 206 if err != nil {
207 return err 207 return err
208 } 208 }
209 - 209 + // 发送订阅消息
  210 + err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).ReplyComment(c, articleInfo, &newComment)
  211 + if err != nil {
  212 + return err
  213 + }
210 return nil 214 return nil
211 }, true) 215 }, true)
212 216
@@ -2,6 +2,7 @@ package department @@ -2,6 +2,7 @@ package department
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "github.com/samber/lo"
5 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain" 8 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
@@ -39,6 +40,30 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty @@ -39,6 +40,30 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty
39 Total: total, 40 Total: total,
40 List: make([]types.Department, 0), 41 List: make([]types.Department, 0),
41 } 42 }
  43 +
  44 + _, users, _ := l.svcCtx.UserRepository.Find(l.ctx, conn, domain.NewQueryOptions().
  45 + MustWithKV("companyId", userToken.CompanyId).
  46 + WithKV("auditStatus", []int{domain.UserAuditStatusPassed}))
  47 +
  48 + // 统计部门用户数量
  49 + var counterByDepartment = make(map[int64]int)
  50 + lo.ForEach(users, func(item *domain.User, index int) {
  51 + if len(item.Departments) == 0 {
  52 + if _, ok := counterByDepartment[domain.DefaultDepartmentId]; ok {
  53 + counterByDepartment[domain.DefaultDepartmentId]++
  54 + } else {
  55 + counterByDepartment[domain.DefaultDepartmentId] = 1
  56 + }
  57 + return
  58 + }
  59 + for _, dep := range item.Departments {
  60 + if _, ok := counterByDepartment[dep]; ok {
  61 + counterByDepartment[dep]++
  62 + } else {
  63 + counterByDepartment[dep] = 1
  64 + }
  65 + }
  66 + })
42 if req.IncludeRootCompany { 67 if req.IncludeRootCompany {
43 company, _ := l.svcCtx.CompanyRepository.FindOne(l.ctx, conn, userToken.CompanyId) 68 company, _ := l.svcCtx.CompanyRepository.FindOne(l.ctx, conn, userToken.CompanyId)
44 if company != nil { 69 if company != nil {
@@ -47,9 +72,24 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty @@ -47,9 +72,24 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty
47 CompanyId: company.Id, 72 CompanyId: company.Id,
48 ParentId: -1, 73 ParentId: -1,
49 Name: company.Name, 74 Name: company.Name,
  75 + TotalUser: len(users),
50 }) 76 })
51 } 77 }
52 } 78 }
  79 +
  80 + if req.IncludeDefaultDepartment {
  81 + to := types.Department{
  82 + Id: domain.DefaultDepartmentId,
  83 + CompanyId: userToken.CompanyId,
  84 + ParentId: 0,
  85 + Name: "未分组",
  86 + }
  87 + if v, ok := counterByDepartment[domain.DefaultDepartmentId]; ok {
  88 + to.TotalUser = v
  89 + }
  90 + resp.List = append(resp.List, to)
  91 + }
  92 +
53 for _, item := range list { 93 for _, item := range list {
54 to := types.Department{ 94 to := types.Department{
55 Id: item.Id, 95 Id: item.Id,
@@ -57,6 +97,9 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty @@ -57,6 +97,9 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty
57 ParentId: item.ParentId, 97 ParentId: item.ParentId,
58 Name: item.Name, 98 Name: item.Name,
59 } 99 }
  100 + if v, ok := counterByDepartment[item.Id]; ok {
  101 + to.TotalUser = v
  102 + }
60 resp.List = append(resp.List, to) 103 resp.List = append(resp.List, to)
61 } 104 }
62 return resp, nil 105 return resp, nil
  1 +package message
  2 +
  3 +import (
  4 + "context"
  5 + "github.com/samber/lo"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
  10 +
  11 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  12 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  13 +
  14 + "github.com/zeromicro/go-zero/core/logx"
  15 +)
  16 +
  17 +type MiniMessageSubscribeAddLogic struct {
  18 + logx.Logger
  19 + ctx context.Context
  20 + svcCtx *svc.ServiceContext
  21 +}
  22 +
  23 +func NewMiniMessageSubscribeAddLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniMessageSubscribeAddLogic {
  24 + return &MiniMessageSubscribeAddLogic{
  25 + Logger: logx.WithContext(ctx),
  26 + ctx: ctx,
  27 + svcCtx: svcCtx,
  28 + }
  29 +}
  30 +
  31 +func (l *MiniMessageSubscribeAddLogic) MiniMessageSubscribeAdd(req *types.MessageSubscribeAddRequest) (resp *types.MessageSubscribeAddResponse, err error) {
  32 + var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  33 + userId := userToken.UserId
  34 + companyId := userToken.CompanyId
  35 + var conn = l.svcCtx.DefaultDBConn()
  36 + //验证类型
  37 + for _, item := range req.Types {
  38 + if !lo.Contains([]int{domain.SubscribeTypeReplyComment, domain.SubscribeTypeLike, domain.SubscribeTypeFollow}, item) {
  39 + return nil, xerr.NewErrMsg("请订阅正确的消息类型")
  40 + }
  41 + }
  42 + resp = &types.MessageSubscribeAddResponse{Items: make([]types.MessageSubscribeItem, 0)}
  43 + err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, conn transaction.Conn) error {
  44 + for _, item := range req.Types {
  45 + userSubscribe, err := l.svcCtx.UserSubscribeRepository.FindOneByType(l.ctx, conn, companyId, userId, item)
  46 + if err == nil { //已有数据增加次数
  47 + userSubscribe.Count += 1
  48 + _, err = l.svcCtx.UserSubscribeRepository.Update(l.ctx, conn, userSubscribe)
  49 + if err != nil {
  50 + return err
  51 + }
  52 + } else { //新增
  53 + userSubscribe, err = l.svcCtx.UserSubscribeRepository.Insert(l.ctx, conn, &domain.UserSubscribe{
  54 + Type: item,
  55 + UserId: userId,
  56 + CompanyId: companyId,
  57 + Count: 1,
  58 + })
  59 + if err != nil {
  60 + return err
  61 + }
  62 + }
  63 + resp.Items = append(resp.Items, types.MessageSubscribeItem{
  64 + Type: userSubscribe.Type,
  65 + Count: userSubscribe.Count,
  66 + UserId: userSubscribe.UserId,
  67 + CompanyId: userSubscribe.CompanyId,
  68 + })
  69 + }
  70 + return nil
  71 + }, true)
  72 + if err != nil {
  73 + return nil, xerr.NewErrMsgErr("增加订阅消息次数失败", err)
  74 + }
  75 + return
  76 +}
  1 +package message
  2 +
  3 +import (
  4 + "context"
  5 + "github.com/samber/lo"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  8 +
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  11 +
  12 + "github.com/zeromicro/go-zero/core/logx"
  13 +)
  14 +
  15 +type MiniMessageSubscribeListLogic struct {
  16 + logx.Logger
  17 + ctx context.Context
  18 + svcCtx *svc.ServiceContext
  19 +}
  20 +
  21 +func NewMiniMessageSubscribeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniMessageSubscribeListLogic {
  22 + return &MiniMessageSubscribeListLogic{
  23 + Logger: logx.WithContext(ctx),
  24 + ctx: ctx,
  25 + svcCtx: svcCtx,
  26 + }
  27 +}
  28 +
  29 +func (l *MiniMessageSubscribeListLogic) MiniMessageSubscribeList(req *types.MessageSubscribeListRequest) (resp *types.MessageSubscribeListResponse, err error) {
  30 + var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  31 + userId := userToken.UserId
  32 + companyId := userToken.CompanyId
  33 + var conn = l.svcCtx.DefaultDBConn()
  34 + resp = &types.MessageSubscribeListResponse{Items: make([]types.MessageSubscribeItem, 0)}
  35 + _, list, err := l.svcCtx.UserSubscribeRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("companyId", companyId).WithKV("userId", userId))
  36 + lo.ForEach(list, func(item *domain.UserSubscribe, index int) {
  37 + resp.Items = append(resp.Items, types.MessageSubscribeItem{
  38 + Type: item.Type,
  39 + Count: item.Count,
  40 + UserId: item.UserId,
  41 + CompanyId: item.CompanyId,
  42 + })
  43 + })
  44 + return
  45 +}
  1 +package message
  2 +
  3 +import (
  4 + "context"
  5 + "fmt"
  6 + "github.com/jinzhu/copier"
  7 + "github.com/silenceper/wechat/v2"
  8 + "github.com/silenceper/wechat/v2/cache"
  9 + miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
  10 + "github.com/silenceper/wechat/v2/miniprogram/subscribe"
  11 + "github.com/zeromicro/go-zero/core/logx"
  12 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  13 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  14 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  15 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
  16 + "strings"
  17 + "time"
  18 +)
  19 +
  20 +type MiniSubscribeLogic struct {
  21 + logx.Logger
  22 + ctx context.Context
  23 + svcCtx *svc.ServiceContext
  24 +}
  25 +
  26 +func NewMiniSubscribeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniSubscribeLogic {
  27 + return &MiniSubscribeLogic{
  28 + Logger: logx.WithContext(ctx),
  29 + ctx: ctx,
  30 + svcCtx: svcCtx,
  31 + }
  32 +}
  33 +
  34 +func (l *MiniSubscribeLogic) getSubScribe() *subscribe.Subscribe {
  35 + miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
  36 + AppID: l.svcCtx.Config.Wechat.AppID,
  37 + AppSecret: l.svcCtx.Config.Wechat.AppSecret,
  38 + Cache: cache.NewMemory(),
  39 + })
  40 + return miniprogram.GetSubscribe()
  41 +}
  42 +
  43 +// getOpenId 获取绑定用户openID
  44 +func (l *MiniSubscribeLogic) getOpenId(conn transaction.Conn, userId int64) (string, error) {
  45 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
  46 + if err != nil {
  47 + return "", err
  48 + }
  49 + //获取微信绑定
  50 + userWechat, err := l.svcCtx.UserWechatRepository.FindOneByPhone(l.ctx, conn, userInfo.Phone)
  51 + if err != nil {
  52 + return "", err
  53 + }
  54 + return userWechat.OpenId, nil
  55 +}
  56 +
  57 +// sendAndDecrease 保存并扣减订阅消息
  58 +func (l *MiniSubscribeLogic) sendAndDecrease(conn transaction.Conn, companyId, userId int64, mType int, msg *subscribe.Message) error {
  59 + templateData := make(map[string]interface{})
  60 + _ = copier.Copy(&templateData, msg.Data)
  61 + subscribeMessage := &domain.MessageSubscribe{
  62 + Type: mType,
  63 + CompanyId: companyId,
  64 + UserId: userId,
  65 + OpenId: msg.ToUser,
  66 + TemplateId: msg.TemplateID,
  67 + TemplateData: templateData,
  68 + }
  69 + //获取订阅次数
  70 + userSubscribe, err := l.svcCtx.UserSubscribeRepository.FindOneByType(l.ctx, conn, companyId, userId, mType)
  71 + if err != nil || userSubscribe.Count <= 0 {
  72 + subscribeMessage.Result = "fail"
  73 + subscribeMessage.Error = "订阅次数已用完"
  74 + } else {
  75 + //扣减订阅次数
  76 + userSubscribe.Count = userSubscribe.Count - 1
  77 + _, err = l.svcCtx.UserSubscribeRepository.Update(l.ctx, conn, userSubscribe)
  78 + if err != nil {
  79 + return err
  80 + }
  81 + //发送订阅消息
  82 + subCtx := l.getSubScribe()
  83 + sendErr := subCtx.Send(msg)
  84 + if sendErr != nil {
  85 + subscribeMessage.Result = "fail"
  86 + subscribeMessage.Error = sendErr.Error()
  87 + } else {
  88 + subscribeMessage.Result = "ok"
  89 + }
  90 + }
  91 + //保存订阅结果
  92 + _, err = l.svcCtx.MessageSubscribeRepository.Insert(l.ctx, conn, subscribeMessage)
  93 + if err != nil {
  94 + return err
  95 + }
  96 + return nil
  97 +}
  98 +
  99 +func (l *MiniSubscribeLogic) messageSubscribe(companyId, userId int64, mType int) *domain.MessageSubscribe {
  100 + return &domain.MessageSubscribe{
  101 + Type: mType,
  102 + CompanyId: companyId,
  103 + UserId: userId,
  104 + }
  105 +}
  106 +
  107 +// getReplyCommentUserInfo 获取评论消息用户信息 用户名称+职位 例:张三-董事办
  108 +func (l *MiniSubscribeLogic) getReplyCommentUserInfo(conn transaction.Conn, companyId, userId int64) (string, error) {
  109 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
  110 + if err != nil {
  111 + return "", xerr.NewErrMsgErr("获取评论用户信息失败", err)
  112 + }
  113 + users := []string{userInfo.Name}
  114 + if len(userInfo.Roles) > 0 {
  115 + _, roles, err := l.svcCtx.RoleRepository.Find(l.ctx, conn, domain.IndexCompanyId(companyId)().MustWithKV("ids", userInfo.Roles))
  116 + if err == nil && len(roles) > 0 {
  117 + roleNames := make([]string, 0)
  118 + for _, item := range roles {
  119 + roleNames = append(roleNames, item.Name)
  120 + }
  121 + users = append(users, strings.Join(roleNames, "、"))
  122 + }
  123 + }
  124 + return strings.Join(users, "-"), nil
  125 +}
  126 +
  127 +// ReplyComment 发送评论订阅消息
  128 +// @param conn 数据库连接
  129 +// @param article 文章
  130 +// @param comment 评论
  131 +func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain.Article, comment *domain.ArticleComment) error {
  132 + //评论用户+职位 例: 张三-董事办
  133 + fromUserName, err := l.getReplyCommentUserInfo(conn, comment.CompanyId, comment.FromUserId)
  134 + if err != nil {
  135 + return xerr.NewErrMsgErr("发送消息失败", err)
  136 + }
  137 + //评论消息
  138 + msg := &subscribe.Message{
  139 + TemplateID: domain.SubscribeTemplateComment,
  140 + Data: map[string]*subscribe.DataItem{
  141 + //文章标题
  142 + "thing1": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
  143 + //评论内容
  144 + "thing2": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
  145 + //评论时间
  146 + "time3": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  147 + //评论用户
  148 + "thing5": &subscribe.DataItem{Value: fromUserName},
  149 + //备注
  150 + "thing9": &subscribe.DataItem{Value: ""},
  151 + },
  152 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  153 + }
  154 + //发帖人接收消息
  155 + openId, err := l.getOpenId(conn, article.AuthorId)
  156 + //未绑定微信号,直接返回
  157 + if err == nil && openId != "" {
  158 + msg.ToUser = openId
  159 + msg.Page = fmt.Sprintf("/pages/detail/more-comment?id=%v", article.Id) //跳转页面 帖子评论聚合页
  160 + //备注
  161 + userCount, err := l.svcCtx.ArticleCommentRepository.CommentUserCount(l.ctx, conn, comment.CompanyId, comment.ArticleId)
  162 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的帖子最近已有%v人评论,点击查看详情", userCount)}
  163 + //发送微信订阅消息
  164 + err = l.sendAndDecrease(conn, comment.CompanyId, article.AuthorId, domain.SubscribeTypeReplyComment, msg)
  165 + if err != nil {
  166 + return xerr.NewErrMsgErr("评论失败", err)
  167 + }
  168 + }
  169 + //评论回复
  170 + if comment.Pid > 0 {
  171 + toOpenId, err := l.getOpenId(conn, comment.ToUserId)
  172 + if err == nil && toOpenId != "" {
  173 + msg.ToUser = toOpenId
  174 + msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面评论聚合页
  175 + //备注
  176 + replyCount, err := l.svcCtx.ArticleCommentRepository.ReplyUserCount(l.ctx, conn, comment.CompanyId, comment.Pid)
  177 + if err == nil {
  178 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的评论最近已有%v人回复,点击查看详情", replyCount)}
  179 + //发送微信订阅消息
  180 + err = l.sendAndDecrease(conn, comment.CompanyId, comment.ToUserId, domain.SubscribeTypeReplyComment, msg)
  181 + if err != nil {
  182 + return xerr.NewErrMsgErr("评论失败", err)
  183 + }
  184 + }
  185 + }
  186 + }
  187 + //@消息
  188 + if len(comment.AtWho) > 0 {
  189 + for _, at := range comment.AtWho {
  190 + atOpenId, err := l.getOpenId(conn, at.Id)
  191 + //未绑定微信跳过
  192 + if err != nil || atOpenId == "" {
  193 + continue
  194 + }
  195 + msg.ToUser = atOpenId
  196 + msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面 评论详情页
  197 + //备注
  198 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("%v在评论中提到了你", comment.FromUser.Name)}
  199 + //发送微信订阅消息
  200 + err = l.sendAndDecrease(conn, comment.CompanyId, at.Id, domain.SubscribeTypeReplyComment, msg)
  201 + if err != nil {
  202 + return xerr.NewErrMsgErr("评论失败", err)
  203 + }
  204 + }
  205 + }
  206 + return nil
  207 +}
  208 +
  209 +// LikeArticle 帖子点赞订阅消息
  210 +func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.Article, userInfo *domain.User) error {
  211 + openId, err := l.getOpenId(conn, article.AuthorId)
  212 + if err != nil || openId == "" {
  213 + return nil
  214 + }
  215 + newArticle, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, article.Id)
  216 + if err != nil {
  217 + return xerr.NewErrMsgErr("未获取到帖子信息", err)
  218 + }
  219 + msg := &subscribe.Message{
  220 + ToUser: openId,
  221 + TemplateID: domain.SubscribeTemplateLike,
  222 + Page: fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
  223 + Data: map[string]*subscribe.DataItem{
  224 + //点赞用户
  225 + "name1": &subscribe.DataItem{Value: userInfo.Name},
  226 + //点赞时间
  227 + "date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  228 + //动态内容
  229 + "thing8": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
  230 + //被赞次数
  231 + "number4": &subscribe.DataItem{Value: newArticle.CountLove},
  232 + //温馨提示
  233 + "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
  234 + },
  235 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  236 + }
  237 + err = l.sendAndDecrease(conn, article.CompanyId, article.AuthorId, domain.SubscribeTypeLike, msg)
  238 + if err != nil {
  239 + return xerr.NewErrMsgErr("点赞失败", err)
  240 + }
  241 + return nil
  242 +}
  243 +
  244 +// LikeComment 点赞评论订阅消息
  245 +func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.ArticleComment, userInfo *domain.User) error {
  246 + openId, err := l.getOpenId(conn, comment.FromUserId)
  247 + if err != nil || openId == "" {
  248 + return nil
  249 + }
  250 + //获取被赞次数
  251 + newComment, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, comment.Id)
  252 + if err != nil {
  253 + return xerr.NewErrMsgErr("未获取到评论信息", err)
  254 + }
  255 + msg := &subscribe.Message{
  256 + ToUser: openId,
  257 + TemplateID: domain.SubscribeTemplateLike,
  258 + Page: fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", comment.ArticleId, comment.Id),
  259 + Data: map[string]*subscribe.DataItem{
  260 + //点赞用户
  261 + "name1": &subscribe.DataItem{Value: userInfo.Name},
  262 + //点赞时间
  263 + "date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  264 + //动态内容
  265 + "thing8": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
  266 + //被赞次数
  267 + "number4": &subscribe.DataItem{Value: newComment.CountUserLove},
  268 + //温馨提示
  269 + "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
  270 + },
  271 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  272 + }
  273 + err = l.sendAndDecrease(conn, comment.CompanyId, comment.FromUserId, domain.SubscribeTypeLike, msg)
  274 + if err != nil {
  275 + return xerr.NewErrMsgErr("点赞失败", err)
  276 + }
  277 + return nil
  278 +}
  279 +
  280 +// FollowArticle 发帖关注更新提醒
  281 +func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domain.Article) error {
  282 + //获取关注帖子作者的人员
  283 + _, userInfo, err := l.svcCtx.UserFollowRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("toUserIds", []int64{article.AuthorId}))
  284 + if err == nil && len(userInfo) > 0 {
  285 + for _, item := range userInfo {
  286 + openId, err := l.getOpenId(conn, item.FromUserId)
  287 + if err != nil || openId == "" {
  288 + continue
  289 + }
  290 + msg := &subscribe.Message{
  291 + ToUser: openId,
  292 + TemplateID: domain.SubscribeTemplateFollow,
  293 + Page: fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
  294 + Data: map[string]*subscribe.DataItem{
  295 + //创作者
  296 + "thing1": &subscribe.DataItem{Value: article.Author.Name},
  297 + //作品名称
  298 + "thing2": &subscribe.DataItem{Value: article.Title},
  299 + //内容摘要
  300 + "thing5": &subscribe.DataItem{Value: ""},
  301 + //发布时间
  302 + "time6": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  303 + //温馨提示
  304 + "thing3": &subscribe.DataItem{Value: "你关注的人发布了新的帖子"},
  305 + },
  306 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  307 + }
  308 + err = l.sendAndDecrease(conn, article.CompanyId, item.FromUserId, domain.SubscribeTypeFollow, msg)
  309 + if err != nil {
  310 + return xerr.NewErrMsgErr("保存订阅消息失败", err)
  311 + }
  312 + }
  313 + }
  314 + return nil
  315 +}
@@ -40,7 +40,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs @@ -40,7 +40,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs
40 "list": groups, 40 "list": groups,
41 } 41 }
42 company, err = l.svcCtx.CompanyRepository.FindOne(l.ctx, conn, userToken.CompanyId) 42 company, err = l.svcCtx.CompanyRepository.FindOne(l.ctx, conn, userToken.CompanyId)
43 - if err != nil { 43 + if err != nil || company == nil {
44 return nil, xerr.NewErrMsgErr("查找部门用户失败", err) 44 return nil, xerr.NewErrMsgErr("查找部门用户失败", err)
45 } 45 }
46 _, departments, err = l.svcCtx.DepartmentRepository.Find(l.ctx, conn, domain.IndexCompanyId(userToken.CompanyId)().WithFindOnly()) 46 _, departments, err = l.svcCtx.DepartmentRepository.Find(l.ctx, conn, domain.IndexCompanyId(userToken.CompanyId)().WithFindOnly())
@@ -51,7 +51,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs @@ -51,7 +51,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs
51 if err != nil { 51 if err != nil {
52 return nil, xerr.NewErrMsgErr("查找部门用户失败", err) 52 return nil, xerr.NewErrMsgErr("查找部门用户失败", err)
53 } 53 }
54 - departments = append([]*domain.Department{&domain.Department{Id: 0, Name: company.Name}}, departments...) 54 + departments = append([]*domain.Department{&domain.Department{Id: 0, Name: "未分组"}}, departments...)
55 lo.ForEach(departments, func(item *domain.Department, index int) { 55 lo.ForEach(departments, func(item *domain.Department, index int) {
56 group := DepartmentUser{ 56 group := DepartmentUser{
57 Id: item.Id, 57 Id: item.Id,
@@ -61,7 +61,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs @@ -61,7 +61,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs
61 groupUserSet := collection.NewSet() 61 groupUserSet := collection.NewSet()
62 for _, user := range users { 62 for _, user := range users {
63 // 未分配部门的归类到公司底下 63 // 未分配部门的归类到公司底下
64 - if len(user.Departments) == 0 { 64 + if item.Id == 0 && len(user.Departments) == 0 {
65 if !groupUserSet.Contains(user.Id) { 65 if !groupUserSet.Contains(user.Id) {
66 group.Users = append(group.Users, &domain.User{ 66 group.Users = append(group.Users, &domain.User{
67 Id: user.Id, 67 Id: user.Id,
@@ -35,7 +35,7 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res @@ -35,7 +35,7 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res
35 var ( 35 var (
36 loginInfo *domain.LoginInfo 36 loginInfo *domain.LoginInfo
37 token string 37 token string
38 - loginCreator domain.LoginCreator = WxClientLogin{l: l} 38 + loginCreator domain.LoginCreator = WxClientLogin{svcCtx: l.svcCtx, ctx: l.ctx}
39 ) 39 )
40 switch req.LoginType { 40 switch req.LoginType {
41 case domain.LoginTypeWechatLogin: 41 case domain.LoginTypeWechatLogin:
@@ -102,7 +102,8 @@ func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string, @@ -102,7 +102,8 @@ func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string,
102 } 102 }
103 103
104 type WxClientLogin struct { 104 type WxClientLogin struct {
105 - l *MiniUserLoginLogic 105 + svcCtx *svc.ServiceContext
  106 + ctx context.Context
106 } 107 }
107 108
108 func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.LoginInfo, error) { 109 func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.LoginInfo, error) {
@@ -111,8 +112,8 @@ func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.Lo @@ -111,8 +112,8 @@ func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.Lo
111 Phone: "", 112 Phone: "",
112 } 113 }
113 miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{ 114 miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
114 - AppID: c.l.svcCtx.Config.Wechat.AppID,  
115 - AppSecret: c.l.svcCtx.Config.Wechat.AppSecret, 115 + AppID: c.svcCtx.Config.Wechat.AppID,
  116 + AppSecret: c.svcCtx.Config.Wechat.AppSecret,
116 Cache: cache.NewMemory(), 117 Cache: cache.NewMemory(),
117 }) 118 })
118 authResult, err := miniprogram.GetAuth().GetPhoneNumber(code) 119 authResult, err := miniprogram.GetAuth().GetPhoneNumber(code)
@@ -130,6 +131,23 @@ func (c WxClientLogin) WechatLogin(r domain.WechatLoginRequest) (*domain.LoginIn @@ -130,6 +131,23 @@ func (c WxClientLogin) WechatLogin(r domain.WechatLoginRequest) (*domain.LoginIn
130 return nil, nil 131 return nil, nil
131 } 132 }
132 133
  134 +func (c WxClientLogin) GetOpenId(r domain.WechatLoginRequest) (string, error) {
  135 + miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
  136 + AppID: c.svcCtx.Config.Wechat.AppID,
  137 + AppSecret: c.svcCtx.Config.Wechat.AppSecret,
  138 + Cache: cache.NewMemory(),
  139 + })
  140 + result, err := miniprogram.GetAuth().Code2Session(r.Code)
  141 + if err != nil {
  142 + return "", xerr.NewErrMsgErr("发起授权请求失败", err)
  143 + }
  144 + plainData, err := miniprogram.GetEncryptor().Decrypt(result.SessionKey, r.EncryptedData, r.IV)
  145 + if err != nil {
  146 + return "", xerr.NewErrMsgErr("获取授权用户失败", err)
  147 + }
  148 + return plainData.OpenID, nil
  149 +}
  150 +
133 func (c WxClientLogin) PhonePasswordLogin(phone string, password string) (*domain.LoginInfo, error) { 151 func (c WxClientLogin) PhonePasswordLogin(phone string, password string) (*domain.LoginInfo, error) {
134 panic("implement me") 152 panic("implement me")
135 } 153 }
@@ -139,10 +157,10 @@ func (c WxClientLogin) PhoneSmsCodeLogin(phone string, code string) (*domain.Log @@ -139,10 +157,10 @@ func (c WxClientLogin) PhoneSmsCodeLogin(phone string, code string) (*domain.Log
139 err error 157 err error
140 skipCheckSmsCode bool = false 158 skipCheckSmsCode bool = false
141 ) 159 )
142 - if c.l.svcCtx.Config.DebugSmsCode != "" && c.l.svcCtx.Config.DebugSmsCode == code { 160 + if c.svcCtx.Config.DebugSmsCode != "" && c.svcCtx.Config.DebugSmsCode == code {
143 skipCheckSmsCode = true 161 skipCheckSmsCode = true
144 } 162 }
145 - if _, err = c.l.svcCtx.SmsService.CheckSmsCode(c.l.ctx, smslib.RequestCheckSmsCode{Phone: phone, Code: code}); err != nil && !skipCheckSmsCode { 163 + if _, err = c.svcCtx.SmsService.CheckSmsCode(c.ctx, smslib.RequestCheckSmsCode{Phone: phone, Code: code}); err != nil && !skipCheckSmsCode {
146 return nil, xerr.NewErrMsgErr(err.Error(), err) 164 return nil, xerr.NewErrMsgErr(err.Error(), err)
147 } 165 }
148 response := &domain.LoginInfo{ 166 response := &domain.LoginInfo{
  1 +package user
  2 +
  3 +import (
  4 + "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
  8 +
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  11 +
  12 + "github.com/zeromicro/go-zero/core/logx"
  13 +)
  14 +
  15 +type MiniWechatBindLogic struct {
  16 + logx.Logger
  17 + ctx context.Context
  18 + svcCtx *svc.ServiceContext
  19 +}
  20 +
  21 +func NewMiniWechatBindLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniWechatBindLogic {
  22 + return &MiniWechatBindLogic{
  23 + Logger: logx.WithContext(ctx),
  24 + ctx: ctx,
  25 + svcCtx: svcCtx,
  26 + }
  27 +}
  28 +
  29 +func (l *MiniWechatBindLogic) MiniWechatBind(req *types.MiniWechatBindRequest) (resp *types.MiniWechatBindResponse, err error) {
  30 + var loginCreator domain.LoginCreator = WxClientLogin{svcCtx: l.svcCtx, ctx: l.ctx}
  31 + openId, err := loginCreator.GetOpenId(domain.WechatLoginRequest{
  32 + Code: req.WechatAuthCode,
  33 + EncryptedData: req.WechatEncryptedData,
  34 + IV: req.WechatIV,
  35 + })
  36 + if err != nil {
  37 + return nil, xerr.NewErrMsgErr("授权失败", err)
  38 + }
  39 + var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  40 + userId := userToken.UserId
  41 + var conn = l.svcCtx.DefaultDBConn()
  42 + //获取用户信息
  43 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
  44 + if err != nil {
  45 + return nil, xerr.NewErrMsgErr("获取用户信息失败", err)
  46 + }
  47 + _, err = l.svcCtx.UserWechatRepository.FindOneByPhone(l.ctx, conn, userInfo.Phone)
  48 + if err != nil { // 未存储
  49 + _, err = l.svcCtx.UserWechatRepository.Insert(l.ctx, conn, &domain.UserWechat{
  50 + Phone: userInfo.Phone,
  51 + OpenId: openId,
  52 + })
  53 + if err != nil {
  54 + return nil, xerr.NewErrMsgErr("授权失败", err)
  55 + }
  56 + }
  57 + if err != nil {
  58 + return nil, xerr.NewErrMsg("保存用户信息失败")
  59 + }
  60 + return &types.MiniWechatBindResponse{
  61 + Bind: true,
  62 + Phone: userInfo.Phone,
  63 + OpenId: openId,
  64 + }, nil
  65 +}
  1 +package user
  2 +
  3 +import (
  4 + "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
  7 +
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  10 +
  11 + "github.com/zeromicro/go-zero/core/logx"
  12 +)
  13 +
  14 +type MiniWechatInfoLogic struct {
  15 + logx.Logger
  16 + ctx context.Context
  17 + svcCtx *svc.ServiceContext
  18 +}
  19 +
  20 +func NewMiniWechatInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniWechatInfoLogic {
  21 + return &MiniWechatInfoLogic{
  22 + Logger: logx.WithContext(ctx),
  23 + ctx: ctx,
  24 + svcCtx: svcCtx,
  25 + }
  26 +}
  27 +
  28 +func (l *MiniWechatInfoLogic) MiniWechatInfo(req *types.MiniWechatInfoRequest) (resp *types.MiniWechatInfoResponse, err error) {
  29 + var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  30 + userId := userToken.UserId
  31 + var conn = l.svcCtx.DefaultDBConn()
  32 + user, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
  33 + if err != nil {
  34 + return nil, xerr.NewErrMsg("未获取到用户信息")
  35 + }
  36 + userWechat, err := l.svcCtx.UserWechatRepository.FindOneByPhone(l.ctx, conn, user.Phone)
  37 + if err != nil {
  38 + return &types.MiniWechatInfoResponse{
  39 + Bind: false,
  40 + }, nil
  41 + } else {
  42 + return &types.MiniWechatInfoResponse{
  43 + Bind: true,
  44 + OpenId: userWechat.OpenId,
  45 + Phone: userWechat.Phone,
  46 + }, nil
  47 + }
  48 +}
@@ -41,8 +41,11 @@ func (l *SystemUserSearchLogic) SystemUserSearch(req *types.SystemUserSearchRequ @@ -41,8 +41,11 @@ func (l *SystemUserSearchLogic) SystemUserSearch(req *types.SystemUserSearchRequ
41 WithKV("likePhone", req.Phone). 41 WithKV("likePhone", req.Phone).
42 WithKV("position", req.Position). 42 WithKV("position", req.Position).
43 WithKV("enable", req.Enable). 43 WithKV("enable", req.Enable).
44 - WithKV("departmentId", req.DepartmentId).  
45 WithKV("auditStatus", []int{domain.UserAuditStatusPassed}) 44 WithKV("auditStatus", []int{domain.UserAuditStatusPassed})
  45 +
  46 + if req.DepartmentId != nil {
  47 + queryOptions.MustWithKV("departmentId", *req.DepartmentId)
  48 + }
46 if total, users, err = l.svcCtx.UserRepository.Find(l.ctx, conn, queryOptions); err != nil { 49 if total, users, err = l.svcCtx.UserRepository.Find(l.ctx, conn, queryOptions); err != nil {
47 return nil, xerr.NewErr(err) 50 return nil, xerr.NewErr(err)
48 } 51 }
@@ -37,16 +37,19 @@ type ServiceContext struct { @@ -37,16 +37,19 @@ type ServiceContext struct {
37 ArticleAndTagRepository domain.ArticleAndTagRepository 37 ArticleAndTagRepository domain.ArticleAndTagRepository
38 ArticleDraftOperationRepository domain.ArticleDraftOperationRepository 38 ArticleDraftOperationRepository domain.ArticleDraftOperationRepository
39 39
40 - CompanyRepository domain.CompanyRepository  
41 - DepartmentRepository domain.DepartmentRepository  
42 - MessageBusinessRepository domain.MessageBusinessRepository  
43 - MessageSystemRepository domain.MessageSystemRepository  
44 - RoleRepository domain.RoleRepository  
45 - UserFollowRepository domain.UserFollowRepository  
46 - UserLoveFlagRepository domain.UserLoveFlagRepository  
47 - UserReadArticleRepository domain.UserReadArticleRepository  
48 - UserRepository domain.UserRepository  
49 - UserRoleRepository domain.UserRoleRepository 40 + CompanyRepository domain.CompanyRepository
  41 + DepartmentRepository domain.DepartmentRepository
  42 + MessageBusinessRepository domain.MessageBusinessRepository
  43 + MessageSystemRepository domain.MessageSystemRepository
  44 + MessageSubscribeRepository domain.MessageSubscribeRepository
  45 + RoleRepository domain.RoleRepository
  46 + UserFollowRepository domain.UserFollowRepository
  47 + UserLoveFlagRepository domain.UserLoveFlagRepository
  48 + UserReadArticleRepository domain.UserReadArticleRepository
  49 + UserRepository domain.UserRepository
  50 + UserRoleRepository domain.UserRoleRepository
  51 + UserSubscribeRepository domain.UserSubscribeRepository
  52 + UserWechatRepository domain.UserWechatRepository
50 53
51 ApiAuthService authlib.ApiAuthService 54 ApiAuthService authlib.ApiAuthService
52 SmsService smslib.SMSService 55 SmsService smslib.SMSService
@@ -92,17 +95,20 @@ func NewServiceContext(c config.Config) *ServiceContext { @@ -92,17 +95,20 @@ func NewServiceContext(c config.Config) *ServiceContext {
92 ArticleCategoryRepository: repository.NewArticleCategoryRepository(cache.NewCachedRepository(mlCache)), 95 ArticleCategoryRepository: repository.NewArticleCategoryRepository(cache.NewCachedRepository(mlCache)),
93 ArticleDraftOperationRepository: repository.NewArticleDraftOperationRepository(cache.NewCachedRepository(mlCache)), 96 ArticleDraftOperationRepository: repository.NewArticleDraftOperationRepository(cache.NewCachedRepository(mlCache)),
94 97
95 - CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)),  
96 - DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)),  
97 - MessageBusinessRepository: repository.NewMessageBusinessRepository(cache.NewCachedRepository(mlCache)),  
98 - MessageSystemRepository: repository.NewMessageSystemRepository(cache.NewCachedRepository(mlCache)),  
99 - RoleRepository: repository.NewRoleRepository(cache.NewCachedRepository(mlCache)),  
100 - UserFollowRepository: repository.NewUserFollowRepository(cache.NewCachedRepository(mlCache)),  
101 - UserLoveFlagRepository: repository.NewUserLoveFlagRepository(cache.NewCachedRepository(mlCache)),  
102 - UserRepository: repository.NewUserRepository(cache.NewCachedRepository(mlCache)),  
103 - UserReadArticleRepository: repository.NewUserReadArticleRepository(cache.NewCachedRepository(mlCache)),  
104 - ArticleTagRepository: repository.NewArticleTagRepository(cache.NewCachedRepository(mlCache)),  
105 - UserRoleRepository: repository.NewUserRoleRepository(cache.NewCachedRepository(mlCache)), 98 + CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)),
  99 + DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)),
  100 + MessageBusinessRepository: repository.NewMessageBusinessRepository(cache.NewCachedRepository(mlCache)),
  101 + MessageSystemRepository: repository.NewMessageSystemRepository(cache.NewCachedRepository(mlCache)),
  102 + MessageSubscribeRepository: repository.NewMessageSubscribeRepository(cache.NewCachedRepository(mlCache)),
  103 + RoleRepository: repository.NewRoleRepository(cache.NewCachedRepository(mlCache)),
  104 + UserFollowRepository: repository.NewUserFollowRepository(cache.NewCachedRepository(mlCache)),
  105 + UserLoveFlagRepository: repository.NewUserLoveFlagRepository(cache.NewCachedRepository(mlCache)),
  106 + UserRepository: repository.NewUserRepository(cache.NewCachedRepository(mlCache)),
  107 + UserReadArticleRepository: repository.NewUserReadArticleRepository(cache.NewCachedRepository(mlCache)),
  108 + ArticleTagRepository: repository.NewArticleTagRepository(cache.NewCachedRepository(mlCache)),
  109 + UserRoleRepository: repository.NewUserRoleRepository(cache.NewCachedRepository(mlCache)),
  110 + UserSubscribeRepository: repository.NewUserSubscribeRepository(cache.NewCachedRepository(mlCache)),
  111 + UserWechatRepository: repository.NewUserWechatRepository(cache.NewCachedRepository(mlCache)),
106 } 112 }
107 } 113 }
108 114
@@ -347,6 +347,28 @@ type SimpleArticle struct { @@ -347,6 +347,28 @@ type SimpleArticle struct {
347 Show int `json:"show"` // 文章的展示状态(0显示、1不显示) 347 Show int `json:"show"` // 文章的展示状态(0显示、1不显示)
348 } 348 }
349 349
  350 +type MessageSubscribeAddRequest struct {
  351 + Types []int `json:"types"` // 订阅消息类型
  352 +}
  353 +
  354 +type MessageSubscribeAddResponse struct {
  355 + Items []MessageSubscribeItem `json:"items"`
  356 +}
  357 +
  358 +type MessageSubscribeItem struct {
  359 + Type int `json:"type"` // 订阅消息类型
  360 + Count int `json:"count"` // 订阅次数
  361 + UserId int64 `json:"userId"` // 用户ID
  362 + CompanyId int64 `json:"companyId"` // 公司ID
  363 +}
  364 +
  365 +type MessageSubscribeListRequest struct {
  366 +}
  367 +
  368 +type MessageSubscribeListResponse struct {
  369 + Items []MessageSubscribeItem `json:"items"`
  370 +}
  371 +
350 type TagCreateRequest struct { 372 type TagCreateRequest struct {
351 CompanyId int64 `json:",optional"` 373 CompanyId int64 `json:",optional"`
352 Image string `json:"image"` 374 Image string `json:"image"`
@@ -637,6 +659,7 @@ type Department struct { @@ -637,6 +659,7 @@ type Department struct {
637 ParentId int64 `json:"parentId"` // 父级ID 659 ParentId int64 `json:"parentId"` // 父级ID
638 Name string `json:"name"` // 部门名称 660 Name string `json:"name"` // 部门名称
639 UserIds []int64 `json:"userIds"` // 部门下的用户 661 UserIds []int64 `json:"userIds"` // 部门下的用户
  662 + TotalUser int `json:"totalUser"` // 累计用户
640 } 663 }
641 664
642 type UserSearchRequest struct { 665 type UserSearchRequest struct {
@@ -786,7 +809,7 @@ type SystemUserSearchRequest struct { @@ -786,7 +809,7 @@ type SystemUserSearchRequest struct {
786 Phone string `json:"phone,optional"` // 手机号 唯一 809 Phone string `json:"phone,optional"` // 手机号 唯一
787 Position string `json:"position,optional"` // 职位 810 Position string `json:"position,optional"` // 职位
788 Enable int `json:"enable,optional"` // 启用状态 1:启用 2:禁用 811 Enable int `json:"enable,optional"` // 启用状态 1:启用 2:禁用
789 - DepartmentId int64 `json:"departmentId,optional"` // 所属部门 812 + DepartmentId *int64 `json:"departmentId,optional"` // 所属部门
790 } 813 }
791 814
792 type SystemUserSearchResponse struct { 815 type SystemUserSearchResponse struct {
@@ -846,6 +869,27 @@ type SystemUserAccountSearchResponse struct { @@ -846,6 +869,27 @@ type SystemUserAccountSearchResponse struct {
846 Total int64 `json:"total"` 869 Total int64 `json:"total"`
847 } 870 }
848 871
  872 +type MiniWechatInfoRequest struct {
  873 +}
  874 +
  875 +type MiniWechatInfoResponse struct {
  876 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  877 + OpenId string `json:"openId"` // 绑定的微信openId
  878 + Phone string `json:"phone"` // 绑定手机号
  879 +}
  880 +
  881 +type MiniWechatBindRequest struct {
  882 + WechatAuthCode string `json:"wechatAuthcode"` // 微信登录 授权码
  883 + WechatEncryptedData string `json:"wechatEncryptedData"` // 微信登录 加密数据
  884 + WechatIV string `json:"wechatIV"` // 微信登录 加密算法初始向量
  885 +}
  886 +
  887 +type MiniWechatBindResponse struct {
  888 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  889 + OpenId string `json:"openId"` // 绑定的微信openId
  890 + Phone string `json:"phone"` // 绑定手机号
  891 +}
  892 +
849 type CompanySearchRequest struct { 893 type CompanySearchRequest struct {
850 Page int `json:"page,optional"` 894 Page int `json:"page,optional"`
851 Size int `json:"size,optional"` 895 Size int `json:"size,optional"`
@@ -1727,9 +1771,10 @@ type DepartmentUpdateRequest struct { @@ -1727,9 +1771,10 @@ type DepartmentUpdateRequest struct {
1727 } 1771 }
1728 1772
1729 type DepartmentListRequest struct { 1773 type DepartmentListRequest struct {
1730 - Page int `json:"page"`  
1731 - Size int `json:"size"`  
1732 - IncludeRootCompany bool `json:"includeRootCompany,optional"` // 包含公司(把公司当作部门作为顶级节点 部门ID:0) 1774 + Page int `json:"page"`
  1775 + Size int `json:"size"`
  1776 + IncludeRootCompany bool `json:"includeRootCompany,optional"` // 包含公司(把公司当作部门作为顶级节点 部门ID:0)
  1777 + IncludeDefaultDepartment bool `json:"includeDefaultDepartment,optional"` // 包含默认分组
1733 } 1778 }
1734 1779
1735 type DepartmentListResponse struct { 1780 type DepartmentListResponse struct {
  1 +
  2 +syntax = "v1"
  3 +
  4 +info(
  5 + title: "xx实例"
  6 + desc: "xx实例"
  7 + author: "author"
  8 + email: "email"
  9 + version: "v1"
  10 +)
  11 +
  12 +@server(
  13 + prefix: message_subscribe/v1
  14 + group: message_subscribe
  15 + jwt: JwtAuth
  16 +)
  17 +service Core {
  18 + @handler getMessageSubscribe
  19 + post /message_subscribe/:id (MessageSubscribeGetRequest) returns (MessageSubscribeGetResponse)
  20 + @handler saveMessageSubscribe
  21 + post /message_subscribe (MessageSubscribeSaveRequest) returns (MessageSubscribeSaveResponse)
  22 + @handler deleteMessageSubscribe
  23 + delete /message_subscribe/:id (MessageSubscribeDeleteRequest) returns (MessageSubscribeDeleteResponse)
  24 + @handler updateMessageSubscribe
  25 + put /message_subscribe/:id (MessageSubscribeUpdateRequest) returns (MessageSubscribeUpdateResponse)
  26 + @handler searchMessageSubscribe
  27 + post /message_subscribe/search (MessageSubscribeSearchRequest) returns (MessageSubscribeSearchResponse)
  28 +}
  29 +
  30 +type (
  31 + MessageSubscribeGetRequest {
  32 + Id int64 `path:"id"`
  33 + }
  34 + MessageSubscribeGetResponse struct{
  35 + MessageSubscribe MessageSubscribeItem `json:"message_subscribe"`
  36 + }
  37 +
  38 + MessageSubscribeSaveRequest struct{
  39 + MessageSubscribe MessageSubscribeItem `json:"message_subscribe"`
  40 + }
  41 + MessageSubscribeSaveResponse struct{}
  42 +
  43 + MessageSubscribeDeleteRequest struct{
  44 + Id int64 `path:"id"`
  45 + }
  46 + MessageSubscribeDeleteResponse struct{}
  47 +
  48 + MessageSubscribeUpdateRequest struct{
  49 + Id int64 `path:"id"`
  50 + MessageSubscribe MessageSubscribeItem `json:"message_subscribe"`
  51 + }
  52 + MessageSubscribeUpdateResponse struct{}
  53 +
  54 + MessageSubscribeSearchRequest struct{
  55 + Page int `json:"page"`
  56 + Size int `json:"size"`
  57 + }
  58 + MessageSubscribeSearchResponse{
  59 + List []MessageSubscribeItem `json:"list"`
  60 + Total int64 `json:"total"`
  61 + }
  62 + MessageSubscribeItem struct{
  63 +
  64 + }
  65 +)
  1 +
  2 +syntax = "v1"
  3 +
  4 +info(
  5 + title: "xx实例"
  6 + desc: "xx实例"
  7 + author: "author"
  8 + email: "email"
  9 + version: "v1"
  10 +)
  11 +
  12 +@server(
  13 + prefix: user_subscribe/v1
  14 + group: user_subscribe
  15 + jwt: JwtAuth
  16 +)
  17 +service Core {
  18 + @handler getUserSubscribe
  19 + post /user_subscribe/:id (UserSubscribeGetRequest) returns (UserSubscribeGetResponse)
  20 + @handler saveUserSubscribe
  21 + post /user_subscribe (UserSubscribeSaveRequest) returns (UserSubscribeSaveResponse)
  22 + @handler deleteUserSubscribe
  23 + delete /user_subscribe/:id (UserSubscribeDeleteRequest) returns (UserSubscribeDeleteResponse)
  24 + @handler updateUserSubscribe
  25 + put /user_subscribe/:id (UserSubscribeUpdateRequest) returns (UserSubscribeUpdateResponse)
  26 + @handler searchUserSubscribe
  27 + post /user_subscribe/search (UserSubscribeSearchRequest) returns (UserSubscribeSearchResponse)
  28 +}
  29 +
  30 +type (
  31 + UserSubscribeGetRequest {
  32 + Id int64 `path:"id"`
  33 + }
  34 + UserSubscribeGetResponse struct{
  35 + UserSubscribe UserSubscribeItem `json:"user_subscribe"`
  36 + }
  37 +
  38 + UserSubscribeSaveRequest struct{
  39 + UserSubscribe UserSubscribeItem `json:"user_subscribe"`
  40 + }
  41 + UserSubscribeSaveResponse struct{}
  42 +
  43 + UserSubscribeDeleteRequest struct{
  44 + Id int64 `path:"id"`
  45 + }
  46 + UserSubscribeDeleteResponse struct{}
  47 +
  48 + UserSubscribeUpdateRequest struct{
  49 + Id int64 `path:"id"`
  50 + UserSubscribe UserSubscribeItem `json:"user_subscribe"`
  51 + }
  52 + UserSubscribeUpdateResponse struct{}
  53 +
  54 + UserSubscribeSearchRequest struct{
  55 + Page int `json:"page"`
  56 + Size int `json:"size"`
  57 + }
  58 + UserSubscribeSearchResponse{
  59 + List []UserSubscribeItem `json:"list"`
  60 + Total int64 `json:"total"`
  61 + }
  62 + UserSubscribeItem struct{
  63 +
  64 + }
  65 +)
  1 +
  2 +syntax = "v1"
  3 +
  4 +info(
  5 + title: "xx实例"
  6 + desc: "xx实例"
  7 + author: "author"
  8 + email: "email"
  9 + version: "v1"
  10 +)
  11 +
  12 +@server(
  13 + prefix: user_wechat/v1
  14 + group: user_wechat
  15 + jwt: JwtAuth
  16 +)
  17 +service Core {
  18 + @handler getUserWechat
  19 + post /user_wechat/:id (UserWechatGetRequest) returns (UserWechatGetResponse)
  20 + @handler saveUserWechat
  21 + post /user_wechat (UserWechatSaveRequest) returns (UserWechatSaveResponse)
  22 + @handler deleteUserWechat
  23 + delete /user_wechat/:id (UserWechatDeleteRequest) returns (UserWechatDeleteResponse)
  24 + @handler updateUserWechat
  25 + put /user_wechat/:id (UserWechatUpdateRequest) returns (UserWechatUpdateResponse)
  26 + @handler searchUserWechat
  27 + post /user_wechat/search (UserWechatSearchRequest) returns (UserWechatSearchResponse)
  28 +}
  29 +
  30 +type (
  31 + UserWechatGetRequest {
  32 + Id int64 `path:"id"`
  33 + }
  34 + UserWechatGetResponse struct{
  35 + UserWechat UserWechatItem `json:"user_wechat"`
  36 + }
  37 +
  38 + UserWechatSaveRequest struct{
  39 + UserWechat UserWechatItem `json:"user_wechat"`
  40 + }
  41 + UserWechatSaveResponse struct{}
  42 +
  43 + UserWechatDeleteRequest struct{
  44 + Id int64 `path:"id"`
  45 + }
  46 + UserWechatDeleteResponse struct{}
  47 +
  48 + UserWechatUpdateRequest struct{
  49 + Id int64 `path:"id"`
  50 + UserWechat UserWechatItem `json:"user_wechat"`
  51 + }
  52 + UserWechatUpdateResponse struct{}
  53 +
  54 + UserWechatSearchRequest struct{
  55 + Page int `json:"page"`
  56 + Size int `json:"size"`
  57 + }
  58 + UserWechatSearchResponse{
  59 + List []UserWechatItem `json:"list"`
  60 + Total int64 `json:"total"`
  61 + }
  62 + UserWechatItem struct{
  63 +
  64 + }
  65 +)
  1 +
  2 +syntax = "proto3";
  3 +
  4 +option go_package ="./pb";
  5 +
  6 +package pb;
  7 +
  8 +message MessageSubscribeGetReq {
  9 + int64 Id = 1;
  10 +}
  11 +message MessageSubscribeGetResp{
  12 + MessageSubscribeItem User = 1;
  13 +}
  14 +
  15 +message MessageSubscribeSaveReq {
  16 +
  17 +}
  18 +message MessageSubscribeSaveResp{
  19 +
  20 +}
  21 +
  22 +message MessageSubscribeDeleteReq {
  23 + int64 Id = 1;
  24 +}
  25 +message MessageSubscribeDeleteResp{
  26 +
  27 +}
  28 +
  29 +message MessageSubscribeUpdateReq {
  30 + int64 Id = 1;
  31 +}
  32 +message MessageSubscribeUpdateResp{
  33 +
  34 +}
  35 +
  36 +message MessageSubscribeSearchReq {
  37 + int64 PageNumber = 1;
  38 + int64 PageSize = 2;
  39 +}
  40 +message MessageSubscribeSearchResp{
  41 + repeated MessageSubscribeItem List =1;
  42 + int64 Total =2;
  43 +}
  44 +message MessageSubscribeItem {
  45 +
  46 +}
  47 +
  48 +service MessageSubscribeService {
  49 + rpc MessageSubscribeGet(MessageSubscribeGetReq) returns(MessageSubscribeGetResp);
  50 + rpc MessageSubscribeSave(MessageSubscribeSaveReq) returns(MessageSubscribeSaveResp);
  51 + rpc MessageSubscribeDelete(MessageSubscribeDeleteReq) returns(MessageSubscribeDeleteResp);
  52 + rpc MessageSubscribeUpdate(MessageSubscribeUpdateReq) returns(MessageSubscribeUpdateResp);
  53 + rpc MessageSubscribeSearch(MessageSubscribeSearchReq) returns(MessageSubscribeSearchResp);
  54 +}
  1 +
  2 +syntax = "proto3";
  3 +
  4 +option go_package ="./pb";
  5 +
  6 +package pb;
  7 +
  8 +message UserSubscribeGetReq {
  9 + int64 Id = 1;
  10 +}
  11 +message UserSubscribeGetResp{
  12 + UserSubscribeItem User = 1;
  13 +}
  14 +
  15 +message UserSubscribeSaveReq {
  16 +
  17 +}
  18 +message UserSubscribeSaveResp{
  19 +
  20 +}
  21 +
  22 +message UserSubscribeDeleteReq {
  23 + int64 Id = 1;
  24 +}
  25 +message UserSubscribeDeleteResp{
  26 +
  27 +}
  28 +
  29 +message UserSubscribeUpdateReq {
  30 + int64 Id = 1;
  31 +}
  32 +message UserSubscribeUpdateResp{
  33 +
  34 +}
  35 +
  36 +message UserSubscribeSearchReq {
  37 + int64 PageNumber = 1;
  38 + int64 PageSize = 2;
  39 +}
  40 +message UserSubscribeSearchResp{
  41 + repeated UserSubscribeItem List =1;
  42 + int64 Total =2;
  43 +}
  44 +message UserSubscribeItem {
  45 +
  46 +}
  47 +
  48 +service UserSubscribeService {
  49 + rpc UserSubscribeGet(UserSubscribeGetReq) returns(UserSubscribeGetResp);
  50 + rpc UserSubscribeSave(UserSubscribeSaveReq) returns(UserSubscribeSaveResp);
  51 + rpc UserSubscribeDelete(UserSubscribeDeleteReq) returns(UserSubscribeDeleteResp);
  52 + rpc UserSubscribeUpdate(UserSubscribeUpdateReq) returns(UserSubscribeUpdateResp);
  53 + rpc UserSubscribeSearch(UserSubscribeSearchReq) returns(UserSubscribeSearchResp);
  54 +}
  1 +
  2 +syntax = "proto3";
  3 +
  4 +option go_package ="./pb";
  5 +
  6 +package pb;
  7 +
  8 +message UserWechatGetReq {
  9 + int64 Id = 1;
  10 +}
  11 +message UserWechatGetResp{
  12 + UserWechatItem User = 1;
  13 +}
  14 +
  15 +message UserWechatSaveReq {
  16 +
  17 +}
  18 +message UserWechatSaveResp{
  19 +
  20 +}
  21 +
  22 +message UserWechatDeleteReq {
  23 + int64 Id = 1;
  24 +}
  25 +message UserWechatDeleteResp{
  26 +
  27 +}
  28 +
  29 +message UserWechatUpdateReq {
  30 + int64 Id = 1;
  31 +}
  32 +message UserWechatUpdateResp{
  33 +
  34 +}
  35 +
  36 +message UserWechatSearchReq {
  37 + int64 PageNumber = 1;
  38 + int64 PageSize = 2;
  39 +}
  40 +message UserWechatSearchResp{
  41 + repeated UserWechatItem List =1;
  42 + int64 Total =2;
  43 +}
  44 +message UserWechatItem {
  45 +
  46 +}
  47 +
  48 +service UserWechatService {
  49 + rpc UserWechatGet(UserWechatGetReq) returns(UserWechatGetResp);
  50 + rpc UserWechatSave(UserWechatSaveReq) returns(UserWechatSaveResp);
  51 + rpc UserWechatDelete(UserWechatDeleteReq) returns(UserWechatDeleteResp);
  52 + rpc UserWechatUpdate(UserWechatUpdateReq) returns(UserWechatUpdateResp);
  53 + rpc UserWechatSearch(UserWechatSearchReq) returns(UserWechatSearchResp);
  54 +}
@@ -24,8 +24,11 @@ func Migrate(db *gorm.DB) { @@ -24,8 +24,11 @@ func Migrate(db *gorm.DB) {
24 //&models.MessageBusiness{}, 24 //&models.MessageBusiness{},
25 //&models.Department{}, 25 //&models.Department{},
26 //&models.ArticleAndTag{}, 26 //&models.ArticleAndTag{},
27 - &models.ArticleDraftOperation{},  
28 - &models.ArticleCategory{}, 27 + //&models.ArticleDraftOperation{},
  28 + //&models.ArticleCategory{},
  29 + &models.UserSubscribe{},
  30 + &models.MessageSubscribe{},
  31 + &models.UserWechat{},
29 } 32 }
30 33
31 db.AutoMigrate(modelsList...) 34 db.AutoMigrate(modelsList...)
  1 +package models
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  6 + "gorm.io/gorm"
  7 + "gorm.io/plugin/soft_delete"
  8 +)
  9 +
  10 +type MessageSubscribe struct {
  11 + Id int64 `json:"id"` // 唯一标识
  12 + Type int `json:"type"` // 分类(1评论回复 2获赞 3关注人更新)
  13 + CompanyId int64 `json:"companyId"` // 公司ID
  14 + UserId int64 `json:"userId"` // 用户ID
  15 + OpenId string `json:"openId"` // 微信openID
  16 + TemplateId string `json:"templateId"` // 模板ID
  17 + TemplateData map[string]interface{} `json:"templateData" gorm:"serializer:json;type:text;"` // 模板参数
  18 + Result string `json:"result"` // 发送结果
  19 + Error string `json:"error"` // 调用接口错误信息
  20 + CreatedAt int64 `json:",omitempty"` // 创建时间
  21 + UpdatedAt int64 `json:",omitempty"` // 更新时间
  22 + DeletedAt int64 `json:",omitempty"` // 删除时间
  23 + Version int `json:",omitempty"` // 版本
  24 + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
  25 +}
  26 +
  27 +func (m *MessageSubscribe) TableName() string {
  28 + return "message_subscribe"
  29 +}
  30 +
  31 +func (m *MessageSubscribe) BeforeCreate(tx *gorm.DB) (err error) {
  32 + // m.CreatedAt = time.Now().Unix()
  33 + // m.UpdatedAt = time.Now().Unix()
  34 + return
  35 +}
  36 +
  37 +func (m *MessageSubscribe) BeforeUpdate(tx *gorm.DB) (err error) {
  38 + // m.UpdatedAt = time.Now().Unix()
  39 + return
  40 +}
  41 +
  42 +func (m *MessageSubscribe) CacheKeyFunc() string {
  43 + if m.Id == 0 {
  44 + return ""
  45 + }
  46 + return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
  47 +}
  48 +
  49 +func (m *MessageSubscribe) CacheKeyFuncByObject(obj interface{}) string {
  50 + if v, ok := obj.(*MessageSubscribe); ok {
  51 + return v.CacheKeyFunc()
  52 + }
  53 + return ""
  54 +}
  55 +
  56 +func (m *MessageSubscribe) CachePrimaryKeyFunc() string {
  57 + if len("") == 0 {
  58 + return ""
  59 + }
  60 + return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
  61 +}
  1 +package models
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  6 + "gorm.io/gorm"
  7 + "gorm.io/plugin/soft_delete"
  8 +)
  9 +
  10 +type UserSubscribe struct {
  11 + Id int64 `json:"id"` // 唯一标识
  12 + Type int `json:"type" gorm:"type:int;"` // 分类(1评论回复 2获赞 3关注人更新)
  13 + CompanyId int64 `json:"companyId"` // 公司ID
  14 + UserId int64 `json:"userId"` // 用户ID
  15 + Count int `json:"count" gorm:"type:int;"` // 订阅次数
  16 + CreatedAt int64 `json:",omitempty"` // 创建时间
  17 + UpdatedAt int64 `json:",omitempty"` // 更新时间
  18 + DeletedAt int64 `json:",omitempty"` // 删除时间
  19 + Version int `json:",omitempty"` // 版本
  20 + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
  21 +}
  22 +
  23 +func (m *UserSubscribe) TableName() string {
  24 + return "user_subscribe"
  25 +}
  26 +
  27 +func (m *UserSubscribe) BeforeCreate(tx *gorm.DB) (err error) {
  28 + // m.CreatedAt = time.Now().Unix()
  29 + // m.UpdatedAt = time.Now().Unix()
  30 + return
  31 +}
  32 +
  33 +func (m *UserSubscribe) BeforeUpdate(tx *gorm.DB) (err error) {
  34 + // m.UpdatedAt = time.Now().Unix()
  35 + return
  36 +}
  37 +
  38 +func (m *UserSubscribe) CacheKeyFunc() string {
  39 + if m.Id == 0 {
  40 + return ""
  41 + }
  42 + return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
  43 +}
  44 +
  45 +func (m *UserSubscribe) CacheKeyFuncByObject(obj interface{}) string {
  46 + if v, ok := obj.(*UserSubscribe); ok {
  47 + return v.CacheKeyFunc()
  48 + }
  49 + return ""
  50 +}
  51 +
  52 +func (m *UserSubscribe) CachePrimaryKeyFunc() string {
  53 + if len("") == 0 {
  54 + return ""
  55 + }
  56 + return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
  57 +}
  1 +package models
  2 +
  3 +import (
  4 + "fmt"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  6 + "gorm.io/gorm"
  7 + "gorm.io/plugin/soft_delete"
  8 +)
  9 +
  10 +type UserWechat struct {
  11 + Id int64 `json:"id"` // 唯一标识
  12 + OpenId string `json:"openId"` // 微信openId
  13 + Phone string `json:"phone" gorm:"unique"` // 微信手机号
  14 + CreatedAt int64 `json:",omitempty"` // 创建时间
  15 + UpdatedAt int64 `json:",omitempty"` // 更新时间
  16 + DeletedAt int64 `json:",omitempty"` // 删除时间
  17 + Version int `json:",omitempty"` // 版本
  18 + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
  19 +}
  20 +
  21 +func (m *UserWechat) TableName() string {
  22 + return "user_wechat"
  23 +}
  24 +
  25 +func (m *UserWechat) BeforeCreate(tx *gorm.DB) (err error) {
  26 + // m.CreatedAt = time.Now().Unix()
  27 + // m.UpdatedAt = time.Now().Unix()
  28 + return
  29 +}
  30 +
  31 +func (m *UserWechat) BeforeUpdate(tx *gorm.DB) (err error) {
  32 + // m.UpdatedAt = time.Now().Unix()
  33 + return
  34 +}
  35 +
  36 +func (m *UserWechat) CacheKeyFunc() string {
  37 + if m.Id == 0 {
  38 + return ""
  39 + }
  40 + return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
  41 +}
  42 +
  43 +func (m *UserWechat) CacheKeyFuncByObject(obj interface{}) string {
  44 + if v, ok := obj.(*UserWechat); ok {
  45 + return v.CacheKeyFunc()
  46 + }
  47 + return ""
  48 +}
  49 +
  50 +func (m *UserWechat) CachePrimaryKeyFunc() string {
  51 + if len("") == 0 {
  52 + return ""
  53 + }
  54 + return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
  55 +}
@@ -437,6 +437,28 @@ func (repository *ArticleCommentRepository) CustomSearchBy(ctx context.Context, @@ -437,6 +437,28 @@ func (repository *ArticleCommentRepository) CustomSearchBy(ctx context.Context,
437 437
438 } 438 }
439 439
  440 +// CommentUserCount 统计评论人数
  441 +func (repository *ArticleCommentRepository) CommentUserCount(ctx context.Context, conn transaction.Conn, companyId int64, articleId int64) (int64, error) {
  442 + var (
  443 + err error
  444 + tx = conn.DB()
  445 + c int64
  446 + )
  447 + err = tx.Model(&models.ArticleComment{}).Where("company_id = ? and article_id = ?", companyId, articleId).Group("from_user_id").Count(&c).Error
  448 + return c, err
  449 +}
  450 +
  451 +// ReplyUserCount 统计回复人数
  452 +func (repository *ArticleCommentRepository) ReplyUserCount(ctx context.Context, conn transaction.Conn, companyId int64, commentId int64) (int64, error) {
  453 + var (
  454 + err error
  455 + tx = conn.DB()
  456 + c int64
  457 + )
  458 + err = tx.Model(&models.ArticleComment{}).Where("company_id = ? and pid = ?", companyId, commentId).Group("from_user_id").Count(&c).Error
  459 + return c, err
  460 +}
  461 +
440 func NewArticleCommentRepository(cache *cache.CachedRepository) domain.ArticleCommentRepository { 462 func NewArticleCommentRepository(cache *cache.CachedRepository) domain.ArticleCommentRepository {
441 return &ArticleCommentRepository{CachedRepository: cache} 463 return &ArticleCommentRepository{CachedRepository: cache}
442 } 464 }
  1 +package repository
  2 +
  3 +import (
  4 + "context"
  5 + "github.com/jinzhu/copier"
  6 + "github.com/pkg/errors"
  7 + "github.com/tiptok/gocomm/pkg/cache"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/models"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  11 + "gorm.io/gorm"
  12 +)
  13 +
  14 +type MessageSubscribeRepository struct {
  15 + *cache.CachedRepository
  16 +}
  17 +
  18 +func (repository *MessageSubscribeRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
  19 + var (
  20 + err error
  21 + m = &models.MessageSubscribe{}
  22 + tx = conn.DB()
  23 + )
  24 + if m, err = repository.DomainModelToModel(dm); err != nil {
  25 + return nil, err
  26 + }
  27 + if tx = tx.Model(m).Save(m); tx.Error != nil {
  28 + return nil, tx.Error
  29 + }
  30 + dm.Id = m.Id
  31 + return repository.ModelToDomainModel(m)
  32 +
  33 +}
  34 +
  35 +func (repository *MessageSubscribeRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
  36 + var (
  37 + err error
  38 + m *models.MessageSubscribe
  39 + tx = conn.DB()
  40 + )
  41 + if m, err = repository.DomainModelToModel(dm); err != nil {
  42 + return nil, err
  43 + }
  44 + queryFunc := func() (interface{}, error) {
  45 + tx = tx.Model(m).Select("*").Updates(m)
  46 + return nil, tx.Error
  47 + }
  48 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  49 + return nil, err
  50 + }
  51 + return repository.ModelToDomainModel(m)
  52 +}
  53 +
  54 +func (repository *MessageSubscribeRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
  55 + var (
  56 + err error
  57 + m *models.MessageSubscribe
  58 + tx = transaction.DB()
  59 + )
  60 + if m, err = repository.DomainModelToModel(dm); err != nil {
  61 + return nil, err
  62 + }
  63 + oldVersion := dm.Version
  64 + m.Version += 1
  65 + queryFunc := func() (interface{}, error) {
  66 + tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
  67 + if tx.RowsAffected == 0 {
  68 + return nil, domain.ErrUpdateFail
  69 + }
  70 + return nil, tx.Error
  71 + }
  72 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  73 + return nil, err
  74 + }
  75 + return repository.ModelToDomainModel(m)
  76 +}
  77 +
  78 +func (repository *MessageSubscribeRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
  79 + var (
  80 + tx = conn.DB()
  81 + m = &models.MessageSubscribe{Id: dm.Identify().(int64)}
  82 + )
  83 + queryFunc := func() (interface{}, error) {
  84 + tx = tx.Where("id = ?", m.Id).Delete(m)
  85 + return m, tx.Error
  86 + }
  87 + if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  88 + return dm, err
  89 + }
  90 + return repository.ModelToDomainModel(m)
  91 +}
  92 +
  93 +func (repository *MessageSubscribeRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.MessageSubscribe, error) {
  94 + var (
  95 + err error
  96 + tx = conn.DB()
  97 + m = new(models.MessageSubscribe)
  98 + )
  99 + queryFunc := func() (interface{}, error) {
  100 + tx = tx.Model(m).Where("id = ?", id).First(m)
  101 + if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
  102 + return nil, domain.ErrNotFound
  103 + }
  104 + return m, tx.Error
  105 + }
  106 + cacheModel := new(models.MessageSubscribe)
  107 + cacheModel.Id = id
  108 + if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
  109 + return nil, err
  110 + }
  111 + return repository.ModelToDomainModel(m)
  112 +}
  113 +
  114 +func (repository *MessageSubscribeRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.MessageSubscribe, error) {
  115 + var (
  116 + tx = conn.DB()
  117 + ms []*models.MessageSubscribe
  118 + dms = make([]*domain.MessageSubscribe, 0)
  119 + total int64
  120 + )
  121 + queryFunc := func() (interface{}, error) {
  122 + tx = tx.Model(&ms).Order("id desc")
  123 + if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
  124 + return dms, tx.Error
  125 + }
  126 + return dms, nil
  127 + }
  128 +
  129 + if _, err := repository.Query(queryFunc); err != nil {
  130 + return 0, nil, err
  131 + }
  132 +
  133 + for _, item := range ms {
  134 + if dm, err := repository.ModelToDomainModel(item); err != nil {
  135 + return 0, dms, err
  136 + } else {
  137 + dms = append(dms, dm)
  138 + }
  139 + }
  140 + return total, dms, nil
  141 +}
  142 +
  143 +func (repository *MessageSubscribeRepository) ModelToDomainModel(from *models.MessageSubscribe) (*domain.MessageSubscribe, error) {
  144 + to := &domain.MessageSubscribe{}
  145 + err := copier.Copy(to, from)
  146 + return to, err
  147 +}
  148 +
  149 +func (repository *MessageSubscribeRepository) DomainModelToModel(from *domain.MessageSubscribe) (*models.MessageSubscribe, error) {
  150 + to := &models.MessageSubscribe{}
  151 + err := copier.Copy(to, from)
  152 + return to, err
  153 +}
  154 +
  155 +func NewMessageSubscribeRepository(cache *cache.CachedRepository) domain.MessageSubscribeRepository {
  156 + return &MessageSubscribeRepository{CachedRepository: cache}
  157 +}
@@ -174,7 +174,12 @@ func (repository *UserRepository) Find(ctx context.Context, conn transaction.Con @@ -174,7 +174,12 @@ func (repository *UserRepository) Find(ctx context.Context, conn transaction.Con
174 tx.Where("position = ? ", v) 174 tx.Where("position = ? ", v)
175 } 175 }
176 if v, ok := queryOptions["departmentId"]; ok { 176 if v, ok := queryOptions["departmentId"]; ok {
177 - tx.Where(fmt.Sprintf("departments @>'[%v]'", v)) 177 + // 未分组用户部门ID=0
  178 + if vi, okVi := v.(int64); okVi && vi == domain.DefaultDepartmentId {
  179 + tx.Where(fmt.Sprintf("departments = '[]'"))
  180 + } else {
  181 + tx.Where(fmt.Sprintf("departments @>'[%v]'", v))
  182 + }
178 } 183 }
179 if v, ok := queryOptions["roleId"]; ok { 184 if v, ok := queryOptions["roleId"]; ok {
180 tx.Where(fmt.Sprintf("roles @>'[%v]'", v)) 185 tx.Where(fmt.Sprintf("roles @>'[%v]'", v))
  1 +package repository
  2 +
  3 +import (
  4 + "context"
  5 + "github.com/jinzhu/copier"
  6 + "github.com/pkg/errors"
  7 + "github.com/tiptok/gocomm/pkg/cache"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/models"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  11 + "gorm.io/gorm"
  12 +)
  13 +
  14 +type UserSubscribeRepository struct {
  15 + *cache.CachedRepository
  16 +}
  17 +
  18 +func (repository *UserSubscribeRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
  19 + var (
  20 + err error
  21 + m = &models.UserSubscribe{}
  22 + tx = conn.DB()
  23 + )
  24 + if m, err = repository.DomainModelToModel(dm); err != nil {
  25 + return nil, err
  26 + }
  27 + if tx = tx.Model(m).Save(m); tx.Error != nil {
  28 + return nil, tx.Error
  29 + }
  30 + dm.Id = m.Id
  31 + return repository.ModelToDomainModel(m)
  32 +
  33 +}
  34 +
  35 +func (repository *UserSubscribeRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
  36 + var (
  37 + err error
  38 + m *models.UserSubscribe
  39 + tx = conn.DB()
  40 + )
  41 + if m, err = repository.DomainModelToModel(dm); err != nil {
  42 + return nil, err
  43 + }
  44 + queryFunc := func() (interface{}, error) {
  45 + tx = tx.Model(m).Select("*").Updates(m)
  46 + return nil, tx.Error
  47 + }
  48 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  49 + return nil, err
  50 + }
  51 + return repository.ModelToDomainModel(m)
  52 +}
  53 +
  54 +func (repository *UserSubscribeRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
  55 + var (
  56 + err error
  57 + m *models.UserSubscribe
  58 + tx = transaction.DB()
  59 + )
  60 + if m, err = repository.DomainModelToModel(dm); err != nil {
  61 + return nil, err
  62 + }
  63 + oldVersion := dm.Version
  64 + m.Version += 1
  65 + queryFunc := func() (interface{}, error) {
  66 + tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
  67 + if tx.RowsAffected == 0 {
  68 + return nil, domain.ErrUpdateFail
  69 + }
  70 + return nil, tx.Error
  71 + }
  72 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  73 + return nil, err
  74 + }
  75 + return repository.ModelToDomainModel(m)
  76 +}
  77 +
  78 +func (repository *UserSubscribeRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
  79 + var (
  80 + tx = conn.DB()
  81 + m = &models.UserSubscribe{Id: dm.Identify().(int64)}
  82 + )
  83 + queryFunc := func() (interface{}, error) {
  84 + tx = tx.Where("id = ?", m.Id).Delete(m)
  85 + return m, tx.Error
  86 + }
  87 + if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  88 + return dm, err
  89 + }
  90 + return repository.ModelToDomainModel(m)
  91 +}
  92 +
  93 +func (repository *UserSubscribeRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.UserSubscribe, error) {
  94 + var (
  95 + err error
  96 + tx = conn.DB()
  97 + m = new(models.UserSubscribe)
  98 + )
  99 + queryFunc := func() (interface{}, error) {
  100 + tx = tx.Model(m).Where("id = ?", id).First(m)
  101 + if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
  102 + return nil, domain.ErrNotFound
  103 + }
  104 + return m, tx.Error
  105 + }
  106 + cacheModel := new(models.UserSubscribe)
  107 + cacheModel.Id = id
  108 + if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
  109 + return nil, err
  110 + }
  111 + return repository.ModelToDomainModel(m)
  112 +}
  113 +
  114 +func (repository *UserSubscribeRepository) FindOneByType(ctx context.Context, conn transaction.Conn, companyId, userId int64, mType int) (*domain.UserSubscribe, error) {
  115 + var (
  116 + err error
  117 + tx = conn.DB()
  118 + m = new(models.UserSubscribe)
  119 + )
  120 + queryFunc := func() (interface{}, error) {
  121 + tx = tx.Model(m).Where("company_id = ? and user_id = ? and type = ?", companyId, userId, mType).First(m)
  122 + if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
  123 + return nil, domain.ErrNotFound
  124 + }
  125 + return m, tx.Error
  126 + }
  127 + cacheModel := new(models.UserSubscribe)
  128 + cacheModel.Id = m.Id
  129 + if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
  130 + return nil, err
  131 + }
  132 + return repository.ModelToDomainModel(m)
  133 +}
  134 +
  135 +func (repository *UserSubscribeRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.UserSubscribe, error) {
  136 + var (
  137 + tx = conn.DB()
  138 + ms []*models.UserSubscribe
  139 + dms = make([]*domain.UserSubscribe, 0)
  140 + total int64
  141 + )
  142 + queryFunc := func() (interface{}, error) {
  143 + tx = tx.Model(&ms).Order("id desc")
  144 + if v, ok := queryOptions["companyId"]; ok {
  145 + tx = tx.Where("company_id = ?", v)
  146 + }
  147 + if v, ok := queryOptions["userId"]; ok {
  148 + tx = tx.Where("user_id = ?", v)
  149 + }
  150 + if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
  151 + return dms, tx.Error
  152 + }
  153 + return dms, nil
  154 + }
  155 +
  156 + if _, err := repository.Query(queryFunc); err != nil {
  157 + return 0, nil, err
  158 + }
  159 +
  160 + for _, item := range ms {
  161 + if dm, err := repository.ModelToDomainModel(item); err != nil {
  162 + return 0, dms, err
  163 + } else {
  164 + dms = append(dms, dm)
  165 + }
  166 + }
  167 + return total, dms, nil
  168 +}
  169 +
  170 +func (repository *UserSubscribeRepository) ModelToDomainModel(from *models.UserSubscribe) (*domain.UserSubscribe, error) {
  171 + to := &domain.UserSubscribe{}
  172 + err := copier.Copy(to, from)
  173 + return to, err
  174 +}
  175 +
  176 +func (repository *UserSubscribeRepository) DomainModelToModel(from *domain.UserSubscribe) (*models.UserSubscribe, error) {
  177 + to := &models.UserSubscribe{}
  178 + err := copier.Copy(to, from)
  179 + return to, err
  180 +}
  181 +
  182 +func NewUserSubscribeRepository(cache *cache.CachedRepository) domain.UserSubscribeRepository {
  183 + return &UserSubscribeRepository{CachedRepository: cache}
  184 +}
  1 +package repository
  2 +
  3 +import (
  4 + "context"
  5 + "github.com/jinzhu/copier"
  6 + "github.com/pkg/errors"
  7 + "github.com/tiptok/gocomm/pkg/cache"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/models"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  11 + "gorm.io/gorm"
  12 +)
  13 +
  14 +type UserWechatRepository struct {
  15 + *cache.CachedRepository
  16 +}
  17 +
  18 +func (repository *UserWechatRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
  19 + var (
  20 + err error
  21 + m = &models.UserWechat{}
  22 + tx = conn.DB()
  23 + )
  24 + if m, err = repository.DomainModelToModel(dm); err != nil {
  25 + return nil, err
  26 + }
  27 + if tx = tx.Model(m).Save(m); tx.Error != nil {
  28 + return nil, tx.Error
  29 + }
  30 + dm.Id = m.Id
  31 + return repository.ModelToDomainModel(m)
  32 +
  33 +}
  34 +
  35 +func (repository *UserWechatRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
  36 + var (
  37 + err error
  38 + m *models.UserWechat
  39 + tx = conn.DB()
  40 + )
  41 + if m, err = repository.DomainModelToModel(dm); err != nil {
  42 + return nil, err
  43 + }
  44 + queryFunc := func() (interface{}, error) {
  45 + tx = tx.Model(m).Updates(m)
  46 + return nil, tx.Error
  47 + }
  48 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  49 + return nil, err
  50 + }
  51 + return repository.ModelToDomainModel(m)
  52 +}
  53 +
  54 +func (repository *UserWechatRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
  55 + var (
  56 + err error
  57 + m *models.UserWechat
  58 + tx = transaction.DB()
  59 + )
  60 + if m, err = repository.DomainModelToModel(dm); err != nil {
  61 + return nil, err
  62 + }
  63 + oldVersion := dm.Version
  64 + m.Version += 1
  65 + queryFunc := func() (interface{}, error) {
  66 + tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
  67 + if tx.RowsAffected == 0 {
  68 + return nil, domain.ErrUpdateFail
  69 + }
  70 + return nil, tx.Error
  71 + }
  72 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  73 + return nil, err
  74 + }
  75 + return repository.ModelToDomainModel(m)
  76 +}
  77 +
  78 +func (repository *UserWechatRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
  79 + var (
  80 + tx = conn.DB()
  81 + m = &models.UserWechat{Id: dm.Identify().(int64)}
  82 + )
  83 + queryFunc := func() (interface{}, error) {
  84 + tx = tx.Where("id = ?", m.Id).Delete(m)
  85 + return m, tx.Error
  86 + }
  87 + if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  88 + return dm, err
  89 + }
  90 + return repository.ModelToDomainModel(m)
  91 +}
  92 +
  93 +func (repository *UserWechatRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.UserWechat, error) {
  94 + var (
  95 + err error
  96 + tx = conn.DB()
  97 + m = new(models.UserWechat)
  98 + )
  99 + queryFunc := func() (interface{}, error) {
  100 + tx = tx.Model(m).Where("id = ?", id).First(m)
  101 + if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
  102 + return nil, domain.ErrNotFound
  103 + }
  104 + return m, tx.Error
  105 + }
  106 + cacheModel := new(models.UserWechat)
  107 + cacheModel.Id = id
  108 + if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
  109 + return nil, err
  110 + }
  111 + return repository.ModelToDomainModel(m)
  112 +}
  113 +
  114 +func (repository *UserWechatRepository) FindOneByPhone(ctx context.Context, conn transaction.Conn, phone string) (*domain.UserWechat, error) {
  115 + var (
  116 + err error
  117 + tx = conn.DB()
  118 + m = new(models.UserWechat)
  119 + )
  120 + queryFunc := func() (interface{}, error) {
  121 + tx = tx.Model(m).Where("phone = ?", phone).First(m)
  122 + if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
  123 + return nil, domain.ErrNotFound
  124 + }
  125 + return m, tx.Error
  126 + }
  127 + cacheModel := new(models.UserWechat)
  128 + cacheModel.Id = m.Id
  129 + if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
  130 + return nil, err
  131 + }
  132 + return repository.ModelToDomainModel(m)
  133 +}
  134 +
  135 +func (repository *UserWechatRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.UserWechat, error) {
  136 + var (
  137 + tx = conn.DB()
  138 + ms []*models.UserWechat
  139 + dms = make([]*domain.UserWechat, 0)
  140 + total int64
  141 + )
  142 + queryFunc := func() (interface{}, error) {
  143 + tx = tx.Model(&ms).Order("id desc")
  144 + if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
  145 + return dms, tx.Error
  146 + }
  147 + return dms, nil
  148 + }
  149 +
  150 + if _, err := repository.Query(queryFunc); err != nil {
  151 + return 0, nil, err
  152 + }
  153 +
  154 + for _, item := range ms {
  155 + if dm, err := repository.ModelToDomainModel(item); err != nil {
  156 + return 0, dms, err
  157 + } else {
  158 + dms = append(dms, dm)
  159 + }
  160 + }
  161 + return total, dms, nil
  162 +}
  163 +
  164 +func (repository *UserWechatRepository) ModelToDomainModel(from *models.UserWechat) (*domain.UserWechat, error) {
  165 + to := &domain.UserWechat{}
  166 + err := copier.Copy(to, from)
  167 + return to, err
  168 +}
  169 +
  170 +func (repository *UserWechatRepository) DomainModelToModel(from *domain.UserWechat) (*models.UserWechat, error) {
  171 + to := &models.UserWechat{}
  172 + err := copier.Copy(to, from)
  173 + return to, err
  174 +}
  175 +
  176 +func NewUserWechatRepository(cache *cache.CachedRepository) domain.UserWechatRepository {
  177 + return &UserWechatRepository{CachedRepository: cache}
  178 +}
@@ -131,6 +131,15 @@ func (m *Article) SetSummary(sectionList []*ArticleSection) { @@ -131,6 +131,15 @@ func (m *Article) SetSummary(sectionList []*ArticleSection) {
131 m.Summary = string(runeContent[0:length]) 131 m.Summary = string(runeContent[0:length])
132 } 132 }
133 133
  134 +// GetSubscribeMessageTitle 获取订阅消息标题 超过20个字用...
  135 +func (m *Article) GetSubscribeMessageTitle() string {
  136 + runeContent := []rune(m.Title)
  137 + if len(runeContent) > 20 {
  138 + return string(runeContent[0:20]) + "..."
  139 + }
  140 + return m.Title
  141 +}
  142 +
134 func (m *Article) WhoCanRead(userId int64) bool { 143 func (m *Article) WhoCanRead(userId int64) bool {
135 if m.AuthorId == userId { 144 if m.AuthorId == userId {
136 return true 145 return true
@@ -3,11 +3,8 @@ package domain @@ -3,11 +3,8 @@ package domain
3 import ( 3 import (
4 "bytes" 4 "bytes"
5 "context" 5 "context"
6 - "encoding/json"  
7 - "fmt"  
8 - "sort"  
9 -  
10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction" 6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  7 + "reflect"
11 ) 8 )
12 9
13 // 编辑文章后保存的历史记录 10 // 编辑文章后保存的历史记录
@@ -51,95 +48,119 @@ func (bk *ArticleBackup) CheckChangeField(oldBackup *ArticleBackup) bool { @@ -51,95 +48,119 @@ func (bk *ArticleBackup) CheckChangeField(oldBackup *ArticleBackup) bool {
51 bk.ChangeField = make([]string, 0) 48 bk.ChangeField = make([]string, 0)
52 //比较 WhoRead 49 //比较 WhoRead
53 { 50 {
54 - whoReadChanged := false  
55 - sort.Slice(bk.WhoRead, func(i, j int) bool {  
56 - return bk.WhoRead[i] < bk.WhoRead[j]  
57 - })  
58 - sort.Slice(oldBackup.WhoRead, func(i, j int) bool {  
59 - return oldBackup.WhoRead[i] < oldBackup.WhoRead[j]  
60 - })  
61 -  
62 - if len(bk.WhoRead) != len(oldBackup.WhoRead) {  
63 - whoReadChanged = true  
64 - } else {  
65 - for i := range bk.WhoRead {  
66 - if bk.WhoRead[i] != oldBackup.WhoRead[i] {  
67 - whoReadChanged = true  
68 - }  
69 - }  
70 - }  
71 - if whoReadChanged { 51 + //whoReadChanged := false
  52 + //sort.Slice(bk.WhoRead, func(i, j int) bool {
  53 + // return bk.WhoRead[i] < bk.WhoRead[j]
  54 + //})
  55 + //sort.Slice(oldBackup.WhoRead, func(i, j int) bool {
  56 + // return oldBackup.WhoRead[i] < oldBackup.WhoRead[j]
  57 + //})
  58 + //
  59 + //if len(bk.WhoRead) != len(oldBackup.WhoRead) {
  60 + // whoReadChanged = true
  61 + //} else {
  62 + // for i := range bk.WhoRead {
  63 + // if bk.WhoRead[i] != oldBackup.WhoRead[i] {
  64 + // whoReadChanged = true
  65 + // }
  66 + // }
  67 + //}
  68 + //if whoReadChanged {
  69 + // bk.ChangeField = append(bk.ChangeField, "WhoRead")
  70 + //}
  71 + if !reflect.DeepEqual(oldBackup.WhoRead, bk.WhoRead) {
72 bk.ChangeField = append(bk.ChangeField, "WhoRead") 72 bk.ChangeField = append(bk.ChangeField, "WhoRead")
73 } 73 }
74 } 74 }
75 75
76 //比较 whoReview 76 //比较 whoReview
77 { 77 {
78 - whoReviewChanged := false  
79 - sort.Slice(bk.WhoReview, func(i, j int) bool {  
80 - return bk.WhoReview[i] < bk.WhoReview[j]  
81 - })  
82 - sort.Slice(oldBackup.WhoReview, func(i, j int) bool {  
83 - return oldBackup.WhoReview[i] < oldBackup.WhoReview[j]  
84 - })  
85 -  
86 - if len(bk.WhoReview) != len(oldBackup.WhoReview) {  
87 - whoReviewChanged = true  
88 - } else {  
89 - for i := range bk.WhoReview {  
90 - if bk.WhoReview[i] != oldBackup.WhoReview[i] {  
91 - whoReviewChanged = true  
92 - }  
93 - }  
94 - }  
95 - if whoReviewChanged { 78 + //whoReviewChanged := false
  79 + //sort.Slice(bk.WhoReview, func(i, j int) bool {
  80 + // return bk.WhoReview[i] < bk.WhoReview[j]
  81 + //})
  82 + //sort.Slice(oldBackup.WhoReview, func(i, j int) bool {
  83 + // return oldBackup.WhoReview[i] < oldBackup.WhoReview[j]
  84 + //})
  85 + //
  86 + //if len(bk.WhoReview) != len(oldBackup.WhoReview) {
  87 + // whoReviewChanged = true
  88 + //} else {
  89 + // for i := range bk.WhoReview {
  90 + // if bk.WhoReview[i] != oldBackup.WhoReview[i] {
  91 + // whoReviewChanged = true
  92 + // }
  93 + // }
  94 + //}
  95 + //if whoReviewChanged {
  96 + // bk.ChangeField = append(bk.ChangeField, "WhoReview")
  97 + //}
  98 + if !reflect.DeepEqual(oldBackup.WhoReview, bk.WhoReview) {
96 bk.ChangeField = append(bk.ChangeField, "WhoReview") 99 bk.ChangeField = append(bk.ChangeField, "WhoReview")
97 } 100 }
98 } 101 }
99 //比较段落内容+图片+视频 是否发生变更 102 //比较段落内容+图片+视频 是否发生变更
100 { 103 {
101 - sectionChanged := false  
102 - newSectionData := map[string]string{  
103 - "title": bk.Title,  
104 - }  
105 -  
106 - oldSectionData := map[string]string{  
107 - "title": oldBackup.Title,  
108 - }  
109 -  
110 - for _, val := range bk.Section {  
111 - mkey := fmt.Sprintf("section-%d", val.SortBy)  
112 - newSectionData[mkey] = val.Content  
113 - }  
114 - for _, val := range bk.Images {  
115 - newSectionData[val.Url] = ""  
116 - }  
117 - for _, val := range bk.Videos {  
118 - newSectionData[val.Url] = ""  
119 - }  
120 -  
121 - for _, val := range oldBackup.Section {  
122 - mKey := fmt.Sprintf("section-%d", val.SortBy)  
123 - oldSectionData[mKey] = val.Content  
124 - }  
125 - for _, val := range oldBackup.Images {  
126 - oldSectionData[val.Url] = ""  
127 - }  
128 - for _, val := range oldBackup.Videos {  
129 - oldSectionData[val.Url] = ""  
130 - }  
131 - newSectionJson, _ := json.Marshal(newSectionData)  
132 - oldSectionJson, _ := json.Marshal(oldSectionData)  
133 - if ok := bytes.Equal(newSectionJson, oldSectionJson); !ok {  
134 - sectionChanged = true  
135 - }  
136 - if sectionChanged { 104 + //sectionChanged := false
  105 + //newSectionData := map[string]string{
  106 + // "title": bk.Title,
  107 + //}
  108 + //
  109 + //oldSectionData := map[string]string{
  110 + // "title": oldBackup.Title,
  111 + //}
  112 + //
  113 + //for _, val := range bk.Section {
  114 + // mkey := fmt.Sprintf("section-%d", val.SortBy)
  115 + // newSectionData[mkey] = val.Content
  116 + //}
  117 + //for _, val := range bk.Images {
  118 + // newSectionData[val.Url] = ""
  119 + //}
  120 + //for _, val := range bk.Videos {
  121 + // newSectionData[val.Url] = ""
  122 + //}
  123 + //
  124 + //for _, val := range oldBackup.Section {
  125 + // mKey := fmt.Sprintf("section-%d", val.SortBy)
  126 + // oldSectionData[mKey] = val.Content
  127 + //}
  128 + //for _, val := range oldBackup.Images {
  129 + // oldSectionData[val.Url] = ""
  130 + //}
  131 + //for _, val := range oldBackup.Videos {
  132 + // oldSectionData[val.Url] = ""
  133 + //}
  134 + //newSectionJson, _ := json.Marshal(newSectionData)
  135 + //oldSectionJson, _ := json.Marshal(oldSectionData)
  136 + //if ok := bytes.Equal(newSectionJson, oldSectionJson); !ok {
  137 + // sectionChanged = true
  138 + //}
  139 + //if sectionChanged {
  140 + // bk.ChangeField = append(bk.ChangeField, "Section")
  141 + //}
  142 + if !reflect.DeepEqual(backUpContent(bk), backUpContent(oldBackup)) {
137 bk.ChangeField = append(bk.ChangeField, "Section") 143 bk.ChangeField = append(bk.ChangeField, "Section")
138 } 144 }
139 } 145 }
140 return len(bk.ChangeField) > 0 146 return len(bk.ChangeField) > 0
141 } 147 }
142 148
  149 +func backUpContent(bk *ArticleBackup) string {
  150 + buf := bytes.NewBuffer(nil)
  151 + buf.WriteString(bk.Title)
  152 + for _, val := range bk.Images {
  153 + buf.WriteString(val.Url)
  154 + }
  155 + for _, val := range bk.Videos {
  156 + buf.WriteString(val.Url)
  157 + }
  158 + for _, val := range bk.Section {
  159 + buf.WriteString(val.Content)
  160 + }
  161 + return buf.String()
  162 +}
  163 +
143 // 创建备份信息 164 // 创建备份信息
144 func (bk *ArticleBackup) MakeBackup(operator UserSimple, article *Article, section []*ArticleSection, action string) { 165 func (bk *ArticleBackup) MakeBackup(operator UserSimple, article *Article, section []*ArticleSection, action string) {
145 sectionBackup := make([]ArticleSection, len(section)) 166 sectionBackup := make([]ArticleSection, len(section))
@@ -80,6 +80,10 @@ type ArticleCommentRepository interface { @@ -80,6 +80,10 @@ type ArticleCommentRepository interface {
80 // 特定的查询 80 // 特定的查询
81 CustomSearchBy(ctx context.Context, conn transaction.Conn, companyId int64, page int, size int, 81 CustomSearchBy(ctx context.Context, conn transaction.Conn, companyId int64, page int, size int,
82 topId int64, articleTitle string, contentLike string, fromUserId int64, show int, createdAtRange [2]int64) (int, []*ArticleCommentShow, error) 82 topId int64, articleTitle string, contentLike string, fromUserId int64, show int, createdAtRange [2]int64) (int, []*ArticleCommentShow, error)
  83 + // CommentUserCount 统计帖子评论人数
  84 + CommentUserCount(ctx context.Context, conn transaction.Conn, companyId int64, articleId int64) (int64, error)
  85 + // ReplyUserCount 统计评论回复人数
  86 + ReplyUserCount(ctx context.Context, conn transaction.Conn, companyId int64, commentId int64) (int64, error)
83 } 87 }
84 88
85 // 运营点数 填写的最大值 89 // 运营点数 填写的最大值
@@ -92,3 +96,12 @@ func (m *ArticleComment) MaxCountAdminLove(articleWhoRead int) int { @@ -92,3 +96,12 @@ func (m *ArticleComment) MaxCountAdminLove(articleWhoRead int) int {
92 } 96 }
93 return x 97 return x
94 } 98 }
  99 +
  100 +// GetSubscribeMessageContent 获取订阅消息评论内容 最多显示20个字,超出用...
  101 +func (m *ArticleComment) GetSubscribeMessageContent() string {
  102 + runeContent := []rune(m.Content)
  103 + if len(runeContent) > 20 {
  104 + return string(runeContent[0:20]) + "..."
  105 + }
  106 + return m.Content
  107 +}
@@ -31,3 +31,5 @@ func (m *Department) Identify() interface{} { @@ -31,3 +31,5 @@ func (m *Department) Identify() interface{} {
31 } 31 }
32 return m.Id 32 return m.Id
33 } 33 }
  34 +
  35 +const DefaultDepartmentId = -1
  1 +package domain
  2 +
  3 +import (
  4 + "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  6 + "gorm.io/plugin/soft_delete"
  7 +)
  8 +
  9 +type MessageSubscribe struct {
  10 + Id int64 `json:"id"` // 唯一标识
  11 + Type int `json:"type"` // 分类(1评论回复 2获赞 3关注人更新)
  12 + CompanyId int64 `json:"companyId"` // 公司ID
  13 + UserId int64 `json:"userId"` // 用户ID
  14 + OpenId string `json:"openId"` // 微信openID
  15 + TemplateId string `json:"templateId"` // 模板ID
  16 + TemplateData map[string]interface{} `json:"templateData"` // 模板参数
  17 + Result string `json:"result"` // 发送结果
  18 + Error string `json:"error"` // 调用接口错误信息
  19 + CreatedAt int64 `json:",omitempty"` // 创建时间
  20 + UpdatedAt int64 `json:",omitempty"` // 更新时间
  21 + DeletedAt int64 `json:",omitempty"` // 删除时间
  22 + Version int `json:",omitempty"` // 版本
  23 + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
  24 +}
  25 +
  26 +var (
  27 + SubscribeTypeReplyComment = 1 // 评论回复
  28 + SubscribeTypeLike = 2 // 点赞
  29 + SubscribeTypeFollow = 3 // 关注人更新
  30 +
  31 + SubscribeTemplateComment = "DxnQTZVHKrH7TOJiV-tK9w72hbkfLM87eXzhVy4cyhE" // 订阅消息 评论提醒
  32 + SubscribeTemplateLike = "oRdUINwfMK5_4ok_3lNgpkKT_SJqyGOvP4ZDgdsea9E" // 订阅消息 动态点赞通知
  33 + SubscribeTemplateFollow = "XdS11h2ZGGByzu-wMd16KxJ-LPjZy0yxZDmgQaVfDHE" // 订阅消息 关注更新提醒
  34 +)
  35 +
  36 +type MessageSubscribeRepository interface {
  37 + Insert(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
  38 + Update(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
  39 + UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
  40 + Delete(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
  41 + FindOne(ctx context.Context, conn transaction.Conn, id int64) (*MessageSubscribe, error)
  42 + Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*MessageSubscribe, error)
  43 +}
  44 +
  45 +func (m *MessageSubscribe) Identify() interface{} {
  46 + if m.Id == 0 {
  47 + return nil
  48 + }
  49 + return m.Id
  50 +}
@@ -151,6 +151,7 @@ type ( @@ -151,6 +151,7 @@ type (
151 PhonePasswordLogin(phone string, password string) (*LoginInfo, error) 151 PhonePasswordLogin(phone string, password string) (*LoginInfo, error)
152 PhoneSmsCodeLogin(phone string, code string) (*LoginInfo, error) 152 PhoneSmsCodeLogin(phone string, code string) (*LoginInfo, error)
153 WechatPhoneLogin(r WechatLoginRequest) (*LoginInfo, error) 153 WechatPhoneLogin(r WechatLoginRequest) (*LoginInfo, error)
  154 + GetOpenId(r WechatLoginRequest) (string, error)
154 } 155 }
155 WechatLoginRequest struct { 156 WechatLoginRequest struct {
156 Code string // 授权码 157 Code string // 授权码
  1 +package domain
  2 +
  3 +import (
  4 + "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  6 + "gorm.io/plugin/soft_delete"
  7 +)
  8 +
  9 +type UserSubscribe struct {
  10 + Id int64 `json:"id"` // 唯一标识
  11 + Type int `json:"type"` // 分类(1评论回复 2获赞 3关注人更新)
  12 + CompanyId int64 `json:"companyId"` // 公司ID
  13 + UserId int64 `json:"userId"` // 用户ID
  14 + Count int `json:"count"` // 订阅次数
  15 + CreatedAt int64 `json:",omitempty"` // 创建时间
  16 + UpdatedAt int64 `json:",omitempty"` // 更新时间
  17 + DeletedAt int64 `json:",omitempty"` // 删除时间
  18 + Version int `json:",omitempty"` // 版本
  19 + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
  20 +}
  21 +
  22 +type UserSubscribeRepository interface {
  23 + Insert(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
  24 + Update(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
  25 + UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
  26 + Delete(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
  27 + FindOne(ctx context.Context, conn transaction.Conn, id int64) (*UserSubscribe, error)
  28 + FindOneByType(ctx context.Context, conn transaction.Conn, companyId, userId int64, mType int) (*UserSubscribe, error)
  29 + Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*UserSubscribe, error)
  30 +}
  31 +
  32 +func (m *UserSubscribe) Identify() interface{} {
  33 + if m.Id == 0 {
  34 + return nil
  35 + }
  36 + return m.Id
  37 +}
  1 +package domain
  2 +
  3 +import (
  4 + "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  6 + "gorm.io/plugin/soft_delete"
  7 +)
  8 +
  9 +type UserWechat struct {
  10 + Id int64 `json:"id"` // 唯一标识
  11 + OpenId string `json:"openId"` // 微信openId
  12 + Phone string `json:"phone"` // 微信手机号
  13 + CreatedAt int64 `json:",omitempty"` // 创建时间
  14 + UpdatedAt int64 `json:",omitempty"` // 更新时间
  15 + DeletedAt int64 `json:",omitempty"` // 删除时间
  16 + Version int `json:",omitempty"` // 版本
  17 + IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
  18 +}
  19 +
  20 +type UserWechatRepository interface {
  21 + Insert(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
  22 + Update(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
  23 + UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
  24 + Delete(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
  25 + FindOne(ctx context.Context, conn transaction.Conn, id int64) (*UserWechat, error)
  26 + FindOneByPhone(ctx context.Context, conn transaction.Conn, phone string) (*UserWechat, error)
  27 + Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*UserWechat, error)
  28 +}
  29 +
  30 +func (m *UserWechat) Identify() interface{} {
  31 + if m.Id == 0 {
  32 + return nil
  33 + }
  34 + return m.Id
  35 +}
1 -CREATE TABLE `department` (  
2 - `id` int(0) NOT NULL COMMENT '唯一标识',  
3 - PRIMARY KEY (`id`) USING BTREE 1 +CREATE TABLE `department`
  2 +(
  3 + `id` int(0) NOT NULL COMMENT '唯一标识',
  4 + PRIMARY KEY (`id`) USING BTREE
4 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 5 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
5 6
6 -CREATE TABLE `role` (  
7 - `id` int(0) NOT NULL COMMENT '唯一标识',  
8 - PRIMARY KEY (`id`) USING BTREE 7 +CREATE TABLE `role`
  8 +(
  9 + `id` int(0) NOT NULL COMMENT '唯一标识',
  10 + PRIMARY KEY (`id`) USING BTREE
9 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 11 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
10 12
11 -CREATE TABLE `user` (  
12 - `id` int(0) NOT NULL COMMENT '唯一标识',  
13 - PRIMARY KEY (`id`) USING BTREE 13 +CREATE TABLE `user`
  14 +(
  15 + `id` int(0) NOT NULL COMMENT '唯一标识',
  16 + PRIMARY KEY (`id`) USING BTREE
14 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 17 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
15 18
16 -CREATE TABLE `user_role` (  
17 - `id` int(0) NOT NULL COMMENT '唯一标识',  
18 - PRIMARY KEY (`id`) USING BTREE 19 +CREATE TABLE `user_role`
  20 +(
  21 + `id` int(0) NOT NULL COMMENT '唯一标识',
  22 + PRIMARY KEY (`id`) USING BTREE
19 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 23 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
20 24
21 -CREATE TABLE `company` (  
22 - `id` int(0) NOT NULL COMMENT '唯一标识',  
23 - PRIMARY KEY (`id`) USING BTREE 25 +CREATE TABLE `company`
  26 +(
  27 + `id` int(0) NOT NULL COMMENT '唯一标识',
  28 + PRIMARY KEY (`id`) USING BTREE
24 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 29 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
25 30
26 -CREATE TABLE `user_follow` (  
27 - `id` int(0) NOT NULL COMMENT '唯一标识',  
28 - PRIMARY KEY (`id`) USING BTREE 31 +CREATE TABLE `user_follow`
  32 +(
  33 + `id` int(0) NOT NULL COMMENT '唯一标识',
  34 + PRIMARY KEY (`id`) USING BTREE
29 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 35 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
30 36
31 -CREATE TABLE `article_draft_operation` (  
32 - `id` int(0) NOT NULL COMMENT '唯一标识',  
33 - PRIMARY KEY (`id`) USING BTREE 37 +CREATE TABLE `article_draft_operation`
  38 +(
  39 + `id` int(0) NOT NULL COMMENT '唯一标识',
  40 + PRIMARY KEY (`id`) USING BTREE
34 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 41 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
35 42
36 -CREATE TABLE `article_category` (  
37 - `id` int(0) NOT NULL COMMENT '唯一标识',  
38 - PRIMARY KEY (`id`) USING BTREE 43 +CREATE TABLE `article_category`
  44 +(
  45 + `id` int(0) NOT NULL COMMENT '唯一标识',
  46 + PRIMARY KEY (`id`) USING BTREE
  47 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  48 +
  49 +CREATE TABLE `message_subscribe`
  50 +(
  51 + `id` int(0) NOT NULL COMMENT '唯一标识',
  52 + PRIMARY KEY (`id`) USING BTREE
  53 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  54 +
  55 +CREATE TABLE `user_subscribe`
  56 +(
  57 + `id` int(0) NOT NULL COMMENT '唯一标识',
  58 + PRIMARY KEY (`id`) USING BTREE
  59 +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
  60 +
  61 +CREATE TABLE `user_wechat`
  62 +(
  63 + `id` int(0) NOT NULL COMMENT '唯一标识',
  64 + PRIMARY KEY (`id`) USING BTREE
39 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; 65 ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;