feat: 同步质量校验修复并精简工作台操作
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { reactive } from 'vue'
|
||||
import { validOptionalSize } from './model'
|
||||
import type { KeyframeReadiness } from './types'
|
||||
import type { QualityInput, QualityReceipt, QualityTarget, VisualValidation } from './quality.types'
|
||||
|
||||
/** 未返回的操作不显示上次成功结论;网络失败不会自动重发。 */
|
||||
const sessions = reactive<Record<string, { receipt: QualityReceipt | null; error: string }>>({})
|
||||
|
||||
/** 正式 ID 与目标类型共同隔离会话结果,批量回执按剧集隔离。 */
|
||||
export function qualityKey(projectId: string, target: QualityTarget | null) {
|
||||
return JSON.stringify([
|
||||
projectId,
|
||||
target?.kind,
|
||||
target && ('assetId' in target ? [target.shotId, target.assetId] : target.episodeNo)
|
||||
])
|
||||
}
|
||||
|
||||
/** 同一目标关闭后重新打开仍能查看本会话的回执。 */
|
||||
export function qualitySession(key: string) {
|
||||
return (sessions[key] ??= { receipt: null, error: '' })
|
||||
}
|
||||
|
||||
/** 一行一个允许文字,仅清理空白与重复,不自行添加授权内容。 */
|
||||
export function allowedTextLines(value: string) {
|
||||
return [
|
||||
...new Set(
|
||||
value
|
||||
.split('\n')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean)
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
/** 付费前独立校验整数、尺寸与剧集范围,0 次修复代表只验不修。 */
|
||||
export function validQualityInput(input: QualityInput) {
|
||||
return (
|
||||
[input.concurrency, input.limit, input.episodeNo].every(value => Number.isSafeInteger(value) && value > 0) &&
|
||||
Number.isSafeInteger(input.maxRepairAttempts) &&
|
||||
input.maxRepairAttempts >= 0 &&
|
||||
validOptionalSize(input.width ?? '', input.height ?? '')
|
||||
)
|
||||
}
|
||||
|
||||
/** 与后端保持同一优先级:全项目有过期项时先筛过期,再按当前集筛选。 */
|
||||
export function qualityTargets(readiness: KeyframeReadiness, input: QualityInput) {
|
||||
return readiness.items
|
||||
.filter(
|
||||
item =>
|
||||
item.status === 'ready' &&
|
||||
(input.force ||
|
||||
(readiness.stalePrimaryKeyframe > 0
|
||||
? item.primaryKeyframeStale === true
|
||||
: !item.primaryKeyframeId)) &&
|
||||
item.episodeNo === input.episodeNo
|
||||
)
|
||||
.slice(0, input.limit)
|
||||
}
|
||||
|
||||
/** 最小响应校验,避免畸形响应或仅 HTTP 200 被显示成视觉通过。 */
|
||||
export function isVisualValidation(value: unknown): value is VisualValidation {
|
||||
if (!value || typeof value !== 'object') return false
|
||||
const item = value as VisualValidation
|
||||
return (
|
||||
typeof item.passed === 'boolean' &&
|
||||
typeof item.summary === 'string' &&
|
||||
typeof item.subjectCountConsistent === 'boolean' &&
|
||||
Array.isArray(item.subjects) &&
|
||||
item.subjects.every(
|
||||
subject =>
|
||||
typeof subject.subjectRef === 'string' &&
|
||||
typeof subject.identityConsistent === 'boolean' &&
|
||||
typeof subject.formConsistent === 'boolean' &&
|
||||
Array.isArray(subject.issues) &&
|
||||
subject.issues.every(issue => typeof issue === 'string')
|
||||
) &&
|
||||
Array.isArray(item.issues) &&
|
||||
item.issues.every(
|
||||
issue => typeof issue.description === 'string' && ['warning', 'error'].includes(issue.severity)
|
||||
) &&
|
||||
typeof item.unauthorizedText?.detected === 'boolean' &&
|
||||
Array.isArray(item.unauthorizedText.texts)
|
||||
)
|
||||
}
|
||||
|
||||
/** 读取视频已保存的抽样校验,不为查看历史再次调用视觉模型。 */
|
||||
export function savedVideoValidation(rawJson?: string | null): VisualValidation | null {
|
||||
try {
|
||||
const value: unknown = JSON.parse(rawJson || '{}').videoValidation
|
||||
return isVisualValidation(value) ? value : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/** 识别后端修复候选标记,避免未复检候选通过普通主视频按钮绕过校验。 */
|
||||
export function videoRepairInfo(rawJson?: string | null): { attempt: number } | null {
|
||||
try {
|
||||
const repair: unknown = JSON.parse(rawJson || '{}').repair
|
||||
if (!repair || typeof repair !== 'object' || Array.isArray(repair)) return null
|
||||
const attempt = (repair as { attempt?: unknown }).attempt
|
||||
return { attempt: typeof attempt === 'number' && Number.isSafeInteger(attempt) && attempt >= 0 ? attempt : 0 }
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user