|
|
@@ -296,7 +296,7 @@ html_content = f"""<!DOCTYPE html>
|
|
|
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
|
|
|
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
|
background: #f5f5f5; padding: 20px; }}
|
|
|
- .container {{ max-width: 1200px; margin: 0 auto; }}
|
|
|
+ .container {{ width: 100%; max-width: none; }}
|
|
|
h1 {{ font-size: 24px; margin-bottom: 10px; color: #333; }}
|
|
|
.subtitle {{ color: #666; margin-bottom: 20px; font-size: 14px; }}
|
|
|
|
|
|
@@ -409,6 +409,21 @@ html_content = f"""<!DOCTYPE html>
|
|
|
<label>最小点击:</label>
|
|
|
<input type="number" id="min-click-input" value="100" min="0" step="100" style="width:70px" onchange="onFilterChange()">
|
|
|
</div>
|
|
|
+ <div class="control-group">
|
|
|
+ <label>下级≥:</label>
|
|
|
+ <input type="number" id="min-children-input" value="2" min="1" max="20" style="width:50px" onchange="onFilterChange()">
|
|
|
+ </div>
|
|
|
+ <div class="control-group">
|
|
|
+ <label>下级点击≥:</label>
|
|
|
+ <input type="number" id="min-child-click-input" value="10" min="0" step="10" style="width:60px" onchange="onFilterChange()">
|
|
|
+ </div>
|
|
|
+ <div class="control-group">
|
|
|
+ <label>下级排序:</label>
|
|
|
+ <select id="child-sort-select" onchange="onFilterChange()">
|
|
|
+ <option value="click" selected>点击UV</option>
|
|
|
+ <option value="sim">相似度</option>
|
|
|
+ </select>
|
|
|
+ </div>
|
|
|
<div class="control-group">
|
|
|
<label>Top:</label>
|
|
|
<input type="number" id="top-input" value="50" min="1" max="500" style="width:60px" onchange="onFilterChange()">
|
|
|
@@ -473,6 +488,9 @@ html_content = f"""<!DOCTYPE html>
|
|
|
channel: document.getElementById('channel-select').value,
|
|
|
category: document.getElementById('category-select').value,
|
|
|
minClick: parseInt(document.getElementById('min-click-input').value) || 0,
|
|
|
+ minChildren: parseInt(document.getElementById('min-children-input').value) || 2,
|
|
|
+ minChildClick: parseInt(document.getElementById('min-child-click-input').value) || 10,
|
|
|
+ childSort: document.getElementById('child-sort-select').value,
|
|
|
top: parseInt(document.getElementById('top-input').value) || 50
|
|
|
}};
|
|
|
}}
|
|
|
@@ -593,18 +611,35 @@ html_content = f"""<!DOCTYPE html>
|
|
|
shareData = categoryFiltered.share;
|
|
|
videoData = categoryFiltered.video;
|
|
|
|
|
|
- // 按最小点击UV过滤(分享标题层 + 视频标题层)
|
|
|
+ // 下级排序函数
|
|
|
+ const childSortFn = filters.childSort === 'click'
|
|
|
+ ? (a, b) => b.total_click - a.total_click
|
|
|
+ : (a, b) => b.sim - a.sim;
|
|
|
+
|
|
|
+ // 按最小点击UV过滤 + 下级点击过滤 + 下级排序
|
|
|
if (shareData.share_titles) {{
|
|
|
shareData.share_titles = shareData.share_titles
|
|
|
.filter(st => st.total_click >= filters.minClick)
|
|
|
.map(st => {{
|
|
|
- st.video_titles = st.video_titles.filter(vt => vt.total_click >= filters.minClick);
|
|
|
+ // 下级点击过滤 + 排序
|
|
|
+ st.video_titles = st.video_titles
|
|
|
+ .filter(vt => vt.total_click >= filters.minChildClick)
|
|
|
+ .sort(childSortFn);
|
|
|
return st;
|
|
|
}})
|
|
|
- .filter(st => st.video_titles.length > 0); // 移除没有视频标题的
|
|
|
+ .filter(st => st.video_titles.length >= filters.minChildren); // 下级数量筛选
|
|
|
}}
|
|
|
if (videoData.videos) {{
|
|
|
- videoData.videos = videoData.videos.filter(v => v.total_click >= filters.minClick);
|
|
|
+ videoData.videos = videoData.videos
|
|
|
+ .filter(v => v.total_click >= filters.minClick)
|
|
|
+ .map(v => {{
|
|
|
+ // 下级点击过滤 + 排序
|
|
|
+ v.share_titles = v.share_titles
|
|
|
+ .filter(st => st.total_click >= filters.minChildClick)
|
|
|
+ .sort(childSortFn);
|
|
|
+ return v;
|
|
|
+ }})
|
|
|
+ .filter(v => v.share_titles.length >= filters.minChildren); // 下级数量筛选
|
|
|
}}
|
|
|
|
|
|
// 记录真实数量(过滤后、截取前)
|
|
|
@@ -728,12 +763,12 @@ html_content = f"""<!DOCTYPE html>
|
|
|
return rate >= q66 ? 'good' : (rate <= q33 ? 'bad' : '');
|
|
|
}}
|
|
|
|
|
|
- // 渲染三种回流率
|
|
|
+ // 渲染三种回流率(4位小数)
|
|
|
function renderRates(item) {{
|
|
|
return `
|
|
|
- <span class="rate" style="${{rateGradient(item.overall_rate)}}">整体 ${{(item.overall_rate * 100).toFixed(1)}}%</span>
|
|
|
- <span class="rate" style="${{rateGradient(item.head_rate)}}">头部 ${{(item.head_rate * 100).toFixed(1)}}%</span>
|
|
|
- <span class="rate" style="${{rateGradient(item.rec_rate)}}">推荐 ${{(item.rec_rate * 100).toFixed(1)}}%</span>
|
|
|
+ <span class="rate" style="${{rateGradient(item.overall_rate)}}">整体 ${{item.overall_rate.toFixed(4)}}</span>
|
|
|
+ <span class="rate" style="${{rateGradient(item.head_rate)}}">头部 ${{item.head_rate.toFixed(4)}}</span>
|
|
|
+ <span class="rate" style="${{rateGradient(item.rec_rate)}}">推荐 ${{item.rec_rate.toFixed(4)}}</span>
|
|
|
`;
|
|
|
}}
|
|
|
|