# FlexRowForm (FormContainer) 弹性行表单

基于结构化行的表单布局系统，提供明确的行和单元格组织，实现精确的表单布局和12列网格支持。

## 特性

- **明确的行结构**: 手动行定义，实现精确的布局控制
- **12列网格系统**: 单元格可跨越1-12列，使用百分比宽度
- **布局模式**: 支持垂直和水平字段布局
- **结构化组织**: 行和单元格之间的清晰分离
- **FormField集成**: 与FormField组件无缝协作
- **响应式设计**: 灵活的网格系统，适应不同屏幕尺寸

## 安装

```bash
npm install @ticatec/uniface-element
```

## 使用方法

### 基本用法

```svelte
<script>
  import FormContainer, { Row, Cell } from '@ticatec/uniface-element/flex-row-form';
  import FormField from '@ticatec/uniface-element/form-field';
  import TextEditor from '@ticatec/uniface-element/text-editor';
  
  let formData = {};
</script>

<FormContainer>
  <Row>
    <Cell span={6}>
      <FormField label="名" required>
        <TextEditor bind:value={formData.firstName} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="姓" required>
        <TextEditor bind:value={formData.lastName} variant="filled" />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={12}>
      <FormField label="邮箱地址">
        <TextEditor bind:value={formData.email} variant="filled" />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

### 完整表单示例

```svelte
<script>
  import FormContainer, { Row, Cell } from '@ticatec/uniface-element/flex-row-form';
  import FormField from '@ticatec/uniface-element/form-field';
  import TextEditor from '@ticatec/uniface-element/text-editor';
  import DatePicker from '@ticatec/uniface-element/date-picker';
  import OptionsSelect from '@ticatec/uniface-element/options-select';
  import MemoEditor from '@ticatec/uniface-element/memo-editor';
  
  let formData = {};
  let errors = {};
  
  const genderOptions = [
    { code: 'F', text: '女' },
    { code: 'M', text: '男' }
  ];
  
  const countries = [
    { code: 'AU', text: '澳大利亚' },
    { code: 'NZ', text: '新西兰' },
    { code: 'US', text: '美国' }
  ];
</script>

<FormContainer style="max-width: 800px; margin: 0 auto; border: 1px solid #e1e1e1; padding: 20px;">
  <Row>
    <Cell span={4}>
      <FormField label="姓名" required error={errors.name}>
        <TextEditor 
          bind:value={formData.name} 
          variant="filled"
          placeholder="请输入姓名"
          input$maxLength={50}
        />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="出生日期" required error={errors.dob}>
        <DatePicker 
          bind:value={formData.dob} 
          variant="filled"
          max={new Date()}
        />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="性别" required error={errors.gender}>
        <OptionsSelect 
          bind:value={formData.gender} 
          variant="filled"
          options={genderOptions}
        />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={6}>
      <FormField label="国籍" error={errors.nationality}>
        <OptionsSelect 
          bind:value={formData.nationality} 
          variant="filled"
          options={countries}
        />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="电话号码" error={errors.phone}>
        <TextEditor 
          bind:value={formData.phone} 
          variant="filled"
          placeholder="请输入电话号码"
        />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={12}>
      <FormField label="备注" error={errors.notes}>
        <MemoEditor 
          bind:value={formData.notes} 
          variant="filled"
          input$rows={4}
          input$maxLength={300}
          showIndicator
        />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

### 水平布局

```svelte
<FormContainer fieldLayout="horizontal">
  <Row>
    <Cell span={6}>
      <FormField label="开始日期">
        <DatePicker bind:value={startDate} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="结束日期">
        <DatePicker bind:value={endDate} variant="filled" />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={12}>
      <FormField label="描述" label$alignment="top">
        <MemoEditor bind:value={description} variant="filled" />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

## API 参考

### FormContainer

结构化行表单布局的主容器组件。

#### 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `style` | `string` | `''` | 表单容器的自定义CSS样式 |
| `fieldLayout` | `'vertical' \| 'horizontal'` | `'vertical'` | 表单字段的布局模式 |
| `class` | `string` | `''` | 容器的额外CSS类 |

#### 插槽

| 插槽 | 描述 |
|------|-------------|
| default | 包含Row组件的表单内容 |

### Row

用于在水平行中组织单元格的容器组件。

#### 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `style` | `string` | `''` | 行的自定义CSS样式 |
| `class` | `string` | `''` | 行的额外CSS类 |

#### 插槽

| 插槽 | 描述 |
|------|-------------|
| default | 行的Cell组件和内容 |

### Cell

在行内跨越指定列数的网格单元格组件。

#### 属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `span` | `number` | `1` | 跨越的列数（1-12） |
| `style` | `string` | `''` | 单元格的自定义CSS样式 |
| `class` | `string` | `''` | 单元格的额外CSS类 |

#### 插槽

| 插槽 | 描述 |
|------|-------------|
| default | 单元格的内容（通常是FormField组件） |

## 网格系统

FlexRowForm使用12列网格系统，每个Cell可以跨越1-12列：

- **span={1}**: 8.33% 宽度 (1/12)
- **span={2}**: 16.67% 宽度 (2/12)  
- **span={3}**: 25% 宽度 (3/12)
- **span={4}**: 33.33% 宽度 (4/12)
- **span={6}**: 50% 宽度 (6/12)
- **span={8}**: 66.67% 宽度 (8/12)
- **span={12}**: 100% 宽度 (12/12)

## 布局示例

### 多行复杂表单

```svelte
<FormContainer>
  <!-- 标题行 -->
  <Row>
    <Cell span={12}>
      <FormField label="项目标题" required>
        <TextEditor bind:value={project.title} variant="filled" />
      </FormField>
    </Cell>
  </Row>
  
  <!-- 详情行 -->
  <Row>
    <Cell span={4}>
      <FormField label="开始日期" required>
        <DatePicker bind:value={project.startDate} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="结束日期">
        <DatePicker bind:value={project.endDate} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="优先级">
        <OptionsSelect bind:value={project.priority} options={priorities} />
      </FormField>
    </Cell>
  </Row>
  
  <!-- 联系信息行 -->
  <Row>
    <Cell span={6}>
      <FormField label="项目经理">
        <TextEditor bind:value={project.manager} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="联系邮箱">
        <TextEditor bind:value={project.email} variant="filled" />
      </FormField>
    </Cell>
  </Row>
  
  <!-- 描述行 -->
  <Row>
    <Cell span={12}>
      <FormField label="项目描述" label$alignment="top">
        <MemoEditor bind:value={project.description} variant="filled" />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

### 不对称布局

```svelte
<FormContainer>
  <Row>
    <Cell span={8}>
      <FormField label="主要信息">
        <TextEditor bind:value={mainInfo} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="代码">
        <TextEditor bind:value={code} variant="filled" />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={3}>
      <FormField label="类型">
        <OptionsSelect bind:value={type} options={typeOptions} />
      </FormField>
    </Cell>
    
    <Cell span={3}>
      <FormField label="状态">
        <OptionsSelect bind:value={status} options={statusOptions} />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="参考">
        <TextEditor bind:value={reference} variant="filled" />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

### 表单分区

```svelte
<FormContainer>
  <!-- 个人信息分区 -->
  <Row>
    <Cell span={12}>
      <h3>个人信息</h3>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={6}>
      <FormField label="名" required>
        <TextEditor bind:value={personal.firstName} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="姓" required>
        <TextEditor bind:value={personal.lastName} variant="filled" />
      </FormField>
    </Cell>
  </Row>
  
  <!-- 联系信息分区 -->
  <Row>
    <Cell span={12}>
      <h3>联系信息</h3>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={8}>
      <FormField label="邮箱地址" required>
        <TextEditor bind:value={contact.email} variant="filled" />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="电话">
        <TextEditor bind:value={contact.phone} variant="filled" />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

## 验证和错误处理

```svelte
<script>
  let formData = {
    name: '',
    email: '',
    phone: '',
    notes: ''
  };
  
  let errors = {};
  
  function validateForm() {
    errors = {};
    
    if (!formData.name?.trim()) {
      errors.name = '姓名为必填项';
    }
    
    if (!formData.email?.trim()) {
      errors.email = '邮箱为必填项';
    } else if (!/\S+@\S+\.\S+/.test(formData.email)) {
      errors.email = '请输入有效的邮箱地址';
    }
    
    if (formData.phone && !/^\+?[\d\s\-()]+$/.test(formData.phone)) {
      errors.phone = '请输入有效的电话号码';
    }
    
    return Object.keys(errors).length === 0;
  }
  
  function handleSubmit() {
    if (validateForm()) {
      console.log('表单提交:', formData);
    }
  }
</script>

<FormContainer>
  <Row>
    <Cell span={6}>
      <FormField label="姓名" required error={errors.name}>
        <TextEditor 
          bind:value={formData.name}
          variant="filled"
          placeholder="请输入您的姓名"
        />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="电话号码" error={errors.phone}>
        <TextEditor 
          bind:value={formData.phone}
          variant="filled"
          placeholder="请输入电话号码"
        />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={12}>
      <FormField label="邮箱地址" required error={errors.email}>
        <TextEditor 
          bind:value={formData.email}
          variant="filled"
          placeholder="请输入邮箱地址"
        />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={12}>
      <FormField label="备注">
        <MemoEditor 
          bind:value={formData.notes}
          variant="filled"
          placeholder="请输入备注信息..."
        />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <Cell span={12} style="text-align: right; margin-top: 20px;">
      <button type="button" on:click={handleSubmit}>
        提交表单
      </button>
    </Cell>
  </Row>
</FormContainer>
```

## 样式

### 自定义表单样式

```svelte
<FormContainer 
  style="
    max-width: 900px;
    margin: 2rem auto;
    padding: 2rem;
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    background: #ffffff;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  "
>
  <Row style="margin-bottom: 1.5rem;">
    <Cell span={12}>
      <h2 style="margin: 0; color: #2d3748;">表单标题</h2>
    </Cell>
  </Row>
  
  <!-- 表单内容 -->
</FormContainer>
```

### CSS 类

```css
.custom-form-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 2rem;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.custom-form-container .form-row {
  margin-bottom: 1.5rem;
}

.custom-form-container .form-row:last-child {
  margin-bottom: 0;
}

.custom-form-container .form-cell {
  padding: 0 0.5rem;
}
```

## 响应式设计

```svelte
<FormContainer class="responsive-form">
  <Row>
    <Cell span={4}>
      <FormField label="字段1">
        <TextEditor bind:value={field1} />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="字段2">
        <TextEditor bind:value={field2} />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="字段3">
        <TextEditor bind:value={field3} />
      </FormField>
    </Cell>
  </Row>
</FormContainer>

<style>
  @media (max-width: 768px) {
    :global(.responsive-form .form-cell) {
      width: 100% !important;
      margin-bottom: 1rem;
    }
  }
  
  @media (max-width: 480px) {
    :global(.responsive-form) {
      padding: 1rem;
    }
  }
</style>
```

## 最佳实践

### 1. 逻辑行组织

在同一行中分组相关字段：

```svelte
<FormContainer>
  <!-- 一行中的个人详情 -->
  <Row>
    <Cell span={4}>
      <FormField label="名" required>
        <TextEditor bind:value={firstName} />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="姓" required>
        <TextEditor bind:value={lastName} />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="出生日期">
        <DatePicker bind:value={dateOfBirth} />
      </FormField>
    </Cell>
  </Row>
  
  <!-- 另一行中的联系详情 -->
  <Row>
    <Cell span={8}>
      <FormField label="邮箱地址" required>
        <TextEditor bind:value={email} />
      </FormField>
    </Cell>
    
    <Cell span={4}>
      <FormField label="电话">
        <TextEditor bind:value={phone} />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

### 2. 一致的间距

对相似字段类型使用一致的单元格跨度：

```svelte
<FormContainer>
  <Row>
    <!-- 标准文本字段：各6列 -->
    <Cell span={6}>
      <FormField label="用户名" required>
        <TextEditor bind:value={username} />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="部门">
        <TextEditor bind:value={department} />
      </FormField>
    </Cell>
  </Row>
  
  <Row>
    <!-- 重要字段：全宽 -->
    <Cell span={12}>
      <FormField label="描述">
        <MemoEditor bind:value={description} />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

### 3. 表单分区

使用行创建清晰的表单分区：

```svelte
<FormContainer>
  <!-- 分区标题 -->
  <Row>
    <Cell span={12}>
      <h3 style="border-bottom: 1px solid #e2e8f0; padding-bottom: 0.5rem;">
        账户信息
      </h3>
    </Cell>
  </Row>
  
  <!-- 分区字段 -->
  <Row>
    <Cell span={6}>
      <FormField label="用户名" required>
        <TextEditor bind:value={username} />
      </FormField>
    </Cell>
    
    <Cell span={6}>
      <FormField label="邮箱" required>
        <TextEditor bind:value={email} />
      </FormField>
    </Cell>
  </Row>
</FormContainer>
```

## 与FlexForm的比较

| 特性 | FlexRowForm | FlexForm |
|---------|-------------|----------|
| 结构 | 明确的行和单元格 | 自动换行 |
| 布局控制 | 高精度 | 自动流动 |
| 行管理 | 手动换行 | 自动换行 |
| 使用场景 | 复杂结构化表单 | 简单流动表单 |
| 复杂度 | 较高 | 较低 |

## 与其他组件集成

### 动态内容

```svelte
<script>
  let items = [
    { id: 1, name: '', value: '' },
    { id: 2, name: '', value: '' }
  ];
  
  function addItem() {
    items = [...items, { id: Date.now(), name: '', value: '' }];
  }
  
  function removeItem(id) {
    items = items.filter(item => item.id !== id);
  }
</script>

<FormContainer>
  {#each items as item, index}
    <Row>
      <Cell span={5}>
        <FormField label="名称">
          <TextEditor bind:value={item.name} variant="filled" />
        </FormField>
      </Cell>
      
      <Cell span={5}>
        <FormField label="值">
          <TextEditor bind:value={item.value} variant="filled" />
        </FormField>
      </Cell>
      
      <Cell span={2} style="display: flex; align-items: end;">
        <button type="button" on:click={() => removeItem(item.id)}>
          删除
        </button>
      </Cell>
    </Row>
  {/each}
  
  <Row>
    <Cell span={12} style="text-align: center; margin-top: 1rem;">
      <button type="button" on:click={addItem}>
        添加项目
      </button>
    </Cell>
  </Row>
</FormContainer>
```

## 无障碍功能

- **语义结构**: 具有逻辑tab顺序的正确表单组织
- **键盘导航**: 标准表单导航模式
- **屏幕阅读器支持**: 清晰的行和单元格结构
- **错误关联**: 错误消息与字段的正确关联
- **焦点管理**: 通过行和单元格的逻辑焦点流

## 浏览器支持

- **现代浏览器**: Chrome、Firefox、Safari、Edge（最新版本）
- **移动浏览器**: iOS Safari、Chrome Mobile、Firefox Mobile
- **CSS Flexbox**: 布局功能必需

## 相关组件

- **FormField**: 带标签和验证的表单字段包装器
- **FlexForm**: 替代的自动换行表单布局
- **TextEditor**: 单行文本输入组件
- **DatePicker**: 日期选择组件
- **OptionsSelect**: 下拉选择组件

## 许可证

MIT许可证 - 详情请参阅LICENSE文件。