/** * 跨模块共享枚举。 * 与 contracts/data-models.md 中的枚举**逐字对应**,改动必须同步契约版本。 */ export enum SourceType { /** 原创 */ Original = 'original', /** 已获授权 */ Licensed = 'licensed', /** Creative Commons */ Cc = 'cc', /** 公共领域 */ PublicDomain = 'public_domain', /** 用户上传(需审核) */ UserUpload = 'user_upload', /** 其他(须在 sourceName 说明) */ Other = 'other', } export enum PublishStatus { Draft = 'draft', Pending = 'pending', Published = 'published', Rejected = 'rejected', } export enum MotionFormat { Bvh = 'bvh', Fbx = 'fbx', Gltf = 'gltf', Glb = 'glb', KeypointsJson = 'keypoints-json', } export enum ModelFormat { Vrm = 'vrm', Glb = 'glb', Gltf = 'gltf', Fbx = 'fbx', } export enum PreprocessState { None = 'none', Running = 'running', Done = 'done', Failed = 'failed', } export enum ReviewAction { Submit = 'submit', Approve = 'approve', Reject = 'reject', Withdraw = 'withdraw', } export enum TargetType { Song = 'song', Motion = 'motion', Model = 'model', } export enum AssetKind { SongAudio = 'song-audio', SongCover = 'song-cover', Motion = 'motion', Model = 'model', Thumbnail = 'thumbnail', Keypoints = 'keypoints', } export const SOURCE_TYPE_VALUES = Object.values(SourceType) as string[]; export const PUBLISH_STATUS_VALUES = Object.values(PublishStatus) as string[]; export const MOTION_FORMAT_VALUES = Object.values(MotionFormat) as string[]; export const MODEL_FORMAT_VALUES = Object.values(ModelFormat) as string[]; export const TARGET_TYPE_VALUES = Object.values(TargetType) as string[]; /** 允许上传的扩展名 → 动作格式 */ export const MOTION_EXTENSION_MAP: Record = { '.bvh': MotionFormat.Bvh, '.fbx': MotionFormat.Fbx, '.gltf': MotionFormat.Gltf, '.glb': MotionFormat.Glb, '.json': MotionFormat.KeypointsJson, }; /** 允许上传的扩展名 → 模型格式 */ export const MODEL_EXTENSION_MAP: Record = { '.vrm': ModelFormat.Vrm, '.glb': ModelFormat.Glb, '.gltf': ModelFormat.Gltf, '.fbx': ModelFormat.Fbx, }; export const AUDIO_EXTENSIONS = ['.mp3', '.wav', '.ogg', '.m4a', '.aac', '.flac']; export const IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp']; /** * 状态机:契约 database.md §状态机。 * key = 当前状态,value = 允许流转到的状态集合。 */ export const STATUS_TRANSITIONS: Record = { [PublishStatus.Draft]: [PublishStatus.Pending, PublishStatus.Published], [PublishStatus.Pending]: [PublishStatus.Published, PublishStatus.Rejected, PublishStatus.Draft], [PublishStatus.Published]: [PublishStatus.Draft, PublishStatus.Rejected], [PublishStatus.Rejected]: [PublishStatus.Pending, PublishStatus.Draft], }; export function canTransition(from: PublishStatus, to: PublishStatus): boolean { return (STATUS_TRANSITIONS[from] ?? []).includes(to); } /** 审核动作 → 目标状态 */ export const ACTION_TARGET_STATUS: Record = { [ReviewAction.Submit]: PublishStatus.Pending, [ReviewAction.Approve]: PublishStatus.Published, [ReviewAction.Reject]: PublishStatus.Rejected, [ReviewAction.Withdraw]: PublishStatus.Draft, };