表单是低代码平台中最常用的组件之一,用于数据收集、编辑和提交。本章将详细介绍如何设计和实现一个强大的表单引擎,支持动态表单生成、复杂验证规则、条件显示逻辑等高级特性。

7.1 表单引擎架构概览

7.1.1 整体架构设计

// 表单引擎接口
interface FormEngine {
  // 表单管理
  createForm(config: FormConfig): Promise<Form>;
  getForm(id: string): Form | null;
  updateForm(id: string, config: Partial<FormConfig>): Promise<void>;
  deleteForm(id: string): Promise<void>;
  
  // 表单渲染
  renderForm(formId: string, container: HTMLElement): Promise<FormRenderer>;
  
  // 表单验证
  validateForm(formId: string): Promise<ValidationResult>;
  
  // 表单数据
  getFormData(formId: string): any;
  setFormData(formId: string, data: any): Promise<void>;
  
  // 事件处理
  on(event: string, handler: Function): void;
  off(event: string, handler: Function): void;
  emit(event: string, data: any): void;
}

// 表单引擎实现
class LowCodeFormEngine implements FormEngine {
  private forms: Map<string, Form> = new Map();
  private renderers: Map<string, FormRenderer> = new Map();
  private fieldRegistry: FieldRegistry;
  private validationEngine: FormValidationEngine;
  private dataEngine: DataEngine;
  private eventBus: EventBus;
  
  constructor(config: FormEngineConfig) {
    this.fieldRegistry = new FieldRegistry(config.fields || []);
    this.validationEngine = new FormValidationEngine(config.validation || {});
    this.dataEngine = config.dataEngine;
    this.eventBus = new EventBus();
    
    this.initializeBuiltinFields();
  }
  
  async createForm(config: FormConfig): Promise<Form> {
    // 验证配置
    this.validateFormConfig(config);
    
    // 创建表单实例
    const form = new Form({
      ...config,
      engine: this,
      fieldRegistry: this.fieldRegistry,
      validationEngine: this.validationEngine,
      dataEngine: this.dataEngine
    });
    
    // 初始化表单
    await form.initialize();
    
    // 注册表单
    this.forms.set(form.id, form);
    
    // 触发事件
    this.emit('form:created', { form });
    
    return form;
  }
  
  getForm(id: string): Form | null {
    return this.forms.get(id) || null;
  }
  
  async updateForm(id: string, config: Partial<FormConfig>): Promise<void> {
    const form = this.getForm(id);
    if (!form) {
      throw new Error(`表单未找到: ${id}`);
    }
    
    await form.update(config);
    this.emit('form:updated', { form, config });
  }
  
  async deleteForm(id: string): Promise<void> {
    const form = this.getForm(id);
    if (!form) {
      return;
    }
    
    // 清理渲染器
    const renderer = this.renderers.get(id);
    if (renderer) {
      await renderer.destroy();
      this.renderers.delete(id);
    }
    
    // 销毁表单
    await form.destroy();
    this.forms.delete(id);
    
    this.emit('form:deleted', { formId: id });
  }
  
  async renderForm(formId: string, container: HTMLElement): Promise<FormRenderer> {
    const form = this.getForm(formId);
    if (!form) {
      throw new Error(`表单未找到: ${formId}`);
    }
    
    // 创建渲染器
    const renderer = new FormRenderer({
      form,
      container,
      fieldRegistry: this.fieldRegistry,
      eventBus: this.eventBus
    });
    
    // 渲染表单
    await renderer.render();
    
    // 注册渲染器
    this.renderers.set(formId, renderer);
    
    return renderer;
  }
  
  async validateForm(formId: string): Promise<ValidationResult> {
    const form = this.getForm(formId);
    if (!form) {
      throw new Error(`表单未找到: ${formId}`);
    }
    
    return await form.validate();
  }
  
  getFormData(formId: string): any {
    const form = this.getForm(formId);
    if (!form) {
      throw new Error(`表单未找到: ${formId}`);
    }
    
    return form.getData();
  }
  
  async setFormData(formId: string, data: any): Promise<void> {
    const form = this.getForm(formId);
    if (!form) {
      throw new Error(`表单未找到: ${formId}`);
    }
    
    await form.setData(data);
  }
  
  // 事件处理
  on(event: string, handler: Function): void {
    this.eventBus.on(event, handler);
  }
  
  off(event: string, handler: Function): void {
    this.eventBus.off(event, handler);
  }
  
  emit(event: string, data: any): void {
    this.eventBus.emit(event, data);
  }
  
  // 验证表单配置
  private validateFormConfig(config: FormConfig): void {
    if (!config.id) {
      throw new Error('表单ID不能为空');
    }
    
    if (!config.fields || config.fields.length === 0) {
      throw new Error('表单字段不能为空');
    }
    
    // 验证字段配置
    config.fields.forEach(field => {
      if (!field.name) {
        throw new Error('字段名称不能为空');
      }
      
      if (!field.type) {
        throw new Error(`字段 ${field.name} 的类型不能为空`);
      }
      
      if (!this.fieldRegistry.hasField(field.type)) {
        throw new Error(`未知的字段类型: ${field.type}`);
      }
    });
  }
  
  // 初始化内置字段
  private initializeBuiltinFields(): void {
    // 注册内置字段类型
    this.fieldRegistry.register(new TextFieldDefinition());
    this.fieldRegistry.register(new NumberFieldDefinition());
    this.fieldRegistry.register(new EmailFieldDefinition());
    this.fieldRegistry.register(new PasswordFieldDefinition());
    this.fieldRegistry.register(new TextareaFieldDefinition());
    this.fieldRegistry.register(new SelectFieldDefinition());
    this.fieldRegistry.register(new CheckboxFieldDefinition());
    this.fieldRegistry.register(new RadioFieldDefinition());
    this.fieldRegistry.register(new DateFieldDefinition());
    this.fieldRegistry.register(new FileFieldDefinition());
    this.fieldRegistry.register(new SwitchFieldDefinition());
    this.fieldRegistry.register(new SliderFieldDefinition());
    this.fieldRegistry.register(new RateFieldDefinition());
    this.fieldRegistry.register(new ColorFieldDefinition());
    this.fieldRegistry.register(new CascaderFieldDefinition());
    this.fieldRegistry.register(new TreeSelectFieldDefinition());
    this.fieldRegistry.register(new TransferFieldDefinition());
    this.fieldRegistry.register(new UploadFieldDefinition());
  }
}

7.6 完整使用示例

7.6.1 表单引擎集成示例

// 完整的表单引擎使用示例
class LowCodeFormEngineDemo {
  private formEngine: LowCodeFormEngine;
  private eventBus: EventBus;
  private container: HTMLElement;
  
  constructor(container: HTMLElement) {
    this.container = container;
    this.eventBus = new EventBus();
    this.formEngine = new LowCodeFormEngine({
      eventBus: this.eventBus,
      validationEnabled: true,
      autoSave: true,
      autoSaveInterval: 5000
    });
    
    this.initializeDemo();
  }
  
  private async initializeDemo(): Promise<void> {
    // 创建用户注册表单
    await this.createUserRegistrationForm();
    
    // 创建产品信息表单
    await this.createProductForm();
    
    // 绑定事件监听
    this.bindEvents();
  }
  
  private async createUserRegistrationForm(): Promise<void> {
    // 创建表单配置
    const formConfig: FormConfig = {
      id: 'user-registration',
      title: '用户注册',
      description: '请填写以下信息完成注册',
      layout: {
        type: LayoutType.GRID,
        columns: 2,
        gap: '16px',
        responsive: true,
        breakpoints: {
          xs: 1,
          sm: 1,
          md: 2,
          lg: 2,
          xl: 2
        }
      },
      submitUrl: '/api/users/register',
      method: 'POST'
    };
    
    // 创建表单
    const form = await this.formEngine.createForm(formConfig);
    
    // 添加用户名字段
    const usernameField = await this.formEngine.createField({
      name: 'username',
      type: FieldType.TEXT,
      label: '用户名',
      placeholder: '请输入用户名',
      required: true,
      gridColumn: 'span 2'
    });
    
    // 添加验证规则
    const validationEngine = new FormValidationEngine(form);
    validationEngine.addRule('username', {
      type: ValidationRuleType.REQUIRED,
      message: '用户名不能为空'
    });
    validationEngine.addRule('username', {
      type: ValidationRuleType.MIN_LENGTH,
      value: 3,
      message: '用户名至少需要3个字符'
    });
    validationEngine.addRule('username', {
      type: ValidationRuleType.PATTERN,
      value: /^[a-zA-Z0-9_]+$/,
      message: '用户名只能包含字母、数字和下划线'
    });
    
    form.addField(usernameField);
    
    // 添加邮箱字段
    const emailField = await this.formEngine.createField({
      name: 'email',
      type: FieldType.TEXT,
      label: '邮箱地址',
      placeholder: '请输入邮箱地址',
      required: true
    });
    
    validationEngine.addRule('email', {
      type: ValidationRuleType.REQUIRED,
      message: '邮箱地址不能为空'
    });
    validationEngine.addRule('email', {
      type: ValidationRuleType.EMAIL,
      message: '请输入有效的邮箱地址'
    });
    
    form.addField(emailField);
    
    // 添加手机号字段
    const phoneField = await this.formEngine.createField({
      name: 'phone',
      type: FieldType.TEXT,
      label: '手机号码',
      placeholder: '请输入手机号码',
      required: true
    });
    
    validationEngine.addRule('phone', {
      type: ValidationRuleType.REQUIRED,
      message: '手机号码不能为空'
    });
    validationEngine.addRule('phone', {
      type: ValidationRuleType.CUSTOM,
      message: '请输入有效的手机号码',
      validator: (value: string) => {
        const phoneRegex = /^1[3-9]\d{9}$/;
        return phoneRegex.test(value);
      }
    });
    
    form.addField(phoneField);
    
    // 添加密码字段
    const passwordField = await this.formEngine.createField({
      name: 'password',
      type: FieldType.PASSWORD,
      label: '密码',
      placeholder: '请输入密码',
      required: true,
      gridColumn: 'span 2'
    });
    
    validationEngine.addRule('password', {
      type: ValidationRuleType.REQUIRED,
      message: '密码不能为空'
    });
    validationEngine.addRule('password', {
      type: ValidationRuleType.MIN_LENGTH,
      value: 8,
      message: '密码至少需要8个字符'
    });
    validationEngine.addRule('password', {
      type: ValidationRuleType.PATTERN,
      value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/,
      message: '密码必须包含大小写字母和数字'
    });
    
    form.addField(passwordField);
    
    // 添加确认密码字段
    const confirmPasswordField = await this.formEngine.createField({
      name: 'confirmPassword',
      type: FieldType.PASSWORD,
      label: '确认密码',
      placeholder: '请再次输入密码',
      required: true,
      gridColumn: 'span 2'
    });
    
    validationEngine.addRule('confirmPassword', {
      type: ValidationRuleType.REQUIRED,
      message: '确认密码不能为空'
    });
    validationEngine.addRule('confirmPassword', {
      type: ValidationRuleType.CUSTOM,
      message: '两次输入的密码不一致',
      validator: (value: string) => {
        const password = form.getFieldValue('password');
        return value === password;
      }
    });
    
    form.addField(confirmPasswordField);
    
    // 添加性别字段
    const genderField = await this.formEngine.createField({
      name: 'gender',
      type: FieldType.SELECT,
      label: '性别',
      options: [
        { value: 'male', label: '男' },
        { value: 'female', label: '女' },
        { value: 'other', label: '其他' }
      ],
      required: true
    });
    
    form.addField(genderField);
    
    // 添加生日字段
    const birthdayField = await this.formEngine.createField({
      name: 'birthday',
      type: FieldType.DATE,
      label: '生日',
      required: false
    });
    
    form.addField(birthdayField);
    
    // 添加头像上传字段
    const avatarField = await this.formEngine.createField({
      name: 'avatar',
      type: FieldType.FILE,
      label: '头像',
      accept: 'image/*',
      maxSize: 2 * 1024 * 1024, // 2MB
      gridColumn: 'span 2'
    });
    
    form.addField(avatarField);
    
    // 渲染表单
    const formContainer = document.createElement('div');
    formContainer.className = 'form-container';
    this.container.appendChild(formContainer);
    
    await this.formEngine.renderForm(form.id, formContainer);
  }
  
  private async createProductForm(): Promise<void> {
    // 创建产品表单配置
    const formConfig: FormConfig = {
      id: 'product-form',
      title: '产品信息',
      description: '请填写产品的详细信息',
      layout: {
        type: LayoutType.TABS
      },
      submitUrl: '/api/products',
      method: 'POST'
    };
    
    // 创建表单
    const form = await this.formEngine.createForm(formConfig);
    
    // 基本信息标签页
    const basicInfoTab = {
      id: 'basic-info',
      title: '基本信息',
      fields: [
        {
          name: 'name',
          type: FieldType.TEXT,
          label: '产品名称',
          required: true
        },
        {
          name: 'category',
          type: FieldType.SELECT,
          label: '产品分类',
          options: [
            { value: 'electronics', label: '电子产品' },
            { value: 'clothing', label: '服装' },
            { value: 'books', label: '图书' },
            { value: 'home', label: '家居用品' }
          ],
          required: true
        },
        {
          name: 'price',
          type: FieldType.NUMBER,
          label: '价格',
          required: true
        },
        {
          name: 'description',
          type: FieldType.TEXTAREA,
          label: '产品描述',
          rows: 4
        }
      ]
    };
    
    // 详细信息标签页
    const detailInfoTab = {
      id: 'detail-info',
      title: '详细信息',
      fields: [
        {
          name: 'specifications',
          type: FieldType.TEXTAREA,
          label: '产品规格',
          rows: 6
        },
        {
          name: 'images',
          type: FieldType.FILE,
          label: '产品图片',
          accept: 'image/*',
          multiple: true,
          maxCount: 5
        },
        {
          name: 'tags',
          type: FieldType.TEXT,
          label: '标签',
          placeholder: '用逗号分隔多个标签'
        }
      ]
    };
    
    // 添加字段到表单
    for (const tab of [basicInfoTab, detailInfoTab]) {
      for (const fieldConfig of tab.fields) {
        const field = await this.formEngine.createField(fieldConfig);
        form.addField(field);
      }
    }
    
    // 渲染表单
    const formContainer = document.createElement('div');
    formContainer.className = 'form-container';
    formContainer.style.marginTop = '32px';
    this.container.appendChild(formContainer);
    
    await this.formEngine.renderForm(form.id, formContainer);
  }
  
  private bindEvents(): void {
    // 监听表单提交成功
    this.eventBus.on('form:submitSuccess', (event) => {
      console.log('表单提交成功:', event.result);
      this.showMessage('表单提交成功!', 'success');
    });
    
    // 监听表单提交失败
    this.eventBus.on('form:submitError', (event) => {
      console.error('表单提交失败:', event.error || event.result);
      this.showMessage('表单提交失败,请检查输入信息', 'error');
    });
    
    // 监听表单验证
    this.eventBus.on('form:validated', (event) => {
      if (!event.result.valid) {
        console.log('表单验证失败:', event.result.errors);
      }
    });
    
    // 监听字段值变化
    this.eventBus.on('field:valueChanged', (event) => {
      console.log(`字段 ${event.field.name} 值变化:`, event.value);
    });
    
    // 监听表单重置
    this.eventBus.on('form:reset', (event) => {
      console.log('表单已重置:', event.form.id);
      this.showMessage('表单已重置', 'info');
    });
  }
  
  private showMessage(message: string, type: 'success' | 'error' | 'info'): void {
    const messageElement = document.createElement('div');
    messageElement.className = `message message-${type}`;
    messageElement.textContent = message;
    messageElement.style.cssText = `
      position: fixed;
      top: 20px;
      right: 20px;
      padding: 12px 24px;
      border-radius: 4px;
      color: white;
      font-weight: 500;
      z-index: 1000;
      animation: slideIn 0.3s ease-out;
    `;
    
    switch (type) {
      case 'success':
        messageElement.style.backgroundColor = '#52c41a';
        break;
      case 'error':
        messageElement.style.backgroundColor = '#ff4d4f';
        break;
      case 'info':
        messageElement.style.backgroundColor = '#1890ff';
        break;
    }
    
    document.body.appendChild(messageElement);
    
    // 3秒后自动移除
    setTimeout(() => {
      if (messageElement.parentNode) {
        messageElement.parentNode.removeChild(messageElement);
      }
    }, 3000);
  }
}

// 使用示例
const demo = new LowCodeFormEngineDemo(document.getElementById('app')!);

7.7 本章小结

在本章中,我们深入学习了低代码平台中表单引擎与动态表单的实现。通过系统性的架构设计和详细的代码实现,我们构建了一个功能完整、扩展性强的表单系统。

7.7.1 核心要点回顾

表单引擎架构: - 采用模块化设计,包含表单管理、字段管理、渲染引擎、验证引擎等核心模块 - 基于事件驱动架构,实现组件间的松耦合通信 - 支持插件化扩展,可以灵活添加新的字段类型和功能

动态表单字段: - 实现了文本、密码、数字、选择、日期、文件等多种字段类型 - 每个字段都支持完整的生命周期管理和事件处理 - 提供统一的字段接口,便于扩展新的字段类型

表单渲染引擎: - 支持多种布局方式:垂直、水平、网格、标签页、手风琴 - 实现响应式布局,适配不同屏幕尺寸 - 提供灵活的样式定制和主题支持

表单验证引擎: - 内置常用验证规则:必填、长度、格式、数值范围等 - 支持自定义验证器和异步验证 - 提供实时验证和批量验证功能

7.7.2 技术特色

  1. 类型安全:使用 TypeScript 提供完整的类型定义和检查
  2. 事件驱动:基于事件总线实现组件间通信,提高系统的可维护性
  3. 插件化架构:支持字段类型、验证器、布局引擎的插件化扩展
  4. 响应式设计:支持多种布局方式和响应式适配
  5. 性能优化:实现字段的懒加载和按需渲染

7.7.3 最佳实践

  1. 字段设计:遵循单一职责原则,每个字段专注于特定的数据类型
  2. 验证策略:结合前端验证和后端验证,确保数据安全性
  3. 用户体验:提供实时反馈、错误提示和操作引导
  4. 性能考虑:对于大型表单,采用虚拟滚动和分页加载
  5. 可访问性:遵循 WCAG 标准,支持键盘导航和屏幕阅读器

7.7.4 扩展方向

  1. 高级字段类型:富文本编辑器、代码编辑器、地图选择器等
  2. 表单模板:预定义的表单模板和快速生成工具
  3. 数据联动:字段间的依赖关系和联动更新
  4. 表单分析:用户行为分析和表单优化建议
  5. 国际化支持:多语言表单和本地化适配

通过本章的学习,我们掌握了表单引擎的核心技术和实现方法。在下一章中,我们将学习工作流引擎与流程管理,了解如何在低代码平台中实现复杂的业务流程自动化。

// 表单配置 interface FormConfig { id: string; name: string; title?: string; description?: string; fields: FieldConfig[]; layout?: FormLayout; validation?: FormValidationConfig; submission?: FormSubmissionConfig; styling?: FormStylingConfig; behavior?: FormBehaviorConfig; dataSource?: DataSourceConfig; }

// 表单引擎配置 interface FormEngineConfig { fields?: FieldDefinition[]; validation?: ValidationEngineConfig; dataEngine: DataEngine; }


### 7.1.2 核心数据结构

```typescript
// 表单类
class Form {
  public readonly id: string;
  public readonly name: string;
  public title?: string;
  public description?: string;
  
  private fields: Map<string, FormField> = new Map();
  private data: any = {};
  private errors: Map<string, string[]> = new Map();
  private config: FormConfig;
  private engine: FormEngine;
  private fieldRegistry: FieldRegistry;
  private validationEngine: FormValidationEngine;
  private dataEngine: DataEngine;
  private eventBus: EventBus;
  
  constructor(options: FormOptions) {
    this.id = options.id;
    this.name = options.name;
    this.title = options.title;
    this.description = options.description;
    this.config = options.config;
    this.engine = options.engine;
    this.fieldRegistry = options.fieldRegistry;
    this.validationEngine = options.validationEngine;
    this.dataEngine = options.dataEngine;
    this.eventBus = new EventBus();
  }
  
  async initialize(): Promise<void> {
    // 创建字段实例
    for (const fieldConfig of this.config.fields) {
      const fieldDefinition = this.fieldRegistry.getField(fieldConfig.type);
      if (!fieldDefinition) {
        throw new Error(`未知的字段类型: ${fieldConfig.type}`);
      }
      
      const field = new FormField({
        config: fieldConfig,
        definition: fieldDefinition,
        form: this,
        validationEngine: this.validationEngine
      });
      
      await field.initialize();
      this.fields.set(field.name, field);
    }
    
    // 初始化数据
    this.initializeData();
    
    // 设置字段依赖关系
    this.setupFieldDependencies();
    
    // 绑定数据源
    if (this.config.dataSource) {
      await this.bindDataSource();
    }
  }
  
  async update(config: Partial<FormConfig>): Promise<void> {
    // 更新配置
    this.config = { ...this.config, ...config };
    
    // 重新初始化
    await this.initialize();
    
    this.emit('form:updated', { form: this });
  }
  
  async validate(): Promise<ValidationResult> {
    const errors: ValidationError[] = [];
    
    // 验证所有字段
    for (const field of this.fields.values()) {
      const fieldResult = await field.validate();
      if (!fieldResult.valid) {
        errors.push(...fieldResult.errors);
      }
    }
    
    // 表单级验证
    if (this.config.validation?.rules) {
      const formResult = await this.validationEngine.validateForm(
        this.data,
        this.config.validation.rules
      );
      
      if (!formResult.valid) {
        errors.push(...formResult.errors);
      }
    }
    
    // 更新错误状态
    this.updateErrors(errors);
    
    const result = {
      valid: errors.length === 0,
      errors
    };
    
    this.emit('form:validated', { form: this, result });
    
    return result;
  }
  
  getData(): any {
    const data: any = {};
    
    for (const field of this.fields.values()) {
      if (field.isVisible() && !field.isDisabled()) {
        this.setNestedValue(data, field.name, field.getValue());
      }
    }
    
    return data;
  }
  
  async setData(data: any): Promise<void> {
    this.data = { ...data };
    
    // 更新字段值
    for (const field of this.fields.values()) {
      const value = this.getNestedValue(data, field.name);
      if (value !== undefined) {
        await field.setValue(value);
      }
    }
    
    this.emit('form:dataChanged', { form: this, data });
  }
  
  getField(name: string): FormField | null {
    return this.fields.get(name) || null;
  }
  
  getFields(): FormField[] {
    return Array.from(this.fields.values());
  }
  
  async submit(): Promise<SubmissionResult> {
    // 验证表单
    const validation = await this.validate();
    if (!validation.valid) {
      return {
        success: false,
        errors: validation.errors
      };
    }
    
    // 获取提交数据
    const data = this.getData();
    
    // 执行提交逻辑
    if (this.config.submission) {
      try {
        const result = await this.executeSubmission(data);
        this.emit('form:submitted', { form: this, data, result });
        return result;
      } catch (error) {
        const result = {
          success: false,
          error: error.message
        };
        this.emit('form:submitError', { form: this, data, error });
        return result;
      }
    }
    
    // 默认成功
    const result = { success: true, data };
    this.emit('form:submitted', { form: this, data, result });
    return result;
  }
  
  async reset(): Promise<void> {
    // 重置所有字段
    for (const field of this.fields.values()) {
      await field.reset();
    }
    
    // 清除错误
    this.errors.clear();
    
    // 重新初始化数据
    this.initializeData();
    
    this.emit('form:reset', { form: this });
  }
  
  async destroy(): Promise<void> {
    // 销毁所有字段
    for (const field of this.fields.values()) {
      await field.destroy();
    }
    
    this.fields.clear();
    this.errors.clear();
    
    this.emit('form:destroyed', { form: this });
  }
  
  // 事件处理
  on(event: string, handler: Function): void {
    this.eventBus.on(event, handler);
  }
  
  off(event: string, handler: Function): void {
    this.eventBus.off(event, handler);
  }
  
  emit(event: string, data: any): void {
    this.eventBus.emit(event, data);
  }
  
  // 私有方法
  private initializeData(): void {
    this.data = {};
    
    for (const field of this.fields.values()) {
      const defaultValue = field.getDefaultValue();
      if (defaultValue !== undefined) {
        this.setNestedValue(this.data, field.name, defaultValue);
      }
    }
  }
  
  private setupFieldDependencies(): void {
    for (const field of this.fields.values()) {
      const dependencies = field.getDependencies();
      
      for (const dependency of dependencies) {
        const dependentField = this.getField(dependency);
        if (dependentField) {
          dependentField.on('value:changed', () => {
            field.updateVisibility();
            field.updateDisabled();
            field.updateOptions();
          });
        }
      }
    }
  }
  
  private async bindDataSource(): Promise<void> {
    if (!this.config.dataSource) {
      return;
    }
    
    try {
      const data = await this.dataEngine.query(
        this.config.dataSource.id,
        this.config.dataSource.params
      );
      
      if (data) {
        await this.setData(data);
      }
    } catch (error) {
      console.error('数据源绑定失败:', error);
    }
  }
  
  private async executeSubmission(data: any): Promise<SubmissionResult> {
    const submission = this.config.submission!;
    
    switch (submission.type) {
      case 'api':
        return await this.submitToApi(data, submission.config as ApiSubmissionConfig);
      case 'dataSource':
        return await this.submitToDataSource(data, submission.config as DataSourceSubmissionConfig);
      case 'custom':
        return await this.submitCustom(data, submission.config as CustomSubmissionConfig);
      default:
        throw new Error(`未知的提交类型: ${submission.type}`);
    }
  }
  
  private async submitToApi(data: any, config: ApiSubmissionConfig): Promise<SubmissionResult> {
    const response = await fetch(config.url, {
      method: config.method || 'POST',
      headers: {
        'Content-Type': 'application/json',
        ...config.headers
      },
      body: JSON.stringify(data)
    });
    
    if (!response.ok) {
      throw new Error(`API提交失败: ${response.statusText}`);
    }
    
    const result = await response.json();
    return {
      success: true,
      data: result
    };
  }
  
  private async submitToDataSource(data: any, config: DataSourceSubmissionConfig): Promise<SubmissionResult> {
    const result = await this.dataEngine.execute(config.dataSourceId, {
      operation: config.operation || 'create',
      data
    });
    
    return {
      success: result.success,
      data: result.data,
      error: result.error
    };
  }
  
  private async submitCustom(data: any, config: CustomSubmissionConfig): Promise<SubmissionResult> {
    return await config.handler(data, this);
  }
  
  private updateErrors(errors: ValidationError[]): void {
    this.errors.clear();
    
    for (const error of errors) {
      const fieldErrors = this.errors.get(error.field) || [];
      fieldErrors.push(error.message);
      this.errors.set(error.field, fieldErrors);
    }
  }
  
  private getNestedValue(obj: any, path: string): any {
    const keys = path.split('.');
    let current = obj;
    
    for (const key of keys) {
      if (current === null || current === undefined) {
        return undefined;
      }
      current = current[key];
    }
    
    return current;
  }
  
  private setNestedValue(obj: any, path: string, value: any): void {
    const keys = path.split('.');
    let current = obj;
    
    for (let i = 0; i < keys.length - 1; i++) {
      const key = keys[i];
      if (!(key in current) || typeof current[key] !== 'object') {
        current[key] = {};
      }
      current = current[key];
    }
    
    current[keys[keys.length - 1]] = value;
  }
}

// 表单选项
interface FormOptions {
  id: string;
  name: string;
  title?: string;
  description?: string;
  config: FormConfig;
  engine: FormEngine;
  fieldRegistry: FieldRegistry;
  validationEngine: FormValidationEngine;
  dataEngine: DataEngine;
}

// 提交结果
interface SubmissionResult {
  success: boolean;
  data?: any;
  error?: string;
  errors?: ValidationError[];
}

// 提交配置
interface FormSubmissionConfig {
  type: 'api' | 'dataSource' | 'custom';
  config: ApiSubmissionConfig | DataSourceSubmissionConfig | CustomSubmissionConfig;
}

interface ApiSubmissionConfig {
  url: string;
  method?: string;
  headers?: Record<string, string>;
}

interface DataSourceSubmissionConfig {
  dataSourceId: string;
  operation?: string;
}

interface CustomSubmissionConfig {
  handler: (data: any, form: Form) => Promise<SubmissionResult>;
}

7.2 字段注册系统

7.2.1 字段注册器

// 字段注册器
class FieldRegistry {
  private fields: Map<string, FieldDefinition> = new Map();
  private categories: Map<string, FieldCategory> = new Map();
  
  constructor(fields: FieldDefinition[] = []) {
    fields.forEach(field => this.register(field));
    this.initializeCategories();
  }
  
  // 注册字段
  register(field: FieldDefinition): void {
    this.fields.set(field.type, field);
    
    // 添加到分类
    const category = this.categories.get(field.category) || {
      id: field.category,
      name: field.category,
      fields: []
    };
    
    if (!category.fields.includes(field.type)) {
      category.fields.push(field.type);
    }
    
    this.categories.set(field.category, category);
  }
  
  // 获取字段定义
  getField(type: string): FieldDefinition | null {
    return this.fields.get(type) || null;
  }
  
  // 检查字段是否存在
  hasField(type: string): boolean {
    return this.fields.has(type);
  }
  
  // 获取所有字段
  getAllFields(): FieldDefinition[] {
    return Array.from(this.fields.values());
  }
  
  // 按分类获取字段
  getFieldsByCategory(category: string): FieldDefinition[] {
    const categoryInfo = this.categories.get(category);
    if (!categoryInfo) {
      return [];
    }
    
    return categoryInfo.fields
      .map(type => this.getField(type))
      .filter(field => field !== null) as FieldDefinition[];
  }
  
  // 获取所有分类
  getCategories(): FieldCategory[] {
    return Array.from(this.categories.values());
  }
  
  // 搜索字段
  searchFields(query: string): FieldDefinition[] {
    const lowerQuery = query.toLowerCase();
    
    return this.getAllFields().filter(field => 
      field.name.toLowerCase().includes(lowerQuery) ||
      field.type.toLowerCase().includes(lowerQuery) ||
      (field.description && field.description.toLowerCase().includes(lowerQuery))
    );
  }
  
  // 初始化分类
  private initializeCategories(): void {
    const defaultCategories = [
      { id: 'basic', name: '基础字段', fields: [] },
      { id: 'input', name: '输入字段', fields: [] },
      { id: 'selection', name: '选择字段', fields: [] },
      { id: 'display', name: '显示字段', fields: [] },
      { id: 'layout', name: '布局字段', fields: [] },
      { id: 'advanced', name: '高级字段', fields: [] }
    ];
    
    defaultCategories.forEach(category => {
      if (!this.categories.has(category.id)) {
        this.categories.set(category.id, category);
      }
    });
  }
}

// 字段分类
interface FieldCategory {
  id: string;
  name: string;
  fields: string[];
}

// 字段定义基类
abstract class FieldDefinition {
  abstract readonly type: string;
  abstract readonly name: string;
  abstract readonly category: string;
  abstract readonly icon?: string;
  abstract readonly description?: string;
  
  // 创建字段实例
  abstract createField(config: FieldConfig): FormField;
  
  // 获取默认配置
  abstract getDefaultConfig(): Partial<FieldConfig>;
  
  // 获取配置模式
  abstract getConfigSchema(): FieldConfigSchema;
  
  // 验证配置
  validateConfig(config: FieldConfig): ValidationResult {
    const schema = this.getConfigSchema();
    return this.validateAgainstSchema(config, schema);
  }
  
  // 根据模式验证
  private validateAgainstSchema(config: any, schema: FieldConfigSchema): ValidationResult {
    const errors: ValidationError[] = [];
    
    // 验证必填属性
    for (const required of schema.required || []) {
      if (!(required in config) || config[required] === undefined) {
        errors.push({
          field: required,
          rule: ValidationRuleType.REQUIRED,
          message: `${required} 是必填属性`,
          value: config[required]
        });
      }
    }
    
    // 验证属性类型
    for (const [property, propertySchema] of Object.entries(schema.properties || {})) {
      if (property in config) {
        const value = config[property];
        if (!this.validatePropertyType(value, propertySchema)) {
          errors.push({
            field: property,
            rule: ValidationRuleType.TYPE,
            message: `${property} 类型不正确`,
            value
          });
        }
      }
    }
    
    return {
      valid: errors.length === 0,
      errors
    };
  }
  
  private validatePropertyType(value: any, schema: PropertySchema): boolean {
    switch (schema.type) {
      case 'string':
        return typeof value === 'string';
      case 'number':
        return typeof value === 'number';
      case 'boolean':
        return typeof value === 'boolean';
      case 'array':
        return Array.isArray(value);
      case 'object':
        return typeof value === 'object' && !Array.isArray(value);
      default:
        return true;
    }
  }
}

// 字段配置模式
interface FieldConfigSchema {
  properties?: Record<string, PropertySchema>;
  required?: string[];
}

interface PropertySchema {
  type: 'string' | 'number' | 'boolean' | 'array' | 'object';
  description?: string;
  default?: any;
  enum?: any[];
}

7.2.2 内置字段定义

// 文本字段定义
class TextFieldDefinition extends FieldDefinition {
  readonly type = 'text';
  readonly name = '文本输入';
  readonly category = 'input';
  readonly icon = 'text';
  readonly description = '单行文本输入字段';
  
  createField(config: FieldConfig): FormField {
    return new TextField(config, this);
  }
  
  getDefaultConfig(): Partial<FieldConfig> {
    return {
      placeholder: '请输入文本',
      maxLength: 255,
      clearable: true
    };
  }
  
  getConfigSchema(): FieldConfigSchema {
    return {
      properties: {
        placeholder: { type: 'string', description: '占位符文本' },
        maxLength: { type: 'number', description: '最大长度' },
        minLength: { type: 'number', description: '最小长度' },
        clearable: { type: 'boolean', description: '是否可清除' },
        prefix: { type: 'string', description: '前缀图标' },
        suffix: { type: 'string', description: '后缀图标' }
      },
      required: ['name', 'type']
    };
  }
}

// 数字字段定义
class NumberFieldDefinition extends FieldDefinition {
  readonly type = 'number';
  readonly name = '数字输入';
  readonly category = 'input';
  readonly icon = 'number';
  readonly description = '数字输入字段';
  
  createField(config: FieldConfig): FormField {
    return new NumberField(config, this);
  }
  
  getDefaultConfig(): Partial<FieldConfig> {
    return {
      placeholder: '请输入数字',
      step: 1,
      precision: 0
    };
  }
  
  getConfigSchema(): FieldConfigSchema {
    return {
      properties: {
        placeholder: { type: 'string', description: '占位符文本' },
        min: { type: 'number', description: '最小值' },
        max: { type: 'number', description: '最大值' },
        step: { type: 'number', description: '步长' },
        precision: { type: 'number', description: '精度' },
        controls: { type: 'boolean', description: '是否显示控制按钮' }
      },
      required: ['name', 'type']
    };
  }
}

// 选择字段定义
class SelectFieldDefinition extends FieldDefinition {
  readonly type = 'select';
  readonly name = '下拉选择';
  readonly category = 'selection';
  readonly icon = 'select';
  readonly description = '下拉选择字段';
  
  createField(config: FieldConfig): FormField {
    return new SelectField(config, this);
  }
  
  getDefaultConfig(): Partial<FieldConfig> {
    return {
      placeholder: '请选择',
      clearable: true,
      filterable: false,
      multiple: false,
      options: []
    };
  }
  
  getConfigSchema(): FieldConfigSchema {
    return {
      properties: {
        placeholder: { type: 'string', description: '占位符文本' },
        clearable: { type: 'boolean', description: '是否可清除' },
        filterable: { type: 'boolean', description: '是否可搜索' },
        multiple: { type: 'boolean', description: '是否多选' },
        options: { type: 'array', description: '选项列表' },
        optionsSource: { type: 'object', description: '选项数据源' }
      },
      required: ['name', 'type']
    };
  }
}

// 日期字段定义
class DateFieldDefinition extends FieldDefinition {
  readonly type = 'date';
  readonly name = '日期选择';
  readonly category = 'input';
  readonly icon = 'date';
  readonly description = '日期选择字段';
  
  createField(config: FieldConfig): FormField {
    return new DateField(config, this);
  }
  
  getDefaultConfig(): Partial<FieldConfig> {
    return {
      placeholder: '请选择日期',
      format: 'YYYY-MM-DD',
      clearable: true
    };
  }
  
  getConfigSchema(): FieldConfigSchema {
    return {
      properties: {
        placeholder: { type: 'string', description: '占位符文本' },
        format: { type: 'string', description: '日期格式' },
        clearable: { type: 'boolean', description: '是否可清除' },
        disabledDate: { type: 'object', description: '禁用日期函数' },
        shortcuts: { type: 'array', description: '快捷选项' }
      },
      required: ['name', 'type']
    };
  }
}

// 文件上传字段定义
class FileFieldDefinition extends FieldDefinition {
  readonly type = 'file';
  readonly name = '文件上传';
  readonly category = 'input';
  readonly icon = 'upload';
  readonly description = '文件上传字段';
  
  createField(config: FieldConfig): FormField {
    return new FileField(config, this);
  }
  
  getDefaultConfig(): Partial<FieldConfig> {
    return {
      accept: '*',
      multiple: false,
      maxSize: 10 * 1024 * 1024, // 10MB
      maxCount: 1
    };
  }
  
  getConfigSchema(): FieldConfigSchema {
    return {
      properties: {
        accept: { type: 'string', description: '接受的文件类型' },
        multiple: { type: 'boolean', description: '是否多选' },
        maxSize: { type: 'number', description: '最大文件大小' },
        maxCount: { type: 'number', description: '最大文件数量' },
        uploadUrl: { type: 'string', description: '上传地址' },
        headers: { type: 'object', description: '上传请求头' }
      },
      required: ['name', 'type']
    };
  }
}

7.3 表单字段实现

7.3.1 字段基类

// 表单字段基类
abstract class FormField {
  public readonly name: string;
  public readonly type: string;
  public readonly label: string;
  
  protected config: FieldConfig;
  protected definition: FieldDefinition;
  protected form: Form;
  protected validationEngine: FormValidationEngine;
  protected eventBus: EventBus;
  protected element: HTMLElement | null = null;
  protected value: any;
  protected defaultValue: any;
  protected errors: string[] = [];
  protected visible: boolean = true;
  protected disabled: boolean = false;
  protected readonly: boolean = false;
  
  constructor(options: FieldOptions) {
    this.config = options.config;
    this.definition = options.definition;
    this.form = options.form;
    this.validationEngine = options.validationEngine;
    this.eventBus = new EventBus();
    
    this.name = this.config.name;
    this.type = this.config.type;
    this.label = this.config.label || this.name;
    this.defaultValue = this.config.defaultValue;
    this.value = this.defaultValue;
    this.visible = this.config.visible !== false;
    this.disabled = this.config.disabled === true;
    this.readonly = this.config.readonly === true;
  }
  
  async initialize(): Promise<void> {
    // 初始化字段特定逻辑
    await this.initializeField();
    
    // 设置初始值
    if (this.defaultValue !== undefined) {
      await this.setValue(this.defaultValue);
    }
  }
  
  // 抽象方法 - 子类必须实现
  abstract render(container: HTMLElement): Promise<HTMLElement>;
  abstract getValue(): any;
  abstract setValue(value: any): Promise<void>;
  abstract focus(): void;
  abstract blur(): void;
  abstract clear(): void;
  
  // 字段初始化 - 子类可重写
  protected async initializeField(): Promise<void> {
    // 默认实现为空
  }
  
  // 验证字段
  async validate(): Promise<ValidationResult> {
    const errors: ValidationError[] = [];
    const value = this.getValue();
    
    // 必填验证
    if (this.config.required && this.isEmpty(value)) {
      errors.push({
        field: this.name,
        rule: ValidationRuleType.REQUIRED,
        message: this.config.requiredMessage || `${this.label} 是必填字段`,
        value
      });
    }
    
    // 字段特定验证
    if (!this.isEmpty(value)) {
      const fieldErrors = await this.validateField(value);
      errors.push(...fieldErrors);
    }
    
    // 自定义验证规则
    if (this.config.rules) {
      for (const rule of this.config.rules) {
        const ruleResult = await this.validationEngine.validateRule(value, rule);
        if (!ruleResult.valid) {
          errors.push(...ruleResult.errors);
        }
      }
    }
    
    // 更新错误状态
    this.errors = errors.map(error => error.message);
    this.updateErrorDisplay();
    
    const result = {
      valid: errors.length === 0,
      errors
    };
    
    this.emit('field:validated', { field: this, result });
    
    return result;
  }
  
  // 字段特定验证 - 子类可重写
  protected async validateField(value: any): Promise<ValidationError[]> {
    return [];
  }
  
  // 获取默认值
  getDefaultValue(): any {
    return this.defaultValue;
  }
  
  // 重置字段
  async reset(): Promise<void> {
    await this.setValue(this.defaultValue);
    this.errors = [];
    this.updateErrorDisplay();
    this.emit('field:reset', { field: this });
  }
  
  // 销毁字段
  async destroy(): Promise<void> {
    if (this.element && this.element.parentNode) {
      this.element.parentNode.removeChild(this.element);
    }
    
    this.element = null;
    this.emit('field:destroyed', { field: this });
  }
  
  // 可见性控制
  isVisible(): boolean {
    return this.visible;
  }
  
  setVisible(visible: boolean): void {
    this.visible = visible;
    this.updateVisibility();
    this.emit('field:visibilityChanged', { field: this, visible });
  }
  
  updateVisibility(): void {
    if (this.element) {
      this.element.style.display = this.visible ? '' : 'none';
    }
  }
  
  // 禁用状态控制
  isDisabled(): boolean {
    return this.disabled;
  }
  
  setDisabled(disabled: boolean): void {
    this.disabled = disabled;
    this.updateDisabled();
    this.emit('field:disabledChanged', { field: this, disabled });
  }
  
  updateDisabled(): void {
    if (this.element) {
      const input = this.element.querySelector('input, select, textarea') as HTMLInputElement;
      if (input) {
        input.disabled = this.disabled;
      }
    }
  }
  
  // 只读状态控制
  isReadonly(): boolean {
    return this.readonly;
  }
  
  setReadonly(readonly: boolean): void {
    this.readonly = readonly;
    this.updateReadonly();
    this.emit('field:readonlyChanged', { field: this, readonly });
  }
  
  updateReadonly(): void {
    if (this.element) {
      const input = this.element.querySelector('input, select, textarea') as HTMLInputElement;
      if (input) {
        input.readOnly = this.readonly;
      }
    }
  }
  
  // 获取依赖字段
  getDependencies(): string[] {
    const dependencies: string[] = [];
    
    // 从可见性条件中提取依赖
    if (this.config.visibleWhen) {
      dependencies.push(...this.extractDependenciesFromCondition(this.config.visibleWhen));
    }
    
    // 从禁用条件中提取依赖
    if (this.config.disabledWhen) {
      dependencies.push(...this.extractDependenciesFromCondition(this.config.disabledWhen));
    }
    
    // 从选项数据源中提取依赖
    if (this.config.optionsSource && this.config.optionsSource.dependencies) {
      dependencies.push(...this.config.optionsSource.dependencies);
    }
    
    return [...new Set(dependencies)];
  }
  
  // 更新选项(用于依赖字段)
  async updateOptions(): Promise<void> {
    // 子类可重写
  }
  
  // 事件处理
  on(event: string, handler: Function): void {
    this.eventBus.on(event, handler);
  }
  
  off(event: string, handler: Function): void {
    this.eventBus.off(event, handler);
  }
  
  emit(event: string, data: any): void {
    this.eventBus.emit(event, data);
  }
  
  // 工具方法
  protected isEmpty(value: any): boolean {
    return value === null || value === undefined || value === '' || 
           (Array.isArray(value) && value.length === 0);
  }
  
  protected updateErrorDisplay(): void {
    if (this.element) {
      const errorContainer = this.element.querySelector('.field-errors');
      if (errorContainer) {
        errorContainer.innerHTML = '';
        
        if (this.errors.length > 0) {
          this.errors.forEach(error => {
            const errorElement = document.createElement('div');
            errorElement.className = 'field-error';
            errorElement.textContent = error;
            errorContainer.appendChild(errorElement);
          });
          
          this.element.classList.add('has-error');
        } else {
          this.element.classList.remove('has-error');
        }
      }
    }
  }
  
  protected extractDependenciesFromCondition(condition: FieldCondition): string[] {
    const dependencies: string[] = [];
    
    if (condition.field) {
      dependencies.push(condition.field);
    }
    
    if (condition.and) {
      condition.and.forEach(subCondition => {
        dependencies.push(...this.extractDependenciesFromCondition(subCondition));
      });
    }
    
    if (condition.or) {
      condition.or.forEach(subCondition => {
        dependencies.push(...this.extractDependenciesFromCondition(subCondition));
      });
    }
    
    return dependencies;
  }
  
  protected createFieldContainer(): HTMLElement {
    const container = document.createElement('div');
    container.className = `field-container field-${this.type}`;
    container.setAttribute('data-field-name', this.name);
    
    // 添加标签
    if (this.label) {
      const label = document.createElement('label');
      label.className = 'field-label';
      label.textContent = this.label;
      
      if (this.config.required) {
        label.classList.add('required');
      }
      
      container.appendChild(label);
    }
    
    // 添加字段包装器
    const wrapper = document.createElement('div');
    wrapper.className = 'field-wrapper';
    container.appendChild(wrapper);
    
    // 添加帮助文本
    if (this.config.help) {
      const help = document.createElement('div');
      help.className = 'field-help';
      help.textContent = this.config.help;
      container.appendChild(help);
    }
    
    // 添加错误容器
    const errors = document.createElement('div');
    errors.className = 'field-errors';
    container.appendChild(errors);
    
    return container;
  }
}

// 字段选项
interface FieldOptions {
  config: FieldConfig;
  definition: FieldDefinition;
  form: Form;
  validationEngine: FormValidationEngine;
}

// 字段配置
interface FieldConfig {
  name: string;
  type: string;
  label?: string;
  placeholder?: string;
  help?: string;
  required?: boolean;
  requiredMessage?: string;
  defaultValue?: any;
  visible?: boolean;
  disabled?: boolean;
  readonly?: boolean;
  rules?: ValidationRule[];
  visibleWhen?: FieldCondition;
  disabledWhen?: FieldCondition;
  optionsSource?: OptionsSource;
  [key: string]: any;
}

// 字段条件
interface FieldCondition {
  field?: string;
  operator?: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'nin' | 'contains' | 'startsWith' | 'endsWith';
  value?: any;
  and?: FieldCondition[];
  or?: FieldCondition[];
}

// 选项数据源
interface OptionsSource {
  type: 'static' | 'api' | 'dataSource' | 'function';
  data?: any;
  url?: string;
  dataSourceId?: string;
  dependencies?: string[];
  transform?: (data: any) => any[];
}

7.3.2 具体字段实现

// 文本字段实现
class TextField extends FormField {
  private input: HTMLInputElement | null = null;
  
  async render(container: HTMLElement): Promise<HTMLElement> {
    this.element = this.createFieldContainer();
    const wrapper = this.element.querySelector('.field-wrapper') as HTMLElement;
    
    // 创建输入框
    this.input = document.createElement('input');
    this.input.type = 'text';
    this.input.className = 'field-input';
    this.input.placeholder = this.config.placeholder || '';
    
    if (this.config.maxLength) {
      this.input.maxLength = this.config.maxLength;
    }
    
    // 绑定事件
    this.input.addEventListener('input', () => {
      this.value = this.input!.value;
      this.emit('value:changed', { field: this, value: this.value });
    });
    
    this.input.addEventListener('blur', () => {
      this.validate();
      this.emit('field:blur', { field: this });
    });
    
    wrapper.appendChild(this.input);
    
    // 添加清除按钮
    if (this.config.clearable) {
      const clearButton = document.createElement('button');
      clearButton.type = 'button';
      clearButton.className = 'field-clear';
      clearButton.innerHTML = '×';
      clearButton.addEventListener('click', () => this.clear());
      wrapper.appendChild(clearButton);
    }
    
    container.appendChild(this.element);
    return this.element;
  }
  
  getValue(): string {
    return this.value || '';
  }
  
  async setValue(value: string): Promise<void> {
    this.value = value || '';
    if (this.input) {
      this.input.value = this.value;
    }
    this.emit('value:changed', { field: this, value: this.value });
  }
  
  focus(): void {
    if (this.input) {
      this.input.focus();
    }
  }
  
  blur(): void {
    if (this.input) {
      this.input.blur();
    }
  }
  
  clear(): void {
    this.setValue('');
  }
  
  protected async validateField(value: string): Promise<ValidationError[]> {
    const errors: ValidationError[] = [];
    
    // 长度验证
    if (this.config.minLength && value.length < this.config.minLength) {
      errors.push({
        field: this.name,
        rule: ValidationRuleType.MIN_LENGTH,
        message: `${this.label} 最小长度为 ${this.config.minLength}`,
        value
      });
    }
    
    if (this.config.maxLength && value.length > this.config.maxLength) {
      errors.push({
        field: this.name,
        rule: ValidationRuleType.MAX_LENGTH,
        message: `${this.label} 最大长度为 ${this.config.maxLength}`,
        value
      });
    }
    
    // 正则验证
    if (this.config.pattern) {
      const regex = new RegExp(this.config.pattern);
      if (!regex.test(value)) {
        errors.push({
          field: this.name,
          rule: ValidationRuleType.PATTERN,
          message: this.config.patternMessage || `${this.label} 格式不正确`,
          value
        });
      }
    }
    
    return errors;
  }
}

// 数字字段实现
class NumberField extends FormField {
  private input: HTMLInputElement | null = null;
  
  async render(container: HTMLElement): Promise<HTMLElement> {
    this.element = this.createFieldContainer();
    const wrapper = this.element.querySelector('.field-wrapper') as HTMLElement;
    
    // 创建输入框
    this.input = document.createElement('input');
    this.input.type = 'number';
    this.input.className = 'field-input';
    this.input.placeholder = this.config.placeholder || '';
    
    if (this.config.min !== undefined) {
      this.input.min = this.config.min.toString();
    }
    
    if (this.config.max !== undefined) {
      this.input.max = this.config.max.toString();
    }
    
    if (this.config.step !== undefined) {
      this.input.step = this.config.step.toString();
    }
    
    // 绑定事件
    this.input.addEventListener('input', () => {
      const numValue = parseFloat(this.input!.value);
      this.value = isNaN(numValue) ? null : numValue;
      this.emit('value:changed', { field: this, value: this.value });
    });
    
    this.input.addEventListener('blur', () => {
      this.validate();
      this.emit('field:blur', { field: this });
    });
    
    wrapper.appendChild(this.input);
    container.appendChild(this.element);
    return this.element;
  }
  
  getValue(): number | null {
    return this.value;
  }
  
  async setValue(value: number | null): Promise<void> {
    this.value = value;
    if (this.input) {
      this.input.value = value !== null ? value.toString() : '';
    }
    this.emit('value:changed', { field: this, value: this.value });
  }
  
  focus(): void {
    if (this.input) {
      this.input.focus();
    }
  }
  
  blur(): void {
    if (this.input) {
      this.input.blur();
    }
  }
  
  clear(): void {
    this.setValue(null);
  }
  
  protected async validateField(value: number): Promise<ValidationError[]> {
    const errors: ValidationError[] = [];
    
    // 范围验证
    if (this.config.min !== undefined && value < this.config.min) {
      errors.push({
        field: this.name,
        rule: ValidationRuleType.MIN_VALUE,
        message: `${this.label} 最小值为 ${this.config.min}`,
        value
      });
    }
    
    if (this.config.max !== undefined && value > this.config.max) {
      errors.push({
        field: this.name,
        rule: ValidationRuleType.MAX_VALUE,
        message: `${this.label} 最大值为 ${this.config.max}`,
        value
      });
    }
    
    return errors;
  }
}

// 选择字段实现
class SelectField extends FormField {
  private select: HTMLSelectElement | null = null;
  private options: FieldOption[] = [];
  
  async render(container: HTMLElement): Promise<HTMLElement> {
    this.element = this.createFieldContainer();
    const wrapper = this.element.querySelector('.field-wrapper') as HTMLElement;
    
    // 创建选择框
    this.select = document.createElement('select');
    this.select.className = 'field-input';
    
    if (this.config.multiple) {
      this.select.multiple = true;
    }
    
    // 绑定事件
    this.select.addEventListener('change', () => {
      this.updateValueFromSelect();
      this.emit('value:changed', { field: this, value: this.value });
    });
    
    this.select.addEventListener('blur', () => {
      this.validate();
      this.emit('field:blur', { field: this });
    });
    
    wrapper.appendChild(this.select);
    
    // 加载选项
    await this.loadOptions();
    
    container.appendChild(this.element);
    return this.element;
  }
  
  getValue(): any {
    return this.value;
  }
  
  async setValue(value: any): Promise<void> {
    this.value = value;
    this.updateSelectFromValue();
    this.emit('value:changed', { field: this, value: this.value });
  }
  
  focus(): void {
    if (this.select) {
      this.select.focus();
    }
  }
  
  blur(): void {
    if (this.select) {
      this.select.blur();
    }
  }
  
  clear(): void {
    this.setValue(this.config.multiple ? [] : null);
  }
  
  async updateOptions(): Promise<void> {
    await this.loadOptions();
  }
  
  private async loadOptions(): Promise<void> {
    if (this.config.options) {
      this.options = this.config.options;
    } else if (this.config.optionsSource) {
      this.options = await this.loadOptionsFromSource();
    } else {
      this.options = [];
    }
    
    this.renderOptions();
  }
  
  private async loadOptionsFromSource(): Promise<FieldOption[]> {
    const source = this.config.optionsSource!;
    
    switch (source.type) {
      case 'static':
        return source.data || [];
      
      case 'api':
        if (source.url) {
          const response = await fetch(source.url);
          const data = await response.json();
          return source.transform ? source.transform(data) : data;
        }
        break;
      
      case 'dataSource':
        if (source.dataSourceId) {
          const result = await this.form['dataEngine'].query(source.dataSourceId);
          return source.transform ? source.transform(result.data) : result.data;
        }
        break;
      
      case 'function':
        if (source.transform) {
          const formData = this.form.getData();
          return source.transform(formData);
        }
        break;
    }
    
    return [];
  }
  
  private renderOptions(): void {
    if (!this.select) {
      return;
    }
    
    // 清空现有选项
    this.select.innerHTML = '';
    
    // 添加占位符选项
    if (this.config.placeholder && !this.config.multiple) {
      const placeholderOption = document.createElement('option');
      placeholderOption.value = '';
      placeholderOption.textContent = this.config.placeholder;
      placeholderOption.disabled = true;
      placeholderOption.selected = true;
      this.select.appendChild(placeholderOption);
    }
    
    // 添加选项
    this.options.forEach(option => {
      const optionElement = document.createElement('option');
      optionElement.value = option.value;
      optionElement.textContent = option.label;
      this.select!.appendChild(optionElement);
    });
    
    // 更新选中状态
    this.updateSelectFromValue();
  }
  
  private updateValueFromSelect(): void {
    if (!this.select) {
      return;
    }
    
    if (this.config.multiple) {
      const selectedValues: string[] = [];
      for (let i = 0; i < this.select.options.length; i++) {
        if (this.select.options[i].selected) {
          selectedValues.push(this.select.options[i].value);
        }
      }
      this.value = selectedValues;
    } else {
      this.value = this.select.value || null;
    }
  }
  
  private updateSelectFromValue(): void {
    if (!this.select) {
      return;
    }
    
    if (this.config.multiple && Array.isArray(this.value)) {
      for (let i = 0; i < this.select.options.length; i++) {
        this.select.options[i].selected = this.value.includes(this.select.options[i].value);
      }
    } else {
      this.select.value = this.value || '';
    }
  }
}

// 字段选项
interface FieldOption {
  value: string;
  label: string;
  disabled?: boolean;
}

// 日期字段实现
class DateField extends FormField {
  private input: HTMLInputElement | null = null;
  
  async render(container: HTMLElement): Promise<HTMLElement> {
    this.element = this.createFieldContainer();
    const wrapper = this.element.querySelector('.field-wrapper') as HTMLElement;
    
    // 创建日期输入框
    this.input = document.createElement('input');
    this.input.type = 'date';
    this.input.className = 'field-input';
    
    // 绑定事件
    this.input.addEventListener('change', () => {
      this.value = this.input!.value || null;
      this.emit('value:changed', { field: this, value: this.value });
    });
    
    this.input.addEventListener('blur', () => {
      this.validate();
      this.emit('field:blur', { field: this });
    });
    
    wrapper.appendChild(this.input);
    container.appendChild(this.element);
    return this.element;
  }
  
  getValue(): string | null {
    return this.value;
  }
  
  async setValue(value: string | null): Promise<void> {
    this.value = value;
    if (this.input) {
      this.input.value = value || '';
    }
    this.emit('value:changed', { field: this, value: this.value });
  }
  
  focus(): void {
    if (this.input) {
      this.input.focus();
    }
  }
  
  blur(): void {
    if (this.input) {
      this.input.blur();
    }
  }
  
  clear(): void {
    this.setValue(null);
  }
}

// 文件上传字段实现
class FileField extends FormField {
  private input: HTMLInputElement | null = null;
  private fileList: HTMLElement | null = null;
  private files: File[] = [];
  
  async render(container: HTMLElement): Promise<HTMLElement> {
    this.element = this.createFieldContainer();
    const wrapper = this.element.querySelector('.field-wrapper') as HTMLElement;
    
    // 创建文件输入框
    this.input = document.createElement('input');
    this.input.type = 'file';
    this.input.className = 'field-input';
    
    if (this.config.accept) {
      this.input.accept = this.config.accept;
    }
    
    if (this.config.multiple) {
      this.input.multiple = true;
    }
    
    // 绑定事件
    this.input.addEventListener('change', () => {
      this.handleFileChange();
    });
    
    wrapper.appendChild(this.input);
    
    // 创建文件列表
    this.fileList = document.createElement('div');
    this.fileList.className = 'file-list';
    wrapper.appendChild(this.fileList);
    
    container.appendChild(this.element);
    return this.element;
  }
  
  getValue(): File[] {
    return this.files;
  }
  
  async setValue(value: File[]): Promise<void> {
    this.files = value || [];
    this.updateFileList();
    this.emit('value:changed', { field: this, value: this.value });
  }
  
  focus(): void {
    if (this.input) {
      this.input.focus();
    }
  }
  
  blur(): void {
    if (this.input) {
      this.input.blur();
    }
  }
  
  clear(): void {
    this.setValue([]);
    if (this.input) {
      this.input.value = '';
    }
  }
  
  private handleFileChange(): void {
    if (!this.input || !this.input.files) {
      return;
    }
    
    const newFiles = Array.from(this.input.files);
    
    // 验证文件
    const validFiles = newFiles.filter(file => this.validateFile(file));
    
    if (this.config.multiple) {
      this.files = [...this.files, ...validFiles];
      
      // 检查最大文件数量
      if (this.config.maxCount && this.files.length > this.config.maxCount) {
        this.files = this.files.slice(0, this.config.maxCount);
      }
    } else {
      this.files = validFiles.slice(0, 1);
    }
    
    this.updateFileList();
    this.emit('value:changed', { field: this, value: this.files });
  }
  
  private validateFile(file: File): boolean {
    // 检查文件大小
    if (this.config.maxSize && file.size > this.config.maxSize) {
      console.warn(`文件 ${file.name} 超过最大大小限制`);
      return false;
    }
    
    // 检查文件类型
    if (this.config.accept && this.config.accept !== '*') {
      const acceptTypes = this.config.accept.split(',').map(type => type.trim());
      const fileType = file.type;
      const fileName = file.name;
      
      const isAccepted = acceptTypes.some(acceptType => {
        if (acceptType.startsWith('.')) {
          return fileName.toLowerCase().endsWith(acceptType.toLowerCase());
        } else {
          return fileType.match(acceptType.replace('*', '.*'));
        }
      });
      
      if (!isAccepted) {
        console.warn(`文件 ${file.name} 类型不被接受`);
        return false;
      }
    }
    
    return true;
  }
  
  private updateFileList(): void {
    if (!this.fileList) {
      return;
    }
    
    this.fileList.innerHTML = '';
    
    this.files.forEach((file, index) => {
      const fileItem = document.createElement('div');
      fileItem.className = 'file-item';
      
      const fileName = document.createElement('span');
      fileName.className = 'file-name';
      fileName.textContent = file.name;
      
      const fileSize = document.createElement('span');
      fileSize.className = 'file-size';
      fileSize.textContent = this.formatFileSize(file.size);
      
      const removeButton = document.createElement('button');
      removeButton.type = 'button';
      removeButton.className = 'file-remove';
      removeButton.textContent = '删除';
      removeButton.addEventListener('click', () => {
        this.removeFile(index);
      });
      
      fileItem.appendChild(fileName);
      fileItem.appendChild(fileSize);
      fileItem.appendChild(removeButton);
      
      this.fileList.appendChild(fileItem);
    });
  }
  
  private removeFile(index: number): void {
    this.files.splice(index, 1);
    this.updateFileList();
    this.emit('value:changed', { field: this, value: this.files });
  }
  
  private formatFileSize(bytes: number): string {
    if (bytes === 0) return '0 Bytes';
    
    const k = 1024;
    const sizes = ['Bytes', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  }
}

7.4 表单渲染引擎

7.4.1 表单渲染器

// 表单渲染器
class FormRenderer {
  private form: Form;
  private container: HTMLElement;
  private fieldRegistry: FieldRegistry;
  private eventBus: EventBus;
  private element: HTMLElement | null = null;
  private fieldElements: Map<string, HTMLElement> = new Map();
  
  constructor(options: FormRendererOptions) {
    this.form = options.form;
    this.container = options.container;
    this.fieldRegistry = options.fieldRegistry;
    this.eventBus = options.eventBus;
  }
  
  async render(): Promise<void> {
    // 创建表单元素
    this.element = document.createElement('form');
    this.element.className = 'lowcode-form';
    this.element.setAttribute('data-form-id', this.form.id);
    
    // 阻止默认提交
    this.element.addEventListener('submit', (e) => {
      e.preventDefault();
      this.handleSubmit();
    });
    
    // 渲染表单标题
    if (this.form.title) {
      const title = document.createElement('h2');
      title.className = 'form-title';
      title.textContent = this.form.title;
      this.element.appendChild(title);
    }
    
    // 渲染表单描述
    if (this.form.description) {
      const description = document.createElement('p');
      description.className = 'form-description';
      description.textContent = this.form.description;
      this.element.appendChild(description);
    }
    
    // 渲染字段
    await this.renderFields();
    
    // 渲染表单按钮
    this.renderFormActions();
    
    // 添加到容器
    this.container.appendChild(this.element);
    
    // 绑定事件
    this.bindEvents();
  }
  
  async destroy(): Promise<void> {
    if (this.element && this.element.parentNode) {
      this.element.parentNode.removeChild(this.element);
    }
    
    this.fieldElements.clear();
    this.element = null;
  }
  
  private async renderFields(): Promise<void> {
    const fieldsContainer = document.createElement('div');
    fieldsContainer.className = 'form-fields';
    
    const fields = this.form.getFields();
    
    for (const field of fields) {
      const fieldElement = await field.render(fieldsContainer);
      this.fieldElements.set(field.name, fieldElement);
    }
    
    this.element!.appendChild(fieldsContainer);
  }
  
  private renderFormActions(): void {
    const actionsContainer = document.createElement('div');
    actionsContainer.className = 'form-actions';
    
    // 提交按钮
    const submitButton = document.createElement('button');
    submitButton.type = 'submit';
    submitButton.className = 'btn btn-primary';
    submitButton.textContent = '提交';
    actionsContainer.appendChild(submitButton);
    
    // 重置按钮
    const resetButton = document.createElement('button');
    resetButton.type = 'button';
    resetButton.className = 'btn btn-secondary';
    resetButton.textContent = '重置';
    resetButton.addEventListener('click', () => this.handleReset());
    actionsContainer.appendChild(resetButton);
    
    this.element!.appendChild(actionsContainer);
  }
  
  private bindEvents(): void {
    // 监听表单事件
    this.form.on('form:dataChanged', () => {
      this.updateFieldVisibility();
    });
    
    this.form.on('form:validated', (event) => {
      this.updateValidationDisplay(event.result);
    });
  }
  
  private async handleSubmit(): Promise<void> {
    try {
      const result = await this.form.submit();
      
      if (result.success) {
        this.eventBus.emit('form:submitSuccess', { form: this.form, result });
      } else {
        this.eventBus.emit('form:submitError', { form: this.form, result });
      }
    } catch (error) {
      this.eventBus.emit('form:submitError', { form: this.form, error });
    }
  }
  
  private async handleReset(): Promise<void> {
    await this.form.reset();
    this.eventBus.emit('form:reset', { form: this.form });
  }
  
  private updateFieldVisibility(): void {
    const fields = this.form.getFields();
    
    fields.forEach(field => {
      const element = this.fieldElements.get(field.name);
      if (element) {
        element.style.display = field.isVisible() ? '' : 'none';
      }
    });
  }
  
  private updateValidationDisplay(result: ValidationResult): void {
    // 清除之前的验证状态
    if (this.element) {
      this.element.classList.remove('has-errors');
      
      if (!result.valid) {
        this.element.classList.add('has-errors');
      }
    }
  }
}

// 表单渲染器选项
interface FormRendererOptions {
  form: Form;
  container: HTMLElement;
  fieldRegistry: FieldRegistry;
  eventBus: EventBus;
}

7.4.2 表单布局引擎

// 布局类型
enum LayoutType {
  VERTICAL = 'vertical',
  HORIZONTAL = 'horizontal',
  GRID = 'grid',
  TABS = 'tabs',
  ACCORDION = 'accordion'
}

// 布局配置
interface LayoutConfig {
  type: LayoutType;
  columns?: number;
  gap?: string;
  responsive?: boolean;
  breakpoints?: {
    xs?: number;
    sm?: number;
    md?: number;
    lg?: number;
    xl?: number;
  };
}

// 表单布局引擎
class FormLayoutEngine {
  private form: Form;
  private config: LayoutConfig;
  private container: HTMLElement;
  
  constructor(form: Form, config: LayoutConfig, container: HTMLElement) {
    this.form = form;
    this.config = config;
    this.container = container;
  }
  
  render(): HTMLElement {
    switch (this.config.type) {
      case LayoutType.VERTICAL:
        return this.renderVerticalLayout();
      case LayoutType.HORIZONTAL:
        return this.renderHorizontalLayout();
      case LayoutType.GRID:
        return this.renderGridLayout();
      case LayoutType.TABS:
        return this.renderTabsLayout();
      case LayoutType.ACCORDION:
        return this.renderAccordionLayout();
      default:
        return this.renderVerticalLayout();
    }
  }
  
  private renderVerticalLayout(): HTMLElement {
    const layout = document.createElement('div');
    layout.className = 'form-layout form-layout-vertical';
    
    if (this.config.gap) {
      layout.style.gap = this.config.gap;
    }
    
    return layout;
  }
  
  private renderHorizontalLayout(): HTMLElement {
    const layout = document.createElement('div');
    layout.className = 'form-layout form-layout-horizontal';
    layout.style.display = 'flex';
    layout.style.flexDirection = 'row';
    layout.style.flexWrap = 'wrap';
    
    if (this.config.gap) {
      layout.style.gap = this.config.gap;
    }
    
    return layout;
  }
  
  private renderGridLayout(): HTMLElement {
    const layout = document.createElement('div');
    layout.className = 'form-layout form-layout-grid';
    layout.style.display = 'grid';
    
    if (this.config.columns) {
      layout.style.gridTemplateColumns = `repeat(${this.config.columns}, 1fr)`;
    }
    
    if (this.config.gap) {
      layout.style.gap = this.config.gap;
    }
    
    // 响应式处理
    if (this.config.responsive && this.config.breakpoints) {
      this.applyResponsiveGrid(layout);
    }
    
    return layout;
  }
  
  private renderTabsLayout(): HTMLElement {
    const layout = document.createElement('div');
    layout.className = 'form-layout form-layout-tabs';
    
    // 创建标签页头部
    const tabsHeader = document.createElement('div');
    tabsHeader.className = 'tabs-header';
    
    // 创建标签页内容
    const tabsContent = document.createElement('div');
    tabsContent.className = 'tabs-content';
    
    layout.appendChild(tabsHeader);
    layout.appendChild(tabsContent);
    
    return layout;
  }
  
  private renderAccordionLayout(): HTMLElement {
    const layout = document.createElement('div');
    layout.className = 'form-layout form-layout-accordion';
    
    return layout;
  }
  
  private applyResponsiveGrid(layout: HTMLElement): void {
    const breakpoints = this.config.breakpoints!;
    
    // 创建媒体查询样式
    const style = document.createElement('style');
    let css = '';
    
    if (breakpoints.xs) {
      css += `@media (max-width: 576px) {
        .form-layout-grid {
          grid-template-columns: repeat(${breakpoints.xs}, 1fr);
        }
      }`;
    }
    
    if (breakpoints.sm) {
      css += `@media (min-width: 576px) and (max-width: 768px) {
        .form-layout-grid {
          grid-template-columns: repeat(${breakpoints.sm}, 1fr);
        }
      }`;
    }
    
    if (breakpoints.md) {
      css += `@media (min-width: 768px) and (max-width: 992px) {
        .form-layout-grid {
          grid-template-columns: repeat(${breakpoints.md}, 1fr);
        }
      }`;
    }
    
    if (breakpoints.lg) {
      css += `@media (min-width: 992px) and (max-width: 1200px) {
        .form-layout-grid {
          grid-template-columns: repeat(${breakpoints.lg}, 1fr);
        }
      }`;
    }
    
    if (breakpoints.xl) {
      css += `@media (min-width: 1200px) {
        .form-layout-grid {
          grid-template-columns: repeat(${breakpoints.xl}, 1fr);
        }
      }`;
    }
    
    style.textContent = css;
    document.head.appendChild(style);
  }
}

7.5 表单验证引擎

7.5.1 验证规则系统

”`typescript // 验证规则类型 enum ValidationRuleType { REQUIRED = ‘required’, MIN_LENGTH = ‘minLength’, MAX_LENGTH = ‘maxLength’, PATTERN = ‘pattern’, EMAIL = ‘email’, URL = ‘url’, NUMBER = ‘number’, INTEGER = ‘integer’, MIN = ‘min’, MAX = ‘max’, CUSTOM = ‘custom’ }

// 验证规则 interface ValidationRule { type: ValidationRuleType; value?: any; message?: string; validator?: (value: any, field: FormField) => boolean | Promise; }

// 验证结果 interface ValidationResult { valid: boolean; errors: ValidationError[]; }

// 验证错误 interface ValidationError { field: string; rule: ValidationRuleType; message: string; value?: any; }

// 表单验证引擎 class FormValidationEngine { private form: Form; private rules: Map = new Map(); private customValidators: Map = new Map();

constructor(form: Form) { this.form = form; this.initializeBuiltInValidators(); }

// 添加验证规则 addRule(fieldName: string, rule: ValidationRule): void { if (!this.rules.has(fieldName)) { this.rules.set(fieldName, []); }

this.rules.get(fieldName)!.push(rule);

}

// 移除验证规则 removeRule(fieldName: string, ruleType: ValidationRuleType): void { const fieldRules = this.rules.get(fieldName); if (fieldRules) { const index = fieldRules.findIndex(rule => rule.type === ruleType); if (index !== -1) { fieldRules.splice(index, 1); } } }

// 清除字段的所有验证规则 clearRules(fieldName: string): void { this.rules.delete(fieldName); }

// 注册自定义验证器 registerValidator(name: string, validator: Function): void { this.customValidators.set(name, validator); }

// 验证单个字段 async validateField(fieldName: string): Promise { const field = this.form.getField(fieldName); if (!field) { return { valid: true, errors: [] }; }

const rules = this.rules.get(fieldName) || [];
const errors: ValidationError[] = [];

for (const rule of rules) {
  const isValid = await this.validateRule(field, rule);
  if (!isValid) {
    errors.push({
      field: fieldName,
      rule: rule.type,
      message: rule.message || this.getDefaultMessage(rule.type, rule.value),
      value: field.getValue()
    });
  }
}

return {
  valid: errors.length === 0,
  errors
};

}

// 验证整个表单 async validateForm(): Promise { const allErrors: ValidationError[] = []; const fields = this.form.getFields();

for (const field of fields) {
  const result = await this.validateField(field.name);
  allErrors.push(...result.errors);
}

return {
  valid: allErrors.length === 0,
  errors: allErrors
};

}

// 验证单个规则 private async validateRule(field: FormField, rule: ValidationRule): Promise { const value = field.getValue();

switch (rule.type) {
  case ValidationRuleType.REQUIRED:
    return this.validateRequired(value);

  case ValidationRuleType.MIN_LENGTH:
    return this.validateMinLength(value, rule.value);

  case ValidationRuleType.MAX_LENGTH:
    return this.validateMaxLength(value, rule.value);

  case ValidationRuleType.PATTERN:
    return this.validatePattern(value, rule.value);

  case ValidationRuleType.EMAIL:
    return this.validateEmail(value);

  case ValidationRuleType.URL:
    return this.validateUrl(value);

  case ValidationRuleType.NUMBER:
    return this.validateNumber(value);

  case ValidationRuleType.INTEGER:
    return this.validateInteger(value);

  case ValidationRuleType.MIN:
    return this.validateMin(value, rule.value);

  case ValidationRuleType.MAX:
    return this.validateMax(value, rule.value);

  case ValidationRuleType.CUSTOM:
    if (rule.validator) {
      return await rule.validator(value, field);
    }
    return true;

  default:
    return true;
}

}

// 内置验证器 private initializeBuiltInValidators(): void { // Required 验证器 this.customValidators.set(‘required’, (value: any) => { return this.validateRequired(value); });

// Email 验证器
this.customValidators.set('email', (value: any) => {
  return this.validateEmail(value);
});

// URL 验证器
this.customValidators.set('url', (value: any) => {
  return this.validateUrl(value);
});

// 手机号验证器
this.customValidators.set('phone', (value: any) => {
  if (!value) return true;
  const phoneRegex = /^1[3-9]\d{9}$/;
  return phoneRegex.test(value.toString());
});

// 身份证验证器
this.customValidators.set('idCard', (value: any) => {
  if (!value) return true;
  const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
  return idCardRegex.test(value.toString());
});

}

private validateRequired(value: any): boolean { if (value === null || value === undefined) { return false; }

if (typeof value === 'string') {
  return value.trim().length > 0;
}

if (Array.isArray(value)) {
  return value.length > 0;
}

return true;

}

private validateMinLength(value: any, minLength: number): boolean { if (!value) return true;

if (typeof value === 'string' || Array.isArray(value)) {
  return value.length >= minLength;
}

return true;

}

private validateMaxLength(value: any, maxLength: number): boolean { if (!value) return true;

if (typeof value === 'string' || Array.isArray(value)) {
  return value.length <= maxLength;
}

return true;

}

private validatePattern(value: any, pattern: string | RegExp): boolean { if (!value) return true;

const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;
return regex.test(value.toString());

}

private validateEmail(value: any): boolean { if (!value) return true;

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(value.toString());

}

private validateUrl(value: any): boolean { if (!value) return true;

try {
  new URL(value.toString());
  return true;
} catch {
  return false;
}

}

private validateNumber(value: any): boolean { if (!value) return true;

return !isNaN(Number(value));

}

private validateInteger(value: any): boolean { if (!value) return true;

const num = Number(value);
return !isNaN(num) && Number.isInteger(num);

}

private validateMin(value: any, min: number): boolean { if (!value) return true;

const num = Number(value);
return !isNaN(num) && num >= min;

}

private validateMax(value: any, max: number): boolean { if (!value) return true;

const num = Number(value);
return !isNaN(num) && num <= max;

}

private getDefaultMessage(ruleType: ValidationRuleType, value?: any): string { switch (ruleType) { case ValidationRuleType.REQUIRED: return ‘此字段为必填项’; case ValidationRuleType.MIN_LENGTH: return 最少需要 ${value} 个字符; case ValidationRuleType.MAX_LENGTH: return 最多允许 ${value} 个字符; case ValidationRuleType.EMAIL: return ‘请输入有效的邮箱地址’; case ValidationRuleType.URL: return ‘请输入有效的URL地址’; case ValidationRuleType.NUMBER: return ‘请输入有效的数字’; case ValidationRuleType.INTEGER: return ‘请输入有效的整数’; case ValidationRuleType.MIN: return 值不能小于 ${value}; case ValidationRuleType.MAX: return 值不能大于 ${value}; default: return ‘输入值无效’; } } }