49 lines
2.0 KiB
TypeScript
49 lines
2.0 KiB
TypeScript
export type SubmissionRestrictionMode = 'none' | 'semester' | 'window'
|
|
|
|
export type SubmissionRestrictionScope = 'self' | 'all'
|
|
|
|
export interface SubmissionRestrictionPolicy {
|
|
mode: SubmissionRestrictionMode
|
|
sameSongHours: number | null
|
|
sameArtistHours: number | null
|
|
scope: SubmissionRestrictionScope
|
|
}
|
|
|
|
export interface SubmissionRestrictionSettings {
|
|
enableSubmissionRestriction?: boolean | null
|
|
sameSongRestrictionHours?: number | string | null
|
|
sameArtistRestrictionHours?: number | string | null
|
|
submissionRestrictionScope?: string | null
|
|
}
|
|
|
|
/** 归一化限制时长:非正整数一律视为未配置 */
|
|
export function normalizeRestrictionHours(value: unknown): number | null {
|
|
if (value === null || value === undefined || value === '') return null
|
|
const parsed = Number(value)
|
|
if (!Number.isFinite(parsed)) return null
|
|
const hours = Math.floor(parsed)
|
|
return hours >= 1 ? hours : null
|
|
}
|
|
|
|
/**
|
|
* 重复投稿限制口径(投稿与预检共用,两处的判定必须完全一致):
|
|
* - 开关关闭:不做任何重复投稿限制,普通用户可重复投稿已排期或已播放的歌曲
|
|
* - 开关开启且未配置时长:沿用本学期同一首歌不可重复投稿的规则
|
|
* - 开关开启且配置时长:按排期后的冷却窗口判定同一首歌 / 同一歌手
|
|
*/
|
|
export function resolveSubmissionRestrictionPolicy(
|
|
settings: SubmissionRestrictionSettings | null | undefined
|
|
): SubmissionRestrictionPolicy {
|
|
const sameSongHours = normalizeRestrictionHours(settings?.sameSongRestrictionHours)
|
|
const sameArtistHours = normalizeRestrictionHours(settings?.sameArtistRestrictionHours)
|
|
const scope: SubmissionRestrictionScope =
|
|
settings?.submissionRestrictionScope === 'self' ? 'self' : 'all'
|
|
|
|
if (!settings?.enableSubmissionRestriction) {
|
|
return { mode: 'none', sameSongHours, sameArtistHours, scope }
|
|
}
|
|
|
|
const mode: SubmissionRestrictionMode = sameSongHours || sameArtistHours ? 'window' : 'semester'
|
|
return { mode, sameSongHours, sameArtistHours, scope }
|
|
}
|