作者 zhuangmx

消息订阅

正在显示 39 个修改的文件 包含 2049 行增加20 行删除
@@ -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(
@@ -524,3 +531,29 @@ type( @@ -524,3 +531,29 @@ type(
524 Total int64 `json:"total"` 531 Total int64 `json:"total"`
525 } 532 }
526 ) 533 )
  534 +
  535 +// 检测微信绑定信息
  536 +type (
  537 + MiniWechatInfoRequest {
  538 +
  539 + }
  540 + MiniWechatInfoResponse {
  541 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  542 + OpenId string `json:"openId"` // 绑定的微信openId
  543 + Phone string `json:"phone"` // 绑定手机号
  544 + }
  545 +)
  546 +
  547 +// 绑定微信账号
  548 +type (
  549 + MiniWechatBindRequest {
  550 + WechatAuthCode string `json:"wechatAuthcode"` // 微信登录 授权码
  551 + WechatEncryptedData string `json:"wechatEncryptedData"` // 微信登录 加密数据
  552 + WechatIV string `json:"wechatIV"` // 微信登录 加密算法初始向量
  553 + }
  554 + MiniWechatBindResponse {
  555 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  556 + OpenId string `json:"openId"` // 绑定的微信openId
  557 + Phone string `json:"phone"` // 绑定手机号
  558 + }
  559 +)
  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 +}
@@ -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
  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 +// saveMessage 保存订阅消息
  58 +func (l *MiniSubscribeLogic) saveMessage(conn transaction.Conn, companyId, userId int64, mType int, msg *subscribe.Message, sendErr error) 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 + if sendErr != nil {
  70 + subscribeMessage.Result = "fail"
  71 + subscribeMessage.Error = sendErr.Error()
  72 + } else {
  73 + subscribeMessage.Result = "ok"
  74 + }
  75 + _, err := l.svcCtx.MessageSubscribeRepository.Insert(l.ctx, conn, subscribeMessage)
  76 + return err
  77 +}
  78 +
  79 +func (l *MiniSubscribeLogic) messageSubscribe(companyId, userId int64, mType int) *domain.MessageSubscribe {
  80 + return &domain.MessageSubscribe{
  81 + Type: mType,
  82 + CompanyId: companyId,
  83 + UserId: userId,
  84 + }
  85 +}
  86 +
  87 +// getReplyCommentUserInfo 获取评论消息用户信息 用户名称+职位 例:张三-董事办
  88 +func (l *MiniSubscribeLogic) getReplyCommentUserInfo(conn transaction.Conn, companyId, userId int64) (string, error) {
  89 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
  90 + if err != nil {
  91 + return "", xerr.NewErrMsgErr("获取评论用户信息失败", err)
  92 + }
  93 + users := []string{userInfo.Name}
  94 + if len(userInfo.Roles) > 0 {
  95 + _, roles, err := l.svcCtx.RoleRepository.Find(l.ctx, conn, domain.IndexCompanyId(companyId)().MustWithKV("ids", userInfo.Roles))
  96 + if err == nil && len(roles) > 0 {
  97 + roleNames := make([]string, 0)
  98 + for _, item := range roles {
  99 + roleNames = append(roleNames, item.Name)
  100 + }
  101 + users = append(users, strings.Join(roleNames, "、"))
  102 + }
  103 + }
  104 + return strings.Join(users, "-"), nil
  105 +}
  106 +
  107 +// ReplyComment 发送评论订阅消息
  108 +// @param conn 数据库连接
  109 +// @param article 文章
  110 +// @param comment 评论
  111 +func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain.Article, comment *domain.ArticleComment) error {
  112 + subCtx := l.getSubScribe()
  113 + //评论用户+职位 例: 张三-董事办
  114 + fromUserName, err := l.getReplyCommentUserInfo(conn, comment.CompanyId, comment.FromUserId)
  115 + if err != nil {
  116 + return xerr.NewErrMsgErr("发送消息失败", err)
  117 + }
  118 + //评论消息
  119 + msg := &subscribe.Message{
  120 + TemplateID: domain.SubscribeTemplateComment,
  121 + Data: map[string]*subscribe.DataItem{
  122 + //文章标题
  123 + "thing1": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
  124 + //评论内容
  125 + "thing2": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
  126 + //评论时间
  127 + "thing3": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  128 + //评论用户
  129 + "thing5": &subscribe.DataItem{Value: fromUserName},
  130 + //备注
  131 + "thing9": &subscribe.DataItem{Value: ""},
  132 + },
  133 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  134 + }
  135 + //发帖人接收消息
  136 + openId, err := l.getOpenId(conn, article.AuthorId)
  137 + //未绑定微信号,直接返回
  138 + if err == nil && openId != "" {
  139 + msg.ToUser = openId
  140 + msg.Page = fmt.Sprintf("/pages/detail/more-comment?id=%v", article.Id) //跳转页面 帖子评论聚合页
  141 + //备注
  142 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的帖子最近已有%v人评论,点击查看详情", article.CountComment)}
  143 + //发送微信订阅消息
  144 + err = subCtx.Send(msg)
  145 + err = l.saveMessage(conn, comment.CompanyId, article.AuthorId, domain.SubscribeTypeReplyComment, msg, err)
  146 + if err != nil {
  147 + return xerr.NewErrMsgErr("评论失败", err)
  148 + }
  149 + }
  150 + //评论回复
  151 + if comment.Pid > 0 {
  152 + toOpenId, err := l.getOpenId(conn, comment.ToUserId)
  153 + if err == nil && toOpenId != "" {
  154 + msg.ToUser = toOpenId
  155 + msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面评论聚合页
  156 + //备注
  157 + parent, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, comment.Pid)
  158 + if err == nil && parent.Id > 0 {
  159 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的评论最近已有%v人回复,点击查看详情", parent.CountReply)}
  160 + //发送微信订阅消息
  161 + err = subCtx.Send(msg)
  162 + err = l.saveMessage(conn, comment.CompanyId, comment.ToUserId, domain.SubscribeTypeReplyComment, msg, err)
  163 + if err != nil {
  164 + return xerr.NewErrMsgErr("评论失败", err)
  165 + }
  166 + }
  167 + }
  168 + }
  169 + //@消息
  170 + if len(comment.AtWho) > 0 {
  171 + for _, at := range comment.AtWho {
  172 + atOpenId, err := l.getOpenId(conn, at.Id)
  173 + //未绑定微信跳过
  174 + if err != nil || atOpenId == "" {
  175 + continue
  176 + }
  177 + msg.ToUser = atOpenId
  178 + msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面 评论详情页
  179 + //备注
  180 + msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("%v在评论中提到了你", comment.FromUser.Name)}
  181 + //发送微信订阅消息
  182 + err = subCtx.Send(msg)
  183 + err = l.saveMessage(conn, comment.CompanyId, at.Id, domain.SubscribeTypeReplyComment, msg, err)
  184 + if err != nil {
  185 + return xerr.NewErrMsgErr("评论失败", err)
  186 + }
  187 + }
  188 + }
  189 + return nil
  190 +}
  191 +
  192 +// LikeArticle 帖子点赞订阅消息
  193 +func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.Article, userInfo *domain.User) error {
  194 + subCtx := l.getSubScribe()
  195 + openId, err := l.getOpenId(conn, article.AuthorId)
  196 + if err != nil || openId == "" {
  197 + return nil
  198 + }
  199 + msg := &subscribe.Message{
  200 + ToUser: openId,
  201 + TemplateID: domain.SubscribeTemplateLike,
  202 + Page: fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
  203 + Data: map[string]*subscribe.DataItem{
  204 + //点赞用户
  205 + "name1": &subscribe.DataItem{Value: userInfo.Name},
  206 + //点赞时间
  207 + "data2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  208 + //动态内容
  209 + "thing8": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
  210 + //被赞次数
  211 + "number4": &subscribe.DataItem{Value: article.CountLove},
  212 + //温馨提示
  213 + "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
  214 + },
  215 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  216 + }
  217 + err = subCtx.Send(msg)
  218 + err = l.saveMessage(conn, article.CompanyId, article.AuthorId, domain.SubscribeTypeLike, msg, err)
  219 + if err != nil {
  220 + return xerr.NewErrMsgErr("点赞失败", err)
  221 + }
  222 + return nil
  223 +}
  224 +
  225 +// LikeComment 点赞评论订阅消息
  226 +func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.ArticleComment, userInfo *domain.User) error {
  227 + subCtx := l.getSubScribe()
  228 + openId, err := l.getOpenId(conn, comment.FromUserId)
  229 + if err != nil || openId == "" {
  230 + return nil
  231 + }
  232 + msg := &subscribe.Message{
  233 + ToUser: openId,
  234 + TemplateID: domain.SubscribeTemplateLike,
  235 + Page: fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", comment.ArticleId, comment.Id),
  236 + Data: map[string]*subscribe.DataItem{
  237 + //点赞用户
  238 + "name1": &subscribe.DataItem{Value: userInfo.Name},
  239 + //点赞时间
  240 + "data2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  241 + //动态内容
  242 + "thing8": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
  243 + //被赞次数
  244 + "number4": &subscribe.DataItem{Value: comment.CountUserLove},
  245 + //温馨提示
  246 + "thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
  247 + },
  248 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  249 + }
  250 + err = subCtx.Send(msg)
  251 + err = l.saveMessage(conn, comment.CompanyId, comment.FromUserId, domain.SubscribeTypeLike, msg, err)
  252 + if err != nil {
  253 + return xerr.NewErrMsgErr("点赞失败", err)
  254 + }
  255 + return nil
  256 +}
  257 +
  258 +// FollowArticle 发帖关注更新提醒
  259 +func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domain.Article) error {
  260 + subCtx := l.getSubScribe()
  261 + //获取关注帖子作者的人员
  262 + _, userInfo, err := l.svcCtx.UserFollowRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("toUserIds", []int64{article.AuthorId}))
  263 + if err == nil && len(userInfo) > 0 {
  264 + for _, item := range userInfo {
  265 + openId, err := l.getOpenId(conn, item.FromUserId)
  266 + if err != nil || openId == "" {
  267 + continue
  268 + }
  269 + msg := &subscribe.Message{
  270 + ToUser: openId,
  271 + TemplateID: domain.SubscribeTemplateFollow,
  272 + Page: fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
  273 + Data: map[string]*subscribe.DataItem{
  274 + //创作者
  275 + "thing1": &subscribe.DataItem{Value: article.Author.Name},
  276 + //作品名称
  277 + "thing2": &subscribe.DataItem{Value: article.Title},
  278 + //内容摘要
  279 + "thing5": &subscribe.DataItem{Value: ""},
  280 + //发布时间
  281 + "thing6": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
  282 + //温馨提示
  283 + "thing3": &subscribe.DataItem{Value: "你关注的人发布了新的帖子"},
  284 + },
  285 + MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
  286 + }
  287 + err = subCtx.Send(msg)
  288 + err = l.saveMessage(conn, article.CompanyId, item.FromUserId, domain.SubscribeTypeFollow, msg, err)
  289 + if err != nil {
  290 + return xerr.NewErrMsgErr("保存订阅消息失败", err)
  291 + }
  292 + }
  293 + }
  294 + return nil
  295 +}
@@ -2,10 +2,10 @@ package user @@ -2,10 +2,10 @@ package user
2 2
3 import ( 3 import (
4 "context" 4 "context"
5 - "fmt"  
6 "github.com/silenceper/wechat/v2" 5 "github.com/silenceper/wechat/v2"
7 "github.com/silenceper/wechat/v2/cache" 6 "github.com/silenceper/wechat/v2/cache"
8 miniConfig "github.com/silenceper/wechat/v2/miniprogram/config" 7 miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
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/domain"
10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/smslib" 10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/smslib"
11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool" 11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool"
@@ -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:
@@ -53,6 +53,11 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res @@ -53,6 +53,11 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res
53 53
54 var users []*domain.User 54 var users []*domain.User
55 conn := l.svcCtx.DefaultDBConn() 55 conn := l.svcCtx.DefaultDBConn()
  56 + //保存微信用户信息
  57 + err = saveUserWechat(l.svcCtx, l.ctx, conn, loginInfo)
  58 + if err != nil {
  59 + return nil, err
  60 + }
56 _, users, err = l.svcCtx.UserRepository.Find(l.ctx, conn, domain.NewQueryOptions(). 61 _, users, err = l.svcCtx.UserRepository.Find(l.ctx, conn, domain.NewQueryOptions().
57 MustWithKV("phone", loginInfo.Phone). 62 MustWithKV("phone", loginInfo.Phone).
58 MustWithKV("auditStatus", []int{domain.UserAuditStatusWait, domain.UserAuditStatusPassed}). 63 MustWithKV("auditStatus", []int{domain.UserAuditStatusWait, domain.UserAuditStatusPassed}).
@@ -87,6 +92,23 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res @@ -87,6 +92,23 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res
87 return 92 return
88 } 93 }
89 94
  95 +// saveUserWechat 保存微信授权信息
  96 +func saveUserWechat(svcCtx *svc.ServiceContext, ctx context.Context, conn transaction.Conn, loginInfo *domain.LoginInfo) error {
  97 + if loginInfo.Phone != "" && loginInfo.OpenId != "" {
  98 + _, err := svcCtx.UserWechatRepository.FindOneByPhone(ctx, conn, loginInfo.Phone)
  99 + if err != nil { // 未存储
  100 + _, err = svcCtx.UserWechatRepository.Insert(ctx, conn, &domain.UserWechat{
  101 + OpenId: loginInfo.OpenId,
  102 + Phone: loginInfo.Phone,
  103 + })
  104 + if err != nil {
  105 + return err
  106 + }
  107 + }
  108 + }
  109 + return nil
  110 +}
  111 +
90 func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string, err error) { 112 func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string, err error) {
91 var userJwtToken = tool.UserToken{} 113 var userJwtToken = tool.UserToken{}
92 if user != nil { 114 if user != nil {
@@ -102,7 +124,8 @@ func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string, @@ -102,7 +124,8 @@ func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string,
102 } 124 }
103 125
104 type WxClientLogin struct { 126 type WxClientLogin struct {
105 - l *MiniUserLoginLogic 127 + svcCtx *svc.ServiceContext
  128 + ctx context.Context
106 } 129 }
107 130
108 func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.LoginInfo, error) { 131 func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.LoginInfo, error) {
@@ -111,18 +134,29 @@ func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.Lo @@ -111,18 +134,29 @@ func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.Lo
111 Phone: "", 134 Phone: "",
112 } 135 }
113 miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{ 136 miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
114 - AppID: c.l.svcCtx.Config.Wechat.AppID,  
115 - AppSecret: c.l.svcCtx.Config.Wechat.AppSecret, 137 + AppID: c.svcCtx.Config.Wechat.AppID,
  138 + AppSecret: c.svcCtx.Config.Wechat.AppSecret,
116 Cache: cache.NewMemory(), 139 Cache: cache.NewMemory(),
117 }) 140 })
118 - authResult, err := miniprogram.GetAuth().GetPhoneNumber(code) 141 + result, err := miniprogram.GetAuth().Code2Session(code)
  142 + if err != nil {
  143 + return nil, xerr.NewErrMsgErr("发起授权请求失败", err)
  144 + }
  145 + plainData, err := miniprogram.GetEncryptor().Decrypt(result.SessionKey, r.EncryptedData, r.IV)
  146 + if err != nil {
  147 + return nil, xerr.NewErrMsgErr("获取授权用户失败", err)
  148 + }
  149 + //增加微信用户openId
  150 + response.OpenId = plainData.OpenID
  151 + response.Phone = plainData.PhoneNumber
  152 + /*authResult, err := miniprogram.GetAuth().GetPhoneNumber(code)
119 if err != nil || authResult.ErrCode != 0 || authResult.PhoneInfo.PhoneNumber == "" { 153 if err != nil || authResult.ErrCode != 0 || authResult.PhoneInfo.PhoneNumber == "" {
120 return response, xerr.NewCodeErrMsg(xerr.ErrWxMiniAuthFailError, nil, fmt.Sprintf("发起授权请求失败1 err : %v , code : %s , authResult : %+v", err, code, authResult)) 154 return response, xerr.NewCodeErrMsg(xerr.ErrWxMiniAuthFailError, nil, fmt.Sprintf("发起授权请求失败1 err : %v , code : %s , authResult : %+v", err, code, authResult))
121 } 155 }
122 var ( 156 var (
123 phone = authResult.PhoneInfo.PhoneNumber 157 phone = authResult.PhoneInfo.PhoneNumber
124 ) 158 )
125 - response.Phone = phone 159 + response.Phone = phone*/
126 return response, nil 160 return response, nil
127 } 161 }
128 162
@@ -139,10 +173,10 @@ func (c WxClientLogin) PhoneSmsCodeLogin(phone string, code string) (*domain.Log @@ -139,10 +173,10 @@ func (c WxClientLogin) PhoneSmsCodeLogin(phone string, code string) (*domain.Log
139 err error 173 err error
140 skipCheckSmsCode bool = false 174 skipCheckSmsCode bool = false
141 ) 175 )
142 - if c.l.svcCtx.Config.DebugSmsCode != "" && c.l.svcCtx.Config.DebugSmsCode == code { 176 + if c.svcCtx.Config.DebugSmsCode != "" && c.svcCtx.Config.DebugSmsCode == code {
143 skipCheckSmsCode = true 177 skipCheckSmsCode = true
144 } 178 }
145 - if _, err = c.l.svcCtx.SmsService.CheckSmsCode(c.l.ctx, smslib.RequestCheckSmsCode{Phone: phone, Code: code}); err != nil && !skipCheckSmsCode { 179 + 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) 180 return nil, xerr.NewErrMsgErr(err.Error(), err)
147 } 181 }
148 response := &domain.LoginInfo{ 182 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/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 MiniWechatBindLogic struct {
  15 + logx.Logger
  16 + ctx context.Context
  17 + svcCtx *svc.ServiceContext
  18 +}
  19 +
  20 +func NewMiniWechatBindLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniWechatBindLogic {
  21 + return &MiniWechatBindLogic{
  22 + Logger: logx.WithContext(ctx),
  23 + ctx: ctx,
  24 + svcCtx: svcCtx,
  25 + }
  26 +}
  27 +
  28 +func (l *MiniWechatBindLogic) MiniWechatBind(req *types.MiniWechatBindRequest) (resp *types.MiniWechatBindResponse, err error) {
  29 + var loginCreator domain.LoginCreator = WxClientLogin{svcCtx: l.svcCtx, ctx: l.ctx}
  30 + loginInfo, err := loginCreator.WechatPhoneLogin(domain.WechatLoginRequest{
  31 + Code: req.WechatAuthCode,
  32 + EncryptedData: req.WechatEncryptedData,
  33 + IV: req.WechatIV,
  34 + })
  35 + if err != nil {
  36 + return nil, xerr.NewErrMsgErr("授权失败", err)
  37 + }
  38 + var conn = l.svcCtx.DefaultDBConn()
  39 + err = saveUserWechat(l.svcCtx, l.ctx, conn, loginInfo)
  40 + if err != nil {
  41 + return nil, xerr.NewErrMsg("保存用户信息失败")
  42 + }
  43 + return &types.MiniWechatBindResponse{
  44 + Bind: true,
  45 + Phone: loginInfo.Phone,
  46 + OpenId: loginInfo.OpenId,
  47 + }, nil
  48 +}
  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,12 +41,15 @@ type ServiceContext struct { @@ -41,12 +41,15 @@ type ServiceContext struct {
41 DepartmentRepository domain.DepartmentRepository 41 DepartmentRepository domain.DepartmentRepository
42 MessageBusinessRepository domain.MessageBusinessRepository 42 MessageBusinessRepository domain.MessageBusinessRepository
43 MessageSystemRepository domain.MessageSystemRepository 43 MessageSystemRepository domain.MessageSystemRepository
  44 + MessageSubscribeRepository domain.MessageSubscribeRepository
44 RoleRepository domain.RoleRepository 45 RoleRepository domain.RoleRepository
45 UserFollowRepository domain.UserFollowRepository 46 UserFollowRepository domain.UserFollowRepository
46 UserLoveFlagRepository domain.UserLoveFlagRepository 47 UserLoveFlagRepository domain.UserLoveFlagRepository
47 UserReadArticleRepository domain.UserReadArticleRepository 48 UserReadArticleRepository domain.UserReadArticleRepository
48 UserRepository domain.UserRepository 49 UserRepository domain.UserRepository
49 UserRoleRepository domain.UserRoleRepository 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
@@ -96,6 +99,7 @@ func NewServiceContext(c config.Config) *ServiceContext { @@ -96,6 +99,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
96 DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)), 99 DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)),
97 MessageBusinessRepository: repository.NewMessageBusinessRepository(cache.NewCachedRepository(mlCache)), 100 MessageBusinessRepository: repository.NewMessageBusinessRepository(cache.NewCachedRepository(mlCache)),
98 MessageSystemRepository: repository.NewMessageSystemRepository(cache.NewCachedRepository(mlCache)), 101 MessageSystemRepository: repository.NewMessageSystemRepository(cache.NewCachedRepository(mlCache)),
  102 + MessageSubscribeRepository: repository.NewMessageSubscribeRepository(cache.NewCachedRepository(mlCache)),
99 RoleRepository: repository.NewRoleRepository(cache.NewCachedRepository(mlCache)), 103 RoleRepository: repository.NewRoleRepository(cache.NewCachedRepository(mlCache)),
100 UserFollowRepository: repository.NewUserFollowRepository(cache.NewCachedRepository(mlCache)), 104 UserFollowRepository: repository.NewUserFollowRepository(cache.NewCachedRepository(mlCache)),
101 UserLoveFlagRepository: repository.NewUserLoveFlagRepository(cache.NewCachedRepository(mlCache)), 105 UserLoveFlagRepository: repository.NewUserLoveFlagRepository(cache.NewCachedRepository(mlCache)),
@@ -103,6 +107,8 @@ func NewServiceContext(c config.Config) *ServiceContext { @@ -103,6 +107,8 @@ func NewServiceContext(c config.Config) *ServiceContext {
103 UserReadArticleRepository: repository.NewUserReadArticleRepository(cache.NewCachedRepository(mlCache)), 107 UserReadArticleRepository: repository.NewUserReadArticleRepository(cache.NewCachedRepository(mlCache)),
104 ArticleTagRepository: repository.NewArticleTagRepository(cache.NewCachedRepository(mlCache)), 108 ArticleTagRepository: repository.NewArticleTagRepository(cache.NewCachedRepository(mlCache)),
105 UserRoleRepository: repository.NewUserRoleRepository(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"`
@@ -846,6 +868,27 @@ type SystemUserAccountSearchResponse struct { @@ -846,6 +868,27 @@ type SystemUserAccountSearchResponse struct {
846 Total int64 `json:"total"` 868 Total int64 `json:"total"`
847 } 869 }
848 870
  871 +type MiniWechatInfoRequest struct {
  872 +}
  873 +
  874 +type MiniWechatInfoResponse struct {
  875 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  876 + OpenId string `json:"openId"` // 绑定的微信openId
  877 + Phone string `json:"phone"` // 绑定手机号
  878 +}
  879 +
  880 +type MiniWechatBindRequest struct {
  881 + WechatAuthCode string `json:"wechatAuthcode"` // 微信登录 授权码
  882 + WechatEncryptedData string `json:"wechatEncryptedData"` // 微信登录 加密数据
  883 + WechatIV string `json:"wechatIV"` // 微信登录 加密算法初始向量
  884 +}
  885 +
  886 +type MiniWechatBindResponse struct {
  887 + Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
  888 + OpenId string `json:"openId"` // 绑定的微信openId
  889 + Phone string `json:"phone"` // 绑定手机号
  890 +}
  891 +
849 type CompanySearchRequest struct { 892 type CompanySearchRequest struct {
850 Page int `json:"page,optional"` 893 Page int `json:"page,optional"`
851 Size int `json:"size,optional"` 894 Size int `json:"size,optional"`
  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" gorm:"unique"` // 微信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 +}
  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 +}
  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
@@ -92,3 +92,12 @@ func (m *ArticleComment) MaxCountAdminLove(articleWhoRead int) int { @@ -92,3 +92,12 @@ func (m *ArticleComment) MaxCountAdminLove(articleWhoRead int) int {
92 } 92 }
93 return x 93 return x
94 } 94 }
  95 +
  96 +// GetSubscribeMessageContent 获取订阅消息评论内容 最多显示20个字,超出用...
  97 +func (m *ArticleComment) GetSubscribeMessageContent() string {
  98 + runeContent := []rune(m.Content)
  99 + if len(runeContent) > 20 {
  100 + return string(runeContent[0:20]) + "..."
  101 + }
  102 + return m.Content
  103 +}
  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 +}
@@ -161,5 +161,6 @@ type ( @@ -161,5 +161,6 @@ type (
161 User *User 161 User *User
162 Phone string 162 Phone string
163 Message string 163 Message string
  164 + OpenId string
164 } 165 }
165 ) 166 )
  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` ( 1 +CREATE TABLE `department`
  2 +(
2 `id` int(0) NOT NULL COMMENT '唯一标识', 3 `id` int(0) NOT NULL COMMENT '唯一标识',
3 PRIMARY KEY (`id`) USING BTREE 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 +CREATE TABLE `role`
  8 +(
7 `id` int(0) NOT NULL COMMENT '唯一标识', 9 `id` int(0) NOT NULL COMMENT '唯一标识',
8 PRIMARY KEY (`id`) USING BTREE 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` ( 13 +CREATE TABLE `user`
  14 +(
12 `id` int(0) NOT NULL COMMENT '唯一标识', 15 `id` int(0) NOT NULL COMMENT '唯一标识',
13 PRIMARY KEY (`id`) USING BTREE 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` ( 19 +CREATE TABLE `user_role`
  20 +(
17 `id` int(0) NOT NULL COMMENT '唯一标识', 21 `id` int(0) NOT NULL COMMENT '唯一标识',
18 PRIMARY KEY (`id`) USING BTREE 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` ( 25 +CREATE TABLE `company`
  26 +(
22 `id` int(0) NOT NULL COMMENT '唯一标识', 27 `id` int(0) NOT NULL COMMENT '唯一标识',
23 PRIMARY KEY (`id`) USING BTREE 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` ( 31 +CREATE TABLE `user_follow`
  32 +(
27 `id` int(0) NOT NULL COMMENT '唯一标识', 33 `id` int(0) NOT NULL COMMENT '唯一标识',
28 PRIMARY KEY (`id`) USING BTREE 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` ( 37 +CREATE TABLE `article_draft_operation`
  38 +(
32 `id` int(0) NOT NULL COMMENT '唯一标识', 39 `id` int(0) NOT NULL COMMENT '唯一标识',
33 PRIMARY KEY (`id`) USING BTREE 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` ( 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 +(
37 `id` int(0) NOT NULL COMMENT '唯一标识', 63 `id` int(0) NOT NULL COMMENT '唯一标识',
38 PRIMARY KEY (`id`) USING BTREE 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;