作者 zhuangmx

Merge branch 'dev' into test

正在显示 39 个修改的文件 包含 2086 行增加57 行删除
... ... @@ -26,6 +26,14 @@ service Core {
@doc "点赞消息"
@handler miniLike
post /mini/message/like (MessageRequest) returns (MessageBusinessResponse)
@doc "增加订阅消息次数"
@handler miniMessageSubscribeAdd
post /mini/message/subscribe/add (MessageSubscribeAddRequest) returns (MessageSubscribeAddResponse)
@doc "获取订阅消息次数"
@handler miniMessageSubscribeList
post /mini/message/subscribe/list (MessageSubscribeListRequest) returns (MessageSubscribeListResponse)
}
type (
... ... @@ -86,4 +94,25 @@ type (
CountComment int `json:"countComment"` // 评论数量
Show int `json:"show"` // 文章的展示状态(0显示、1不显示)
}
// 增加消息订阅次数
MessageSubscribeAddRequest {
Types []int `json:"types"` // 订阅消息类型
}
MessageSubscribeAddResponse {
Items []MessageSubscribeItem `json:"items"`
}
MessageSubscribeItem {
Type int `json:"type"` // 订阅消息类型
Count int `json:"count"` // 订阅次数
UserId int64 `json:"userId"` // 用户ID
CompanyId int64 `json:"companyId"` // 公司ID
}
//订阅消息次数详情
MessageSubscribeListRequest {
}
MessageSubscribeListResponse {
Items []MessageSubscribeItem `json:"items"`
}
)
... ...
... ... @@ -95,6 +95,13 @@ service Core {
@doc "个人主页-用户发布的信息"
@handler miniHomepageUserNews
post /mini/homepage/user_news (MiniHomepageUserNewsRequest)returns(MiniHomepageUserNewsResposne)
@doc "检测是否绑定微信"
@handler miniWechatInfo
get /mini/wechat/info (MiniWechatInfoRequest) returns (MiniWechatInfoResponse)
@doc "绑定微信"
@handler miniWechatBind
post /mini/wechat/bind (MiniWechatBindRequest) returns (MiniWechatBindResponse)
}
type(
... ... @@ -524,4 +531,30 @@ type(
List []SystemUser `json:"list"`
Total int64 `json:"total"`
}
)
// 检测微信绑定信息
type (
MiniWechatInfoRequest {
}
MiniWechatInfoResponse {
Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
OpenId string `json:"openId"` // 绑定的微信openId
Phone string `json:"phone"` // 绑定手机号
}
)
// 绑定微信账号
type (
MiniWechatBindRequest {
WechatAuthCode string `json:"wechatAuthcode"` // 微信登录 授权码
WechatEncryptedData string `json:"wechatEncryptedData"` // 微信登录 加密数据
WechatIV string `json:"wechatIV"` // 微信登录 加密算法初始向量
}
MiniWechatBindResponse {
Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
OpenId string `json:"openId"` // 绑定的微信openId
Phone string `json:"phone"` // 绑定手机号
}
)
\ No newline at end of file
... ...
package message
import (
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result"
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
)
func MiniMessageSubscribeAddHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.MessageSubscribeAddRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := message.NewMiniMessageSubscribeAddLogic(r.Context(), svcCtx)
resp, err := l.MiniMessageSubscribeAdd(&req)
result.HttpResult(r, w, resp, err)
}
}
... ...
package message
import (
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/result"
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
)
func MiniMessageSubscribeListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.MessageSubscribeListRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := message.NewMiniMessageSubscribeListLogic(r.Context(), svcCtx)
resp, err := l.MiniMessageSubscribeList(&req)
result.HttpResult(r, w, resp, err)
}
}
... ...
... ... @@ -163,6 +163,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/mini/message/like",
Handler: message.MiniLikeHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/mini/message/subscribe/add",
Handler: message.MiniMessageSubscribeAddHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/mini/message/subscribe/list",
Handler: message.MiniMessageSubscribeListHandler(serverCtx),
},
}...,
),
rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret),
... ... @@ -339,6 +349,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/mini/homepage/user_news",
Handler: user.MiniHomepageUserNewsHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/mini/wechat/info",
Handler: user.MiniWechatInfoHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/mini/wechat/bind",
Handler: user.MiniWechatBindHandler(serverCtx),
},
}...,
),
rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret),
... ...
package user
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/user"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
)
func MiniWechatBindHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.MiniWechatBindRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := user.NewMiniWechatBindLogic(r.Context(), svcCtx)
resp, err := l.MiniWechatBind(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
... ...
package user
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/user"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
)
func MiniWechatInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.MiniWechatInfoRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := user.NewMiniWechatInfoLogic(r.Context(), svcCtx)
resp, err := l.MiniWechatInfo(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
... ...
... ... @@ -2,6 +2,7 @@ package article
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
"strconv"
"strings"
"text/template"
... ... @@ -198,6 +199,12 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
if err != nil {
return xerr.NewErrMsgErr("创建文章失败", err)
}
//发送订阅消息
err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).FollowArticle(conn, newArticle)
if err != nil {
return xerr.NewErrMsgErr("创建文章失败", err)
}
return nil
}, true)
if err != nil {
... ...
... ... @@ -271,6 +271,11 @@ func (l *MiniSetUserLikeLogic) setUserLikeArticle(req *types.MiniSetUserLikeRequ
return err
}
//发送订阅消息
err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).LikeArticle(c, articleInfo, userInfo)
if err != nil {
return err
}
return nil
}, true)
if err != nil {
... ... @@ -362,6 +367,11 @@ func (l *MiniSetUserLikeLogic) setUserLikeComment(req *types.MiniSetUserLikeRequ
return err
}
// 订阅消息
err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).LikeComment(c, commentInfo, userInfo)
if err != nil {
return err
}
return nil
}, true)
if err != nil {
... ...
... ... @@ -4,6 +4,7 @@ import (
"context"
"github.com/pkg/errors"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/message"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/authlib"
... ... @@ -154,6 +155,11 @@ func (l *SystemCreateArticleLogic) SystemCreateArticle(req *types.SystemArticleC
return xerr.NewErrMsg("删除草稿失败")
}
}
//发送订阅消息
err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).FollowArticle(conn, article)
if err != nil {
return xerr.NewErrMsgErr("创建文章失败", err)
}
return nil
}, true)
if err != nil {
... ...
... ... @@ -206,7 +206,11 @@ func (l *MiniCreateArticleCommentLogic) MiniCreateArticleComment(req *types.Mini
if err != nil {
return err
}
// 发送订阅消息
err = message.NewMiniSubscribeLogic(l.ctx, l.svcCtx).ReplyComment(c, articleInfo, &newComment)
if err != nil {
return err
}
return nil
}, true)
... ...
package message
import (
"context"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type MiniMessageSubscribeAddLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMiniMessageSubscribeAddLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniMessageSubscribeAddLogic {
return &MiniMessageSubscribeAddLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *MiniMessageSubscribeAddLogic) MiniMessageSubscribeAdd(req *types.MessageSubscribeAddRequest) (resp *types.MessageSubscribeAddResponse, err error) {
var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
userId := userToken.UserId
companyId := userToken.CompanyId
var conn = l.svcCtx.DefaultDBConn()
//验证类型
for _, item := range req.Types {
if !lo.Contains([]int{domain.SubscribeTypeReplyComment, domain.SubscribeTypeLike, domain.SubscribeTypeFollow}, item) {
return nil, xerr.NewErrMsg("请订阅正确的消息类型")
}
}
resp = &types.MessageSubscribeAddResponse{Items: make([]types.MessageSubscribeItem, 0)}
err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, conn transaction.Conn) error {
for _, item := range req.Types {
userSubscribe, err := l.svcCtx.UserSubscribeRepository.FindOneByType(l.ctx, conn, companyId, userId, item)
if err == nil { //已有数据增加次数
userSubscribe.Count += 1
_, err = l.svcCtx.UserSubscribeRepository.Update(l.ctx, conn, userSubscribe)
if err != nil {
return err
}
} else { //新增
userSubscribe, err = l.svcCtx.UserSubscribeRepository.Insert(l.ctx, conn, &domain.UserSubscribe{
Type: item,
UserId: userId,
CompanyId: companyId,
Count: 1,
})
if err != nil {
return err
}
}
resp.Items = append(resp.Items, types.MessageSubscribeItem{
Type: userSubscribe.Type,
Count: userSubscribe.Count,
UserId: userSubscribe.UserId,
CompanyId: userSubscribe.CompanyId,
})
}
return nil
}, true)
if err != nil {
return nil, xerr.NewErrMsgErr("增加订阅消息次数失败", err)
}
return
}
... ...
package message
import (
"context"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type MiniMessageSubscribeListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMiniMessageSubscribeListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniMessageSubscribeListLogic {
return &MiniMessageSubscribeListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *MiniMessageSubscribeListLogic) MiniMessageSubscribeList(req *types.MessageSubscribeListRequest) (resp *types.MessageSubscribeListResponse, err error) {
var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
userId := userToken.UserId
companyId := userToken.CompanyId
var conn = l.svcCtx.DefaultDBConn()
resp = &types.MessageSubscribeListResponse{Items: make([]types.MessageSubscribeItem, 0)}
_, list, err := l.svcCtx.UserSubscribeRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("companyId", companyId).WithKV("userId", userId))
lo.ForEach(list, func(item *domain.UserSubscribe, index int) {
resp.Items = append(resp.Items, types.MessageSubscribeItem{
Type: item.Type,
Count: item.Count,
UserId: item.UserId,
CompanyId: item.CompanyId,
})
})
return
}
... ...
package message
import (
"context"
"fmt"
"github.com/jinzhu/copier"
"github.com/silenceper/wechat/v2"
"github.com/silenceper/wechat/v2/cache"
miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
"github.com/silenceper/wechat/v2/miniprogram/subscribe"
"github.com/zeromicro/go-zero/core/logx"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"strings"
"time"
)
type MiniSubscribeLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMiniSubscribeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniSubscribeLogic {
return &MiniSubscribeLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *MiniSubscribeLogic) getSubScribe() *subscribe.Subscribe {
miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
AppID: l.svcCtx.Config.Wechat.AppID,
AppSecret: l.svcCtx.Config.Wechat.AppSecret,
Cache: cache.NewMemory(),
})
return miniprogram.GetSubscribe()
}
// getOpenId 获取绑定用户openID
func (l *MiniSubscribeLogic) getOpenId(conn transaction.Conn, userId int64) (string, error) {
userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
if err != nil {
return "", err
}
//获取微信绑定
userWechat, err := l.svcCtx.UserWechatRepository.FindOneByPhone(l.ctx, conn, userInfo.Phone)
if err != nil {
return "", err
}
return userWechat.OpenId, nil
}
// saveMessage 保存订阅消息
func (l *MiniSubscribeLogic) saveMessage(conn transaction.Conn, companyId, userId int64, mType int, msg *subscribe.Message, sendErr error) error {
templateData := make(map[string]interface{})
_ = copier.Copy(&templateData, msg.Data)
subscribeMessage := &domain.MessageSubscribe{
Type: mType,
CompanyId: companyId,
UserId: userId,
OpenId: msg.ToUser,
TemplateId: msg.TemplateID,
TemplateData: templateData,
}
if sendErr != nil {
subscribeMessage.Result = "fail"
subscribeMessage.Error = sendErr.Error()
} else {
subscribeMessage.Result = "ok"
}
_, err := l.svcCtx.MessageSubscribeRepository.Insert(l.ctx, conn, subscribeMessage)
return err
}
func (l *MiniSubscribeLogic) messageSubscribe(companyId, userId int64, mType int) *domain.MessageSubscribe {
return &domain.MessageSubscribe{
Type: mType,
CompanyId: companyId,
UserId: userId,
}
}
// getReplyCommentUserInfo 获取评论消息用户信息 用户名称+职位 例:张三-董事办
func (l *MiniSubscribeLogic) getReplyCommentUserInfo(conn transaction.Conn, companyId, userId int64) (string, error) {
userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
if err != nil {
return "", xerr.NewErrMsgErr("获取评论用户信息失败", err)
}
users := []string{userInfo.Name}
if len(userInfo.Roles) > 0 {
_, roles, err := l.svcCtx.RoleRepository.Find(l.ctx, conn, domain.IndexCompanyId(companyId)().MustWithKV("ids", userInfo.Roles))
if err == nil && len(roles) > 0 {
roleNames := make([]string, 0)
for _, item := range roles {
roleNames = append(roleNames, item.Name)
}
users = append(users, strings.Join(roleNames, "、"))
}
}
return strings.Join(users, "-"), nil
}
// ReplyComment 发送评论订阅消息
// @param conn 数据库连接
// @param article 文章
// @param comment 评论
func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain.Article, comment *domain.ArticleComment) error {
subCtx := l.getSubScribe()
//评论用户+职位 例: 张三-董事办
fromUserName, err := l.getReplyCommentUserInfo(conn, comment.CompanyId, comment.FromUserId)
if err != nil {
return xerr.NewErrMsgErr("发送消息失败", err)
}
//评论消息
msg := &subscribe.Message{
TemplateID: domain.SubscribeTemplateComment,
Data: map[string]*subscribe.DataItem{
//文章标题
"thing1": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
//评论内容
"thing2": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
//评论时间
"thing3": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
//评论用户
"thing5": &subscribe.DataItem{Value: fromUserName},
//备注
"thing9": &subscribe.DataItem{Value: ""},
},
MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
}
//发帖人接收消息
openId, err := l.getOpenId(conn, article.AuthorId)
//未绑定微信号,直接返回
if err == nil && openId != "" {
msg.ToUser = openId
msg.Page = fmt.Sprintf("/pages/detail/more-comment?id=%v", article.Id) //跳转页面 帖子评论聚合页
//备注
msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的帖子最近已有%v人评论,点击查看详情", article.CountComment)}
//发送微信订阅消息
err = subCtx.Send(msg)
err = l.saveMessage(conn, comment.CompanyId, article.AuthorId, domain.SubscribeTypeReplyComment, msg, err)
if err != nil {
return xerr.NewErrMsgErr("评论失败", err)
}
}
//评论回复
if comment.Pid > 0 {
toOpenId, err := l.getOpenId(conn, comment.ToUserId)
if err == nil && toOpenId != "" {
msg.ToUser = toOpenId
msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面评论聚合页
//备注
parent, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, comment.Pid)
if err == nil && parent.Id > 0 {
msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的评论最近已有%v人回复,点击查看详情", parent.CountReply)}
//发送微信订阅消息
err = subCtx.Send(msg)
err = l.saveMessage(conn, comment.CompanyId, comment.ToUserId, domain.SubscribeTypeReplyComment, msg, err)
if err != nil {
return xerr.NewErrMsgErr("评论失败", err)
}
}
}
}
//@消息
if len(comment.AtWho) > 0 {
for _, at := range comment.AtWho {
atOpenId, err := l.getOpenId(conn, at.Id)
//未绑定微信跳过
if err != nil || atOpenId == "" {
continue
}
msg.ToUser = atOpenId
msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面 评论详情页
//备注
msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("%v在评论中提到了你", comment.FromUser.Name)}
//发送微信订阅消息
err = subCtx.Send(msg)
err = l.saveMessage(conn, comment.CompanyId, at.Id, domain.SubscribeTypeReplyComment, msg, err)
if err != nil {
return xerr.NewErrMsgErr("评论失败", err)
}
}
}
return nil
}
// LikeArticle 帖子点赞订阅消息
func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.Article, userInfo *domain.User) error {
subCtx := l.getSubScribe()
openId, err := l.getOpenId(conn, article.AuthorId)
if err != nil || openId == "" {
return nil
}
msg := &subscribe.Message{
ToUser: openId,
TemplateID: domain.SubscribeTemplateLike,
Page: fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
Data: map[string]*subscribe.DataItem{
//点赞用户
"name1": &subscribe.DataItem{Value: userInfo.Name},
//点赞时间
"data2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
//动态内容
"thing8": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
//被赞次数
"number4": &subscribe.DataItem{Value: article.CountLove},
//温馨提示
"thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
},
MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
}
err = subCtx.Send(msg)
err = l.saveMessage(conn, article.CompanyId, article.AuthorId, domain.SubscribeTypeLike, msg, err)
if err != nil {
return xerr.NewErrMsgErr("点赞失败", err)
}
return nil
}
// LikeComment 点赞评论订阅消息
func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.ArticleComment, userInfo *domain.User) error {
subCtx := l.getSubScribe()
openId, err := l.getOpenId(conn, comment.FromUserId)
if err != nil || openId == "" {
return nil
}
msg := &subscribe.Message{
ToUser: openId,
TemplateID: domain.SubscribeTemplateLike,
Page: fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", comment.ArticleId, comment.Id),
Data: map[string]*subscribe.DataItem{
//点赞用户
"name1": &subscribe.DataItem{Value: userInfo.Name},
//点赞时间
"data2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
//动态内容
"thing8": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
//被赞次数
"number4": &subscribe.DataItem{Value: comment.CountUserLove},
//温馨提示
"thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
},
MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
}
err = subCtx.Send(msg)
err = l.saveMessage(conn, comment.CompanyId, comment.FromUserId, domain.SubscribeTypeLike, msg, err)
if err != nil {
return xerr.NewErrMsgErr("点赞失败", err)
}
return nil
}
// FollowArticle 发帖关注更新提醒
func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domain.Article) error {
subCtx := l.getSubScribe()
//获取关注帖子作者的人员
_, userInfo, err := l.svcCtx.UserFollowRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("toUserIds", []int64{article.AuthorId}))
if err == nil && len(userInfo) > 0 {
for _, item := range userInfo {
openId, err := l.getOpenId(conn, item.FromUserId)
if err != nil || openId == "" {
continue
}
msg := &subscribe.Message{
ToUser: openId,
TemplateID: domain.SubscribeTemplateFollow,
Page: fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
Data: map[string]*subscribe.DataItem{
//创作者
"thing1": &subscribe.DataItem{Value: article.Author.Name},
//作品名称
"thing2": &subscribe.DataItem{Value: article.Title},
//内容摘要
"thing5": &subscribe.DataItem{Value: ""},
//发布时间
"thing6": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
//温馨提示
"thing3": &subscribe.DataItem{Value: "你关注的人发布了新的帖子"},
},
MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
}
err = subCtx.Send(msg)
err = l.saveMessage(conn, article.CompanyId, item.FromUserId, domain.SubscribeTypeFollow, msg, err)
if err != nil {
return xerr.NewErrMsgErr("保存订阅消息失败", err)
}
}
}
return nil
}
... ...
... ... @@ -2,10 +2,10 @@ package user
import (
"context"
"fmt"
"github.com/silenceper/wechat/v2"
"github.com/silenceper/wechat/v2/cache"
miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/smslib"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool"
... ... @@ -35,7 +35,7 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res
var (
loginInfo *domain.LoginInfo
token string
loginCreator domain.LoginCreator = WxClientLogin{l: l}
loginCreator domain.LoginCreator = WxClientLogin{svcCtx: l.svcCtx, ctx: l.ctx}
)
switch req.LoginType {
case domain.LoginTypeWechatLogin:
... ... @@ -53,6 +53,11 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res
var users []*domain.User
conn := l.svcCtx.DefaultDBConn()
//保存微信用户信息
err = saveUserWechat(l.svcCtx, l.ctx, conn, loginInfo)
if err != nil {
return nil, err
}
_, users, err = l.svcCtx.UserRepository.Find(l.ctx, conn, domain.NewQueryOptions().
MustWithKV("phone", loginInfo.Phone).
MustWithKV("auditStatus", []int{domain.UserAuditStatusWait, domain.UserAuditStatusPassed}).
... ... @@ -87,6 +92,23 @@ func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (res
return
}
// saveUserWechat 保存微信授权信息
func saveUserWechat(svcCtx *svc.ServiceContext, ctx context.Context, conn transaction.Conn, loginInfo *domain.LoginInfo) error {
if loginInfo.Phone != "" && loginInfo.OpenId != "" {
_, err := svcCtx.UserWechatRepository.FindOneByPhone(ctx, conn, loginInfo.Phone)
if err != nil { // 未存储
_, err = svcCtx.UserWechatRepository.Insert(ctx, conn, &domain.UserWechat{
OpenId: loginInfo.OpenId,
Phone: loginInfo.Phone,
})
if err != nil {
return err
}
}
}
return nil
}
func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string, err error) {
var userJwtToken = tool.UserToken{}
if user != nil {
... ... @@ -102,7 +124,8 @@ func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string,
}
type WxClientLogin struct {
l *MiniUserLoginLogic
svcCtx *svc.ServiceContext
ctx context.Context
}
func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.LoginInfo, error) {
... ... @@ -111,18 +134,29 @@ func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.Lo
Phone: "",
}
miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
AppID: c.l.svcCtx.Config.Wechat.AppID,
AppSecret: c.l.svcCtx.Config.Wechat.AppSecret,
AppID: c.svcCtx.Config.Wechat.AppID,
AppSecret: c.svcCtx.Config.Wechat.AppSecret,
Cache: cache.NewMemory(),
})
authResult, err := miniprogram.GetAuth().GetPhoneNumber(code)
result, err := miniprogram.GetAuth().Code2Session(code)
if err != nil {
return nil, xerr.NewErrMsgErr("发起授权请求失败", err)
}
plainData, err := miniprogram.GetEncryptor().Decrypt(result.SessionKey, r.EncryptedData, r.IV)
if err != nil {
return nil, xerr.NewErrMsgErr("获取授权用户失败", err)
}
//增加微信用户openId
response.OpenId = plainData.OpenID
response.Phone = plainData.PhoneNumber
/*authResult, err := miniprogram.GetAuth().GetPhoneNumber(code)
if err != nil || authResult.ErrCode != 0 || authResult.PhoneInfo.PhoneNumber == "" {
return response, xerr.NewCodeErrMsg(xerr.ErrWxMiniAuthFailError, nil, fmt.Sprintf("发起授权请求失败1 err : %v , code : %s , authResult : %+v", err, code, authResult))
}
var (
phone = authResult.PhoneInfo.PhoneNumber
)
response.Phone = phone
response.Phone = phone*/
return response, nil
}
... ... @@ -139,10 +173,10 @@ func (c WxClientLogin) PhoneSmsCodeLogin(phone string, code string) (*domain.Log
err error
skipCheckSmsCode bool = false
)
if c.l.svcCtx.Config.DebugSmsCode != "" && c.l.svcCtx.Config.DebugSmsCode == code {
if c.svcCtx.Config.DebugSmsCode != "" && c.svcCtx.Config.DebugSmsCode == code {
skipCheckSmsCode = true
}
if _, err = c.l.svcCtx.SmsService.CheckSmsCode(c.l.ctx, smslib.RequestCheckSmsCode{Phone: phone, Code: code}); err != nil && !skipCheckSmsCode {
if _, err = c.svcCtx.SmsService.CheckSmsCode(c.ctx, smslib.RequestCheckSmsCode{Phone: phone, Code: code}); err != nil && !skipCheckSmsCode {
return nil, xerr.NewErrMsgErr(err.Error(), err)
}
response := &domain.LoginInfo{
... ...
package user
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type MiniWechatBindLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMiniWechatBindLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniWechatBindLogic {
return &MiniWechatBindLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *MiniWechatBindLogic) MiniWechatBind(req *types.MiniWechatBindRequest) (resp *types.MiniWechatBindResponse, err error) {
var loginCreator domain.LoginCreator = WxClientLogin{svcCtx: l.svcCtx, ctx: l.ctx}
loginInfo, err := loginCreator.WechatPhoneLogin(domain.WechatLoginRequest{
Code: req.WechatAuthCode,
EncryptedData: req.WechatEncryptedData,
IV: req.WechatIV,
})
if err != nil {
return nil, xerr.NewErrMsgErr("授权失败", err)
}
var conn = l.svcCtx.DefaultDBConn()
err = saveUserWechat(l.svcCtx, l.ctx, conn, loginInfo)
if err != nil {
return nil, xerr.NewErrMsg("保存用户信息失败")
}
return &types.MiniWechatBindResponse{
Bind: true,
Phone: loginInfo.Phone,
OpenId: loginInfo.OpenId,
}, nil
}
... ...
package user
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type MiniWechatInfoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMiniWechatInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniWechatInfoLogic {
return &MiniWechatInfoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *MiniWechatInfoLogic) MiniWechatInfo(req *types.MiniWechatInfoRequest) (resp *types.MiniWechatInfoResponse, err error) {
var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
userId := userToken.UserId
var conn = l.svcCtx.DefaultDBConn()
user, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
if err != nil {
return nil, xerr.NewErrMsg("未获取到用户信息")
}
userWechat, err := l.svcCtx.UserWechatRepository.FindOneByPhone(l.ctx, conn, user.Phone)
if err != nil {
return &types.MiniWechatInfoResponse{
Bind: false,
}, nil
} else {
return &types.MiniWechatInfoResponse{
Bind: true,
OpenId: userWechat.OpenId,
Phone: userWechat.Phone,
}, nil
}
}
... ...
... ... @@ -37,16 +37,19 @@ type ServiceContext struct {
ArticleAndTagRepository domain.ArticleAndTagRepository
ArticleDraftOperationRepository domain.ArticleDraftOperationRepository
CompanyRepository domain.CompanyRepository
DepartmentRepository domain.DepartmentRepository
MessageBusinessRepository domain.MessageBusinessRepository
MessageSystemRepository domain.MessageSystemRepository
RoleRepository domain.RoleRepository
UserFollowRepository domain.UserFollowRepository
UserLoveFlagRepository domain.UserLoveFlagRepository
UserReadArticleRepository domain.UserReadArticleRepository
UserRepository domain.UserRepository
UserRoleRepository domain.UserRoleRepository
CompanyRepository domain.CompanyRepository
DepartmentRepository domain.DepartmentRepository
MessageBusinessRepository domain.MessageBusinessRepository
MessageSystemRepository domain.MessageSystemRepository
MessageSubscribeRepository domain.MessageSubscribeRepository
RoleRepository domain.RoleRepository
UserFollowRepository domain.UserFollowRepository
UserLoveFlagRepository domain.UserLoveFlagRepository
UserReadArticleRepository domain.UserReadArticleRepository
UserRepository domain.UserRepository
UserRoleRepository domain.UserRoleRepository
UserSubscribeRepository domain.UserSubscribeRepository
UserWechatRepository domain.UserWechatRepository
ApiAuthService authlib.ApiAuthService
SmsService smslib.SMSService
... ... @@ -92,17 +95,20 @@ func NewServiceContext(c config.Config) *ServiceContext {
ArticleCategoryRepository: repository.NewArticleCategoryRepository(cache.NewCachedRepository(mlCache)),
ArticleDraftOperationRepository: repository.NewArticleDraftOperationRepository(cache.NewCachedRepository(mlCache)),
CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)),
DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)),
MessageBusinessRepository: repository.NewMessageBusinessRepository(cache.NewCachedRepository(mlCache)),
MessageSystemRepository: repository.NewMessageSystemRepository(cache.NewCachedRepository(mlCache)),
RoleRepository: repository.NewRoleRepository(cache.NewCachedRepository(mlCache)),
UserFollowRepository: repository.NewUserFollowRepository(cache.NewCachedRepository(mlCache)),
UserLoveFlagRepository: repository.NewUserLoveFlagRepository(cache.NewCachedRepository(mlCache)),
UserRepository: repository.NewUserRepository(cache.NewCachedRepository(mlCache)),
UserReadArticleRepository: repository.NewUserReadArticleRepository(cache.NewCachedRepository(mlCache)),
ArticleTagRepository: repository.NewArticleTagRepository(cache.NewCachedRepository(mlCache)),
UserRoleRepository: repository.NewUserRoleRepository(cache.NewCachedRepository(mlCache)),
CompanyRepository: repository.NewCompanyRepository(cache.NewCachedRepository(mlCache)),
DepartmentRepository: repository.NewDepartmentRepository(cache.NewCachedRepository(mlCache)),
MessageBusinessRepository: repository.NewMessageBusinessRepository(cache.NewCachedRepository(mlCache)),
MessageSystemRepository: repository.NewMessageSystemRepository(cache.NewCachedRepository(mlCache)),
MessageSubscribeRepository: repository.NewMessageSubscribeRepository(cache.NewCachedRepository(mlCache)),
RoleRepository: repository.NewRoleRepository(cache.NewCachedRepository(mlCache)),
UserFollowRepository: repository.NewUserFollowRepository(cache.NewCachedRepository(mlCache)),
UserLoveFlagRepository: repository.NewUserLoveFlagRepository(cache.NewCachedRepository(mlCache)),
UserRepository: repository.NewUserRepository(cache.NewCachedRepository(mlCache)),
UserReadArticleRepository: repository.NewUserReadArticleRepository(cache.NewCachedRepository(mlCache)),
ArticleTagRepository: repository.NewArticleTagRepository(cache.NewCachedRepository(mlCache)),
UserRoleRepository: repository.NewUserRoleRepository(cache.NewCachedRepository(mlCache)),
UserSubscribeRepository: repository.NewUserSubscribeRepository(cache.NewCachedRepository(mlCache)),
UserWechatRepository: repository.NewUserWechatRepository(cache.NewCachedRepository(mlCache)),
}
}
... ...
... ... @@ -347,6 +347,28 @@ type SimpleArticle struct {
Show int `json:"show"` // 文章的展示状态(0显示、1不显示)
}
type MessageSubscribeAddRequest struct {
Types []int `json:"types"` // 订阅消息类型
}
type MessageSubscribeAddResponse struct {
Items []MessageSubscribeItem `json:"items"`
}
type MessageSubscribeItem struct {
Type int `json:"type"` // 订阅消息类型
Count int `json:"count"` // 订阅次数
UserId int64 `json:"userId"` // 用户ID
CompanyId int64 `json:"companyId"` // 公司ID
}
type MessageSubscribeListRequest struct {
}
type MessageSubscribeListResponse struct {
Items []MessageSubscribeItem `json:"items"`
}
type TagCreateRequest struct {
CompanyId int64 `json:",optional"`
Image string `json:"image"`
... ... @@ -847,6 +869,27 @@ type SystemUserAccountSearchResponse struct {
Total int64 `json:"total"`
}
type MiniWechatInfoRequest struct {
}
type MiniWechatInfoResponse struct {
Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
OpenId string `json:"openId"` // 绑定的微信openId
Phone string `json:"phone"` // 绑定手机号
}
type MiniWechatBindRequest struct {
WechatAuthCode string `json:"wechatAuthcode"` // 微信登录 授权码
WechatEncryptedData string `json:"wechatEncryptedData"` // 微信登录 加密数据
WechatIV string `json:"wechatIV"` // 微信登录 加密算法初始向量
}
type MiniWechatBindResponse struct {
Bind bool `json:"bind"` // 绑定结果 true-已绑定 false-未绑定
OpenId string `json:"openId"` // 绑定的微信openId
Phone string `json:"phone"` // 绑定手机号
}
type CompanySearchRequest struct {
Page int `json:"page,optional"`
Size int `json:"size,optional"`
... ...
syntax = "v1"
info(
title: "xx实例"
desc: "xx实例"
author: "author"
email: "email"
version: "v1"
)
@server(
prefix: message_subscribe/v1
group: message_subscribe
jwt: JwtAuth
)
service Core {
@handler getMessageSubscribe
post /message_subscribe/:id (MessageSubscribeGetRequest) returns (MessageSubscribeGetResponse)
@handler saveMessageSubscribe
post /message_subscribe (MessageSubscribeSaveRequest) returns (MessageSubscribeSaveResponse)
@handler deleteMessageSubscribe
delete /message_subscribe/:id (MessageSubscribeDeleteRequest) returns (MessageSubscribeDeleteResponse)
@handler updateMessageSubscribe
put /message_subscribe/:id (MessageSubscribeUpdateRequest) returns (MessageSubscribeUpdateResponse)
@handler searchMessageSubscribe
post /message_subscribe/search (MessageSubscribeSearchRequest) returns (MessageSubscribeSearchResponse)
}
type (
MessageSubscribeGetRequest {
Id int64 `path:"id"`
}
MessageSubscribeGetResponse struct{
MessageSubscribe MessageSubscribeItem `json:"message_subscribe"`
}
MessageSubscribeSaveRequest struct{
MessageSubscribe MessageSubscribeItem `json:"message_subscribe"`
}
MessageSubscribeSaveResponse struct{}
MessageSubscribeDeleteRequest struct{
Id int64 `path:"id"`
}
MessageSubscribeDeleteResponse struct{}
MessageSubscribeUpdateRequest struct{
Id int64 `path:"id"`
MessageSubscribe MessageSubscribeItem `json:"message_subscribe"`
}
MessageSubscribeUpdateResponse struct{}
MessageSubscribeSearchRequest struct{
Page int `json:"page"`
Size int `json:"size"`
}
MessageSubscribeSearchResponse{
List []MessageSubscribeItem `json:"list"`
Total int64 `json:"total"`
}
MessageSubscribeItem struct{
}
)
... ...
syntax = "v1"
info(
title: "xx实例"
desc: "xx实例"
author: "author"
email: "email"
version: "v1"
)
@server(
prefix: user_subscribe/v1
group: user_subscribe
jwt: JwtAuth
)
service Core {
@handler getUserSubscribe
post /user_subscribe/:id (UserSubscribeGetRequest) returns (UserSubscribeGetResponse)
@handler saveUserSubscribe
post /user_subscribe (UserSubscribeSaveRequest) returns (UserSubscribeSaveResponse)
@handler deleteUserSubscribe
delete /user_subscribe/:id (UserSubscribeDeleteRequest) returns (UserSubscribeDeleteResponse)
@handler updateUserSubscribe
put /user_subscribe/:id (UserSubscribeUpdateRequest) returns (UserSubscribeUpdateResponse)
@handler searchUserSubscribe
post /user_subscribe/search (UserSubscribeSearchRequest) returns (UserSubscribeSearchResponse)
}
type (
UserSubscribeGetRequest {
Id int64 `path:"id"`
}
UserSubscribeGetResponse struct{
UserSubscribe UserSubscribeItem `json:"user_subscribe"`
}
UserSubscribeSaveRequest struct{
UserSubscribe UserSubscribeItem `json:"user_subscribe"`
}
UserSubscribeSaveResponse struct{}
UserSubscribeDeleteRequest struct{
Id int64 `path:"id"`
}
UserSubscribeDeleteResponse struct{}
UserSubscribeUpdateRequest struct{
Id int64 `path:"id"`
UserSubscribe UserSubscribeItem `json:"user_subscribe"`
}
UserSubscribeUpdateResponse struct{}
UserSubscribeSearchRequest struct{
Page int `json:"page"`
Size int `json:"size"`
}
UserSubscribeSearchResponse{
List []UserSubscribeItem `json:"list"`
Total int64 `json:"total"`
}
UserSubscribeItem struct{
}
)
... ...
syntax = "v1"
info(
title: "xx实例"
desc: "xx实例"
author: "author"
email: "email"
version: "v1"
)
@server(
prefix: user_wechat/v1
group: user_wechat
jwt: JwtAuth
)
service Core {
@handler getUserWechat
post /user_wechat/:id (UserWechatGetRequest) returns (UserWechatGetResponse)
@handler saveUserWechat
post /user_wechat (UserWechatSaveRequest) returns (UserWechatSaveResponse)
@handler deleteUserWechat
delete /user_wechat/:id (UserWechatDeleteRequest) returns (UserWechatDeleteResponse)
@handler updateUserWechat
put /user_wechat/:id (UserWechatUpdateRequest) returns (UserWechatUpdateResponse)
@handler searchUserWechat
post /user_wechat/search (UserWechatSearchRequest) returns (UserWechatSearchResponse)
}
type (
UserWechatGetRequest {
Id int64 `path:"id"`
}
UserWechatGetResponse struct{
UserWechat UserWechatItem `json:"user_wechat"`
}
UserWechatSaveRequest struct{
UserWechat UserWechatItem `json:"user_wechat"`
}
UserWechatSaveResponse struct{}
UserWechatDeleteRequest struct{
Id int64 `path:"id"`
}
UserWechatDeleteResponse struct{}
UserWechatUpdateRequest struct{
Id int64 `path:"id"`
UserWechat UserWechatItem `json:"user_wechat"`
}
UserWechatUpdateResponse struct{}
UserWechatSearchRequest struct{
Page int `json:"page"`
Size int `json:"size"`
}
UserWechatSearchResponse{
List []UserWechatItem `json:"list"`
Total int64 `json:"total"`
}
UserWechatItem struct{
}
)
... ...
syntax = "proto3";
option go_package ="./pb";
package pb;
message MessageSubscribeGetReq {
int64 Id = 1;
}
message MessageSubscribeGetResp{
MessageSubscribeItem User = 1;
}
message MessageSubscribeSaveReq {
}
message MessageSubscribeSaveResp{
}
message MessageSubscribeDeleteReq {
int64 Id = 1;
}
message MessageSubscribeDeleteResp{
}
message MessageSubscribeUpdateReq {
int64 Id = 1;
}
message MessageSubscribeUpdateResp{
}
message MessageSubscribeSearchReq {
int64 PageNumber = 1;
int64 PageSize = 2;
}
message MessageSubscribeSearchResp{
repeated MessageSubscribeItem List =1;
int64 Total =2;
}
message MessageSubscribeItem {
}
service MessageSubscribeService {
rpc MessageSubscribeGet(MessageSubscribeGetReq) returns(MessageSubscribeGetResp);
rpc MessageSubscribeSave(MessageSubscribeSaveReq) returns(MessageSubscribeSaveResp);
rpc MessageSubscribeDelete(MessageSubscribeDeleteReq) returns(MessageSubscribeDeleteResp);
rpc MessageSubscribeUpdate(MessageSubscribeUpdateReq) returns(MessageSubscribeUpdateResp);
rpc MessageSubscribeSearch(MessageSubscribeSearchReq) returns(MessageSubscribeSearchResp);
}
... ...
syntax = "proto3";
option go_package ="./pb";
package pb;
message UserSubscribeGetReq {
int64 Id = 1;
}
message UserSubscribeGetResp{
UserSubscribeItem User = 1;
}
message UserSubscribeSaveReq {
}
message UserSubscribeSaveResp{
}
message UserSubscribeDeleteReq {
int64 Id = 1;
}
message UserSubscribeDeleteResp{
}
message UserSubscribeUpdateReq {
int64 Id = 1;
}
message UserSubscribeUpdateResp{
}
message UserSubscribeSearchReq {
int64 PageNumber = 1;
int64 PageSize = 2;
}
message UserSubscribeSearchResp{
repeated UserSubscribeItem List =1;
int64 Total =2;
}
message UserSubscribeItem {
}
service UserSubscribeService {
rpc UserSubscribeGet(UserSubscribeGetReq) returns(UserSubscribeGetResp);
rpc UserSubscribeSave(UserSubscribeSaveReq) returns(UserSubscribeSaveResp);
rpc UserSubscribeDelete(UserSubscribeDeleteReq) returns(UserSubscribeDeleteResp);
rpc UserSubscribeUpdate(UserSubscribeUpdateReq) returns(UserSubscribeUpdateResp);
rpc UserSubscribeSearch(UserSubscribeSearchReq) returns(UserSubscribeSearchResp);
}
... ...
syntax = "proto3";
option go_package ="./pb";
package pb;
message UserWechatGetReq {
int64 Id = 1;
}
message UserWechatGetResp{
UserWechatItem User = 1;
}
message UserWechatSaveReq {
}
message UserWechatSaveResp{
}
message UserWechatDeleteReq {
int64 Id = 1;
}
message UserWechatDeleteResp{
}
message UserWechatUpdateReq {
int64 Id = 1;
}
message UserWechatUpdateResp{
}
message UserWechatSearchReq {
int64 PageNumber = 1;
int64 PageSize = 2;
}
message UserWechatSearchResp{
repeated UserWechatItem List =1;
int64 Total =2;
}
message UserWechatItem {
}
service UserWechatService {
rpc UserWechatGet(UserWechatGetReq) returns(UserWechatGetResp);
rpc UserWechatSave(UserWechatSaveReq) returns(UserWechatSaveResp);
rpc UserWechatDelete(UserWechatDeleteReq) returns(UserWechatDeleteResp);
rpc UserWechatUpdate(UserWechatUpdateReq) returns(UserWechatUpdateResp);
rpc UserWechatSearch(UserWechatSearchReq) returns(UserWechatSearchResp);
}
... ...
... ... @@ -24,8 +24,11 @@ func Migrate(db *gorm.DB) {
//&models.MessageBusiness{},
//&models.Department{},
//&models.ArticleAndTag{},
&models.ArticleDraftOperation{},
&models.ArticleCategory{},
//&models.ArticleDraftOperation{},
//&models.ArticleCategory{},
&models.UserSubscribe{},
&models.MessageSubscribe{},
&models.UserWechat{},
}
db.AutoMigrate(modelsList...)
... ...
package models
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
)
type MessageSubscribe struct {
Id int64 `json:"id"` // 唯一标识
Type int `json:"type"` // 分类(1评论回复 2获赞 3关注人更新)
CompanyId int64 `json:"companyId"` // 公司ID
UserId int64 `json:"userId"` // 用户ID
OpenId string `json:"openId"` // 微信openID
TemplateId string `json:"templateId"` // 模板ID
TemplateData map[string]interface{} `json:"templateData" gorm:"serializer:json;type:text;"` // 模板参数
Result string `json:"result"` // 发送结果
Error string `json:"error"` // 调用接口错误信息
CreatedAt int64 `json:",omitempty"` // 创建时间
UpdatedAt int64 `json:",omitempty"` // 更新时间
DeletedAt int64 `json:",omitempty"` // 删除时间
Version int `json:",omitempty"` // 版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
}
func (m *MessageSubscribe) TableName() string {
return "message_subscribe"
}
func (m *MessageSubscribe) BeforeCreate(tx *gorm.DB) (err error) {
// m.CreatedAt = time.Now().Unix()
// m.UpdatedAt = time.Now().Unix()
return
}
func (m *MessageSubscribe) BeforeUpdate(tx *gorm.DB) (err error) {
// m.UpdatedAt = time.Now().Unix()
return
}
func (m *MessageSubscribe) CacheKeyFunc() string {
if m.Id == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
}
func (m *MessageSubscribe) CacheKeyFuncByObject(obj interface{}) string {
if v, ok := obj.(*MessageSubscribe); ok {
return v.CacheKeyFunc()
}
return ""
}
func (m *MessageSubscribe) CachePrimaryKeyFunc() string {
if len("") == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
}
... ...
package models
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
)
type UserSubscribe struct {
Id int64 `json:"id"` // 唯一标识
Type int `json:"type" gorm:"type:int;"` // 分类(1评论回复 2获赞 3关注人更新)
CompanyId int64 `json:"companyId"` // 公司ID
UserId int64 `json:"userId"` // 用户ID
Count int `json:"count" gorm:"type:int;"` // 订阅次数
CreatedAt int64 `json:",omitempty"` // 创建时间
UpdatedAt int64 `json:",omitempty"` // 更新时间
DeletedAt int64 `json:",omitempty"` // 删除时间
Version int `json:",omitempty"` // 版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
}
func (m *UserSubscribe) TableName() string {
return "user_subscribe"
}
func (m *UserSubscribe) BeforeCreate(tx *gorm.DB) (err error) {
// m.CreatedAt = time.Now().Unix()
// m.UpdatedAt = time.Now().Unix()
return
}
func (m *UserSubscribe) BeforeUpdate(tx *gorm.DB) (err error) {
// m.UpdatedAt = time.Now().Unix()
return
}
func (m *UserSubscribe) CacheKeyFunc() string {
if m.Id == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
}
func (m *UserSubscribe) CacheKeyFuncByObject(obj interface{}) string {
if v, ok := obj.(*UserSubscribe); ok {
return v.CacheKeyFunc()
}
return ""
}
func (m *UserSubscribe) CachePrimaryKeyFunc() string {
if len("") == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
}
... ...
package models
import (
"fmt"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gorm.io/gorm"
"gorm.io/plugin/soft_delete"
)
type UserWechat struct {
Id int64 `json:"id"` // 唯一标识
OpenId string `json:"openId" gorm:"unique"` // 微信openId
Phone string `json:"phone" gorm:"unique"` // 微信手机号
CreatedAt int64 `json:",omitempty"` // 创建时间
UpdatedAt int64 `json:",omitempty"` // 更新时间
DeletedAt int64 `json:",omitempty"` // 删除时间
Version int `json:",omitempty"` // 版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
}
func (m *UserWechat) TableName() string {
return "user_wechat"
}
func (m *UserWechat) BeforeCreate(tx *gorm.DB) (err error) {
// m.CreatedAt = time.Now().Unix()
// m.UpdatedAt = time.Now().Unix()
return
}
func (m *UserWechat) BeforeUpdate(tx *gorm.DB) (err error) {
// m.UpdatedAt = time.Now().Unix()
return
}
func (m *UserWechat) CacheKeyFunc() string {
if m.Id == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:id:%v", domain.ProjectName, m.TableName(), m.Id)
}
func (m *UserWechat) CacheKeyFuncByObject(obj interface{}) string {
if v, ok := obj.(*UserWechat); ok {
return v.CacheKeyFunc()
}
return ""
}
func (m *UserWechat) CachePrimaryKeyFunc() string {
if len("") == 0 {
return ""
}
return fmt.Sprintf("%v:cache:%v:primarykey:%v", domain.ProjectName, m.TableName(), "key")
}
... ...
package repository
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/tiptok/gocomm/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/models"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gorm.io/gorm"
)
type MessageSubscribeRepository struct {
*cache.CachedRepository
}
func (repository *MessageSubscribeRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
var (
err error
m = &models.MessageSubscribe{}
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
if tx = tx.Model(m).Save(m); tx.Error != nil {
return nil, tx.Error
}
dm.Id = m.Id
return repository.ModelToDomainModel(m)
}
func (repository *MessageSubscribeRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
var (
err error
m *models.MessageSubscribe
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Updates(m)
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *MessageSubscribeRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
var (
err error
m *models.MessageSubscribe
tx = transaction.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
oldVersion := dm.Version
m.Version += 1
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
if tx.RowsAffected == 0 {
return nil, domain.ErrUpdateFail
}
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *MessageSubscribeRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.MessageSubscribe) (*domain.MessageSubscribe, error) {
var (
tx = conn.DB()
m = &models.MessageSubscribe{Id: dm.Identify().(int64)}
)
queryFunc := func() (interface{}, error) {
tx = tx.Where("id = ?", m.Id).Delete(m)
return m, tx.Error
}
if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return dm, err
}
return repository.ModelToDomainModel(m)
}
func (repository *MessageSubscribeRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.MessageSubscribe, error) {
var (
err error
tx = conn.DB()
m = new(models.MessageSubscribe)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("id = ?", id).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.MessageSubscribe)
cacheModel.Id = id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *MessageSubscribeRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.MessageSubscribe, error) {
var (
tx = conn.DB()
ms []*models.MessageSubscribe
dms = make([]*domain.MessageSubscribe, 0)
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc")
if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
return dms, tx.Error
}
return dms, nil
}
if _, err := repository.Query(queryFunc); err != nil {
return 0, nil, err
}
for _, item := range ms {
if dm, err := repository.ModelToDomainModel(item); err != nil {
return 0, dms, err
} else {
dms = append(dms, dm)
}
}
return total, dms, nil
}
func (repository *MessageSubscribeRepository) ModelToDomainModel(from *models.MessageSubscribe) (*domain.MessageSubscribe, error) {
to := &domain.MessageSubscribe{}
err := copier.Copy(to, from)
return to, err
}
func (repository *MessageSubscribeRepository) DomainModelToModel(from *domain.MessageSubscribe) (*models.MessageSubscribe, error) {
to := &models.MessageSubscribe{}
err := copier.Copy(to, from)
return to, err
}
func NewMessageSubscribeRepository(cache *cache.CachedRepository) domain.MessageSubscribeRepository {
return &MessageSubscribeRepository{CachedRepository: cache}
}
... ...
package repository
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/tiptok/gocomm/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/models"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gorm.io/gorm"
)
type UserSubscribeRepository struct {
*cache.CachedRepository
}
func (repository *UserSubscribeRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
var (
err error
m = &models.UserSubscribe{}
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
if tx = tx.Model(m).Save(m); tx.Error != nil {
return nil, tx.Error
}
dm.Id = m.Id
return repository.ModelToDomainModel(m)
}
func (repository *UserSubscribeRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
var (
err error
m *models.UserSubscribe
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Updates(m)
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserSubscribeRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
var (
err error
m *models.UserSubscribe
tx = transaction.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
oldVersion := dm.Version
m.Version += 1
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
if tx.RowsAffected == 0 {
return nil, domain.ErrUpdateFail
}
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserSubscribeRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.UserSubscribe) (*domain.UserSubscribe, error) {
var (
tx = conn.DB()
m = &models.UserSubscribe{Id: dm.Identify().(int64)}
)
queryFunc := func() (interface{}, error) {
tx = tx.Where("id = ?", m.Id).Delete(m)
return m, tx.Error
}
if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return dm, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserSubscribeRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.UserSubscribe, error) {
var (
err error
tx = conn.DB()
m = new(models.UserSubscribe)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("id = ?", id).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.UserSubscribe)
cacheModel.Id = id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserSubscribeRepository) FindOneByType(ctx context.Context, conn transaction.Conn, companyId, userId int64, mType int) (*domain.UserSubscribe, error) {
var (
err error
tx = conn.DB()
m = new(models.UserSubscribe)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("company_id = ? and user_id = ? and type = ?", companyId, userId, mType).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.UserSubscribe)
cacheModel.Id = m.Id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserSubscribeRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.UserSubscribe, error) {
var (
tx = conn.DB()
ms []*models.UserSubscribe
dms = make([]*domain.UserSubscribe, 0)
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc")
if v, ok := queryOptions["companyId"]; ok {
tx = tx.Where("company_id = ?", v)
}
if v, ok := queryOptions["userId"]; ok {
tx = tx.Where("user_id = ?", v)
}
if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
return dms, tx.Error
}
return dms, nil
}
if _, err := repository.Query(queryFunc); err != nil {
return 0, nil, err
}
for _, item := range ms {
if dm, err := repository.ModelToDomainModel(item); err != nil {
return 0, dms, err
} else {
dms = append(dms, dm)
}
}
return total, dms, nil
}
func (repository *UserSubscribeRepository) ModelToDomainModel(from *models.UserSubscribe) (*domain.UserSubscribe, error) {
to := &domain.UserSubscribe{}
err := copier.Copy(to, from)
return to, err
}
func (repository *UserSubscribeRepository) DomainModelToModel(from *domain.UserSubscribe) (*models.UserSubscribe, error) {
to := &models.UserSubscribe{}
err := copier.Copy(to, from)
return to, err
}
func NewUserSubscribeRepository(cache *cache.CachedRepository) domain.UserSubscribeRepository {
return &UserSubscribeRepository{CachedRepository: cache}
}
... ...
package repository
import (
"context"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"github.com/tiptok/gocomm/pkg/cache"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/models"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
"gorm.io/gorm"
)
type UserWechatRepository struct {
*cache.CachedRepository
}
func (repository *UserWechatRepository) Insert(ctx context.Context, conn transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
var (
err error
m = &models.UserWechat{}
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
if tx = tx.Model(m).Save(m); tx.Error != nil {
return nil, tx.Error
}
dm.Id = m.Id
return repository.ModelToDomainModel(m)
}
func (repository *UserWechatRepository) Update(ctx context.Context, conn transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
var (
err error
m *models.UserWechat
tx = conn.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Updates(m)
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserWechatRepository) UpdateWithVersion(ctx context.Context, transaction transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
var (
err error
m *models.UserWechat
tx = transaction.DB()
)
if m, err = repository.DomainModelToModel(dm); err != nil {
return nil, err
}
oldVersion := dm.Version
m.Version += 1
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Select("*").Where("id = ?", m.Id).Where("version = ?", oldVersion).Updates(m)
if tx.RowsAffected == 0 {
return nil, domain.ErrUpdateFail
}
return nil, tx.Error
}
if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserWechatRepository) Delete(ctx context.Context, conn transaction.Conn, dm *domain.UserWechat) (*domain.UserWechat, error) {
var (
tx = conn.DB()
m = &models.UserWechat{Id: dm.Identify().(int64)}
)
queryFunc := func() (interface{}, error) {
tx = tx.Where("id = ?", m.Id).Delete(m)
return m, tx.Error
}
if _, err := repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
return dm, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserWechatRepository) FindOne(ctx context.Context, conn transaction.Conn, id int64) (*domain.UserWechat, error) {
var (
err error
tx = conn.DB()
m = new(models.UserWechat)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("id = ?", id).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.UserWechat)
cacheModel.Id = id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserWechatRepository) FindOneByPhone(ctx context.Context, conn transaction.Conn, phone string) (*domain.UserWechat, error) {
var (
err error
tx = conn.DB()
m = new(models.UserWechat)
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(m).Where("phone = ?", phone).First(m)
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, domain.ErrNotFound
}
return m, tx.Error
}
cacheModel := new(models.UserWechat)
cacheModel.Id = m.Id
if err = repository.QueryCache(cacheModel.CacheKeyFunc, m, queryFunc); err != nil {
return nil, err
}
return repository.ModelToDomainModel(m)
}
func (repository *UserWechatRepository) Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*domain.UserWechat, error) {
var (
tx = conn.DB()
ms []*models.UserWechat
dms = make([]*domain.UserWechat, 0)
total int64
)
queryFunc := func() (interface{}, error) {
tx = tx.Model(&ms).Order("id desc")
if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
return dms, tx.Error
}
return dms, nil
}
if _, err := repository.Query(queryFunc); err != nil {
return 0, nil, err
}
for _, item := range ms {
if dm, err := repository.ModelToDomainModel(item); err != nil {
return 0, dms, err
} else {
dms = append(dms, dm)
}
}
return total, dms, nil
}
func (repository *UserWechatRepository) ModelToDomainModel(from *models.UserWechat) (*domain.UserWechat, error) {
to := &domain.UserWechat{}
err := copier.Copy(to, from)
return to, err
}
func (repository *UserWechatRepository) DomainModelToModel(from *domain.UserWechat) (*models.UserWechat, error) {
to := &models.UserWechat{}
err := copier.Copy(to, from)
return to, err
}
func NewUserWechatRepository(cache *cache.CachedRepository) domain.UserWechatRepository {
return &UserWechatRepository{CachedRepository: cache}
}
... ...
... ... @@ -131,6 +131,15 @@ func (m *Article) SetSummary(sectionList []*ArticleSection) {
m.Summary = string(runeContent[0:length])
}
// GetSubscribeMessageTitle 获取订阅消息标题 超过20个字用...
func (m *Article) GetSubscribeMessageTitle() string {
runeContent := []rune(m.Title)
if len(runeContent) > 20 {
return string(runeContent[0:20]) + "..."
}
return m.Title
}
func (m *Article) WhoCanRead(userId int64) bool {
if m.AuthorId == userId {
return true
... ...
... ... @@ -92,3 +92,12 @@ func (m *ArticleComment) MaxCountAdminLove(articleWhoRead int) int {
}
return x
}
// GetSubscribeMessageContent 获取订阅消息评论内容 最多显示20个字,超出用...
func (m *ArticleComment) GetSubscribeMessageContent() string {
runeContent := []rune(m.Content)
if len(runeContent) > 20 {
return string(runeContent[0:20]) + "..."
}
return m.Content
}
... ...
package domain
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gorm.io/plugin/soft_delete"
)
type MessageSubscribe struct {
Id int64 `json:"id"` // 唯一标识
Type int `json:"type"` // 分类(1评论回复 2获赞 3关注人更新)
CompanyId int64 `json:"companyId"` // 公司ID
UserId int64 `json:"userId"` // 用户ID
OpenId string `json:"openId"` // 微信openID
TemplateId string `json:"templateId"` // 模板ID
TemplateData map[string]interface{} `json:"templateData"` // 模板参数
Result string `json:"result"` // 发送结果
Error string `json:"error"` // 调用接口错误信息
CreatedAt int64 `json:",omitempty"` // 创建时间
UpdatedAt int64 `json:",omitempty"` // 更新时间
DeletedAt int64 `json:",omitempty"` // 删除时间
Version int `json:",omitempty"` // 版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
}
var (
SubscribeTypeReplyComment = 1 // 评论回复
SubscribeTypeLike = 2 // 点赞
SubscribeTypeFollow = 3 // 关注人更新
SubscribeTemplateComment = "DxnQTZVHKrH7TOJiV-tK9w72hbkfLM87eXzhVy4cyhE" // 订阅消息 评论提醒
SubscribeTemplateLike = "oRdUINwfMK5_4ok_3lNgpkKT_SJqyGOvP4ZDgdsea9E" // 订阅消息 动态点赞通知
SubscribeTemplateFollow = "XdS11h2ZGGByzu-wMd16KxJ-LPjZy0yxZDmgQaVfDHE" // 订阅消息 关注更新提醒
)
type MessageSubscribeRepository interface {
Insert(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
Update(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
Delete(ctx context.Context, conn transaction.Conn, dm *MessageSubscribe) (*MessageSubscribe, error)
FindOne(ctx context.Context, conn transaction.Conn, id int64) (*MessageSubscribe, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*MessageSubscribe, error)
}
func (m *MessageSubscribe) Identify() interface{} {
if m.Id == 0 {
return nil
}
return m.Id
}
... ...
... ... @@ -161,5 +161,6 @@ type (
User *User
Phone string
Message string
OpenId string
}
)
... ...
package domain
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gorm.io/plugin/soft_delete"
)
type UserSubscribe struct {
Id int64 `json:"id"` // 唯一标识
Type int `json:"type"` // 分类(1评论回复 2获赞 3关注人更新)
CompanyId int64 `json:"companyId"` // 公司ID
UserId int64 `json:"userId"` // 用户ID
Count int `json:"count"` // 订阅次数
CreatedAt int64 `json:",omitempty"` // 创建时间
UpdatedAt int64 `json:",omitempty"` // 更新时间
DeletedAt int64 `json:",omitempty"` // 删除时间
Version int `json:",omitempty"` // 版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
}
type UserSubscribeRepository interface {
Insert(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
Update(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
Delete(ctx context.Context, conn transaction.Conn, dm *UserSubscribe) (*UserSubscribe, error)
FindOne(ctx context.Context, conn transaction.Conn, id int64) (*UserSubscribe, error)
FindOneByType(ctx context.Context, conn transaction.Conn, companyId, userId int64, mType int) (*UserSubscribe, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*UserSubscribe, error)
}
func (m *UserSubscribe) Identify() interface{} {
if m.Id == 0 {
return nil
}
return m.Id
}
... ...
package domain
import (
"context"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"gorm.io/plugin/soft_delete"
)
type UserWechat struct {
Id int64 `json:"id"` // 唯一标识
OpenId string `json:"openId"` // 微信openId
Phone string `json:"phone"` // 微信手机号
CreatedAt int64 `json:",omitempty"` // 创建时间
UpdatedAt int64 `json:",omitempty"` // 更新时间
DeletedAt int64 `json:",omitempty"` // 删除时间
Version int `json:",omitempty"` // 版本
IsDel soft_delete.DeletedAt `gorm:"softDelete:flag,DeletedAtField:DeletedAt"` // 删除标记
}
type UserWechatRepository interface {
Insert(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
Update(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
Delete(ctx context.Context, conn transaction.Conn, dm *UserWechat) (*UserWechat, error)
FindOne(ctx context.Context, conn transaction.Conn, id int64) (*UserWechat, error)
FindOneByPhone(ctx context.Context, conn transaction.Conn, phone string) (*UserWechat, error)
Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*UserWechat, error)
}
func (m *UserWechat) Identify() interface{} {
if m.Id == 0 {
return nil
}
return m.Id
}
... ...
CREATE TABLE `department` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `department`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `role` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `role`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `user` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `user`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `user_role` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `user_role`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `company` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `company`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `user_follow` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `user_follow`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `article_draft_operation` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `article_draft_operation`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `article_category` (
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
CREATE TABLE `article_category`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `message_subscribe`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `user_subscribe`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
CREATE TABLE `user_wechat`
(
`id` int(0) NOT NULL COMMENT '唯一标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
\ No newline at end of file
... ...