作者 yangfu

用户关注

@@ -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
@@ -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
@@ -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 }
@@ -186,6 +186,16 @@ type MiniUserDepartmentUsersResponse struct { @@ -186,6 +186,16 @@ type MiniUserDepartmentUsersResponse struct {
186 Users []*UserItem `json:"users"` 186 Users []*UserItem `json:"users"`
187 } 187 }
188 188
  189 +type MiniUserFollowedSearchRequest struct {
  190 + Page int `json:"page,optional"`
  191 + Size int `json:"size,optional"`
  192 +}
  193 +
  194 +type MiniUserFollowedSearchResponse struct {
  195 + List []*UserFollowItem `json:"users"`
  196 + Total int64 `json:"total"`
  197 +}
  198 +
189 type UserItem struct { 199 type UserItem struct {
190 Id int64 `json:"id,omitempty"` // 用户ID 200 Id int64 `json:"id,omitempty"` // 用户ID
191 CompanyId int64 `json:"companyId,omitempty"` // 公司ID 201 CompanyId int64 `json:"companyId,omitempty"` // 公司ID
@@ -225,6 +235,16 @@ type FollowRequest struct { @@ -225,6 +235,16 @@ type FollowRequest struct {
225 UserId int64 `json:"userId"` 235 UserId int64 `json:"userId"`
226 } 236 }
227 237
  238 +type UserFollowItem struct {
  239 + Id int64 `json:"id"` // 用户ID
  240 + Name string `json:"name"` // 名称
  241 + CompanyName string `json:"companyName"` // 公司名称
  242 + Avatar string `json:"avatar"` // 头像
  243 + Position string `json:"position"` // 职位
  244 + Followed bool `json:"followed"` // 关注
  245 + MutualFollowed bool `json:"mutualFollowed"` // 互相关注标识
  246 +}
  247 +
228 type CompanySearchRequest struct { 248 type CompanySearchRequest struct {
229 Page int `json:"page"` 249 Page int `json:"page"`
230 Size int `json:"size"` 250 Size int `json:"size"`
@@ -10,6 +10,10 @@ import ( @@ -10,6 +10,10 @@ import (
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
@@ -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)