95 lines
2.1 KiB
TypeScript
95 lines
2.1 KiB
TypeScript
import type { TaskReportRow } from "./mvp-db";
|
|
|
|
const CSV_HEADERS = [
|
|
"任务ID",
|
|
"任务名称",
|
|
"任务类型",
|
|
"品牌",
|
|
"平台",
|
|
"所属项目",
|
|
"任务状态",
|
|
"计划数量",
|
|
"领取数",
|
|
"发布数",
|
|
"完成数",
|
|
"完成率",
|
|
"截止日期",
|
|
"创建时间",
|
|
"曝光量合计",
|
|
"阅读量合计",
|
|
"D2点赞",
|
|
"D2评论",
|
|
"D2收藏",
|
|
"D5点赞",
|
|
"D5评论",
|
|
"D5收藏",
|
|
"D7点赞",
|
|
"D7评论",
|
|
"D7收藏",
|
|
"最新点赞",
|
|
"最新评论",
|
|
"最新收藏",
|
|
"最新转发",
|
|
];
|
|
|
|
function taskTypeLabel(value: string) {
|
|
return value === "screenshot_collect" ? "截图采集" : "内容发布";
|
|
}
|
|
|
|
function taskStatusLabel(value: string) {
|
|
return value === "active" ? "进行中" : value === "completed" ? "已完结" : value;
|
|
}
|
|
|
|
function completionRate(row: TaskReportRow) {
|
|
if (!row.claimed_count) return "";
|
|
return `${Math.round((row.completed_count / row.claimed_count) * 100)}%`;
|
|
}
|
|
|
|
function csvCell(value: string | number | null | undefined) {
|
|
const text = value === null || value === undefined ? "" : String(value);
|
|
if (/[",\r\n]/.test(text)) return `"${text.replaceAll('"', '""')}"`;
|
|
return text;
|
|
}
|
|
|
|
export function buildTaskReportCsv(rows: TaskReportRow[]) {
|
|
const lines = [CSV_HEADERS.join(",")];
|
|
for (const row of rows) {
|
|
lines.push(
|
|
[
|
|
row.id,
|
|
row.name,
|
|
taskTypeLabel(row.task_type),
|
|
row.brand,
|
|
row.platform,
|
|
row.project_name ?? "",
|
|
taskStatusLabel(row.status),
|
|
row.quantity,
|
|
row.claimed_count,
|
|
row.published_count,
|
|
row.completed_count,
|
|
completionRate(row),
|
|
row.due_at,
|
|
row.created_at,
|
|
row.exposure_total,
|
|
row.views_total,
|
|
row.d2_likes,
|
|
row.d2_comments,
|
|
row.d2_collects,
|
|
row.d5_likes,
|
|
row.d5_comments,
|
|
row.d5_collects,
|
|
row.d7_likes,
|
|
row.d7_comments,
|
|
row.d7_collects,
|
|
row.latest_likes,
|
|
row.latest_comments,
|
|
row.latest_collects,
|
|
row.latest_shares,
|
|
]
|
|
.map(csvCell)
|
|
.join(","),
|
|
);
|
|
}
|
|
return `\uFEFF${lines.join("\r\n")}`;
|
|
}
|