74 lines
2.2 KiB
TypeScript
74 lines
2.2 KiB
TypeScript
export type FirstPassReviewStatus = 'approved' | 'revision_required' | 'pending_review' | 'unknown'
|
|
|
|
export type FirstPassReviewStatusCount = {
|
|
status: string
|
|
count: number
|
|
}
|
|
|
|
export type FirstPassReviewSummary = {
|
|
totalUploads: number
|
|
totalApproved: number
|
|
firstPassApproved: number
|
|
rate: number | null
|
|
statusBreakdown: {
|
|
approved: number
|
|
revisionRequired: number
|
|
pendingReview: number
|
|
unknown: number
|
|
}
|
|
readAt: string
|
|
/** 作品过稿后台的增量检查状态;统计本身仍直接读取该后台。 */
|
|
syncStatus?: 'idle' | 'syncing' | 'ready' | 'error'
|
|
lastSyncedAt?: string | null
|
|
syncRowsChecked?: number
|
|
}
|
|
|
|
export function normalizeFirstPassReviewStatus(status: string): FirstPassReviewStatus {
|
|
if (status === 'approved' || status === 'revision_required' || status === 'pending_review') {
|
|
return status
|
|
}
|
|
return 'unknown'
|
|
}
|
|
|
|
/**
|
|
* 首轮通过率 = V1 审核通过作品数 / 当前已通过作品数。
|
|
*
|
|
* totalUploads 和状态拆分用于展示全部 V1 明细,不参与比率分母。
|
|
*/
|
|
export function buildFirstPassReviewSummary(
|
|
rows: FirstPassReviewStatusCount[],
|
|
totalApproved: number,
|
|
readAt = new Date(),
|
|
): FirstPassReviewSummary {
|
|
const statusBreakdown = {
|
|
approved: 0,
|
|
revisionRequired: 0,
|
|
pendingReview: 0,
|
|
unknown: 0,
|
|
}
|
|
|
|
for (const row of rows) {
|
|
const count = Math.max(0, Number(row.count) || 0)
|
|
const normalizedStatus = normalizeFirstPassReviewStatus(row.status)
|
|
if (normalizedStatus === 'approved') statusBreakdown.approved += count
|
|
else if (normalizedStatus === 'revision_required') statusBreakdown.revisionRequired += count
|
|
else if (normalizedStatus === 'pending_review') statusBreakdown.pendingReview += count
|
|
else statusBreakdown.unknown += count
|
|
}
|
|
|
|
const totalUploads = Object.values(statusBreakdown).reduce((total, count) => total + count, 0)
|
|
const approvedDenominator = Math.max(0, Number(totalApproved) || 0)
|
|
const firstPassApproved = statusBreakdown.approved
|
|
|
|
return {
|
|
totalUploads,
|
|
totalApproved: approvedDenominator,
|
|
firstPassApproved,
|
|
rate: approvedDenominator === 0
|
|
? null
|
|
: Math.round((firstPassApproved / approvedDenominator) * 1000) / 10,
|
|
statusBreakdown,
|
|
readAt: readAt.toISOString(),
|
|
}
|
|
}
|