153 lines
5.0 KiB
TypeScript
153 lines
5.0 KiB
TypeScript
export type JsonValue = any;
|
|
export type JsonRecord = Record<string, JsonValue>;
|
|
|
|
export interface VideoPromptSchemaFieldConfig {
|
|
key: string;
|
|
label: string;
|
|
type?: string;
|
|
enabled: boolean;
|
|
editable: boolean;
|
|
maxLength?: number;
|
|
}
|
|
|
|
export interface VideoPromptSchemaSectionConfig extends VideoPromptSchemaFieldConfig {
|
|
contentKey?: string;
|
|
itemFields: VideoPromptSchemaFieldConfig[];
|
|
children: VideoPromptSchemaFieldConfig[];
|
|
}
|
|
|
|
function isRecord(value: unknown): value is JsonRecord {
|
|
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
}
|
|
|
|
function readString(source: JsonRecord, ...keys: string[]): string {
|
|
for (const key of keys) {
|
|
const value = source[key];
|
|
if (value !== undefined && value !== null && String(value).trim() !== '') return String(value);
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function readBool(source: JsonRecord, defaultValue: boolean, ...keys: string[]): boolean {
|
|
for (const key of keys) {
|
|
const value = source[key];
|
|
if (value === true || value === false) return value;
|
|
if (value === 'true') return true;
|
|
if (value === 'false') return false;
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
function readNumber(source: JsonRecord, ...keys: string[]): number | undefined {
|
|
for (const key of keys) {
|
|
const value = source[key];
|
|
if (typeof value === 'number' && Number.isFinite(value) && value > 0) return value;
|
|
if (typeof value === 'string' && value.trim()) {
|
|
const parsed = Number(value);
|
|
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
function normalizeField(raw: unknown): VideoPromptSchemaFieldConfig | null {
|
|
if (!isRecord(raw)) return null;
|
|
const key = readString(raw, 'key');
|
|
if (!key) return null;
|
|
return {
|
|
key,
|
|
label: readString(raw, 'label') || key,
|
|
type: readString(raw, 'type') || undefined,
|
|
enabled: readBool(raw, true, 'enabled'),
|
|
editable: readBool(raw, true, 'editable'),
|
|
maxLength: readNumber(raw, 'maxLength', 'max_length'),
|
|
};
|
|
}
|
|
|
|
export function getSchemaConfigData(snapshot: unknown): JsonRecord | null {
|
|
if (!isRecord(snapshot)) return null;
|
|
const data = snapshot.data;
|
|
if (isRecord(data)) return data;
|
|
if (Array.isArray(snapshot.sections)) return snapshot;
|
|
return null;
|
|
}
|
|
|
|
export function hasSchemaConfigSnapshot(snapshot: unknown): boolean {
|
|
return !!getSchemaConfigData(snapshot);
|
|
}
|
|
|
|
export function normalizeSchemaSections(snapshot: unknown): VideoPromptSchemaSectionConfig[] {
|
|
const data = getSchemaConfigData(snapshot);
|
|
const rawSections = Array.isArray(data?.sections) ? data.sections : [];
|
|
return rawSections
|
|
.map((raw): VideoPromptSchemaSectionConfig | null => {
|
|
const base = normalizeField(raw);
|
|
if (!base || !isRecord(raw)) return null;
|
|
const children = Array.isArray(raw.children) ? raw.children.map(normalizeField).filter(Boolean) as VideoPromptSchemaFieldConfig[] : [];
|
|
const itemFields = Array.isArray(raw.itemFields)
|
|
? raw.itemFields.map(normalizeField).filter(Boolean) as VideoPromptSchemaFieldConfig[]
|
|
: Array.isArray(raw.item_fields)
|
|
? raw.item_fields.map(normalizeField).filter(Boolean) as VideoPromptSchemaFieldConfig[]
|
|
: [];
|
|
return {
|
|
...base,
|
|
contentKey: readString(raw, 'contentKey', 'content_key') || undefined,
|
|
children,
|
|
itemFields,
|
|
};
|
|
})
|
|
.filter((section): section is VideoPromptSchemaSectionConfig => !!section && section.enabled);
|
|
}
|
|
|
|
export function inferSchemaSections(schema: unknown): VideoPromptSchemaSectionConfig[] {
|
|
if (!isRecord(schema)) return [];
|
|
return Object.entries(schema)
|
|
.filter(([key]) => !['schemaVersion', 'schemaUsage', 'schema_version', 'schema_usage'].includes(key))
|
|
.map(([key, value]) => {
|
|
if (Array.isArray(value) && value.every(isRecord)) {
|
|
const fields = Array.from(new Set(value.flatMap((item) => Object.keys(item))));
|
|
return {
|
|
key,
|
|
label: key,
|
|
type: 'flow',
|
|
enabled: true,
|
|
editable: false,
|
|
itemFields: fields.filter((field) => field !== '时间段').map((field) => ({ key: field, label: field, enabled: true, editable: false })),
|
|
children: [],
|
|
} as VideoPromptSchemaSectionConfig;
|
|
}
|
|
if (isRecord(value)) {
|
|
return {
|
|
key,
|
|
label: key,
|
|
type: 'object',
|
|
enabled: true,
|
|
editable: false,
|
|
children: Object.keys(value).map((field) => ({ key: field, label: field, enabled: true, editable: false })),
|
|
itemFields: [],
|
|
} as VideoPromptSchemaSectionConfig;
|
|
}
|
|
return {
|
|
key,
|
|
label: key,
|
|
type: 'text',
|
|
enabled: true,
|
|
editable: false,
|
|
children: [],
|
|
itemFields: [],
|
|
} as VideoPromptSchemaSectionConfig;
|
|
});
|
|
}
|
|
|
|
export function stringifySchemaValue(value: JsonValue): string {
|
|
if (value === null || value === undefined) return '';
|
|
if (typeof value === 'object') {
|
|
try {
|
|
return JSON.stringify(value, null, 2);
|
|
} catch {
|
|
return String(value);
|
|
}
|
|
}
|
|
return String(value);
|
|
}
|