fix: remove publication verification filter from work analysis

This commit is contained in:
2026-10-06 14:47:13 +08:00
parent fa7b78797d
commit 5691fd1a93
3 changed files with 6 additions and 27 deletions
+3 -1
View File
@@ -48,7 +48,9 @@
自有账号作品:作品总数使用抖音最新非空 `aweme_count`,已保存 `work_count` 仅表示采集进度,不得互相替代;未知总数与零作品必须区分。自有账号作品库保存平台分页返回的全部历史作品,不受采集回看天数限制;回看天数仍限制监控账号作品和评论采集。详情分页浏览已采集作品,并明确展示采集进度与未完整状态,不能将采集成功等同于已采齐。
作品分析:左侧原“竞品分析”统一为“作品分析”,页面通过“竞品账号”“我的账号”两个 TAB 严格区分作品来源;各 TAB 独立保留筛选与分页。支持所属账号、发布时间、时间核验状态和互动阈值筛选,以及发布时间、点赞、评论、分享、收藏、24h 点赞增量升降序;自有作品额外支持观看量。默认最新发布在前,条件变化回到第一页,筛选与排序作用于全部已采集作品后再分页;缺失指标显示“—”,排序放末尾、阈值筛选不将其当作 0。未采集作品不参与分析。
作品分析:左侧原“竞品分析”统一为“作品分析”,页面通过“竞品账号”“我的账号”两个 TAB 严格区分作品来源;各 TAB 独立保留筛选与分页。支持所属账号、发布时间和互动阈值筛选,以及发布时间、点赞、评论、分享、收藏、24h 点赞增量升降序;自有作品额外支持观看量,不展示“时间核验状态”筛选。默认最新发布在前,条件变化回到第一页,筛选与排序作用于全部已采集作品后再分页;缺失指标显示“—”,排序放末尾、阈值筛选不将其当作 0。未采集作品不参与分析。
评论聚合:独立页面通过“我的作品评论”“竞品作品评论”两个 TAB 严格区分来源,各 TAB 保留筛选与页码。列表展示评论发布时间、评论者、内容、所属账号(昵称与 UID)及对应作品;支持所属账号筛选,以及最近 1/6/12 小时、1/3/5/7 天筛选,默认最近 1 天。按评论发布时间计算范围,最新评论在前,同时间按评论 ID 倒序;未记录发布时间、未来时间及未采集评论不参与。筛选先作用于全部已采集评论再分页,条件或每页数量变化回到第一页;只读展示,不新增采集机制。
前端框架:Umi Max 4.7 + React 19;
@@ -9,7 +9,6 @@ type SourceType = 'owned' | 'competitor';
interface Filters {
sourceId?: string;
dates?: [Dayjs, Dayjs];
publishedAtStatus?: string;
minLikes?: number;
minComments?: number;
minShares?: number;
@@ -25,12 +24,6 @@ interface AccountOption {
nickname?: string;
platform_account_key: string;
}
const publishedAtStatusOptions = [
{ value: 'verified', label: '已核验' },
{ value: 'future', label: '未来时间' },
{ value: 'pending_verification', label: '待核验' },
{ value: 'invalid', label: '无效时间' },
];
const metricFilters: { key: keyof Filters; label: string }[] = [
{ key: 'minLikes', label: '最低点赞' },
{ key: 'minComments', label: '最低评论' },
@@ -86,7 +79,6 @@ export function WorkAnalysisTab({ sourceType }: { sourceType: SourceType }) {
sort_order: filters.sortOrder ?? 'desc',
published_after: filters.dates?.[0].startOf('day').toISOString(),
published_before: filters.dates?.[1].endOf('day').toISOString(),
published_at_status: filters.publishedAtStatus,
min_likes: filters.minLikes,
min_comments: filters.minComments,
min_shares: filters.minShares,
@@ -133,22 +125,6 @@ export function WorkAnalysisTab({ sourceType }: { sourceType: SourceType }) {
}
/>
</Form.Item>
<Form.Item label="时间核验状态">
<Select
aria-label="时间核验状态"
placeholder="全部状态"
allowClear
style={{ width: 140 }}
value={filters.publishedAtStatus}
options={publishedAtStatusOptions}
onChange={(value) =>
setFilters((current) => ({
...current,
publishedAtStatus: value,
}))
}
/>
</Form.Item>
</Form>
<Form layout="inline">
{metrics.map(({ key, label }) => (
@@ -69,7 +69,8 @@ for (const sourceType of ['competitor', 'owned']) {
assert.equal(account.props.options[0].value, `${sourceType}-1`);
account.props.onChange(`${sourceType}-1`);
for (const [label, value] of [['最低点赞', 0], ['最低评论', 2], ['最低分享', 3], ['最低收藏', 4], ['最低24h点赞增量', 5]]) control(tree, 'InputNumber', label).props.onChange(value);
control(tree, 'Select', '时间核验状态').props.onChange('verified');
assert.equal(control(tree, 'Select', '时间核验状态'), undefined);
assert.equal('published_at_status' in nodes(tree, 'WorksGallery')[0].props.extraFilters, false);
control(tree, 'Select', '排序指标').props.onChange('likes_growth');
control(tree, 'Select', '排序方向').props.onChange('asc');
const dates = [{ startOf: () => ({ toISOString: () => '2026-01-01T00:00:00.000Z' }) }, { endOf: () => ({ toISOString: () => '2026-01-03T23:59:59.999Z' }) }];
@@ -79,7 +80,7 @@ for (const sourceType of ['competitor', 'owned']) {
tree = app.render();
const gallery = nodes(tree, 'WorksGallery')[0];
assert.equal(gallery.props.sourceId, `${sourceType}-1`);
assert.deepEqual(plain(gallery.props.extraFilters), { growth_hours: 24, sort_by: 'likes_growth', sort_order: 'asc', published_after: '2026-01-01T00:00:00.000Z', published_before: '2026-01-03T23:59:59.999Z', published_at_status: 'verified', min_likes: 0, min_comments: 2, min_shares: 3, min_collect_count: 4, min_likes_growth: 5, ...(sourceType === 'owned' ? { min_play_count: 0 } : {}) });
assert.deepEqual(plain(gallery.props.extraFilters), { growth_hours: 24, sort_by: 'likes_growth', sort_order: 'asc', published_after: '2026-01-01T00:00:00.000Z', published_before: '2026-01-03T23:59:59.999Z', min_likes: 0, min_comments: 2, min_shares: 3, min_collect_count: 4, min_likes_growth: 5, ...(sourceType === 'owned' ? { min_play_count: 0 } : {}) });
const sorts = control(tree, 'Select', '排序指标').props.options.map(option => option.value);
assert.equal(sorts.includes('play_count'), sourceType === 'owned');
assert(sorts.includes('collect_count'));