feat(Talk): 群头像支持自定义上传与成员九宫格默认
This commit is contained in:
1 parent
5707ab0371
commit
8abbe1eefc
5 files changed
+86
-1
No files matched your search
@@ -209,7 +209,7 @@ def BroadcastConversation(ConversationUUID, Action, Extra=None):
|
||||
"""广播「会话级变更」事件(事件名 talk:conversation)
|
||||
|
||||
用于群主/管理员操作后让所有在线成员的会话列表立即同步:
|
||||
改名(renamed)、群公告(announcement)、转让群主(owner_transferred)、
|
||||
改名(renamed)、群公告(announcement)、群头像(avatar)、转让群主(owner_transferred)、
|
||||
成员角色变更(role_changed)、移出成员(members_removed)、解散(dissolved)。
|
||||
事件名不带命名空间前缀,前端订阅的是 'talk:conversation'。
|
||||
"""
|
||||
@@ -791,6 +791,46 @@ class TalkManager:
|
||||
'AnnouncementTime': conv.AnnouncementTime.isoformat() if conv.AnnouncementTime else None,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def SetConversationAvatar(ConversationUUID, OperatorUUID, AvatarSHA1, IsTalkAdmin=False):
|
||||
"""设置群头像(群主/群管理员/Talk 管理员;传空串即恢复默认九宫格)
|
||||
|
||||
AvatarSHA1 为空串表示恢复默认(成员九宫格);非空必须是 40 位十六进制
|
||||
(由 /API/Talk/Upload 上传图片得到,指向 FileAsset)。
|
||||
"""
|
||||
conv = TalkManager.GetConversation(ConversationUUID)
|
||||
operator = _ToBytes(OperatorUUID)
|
||||
if conv is None or conv.Status != STATUS_NORMAL:
|
||||
return False, '会话不存在或已解散', None
|
||||
if conv.ConversationType != TYPE_GROUP:
|
||||
return False, '仅群聊可设置群头像', None
|
||||
member = TalkManager.GetMember(conv.ConversationUUID, operator)
|
||||
if member is None:
|
||||
return False, '您不是该会话成员', None
|
||||
if not TalkManager._IsGroupManager(conv, member, operator) and not IsTalkAdmin:
|
||||
return False, '仅群主或管理员可修改群头像', None
|
||||
sha1 = (AvatarSHA1 or '').strip().lower()
|
||||
if sha1 and (len(sha1) != 40 or any(c not in '0123456789abcdef' for c in sha1)):
|
||||
return False, '无效的头像资源标识', None
|
||||
if sha1 == (conv.AvatarSHA1 or ''):
|
||||
return True, '', {
|
||||
'ConversationUUID': _ToStr(conv.ConversationUUID),
|
||||
'AvatarSHA1': conv.AvatarSHA1 or '',
|
||||
}
|
||||
conv.AvatarSHA1 = sha1
|
||||
conv.save(update_fields=['AvatarSHA1'])
|
||||
operator_name = TalkManager._DisplayName(operator)
|
||||
TalkManager.AppendSystemMessage(
|
||||
conv,
|
||||
f'{operator_name} 更换了群头像' if sha1 else f'{operator_name} 恢复了默认群头像',
|
||||
operator,
|
||||
)
|
||||
BroadcastConversation(conv.ConversationUUID, 'avatar', {'AvatarSHA1': sha1})
|
||||
return True, '', {
|
||||
'ConversationUUID': _ToStr(conv.ConversationUUID),
|
||||
'AvatarSHA1': sha1,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def DissolveConversation(ConversationUUID, OperatorUUID, IsTalkAdmin=False):
|
||||
"""解散会话(仅群主或 Talk 管理员)"""
|
||||
@@ -1163,6 +1203,8 @@ class TalkManager:
|
||||
'LastMessagePreview': Conversation.LastMessagePreview or '',
|
||||
'Announcement': Conversation.Announcement or '',
|
||||
'AnnouncementTime': Conversation.AnnouncementTime.isoformat() if Conversation.AnnouncementTime else None,
|
||||
# 群头像 SHA1(空串=使用成员九宫格默认头像;前端据此拼资源 URL)
|
||||
'AvatarSHA1': Conversation.AvatarSHA1 or '',
|
||||
'UnreadCount': unread_qs.count(),
|
||||
'Members': members,
|
||||
# 群主标记:前端据此对「非管理员群主」显示解散入口(管理员另有 Entry.IsAdmin)
|
||||
|
||||
@@ -33,6 +33,8 @@ class TalkConversation(QModel):
|
||||
# 群公告(仅群聊使用;群主/群管理员可编辑,成员在会话顶部可见)
|
||||
Announcement = models.TextField(default='', db_column='Announcement', verbose_name='群公告')
|
||||
AnnouncementTime = models.DateTimeField(null=True, blank=True, db_column='AnnouncementTime', verbose_name='群公告更新时间')
|
||||
# 群头像(仅群聊使用;存 FileAsset 的 SHA1,空串表示使用成员九宫格默认头像)
|
||||
AvatarSHA1 = models.CharField(max_length=40, default='', db_column='AvatarSHA1', verbose_name='群头像SHA1')
|
||||
# 会话状态:1=正常 0=已解散
|
||||
Status = models.SmallIntegerField(default=1, db_column='Status', verbose_name='状态(1正常/0解散)')
|
||||
CreateTime = models.DateTimeField(default=datetime.datetime.utcnow, db_column='CreateTime', verbose_name='创建时间')
|
||||
|
||||
@@ -13,6 +13,7 @@ urlpatterns = [
|
||||
path('Conversation/Member/Remove', views.ConversationMemberRemoveView.as_view()),
|
||||
path('Conversation/Transfer', views.ConversationTransferView.as_view()),
|
||||
path('Conversation/Announcement', views.ConversationAnnouncementView.as_view()),
|
||||
path('Conversation/Avatar', views.ConversationAvatarView.as_view()),
|
||||
path('Conversation/Dissolve', views.ConversationDissolveView.as_view()),
|
||||
path('Messages', views.MessageListView.as_view()),
|
||||
path('Send', views.SendView.as_view()),
|
||||
|
||||
@@ -316,6 +316,27 @@ class ConversationAnnouncementView(TalkAPIView):
|
||||
return Response({'code': 0, 'data': data})
|
||||
|
||||
|
||||
class ConversationAvatarView(TalkAPIView):
|
||||
"""POST API/Talk/Conversation/Avatar —— 设置群头像(空串即恢复默认九宫格)
|
||||
|
||||
请求体:{ConversationUUID, AvatarSHA1}
|
||||
AvatarSHA1 由 /API/Talk/Upload 上传图片得到(指向 FileAsset)。
|
||||
"""
|
||||
|
||||
def post(self, request):
|
||||
user = _UserBytes(request)
|
||||
conv_uuid = request.data.get('ConversationUUID')
|
||||
avatar_sha1 = request.data.get('AvatarSHA1', '')
|
||||
if not conv_uuid:
|
||||
return Response({'code': 1, 'msg': '缺少 ConversationUUID'}, status=400)
|
||||
is_admin = IsAdmin(request=request) or IsCompanyAdmin(request=request)
|
||||
ok, msg, data = TalkManager.SetConversationAvatar(
|
||||
conv_uuid, user, avatar_sha1, IsTalkAdmin=is_admin)
|
||||
if not ok:
|
||||
return Response({'code': 1, 'msg': msg}, status=400)
|
||||
return Response({'code': 0, 'data': data})
|
||||
|
||||
|
||||
class ConversationDissolveView(TalkAPIView):
|
||||
"""POST API/Talk/Conversation/Dissolve —— 解散会话(仅群主或 Talk 管理员)"""
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
"""Talk 群头像(TalkConversation.AvatarSHA1)
|
||||
"""
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gerp', '0056_talk_conversation_announcement'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='talkconversation',
|
||||
name='AvatarSHA1',
|
||||
field=models.CharField(
|
||||
default='', max_length=40, db_column='AvatarSHA1', verbose_name='群头像SHA1'),
|
||||
),
|
||||
]
|
||||
Reference in new issue
Block a user