作者 Administrator

合并分支 'test' 到 'master'

Test



查看合并请求 !13
正在显示 48 个修改的文件 包含 2295 行增加140 行删除
... ... @@ -60,6 +60,7 @@ type (
Page int `json:"page"`
Size int `json:"size"`
IncludeRootCompany bool `json:"includeRootCompany,optional"` // 包含公司(把公司当作部门作为顶级节点 部门ID:0)
IncludeDefaultDepartment bool `json:"includeDefaultDepartment,optional"` // 包含默认分组
}
DepartmentListResponse {
... ...
... ... @@ -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(
... ... @@ -279,6 +286,7 @@ type(
ParentId int64 `json:"parentId"` // 父级ID
Name string `json:"name"` // 部门名称
UserIds []int64 `json:"userIds"` // 部门下的用户
TotalUser int `json:"totalUser"` // 累计用户
}
UserSearchRequest{
Page int `json:"page,optional"`
... ... @@ -471,7 +479,7 @@ type(
Phone string `json:"phone,optional"` // 手机号 唯一
Position string `json:"position,optional"` // 职位
Enable int `json:"enable,optional"` // 启用状态 1:启用 2:禁用
DepartmentId int64 `json:"departmentId,optional"` // 所属部门
DepartmentId *int64 `json:"departmentId,optional"` // 所属部门
}
SystemUserSearchResponse{
List []SystemUser `json:"list"`
... ... @@ -523,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)
}
}
}
... ...
... ... @@ -87,6 +87,7 @@ func (l *MiniArticleBackupSearchLogic) MiniArticleBackupSearch(req *types.MiniAr
changeFiled = append(changeFiled, "修改了评论范围")
case "Section":
{
changeFiled = append(changeFiled, "修改了文章内容")
item.Title = backupList[i].Title
item.Content = content.String()
item.Images = images
... ...
... ... @@ -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)
... ...
... ... @@ -2,6 +2,7 @@ package department
import (
"context"
"github.com/samber/lo"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
... ... @@ -39,6 +40,30 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty
Total: total,
List: make([]types.Department, 0),
}
_, users, _ := l.svcCtx.UserRepository.Find(l.ctx, conn, domain.NewQueryOptions().
MustWithKV("companyId", userToken.CompanyId).
WithKV("auditStatus", []int{domain.UserAuditStatusPassed}))
// 统计部门用户数量
var counterByDepartment = make(map[int64]int)
lo.ForEach(users, func(item *domain.User, index int) {
if len(item.Departments) == 0 {
if _, ok := counterByDepartment[domain.DefaultDepartmentId]; ok {
counterByDepartment[domain.DefaultDepartmentId]++
} else {
counterByDepartment[domain.DefaultDepartmentId] = 1
}
return
}
for _, dep := range item.Departments {
if _, ok := counterByDepartment[dep]; ok {
counterByDepartment[dep]++
} else {
counterByDepartment[dep] = 1
}
}
})
if req.IncludeRootCompany {
company, _ := l.svcCtx.CompanyRepository.FindOne(l.ctx, conn, userToken.CompanyId)
if company != nil {
... ... @@ -47,9 +72,24 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty
CompanyId: company.Id,
ParentId: -1,
Name: company.Name,
TotalUser: len(users),
})
}
}
if req.IncludeDefaultDepartment {
to := types.Department{
Id: domain.DefaultDepartmentId,
CompanyId: userToken.CompanyId,
ParentId: 0,
Name: "未分组",
}
if v, ok := counterByDepartment[domain.DefaultDepartmentId]; ok {
to.TotalUser = v
}
resp.List = append(resp.List, to)
}
for _, item := range list {
to := types.Department{
Id: item.Id,
... ... @@ -57,6 +97,9 @@ func (l *SystemListLogic) SystemList(req *types.DepartmentListRequest) (resp *ty
ParentId: item.ParentId,
Name: item.Name,
}
if v, ok := counterByDepartment[item.Id]; ok {
to.TotalUser = v
}
resp.List = append(resp.List, to)
}
return resp, nil
... ...
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
}
// sendAndDecrease 保存并扣减订阅消息
func (l *MiniSubscribeLogic) sendAndDecrease(conn transaction.Conn, companyId, userId int64, mType int, msg *subscribe.Message) 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,
}
//获取订阅次数
userSubscribe, err := l.svcCtx.UserSubscribeRepository.FindOneByType(l.ctx, conn, companyId, userId, mType)
if err != nil || userSubscribe.Count <= 0 {
subscribeMessage.Result = "fail"
subscribeMessage.Error = "订阅次数已用完"
} else {
//扣减订阅次数
userSubscribe.Count = userSubscribe.Count - 1
_, err = l.svcCtx.UserSubscribeRepository.Update(l.ctx, conn, userSubscribe)
if err != nil {
return err
}
//发送订阅消息
subCtx := l.getSubScribe()
sendErr := subCtx.Send(msg)
if sendErr != nil {
subscribeMessage.Result = "fail"
subscribeMessage.Error = sendErr.Error()
} else {
subscribeMessage.Result = "ok"
}
}
//保存订阅结果
_, err = l.svcCtx.MessageSubscribeRepository.Insert(l.ctx, conn, subscribeMessage)
if err != nil {
return err
}
return nil
}
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 {
//评论用户+职位 例: 张三-董事办
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()},
//评论时间
"time3": &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) //跳转页面 帖子评论聚合页
//备注
userCount, err := l.svcCtx.ArticleCommentRepository.CommentUserCount(l.ctx, conn, comment.CompanyId, comment.ArticleId)
msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的帖子最近已有%v人评论,点击查看详情", userCount)}
//发送微信订阅消息
err = l.sendAndDecrease(conn, comment.CompanyId, article.AuthorId, domain.SubscribeTypeReplyComment, msg)
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) //跳转页面评论聚合页
//备注
replyCount, err := l.svcCtx.ArticleCommentRepository.ReplyUserCount(l.ctx, conn, comment.CompanyId, comment.Pid)
if err == nil {
msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的评论最近已有%v人回复,点击查看详情", replyCount)}
//发送微信订阅消息
err = l.sendAndDecrease(conn, comment.CompanyId, comment.ToUserId, domain.SubscribeTypeReplyComment, msg)
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 = l.sendAndDecrease(conn, comment.CompanyId, at.Id, domain.SubscribeTypeReplyComment, msg)
if err != nil {
return xerr.NewErrMsgErr("评论失败", err)
}
}
}
return nil
}
// LikeArticle 帖子点赞订阅消息
func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.Article, userInfo *domain.User) error {
openId, err := l.getOpenId(conn, article.AuthorId)
if err != nil || openId == "" {
return nil
}
newArticle, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, article.Id)
if err != nil {
return xerr.NewErrMsgErr("未获取到帖子信息", err)
}
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},
//点赞时间
"date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
//动态内容
"thing8": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
//被赞次数
"number4": &subscribe.DataItem{Value: newArticle.CountLove},
//温馨提示
"thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
},
MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
}
err = l.sendAndDecrease(conn, article.CompanyId, article.AuthorId, domain.SubscribeTypeLike, msg)
if err != nil {
return xerr.NewErrMsgErr("点赞失败", err)
}
return nil
}
// LikeComment 点赞评论订阅消息
func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.ArticleComment, userInfo *domain.User) error {
openId, err := l.getOpenId(conn, comment.FromUserId)
if err != nil || openId == "" {
return nil
}
//获取被赞次数
newComment, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, comment.Id)
if err != nil {
return xerr.NewErrMsgErr("未获取到评论信息", err)
}
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},
//点赞时间
"date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
//动态内容
"thing8": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
//被赞次数
"number4": &subscribe.DataItem{Value: newComment.CountUserLove},
//温馨提示
"thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
},
MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
}
err = l.sendAndDecrease(conn, comment.CompanyId, comment.FromUserId, domain.SubscribeTypeLike, msg)
if err != nil {
return xerr.NewErrMsgErr("点赞失败", err)
}
return nil
}
// FollowArticle 发帖关注更新提醒
func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domain.Article) error {
//获取关注帖子作者的人员
_, 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: ""},
//发布时间
"time6": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
//温馨提示
"thing3": &subscribe.DataItem{Value: "你关注的人发布了新的帖子"},
},
MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
}
err = l.sendAndDecrease(conn, article.CompanyId, item.FromUserId, domain.SubscribeTypeFollow, msg)
if err != nil {
return xerr.NewErrMsgErr("保存订阅消息失败", err)
}
}
}
return nil
}
... ...
... ... @@ -40,7 +40,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs
"list": groups,
}
company, err = l.svcCtx.CompanyRepository.FindOne(l.ctx, conn, userToken.CompanyId)
if err != nil {
if err != nil || company == nil {
return nil, xerr.NewErrMsgErr("查找部门用户失败", err)
}
_, departments, err = l.svcCtx.DepartmentRepository.Find(l.ctx, conn, domain.IndexCompanyId(userToken.CompanyId)().WithFindOnly())
... ... @@ -51,7 +51,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs
if err != nil {
return nil, xerr.NewErrMsgErr("查找部门用户失败", err)
}
departments = append([]*domain.Department{&domain.Department{Id: 0, Name: company.Name}}, departments...)
departments = append([]*domain.Department{&domain.Department{Id: 0, Name: "未分组"}}, departments...)
lo.ForEach(departments, func(item *domain.Department, index int) {
group := DepartmentUser{
Id: item.Id,
... ... @@ -61,7 +61,7 @@ func (l *MiniUserDepartmentUsersLogic) MiniUserDepartmentUsers(req *types.MiniUs
groupUserSet := collection.NewSet()
for _, user := range users {
// 未分配部门的归类到公司底下
if len(user.Departments) == 0 {
if item.Id == 0 && len(user.Departments) == 0 {
if !groupUserSet.Contains(user.Id) {
group.Users = append(group.Users, &domain.User{
Id: user.Id,
... ...
... ... @@ -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:
... ... @@ -102,7 +102,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,8 +112,8 @@ 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)
... ... @@ -130,6 +131,23 @@ func (c WxClientLogin) WechatLogin(r domain.WechatLoginRequest) (*domain.LoginIn
return nil, nil
}
func (c WxClientLogin) GetOpenId(r domain.WechatLoginRequest) (string, error) {
miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
AppID: c.svcCtx.Config.Wechat.AppID,
AppSecret: c.svcCtx.Config.Wechat.AppSecret,
Cache: cache.NewMemory(),
})
result, err := miniprogram.GetAuth().Code2Session(r.Code)
if err != nil {
return "", xerr.NewErrMsgErr("发起授权请求失败", err)
}
plainData, err := miniprogram.GetEncryptor().Decrypt(result.SessionKey, r.EncryptedData, r.IV)
if err != nil {
return "", xerr.NewErrMsgErr("获取授权用户失败", err)
}
return plainData.OpenID, nil
}
func (c WxClientLogin) PhonePasswordLogin(phone string, password string) (*domain.LoginInfo, error) {
panic("implement me")
}
... ... @@ -139,10 +157,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/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 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}
openId, err := loginCreator.GetOpenId(domain.WechatLoginRequest{
Code: req.WechatAuthCode,
EncryptedData: req.WechatEncryptedData,
IV: req.WechatIV,
})
if err != nil {
return nil, xerr.NewErrMsgErr("授权失败", err)
}
var userToken = contextdata.GetUserTokenFromCtx(l.ctx)
userId := userToken.UserId
var conn = l.svcCtx.DefaultDBConn()
//获取用户信息
userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
if err != nil {
return nil, xerr.NewErrMsgErr("获取用户信息失败", err)
}
_, err = l.svcCtx.UserWechatRepository.FindOneByPhone(l.ctx, conn, userInfo.Phone)
if err != nil { // 未存储
_, err = l.svcCtx.UserWechatRepository.Insert(l.ctx, conn, &domain.UserWechat{
Phone: userInfo.Phone,
OpenId: openId,
})
if err != nil {
return nil, xerr.NewErrMsgErr("授权失败", err)
}
}
if err != nil {
return nil, xerr.NewErrMsg("保存用户信息失败")
}
return &types.MiniWechatBindResponse{
Bind: true,
Phone: userInfo.Phone,
OpenId: 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
}
}
... ...
... ... @@ -41,8 +41,11 @@ func (l *SystemUserSearchLogic) SystemUserSearch(req *types.SystemUserSearchRequ
WithKV("likePhone", req.Phone).
WithKV("position", req.Position).
WithKV("enable", req.Enable).
WithKV("departmentId", req.DepartmentId).
WithKV("auditStatus", []int{domain.UserAuditStatusPassed})
if req.DepartmentId != nil {
queryOptions.MustWithKV("departmentId", *req.DepartmentId)
}
if total, users, err = l.svcCtx.UserRepository.Find(l.ctx, conn, queryOptions); err != nil {
return nil, xerr.NewErr(err)
}
... ...
... ... @@ -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"`
... ... @@ -637,6 +659,7 @@ type Department struct {
ParentId int64 `json:"parentId"` // 父级ID
Name string `json:"name"` // 部门名称
UserIds []int64 `json:"userIds"` // 部门下的用户
TotalUser int `json:"totalUser"` // 累计用户
}
type UserSearchRequest struct {
... ... @@ -786,7 +809,7 @@ type SystemUserSearchRequest struct {
Phone string `json:"phone,optional"` // 手机号 唯一
Position string `json:"position,optional"` // 职位
Enable int `json:"enable,optional"` // 启用状态 1:启用 2:禁用
DepartmentId int64 `json:"departmentId,optional"` // 所属部门
DepartmentId *int64 `json:"departmentId,optional"` // 所属部门
}
type SystemUserSearchResponse struct {
... ... @@ -846,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"`
... ... @@ -1727,9 +1771,10 @@ type DepartmentUpdateRequest struct {
}
type DepartmentListRequest struct {
Page int `json:"page"`
Size int `json:"size"`
IncludeRootCompany bool `json:"includeRootCompany,optional"` // 包含公司(把公司当作部门作为顶级节点 部门ID:0)
Page int `json:"page"`
Size int `json:"size"`
IncludeRootCompany bool `json:"includeRootCompany,optional"` // 包含公司(把公司当作部门作为顶级节点 部门ID:0)
IncludeDefaultDepartment bool `json:"includeDefaultDepartment,optional"` // 包含默认分组
}
type DepartmentListResponse struct {
... ...
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"` // 微信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")
}
... ...
... ... @@ -437,6 +437,28 @@ func (repository *ArticleCommentRepository) CustomSearchBy(ctx context.Context,
}
// CommentUserCount 统计评论人数
func (repository *ArticleCommentRepository) CommentUserCount(ctx context.Context, conn transaction.Conn, companyId int64, articleId int64) (int64, error) {
var (
err error
tx = conn.DB()
c int64
)
err = tx.Model(&models.ArticleComment{}).Where("company_id = ? and article_id = ?", companyId, articleId).Group("from_user_id").Count(&c).Error
return c, err
}
// ReplyUserCount 统计回复人数
func (repository *ArticleCommentRepository) ReplyUserCount(ctx context.Context, conn transaction.Conn, companyId int64, commentId int64) (int64, error) {
var (
err error
tx = conn.DB()
c int64
)
err = tx.Model(&models.ArticleComment{}).Where("company_id = ? and pid = ?", companyId, commentId).Group("from_user_id").Count(&c).Error
return c, err
}
func NewArticleCommentRepository(cache *cache.CachedRepository) domain.ArticleCommentRepository {
return &ArticleCommentRepository{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 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}
}
... ...
... ... @@ -174,7 +174,12 @@ func (repository *UserRepository) Find(ctx context.Context, conn transaction.Con
tx.Where("position = ? ", v)
}
if v, ok := queryOptions["departmentId"]; ok {
tx.Where(fmt.Sprintf("departments @>'[%v]'", v))
// 未分组用户部门ID=0
if vi, okVi := v.(int64); okVi && vi == domain.DefaultDepartmentId {
tx.Where(fmt.Sprintf("departments = '[]'"))
} else {
tx.Where(fmt.Sprintf("departments @>'[%v]'", v))
}
}
if v, ok := queryOptions["roleId"]; ok {
tx.Where(fmt.Sprintf("roles @>'[%v]'", v))
... ...
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
... ...
... ... @@ -3,11 +3,8 @@ package domain
import (
"bytes"
"context"
"encoding/json"
"fmt"
"sort"
"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
"reflect"
)
// 编辑文章后保存的历史记录
... ... @@ -51,95 +48,119 @@ func (bk *ArticleBackup) CheckChangeField(oldBackup *ArticleBackup) bool {
bk.ChangeField = make([]string, 0)
//比较 WhoRead
{
whoReadChanged := false
sort.Slice(bk.WhoRead, func(i, j int) bool {
return bk.WhoRead[i] < bk.WhoRead[j]
})
sort.Slice(oldBackup.WhoRead, func(i, j int) bool {
return oldBackup.WhoRead[i] < oldBackup.WhoRead[j]
})
if len(bk.WhoRead) != len(oldBackup.WhoRead) {
whoReadChanged = true
} else {
for i := range bk.WhoRead {
if bk.WhoRead[i] != oldBackup.WhoRead[i] {
whoReadChanged = true
}
}
}
if whoReadChanged {
//whoReadChanged := false
//sort.Slice(bk.WhoRead, func(i, j int) bool {
// return bk.WhoRead[i] < bk.WhoRead[j]
//})
//sort.Slice(oldBackup.WhoRead, func(i, j int) bool {
// return oldBackup.WhoRead[i] < oldBackup.WhoRead[j]
//})
//
//if len(bk.WhoRead) != len(oldBackup.WhoRead) {
// whoReadChanged = true
//} else {
// for i := range bk.WhoRead {
// if bk.WhoRead[i] != oldBackup.WhoRead[i] {
// whoReadChanged = true
// }
// }
//}
//if whoReadChanged {
// bk.ChangeField = append(bk.ChangeField, "WhoRead")
//}
if !reflect.DeepEqual(oldBackup.WhoRead, bk.WhoRead) {
bk.ChangeField = append(bk.ChangeField, "WhoRead")
}
}
//比较 whoReview
{
whoReviewChanged := false
sort.Slice(bk.WhoReview, func(i, j int) bool {
return bk.WhoReview[i] < bk.WhoReview[j]
})
sort.Slice(oldBackup.WhoReview, func(i, j int) bool {
return oldBackup.WhoReview[i] < oldBackup.WhoReview[j]
})
if len(bk.WhoReview) != len(oldBackup.WhoReview) {
whoReviewChanged = true
} else {
for i := range bk.WhoReview {
if bk.WhoReview[i] != oldBackup.WhoReview[i] {
whoReviewChanged = true
}
}
}
if whoReviewChanged {
//whoReviewChanged := false
//sort.Slice(bk.WhoReview, func(i, j int) bool {
// return bk.WhoReview[i] < bk.WhoReview[j]
//})
//sort.Slice(oldBackup.WhoReview, func(i, j int) bool {
// return oldBackup.WhoReview[i] < oldBackup.WhoReview[j]
//})
//
//if len(bk.WhoReview) != len(oldBackup.WhoReview) {
// whoReviewChanged = true
//} else {
// for i := range bk.WhoReview {
// if bk.WhoReview[i] != oldBackup.WhoReview[i] {
// whoReviewChanged = true
// }
// }
//}
//if whoReviewChanged {
// bk.ChangeField = append(bk.ChangeField, "WhoReview")
//}
if !reflect.DeepEqual(oldBackup.WhoReview, bk.WhoReview) {
bk.ChangeField = append(bk.ChangeField, "WhoReview")
}
}
//比较段落内容+图片+视频 是否发生变更
{
sectionChanged := false
newSectionData := map[string]string{
"title": bk.Title,
}
oldSectionData := map[string]string{
"title": oldBackup.Title,
}
for _, val := range bk.Section {
mkey := fmt.Sprintf("section-%d", val.SortBy)
newSectionData[mkey] = val.Content
}
for _, val := range bk.Images {
newSectionData[val.Url] = ""
}
for _, val := range bk.Videos {
newSectionData[val.Url] = ""
}
for _, val := range oldBackup.Section {
mKey := fmt.Sprintf("section-%d", val.SortBy)
oldSectionData[mKey] = val.Content
}
for _, val := range oldBackup.Images {
oldSectionData[val.Url] = ""
}
for _, val := range oldBackup.Videos {
oldSectionData[val.Url] = ""
}
newSectionJson, _ := json.Marshal(newSectionData)
oldSectionJson, _ := json.Marshal(oldSectionData)
if ok := bytes.Equal(newSectionJson, oldSectionJson); !ok {
sectionChanged = true
}
if sectionChanged {
//sectionChanged := false
//newSectionData := map[string]string{
// "title": bk.Title,
//}
//
//oldSectionData := map[string]string{
// "title": oldBackup.Title,
//}
//
//for _, val := range bk.Section {
// mkey := fmt.Sprintf("section-%d", val.SortBy)
// newSectionData[mkey] = val.Content
//}
//for _, val := range bk.Images {
// newSectionData[val.Url] = ""
//}
//for _, val := range bk.Videos {
// newSectionData[val.Url] = ""
//}
//
//for _, val := range oldBackup.Section {
// mKey := fmt.Sprintf("section-%d", val.SortBy)
// oldSectionData[mKey] = val.Content
//}
//for _, val := range oldBackup.Images {
// oldSectionData[val.Url] = ""
//}
//for _, val := range oldBackup.Videos {
// oldSectionData[val.Url] = ""
//}
//newSectionJson, _ := json.Marshal(newSectionData)
//oldSectionJson, _ := json.Marshal(oldSectionData)
//if ok := bytes.Equal(newSectionJson, oldSectionJson); !ok {
// sectionChanged = true
//}
//if sectionChanged {
// bk.ChangeField = append(bk.ChangeField, "Section")
//}
if !reflect.DeepEqual(backUpContent(bk), backUpContent(oldBackup)) {
bk.ChangeField = append(bk.ChangeField, "Section")
}
}
return len(bk.ChangeField) > 0
}
func backUpContent(bk *ArticleBackup) string {
buf := bytes.NewBuffer(nil)
buf.WriteString(bk.Title)
for _, val := range bk.Images {
buf.WriteString(val.Url)
}
for _, val := range bk.Videos {
buf.WriteString(val.Url)
}
for _, val := range bk.Section {
buf.WriteString(val.Content)
}
return buf.String()
}
// 创建备份信息
func (bk *ArticleBackup) MakeBackup(operator UserSimple, article *Article, section []*ArticleSection, action string) {
sectionBackup := make([]ArticleSection, len(section))
... ...
... ... @@ -80,6 +80,10 @@ type ArticleCommentRepository interface {
// 特定的查询
CustomSearchBy(ctx context.Context, conn transaction.Conn, companyId int64, page int, size int,
topId int64, articleTitle string, contentLike string, fromUserId int64, show int, createdAtRange [2]int64) (int, []*ArticleCommentShow, error)
// CommentUserCount 统计帖子评论人数
CommentUserCount(ctx context.Context, conn transaction.Conn, companyId int64, articleId int64) (int64, error)
// ReplyUserCount 统计评论回复人数
ReplyUserCount(ctx context.Context, conn transaction.Conn, companyId int64, commentId int64) (int64, error)
}
// 运营点数 填写的最大值
... ... @@ -92,3 +96,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
}
... ...
... ... @@ -31,3 +31,5 @@ func (m *Department) Identify() interface{} {
}
return m.Id
}
const DefaultDepartmentId = -1
... ...
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
}
... ...
... ... @@ -151,6 +151,7 @@ type (
PhonePasswordLogin(phone string, password string) (*LoginInfo, error)
PhoneSmsCodeLogin(phone string, code string) (*LoginInfo, error)
WechatPhoneLogin(r WechatLoginRequest) (*LoginInfo, error)
GetOpenId(r WechatLoginRequest) (string, error)
}
WechatLoginRequest struct {
Code 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
... ...