作者 yangfu

用户关注

... ... @@ -41,10 +41,10 @@ service Core {
post /mini/user/department-users (MiniUserDepartmentUsersRequest)returns (MiniUserInfoResponse)
@doc "关注我的人"
@handler miniUserFollower
post /mini/user/follower (UserSearchRequest)returns(UserSearchResponse)
post /mini/user/follower (MiniUserFollowedSearchRequest)returns(MiniUserFollowedSearchResponse)
@doc "我关注的人"
@handler miniUserFollowing
post /mini/user/following (UserSearchRequest)returns(UserSearchResponse)
post /mini/user/following (MiniUserFollowedSearchRequest)returns(MiniUserFollowedSearchResponse)
@doc "关注"
@handler miniUserFollow
post /mini/user/follow (FollowRequest)
... ... @@ -97,6 +97,14 @@ type(
Departments []*Department `json:"departments"`
Users []*UserItem `json:"users"`
}
MiniUserFollowedSearchRequest{
Page int `json:"page,optional"`
Size int `json:"size,optional"`
}
MiniUserFollowedSearchResponse{
List []*UserFollowItem `json:"users"`
Total int64 `json:"total"`
}
UserItem {
Id int64 `json:"id,omitempty"` // 用户ID
CompanyId int64 `json:"companyId,omitempty"` // 公司ID
... ... @@ -133,6 +141,15 @@ type(
FollowRequest{
UserId int64 `json:"userId"`
}
UserFollowItem struct {
Id int64 `json:"id"` // 用户ID
Name string `json:"name"` // 名称
CompanyName string `json:"companyName"` // 公司名称
Avatar string `json:"avatar"` // 头像
Position string `json:"position"` // 职位
Followed bool `json:"followed"` // 关注
MutualFollowed bool `json:"mutualFollowed"` // 互相关注标识
}
)
... ...
... ... @@ -12,7 +12,7 @@ import (
func MiniUserFollowerHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.UserSearchRequest
var req types.MiniUserFollowedSearchRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
... ...
... ... @@ -12,7 +12,7 @@ import (
func MiniUserFollowingHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.UserSearchRequest
var req types.MiniUserFollowedSearchRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
... ...
... ... @@ -2,6 +2,10 @@ package user
import (
"context"
"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"
... ... @@ -23,8 +27,32 @@ func NewMiniUserFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Mi
}
}
func (l *MiniUserFollowLogic) MiniUserFollow(req *types.FollowRequest) error {
// todo: add your logic here and delete this line
func (l *MiniUserFollowLogic) MiniUserFollow(req *types.FollowRequest) (err error) {
var (
conn = l.svcCtx.DefaultDBConn()
user *domain.User
targetUser *domain.User
userToken = contextdata.GetUserTokenFromCtx(l.ctx)
)
if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
return xerr.NewErrMsgErr("用户不存在", err)
}
if targetUser, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId); err != nil {
return xerr.NewErrMsgErr("关注的用户不存在", err)
}
if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error {
if err = user.Follow(targetUser); err != nil {
return err
}
if user, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, user); err != nil {
return err
}
if targetUser, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, targetUser); err != nil {
return err
}
return nil
}, true); err != nil {
return xerr.NewErrMsgErr("关注用户失败", err)
}
return nil
}
... ...
... ... @@ -2,6 +2,10 @@ package user
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/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"
... ... @@ -23,8 +27,42 @@ func NewMiniUserFollowerLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
}
}
func (l *MiniUserFollowerLogic) MiniUserFollower(req *types.UserSearchRequest) (resp *types.UserSearchResponse, err error) {
// todo: add your logic here and delete this line
func (l *MiniUserFollowerLogic) MiniUserFollower(req *types.MiniUserFollowedSearchRequest) (resp *types.MiniUserFollowedSearchResponse, err error) {
var (
conn = l.svcCtx.DefaultDBConn()
user *domain.User
userToken = contextdata.GetUserTokenFromCtx(l.ctx)
companyMap = make(map[int64]*domain.Company)
)
if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
return nil, xerr.NewErrMsgErr("用户不存在", err)
}
var (
users = user.Follower
total = int64(len(users))
offset, limit = domain.OffsetLimit(req.Page, req.Size)
)
users = lo.Slice(users, offset, offset+limit)
resp = &types.MiniUserFollowedSearchResponse{
Total: total,
List: make([]*types.UserFollowItem, 0),
}
lo.ForEach(users, func(item int64, index int) {
if foundUser, _ := l.svcCtx.UserRepository.FindOne(l.ctx, conn, item); foundUser != nil {
var companyName = ""
if company, _ := domain.LazyLoad(companyMap, l.ctx, conn, foundUser.CompanyId, l.svcCtx.CompanyRepository.FindOne); company != nil {
companyName = company.Name
}
resp.List = append(resp.List, &types.UserFollowItem{
Id: foundUser.Id,
Name: foundUser.Name,
CompanyName: companyName,
Avatar: foundUser.Avatar,
Position: foundUser.Position,
Followed: true,
MutualFollowed: lo.Contains(user.Following, item),
})
}
})
return
}
... ...
... ... @@ -2,6 +2,10 @@ package user
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/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"
... ... @@ -23,8 +27,42 @@ func NewMiniUserFollowingLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
}
func (l *MiniUserFollowingLogic) MiniUserFollowing(req *types.UserSearchRequest) (resp *types.UserSearchResponse, err error) {
// todo: add your logic here and delete this line
func (l *MiniUserFollowingLogic) MiniUserFollowing(req *types.MiniUserFollowedSearchRequest) (resp *types.MiniUserFollowedSearchResponse, err error) {
var (
conn = l.svcCtx.DefaultDBConn()
user *domain.User
userToken = contextdata.GetUserTokenFromCtx(l.ctx)
companyMap = make(map[int64]*domain.Company)
)
if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
return nil, xerr.NewErrMsgErr("用户不存在", err)
}
var (
users = user.Following
total = int64(len(users))
offset, limit = domain.OffsetLimit(req.Page, req.Size)
)
users = lo.Slice(users, offset, offset+limit)
resp = &types.MiniUserFollowedSearchResponse{
Total: total,
List: make([]*types.UserFollowItem, 0),
}
lo.ForEach(users, func(item int64, index int) {
if foundUser, _ := l.svcCtx.UserRepository.FindOne(l.ctx, conn, item); foundUser != nil {
var companyName = ""
if company, _ := domain.LazyLoad(companyMap, l.ctx, conn, foundUser.CompanyId, l.svcCtx.CompanyRepository.FindOne); company != nil {
companyName = company.Name
}
resp.List = append(resp.List, &types.UserFollowItem{
Id: foundUser.Id,
Name: foundUser.Name,
CompanyName: companyName,
Avatar: foundUser.Avatar,
Position: foundUser.Position,
Followed: true,
//MutualFollowed: lo.Contains(user.Following, foundUser.Id),
})
}
})
return
}
... ...
... ... @@ -2,6 +2,10 @@ package user
import (
"context"
"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"
... ... @@ -23,8 +27,32 @@ func NewMiniUserUnFollowLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
}
}
func (l *MiniUserUnFollowLogic) MiniUserUnFollow(req *types.FollowRequest) error {
// todo: add your logic here and delete this line
func (l *MiniUserUnFollowLogic) MiniUserUnFollow(req *types.FollowRequest) (err error) {
var (
conn = l.svcCtx.DefaultDBConn()
user *domain.User
targetUser *domain.User
userToken = contextdata.GetUserTokenFromCtx(l.ctx)
)
if user, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, userToken.UserId); err != nil {
return xerr.NewErrMsgErr("用户不存在", err)
}
if targetUser, err = l.svcCtx.UserRepository.FindOne(l.ctx, conn, req.UserId); err != nil {
return xerr.NewErrMsgErr("关注的用户不存在", err)
}
if err = transaction.UseTrans(l.ctx, l.svcCtx.DB, func(ctx context.Context, conn transaction.Conn) error {
if err = user.Unfollow(targetUser); err != nil {
return err
}
if user, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, user); err != nil {
return err
}
if targetUser, err = l.svcCtx.UserRepository.UpdateWithVersion(ctx, conn, targetUser); err != nil {
return err
}
return nil
}, true); err != nil {
return xerr.NewErrMsgErr("关注用户失败", err)
}
return nil
}
... ...
... ... @@ -186,6 +186,16 @@ type MiniUserDepartmentUsersResponse struct {
Users []*UserItem `json:"users"`
}
type MiniUserFollowedSearchRequest struct {
Page int `json:"page,optional"`
Size int `json:"size,optional"`
}
type MiniUserFollowedSearchResponse struct {
List []*UserFollowItem `json:"users"`
Total int64 `json:"total"`
}
type UserItem struct {
Id int64 `json:"id,omitempty"` // 用户ID
CompanyId int64 `json:"companyId,omitempty"` // 公司ID
... ... @@ -225,6 +235,16 @@ type FollowRequest struct {
UserId int64 `json:"userId"`
}
type UserFollowItem struct {
Id int64 `json:"id"` // 用户ID
Name string `json:"name"` // 名称
CompanyName string `json:"companyName"` // 公司名称
Avatar string `json:"avatar"` // 头像
Position string `json:"position"` // 职位
Followed bool `json:"followed"` // 关注
MutualFollowed bool `json:"mutualFollowed"` // 互相关注标识
}
type CompanySearchRequest struct {
Page int `json:"page"`
Size int `json:"size"`
... ...
... ... @@ -9,7 +9,11 @@ import (
)
type Role struct {
Id int64 // 唯一标识
Id int64 // 唯一标识
Name string `json:"name"` // 角色名称
Auths []int64 `gorm:"type:jsonb;serializer:json"` // 角色权限列表
Remark string `json:"remark"` // 备注
Users []int64 `gorm:"type:jsonb;serializer:json"` // 绑定的用户
CreatedAt int64
UpdatedAt int64
... ...
... ... @@ -85,6 +85,23 @@ func (m *User) Audit(status int) error {
return nil
}
func (m *User) Follow(targetUser *User) error {
if lo.Contains(m.Following, targetUser.Id) {
return fmt.Errorf("已关注用户%v", targetUser.Name)
}
m.Following = append(m.Following, targetUser.Id)
if !lo.Contains(targetUser.Follower, m.Id) {
targetUser.Follower = append(targetUser.Follower, m.Id)
}
return nil
}
func (m *User) Unfollow(targetUser *User) error {
m.Following = lo.Without(m.Following, targetUser.Id)
targetUser.Follower = lo.Without(targetUser.Follower, m.Id)
return nil
}
type (
LoginCreator interface {
WechatLogin(r WechatLoginRequest) (*LoginInfo, error)
... ...