ZHIWEI666 commited on
Commit
5bf0454
·
verified ·
1 Parent(s): 8f0ec20

优化消息提醒

Browse files
Files changed (3) hide show
  1. notifications.py +6 -4
  2. router_messages.py +68 -49
  3. 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
- msgs_db = db.load_data("messages.json", default_data={})
27
- if target_account not in msgs_db: msgs_db[target_account] = []
28
- msgs_db[target_account].insert(0, notif)
29
- db.save_data("messages.json", msgs_db)
 
 
 
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
- msgs_db = db.load_data("messages.json", default_data={})
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
- injected = False
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
- now = int(time.time())
230
- seven_days = 7 * 24 * 3600
231
- valid = []
232
-
233
- # 如果注入了新公告,则判定为需要回写数据库保存
234
- modified = injected
235
-
236
- for m in user_msgs:
237
- if not m.get("is_read") or (now - m.get("created_at", 0) < seven_days):
238
- valid.append(m)
239
- else:
240
- modified = True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
 
242
- if modified:
243
- msgs_db[account] = valid
244
- db.save_data("messages.json", msgs_db)
 
245
 
246
- return {
247
- "status": "success",
248
- "data": valid,
249
- "unread_count": sum(1 for m in valid if not m.get("is_read"))
250
- }
 
 
 
 
 
 
 
 
251
 
252
  @router.post("/api/messages/{account}/read")
253
  async def mark_messages_read(account: str):
254
- msgs_db = db.load_data("messages.json", default_data={})
255
- user_msgs = msgs_db.get(account, [])
256
- modified = False
257
- for m in user_msgs:
258
- if not m.get("is_read"):
259
- m["is_read"] = True
260
- modified = True
261
-
262
- if modified:
263
- msgs_db[account] = user_msgs
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
- import os
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 current_user not in ADMIN_ACCOUNTS:
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 current_user not in ADMIN_ACCOUNTS:
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"]: