更新ios

This commit is contained in:
2026-01-22 13:10:48 +08:00
parent c9f9d59688
commit 82e543d830
2 changed files with 265 additions and 0 deletions

View File

@@ -156,6 +156,7 @@ def send_event_notification(event, device_tokens: List[str]) -> dict:
# 自定义数据
data = {
'type': 'event',
'event_id': event.id,
'importance': event.importance,
'title': event.title,
@@ -173,6 +174,76 @@ def send_event_notification(event, device_tokens: List[str]) -> dict:
)
def send_social_notification(notification, device_tokens: List[str]) -> dict:
"""
发送社交通知推送
Args:
notification: SocialNotification 模型实例或字典
device_tokens: 设备 Token 列表
Returns:
dict: 推送结果
"""
if not device_tokens:
return {'success': 0, 'failed': 0, 'errors': ['没有设备 Token']}
# 支持字典或模型实例
if isinstance(notification, dict):
notif_type = notification.get('type', 'system')
sender_name = notification.get('sender_name', '')
content = notification.get('content', '')
notif_id = notification.get('id')
target_type = notification.get('target_type')
target_id = notification.get('target_id')
else:
notif_type = notification.type
sender_name = notification.sender_name or ''
content = notification.content or ''
notif_id = notification.id
target_type = notification.target_type
target_id = notification.target_id
# 根据通知类型设置标题
type_labels = {
'reply': '💬 新回复',
'mention': '📢 有人@你',
'like': '❤️ 收到点赞',
'follow': '👋 新关注',
'system': '📣 系统通知',
'message': '💬 新消息',
}
title = type_labels.get(notif_type, '📣 新通知')
# 通知内容
if sender_name and content:
body = f"{sender_name}: {content[:80]}" + ('...' if len(content) > 80 else '')
elif sender_name:
body = f"{sender_name} {type_labels.get(notif_type, '发来通知')}"
elif content:
body = content[:100] + ('...' if len(content) > 100 else '')
else:
body = '你收到了一条新通知'
# 自定义数据(传递给 App 用于跳转)
data = {
'type': 'social',
'notification_id': str(notif_id) if notif_id else None,
'notification_type': notif_type,
'target_type': target_type,
'target_id': target_id,
}
return send_push_notification(
device_tokens=device_tokens,
title=title,
body=body,
data=data,
badge=1,
priority=10 # 社交通知优先级高
)
# ==================== 数据库操作(需要在 app.py 中实现) ====================
def get_all_device_tokens(db_session) -> List[str]:

194
app.py
View File

@@ -21249,6 +21249,119 @@ app.register_blueprint(prediction_bp)
# ==================== 社交通知 API ====================
def create_and_push_social_notification(
user_id: int,
notification_type: str,
content: str = None,
sender_id: int = None,
sender_name: str = None,
sender_avatar: str = None,
target_type: str = None,
target_id: str = None
) -> 'SocialNotification':
"""
创建社交通知并发送推送
Args:
user_id: 接收通知的用户 ID
notification_type: 通知类型 (reply, mention, like, follow, system, message)
content: 通知内容
sender_id: 发送者用户 ID可选
sender_name: 发送者名称(可选)
sender_avatar: 发送者头像(可选)
target_type: 关联目标类型 (post, reply, channel, message)
target_id: 关联目标 ID
Returns:
SocialNotification: 创建的通知实例
"""
try:
# 创建通知记录
notification = SocialNotification(
user_id=user_id,
type=notification_type,
sender_id=sender_id,
sender_name=sender_name,
sender_avatar=sender_avatar,
content=content,
target_type=target_type,
target_id=target_id,
is_read=False
)
db.session.add(notification)
db.session.commit()
# 发送 APNs 推送
try:
from apns_push import send_social_notification
# 获取该用户的活跃设备 token
device_tokens_query = db.session.query(UserDeviceToken.device_token).filter(
UserDeviceToken.user_id == user_id,
UserDeviceToken.is_active == True
).all()
tokens = [t[0] for t in device_tokens_query]
if tokens:
print(f'[APNs Social] 准备推送到用户 {user_id}{len(tokens)} 个设备')
result = send_social_notification(notification, tokens)
print(f'[APNs Social] 推送结果: 成功 {result["success"]}, 失败 {result["failed"]}')
else:
print(f'[APNs Social] 用户 {user_id} 没有活跃的设备 token')
except ImportError as e:
print(f'[APNs Social WARN] apns_push 模块未安装或配置: {e}')
except Exception as apns_error:
print(f'[APNs Social ERROR] 推送失败: {apns_error}')
return notification
except Exception as e:
db.session.rollback()
app.logger.error(f"创建社交通知失败: {e}")
raise
def broadcast_social_notification_to_users(
user_ids: list,
notification_type: str,
content: str = None,
sender_id: int = None,
sender_name: str = None,
sender_avatar: str = None,
target_type: str = None,
target_id: str = None
) -> int:
"""
向多个用户广播社交通知(批量创建并推送)
Args:
user_ids: 接收通知的用户 ID 列表
其他参数同 create_and_push_social_notification
Returns:
int: 成功创建的通知数量
"""
success_count = 0
for user_id in user_ids:
try:
create_and_push_social_notification(
user_id=user_id,
notification_type=notification_type,
content=content,
sender_id=sender_id,
sender_name=sender_name,
sender_avatar=sender_avatar,
target_type=target_type,
target_id=target_id
)
success_count += 1
except Exception as e:
app.logger.error(f"向用户 {user_id} 发送通知失败: {e}")
return success_count
@app.route('/api/social/notifications', methods=['GET'])
@login_required
def get_social_notifications():
@@ -21353,6 +21466,87 @@ def get_social_notifications_unread_count():
return jsonify({'code': 500, 'message': str(e)}), 500
@app.route('/api/social/notifications/test', methods=['POST'])
@login_required
def test_social_notification():
"""
测试社交通知推送(仅供开发测试)
向当前用户发送一条测试通知
"""
try:
data = request.get_json() or {}
notification_type = data.get('type', 'system')
content = data.get('content', '这是一条测试通知')
notification = create_and_push_social_notification(
user_id=current_user.id,
notification_type=notification_type,
content=content,
sender_name='系统测试',
target_type='test',
target_id='test_001'
)
return jsonify({
'code': 200,
'message': '测试通知已发送',
'data': notification.to_dict()
})
except Exception as e:
app.logger.error(f"测试通知发送失败: {e}")
return jsonify({'code': 500, 'message': str(e)}), 500
@app.route('/api/social/notifications/send', methods=['POST'])
@login_required
def send_social_notification_api():
"""
发送社交通知 API供后端其他服务调用
请求体:
{
"user_id": 123, // 必填,接收者用户 ID
"type": "message", // 必填,通知类型
"content": "消息内容", // 可选
"sender_id": 456, // 可选,发送者 ID
"sender_name": "张三", // 可选
"sender_avatar": "url", // 可选
"target_type": "post", // 可选
"target_id": "post_123" // 可选
}
"""
try:
data = request.get_json()
if not data:
return jsonify({'code': 400, 'message': '缺少请求体'}), 400
user_id = data.get('user_id')
notification_type = data.get('type')
if not user_id or not notification_type:
return jsonify({'code': 400, 'message': 'user_id 和 type 为必填'}), 400
notification = create_and_push_social_notification(
user_id=user_id,
notification_type=notification_type,
content=data.get('content'),
sender_id=data.get('sender_id'),
sender_name=data.get('sender_name'),
sender_avatar=data.get('sender_avatar'),
target_type=data.get('target_type'),
target_id=data.get('target_id')
)
return jsonify({
'code': 200,
'message': '通知已发送',
'data': notification.to_dict()
})
except Exception as e:
app.logger.error(f"发送社交通知失败: {e}")
return jsonify({'code': 500, 'message': str(e)}), 500
if __name__ == '__main__':
# 创建数据库表
with app.app_context():