Spaces:
Running
Running
优化消息提醒
Browse files- notifications.py +6 -4
- router_messages.py +68 -49
- router_tasks.py +4 -5
notifications.py
CHANGED
|
@@ -23,7 +23,9 @@ def add_notification(target_account: str, notif_data: dict):
|
|
| 23 |
"created_at": int(time.time())
|
| 24 |
}
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
| 23 |
"created_at": int(time.time())
|
| 24 |
}
|
| 25 |
|
| 26 |
+
def updater(data):
|
| 27 |
+
if target_account not in data:
|
| 28 |
+
data[target_account] = []
|
| 29 |
+
data[target_account].insert(0, notif)
|
| 30 |
+
|
| 31 |
+
db.atomic_update("messages.json", updater, default_data={})
|
router_messages.py
CHANGED
|
@@ -202,65 +202,84 @@ async def get_chat_history(account: str, target_account: str):
|
|
| 202 |
|
| 203 |
# ==========================================
|
| 204 |
# 改造:获取通知列表 (加入系统公告懒加载注入)
|
|
|
|
| 205 |
# ==========================================
|
| 206 |
@router.get("/api/messages/{account}")
|
| 207 |
async def get_messages(account: str):
|
| 208 |
-
|
| 209 |
-
user_msgs = msgs_db.get(account, [])
|
| 210 |
-
|
| 211 |
-
# --- 核心改造区:瞬间比对并注入全局公告 ---
|
| 212 |
announcements_db = db.load_data("announcements.json", default_data=[])
|
| 213 |
-
user_msg_ids = {m.get("id") for m in user_msgs}
|
| 214 |
|
| 215 |
-
|
| 216 |
-
for ann in announcements_db:
|
| 217 |
-
if ann.get("id") not in user_msg_ids:
|
| 218 |
-
new_sys_msg = dict(ann)
|
| 219 |
-
new_sys_msg["is_read"] = False
|
| 220 |
-
new_sys_msg["receiver"] = account
|
| 221 |
-
user_msgs.append(new_sys_msg)
|
| 222 |
-
injected = True
|
| 223 |
-
|
| 224 |
-
if injected:
|
| 225 |
-
# 重新按照时间倒序排列,让新公告置顶
|
| 226 |
-
user_msgs.sort(key=lambda x: x.get("created_at", 0), reverse=True)
|
| 227 |
-
# ----------------------------------------
|
| 228 |
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
|
|
|
| 245 |
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
|
| 252 |
@router.post("/api/messages/{account}/read")
|
| 253 |
async def mark_messages_read(account: str):
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
db.save_data("messages.json", msgs_db)
|
| 265 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
return {"status": "success"}
|
|
|
|
| 202 |
|
| 203 |
# ==========================================
|
| 204 |
# 改造:获取通知列表 (加入系统公告懒加载注入)
|
| 205 |
+
# 使用 atomic_update 避免并发覆盖问题
|
| 206 |
# ==========================================
|
| 207 |
@router.get("/api/messages/{account}")
|
| 208 |
async def get_messages(account: str):
|
| 209 |
+
# 公告是只读的,在 atomic_update 外加载
|
|
|
|
|
|
|
|
|
|
| 210 |
announcements_db = db.load_data("announcements.json", default_data=[])
|
|
|
|
| 211 |
|
| 212 |
+
result_container = [None]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
|
| 214 |
+
def updater(data):
|
| 215 |
+
user_msgs = data.get(account, [])
|
| 216 |
+
|
| 217 |
+
# --- 核心改造区:瞬间比对并注入全局公告 ---
|
| 218 |
+
user_msg_ids = {m.get("id") for m in user_msgs}
|
| 219 |
+
|
| 220 |
+
injected = False
|
| 221 |
+
for ann in announcements_db:
|
| 222 |
+
if ann.get("id") not in user_msg_ids:
|
| 223 |
+
new_sys_msg = dict(ann)
|
| 224 |
+
new_sys_msg["is_read"] = False
|
| 225 |
+
new_sys_msg["receiver"] = account
|
| 226 |
+
user_msgs.append(new_sys_msg)
|
| 227 |
+
injected = True
|
| 228 |
+
|
| 229 |
+
if injected:
|
| 230 |
+
# 重新按照时间倒序排列,让新公告置顶
|
| 231 |
+
user_msgs.sort(key=lambda x: x.get("created_at", 0), reverse=True)
|
| 232 |
+
# ----------------------------------------
|
| 233 |
+
|
| 234 |
+
now = int(time.time())
|
| 235 |
+
seven_days = 7 * 24 * 3600
|
| 236 |
+
valid = []
|
| 237 |
+
|
| 238 |
+
# 如果注入了新公告,则判定为需要回写数据库保存
|
| 239 |
+
modified = injected
|
| 240 |
+
|
| 241 |
+
for m in user_msgs:
|
| 242 |
+
if not m.get("is_read") or (now - m.get("created_at", 0) < seven_days):
|
| 243 |
+
valid.append(m)
|
| 244 |
+
else:
|
| 245 |
+
modified = True
|
| 246 |
|
| 247 |
+
# 本次访问即为已读 - 将所有未读消息标记为已读
|
| 248 |
+
if not m.get("is_read"):
|
| 249 |
+
m["is_read"] = True
|
| 250 |
+
modified = True
|
| 251 |
|
| 252 |
+
# 原地修改 data,atomic_update 会自动保存
|
| 253 |
+
data[account] = valid
|
| 254 |
+
|
| 255 |
+
# 通过闭包返回结果
|
| 256 |
+
result_container[0] = {
|
| 257 |
+
"status": "success",
|
| 258 |
+
"data": valid,
|
| 259 |
+
"unread_count": 0 # 🔥 修复:用户已查看消息列表,未读数设为0
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
db.atomic_update("messages.json", updater, default_data={})
|
| 263 |
+
|
| 264 |
+
return result_container[0]
|
| 265 |
|
| 266 |
@router.post("/api/messages/{account}/read")
|
| 267 |
async def mark_messages_read(account: str):
|
| 268 |
+
"""
|
| 269 |
+
标记消息为已读(原子操作,并发安全)
|
| 270 |
+
"""
|
| 271 |
+
def updater(data):
|
| 272 |
+
user_msgs = data.get(account, [])
|
| 273 |
+
modified = False
|
| 274 |
+
for m in user_msgs:
|
| 275 |
+
if not m.get("is_read"):
|
| 276 |
+
m["is_read"] = True
|
| 277 |
+
modified = True
|
|
|
|
| 278 |
|
| 279 |
+
# 原地修改 data,atomic_update 会自动保存
|
| 280 |
+
if modified:
|
| 281 |
+
data[account] = user_msgs
|
| 282 |
+
|
| 283 |
+
db.atomic_update("messages.json", updater, default_data={})
|
| 284 |
+
|
| 285 |
return {"status": "success"}
|
router_tasks.py
CHANGED
|
@@ -15,7 +15,7 @@ from fastapi import APIRouter, HTTPException, Depends, Query
|
|
| 15 |
from sqlalchemy.orm import Session
|
| 16 |
from models import TaskCreate, TaskUpdate, TaskApply, TaskAssign, TaskSubmit, TaskAccept
|
| 17 |
import 数据库连接 as db
|
| 18 |
-
from 安全认证 import require_auth
|
| 19 |
from notifications import add_notification
|
| 20 |
from database_sql import get_db
|
| 21 |
from models_sql import Wallet, Transaction
|
|
@@ -846,8 +846,7 @@ async def accept_task(task_id: str, is_accepted: bool, feedback: str = None, cur
|
|
| 846 |
# ==========================================
|
| 847 |
# ⚖️ 申诉仲裁系统
|
| 848 |
# ==========================================
|
| 849 |
-
|
| 850 |
-
ADMIN_ACCOUNTS = [a.strip() for a in os.getenv("ADMIN_ACCOUNTS", "admin").split(",")]
|
| 851 |
|
| 852 |
@router.post("/api/tasks/{task_id}/dispute")
|
| 853 |
async def create_dispute(task_id: str, reason: str, evidence: list = None, current_user: str = Depends(require_auth)):
|
|
@@ -1000,7 +999,7 @@ async def get_admin_disputes(status: str = None, current_user: str = Depends(req
|
|
| 1000 |
管理员获取申诉列表
|
| 1001 |
- status: pending/responded/resolved
|
| 1002 |
"""
|
| 1003 |
-
if
|
| 1004 |
raise HTTPException(status_code=403, detail="需要管理员权限")
|
| 1005 |
|
| 1006 |
disputes_db = db.load_data("disputes.json", default_data=[])
|
|
@@ -1038,7 +1037,7 @@ async def resolve_dispute(dispute_id: str, resolution: str, ratio: int = None, n
|
|
| 1038 |
- ratio: 分成比例(0-100),表示申诉方获得的比例。仅split时有效
|
| 1039 |
- note: 裁决说明
|
| 1040 |
"""
|
| 1041 |
-
if
|
| 1042 |
raise HTTPException(status_code=403, detail="需要管理员权限")
|
| 1043 |
|
| 1044 |
if resolution not in ["favor_initiator", "favor_respondent", "split"]:
|
|
|
|
| 15 |
from sqlalchemy.orm import Session
|
| 16 |
from models import TaskCreate, TaskUpdate, TaskApply, TaskAssign, TaskSubmit, TaskAccept
|
| 17 |
import 数据库连接 as db
|
| 18 |
+
from 安全认证 import require_auth, is_admin
|
| 19 |
from notifications import add_notification
|
| 20 |
from database_sql import get_db
|
| 21 |
from models_sql import Wallet, Transaction
|
|
|
|
| 846 |
# ==========================================
|
| 847 |
# ⚖️ 申诉仲裁系统
|
| 848 |
# ==========================================
|
| 849 |
+
|
|
|
|
| 850 |
|
| 851 |
@router.post("/api/tasks/{task_id}/dispute")
|
| 852 |
async def create_dispute(task_id: str, reason: str, evidence: list = None, current_user: str = Depends(require_auth)):
|
|
|
|
| 999 |
管理员获取申诉列表
|
| 1000 |
- status: pending/responded/resolved
|
| 1001 |
"""
|
| 1002 |
+
if not is_admin(current_user):
|
| 1003 |
raise HTTPException(status_code=403, detail="需要管理员权限")
|
| 1004 |
|
| 1005 |
disputes_db = db.load_data("disputes.json", default_data=[])
|
|
|
|
| 1037 |
- ratio: 分成比例(0-100),表示申诉方获得的比例。仅split时有效
|
| 1038 |
- note: 裁决说明
|
| 1039 |
"""
|
| 1040 |
+
if not is_admin(current_user):
|
| 1041 |
raise HTTPException(status_code=403, detail="需要管理员权限")
|
| 1042 |
|
| 1043 |
if resolution not in ["favor_initiator", "favor_respondent", "split"]:
|