作者 郑周

Merge remote-tracking branch 'origin/dev' into dev

正在显示 25 个修改的文件 包含 993 行增加65 行删除
@@ -8,6 +8,30 @@ info( @@ -8,6 +8,30 @@ info(
8 version: "v1" 8 version: "v1"
9 ) 9 )
10 10
  11 +// 小程序接口
  12 +@server(
  13 + prefix: v1/mini
  14 + group: article
  15 + jwt: MiniAuth
  16 +)
  17 +service Core {
  18 + @doc "小程序创建发布内容"
  19 + @handler MiniCreateArticle
  20 + post /article (MiniArticleCreateRequest) returns (MiniArticleCreateResponse)
  21 + @doc "小程序获取我发布的文章"
  22 + @handler MiniArticleSearchMe
  23 + post /article/search/me (MiniArticleSearchMeRequest) returns (MiniArticleSearchMeResponse)
  24 + @doc "小程序获取文章内容详情"
  25 + @handler MiniGetArticle
  26 + get /article/:id (MiniArticleGetRequest) returns (MiniArticleGetResponse)
  27 + @doc "小程序获取文章的点赞人员列表"
  28 + @handler MiniUserLikeArticle
  29 + post /article/user_like/list (MiniUserLikeArticleRequest) returns (MiniUserLikeArticleResponse)
  30 + @doc "小程序人员操作点赞文章/评论"
  31 + @handler MiniSetUserLike
  32 + post /article/user_like/set (MiniSetUserLikeRequset) returns (MiniSetUserLikeResponse)
  33 +}
  34 +
11 // 坐标地点描述 35 // 坐标地点描述
12 type Location { 36 type Location {
13 Longitude float64 `json:"longitude,optional"` //经度 37 Longitude float64 `json:"longitude,optional"` //经度
@@ -22,6 +46,7 @@ type Author { @@ -22,6 +46,7 @@ type Author {
22 Avatar string `json:"avatar"` // 人员头像URL 46 Avatar string `json:"avatar"` // 人员头像URL
23 Group string `json:"group"` // 人员的分组 47 Group string `json:"group"` // 人员的分组
24 Position string `json:"position"` // 职位 48 Position string `json:"position"` // 职位
  49 + Company string `json:"company"` // 公司
25 } 50 }
26 51
27 //小程序端创建发布文章 52 //小程序端创建发布文章
@@ -43,21 +68,30 @@ type ( @@ -43,21 +68,30 @@ type (
43 //小程序端查看文章的详情 68 //小程序端查看文章的详情
44 type ( 69 type (
45 MiniArticleGetRequest { 70 MiniArticleGetRequest {
46 - Id int64 `path:"id"` //id 71 + Id int64 `path:"id"` //id
  72 + CompanyId int64 `path:"-"`
47 } 73 }
48 MiniArticleGetResponse { 74 MiniArticleGetResponse {
49 - Title string `json:"title"` //标题  
50 - AuthorId int `json:"authorId"` //发布人id  
51 - Author Author `json:"author"` //发布人  
52 - CreatedAt int64 `json:"createdAt"` //文章的发布时间  
53 - Section []string `json:"section"` //文章的文本内容  
54 - Images []string `json:"images"` //图片  
55 - WhoRead []int64 `json:"whoRead"` //谁可查看  
56 - WhoReview []int64 `json:"whoReview"` //谁可评论  
57 - Location Location `json:"location"` //定位坐标  
58 - CountLove int `json:"countLove"` // 点赞数量  
59 - CountComment int `json:"countComment"` // 评论数量  
60 - Show int `json:"showState"` // 评论的展示状态(0显示、1不显示) 75 + Id int64 `json:"id"` //id
  76 + Title string `json:"title"` //标题
  77 + AuthorId int64 `json:"authorId"` //发布人id
  78 + Author Author `json:"author"` //发布人
  79 + CreatedAt int64 `json:"createdAt"` //文章的发布时间
  80 + Section []ArticleSection `json:"section"` //文章的文本内容
  81 + Images []string `json:"images"` //图片
  82 + WhoRead []int64 `json:"whoRead"` //谁可查看
  83 + WhoReview []int64 `json:"whoReview"` //谁可评论
  84 + Location Location `json:"location"` //定位坐标
  85 + CountLove int `json:"countLove"` // 点赞数量
  86 + CountComment int `json:"countComment"` // 评论数量
  87 + CountRead int `json:"countRead"` // 浏览数量
  88 + Show int `json:"show"` // 评论的展示状态(0显示、1不显示)
  89 + }
  90 + ArticleSection {
  91 + Id int64 `json:"id"` //段落id
  92 + Content string `json:"content"` // 文本内容
  93 + SortBy int `json:"sortBy"` // 排序
  94 + TotalComment int `json:"totalComment"` // 评论的数量
61 } 95 }
62 ) 96 )
63 97
@@ -86,20 +120,38 @@ type ( @@ -86,20 +120,38 @@ type (
86 } 120 }
87 ) 121 )
88 122
89 -// 小程序接口  
90 -@server(  
91 - prefix: v1/mini  
92 - group: article  
93 - jwt: MiniAuth 123 +//获取列表,文章有哪些人进行了点赞
  124 +type (
  125 + MiniUserLikeArticleRequest {
  126 + ArticleId int64 `json:"articleId"` // 文章id
  127 + CompanyId int64 `json:"-"` //公司id
  128 + Page int `json:"page"` //分页,第几页
  129 + Size int `json:"size"` //分页,每页几条
  130 + }
  131 + MiniUserLikeArticleResponse {
  132 + Total int64 `json:"total"` //总数
  133 + List []WhichUserLikeArticle `json:"list"` //列表
  134 + }
  135 + WhichUserLikeArticle {
  136 + ArticleId int64 `json:"articleId"` // 文章id
  137 + UserId int64 `json:"userId"` // 人员id
  138 + Name string `json:"name"` // 人员名称
  139 + Avatar string `json:"avatar"` // 人员头像
  140 + CreatedAt int64 `json:"createdAt"` // 点赞记录的时间
  141 + }
94 ) 142 )
95 -service Core {  
96 - @doc "小程序创建发布内容"  
97 - @handler MiniCreateArticle  
98 - post /article (MiniArticleCreateRequest) returns (MiniArticleCreateResponse)  
99 - @doc "小程序获取我发布的文章"  
100 - @handler MiniArticleSearchMe  
101 - post /article/search/me (MiniArticleSearchMeRequest) returns (MiniArticleSearchMeResponse)  
102 - @doc "小程序获取文章内容详情"  
103 - @handler MiniGetArticle  
104 - get /article/:id (MiniArticleGetRequest) returns (MiniArticleGetResponse)  
105 -}  
  143 +
  144 +// 人员点赞文章/评论
  145 +type (
  146 + MiniSetUserLikeRequset {
  147 + ArticleId int64 `json:"articleId"` //文章id
  148 + CommentId int64 `json:"commentId"` //评论id
  149 + UserId int64 `json:"-"` //操作人
  150 + Flag int `json:"flag"` //点赞标志 1、点赞 2 、取消点赞
  151 + }
  152 + MiniSetUserLikeResponse {
  153 + ArticleId int64 `json:"articleId"` //文章id
  154 + CommentId int64 `json:"commentId"` //评论id
  155 + Count int `json:"count"` //现有的点赞数量
  156 + }
  157 +)
@@ -41,10 +41,10 @@ service Core { @@ -41,10 +41,10 @@ service Core {
41 post /mini/user/department-users (MiniUserDepartmentUsersRequest)returns (MiniUserInfoResponse) 41 post /mini/user/department-users (MiniUserDepartmentUsersRequest)returns (MiniUserInfoResponse)
42 @doc "关注我的人" 42 @doc "关注我的人"
43 @handler miniUserFollower 43 @handler miniUserFollower
44 - post /mini/user/follower (UserSearchRequest)returns(UserSearchResponse) 44 + post /mini/user/follower (MiniUserFollowedSearchRequest)returns(MiniUserFollowedSearchResponse)
45 @doc "我关注的人" 45 @doc "我关注的人"
46 @handler miniUserFollowing 46 @handler miniUserFollowing
47 - post /mini/user/following (UserSearchRequest)returns(UserSearchResponse) 47 + post /mini/user/following (MiniUserFollowedSearchRequest)returns(MiniUserFollowedSearchResponse)
48 @doc "关注" 48 @doc "关注"
49 @handler miniUserFollow 49 @handler miniUserFollow
50 post /mini/user/follow (FollowRequest) 50 post /mini/user/follow (FollowRequest)
@@ -97,6 +97,14 @@ type( @@ -97,6 +97,14 @@ type(
97 Departments []*Department `json:"departments"` 97 Departments []*Department `json:"departments"`
98 Users []*UserItem `json:"users"` 98 Users []*UserItem `json:"users"`
99 } 99 }
  100 + MiniUserFollowedSearchRequest{
  101 + Page int `json:"page,optional"`
  102 + Size int `json:"size,optional"`
  103 + }
  104 + MiniUserFollowedSearchResponse{
  105 + List []*UserFollowItem `json:"users"`
  106 + Total int64 `json:"total"`
  107 + }
100 UserItem { 108 UserItem {
101 Id int64 `json:"id,omitempty"` // 用户ID 109 Id int64 `json:"id,omitempty"` // 用户ID
102 CompanyId int64 `json:"companyId,omitempty"` // 公司ID 110 CompanyId int64 `json:"companyId,omitempty"` // 公司ID
@@ -133,6 +141,15 @@ type( @@ -133,6 +141,15 @@ type(
133 FollowRequest{ 141 FollowRequest{
134 UserId int64 `json:"userId"` 142 UserId int64 `json:"userId"`
135 } 143 }
  144 + UserFollowItem struct {
  145 + Id int64 `json:"id"` // 用户ID
  146 + Name string `json:"name"` // 名称
  147 + CompanyName string `json:"companyName"` // 公司名称
  148 + Avatar string `json:"avatar"` // 头像
  149 + Position string `json:"position"` // 职位
  150 + Followed bool `json:"followed"` // 关注
  151 + MutualFollowed bool `json:"mutualFollowed"` // 互相关注标识
  152 + }
136 ) 153 )
137 154
138 155
@@ -7,6 +7,7 @@ import ( @@ -7,6 +7,7 @@ import (
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/article" 7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/article"
8 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 8 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
9 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 9 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
10 ) 11 )
11 12
12 func MiniGetArticleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { 13 func MiniGetArticleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
@@ -18,7 +19,8 @@ func MiniGetArticleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { @@ -18,7 +19,8 @@ func MiniGetArticleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
18 } 19 }
19 20
20 l := article.NewMiniGetArticleLogic(r.Context(), svcCtx) 21 l := article.NewMiniGetArticleLogic(r.Context(), svcCtx)
21 - 22 + token := contextdata.GetUserTokenFromCtx(r.Context())
  23 + req.CompanyId = token.CompanyId
22 resp, err := l.MiniGetArticle(&req) 24 resp, err := l.MiniGetArticle(&req)
23 if err != nil { 25 if err != nil {
24 httpx.ErrorCtx(r.Context(), w, err) 26 httpx.ErrorCtx(r.Context(), w, err)
  1 +package article
  2 +
  3 +import (
  4 + "net/http"
  5 +
  6 + "github.com/zeromicro/go-zero/rest/httpx"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/article"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  11 +)
  12 +
  13 +func MiniSetUserLikeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  14 + return func(w http.ResponseWriter, r *http.Request) {
  15 + var req types.MiniSetUserLikeRequset
  16 + if err := httpx.Parse(r, &req); err != nil {
  17 + httpx.ErrorCtx(r.Context(), w, err)
  18 + return
  19 + }
  20 +
  21 + l := article.NewMiniSetUserLikeLogic(r.Context(), svcCtx)
  22 + token := contextdata.GetUserTokenFromCtx(r.Context())
  23 + req.UserId = token.UserId
  24 + resp, err := l.MiniSetUserLike(&req)
  25 + if err != nil {
  26 + httpx.ErrorCtx(r.Context(), w, err)
  27 + } else {
  28 + httpx.OkJsonCtx(r.Context(), w, resp)
  29 + }
  30 + }
  31 +}
  1 +package article
  2 +
  3 +import (
  4 + "net/http"
  5 +
  6 + "github.com/zeromicro/go-zero/rest/httpx"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/logic/article"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  11 +)
  12 +
  13 +func MiniUserLikeArticleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
  14 + return func(w http.ResponseWriter, r *http.Request) {
  15 + var req types.MiniUserLikeArticleRequest
  16 + if err := httpx.Parse(r, &req); err != nil {
  17 + httpx.ErrorCtx(r.Context(), w, err)
  18 + return
  19 + }
  20 +
  21 + l := article.NewMiniUserLikeArticleLogic(r.Context(), svcCtx)
  22 + token := contextdata.GetUserTokenFromCtx(r.Context())
  23 + req.CompanyId = token.CompanyId
  24 + resp, err := l.MiniUserLikeArticle(&req)
  25 + if err != nil {
  26 + httpx.ErrorCtx(r.Context(), w, err)
  27 + } else {
  28 + httpx.OkJsonCtx(r.Context(), w, resp)
  29 + }
  30 + }
  31 +}
@@ -192,6 +192,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { @@ -192,6 +192,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
192 Path: "/article/:id", 192 Path: "/article/:id",
193 Handler: article.MiniGetArticleHandler(serverCtx), 193 Handler: article.MiniGetArticleHandler(serverCtx),
194 }, 194 },
  195 + {
  196 + Method: http.MethodPost,
  197 + Path: "/article/user_like/list",
  198 + Handler: article.MiniUserLikeArticleHandler(serverCtx),
  199 + },
  200 + {
  201 + Method: http.MethodPost,
  202 + Path: "/article/user_like/set",
  203 + Handler: article.MiniSetUserLikeHandler(serverCtx),
  204 + },
195 }, 205 },
196 rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret), 206 rest.WithJwt(serverCtx.Config.MiniAuth.AccessSecret),
197 rest.WithPrefix("/v1/mini"), 207 rest.WithPrefix("/v1/mini"),
@@ -12,7 +12,7 @@ import ( @@ -12,7 +12,7 @@ import (
12 12
13 func MiniUserFollowerHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { 13 func MiniUserFollowerHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
14 return func(w http.ResponseWriter, r *http.Request) { 14 return func(w http.ResponseWriter, r *http.Request) {
15 - var req types.UserSearchRequest 15 + var req types.MiniUserFollowedSearchRequest
16 if err := httpx.Parse(r, &req); err != nil { 16 if err := httpx.Parse(r, &req); err != nil {
17 httpx.ErrorCtx(r.Context(), w, err) 17 httpx.ErrorCtx(r.Context(), w, err)
18 return 18 return
@@ -12,7 +12,7 @@ import ( @@ -12,7 +12,7 @@ import (
12 12
13 func MiniUserFollowingHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { 13 func MiniUserFollowingHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
14 return func(w http.ResponseWriter, r *http.Request) { 14 return func(w http.ResponseWriter, r *http.Request) {
15 - var req types.UserSearchRequest 15 + var req types.MiniUserFollowedSearchRequest
16 if err := httpx.Parse(r, &req); err != nil { 16 if err := httpx.Parse(r, &req); err != nil {
17 httpx.ErrorCtx(r.Context(), w, err) 17 httpx.ErrorCtx(r.Context(), w, err)
18 return 18 return
@@ -46,7 +46,9 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -46,7 +46,9 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
46 Company: "", 46 Company: "",
47 CompanyId: author.CompanyId, 47 CompanyId: author.CompanyId,
48 } 48 }
49 - 49 + if len(req.Images) > 9 {
  50 + return nil, xerr.NewErrMsg("图片数量最多9张")
  51 + }
50 //TODO 获取图片的尺寸大小 52 //TODO 获取图片的尺寸大小
51 images := []domain.Image{} 53 images := []domain.Image{}
52 for _, val := range req.Images { 54 for _, val := range req.Images {
@@ -56,6 +58,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR @@ -56,6 +58,7 @@ func (l *MiniCreateArticleLogic) MiniCreateArticle(req *types.MiniArticleCreateR
56 Height: 0, 58 Height: 0,
57 }) 59 })
58 } 60 }
  61 +
59 //检查文章可被哪些人查看 62 //检查文章可被哪些人查看
60 whoRead := []int64{} 63 whoRead := []int64{}
61 if len(req.WhoRead) > 0 { 64 if len(req.WhoRead) > 0 {
@@ -2,9 +2,12 @@ package article @@ -2,9 +2,12 @@ package article
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "sort"
5 6
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 8 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
8 11
9 "github.com/zeromicro/go-zero/core/logx" 12 "github.com/zeromicro/go-zero/core/logx"
10 ) 13 )
@@ -24,7 +27,76 @@ func NewMiniGetArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Mi @@ -24,7 +27,76 @@ func NewMiniGetArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Mi
24 } 27 }
25 28
26 func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (resp *types.MiniArticleGetResponse, err error) { 29 func (l *MiniGetArticleLogic) MiniGetArticle(req *types.MiniArticleGetRequest) (resp *types.MiniArticleGetResponse, err error) {
27 - // todo: add your logic here and delete this line 30 + // 获取文章内容
  31 + var conn = l.svcCtx.DefaultDBConn()
  32 +
  33 + articleInfo, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.Id)
  34 + if err != nil {
  35 + return nil, xerr.NewErrMsgErr("读取文章内容失败", err)
  36 + }
  37 + if articleInfo.CompanyId != req.CompanyId {
  38 + return nil, xerr.NewErrMsg("没有查看权限")
  39 + }
  40 +
  41 + if articleInfo.Show == domain.ArticleShowDisable {
  42 + resp = &types.MiniArticleGetResponse{
  43 + Id: articleInfo.Id,
  44 + Title: articleInfo.Title,
  45 + Show: int(domain.ArticleShowDisable),
  46 + }
  47 + return resp, nil
  48 + }
  49 + queryOption := domain.NewQueryOptions().
  50 + WithFindOnly().
  51 + MustWithKV("articleId", articleInfo.Id)
  52 +
  53 + _, sectionList, err := l.svcCtx.ArticleSectionRepository.Find(l.ctx, conn, queryOption)
  54 + if err != nil {
  55 + return nil, xerr.NewErrMsgErr("读取文章内容失败", err)
  56 + }
  57 + sortBy := domain.SortArticleSection(sectionList)
  58 + sort.Sort(sortBy)
  59 + articleSection := []types.ArticleSection{}
  60 +
  61 + for _, val := range sortBy {
  62 + articleSection = append(articleSection, types.ArticleSection{
  63 + Id: val.Id,
  64 + Content: val.Content,
  65 + SortBy: val.SortBy,
  66 + TotalComment: val.TotalComment,
  67 + })
  68 + }
  69 + resp = &types.MiniArticleGetResponse{
  70 + Id: articleInfo.Id,
  71 + Title: articleInfo.Title,
  72 + AuthorId: articleInfo.AuthorId,
  73 + Author: types.Author{
  74 + Id: articleInfo.Author.Id,
  75 + Name: articleInfo.Author.Name,
  76 + Avatar: articleInfo.Author.Avatar,
  77 + Group: articleInfo.Author.Group,
  78 + Position: articleInfo.Author.Position,
  79 + Company: articleInfo.Author.Company,
  80 + },
  81 + CreatedAt: articleInfo.CreatedAt,
  82 + Section: articleSection,
  83 + Images: []string{},
  84 + WhoRead: articleInfo.WhoRead,
  85 + WhoReview: articleInfo.WhoReview,
  86 + Location: types.Location{
  87 + Longitude: articleInfo.Location.Longitude,
  88 + Latitude: articleInfo.Location.Latitude,
  89 + Descript: articleInfo.Location.Descript,
  90 + },
  91 + CountLove: articleInfo.CountLove,
  92 + CountComment: articleInfo.CountComment,
  93 + CountRead: articleInfo.CountRead,
  94 + Show: int(articleInfo.Show),
  95 + }
  96 +
  97 + for _, val := range articleInfo.Images {
  98 + resp.Images = append(resp.Images, val.Url)
  99 + }
28 100
29 return 101 return
30 } 102 }
  1 +package article
  2 +
  3 +import (
  4 + "context"
  5 +
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  10 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
  11 +
  12 + "github.com/zeromicro/go-zero/core/logx"
  13 +)
  14 +
  15 +type MiniSetUserLikeLogic struct {
  16 + logx.Logger
  17 + ctx context.Context
  18 + svcCtx *svc.ServiceContext
  19 +}
  20 +
  21 +func NewMiniSetUserLikeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniSetUserLikeLogic {
  22 + return &MiniSetUserLikeLogic{
  23 + Logger: logx.WithContext(ctx),
  24 + ctx: ctx,
  25 + svcCtx: svcCtx,
  26 + }
  27 +}
  28 +
  29 +// 设置点赞操作
  30 +func (l *MiniSetUserLikeLogic) MiniSetUserLike(req *types.MiniSetUserLikeRequset) (resp *types.MiniSetUserLikeResponse, err error) {
  31 + //取消点赞文章
  32 + if req.Flag == 2 && req.CommentId == 0 {
  33 + return l.cancelSetUserLikeArticle(req)
  34 + }
  35 + // 取消点赞评论
  36 + if req.Flag == 2 && req.CommentId > 0 {
  37 + return l.cancelSetUserLikeComment(req)
  38 + }
  39 + // 设置点赞文章
  40 + if req.Flag == 1 && req.CommentId == 0 {
  41 + return l.setUserLikeArticle(req)
  42 + }
  43 + // 设置点赞评论
  44 + if req.Flag == 1 && req.CommentId > 0 {
  45 + return l.setUserLikeComment(req)
  46 + }
  47 +
  48 + return nil, xerr.NewErrMsg("操作失败")
  49 +}
  50 +
  51 +// 取消文章点赞
  52 +func (l *MiniSetUserLikeLogic) cancelSetUserLikeArticle(req *types.MiniSetUserLikeRequset) (resp *types.MiniSetUserLikeResponse, err error) {
  53 + var conn = l.svcCtx.DefaultDBConn()
  54 +
  55 + // 检查id
  56 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId)
  57 + if err != nil {
  58 + //无法确认 文章的id
  59 + return nil, xerr.NewErrMsgErr("无法确认操作人员信息", err)
  60 + }
  61 + articleInfo, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.ArticleId)
  62 + if err != nil {
  63 + //无法确认 文章的id
  64 + return nil, xerr.NewErrMsgErr("取消点赞标识失败", err)
  65 + }
  66 + if userInfo.CompanyId != articleInfo.CompanyId {
  67 + // 公司无法对应
  68 + return nil, xerr.NewErrMsg("没有操作权限")
  69 + }
  70 + queryOption := domain.NewQueryOptions().
  71 + WithFindOnly().
  72 + MustWithKV("articleId", req.ArticleId).
  73 + MustWithKV("commentId", req.CommentId).
  74 + MustWithKV("userId", req.UserId)
  75 + _, flagList, err := l.svcCtx.UserLoveFlagRepository.Find(l.ctx, conn, queryOption)
  76 + if err != nil {
  77 + return nil, xerr.NewErrMsgErr("取消点赞标识失败", err)
  78 + }
  79 + if len(flagList) == 0 {
  80 + //没有记录
  81 + resp = &types.MiniSetUserLikeResponse{
  82 + ArticleId: req.ArticleId,
  83 + CommentId: req.CommentId,
  84 + Count: articleInfo.CountLove,
  85 + }
  86 + return resp, nil
  87 + }
  88 + flagInfo := flagList[0]
  89 + err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error {
  90 + // 去除点赞标识
  91 + _, err = l.svcCtx.UserLoveFlagRepository.Delete(ctx, c, flagInfo)
  92 + if err != nil {
  93 + return err
  94 + }
  95 + // 减少文章的点赞数量
  96 + err = l.svcCtx.ArticleRepository.IncreaseCountLove(ctx, c, -1, articleInfo)
  97 + if err != nil {
  98 + return err
  99 + }
  100 + return nil
  101 + }, true)
  102 + if err != nil {
  103 + return nil, xerr.NewErrMsgErr("取消点赞标识失败", err)
  104 + }
  105 + articleInfo, err = l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.ArticleId)
  106 + if err == nil {
  107 + return nil, xerr.NewErrMsgErr("获取点赞数量失败", err)
  108 + }
  109 + resp = &types.MiniSetUserLikeResponse{
  110 + ArticleId: req.ArticleId,
  111 + CommentId: req.CommentId,
  112 + Count: articleInfo.CountLove,
  113 + }
  114 + return resp, nil
  115 +}
  116 +
  117 +// 取消评论点赞
  118 +func (l *MiniSetUserLikeLogic) cancelSetUserLikeComment(req *types.MiniSetUserLikeRequset) (resp *types.MiniSetUserLikeResponse, err error) {
  119 + var conn = l.svcCtx.DefaultDBConn()
  120 + // 检查id
  121 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId)
  122 + if err != nil {
  123 + //无法确认 文章的id
  124 + return nil, xerr.NewErrMsgErr("无法确认操作人员信息", err)
  125 + }
  126 + articleInfo, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.ArticleId)
  127 + if err != nil {
  128 + //无法确认 文章的id
  129 + return nil, xerr.NewErrMsgErr("取消点赞标识失败", err)
  130 + }
  131 + if userInfo.CompanyId != articleInfo.CompanyId {
  132 + // 文章和人员的公司无法对应
  133 + return nil, xerr.NewErrMsg("没有操作权限")
  134 + }
  135 + commentInfo, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, req.CommentId)
  136 + if err != nil {
  137 + return nil, xerr.NewErrMsgErr("无法确认评论信息", err)
  138 + }
  139 + if commentInfo.ArticleId != articleInfo.Id {
  140 + return nil, xerr.NewErrMsg("评论和文章不能对应")
  141 + }
  142 +
  143 + queryOption := domain.NewQueryOptions().
  144 + WithFindOnly().
  145 + MustWithKV("articleId", req.ArticleId).
  146 + MustWithKV("commentId", req.CommentId).
  147 + MustWithKV("userId", req.UserId)
  148 + _, flagList, err := l.svcCtx.UserLoveFlagRepository.Find(l.ctx, conn, queryOption)
  149 + if err != nil {
  150 + return nil, xerr.NewErrMsgErr("取消点赞标识失败", err)
  151 + }
  152 + if len(flagList) == 0 {
  153 + //没有记录
  154 + resp = &types.MiniSetUserLikeResponse{
  155 + ArticleId: req.ArticleId,
  156 + CommentId: req.CommentId,
  157 + Count: commentInfo.CountUserLove,
  158 + }
  159 + return resp, nil
  160 + }
  161 + flagInfo := flagList[0]
  162 + err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error {
  163 + // 去除点赞标识
  164 + _, err = l.svcCtx.UserLoveFlagRepository.Delete(ctx, c, flagInfo)
  165 + if err != nil {
  166 + return err
  167 + }
  168 + // 减少评论的点赞数量
  169 + err = l.svcCtx.ArticleCommentRepository.IncreaseCountUserLove(ctx, c, -1, commentInfo)
  170 + if err != nil {
  171 + return err
  172 + }
  173 + return nil
  174 + }, true)
  175 + if err != nil {
  176 + return nil, xerr.NewErrMsgErr("取消点赞标识失败", err)
  177 + }
  178 + commentInfo, err = l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, req.CommentId)
  179 + if err != nil {
  180 + return nil, xerr.NewErrMsgErr("获取评论的点赞数量失败", err)
  181 + }
  182 + resp = &types.MiniSetUserLikeResponse{
  183 + ArticleId: req.ArticleId,
  184 + CommentId: req.CommentId,
  185 + Count: commentInfo.CountUserLove,
  186 + }
  187 + return resp, nil
  188 +}
  189 +
  190 +// 设置文章点赞
  191 +func (l *MiniSetUserLikeLogic) setUserLikeArticle(req *types.MiniSetUserLikeRequset) (resp *types.MiniSetUserLikeResponse, err error) {
  192 + var conn = l.svcCtx.DefaultDBConn()
  193 +
  194 + // 检查id
  195 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId)
  196 + if err != nil {
  197 + //无法确认 文章的id
  198 + return nil, xerr.NewErrMsgErr("无法确认操作人员信息", err)
  199 + }
  200 + articleInfo, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.ArticleId)
  201 + if err != nil {
  202 + //无法确认 文章的id
  203 + return nil, xerr.NewErrMsgErr("设置点赞标识失败", err)
  204 + }
  205 + if userInfo.CompanyId != articleInfo.CompanyId {
  206 + // 公司无法对应
  207 + return nil, xerr.NewErrMsg("没有操作权限")
  208 + }
  209 + queryOption := domain.NewQueryOptions().
  210 + WithFindOnly().
  211 + MustWithKV("articleId", req.ArticleId).
  212 + MustWithKV("commentId", req.CommentId).
  213 + MustWithKV("userId", req.UserId)
  214 + _, flagList, err := l.svcCtx.UserLoveFlagRepository.Find(l.ctx, conn, queryOption)
  215 + if err != nil {
  216 + return nil, xerr.NewErrMsgErr("设置点赞标识失败", err)
  217 + }
  218 + if len(flagList) > 0 {
  219 + //已经有记录
  220 + resp = &types.MiniSetUserLikeResponse{
  221 + ArticleId: req.ArticleId,
  222 + CommentId: req.CommentId,
  223 + Count: articleInfo.CountLove,
  224 + }
  225 + return resp, nil
  226 + }
  227 + err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error {
  228 + flagInfo := domain.UserLoveFlag{
  229 + Id: 0,
  230 + ArticleId: req.ArticleId,
  231 + CommentId: req.CommentId,
  232 + UserId: req.UserId,
  233 + }
  234 + // 去除点赞标识
  235 + _, err = l.svcCtx.UserLoveFlagRepository.Insert(ctx, c, &flagInfo)
  236 + if err != nil {
  237 + return err
  238 + }
  239 + // 增加文章的点赞数量
  240 + err = l.svcCtx.ArticleRepository.IncreaseCountLove(ctx, c, 1, articleInfo)
  241 + if err != nil {
  242 + return err
  243 + }
  244 + return nil
  245 + }, true)
  246 + if err != nil {
  247 + return nil, xerr.NewErrMsgErr("设置点赞标识失败", err)
  248 + }
  249 + articleInfo, err = l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.ArticleId)
  250 + if err == nil {
  251 + return nil, xerr.NewErrMsgErr("获取点赞数量失败", err)
  252 + }
  253 + resp = &types.MiniSetUserLikeResponse{
  254 + ArticleId: req.ArticleId,
  255 + CommentId: req.CommentId,
  256 + Count: articleInfo.CountLove,
  257 + }
  258 + return resp, nil
  259 +}
  260 +
  261 +// 设置评论点赞
  262 +func (l *MiniSetUserLikeLogic) setUserLikeComment(req *types.MiniSetUserLikeRequset) (resp *types.MiniSetUserLikeResponse, err error) {
  263 + var conn = l.svcCtx.DefaultDBConn()
  264 + // 检查id
  265 + userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId)
  266 + if err != nil {
  267 + //无法确认 文章的id
  268 + return nil, xerr.NewErrMsgErr("无法确认操作人员信息", err)
  269 + }
  270 + articleInfo, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, req.ArticleId)
  271 + if err != nil {
  272 + //无法确认 文章的id
  273 + return nil, xerr.NewErrMsgErr("设置点赞标识失败", err)
  274 + }
  275 + if userInfo.CompanyId != articleInfo.CompanyId {
  276 + // 文章和人员的公司无法对应
  277 + return nil, xerr.NewErrMsg("没有操作权限")
  278 + }
  279 + commentInfo, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, req.CommentId)
  280 + if err != nil {
  281 + return nil, xerr.NewErrMsgErr("无法确认评论信息", err)
  282 + }
  283 + if commentInfo.ArticleId != articleInfo.Id {
  284 + return nil, xerr.NewErrMsg("评论和文章不能对应")
  285 + }
  286 +
  287 + queryOption := domain.NewQueryOptions().
  288 + WithFindOnly().
  289 + MustWithKV("articleId", req.ArticleId).
  290 + MustWithKV("commentId", req.CommentId).
  291 + MustWithKV("userId", req.UserId)
  292 + _, flagList, err := l.svcCtx.UserLoveFlagRepository.Find(l.ctx, conn, queryOption)
  293 + if err != nil {
  294 + return nil, xerr.NewErrMsgErr("设置点赞标识失败", err)
  295 + }
  296 + if len(flagList) > 0 {
  297 + //已经有记录
  298 + resp = &types.MiniSetUserLikeResponse{
  299 + ArticleId: req.ArticleId,
  300 + CommentId: req.CommentId,
  301 + Count: commentInfo.CountUserLove,
  302 + }
  303 + return resp, nil
  304 + }
  305 +
  306 + err = transaction.UseTrans(l.ctx, conn.DB(), func(ctx context.Context, c transaction.Conn) error {
  307 + flagInfo := domain.UserLoveFlag{
  308 + Id: 0,
  309 + ArticleId: req.ArticleId,
  310 + CommentId: req.CommentId,
  311 + UserId: req.UserId,
  312 + }
  313 + // 设置赞标识
  314 + _, err = l.svcCtx.UserLoveFlagRepository.Insert(ctx, c, &flagInfo)
  315 + if err != nil {
  316 + return err
  317 + }
  318 + // 增加评论的点赞数量
  319 + err = l.svcCtx.ArticleCommentRepository.IncreaseCountUserLove(ctx, c, 1, commentInfo)
  320 + if err != nil {
  321 + return err
  322 + }
  323 + return nil
  324 + }, true)
  325 + if err != nil {
  326 + return nil, xerr.NewErrMsgErr("设置点赞标识失败", err)
  327 + }
  328 + commentInfo, err = l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, req.CommentId)
  329 + if err != nil {
  330 + return nil, xerr.NewErrMsgErr("获取评论的点赞数量失败", err)
  331 + }
  332 + resp = &types.MiniSetUserLikeResponse{
  333 + ArticleId: req.ArticleId,
  334 + CommentId: req.CommentId,
  335 + Count: commentInfo.CountUserLove,
  336 + }
  337 + return resp, nil
  338 +}
  1 +package article
  2 +
  3 +import (
  4 + "context"
  5 +
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  9 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
  10 +
  11 + "github.com/zeromicro/go-zero/core/logx"
  12 +)
  13 +
  14 +type MiniUserLikeArticleLogic struct {
  15 + logx.Logger
  16 + ctx context.Context
  17 + svcCtx *svc.ServiceContext
  18 +}
  19 +
  20 +func NewMiniUserLikeArticleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniUserLikeArticleLogic {
  21 + return &MiniUserLikeArticleLogic{
  22 + Logger: logx.WithContext(ctx),
  23 + ctx: ctx,
  24 + svcCtx: svcCtx,
  25 + }
  26 +}
  27 +
  28 +// 获取点赞的人员列表
  29 +func (l *MiniUserLikeArticleLogic) MiniUserLikeArticle(req *types.MiniUserLikeArticleRequest) (resp *types.MiniUserLikeArticleResponse, err error) {
  30 + var conn = l.svcCtx.DefaultDBConn()
  31 + queryOption := domain.NewQueryOptions().
  32 + WithOffsetLimit(req.Page, req.Size).
  33 + MustWithKV("articleId", req.ArticleId).
  34 + MustWithKV("commentId", 0)
  35 + cnt, flagList, err := l.svcCtx.UserLoveFlagRepository.Find(l.ctx, conn, queryOption)
  36 + if err != nil {
  37 + return nil, xerr.NewErrMsgErr("获取人员列表失败", err)
  38 + }
  39 + uidList := []int64{}
  40 + for _, val := range flagList {
  41 + uidList = append(uidList, val.UserId)
  42 + }
  43 + queryOption = domain.NewQueryOptions().
  44 + WithFindOnly().
  45 + MustWithKV("ids", uidList)
  46 +
  47 + // 获取人员列表
  48 + _, userList, err := l.svcCtx.UserRepository.Find(l.ctx, conn, queryOption)
  49 + if err != nil {
  50 + return nil, xerr.NewErrMsgErr("获取人员列表失败", err)
  51 + }
  52 + userMap := map[int64]*domain.User{}
  53 + for i := range userList {
  54 + if userList[i].CompanyId != req.CompanyId {
  55 + return nil, xerr.NewErrMsg("操作失败")
  56 + }
  57 + userMap[userList[i].Id] = userList[i]
  58 + }
  59 + resp = &types.MiniUserLikeArticleResponse{
  60 + Total: cnt,
  61 + List: make([]types.WhichUserLikeArticle, len(flagList)),
  62 + }
  63 + for i, val := range flagList {
  64 + item := types.WhichUserLikeArticle{
  65 + ArticleId: val.ArticleId,
  66 + UserId: val.UserId,
  67 + Name: "[用户已被清除]",
  68 + Avatar: "",
  69 + CreatedAt: val.CreatedAt,
  70 + }
  71 + if u, ok := userMap[val.UserId]; ok {
  72 + item.Name = u.Name
  73 + item.Avatar = u.Avatar
  74 + }
  75 + resp.List[i] = item
  76 + }
  77 + return resp, nil
  78 +}
@@ -2,6 +2,10 @@ package user @@ -2,6 +2,10 @@ package user
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
5 9
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
@@ -23,8 +27,32 @@ func NewMiniUserFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Mi @@ -23,8 +27,32 @@ func NewMiniUserFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Mi
23 } 27 }
24 } 28 }
25 29
26 -func (l *MiniUserFollowLogic) MiniUserFollow(req *types.FollowRequest) error {  
27 - // todo: add your logic here and delete this line  
28 - 30 +func (l *MiniUserFollowLogic) MiniUserFollow(req *types.FollowRequest) (err error) {
  31 + var (
  32 + conn = l.svcCtx.DefaultDBConn()
  33 + user *domain.User
  34 + targetUser *domain.User
  35 + userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  36 + )
  37 + if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
  38 + return xerr.NewErrMsgErr("用户不存在", err)
  39 + }
  40 + if targetUser, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId); err != nil {
  41 + return xerr.NewErrMsgErr("关注的用户不存在", err)
  42 + }
  43 + if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error {
  44 + if err = user.Follow(targetUser); err != nil {
  45 + return err
  46 + }
  47 + if user, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, user); err != nil {
  48 + return err
  49 + }
  50 + if targetUser, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, targetUser); err != nil {
  51 + return err
  52 + }
  53 + return nil
  54 + }, true); err != nil {
  55 + return xerr.NewErrMsgErr("关注用户失败", err)
  56 + }
29 return nil 57 return nil
30 } 58 }
@@ -2,6 +2,10 @@ package user @@ -2,6 +2,10 @@ package user
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "github.com/samber/lo"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
5 9
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
@@ -23,8 +27,42 @@ func NewMiniUserFollowerLogic(ctx context.Context, svcCtx *svc.ServiceContext) * @@ -23,8 +27,42 @@ func NewMiniUserFollowerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
23 } 27 }
24 } 28 }
25 29
26 -func (l *MiniUserFollowerLogic) MiniUserFollower(req *types.UserSearchRequest) (resp *types.UserSearchResponse, err error) {  
27 - // todo: add your logic here and delete this line  
28 - 30 +func (l *MiniUserFollowerLogic) MiniUserFollower(req *types.MiniUserFollowedSearchRequest) (resp *types.MiniUserFollowedSearchResponse, err error) {
  31 + var (
  32 + conn = l.svcCtx.DefaultDBConn()
  33 + user *domain.User
  34 + userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  35 + companyMap = make(map[int64]*domain.Company)
  36 + )
  37 + if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
  38 + return nil, xerr.NewErrMsgErr("用户不存在", err)
  39 + }
  40 + var (
  41 + users = user.Follower
  42 + total = int64(len(users))
  43 + offset, limit = domain.OffsetLimit(req.Page, req.Size)
  44 + )
  45 + users = lo.Slice(users, offset, offset+limit)
  46 + resp = &types.MiniUserFollowedSearchResponse{
  47 + Total: total,
  48 + List: make([]*types.UserFollowItem, 0),
  49 + }
  50 + lo.ForEach(users, func(item int64, index int) {
  51 + if foundUser, _ := l.svcCtx.UserRepository.FindOne(l.ctx, conn, item); foundUser != nil {
  52 + var companyName = ""
  53 + if company, _ := domain.LazyLoad(companyMap, l.ctx, conn, foundUser.CompanyId, l.svcCtx.CompanyRepository.FindOne); company != nil {
  54 + companyName = company.Name
  55 + }
  56 + resp.List = append(resp.List, &types.UserFollowItem{
  57 + Id: foundUser.Id,
  58 + Name: foundUser.Name,
  59 + CompanyName: companyName,
  60 + Avatar: foundUser.Avatar,
  61 + Position: foundUser.Position,
  62 + Followed: true,
  63 + MutualFollowed: lo.Contains(user.Following, item),
  64 + })
  65 + }
  66 + })
29 return 67 return
30 } 68 }
@@ -2,6 +2,10 @@ package user @@ -2,6 +2,10 @@ package user
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "github.com/samber/lo"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
5 9
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
@@ -23,8 +27,42 @@ func NewMiniUserFollowingLogic(ctx context.Context, svcCtx *svc.ServiceContext) @@ -23,8 +27,42 @@ func NewMiniUserFollowingLogic(ctx context.Context, svcCtx *svc.ServiceContext)
23 } 27 }
24 } 28 }
25 29
26 -func (l *MiniUserFollowingLogic) MiniUserFollowing(req *types.UserSearchRequest) (resp *types.UserSearchResponse, err error) {  
27 - // todo: add your logic here and delete this line  
28 - 30 +func (l *MiniUserFollowingLogic) MiniUserFollowing(req *types.MiniUserFollowedSearchRequest) (resp *types.MiniUserFollowedSearchResponse, err error) {
  31 + var (
  32 + conn = l.svcCtx.DefaultDBConn()
  33 + user *domain.User
  34 + userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  35 + companyMap = make(map[int64]*domain.Company)
  36 + )
  37 + if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
  38 + return nil, xerr.NewErrMsgErr("用户不存在", err)
  39 + }
  40 + var (
  41 + users = user.Following
  42 + total = int64(len(users))
  43 + offset, limit = domain.OffsetLimit(req.Page, req.Size)
  44 + )
  45 + users = lo.Slice(users, offset, offset+limit)
  46 + resp = &types.MiniUserFollowedSearchResponse{
  47 + Total: total,
  48 + List: make([]*types.UserFollowItem, 0),
  49 + }
  50 + lo.ForEach(users, func(item int64, index int) {
  51 + if foundUser, _ := l.svcCtx.UserRepository.FindOne(l.ctx, conn, item); foundUser != nil {
  52 + var companyName = ""
  53 + if company, _ := domain.LazyLoad(companyMap, l.ctx, conn, foundUser.CompanyId, l.svcCtx.CompanyRepository.FindOne); company != nil {
  54 + companyName = company.Name
  55 + }
  56 + resp.List = append(resp.List, &types.UserFollowItem{
  57 + Id: foundUser.Id,
  58 + Name: foundUser.Name,
  59 + CompanyName: companyName,
  60 + Avatar: foundUser.Avatar,
  61 + Position: foundUser.Position,
  62 + Followed: true,
  63 + //MutualFollowed: lo.Contains(user.Following, foundUser.Id),
  64 + })
  65 + }
  66 + })
29 return 67 return
30 } 68 }
@@ -2,6 +2,10 @@ package user @@ -2,6 +2,10 @@ package user
2 2
3 import ( 3 import (
4 "context" 4 "context"
  5 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
  6 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
  7 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/contextdata"
  8 + "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
5 9
6 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc" 10 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
7 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types" 11 "gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"
@@ -23,8 +27,32 @@ func NewMiniUserUnFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) * @@ -23,8 +27,32 @@ func NewMiniUserUnFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
23 } 27 }
24 } 28 }
25 29
26 -func (l *MiniUserUnFollowLogic) MiniUserUnFollow(req *types.FollowRequest) error {  
27 - // todo: add your logic here and delete this line  
28 - 30 +func (l *MiniUserUnFollowLogic) MiniUserUnFollow(req *types.FollowRequest) (err error) {
  31 + var (
  32 + conn = l.svcCtx.DefaultDBConn()
  33 + user *domain.User
  34 + targetUser *domain.User
  35 + userToken = contextdata.GetUserTokenFromCtx(l.ctx)
  36 + )
  37 + if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
  38 + return xerr.NewErrMsgErr("用户不存在", err)
  39 + }
  40 + if targetUser, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId); err != nil {
  41 + return xerr.NewErrMsgErr("关注的用户不存在", err)
  42 + }
  43 + if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error {
  44 + if err = user.Unfollow(targetUser); err != nil {
  45 + return err
  46 + }
  47 + if user, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, user); err != nil {
  48 + return err
  49 + }
  50 + if targetUser, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, targetUser); err != nil {
  51 + return err
  52 + }
  53 + return nil
  54 + }, true); err != nil {
  55 + return xerr.NewErrMsgErr("关注用户失败", err)
  56 + }
29 return nil 57 return nil
30 } 58 }
@@ -192,6 +192,16 @@ type MiniUserDepartmentUsersResponse struct { @@ -192,6 +192,16 @@ type MiniUserDepartmentUsersResponse struct {
192 Users []*UserItem `json:"users"` 192 Users []*UserItem `json:"users"`
193 } 193 }
194 194
  195 +type MiniUserFollowedSearchRequest struct {
  196 + Page int `json:"page,optional"`
  197 + Size int `json:"size,optional"`
  198 +}
  199 +
  200 +type MiniUserFollowedSearchResponse struct {
  201 + List []*UserFollowItem `json:"users"`
  202 + Total int64 `json:"total"`
  203 +}
  204 +
195 type UserItem struct { 205 type UserItem struct {
196 Id int64 `json:"id,omitempty"` // 用户ID 206 Id int64 `json:"id,omitempty"` // 用户ID
197 CompanyId int64 `json:"companyId,omitempty"` // 公司ID 207 CompanyId int64 `json:"companyId,omitempty"` // 公司ID
@@ -231,6 +241,16 @@ type FollowRequest struct { @@ -231,6 +241,16 @@ type FollowRequest struct {
231 UserId int64 `json:"userId"` 241 UserId int64 `json:"userId"`
232 } 242 }
233 243
  244 +type UserFollowItem struct {
  245 + Id int64 `json:"id"` // 用户ID
  246 + Name string `json:"name"` // 名称
  247 + CompanyName string `json:"companyName"` // 公司名称
  248 + Avatar string `json:"avatar"` // 头像
  249 + Position string `json:"position"` // 职位
  250 + Followed bool `json:"followed"` // 关注
  251 + MutualFollowed bool `json:"mutualFollowed"` // 互相关注标识
  252 +}
  253 +
234 type CompanySearchRequest struct { 254 type CompanySearchRequest struct {
235 Page int `json:"page"` 255 Page int `json:"page"`
236 Size int `json:"size"` 256 Size int `json:"size"`
@@ -262,6 +282,7 @@ type Author struct { @@ -262,6 +282,7 @@ type Author struct {
262 Avatar string `json:"avatar"` // 人员头像URL 282 Avatar string `json:"avatar"` // 人员头像URL
263 Group string `json:"group"` // 人员的分组 283 Group string `json:"group"` // 人员的分组
264 Position string `json:"position"` // 职位 284 Position string `json:"position"` // 职位
  285 + Company string `json:"company"` // 公司
265 } 286 }
266 287
267 type MiniArticleCreateRequest struct { 288 type MiniArticleCreateRequest struct {
@@ -279,29 +300,39 @@ type MiniArticleCreateResponse struct { @@ -279,29 +300,39 @@ type MiniArticleCreateResponse struct {
279 } 300 }
280 301
281 type MiniArticleGetRequest struct { 302 type MiniArticleGetRequest struct {
282 - Id int64 `path:"id"` //id 303 + Id int64 `path:"id"` //id
  304 + CompanyId int64 `path:"-"`
283 } 305 }
284 306
285 type MiniArticleGetResponse struct { 307 type MiniArticleGetResponse struct {
286 - Title string `json:"title"` //标题  
287 - AuthorId int `json:"authorId"` //发布人id  
288 - Author Author `json:"author"` //发布人  
289 - CreatedAt int64 `json:"createdAt"` //文章的发布时间  
290 - Section []string `json:"section"` //文章的文本内容  
291 - Images []string `json:"images"` //图片  
292 - WhoRead []int64 `json:"whoRead"` //谁可查看  
293 - WhoReview []int64 `json:"whoReview"` //谁可评论  
294 - Location Location `json:"location"` //定位坐标  
295 - CountLove int `json:"countLove"` // 点赞数量  
296 - CountComment int `json:"countComment"` // 评论数量  
297 - Show int `json:"showState"` // 评论的展示状态(0显示、1不显示) 308 + Id int64 `json:"id"` //id
  309 + Title string `json:"title"` //标题
  310 + AuthorId int64 `json:"authorId"` //发布人id
  311 + Author Author `json:"author"` //发布人
  312 + CreatedAt int64 `json:"createdAt"` //文章的发布时间
  313 + Section []ArticleSection `json:"section"` //文章的文本内容
  314 + Images []string `json:"images"` //图片
  315 + WhoRead []int64 `json:"whoRead"` //谁可查看
  316 + WhoReview []int64 `json:"whoReview"` //谁可评论
  317 + Location Location `json:"location"` //定位坐标
  318 + CountLove int `json:"countLove"` // 点赞数量
  319 + CountComment int `json:"countComment"` // 评论数量
  320 + CountRead int `json:"countRead"` // 浏览数量
  321 + Show int `json:"show"` // 评论的展示状态(0显示、1不显示)
  322 +}
  323 +
  324 +type ArticleSection struct {
  325 + Id int64 `json:"id"` //段落id
  326 + Content string `json:"content"` // 文本内容
  327 + SortBy int `json:"sortBy"` // 排序
  328 + TotalComment int `json:"totalComment"` // 评论的数量
298 } 329 }
299 330
300 type MiniArticleSearchMeRequest struct { 331 type MiniArticleSearchMeRequest struct {
301 - AuthorId int64 `json:"-"` 332 + AuthorId int64 `json:"-"`
302 CompanyId int64 `json:"-"` 333 CompanyId int64 `json:"-"`
303 - Page int `json:"page"`  
304 - Size int `json:"size"` 334 + Page int `json:"page"`
  335 + Size int `json:"size"`
305 } 336 }
306 337
307 type MiniArticleSearchMeResponse struct { 338 type MiniArticleSearchMeResponse struct {
@@ -318,3 +349,36 @@ type ArticleSearchMe struct { @@ -318,3 +349,36 @@ type ArticleSearchMe struct {
318 CountComment int `json:"CountComment"` //评论数量 349 CountComment int `json:"CountComment"` //评论数量
319 Show int `json:"show"` //是否隐藏 [0显示、1不显示] 350 Show int `json:"show"` //是否隐藏 [0显示、1不显示]
320 } 351 }
  352 +
  353 +type MiniUserLikeArticleRequest struct {
  354 + ArticleId int64 `json:"articleId"` // 文章id
  355 + CompanyId int64 `json:"-"` //公司id
  356 + Page int `json:"page"` //分页,第几页
  357 + Size int `json:"size"` //分页,每页几条
  358 +}
  359 +
  360 +type MiniUserLikeArticleResponse struct {
  361 + Total int64 `json:"total"` //总数
  362 + List []WhichUserLikeArticle `json:"list"` //列表
  363 +}
  364 +
  365 +type WhichUserLikeArticle struct {
  366 + ArticleId int64 `json:"articleId"` // 文章id
  367 + UserId int64 `json:"userId"` // 人员id
  368 + Name string `json:"name"` // 人员名称
  369 + Avatar string `json:"avatar"` // 人员头像
  370 + CreatedAt int64 `json:"createdAt"` // 点赞记录的时间
  371 +}
  372 +
  373 +type MiniSetUserLikeRequset struct {
  374 + ArticleId int64 `json:"articleId"` //文章id
  375 + CommentId int64 `json:"commentId"` //评论id
  376 + UserId int64 `json:"-"` //操作人
  377 + Flag int `json:"flag"` //点赞标志 1、点赞 2 、取消点赞
  378 +}
  379 +
  380 +type MiniSetUserLikeResponse struct {
  381 + ArticleId int64 `json:"articleId"` //文章id
  382 + CommentId int64 `json:"commentId"` //评论id
  383 + Count int `json:"count"` //现有的点赞数量
  384 +}
@@ -9,7 +9,11 @@ import ( @@ -9,7 +9,11 @@ import (
9 ) 9 )
10 10
11 type Role struct { 11 type Role struct {
12 - Id int64 // 唯一标识 12 + Id int64 // 唯一标识
  13 + Name string `json:"name"` // 角色名称
  14 + Auths []int64 `gorm:"type:jsonb;serializer:json"` // 角色权限列表
  15 + Remark string `json:"remark"` // 备注
  16 + Users []int64 `gorm:"type:jsonb;serializer:json"` // 绑定的用户
13 17
14 CreatedAt int64 18 CreatedAt int64
15 UpdatedAt int64 19 UpdatedAt int64
@@ -194,6 +194,11 @@ func (repository *ArticleCommentRepository) DomainModelToModel(from *domain.Arti @@ -194,6 +194,11 @@ func (repository *ArticleCommentRepository) DomainModelToModel(from *domain.Arti
194 return to, nil 194 return to, nil
195 } 195 }
196 196
  197 +// TODO 点赞数量变动
  198 +func (repository *ArticleCommentRepository) IncreaseCountUserLove(ctx context.Context, conn transaction.Conn, incr int, dm *domain.ArticleComment) error {
  199 + return nil
  200 +}
  201 +
197 func NewArticleCommentRepository(cache *cache.CachedRepository) domain.ArticleCommentRepository { 202 func NewArticleCommentRepository(cache *cache.CachedRepository) domain.ArticleCommentRepository {
198 return &ArticleCommentRepository{CachedRepository: cache} 203 return &ArticleCommentRepository{CachedRepository: cache}
199 } 204 }
@@ -198,6 +198,61 @@ func (repository *ArticleRepository) DomainModelToModel(from *domain.Article) (* @@ -198,6 +198,61 @@ func (repository *ArticleRepository) DomainModelToModel(from *domain.Article) (*
198 return to, nil 198 return to, nil
199 } 199 }
200 200
  201 +// 点赞数量变动
  202 +func (repository *ArticleRepository) IncreaseCountLove(ctx context.Context, conn transaction.Conn, incr int, article *domain.Article) error {
  203 + //
  204 + var (
  205 + err error
  206 + m *models.Article
  207 + tx = conn.DB()
  208 + )
  209 + m = &models.Article{Id: article.Id}
  210 + queryFunc := func() (interface{}, error) {
  211 + tx = tx.Model(m).Update("count_love", gorm.Expr("count_love+?", incr))
  212 + return nil, tx.Error
  213 + }
  214 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  215 + return err
  216 + }
  217 + return nil
  218 +}
  219 +
  220 +// 浏览数量变动
  221 +func (repository *ArticleRepository) IncreaseCountRead(ctx context.Context, conn transaction.Conn, incr int, article *domain.Article) error {
  222 + var (
  223 + err error
  224 + m *models.Article
  225 + tx = conn.DB()
  226 + )
  227 + m = &models.Article{Id: article.Id}
  228 + queryFunc := func() (interface{}, error) {
  229 + tx = tx.Model(m).Update("count_read", gorm.Expr("count_read+?", incr))
  230 + return nil, tx.Error
  231 + }
  232 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  233 + return err
  234 + }
  235 + return nil
  236 +}
  237 +
  238 +// 评论数量变动
  239 +func (repository *ArticleRepository) IncreaseCountComment(ctx context.Context, conn transaction.Conn, incr int, article *domain.Article) error {
  240 + var (
  241 + err error
  242 + m *models.Article
  243 + tx = conn.DB()
  244 + )
  245 + m = &models.Article{Id: article.Id}
  246 + queryFunc := func() (interface{}, error) {
  247 + tx = tx.Model(m).Update("count_comment", gorm.Expr("count_comment+?", incr))
  248 + return nil, tx.Error
  249 + }
  250 + if _, err = repository.Query(queryFunc, m.CacheKeyFunc()); err != nil {
  251 + return err
  252 + }
  253 + return nil
  254 +}
  255 +
201 func NewArticleRepository(cache *cache.CachedRepository) domain.ArticleRepository { 256 func NewArticleRepository(cache *cache.CachedRepository) domain.ArticleRepository {
202 return &ArticleRepository{CachedRepository: cache} 257 return &ArticleRepository{CachedRepository: cache}
203 } 258 }
@@ -120,6 +120,10 @@ func (repository *ArticleSectionRepository) Find(ctx context.Context, conn trans @@ -120,6 +120,10 @@ func (repository *ArticleSectionRepository) Find(ctx context.Context, conn trans
120 ) 120 )
121 queryFunc := func() (interface{}, error) { 121 queryFunc := func() (interface{}, error) {
122 tx = tx.Model(&ms).Order("id desc") 122 tx = tx.Model(&ms).Order("id desc")
  123 +
  124 + if v, ok := queryOptions["articleId"]; ok {
  125 + tx = tx.Where("article_id = ?", v)
  126 + }
123 if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil { 127 if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
124 return dms, tx.Error 128 return dms, tx.Error
125 } 129 }
@@ -120,6 +120,15 @@ func (repository *UserLoveFlagRepository) Find(ctx context.Context, conn transac @@ -120,6 +120,15 @@ func (repository *UserLoveFlagRepository) Find(ctx context.Context, conn transac
120 ) 120 )
121 queryFunc := func() (interface{}, error) { 121 queryFunc := func() (interface{}, error) {
122 tx = tx.Model(&ms).Order("id desc") 122 tx = tx.Model(&ms).Order("id desc")
  123 + if v, ok := queryOptions["articleId"]; ok {
  124 + tx = tx.Where("article_id=?", v)
  125 + }
  126 + if v, ok := queryOptions["commentId"]; ok {
  127 + tx = tx.Where("comment_id=?", v)
  128 + }
  129 + if v, ok := queryOptions["userId"]; ok {
  130 + tx = tx.Where("user_id=?", v)
  131 + }
123 if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil { 132 if total, tx = transaction.PaginationAndCount(ctx, tx, queryOptions, &ms); tx.Error != nil {
124 return dms, tx.Error 133 return dms, tx.Error
125 } 134 }
@@ -37,6 +37,9 @@ type ArticleRepository interface { @@ -37,6 +37,9 @@ type ArticleRepository interface {
37 UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *Article) (*Article, error) 37 UpdateWithVersion(ctx context.Context, conn transaction.Conn, dm *Article) (*Article, error)
38 FindOne(ctx context.Context, conn transaction.Conn, id int64) (*Article, error) 38 FindOne(ctx context.Context, conn transaction.Conn, id int64) (*Article, error)
39 Find(ctx context.Context, conn transaction.Conn, companyId int64, queryOptions map[string]interface{}) (int64, []*Article, error) 39 Find(ctx context.Context, conn transaction.Conn, companyId int64, queryOptions map[string]interface{}) (int64, []*Article, error)
  40 + IncreaseCountLove(ctx context.Context, conn transaction.Conn, incr int, dm *Article) error //点赞数量变动
  41 + IncreaseCountComment(ctx context.Context, conn transaction.Conn, incr int, dm *Article) error //评论数量变动
  42 + IncreaseCountRead(ctx context.Context, conn transaction.Conn, incr int, dm *Article) error //浏览数量变动
40 } 43 }
41 44
42 type ArticleTarget int 45 type ArticleTarget int
@@ -46,4 +46,5 @@ type ArticleCommentRepository interface { @@ -46,4 +46,5 @@ type ArticleCommentRepository interface {
46 Delete(ctx context.Context, conn transaction.Conn, dm *ArticleComment) (*ArticleComment, error) 46 Delete(ctx context.Context, conn transaction.Conn, dm *ArticleComment) (*ArticleComment, error)
47 FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ArticleComment, error) 47 FindOne(ctx context.Context, conn transaction.Conn, id int64) (*ArticleComment, error)
48 Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ArticleComment, error) 48 Find(ctx context.Context, conn transaction.Conn, queryOptions map[string]interface{}) (int64, []*ArticleComment, error)
  49 + IncreaseCountUserLove(ctx context.Context, conn transaction.Conn, incr int, dm *ArticleComment) error //点赞数量变动
49 } 50 }
@@ -85,6 +85,23 @@ func (m *User) Audit(status int) error { @@ -85,6 +85,23 @@ func (m *User) Audit(status int) error {
85 return nil 85 return nil
86 } 86 }
87 87
  88 +func (m *User) Follow(targetUser *User) error {
  89 + if lo.Contains(m.Following, targetUser.Id) {
  90 + return fmt.Errorf("已关注用户%v", targetUser.Name)
  91 + }
  92 + m.Following = append(m.Following, targetUser.Id)
  93 + if !lo.Contains(targetUser.Follower, m.Id) {
  94 + targetUser.Follower = append(targetUser.Follower, m.Id)
  95 + }
  96 + return nil
  97 +}
  98 +
  99 +func (m *User) Unfollow(targetUser *User) error {
  100 + m.Following = lo.Without(m.Following, targetUser.Id)
  101 + targetUser.Follower = lo.Without(targetUser.Follower, m.Id)
  102 + return nil
  103 +}
  104 +
88 type ( 105 type (
89 LoginCreator interface { 106 LoginCreator interface {
90 WechatLogin(r WechatLoginRequest) (*LoginInfo, error) 107 WechatLogin(r WechatLoginRequest) (*LoginInfo, error)