# 页面组件

一个全面的页面容器组件，提供标准化的页面布局，包括头部、内容区域和导航操作。

## 功能

- **标准化布局**：跨应用的统一页面结构
- **头部组件**：内置页面头部，包含标题和描述
- **导航操作**：支持返回和刷新功能
- **灵活样式**：支持自定义外观，带阴影和圆角
- **插槽系统**：可扩展的头部和内容区域
- **响应式设计**：适配不同屏幕尺寸
- **操作集成**：轻松集成导航和刷新操作

## 安装

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

## 基本用法

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
</script>

<Page title="我的页面" comment="这是一个示例页面">
  <div>页面内容在这里</div>
</Page>
```

## API 参考

### 页面属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `title` | `string` | `''` | 头部显示的页面标题 |
| `comment` | `string` | `null` | 副标题或描述文本 |
| `header$style` | `string` | `''` | 头部区域的自定义 CSS 样式 |
| `content$style` | `string` | `''` | 内容区域的自定义 CSS 样式 |
| `round` | `boolean` | `false` | 为页面容器应用圆角 |
| `shadow` | `boolean` | `true` | 为页面容器应用阴影效果 |
| `goBack` | `PageAction \| null` | `null` | 返回按钮操作处理程序 |
| `reload` | `PageAction \| null` | `null` | 刷新按钮操作处理程序 |
| `style` | `string` | `''` | 页面包装器的自定义 CSS 样式 |

### 页面插槽

| 插槽 | 描述 |
|------|-------------|
| `default` | 页面的主要内容区域 |
| `page-header` | 替换整个头部组件 |
| `header-ext` | 头部中的附加内容（如按钮等） |

### 页面头部属性

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `title` | `string` | `''` | 头部标题文本 |
| `comment` | `string` | `''` | 头部副标题/描述 |
| `goBack` | `PageAction \| null` | `null` | 返回导航操作 |
| `reload` | `PageAction \| null` | `null` | 刷新操作 |

### 类型

```typescript
export type PageAction = () => any;
```

## 示例

### 基本页面布局

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
</script>

<Page 
  title="仪表盘" 
  comment="你的应用指标概览"
>
  <div style="padding: 20px;">
    <h2>欢迎体验你的仪表盘</h2>
    <p>在这里你可以查看所有重要的指标和数据。</p>
  </div>
</Page>
```

### 带导航的页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
  import { goto } from '$app/navigation';
  
  function handleGoBack() {
    goto('/dashboard');
  }
  
  function handleReload() {
    window.location.reload();
  }
</script>

<Page 
  title="用户资料" 
  comment="管理你的账户设置"
  goBack={handleGoBack}
  reload={handleReload}
>
  <div style="padding: 20px;">
    <form>
      <!-- 资料表单内容 -->
    </form>
  </div>
</Page>
```

### 带圆角样式的页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
</script>

<Page 
  title="设置" 
  comment="配置你的偏好"
  round
  shadow
  style="max-width: 800px; margin: 0 auto;"
>
  <div style="padding: 24px;">
    <div class="settings-section">
      <h3>常规设置</h3>
      <!-- 设置内容 -->
    </div>
  </div>
</Page>
```

### 带头部扩展的页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
  import Button from '@ticatec/uniface-element/Button';
  
  function handleSave() {
    console.log('保存数据...');
  }
  
  function handleCancel() {
    console.log('取消...');
  }
  
  function handleExport() {
    console.log('导出数据...');
  }
</script>

<Page 
  title="文档编辑器" 
  comment="编辑你的文档内容"
  round
>
  <div slot="header-ext" style="display: flex; gap: 8px;">
    <Button type="primary" label="保存" onClick={handleSave} />
    <Button type="secondary" label="取消" onClick={handleCancel} />
    <Button type="third" label="导出" onClick={handleExport} />
  </div>
  
  <div style="padding: 20px;">
    <textarea 
      style="width: 100%; height: 400px; border: 1px solid #ccc; padding: 12px;"
      placeholder="开始输入你的文档..."
    ></textarea>
  </div>
</Page>
```

### 数据表格页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
  import Button from '@ticatec/uniface-element/Button';
  import DataTable from '@ticatec/uniface-element/DataTable';
  
  let users = [
    { id: 1, name: 'John Doe', email: 'john@example.com', role: '管理员' },
    { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: '用户' },
    { id: 3, name: 'Bob Wilson', email: 'bob@example.com', role: '用户' }
  ];
  
  function handleAddUser() {
    console.log('添加新用户...');
  }
  
  function handleRefresh() {
    console.log('刷新用户列表...');
  }
</script>

<Page 
  title="用户管理" 
  comment="管理系统用户和权限"
  reload={handleRefresh}
  shadow
>
  <div slot="header-ext">
    <Button type="primary" label="添加用户" onClick={handleAddUser} />
  </div>
  
  <div style="padding: 20px;">
    <DataTable 
      data={users}
      columns={[
        { field: 'name', title: '姓名' },
        { field: 'email', title: '邮箱' },
        { field: 'role', title: '角色' }
      ]}
    />
  </div>
</Page>
```

### 带验证的表单页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
  import Button from '@ticatec/uniface-element/Button';
  import FormField from '@ticatec/uniface-element/FormField';
  import TextEditor from '@ticatec/uniface-element/TextEditor';
  
  let formData = {
    title: '',
    description: '',
    category: ''
  };
  
  let isValid = false;
  
  $: isValid = formData.title && formData.description;
  
  function handleGoBack() {
    if (hasUnsavedChanges()) {
      if (confirm('你有未保存的更改，确定要离开吗？')) {
        history.back();
      }
    } else {
      history.back();
    }
  }
  
  function hasUnsavedChanges() {
    return formData.title || formData.description || formData.category;
  }
  
  function handleSubmit() {
    if (isValid) {
      console.log('提交表单：', formData);
    }
  }
  
  function handleReset() {
    formData = { title: '', description: '', category: '' };
  }
</script>

<Page 
  title="创建新项目" 
  comment="填写表单以创建新项目"
  goBack={handleGoBack}
  round
>
  <div slot="header-ext" style="display: flex; gap: 8px;">
    <Button 
      type="primary" 
      label="提交" 
      disabled={!isValid}
      onClick={handleSubmit} 
    />
    <Button type="secondary" label="重置" onClick={handleReset} />
  </div>
  
  <div style="padding: 24px;">
    <div style="max-width: 600px;">
      <FormField label="标题" required>
        <TextEditor 
          variant="outlined" 
          bind:value={formData.title}
          placeholder="输入项目标题"
        />
      </FormField>
      
      <FormField label="描述" required>
        <TextEditor 
          variant="outlined" 
          bind:value={formData.description}
          placeholder="输入描述"
        />
      </FormField>
      
      <FormField label="类别">
        <TextEditor 
          variant="outlined" 
          bind:value={formData.category}
          placeholder="输入类别"
        />
      </FormField>
    </div>
  </div>
</Page>
```

### 自定义头部页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
  import Icon from '@ticatec/uniface-element/Icon';
  
  function handleSearch() {
    console.log('搜索中...');
  }
  
  function handleFilter() {
    console.log('过滤中...');
  }
</script>

<Page style="height: 100vh;">
  <div slot="page-header" class="custom-header">
    <div class="header-left">
      <Icon name="icon_google_apps" />
      <h1>自定义仪表盘</h1>
    </div>
    <div class="header-center">
      <input 
        type="search" 
        placeholder="搜索..." 
        class="search-input"
      />
    </div>
    <div class="header-right">
      <Icon name="icon_google_search" onClick={handleSearch} />
      <Icon name="icon_google_filter_list" onClick={handleFilter} />
    </div>
  </div>
  
  <div style="padding: 20px; height: 100%; overflow-y: auto;">
    <!-- 页面内容 -->
  </div>
</Page>

<style>
  .custom-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 24px;
    background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
    color: white;
  }
  
  .header-left {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  
  .header-left h1 {
    margin: 0;
    font-size: 24px;
    font-weight: 600;
  }
  
  .search-input {
    padding: 8px 16px;
    border: none;
    border-radius: 20px;
    width: 300px;
    outline: none;
  }
  
  .header-right {
    display: flex;
    gap: 16px;
  }
</style>
```

### 仪表盘概览页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
  import Card from '@ticatec/uniface-element/Card';
  
  let stats = [
    { title: '总用户数', value: '1,234', change: '+12%' },
    { title: '收入', value: '$45,678', change: '+5.2%' },
    { title: '订单', value: '890', change: '-2.1%' },
    { title: '转化率', value: '3.2%', change: '+0.8%' }
  ];
  
  function handleRefresh() {
    console.log('刷新仪表盘数据...');
    // 刷新逻辑
  }
</script>

<Page 
  title="分析仪表盘" 
  comment="实时业务指标和洞察"
  reload={handleRefresh}
  shadow={false}
  content$style="background-color: #f5f5f5;"
>
  <div style="padding: 24px;">
    <div class="stats-grid">
      {#each stats as stat}
        <Card style="padding: 20px; text-align: center;">
          <h3 style="margin: 0 0 8px 0; color: #666;">{stat.title}</h3>
          <div style="font-size: 32px; font-weight: bold; margin: 8px 0;">
            {stat.value}
          </div>
          <div style="color: {stat.change.startsWith('+') ? '#4caf50' : '#f44336'};">
            {stat.change}
          </div>
        </Card>
      {/each}
    </div>
    
    <div style="margin-top: 24px;">
      <Card style="padding: 24px;">
        <h3>近期活动</h3>
        <!-- 活动内容 -->
      </Card>
    </div>
  </div>
</Page>

<style>
  .stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 20px;
  }
</style>
```

### 移动响应式页面

```svelte
<script>
  import Page from '@ticatec/uniface-element/Page';
  import Button from '@ticatec/uniface-element/Button';
  
  let isMobile = false;
  
  // 在挂载时检查是否为移动端
  import { onMount } from 'svelte';
  onMount(() => {
    isMobile = window.innerWidth < 768;
    
    const handleResize = () => {
      isMobile = window.innerWidth < 768;
    };
    
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  });
  
  function handleGoBack() {
    history.back();
  }
</script>

<Page 
  title="移动端示例" 
  comment="响应式页面设计"
  goBack={handleGoBack}
  round={!isMobile}
  shadow={!isMobile}
  style={isMobile ? 'height: 100vh; margin: 0;' : 'max-width: 800px; margin: 20px auto;'}
>
  <div style="padding: {isMobile ? '16px' : '24px'};">
    <div class="responsive-content">
      <h2>响应式内容</h2>
      <p>此页面适配移动端和桌面端屏幕。</p>
      
      <div class="button-group">
        <Button type="primary" label="操作 1" />
        <Button type="secondary" label="操作 2" />
      </div>
    </div>
  </div>
</Page>

<style>
  .responsive-content {
    max-width: 100%;
  }
  
  .button-group {
    display: flex;
    gap: 12px;
    margin-top: 20px;
  }
  
  @media (max-width: 767px) {
    .button-group {
      flex-direction: column;
    }
  }
</style>
```

## 最佳实践

1. **一致的布局**：对所有主要应用屏幕使用页面组件
2. **导航**：根据需要提供适当的返回/刷新操作
3. **内容组织**：使用适当的间距并逻辑组织内容
4. **移动响应式**：考虑移动端布局和触摸交互
5. **头部扩展**：使用头部插槽添加页面特定的操作
6. **加载状态**：在数据获取期间显示加载指示器
7. **错误处理**：提供适当的错误状态和恢复选项

## 样式

页面组件提供多个用于样式的 CSS 类：

```css
.uniface-page-wrapper {
  /* 页面包装容器 */
  width: 100%;
  height: 100%;
}

.uniface-page {
  /* 主页面容器 */
  display: flex;
  flex-direction: column;
  height: 100%;
  background: white;
}

.uniface-page.shadow {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.uniface-page.round {
  border-radius: 8px;
  overflow: hidden;
}

.uniface-page-header {
  /* 头部区域 */
  flex: 0 0 auto;
  padding: 16px 24px;
  border-bottom: 1px solid #e0e0e0;
  background: #fafafa;
}

.page-container {
  /* 内容区域 */
  flex: 1 1 auto;
  overflow: hidden;
}

.page-topic {
  /* 页面标题 */
  font-size: 24px;
  font-weight: 600;
  margin-bottom: 4px;
}

.page-comment {
  /* 页面副标题 */
  font-size: 14px;
  color: #666;
}
```

## 可访问性

- 使用语义化 HTML 提供适当的标题层级
- 支持所有交互元素的键盘导航
- 为导航操作提供 ARIA 标签
- 模态式使用的焦点管理
- 屏幕阅读器兼容性
- 支持高对比度模式

## 相关组件

- [页面头部](./PageHeader.md) - 独立的头部组件
- [卡片](../card/README.md) - 用于页面内的内容部分
- [按钮](../button/README.md) - 用于页面操作
- [操作栏](../action-bar/README.md) - 用于多个页面操作