fix version 1

This commit is contained in:
2026-09-22 21:15:34 +08:00
parent 9f86366638
commit d63d7e8b3a
277 changed files with 9959 additions and 1514 deletions

View File

@@ -21,9 +21,9 @@ func GetrelationInfoDetailCard(identity string) (card *pb.RelationItem, err erro
return
}
// 根据id数组获取多条会员信息卡片
func GetrelationInfoDetailCardById(ids []uint) (cards []*pb.RelationItem, err error) {
err = impl.DBService.Table("relation_extend").Select(Filed).Where("relation_id in ?", ids).Find(&cards).Error
// 根据identity数组获取多条会员信息卡片
func GetrelationInfoDetailCardById(identities []string) (cards []*pb.RelationItem, err error) {
err = impl.DBService.Table("relation_extend").Select(Filed).Where("relation_identity in ?", identities).Find(&cards).Error
return
}
@@ -39,7 +39,7 @@ func UniqueSessionID(s1, s2 string) string {
func CollectionFriendApply(id uint) (reply *pb.ApplyFetchReply, err error) {
var (
version int64
ids []uint
identities []string
last_msg_ids []uint
maxSize int = 50
applys = make([]*models.FriendApply, 0)
@@ -57,11 +57,12 @@ func CollectionFriendApply(id uint) (reply *pb.ApplyFetchReply, err error) {
}
for _, item := range applys {
ids = append(ids, item.FromID)
identities = append(identities, item.FromIdentity)
last_msg_ids = append(last_msg_ids, item.LastMessageID)
}
result, err := GetrelationInfoDetailCardById(ids)
// 按申请人身份取资料卡
result, err := GetrelationInfoDetailCardById(identities)
if err != nil {
return nil, err
}
@@ -107,41 +108,61 @@ func CollectionFriendApply(id uint) (reply *pb.ApplyFetchReply, err error) {
// 根据用户ID找到用户的好友信息和分组信息
func CollectionFriendData(id uint) (reply *pb.FriendsReply, err error) {
var (
version int64
ids []uint
version int64
identities []string
relationFriend = make([]models.RelationFriend, 0)
mapRelationFrend = make(map[uint]models.RelationFriend)
mapRelationFrend = make(map[string]models.RelationFriend)
friendInTag = make([]models.FriendInTag, 0)
mapFriendInTag = make(map[string][]string)
mapTagTotal = make(map[string]int64)
)
reply = &pb.FriendsReply{}
impl.DBService.Where("relation_id=?", id).Order("id desc").Find(&relationFriend)
// 好友条目归属列是 passport_id好友身份是 friend_relation_identity
err = impl.DBService.Where("passport_id=?", id).Order("id desc").Find(&relationFriend).Error
if err != nil {
return nil, err
}
for _, item := range relationFriend {
ids = append(ids, item.ID)
mapRelationFrend[item.ID] = item
identities = append(identities, item.FriendrelationIdentity)
mapRelationFrend[item.FriendrelationIdentity] = item
version = int64(item.ID)
}
impl.DBService.Where("relation_id=?", id).Find(&friendInTag)
err = impl.DBService.Where("passport_id=?", id).Find(&friendInTag).Error
if err != nil {
return nil, err
}
for _, item := range friendInTag {
mapFriendInTag[item.FriendIdentity] = append(mapFriendInTag[item.FriendIdentity], item.TagIdentity)
mapTagTotal[item.TagIdentity]++
}
err = impl.DBService.Model(models.FriendTag{}).Where("relation_id=?", id).Order("id asc").Scan(&reply.Tags).Error
// 标签列表按归属过滤并补齐标签名
err = impl.DBService.Model(models.FriendTag{}).Select("id, identity, name as tag_name").Where("passport_id=?", id).Order("id asc").Scan(&reply.Tags).Error
if err != nil {
return
}
// 补齐每个标签的成员数
for idx := range reply.Tags {
reply.Tags[idx].FriendTotal = mapTagTotal[reply.Tags[idx].Identity]
}
reply.Friends, err = GetrelationInfoDetailCardById(ids)
for idx, item := range reply.Friends {
reply.Friends[idx].RemarkName = item.RemarkName
reply.Friends[idx].Popular = item.Popular
if _, ok := mapFriendInTag[item.Identity]; ok {
reply.Friends[idx].Tags = mapFriendInTag[item.Identity]
// 按好友身份装配资料卡,并回填备注与置顶
reply.Friends, err = GetrelationInfoDetailCardById(identities)
if err != nil {
return
}
for idx := range reply.Friends {
if item, ok := mapRelationFrend[reply.Friends[idx].Identity]; ok {
reply.Friends[idx].RemarkName = item.RemarkName
reply.Friends[idx].Popular = int32(item.Popular)
}
if tags, ok := mapFriendInTag[reply.Friends[idx].Identity]; ok {
reply.Friends[idx].Tags = tags
}
}
@@ -154,7 +175,7 @@ func CollectionFriendData(id uint) (reply *pb.FriendsReply, err error) {
func GetrelationInfoDetailCardByMatch(relation_identity string, offset, limit int) (cards []*pb.RelationItem, err error) {
sql := `Select
pe.relation_identity as identity,
pe.name,
pe.nickname,
pe.avatar,
pe.birthday,
pe.sex,
@@ -163,13 +184,13 @@ func GetrelationInfoDetailCardByMatch(relation_identity string, offset, limit in
pe.area,
pe.sign,
rm.status as foreign_status
From relation_match as rm,relation_extend as pe
Left join pe on pe.relation_identity=rm.recommend_identity
From relation_match as rm
Join relation_extend as pe on pe.relation_identity=rm.recommend_identity
Where rm.relation_identity=?
Offset ?
Order by rm.id Desc
Limit ?
Order by rm.id Desc`
err = impl.DBService.Raw(sql, relation_identity, offset, limit).Scan(&cards).Error
Offset ?`
err = impl.DBService.Raw(sql, relation_identity, limit, offset).Scan(&cards).Error
return
}

View File

@@ -1,33 +0,0 @@
package follow
import (
"context"
pb "bsm/full/module/social/relation/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/vars"
"time"
)
// 执行关注
func Do(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
// valildate request id,identity.
if in.Id == 0 && in.Identity == "" {
return nil, errcode.ErrInvalidArgument
}
// TODO: add your logic code & delete this line.
return &pb.DataStatusReply{
Data: vars.OK,
Timeseq: time.Now().UnixMilli(),
}, nil
}

View File

@@ -22,7 +22,7 @@ func Fetch(ctx context.Context, in *pb.FetchRequest) (reply *pb.FetchRelationIte
var (
total int64
column string
ids []uint
ids []string
model = impl.DBService.Model(&models.RelationFollow{})
cards []*pb.RelationItem
)

View File

@@ -15,7 +15,7 @@ import (
// 撤销关注
func Undo(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusReply, err error) {
_, err = service.ParseMetaCtx(ctx, nil)
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
@@ -23,7 +23,8 @@ func Undo(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusReply,
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Model(&models.RelationFollow{}).Delete("identity=?", in.Identity).Error
// 只能撤销自己发起的关注:归属列是 from_identity
err = impl.DBService.Model(&models.RelationFollow{}).Delete("identity=? and from_identity=?", in.Identity, auth.Identity).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -23,6 +23,14 @@ func ApplyDoMessage(ctx context.Context, in *pb.ApplyMessageRequest) (reply *pb.
return nil, errcode.ErrInvalidArgument
}
// 校验该申请存在且属于当前调用者(申请方或被申请方),避免污染他人申请会话
var apply models.FriendApply
err = impl.DBService.Where("id=? and (from_identity=? or to_identity=?)", in.ApplyId, auth.Identity, auth.Identity).First(&apply).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrPermissionDenied
}
msg := models.FriendApplyMessage{
ApplyID: uint(in.ApplyId),
Body: in.Body,
@@ -36,8 +44,8 @@ func ApplyDoMessage(ctx context.Context, in *pb.ApplyMessageRequest) (reply *pb.
return nil, errcode.ErrDB
}
//回写最后一次交流的消息ID
err = impl.DBService.Model(models.FriendApply{}).Where("id=?", msg.ApplyID).UpdateColumn("last_message_id", msg.ID).Error
//回写最后一次交流的消息ID(仍限定申请归属)
err = impl.DBService.Model(models.FriendApply{}).Where("id=? and (from_identity=? or to_identity=?)", msg.ApplyID, auth.Identity, auth.Identity).UpdateColumn("last_message_id", msg.ID).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -25,12 +25,24 @@ func ApplyDoPass(ctx context.Context, in *pb.ApplyDoPassRequest) (reply *pb.Data
return nil, errcode.ErrInvalidArgument
}
// 通过前先按 identity 查出属于当前调用者(被申请方)的申请记录
var apply models.FriendApply
err = impl.DBService.Where("identity=? and to_identity=?", in.ApplyIdentity, auth.Identity).First(&apply).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrPermissionDenied
}
// 申请记录里的申请人必须与请求要加为好友的对象一致,否则视为无申请依据
if apply.FromIdentity != in.FriendRelationIdentity {
return nil, errcode.ErrPermissionDenied
}
//写入好友表
friend := &models.RelationFriend{FriendrelationID: uint(in.FriendRelationId), FriendrelationIdentity: in.FriendRelationIdentity}
friend := &models.RelationFriend{FriendrelationID: apply.FromID, FriendrelationIdentity: apply.FromIdentity}
friend.Identity = utils.UUID()
friend.PassportID = auth.ID
friend.PassportIdentity = auth.Identity
friend.SessionID = common.UniqueSessionID(auth.Identity, in.FriendRelationIdentity)
friend.SessionID = common.UniqueSessionID(auth.Identity, apply.FromIdentity)
err = impl.DBService.Create(&friend).Error
if err != nil {
@@ -40,7 +52,7 @@ func ApplyDoPass(ctx context.Context, in *pb.ApplyDoPassRequest) (reply *pb.Data
//EventMQ向mesh MQ中心发送报文请求推送消息以及更新Cache.
err = impl.DBService.Model(models.FriendApply{}).Where("to_identity=? and identity=?", auth.Identity, in.ApplyIdentity).UpdateColumn("status", 1).Error
err = impl.DBService.Model(models.FriendApply{}).Where("to_identity=? and identity=?", auth.Identity, apply.Identity).UpdateColumn("status", 1).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -45,8 +45,12 @@ func ApplyFetch(ctx context.Context, in *pb.VersionRequest) (reply *pb.ApplyFetc
}
if cacheErr != nil {
printer.Error(err.Error())
printer.Error(cacheErr.Error())
return nil, errcode.ErrRedis
}
if reply == nil {
// 版本一致未走查询分支时兜底返回非 nil 空集合,避免序列化失败
reply = &pb.ApplyFetchReply{}
}
return reply, nil
}

View File

@@ -10,11 +10,12 @@ import (
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"gorm.io/gorm"
)
// 好友申请详情
func ApplyGet(ctx context.Context, in *pb.IdentRequest) (reply *pb.FriendApplyGetReply, err error) {
_, err = service.ParseMetaCtx(ctx, nil)
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
@@ -22,10 +23,14 @@ func ApplyGet(ctx context.Context, in *pb.IdentRequest) (reply *pb.FriendApplyGe
return nil, errcode.ErrInvalidArgument
}
// 只允许查看与自己相关的申请(申请方或被申请方)
var apply models.FriendApply
err = impl.DBService.Where("identity=?", in.Identity).First(&apply).Error
err = impl.DBService.Where("identity=? and (from_identity=? or to_identity=?)", in.Identity, auth.Identity, auth.Identity).First(&apply).Error
if err != nil {
printer.Error(err.Error())
if err == gorm.ErrRecordNotFound {
return nil, errcode.ErrPermissionDenied
}
return nil, errcode.ErrDB
}

View File

@@ -24,7 +24,8 @@ func Delete(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusReply
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Model(models.RelationFriend{}).Delete("relation_id=? and identity=?", auth.ID, in.Identity).Error
// 归属列是 passport_idin.Identity 是好友身份friend_relation_identity
err = impl.DBService.Model(models.RelationFriend{}).Delete("passport_id=? and friend_relation_identity=?", auth.ID, in.Identity).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -24,7 +24,8 @@ func DoPopular(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusRe
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Model(models.RelationFriend{}).Where("relation_id=? and identity=?", auth.ID, in.Identity).UpdateColumn("popular", 1).Error
// 归属列是 passport_idin.Identity 是好友身份friend_relation_identity
err = impl.DBService.Model(models.RelationFriend{}).Where("passport_id=? and friend_relation_identity=?", auth.ID, in.Identity).UpdateColumn("popular", 1).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -45,8 +45,12 @@ func Fetch(ctx context.Context, in *pb.VersionRequest) (reply *pb.FriendsReply,
}
if cacheErr != nil {
printer.Error(err.Error())
printer.Error(cacheErr.Error())
return nil, errcode.ErrRedis
}
if reply == nil {
// 版本一致未走查询分支时兜底返回非 nil 空集合,避免序列化失败
reply = &pb.FriendsReply{}
}
return reply, nil
}

View File

@@ -23,7 +23,8 @@ func ModifyNickname(ctx context.Context, in *pb.ModifyNicknameRequest) (reply *p
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Model(models.RelationFriend{}).Where("relation_id=? and identity=?", auth.ID, in.Identity).UpdateColumn("nickname", in.Nickname).Error
// 归属列是 passport_idin.Identity 是好友身份friend_relation_identity备注列是 remark_name
err = impl.DBService.Model(models.RelationFriend{}).Where("passport_id=? and friend_relation_identity=?", auth.ID, in.Identity).UpdateColumn("remark_name", in.Nickname).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -27,6 +27,24 @@ func TagDoUpdate(ctx context.Context, in *pb.TagDoUpdateRequest) (reply *pb.Data
switch strings.ToUpper(in.Direction) {
case "ADD":
// 校验标签归属当前调用者
var tag models.FriendTag
err = impl.DBService.Where("identity=? and passport_id=?", in.TagIdentity, auth.ID).First(&tag).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrPermissionDenied
}
// 校验目标确实是当前调用者的好友
var friendCount int64
err = impl.DBService.Model(models.RelationFriend{}).Where("passport_id=? and friend_relation_identity=?", auth.ID, in.FriendIdentity).Count(&friendCount).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
if friendCount == 0 {
return nil, errcode.ErrPermissionDenied
}
data := models.FriendInTag{
FriendIdentity: in.FriendIdentity,
TagIdentity: in.TagIdentity,
@@ -36,7 +54,8 @@ func TagDoUpdate(ctx context.Context, in *pb.TagDoUpdateRequest) (reply *pb.Data
err = impl.DBService.Create(&data).Error
case "DEL":
err = impl.DBService.Model(models.FriendInTag{}).Delete("friend_identity=? and tag_identity=?", in.FriendIdentity, in.TagIdentity).Error
// 归属列是 passport_id只能移除自己标签内的成员
err = impl.DBService.Model(models.FriendInTag{}).Delete("friend_identity=? and tag_identity=? and passport_id=?", in.FriendIdentity, in.TagIdentity, auth.ID).Error
default:
return nil, errcode.ErrInvalidArgument
}

View File

@@ -19,7 +19,15 @@ func TagFetch(ctx context.Context, in *pb.Empty) (reply *pb.FriendTagsReply, err
return nil, err
}
err = impl.DBService.Model(models.FriendTag{}).Where("relation_id=?", auth.ID).Count(&reply.Total).Order("id asc").Scan(&reply.Data).Error
// 先初始化返回值,避免对 nil 指针取字段地址
reply = &pb.FriendTagsReply{}
// 标签归属列是 passport_id
err = impl.DBService.Model(models.FriendTag{}).Where("passport_id=?", auth.ID).Count(&reply.Total).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB
}
err = impl.DBService.Model(models.FriendTag{}).Select("id, identity, name as tag_name").Where("passport_id=?", auth.ID).Order("id asc").Scan(&reply.Data).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -23,8 +23,9 @@ func TagMemberFetch(ctx context.Context, in *pb.IdentRequest) (reply *pb.PartFri
return nil, errcode.ErrInvalidArgument
}
var ids []uint
err = impl.DBService.Model(models.RelationFriend{}).Where("relation_id=? and group_identity=?", auth.ID, in.Identity).Pluck("relation_id", ids).Error
// 标签成员在 relation_friend_in_tag归属列是 passport_id标签列是 tag_identity
var ids []string
err = impl.DBService.Model(models.FriendInTag{}).Where("passport_id=? and tag_identity=?", auth.ID, in.Identity).Pluck("friend_identity", &ids).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -24,7 +24,8 @@ func UndoPopular(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatus
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Model(models.RelationFriend{}).Where("relation_id=? and identity=?", auth.ID, in.Identity).UpdateColumn("popular", 0).Error
// 归属列是 passport_idin.Identity 是好友身份friend_relation_identity
err = impl.DBService.Model(models.RelationFriend{}).Where("passport_id=? and friend_relation_identity=?", auth.ID, in.Identity).UpdateColumn("popular", 0).Error
if err != nil {
printer.Error(err.Error())
return nil, errcode.ErrDB

View File

@@ -13,10 +13,10 @@ import (
"git.apinb.com/bsm-sdk/core/vars"
)
// 执行忽略
// 执行忽略:标记匹配记录状态为已忽略
func DoIgnore(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusReply, err error) {
// parse authorization meta.
_, err = service.ParseMetaCtx(ctx, nil)
auth, err := service.ParseMetaCtx(ctx, nil)
if err != nil {
return nil, err
}
@@ -24,11 +24,15 @@ func DoIgnore(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusRep
return nil, errcode.ErrInvalidArgument
}
err = impl.DBService.Model(new(models.RelationFollow)).Delete("identity=?", in.Identity).Error
if err != nil {
printer.Error(err.Error())
// 操作匹配记录表并限定归属status=-1 表示已忽略
result := impl.DBService.Model(new(models.RelationMatch)).Where("relation_identity=? and recommend_identity=?", auth.Identity, in.Identity).UpdateColumn("status", -1)
if result.Error != nil {
printer.Error(result.Error.Error())
return nil, errcode.ErrDB
}
if result.RowsAffected == 0 {
return nil, errcode.ErrPermissionDenied
}
return &pb.DataStatusReply{
Data: vars.OK,
Timeseq: time.Now().UnixMilli(),

View File

@@ -10,11 +10,10 @@ import (
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/printer"
"git.apinb.com/bsm-sdk/core/service"
"git.apinb.com/bsm-sdk/core/utils"
"git.apinb.com/bsm-sdk/core/vars"
)
// 执行通过,加为好友
// 执行通过:标记匹配记录状态为已通过
func DoJoin(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusReply, err error) {
// parse authorization meta.
auth, err := service.ParseMetaCtx(ctx, nil)
@@ -26,17 +25,15 @@ func DoJoin(ctx context.Context, in *pb.IdentRequest) (reply *pb.DataStatusReply
return nil, errcode.ErrInvalidArgument
}
data := &models.RelationFollow{
FromIdentity: auth.Identity,
ToIdentity: in.Identity,
}
data.Identity = utils.UUID()
err = impl.DBService.Create(data).Error
if err != nil {
printer.Error(err.Error())
// 操作匹配记录表并限定归属status=1 表示已通过
result := impl.DBService.Model(&models.RelationMatch{}).Where("relation_identity=? and recommend_identity=?", auth.Identity, in.Identity).UpdateColumn("status", 1)
if result.Error != nil {
printer.Error(result.Error.Error())
return nil, errcode.ErrDB
}
if result.RowsAffected == 0 {
return nil, errcode.ErrPermissionDenied
}
return &pb.DataStatusReply{
Data: vars.OK,
Timeseq: time.Now().UnixMilli(),

View File

@@ -5,6 +5,7 @@ import (
pb "bsm/full/module/social/relation/pb"
"context"
"git.apinb.com/bsm-sdk/core/printer"
gwRuntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
@@ -17,10 +18,17 @@ type Server struct {
grpcConns map[string]*grpc.ClientConn // 连接池
}
func New(addr string) *Server {
// New 创建服务实例
// grpcServ 为空表示独立进程启动,自行创建 gRPC Server 并初始化网关路由
func New(grpcServ *grpc.Server) *Server {
standalone := grpcServ == nil
if standalone {
grpcServ = grpc.NewServer()
}
srv := &Server{
Ctx: context.Background(),
Grpc: grpc.NewServer(),
Grpc: grpcServ,
grpcConns: make(map[string]*grpc.ClientConn),
}
@@ -29,7 +37,25 @@ func New(addr string) *Server {
pb.RegisterFriendServer(srv.Grpc, NewFriendServer())
pb.RegisterMatchServer(srv.Grpc, NewMatchServer())
reflection.Register(srv.Grpc)
if standalone {
// 独立进程需自行初始化网关路由并注册 handler否则 /relation.* 全部 404
srv.Mux = gwRuntime.NewServeMux()
if err := RegisterGateway(srv.Ctx, srv.Mux); err != nil {
printer.Error(err.Error())
}
reflection.Register(srv.Grpc)
}
return srv
}
// RegisterGateway 注册各 service 的 gateway handler
func RegisterGateway(ctx context.Context, mux *gwRuntime.ServeMux) error {
if err := pb.RegisterFollowHandlerServer(ctx, mux, NewFollowServer()); err != nil {
return err
}
if err := pb.RegisterFriendHandlerServer(ctx, mux, NewFriendServer()); err != nil {
return err
}
return pb.RegisterMatchHandlerServer(ctx, mux, NewMatchServer())
}