feat: KOC详情弹窗 + 任务中心单入口改版 + 资源池默认合作方/采集兜底
KOC 详情弹窗(合作方/数据回收/工作台三处入口): - 新增 KocDetailModal:基本信息 / 绑定KOC账号画像 / 参与任务记录 / 履约漏斗 - 工作台最近分发、回收队列账号名、截图回收合作方名、合作方页名称、分发详情头部合作方均可点开 - 分发表行点击仍打开分发详情(stopPropagation 隔离) 任务中心单入口改版(对齐"单任务双阶段"模型): - 任务卡发布/回收面板整块可点,全卡仅保留一个「查看明细」,回收面板重复按钮移除 - 详情页自述身份:动态 label(任务详情·分发与回收一体/仅分发)+ 阶段徽章(含回收·截止/未开通回收) - 内容分发表新增阶段筛选 chips(全部/待发布/已发布待数据/待收截图,未开通回收不显示截图项),筛选落空给专用空态文案 - 数据回收页入口文案改为「选择一个任务进入回收队列」,全站不再区分发布/回收两种任务类型 资源池 KOC 默认加入合作方 + 采集兜底: - partners 新增 released_account_id(mysql/0023):显式解绑/被顶替的账号不再被默认合作方同步回填 - 任务未设置采集计划时,默认按发布时间起连续采集 7 天,等待文案显示「等待D1 · 默认7天」
This commit is contained in:
90
tests/koc-detail.test.mjs
Normal file
90
tests/koc-detail.test.mjs
Normal file
@@ -0,0 +1,90 @@
|
||||
import { strict as assert } from "node:assert";
|
||||
import { readFileSync } from "node:fs";
|
||||
import test from "node:test";
|
||||
|
||||
const source = readFileSync(new URL("../app/admin-app.tsx", import.meta.url), "utf8");
|
||||
|
||||
test("KOC 详情弹窗组件:三段式(基本信息 / 绑定账号 / 参与记录)", () => {
|
||||
const start = source.indexOf("function KocDetailModal");
|
||||
assert.ok(start > 0, "应存在 KocDetailModal 组件");
|
||||
const body = source.slice(start, source.indexOf("function RecoveryPage"));
|
||||
assert.match(body, /KOC详情:\$\{partner\.name\}/);
|
||||
assert.match(body, /① 基本信息/);
|
||||
assert.match(body, /② 绑定 KOC 账号(资源)/);
|
||||
assert.match(body, /③ 参与任务记录/);
|
||||
assert.match(body, /暂无领取记录/);
|
||||
// 概览漏斗:领取 → 发布 → 回收完成
|
||||
assert.match(body, /领取 <b>\{history\.length\}<\/b>/);
|
||||
assert.match(body, /发布 <b>\{publishedCount\}<\/b>/);
|
||||
assert.match(body, /回收完成 <b>\{completedCount\}<\/b>/);
|
||||
// 绑定账号缺失时的兜底文案区分群主与外部KOC
|
||||
assert.match(body, /群主合作方无需绑定 KOC 资源账号/);
|
||||
});
|
||||
|
||||
test("工作台:按 id 挂载 KOC 详情,操作刷新后内容自动更新", () => {
|
||||
assert.match(source, /const \[detailPartnerId, setDetailPartnerId\] = useState<string \| null>\(null\);/);
|
||||
assert.match(
|
||||
source,
|
||||
/data\.partners\.find\(\(partner\) => partner\.id === detailPartnerId\)/,
|
||||
);
|
||||
assert.match(source, /item\.partner_id === partnerRow\.id/);
|
||||
assert.match(source, /<KocDetailModal/);
|
||||
});
|
||||
|
||||
test("工作台最近分发:行可点开分发详情,合作方可点开 KOC 详情", () => {
|
||||
const start = source.indexOf("function OverviewPage");
|
||||
const body = source.slice(start, source.indexOf("function OwnerLinkRow"));
|
||||
assert.match(body, /onOpenDetail=\{onOpenDetail\}/);
|
||||
assert.match(body, /onOpenPartner=\{onOpenPartner\}/);
|
||||
});
|
||||
|
||||
test("分发表/截图回收表:合作方名为 KOC 详情入口且不触发行点击", () => {
|
||||
const tableStart = source.indexOf("function DistributionTable");
|
||||
const tableBody = source.slice(tableStart, source.indexOf("type AdminPreviewImage"));
|
||||
assert.match(tableBody, /onOpenPartner\?: \(partnerId: string\) => void;/);
|
||||
assert.match(tableBody, /className="koc-link"/);
|
||||
assert.match(tableBody, /event\.stopPropagation\(\);\s*onOpenPartner\(item\.partner_id\)/);
|
||||
|
||||
const shotStart = source.indexOf("function ScreenshotTaskTable");
|
||||
const shotBody = source.slice(shotStart, source.indexOf("const RESOURCE_PAGE_SIZE"));
|
||||
assert.match(shotBody, /onOpenPartner\?: \(partnerId: string\) => void;/);
|
||||
assert.match(shotBody, /onOpenPartner\(item\.partner_id\)/);
|
||||
});
|
||||
|
||||
test("数据回收页:回收队列账号名与截图回收合作方均可点开 KOC 详情", () => {
|
||||
const start = source.indexOf("function RecoveryPage");
|
||||
const body = source.slice(start);
|
||||
assert.match(body, /onOpenPartner: \(partnerId: string\) => void;/);
|
||||
// 回收队列:账号名(待识别账号兜底)为入口,且阻断行点击冒泡
|
||||
assert.match(body, /\{item\.account_nickname \|\| "待识别账号"\}\s*<\/button>/);
|
||||
assert.match(
|
||||
body,
|
||||
/event\.stopPropagation\(\);\s*onOpenPartner\(item\.partner_id\)/,
|
||||
);
|
||||
// 截图回收表透传
|
||||
assert.match(body, /<ScreenshotTaskTable\s+distributions=\{taskDistributions\}\s+onOpenPartner=\{onOpenPartner\}/);
|
||||
});
|
||||
|
||||
test("合作方页:合作方名称单元格可点开 KOC 详情", () => {
|
||||
const start = source.indexOf("function PartnersPage");
|
||||
const body = source.slice(start, source.indexOf("function ResourcesPage"));
|
||||
assert.match(body, /onOpenPartner: \(partner: Partner\) => void;/);
|
||||
assert.match(body, /className="partner-name-cell"/);
|
||||
assert.match(body, /onClick=\{\(\) => onOpenPartner\(partner\)\}/);
|
||||
});
|
||||
|
||||
test("分发详情弹窗:头部合作方可跳转 KOC 详情", () => {
|
||||
const start = source.indexOf("function DistributionDetailModal");
|
||||
const body = source.slice(start, source.indexOf("function KocDetailModal"));
|
||||
assert.match(body, /onOpenPartner\?: \(partnerId: string\) => void;/);
|
||||
assert.match(body, /detail-meta-koc/);
|
||||
assert.match(body, /onOpenPartner\(item\.partner_id\)/);
|
||||
});
|
||||
|
||||
test("KOC 详情样式:入口链接与历史记录列表", () => {
|
||||
const css = readFileSync(new URL("../app/globals.css", import.meta.url), "utf8");
|
||||
assert.match(css, /^\.koc-link \{/m);
|
||||
assert.match(css, /^\.partner-name-cell \{/m);
|
||||
assert.match(css, /^\.koc-history-list \{/m);
|
||||
assert.match(css, /^\.koc-summary-strip \{/m);
|
||||
});
|
||||
Reference in New Issue
Block a user