100 lines
2.8 KiB
TypeScript
100 lines
2.8 KiB
TypeScript
import { getTemplateWithFields } from './template-validator'
|
|
import { filterVisibleFieldValues, getVisibleTemplateFields, hasFieldValue } from './field-conditions'
|
|
|
|
type TemplateFieldLike = {
|
|
key: string
|
|
label?: string | null
|
|
type?: string | null
|
|
required?: boolean | null
|
|
conditions?: string | null
|
|
}
|
|
|
|
export type TemplateFieldValidationResult =
|
|
| {
|
|
valid: true
|
|
templateName?: string
|
|
templateFields: Record<string, unknown>
|
|
visibleFieldKeys: string[]
|
|
}
|
|
| {
|
|
valid: false
|
|
error: string
|
|
errorCode: string
|
|
details?: Record<string, unknown>
|
|
}
|
|
|
|
export { hasFieldValue } from './field-conditions'
|
|
|
|
export async function validateSubmittedTemplateFields(args: {
|
|
templateId: string | null | undefined
|
|
templateFields: Record<string, unknown>
|
|
allowUnknownKeys?: boolean
|
|
}): Promise<TemplateFieldValidationResult> {
|
|
const { templateId, templateFields, allowUnknownKeys = true } = args
|
|
|
|
if (!templateId) {
|
|
return {
|
|
valid: true,
|
|
templateFields,
|
|
visibleFieldKeys: Object.keys(templateFields),
|
|
}
|
|
}
|
|
|
|
const template = await getTemplateWithFields(templateId)
|
|
if (!template) {
|
|
return {
|
|
valid: false,
|
|
error: '模板不存在或不可用',
|
|
errorCode: 'TEMPLATE_NOT_FOUND',
|
|
}
|
|
}
|
|
|
|
const fields = (template.fields || []) as TemplateFieldLike[]
|
|
const fieldMap = new Map(fields.map((field) => [field.key, field]))
|
|
const visibleFields = getVisibleTemplateFields(fields, templateFields)
|
|
const visibleTemplateFields = filterVisibleFieldValues(fields, templateFields)
|
|
|
|
if (!allowUnknownKeys) {
|
|
const unknownKeys = Object.keys(templateFields).filter((key) => !fieldMap.has(key))
|
|
if (unknownKeys.length > 0) {
|
|
return {
|
|
valid: false,
|
|
error: `提交了模板中不存在的字段:${unknownKeys.join(', ')}`,
|
|
errorCode: 'UNKNOWN_TEMPLATE_FIELDS',
|
|
details: {
|
|
unknownKeys,
|
|
templateId,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
const missingRequiredFields = visibleFields
|
|
.filter((field) => field.required)
|
|
.filter((field) => !hasFieldValue(visibleTemplateFields[field.key], field.type))
|
|
.map((field) => ({
|
|
key: field.key,
|
|
label: field.label || field.key,
|
|
type: field.type || 'text',
|
|
}))
|
|
|
|
if (missingRequiredFields.length > 0) {
|
|
return {
|
|
valid: false,
|
|
error: `模板必填字段未填写:${missingRequiredFields.map((field) => field.label).join('、')}`,
|
|
errorCode: 'TEMPLATE_REQUIRED_FIELDS_MISSING',
|
|
details: {
|
|
templateId,
|
|
missingRequiredFields,
|
|
},
|
|
}
|
|
}
|
|
|
|
return {
|
|
valid: true,
|
|
templateName: typeof template.name === 'string' ? template.name : undefined,
|
|
templateFields: visibleTemplateFields,
|
|
visibleFieldKeys: visibleFields.map((field) => field.key),
|
|
}
|
|
}
|