refactor(theme): 扩展AppTheme支持卡片样式和圆角风格动态配置 feat(services): 新增HapticService触觉反馈服务 feat(services): 实现ScreenWakeService屏幕常亮管理 feat(services): 添加SoundService音效播放服务 feat(services): 集成AppLockService应用锁功能 feat(services): 实现BatteryOptimizationService电池优化 feat(services): 新增NetworkProxyService网络代理 feat(services): 完善DataExportService数据导出 feat(services): 增强PermissionService权限管理 feat(tools): 工具中心新增拼音转换等多项功能 fix(localization): 修复时区初始化错误 docs: 更新工具中心开发清单和设置重构文档 chore: 更新依赖版本和CI配置
137 lines
4.8 KiB
Python
137 lines
4.8 KiB
Python
# ============================================================
|
|
# 闲言APP — 句子卡片修复后数据流验证
|
|
# 创建时间: 2026-05-01
|
|
# 作用: 验证修复后 fetchMix+sort=newest 的数据唯一性
|
|
# ============================================================
|
|
|
|
import requests
|
|
import json
|
|
import time
|
|
|
|
BASE = "https://tools.wktyl.com"
|
|
|
|
def fetch_mix(mode="random", limit=5, channels=None, sort="newest"):
|
|
params = {"mode": mode, "limit": limit, "sort": sort}
|
|
if channels:
|
|
params["channels"] = ",".join(channels)
|
|
try:
|
|
r = requests.get(f"{BASE}/api/feed/mix", params=params, timeout=10)
|
|
data = r.json()
|
|
if data.get("code") == 1:
|
|
items = data.get("data", {}).get("list", [])
|
|
return items
|
|
except Exception as e:
|
|
print(f" ❌ 请求失败: {e}")
|
|
return []
|
|
|
|
def make_id(item):
|
|
return f"{item.get('feed_type','?')}_{item.get('id')}"
|
|
|
|
print("=" * 70)
|
|
print("验证1: 修复后 fetchMix(mode=random, sort=newest) 数据唯一性")
|
|
print("=" * 70)
|
|
|
|
all_ids = []
|
|
for i in range(10):
|
|
items = fetch_mix(mode="random", limit=5, sort="newest")
|
|
ids = [make_id(item) for item in items]
|
|
all_ids.extend(ids)
|
|
print(f" 第{i+1}次: {ids}")
|
|
time.sleep(0.3)
|
|
|
|
unique = len(set(all_ids))
|
|
total = len(all_ids)
|
|
print(f"\n 📊 总ID数={total}, 去重后={unique}, 重复率={1-unique/total:.1%}")
|
|
print(f" ✅ 修复后API每次返回不同数据" if unique == total else f" ❌ 仍有重复!")
|
|
|
|
print("\n" + "=" * 70)
|
|
print("验证2: 模拟修复后 refreshDailySentences 完整流程")
|
|
print("=" * 70)
|
|
|
|
existing_ids = set()
|
|
for i in range(5):
|
|
items = fetch_mix(mode="random", limit=5, sort="newest")
|
|
if not items:
|
|
print(f" 第{i+1}轮: ❌ API返回空")
|
|
continue
|
|
|
|
daily_list = [make_id(item) for item in items]
|
|
unique = [sid for sid in daily_list if sid not in existing_ids]
|
|
|
|
if not unique and existing_ids:
|
|
retry_items = fetch_mix(mode="random", limit=15, sort="newest")
|
|
if retry_items:
|
|
retry_list = [make_id(item) for item in retry_items]
|
|
unique = [sid for sid in retry_list if sid not in existing_ids]
|
|
|
|
final_list = unique if unique else daily_list
|
|
existing_ids = set(final_list)
|
|
|
|
overlap = set(daily_list) & set([sid for sid in existing_ids if sid in daily_list])
|
|
print(f" 第{i+1}轮: API={daily_list}, unique={len(unique)}, final={len(final_list)}")
|
|
|
|
print(f"\n 📊 5轮后共看到 {len(existing_ids)} 个不同句子")
|
|
|
|
print("\n" + "=" * 70)
|
|
print("验证3: 对比修复前(sort=hottest) vs 修复后(sort=newest)")
|
|
print("=" * 70)
|
|
|
|
for sort_mode in ["hottest", "newest"]:
|
|
ids_set = []
|
|
for i in range(5):
|
|
items = fetch_mix(mode="random", limit=5, sort=sort_mode)
|
|
ids = [make_id(item) for item in items]
|
|
ids_set.extend(ids)
|
|
time.sleep(0.2)
|
|
unique = len(set(ids_set))
|
|
total = len(ids_set)
|
|
rate = 1 - unique/total
|
|
status = "❌ 高重复" if rate > 0.3 else "✅ 低重复"
|
|
print(f" sort={sort_mode:8s}: 总={total}, 去重={unique}, 重复率={rate:.1%} {status}")
|
|
|
|
print("\n" + "=" * 70)
|
|
print("验证4: mode=specific + sort=newest 数据变化性")
|
|
print("=" * 70)
|
|
|
|
all_ids = []
|
|
for i in range(5):
|
|
items = fetch_mix(mode="specific", limit=5,
|
|
channels=["poetry", "wisdom", "story"],
|
|
sort="newest")
|
|
ids = [make_id(item) for item in items]
|
|
all_ids.extend(ids)
|
|
print(f" 第{i+1}次: {ids}")
|
|
time.sleep(0.3)
|
|
|
|
unique = len(set(all_ids))
|
|
total = len(all_ids)
|
|
print(f" 📊 总ID={total}, 去重={unique}, 重复率={1-unique/total:.1%}")
|
|
|
|
print("\n" + "=" * 70)
|
|
print("📋 修复总结")
|
|
print("=" * 70)
|
|
print()
|
|
print("修复内容:")
|
|
print(" 1. FeedMixConfig 添加 sort 字段, 默认 'newest'")
|
|
print(" - 修复前: 不传sort → 后端默认hottest → 热门数据固定")
|
|
print(" - 修复后: 传sort=newest → 每次获取最新数据")
|
|
print()
|
|
print(" 2. refreshDailySentences 添加防重入锁")
|
|
print(" - 防止并发调用导致竞态条件")
|
|
print()
|
|
print(" 3. _fetchDailySentence 初始化不再使用existingIds过滤")
|
|
print(" - 初始化时直接使用API返回的数据")
|
|
print(" - refreshDailySentences 保留去重逻辑确保新内容")
|
|
print()
|
|
print(" 4. DailyCard 只在onEnd时触发onLoadMore")
|
|
print(" - 修复前: 每3次滑动就刷新 → 中途重建CardSwiper")
|
|
print(" - 修复后: 滑完所有卡片才刷新 → 体验更流畅")
|
|
print()
|
|
print(" 5. didUpdateWidget 始终重置卡片状态")
|
|
print(" - 修复前: hasNewContent为false时不重置 → 加载态卡死")
|
|
print(" - 修复后: 始终重置_dataVersion/_frontCardIndex/_allCardsSwiped")
|
|
print()
|
|
print(" 6. refresh() 清空dailySentences")
|
|
print(" - 修复前: refresh不清空 → _fetchDailySentence用旧ID过滤")
|
|
print(" - 修复后: clearDaily=true → 确保获取全新数据")
|