# ============================================================ # 闲言APP — 句子卡片数据永不更新根因验证 # 创建时间: 2026-05-01 # 作用: 验证 fetchMix 接口在相同参数下是否返回相同数据 # ============================================================ import requests import json import time BASE = "https://tools.wktyl.com" def fetch_mix(mode="random", limit=5, channels=None, sort="hottest"): 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" ❌ fetchMix 请求失败: {e}") return [] print("=" * 70) print("根因验证: fetchMix 默认 sort=hottest 是否导致数据固定") print("=" * 70) # 测试1: 默认 sort=hottest 连续3次 print("\n📌 测试1: sort=hottest (默认) 连续3次请求") all_ids_hottest = [] for i in range(3): items = fetch_mix(mode="random", limit=5, sort="hottest") ids = [f"{item.get('feed_type','?')}_{item.get('id')}" for item in items] titles = [item.get("title", "")[:25] for item in items] all_ids_hottest.extend(ids) print(f" 第{i+1}次: ids={ids}") for t in titles: print(f" → {t}") time.sleep(0.3) unique_hottest = len(set(all_ids_hottest)) total_hottest = len(all_ids_hottest) print(f" 📊 总ID数={total_hottest}, 去重后={unique_hottest}, 重复率={1-unique_hottest/total_hottest:.1%}") # 测试2: sort=newest 连续3次 print("\n📌 测试2: sort=newest 连续3次请求") all_ids_newest = [] for i in range(3): items = fetch_mix(mode="random", limit=5, sort="newest") ids = [f"{item.get('feed_type','?')}_{item.get('id')}" for item in items] titles = [item.get("title", "")[:25] for item in items] all_ids_newest.extend(ids) print(f" 第{i+1}次: ids={ids}") for t in titles: print(f" → {t}") time.sleep(0.3) unique_newest = len(set(all_ids_newest)) total_newest = len(all_ids_newest) print(f" 📊 总ID数={total_newest}, 去重后={unique_newest}, 重复率={1-unique_newest/total_newest:.1%}") # 测试3: 对比 hottest vs newest print("\n📌 测试3: hottest vs newest 对比") hottest_items = fetch_mix(mode="random", limit=5, sort="hottest") newest_items = fetch_mix(mode="random", limit=5, sort="newest") hottest_ids = set(f"{item.get('feed_type','?')}_{item.get('id')}" for item in hottest_items) newest_ids = set(f"{item.get('feed_type','?')}_{item.get('id')}" for item in newest_items) overlap = hottest_ids & newest_ids print(f" hottest: {hottest_ids}") print(f" newest: {newest_ids}") print(f" 重叠: {overlap}") # 测试4: 客户端当前代码使用的参数 print("\n📌 测试4: 模拟客户端当前代码 (mode=random, limit=5, 无sort参数)") all_ids_client = [] for i in range(5): items = fetch_mix(mode="random", limit=5) ids = [f"{item.get('feed_type','?')}_{item.get('id')}" for item in items] all_ids_client.extend(ids) print(f" 第{i+1}次: ids={ids}") time.sleep(0.3) unique_client = len(set(all_ids_client)) total_client = len(all_ids_client) print(f" 📊 总ID数={total_client}, 去重后={unique_client}, 重复率={1-unique_client/total_client:.1%}") # 测试5: 检查 FeedMixConfig.toQueryParameters 是否传了 sort print("\n📌 测试5: FeedMixConfig.toQueryParameters 分析") print(" 客户端代码 (feed_model.dart):") print(" Map toQueryParameters() {") print(" final params = {'mode': mode, 'limit': limit};") print(" if (channels.isNotEmpty) params['channels'] = channels.join(',');") print(" if (mode == 'ratio' && ratios.isNotEmpty) params['ratios'] = jsonEncode(ratios);") print(" if (mode == 'group') params['group_size'] = groupSize;") print(" return params;") print(" }") print(" ⚠️ 注意: toQueryParameters 没有传 sort 参数!") print(" ⚠️ 后端默认 sort=hottest,按浏览量排序") print(" ⚠️ hottest 模式下热门内容固定,导致每次返回相同数据!") # 结论 print("\n" + "=" * 70) print("🔍 根因分析") print("=" * 70) print() print("问题: 句子卡片5个句子循环重复,永远不会出现新的") print() print("根因: FeedMixConfig.toQueryParameters() 没有传 sort 参数,") print(" 后端默认 sort=hottest(按浏览量排序),") print(" 热门内容排名稳定,导致每次请求返回相同的高浏览量句子。") print() print("修复方案: FeedMixConfig 添加 sort 字段,默认值 'random' 或 'newest',") print(" toQueryParameters() 传入 sort 参数。") print() print("验证: 如果 hottest 重复率远高于 newest,则确认根因。") print(f" hottest 重复率: {1-unique_hottest/total_hottest:.1%}") print(f" newest 重复率: {1-unique_newest/total_newest:.1%}")