feat(chat): 聊天单向删除
This commit is contained in:
@@ -97,7 +97,7 @@ class User(BaseModel, DateModel):
|
||||
foreign_keys='UserFollows.followed_id',
|
||||
cascade='all, delete-orphan'
|
||||
)
|
||||
chats: Mapped[List['Chat']] = relationship(secondary='chat_participant', back_populates='users')
|
||||
chats: Mapped[List['Chat']] = relationship(secondary='system_chat_participant', back_populates='users')
|
||||
messages: Mapped[List['Message']] = relationship(back_populates='user')
|
||||
read_statuses: Mapped[List['ReadStatus']] = relationship(back_populates='user')
|
||||
|
||||
@@ -261,7 +261,7 @@ class Chat(BaseModel, DateModel):
|
||||
|
||||
guid: Mapped[uuid.UUID] = mapped_column(String(36), nullable=True, default=lambda: str(uuid.uuid4()))
|
||||
|
||||
users: Mapped[List['User']] = relationship(secondary='chat_participant', back_populates='chats')
|
||||
users: Mapped[List['User']] = relationship(secondary='system_chat_participant', back_populates='chats')
|
||||
messages: Mapped[List['Message']] = relationship(back_populates='chat', cascade='all,delete')
|
||||
is_deleted: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
read_statuses: Mapped[List['ReadStatus']] = relationship(back_populates='chat', cascade='all,delete')
|
||||
@@ -320,17 +320,18 @@ class PointsTransaction(BaseModel, DateModel):
|
||||
user_id: Mapped[int] = mapped_column(Integer, comment='用户id')
|
||||
transaction_type: Mapped[int] = mapped_column(Integer, comment='交易类型:1-充值 2-消费 3-赠送 4-过期 5-系统调整')
|
||||
product_id: Mapped[int] = mapped_column(Integer, nullable=True, comment='关联产品id')
|
||||
points : Mapped[int] = mapped_column(Integer, comment='积分数量(正数表示增加,负数表示减少)')
|
||||
balance : Mapped[int] = mapped_column(Integer, comment='交易后余额')
|
||||
status : Mapped[int] = mapped_column(Integer, default=1, comment='状态:0-无效 1-有效 2-已撤销')
|
||||
points: Mapped[int] = mapped_column(Integer, comment='积分数量(正数表示增加,负数表示减少)')
|
||||
balance: Mapped[int] = mapped_column(Integer, comment='交易后余额')
|
||||
status: Mapped[int] = mapped_column(Integer, default=1, comment='状态:0-无效 1-有效 2-已撤销')
|
||||
description: Mapped[str] = mapped_column(String(255), nullable=True, comment='交易描述')
|
||||
|
||||
|
||||
|
||||
chat_participant = Table(
|
||||
'chat_participant',
|
||||
BaseModel.metadata,
|
||||
Column('user_id', Integer, ForeignKey('system_users.user_id'), primary_key=True),
|
||||
Column('chat_id', Integer, ForeignKey('system_chats.id'), primary_key=True),
|
||||
comment='聊天参与者关联表'
|
||||
)
|
||||
class ChatParticipant(BaseModel):
|
||||
__tablename__ = 'system_chat_participant'
|
||||
__table_args__ = (
|
||||
{'comment': '聊天参与者关联表'}
|
||||
)
|
||||
id: None = None
|
||||
user_id: Mapped[int] = mapped_column(Integer, ForeignKey('system_users.user_id'), primary_key=True)
|
||||
chat_id: Mapped[int] = mapped_column(Integer, ForeignKey('system_chats.id'), primary_key=True)
|
||||
is_deleted: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
|
||||
@@ -17,7 +17,7 @@ from sqlalchemy.orm import selectinload
|
||||
from core.base import schema as base_schema
|
||||
from core.db.crud import CRUD
|
||||
from core.db.engine import get_async_session
|
||||
from core.db.models import Message, Chat, User, ReadStatus, chat_participant
|
||||
from core.db.models import Message, Chat, User, ReadStatus, ChatParticipant
|
||||
from core.routers.auth.schema import LoginUser
|
||||
from core.routers.auth.services import get_current_user_form_http, get_current_user_form_ws
|
||||
from core.base.exceptions import WebsocketTooManyRequests
|
||||
@@ -46,11 +46,13 @@ async def get_all_chats(
|
||||
page_size: int = Query(default=15, gt=0, le=200),
|
||||
):
|
||||
filter_conditions = (
|
||||
exists().where(
|
||||
(chat_participant.c.chat_id == Chat.id) &
|
||||
(chat_participant.c.user_id == login_user.user_id)
|
||||
) &
|
||||
Chat.is_deleted.is_(False)
|
||||
exists().where(
|
||||
and_(
|
||||
ChatParticipant.chat_id == Chat.id,
|
||||
ChatParticipant.user_id == login_user.user_id,
|
||||
ChatParticipant.is_deleted == False
|
||||
)
|
||||
)
|
||||
)
|
||||
query = (
|
||||
select(Chat)
|
||||
@@ -163,12 +165,12 @@ async def create_new_chat(
|
||||
.where(
|
||||
and_(
|
||||
exists().where(
|
||||
(chat_participant.c.chat_id == Chat.id) &
|
||||
(chat_participant.c.user_id == login_user.user_id)
|
||||
(ChatParticipant.chat_id == Chat.id) &
|
||||
(ChatParticipant.user_id == login_user.user_id)
|
||||
),
|
||||
exists().where(
|
||||
(chat_participant.c.chat_id == Chat.id) &
|
||||
(chat_participant.c.user_id == recipient_user.user_id)
|
||||
(ChatParticipant.chat_id == Chat.id) &
|
||||
(ChatParticipant.user_id == recipient_user.user_id)
|
||||
),
|
||||
Chat.is_deleted == False
|
||||
)
|
||||
@@ -209,23 +211,34 @@ async def delete_single_chat(
|
||||
db_session: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
subquery = (
|
||||
select(chat_participant.c.chat_id)
|
||||
.where(chat_participant.c.user_id == login_user.user_id)
|
||||
select(ChatParticipant.chat_id)
|
||||
.where(ChatParticipant.user_id == login_user.user_id)
|
||||
).scalar_subquery()
|
||||
|
||||
query = (
|
||||
update(Chat)
|
||||
select(Chat)
|
||||
.where(and_(
|
||||
Chat.id.in_(subquery),
|
||||
Chat.guid == chat_guid
|
||||
))
|
||||
.values(is_deleted=True)
|
||||
)
|
||||
result = await db_session.execute(query)
|
||||
await db_session.commit()
|
||||
chat = result.scalar_one_or_none()
|
||||
|
||||
if result.rowcount == 0:
|
||||
if chat is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='聊天不存在')
|
||||
else:
|
||||
db_curd = CRUD(db_session, Chat)
|
||||
await db_curd.update(
|
||||
data={'is_deleted': True},
|
||||
filters={'id': chat.id},
|
||||
)
|
||||
|
||||
await db_curd.update(
|
||||
model=ChatParticipant,
|
||||
data={'is_deleted': True},
|
||||
filters={'user_id': login_user.user_id, 'chat_id': chat.id},
|
||||
)
|
||||
|
||||
return {'message': '聊天已删除'}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ class ChatUnreadOut(BaseModel):
|
||||
created_at: str
|
||||
updated_at: str
|
||||
recipient_user: LiteUser
|
||||
is_delete: bool = False
|
||||
last_message: PreviewMessage | None
|
||||
unread_messages_count: int
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import aliased, selectinload
|
||||
|
||||
from core.base.exceptions import WebsocketTooManyRequests
|
||||
from core.db.models import User, Chat, ReadStatus, Message, chat_participant
|
||||
from core.db.models import User, Chat, ReadStatus, Message, ChatParticipant
|
||||
from core.routers.auth.schema import LoginUser
|
||||
from core.utils.helper import format_date
|
||||
|
||||
@@ -38,12 +38,14 @@ async def get_user_active_direct_chats(
|
||||
direct_chats_dict[str(direct_chat.guid)] = direct_chat.id
|
||||
return direct_chats_dict
|
||||
|
||||
return None
|
||||
|
||||
|
||||
async def get_unread_messages_per_chat(
|
||||
db_session: AsyncSession, chats: list[Chat], login_user: LoginUser
|
||||
) -> list[dict]:
|
||||
"""获取聊天未读消息数"""
|
||||
unread_messages_info_per_chat = {chat.id: {'message_count': 0} for chat in chats}
|
||||
unread_messages_info_per_chat: dict[int, dict] = {chat.id: {'message_count': 0} for chat in chats}
|
||||
|
||||
# 查询消息情况
|
||||
read_status_alias = aliased(ReadStatus)
|
||||
@@ -85,6 +87,7 @@ async def get_unread_messages_per_chat(
|
||||
updated_at=format_date(chat.updated_at),
|
||||
recipient_user=users[0],
|
||||
last_message=messages_info.get('message'),
|
||||
is_delete=chat.is_deleted,
|
||||
unread_messages_count=messages_info.get('message_count'),
|
||||
))
|
||||
|
||||
@@ -93,8 +96,8 @@ async def get_unread_messages_per_chat(
|
||||
|
||||
async def get_chat(chat_guid, login_user: User, db_session: AsyncSession) -> Chat | None:
|
||||
subquery = (
|
||||
select(chat_participant.c.chat_id)
|
||||
.where(chat_participant.c.user_id == login_user.user_id)
|
||||
select(ChatParticipant.chat_id)
|
||||
.where(ChatParticipant.user_id == login_user.user_id)
|
||||
).scalar_subquery()
|
||||
|
||||
query = (
|
||||
|
||||
Reference in New Issue
Block a user