# Card 卡片组件

一个灵活的卡片容器组件，以结构化格式显示内容，具有可选的头部、操作栏和各种样式选项。非常适合显示结构化信息、用户资料、产品详情等。

## 功能特性

- **灵活结构**: 头部、内容和操作栏部分
- **多种头部选项**: 简单标题或通过插槽自定义头部内容
- **操作栏支持**: 内置操作按钮，支持图标/图片和回调函数
- **视觉变体**: 平面和3D阴影变体
- **自定义样式**: 灵活的样式定制
- **基于插槽的内容**: 通过插槽支持丰富内容
- **交互操作**: 点击处理，具备防抖和悬停提示功能

## 基本用法

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

const cardData = { id: 1, name: '张三' };
</script>

<Card 
  title="用户资料"
  data={cardData}
>
  <p>这是卡片的内容区域。</p>
</Card>
```

## 属性参数

| 属性 | 类型 | 默认值 | 描述 |
|------|------|---------|-------------|
| `style` | `string` | `''` | 自定义CSS样式 |
| `title` | `string` | `null` | 简单头部标题文本 |
| `actions` | `CardAction[]` | `[]` | 操作按钮数组 |
| `variant` | `'plain' \| '3d'` | `'plain'` | 卡片视觉变体 |
| `iconColor` | `string \| null` | `null` | 操作图标的自定义颜色 |
| `data` | `any` | `null` | 传递给操作回调的数据对象 |

## CardAction 接口

```typescript
interface CardAction {
  icon?: string;          // 图标字体类（如FontAwesome）
  img?: string;           // 自定义图标的图片URL
  hint?: string;          // 悬停时的工具提示文本
  disabled?: boolean;     // 操作是否禁用
  callback: (data: any) => void;  // 操作回调函数
}
```

## 插槽

| 插槽 | 描述 |
|------|-------------|
| `header-bar` | 自定义头部内容（覆盖title属性） |
| `default` | 主要卡片内容 |
| `action-bar` | 自定义操作栏内容（当没有actions属性时） |

## 卡片变体

```svelte
<!-- 平面卡片（默认） -->
<Card title="平面卡片" variant="plain">
  <p>简单的扁平卡片设计</p>
</Card>

<!-- 3D阴影卡片 -->
<Card title="3D卡片" variant="3d">
  <p>带阴影效果的卡片</p>
</Card>
```

## 带操作的卡片

```svelte
<script>
import Card, { type CardAction } from '@ticatec/uniface-element/Card';

const userData = { id: 1, name: '张三', email: 'zhang@example.com' };

const actions: CardAction[] = [
  {
    icon: 'fas fa-edit',
    hint: '编辑用户',
    callback: (data) => editUser(data)
  },
  {
    icon: 'fas fa-trash',
    hint: '删除用户',
    callback: (data) => deleteUser(data)
  },
  {
    icon: 'fas fa-share',
    hint: '分享资料',
    callback: (data) => shareProfile(data)
  }
];

const editUser = (user) => {
  console.log('编辑用户:', user);
};

const deleteUser = (user) => {
  console.log('删除用户:', user);
};

const shareProfile = (user) => {
  console.log('分享资料:', user);
};
</script>

<Card 
  title="用户资料"
  {actions}
  data={userData}
  variant="3d"
>
  <div class="profile-content">
    <h3>{userData.name}</h3>
    <p>{userData.email}</p>
  </div>
</Card>
```

## 自定义头部插槽

```svelte
<Card variant="3d">
  <div slot="header-bar" class="custom-header">
    <div class="header-left">
      <img src="/avatar.jpg" alt="用户" class="avatar" />
      <h3>张三</h3>
    </div>
    <div class="header-right">
      <span class="status online">在线</span>
    </div>
  </div>
  
  <div class="profile-details">
    <p>软件开发工程师</p>
    <p>北京市</p>
  </div>
</Card>

<style>
  .custom-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 16px;
  }
  
  .header-left {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  
  .avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
  }
  
  .status.online {
    color: #22c55e;
    font-weight: 500;
  }
</style>
```

## 自定义操作栏

```svelte
<Card title="项目卡片">
  <div class="project-info">
    <h4>项目 Alpha</h4>
    <p>一个革命性的新应用程序</p>
  </div>
  
  <div slot="action-bar" class="custom-actions">
    <button class="btn-primary">查看详情</button>
    <button class="btn-secondary">编辑</button>
    <button class="btn-danger">删除</button>
  </div>
</Card>
```

## 高级示例

### 产品卡片

```svelte
<script>
const product = {
  id: 101,
  name: '无线耳机',
  price: 199.99,
  image: '/headphones.jpg'
};

const productActions = [
  {
    icon: 'fas fa-heart',
    hint: '添加到收藏',
    callback: (data) => addToFavorites(data)
  },
  {
    icon: 'fas fa-shopping-cart',
    hint: '添加到购物车',
    callback: (data) => addToCart(data)
  },
  {
    icon: 'fas fa-share',
    hint: '分享产品',
    callback: (data) => shareProduct(data)
  }
];
</script>

<Card 
  actions={productActions}
  data={product}
  variant="3d"
  style="max-width: 300px;"
>
  <div slot="header-bar" class="product-header">
    <img src={product.image} alt={product.name} class="product-image" />
  </div>
  
  <div class="product-details">
    <h3>{product.name}</h3>
    <div class="price">¥{product.price}</div>
    <div class="rating">
      ⭐⭐⭐⭐⭐ (128 条评价)
    </div>
  </div>
</Card>
```

### 仪表板小部件

```svelte
<script>
const widgetData = { 
  title: '销售概览',
  value: 12345,
  change: '+15.3%'
};

const widgetActions = [
  {
    icon: 'fas fa-refresh',
    hint: '刷新数据',
    callback: (data) => refreshWidget(data)
  },
  {
    icon: 'fas fa-cog',
    hint: '设置',
    callback: (data) => openSettings(data)
  }
];
</script>

<Card 
  title={widgetData.title}
  actions={widgetActions}
  data={widgetData}
  iconColor="#007acc"
>
  <div class="widget-content">
    <div class="metric-value">¥{widgetData.value.toLocaleString()}</div>
    <div class="metric-change positive">{widgetData.change}</div>
  </div>
</Card>

<style>
  .widget-content {
    text-align: center;
    padding: 20px;
  }
  
  .metric-value {
    font-size: 2rem;
    font-weight: bold;
    color: #333;
  }
  
  .metric-change {
    font-size: 1rem;
    margin-top: 8px;
  }
  
  .metric-change.positive {
    color: #22c55e;
  }
</style>
```

### 博客文章卡片

```svelte
<script>
const post = {
  id: 1,
  title: 'Svelte 入门指南',
  excerpt: '学习 Svelte 框架的基础知识...',
  author: '李小明',
  date: '2024-03-15',
  tags: ['svelte', 'javascript', '教程']
};

const postActions = [
  {
    icon: 'fas fa-bookmark',
    hint: '收藏文章',
    callback: (data) => bookmarkPost(data)
  },
  {
    icon: 'fas fa-share',
    hint: '分享文章',
    callback: (data) => sharePost(data)
  }
];
</script>

<Card 
  actions={postActions}
  data={post}
  variant="plain"
>
  <div slot="header-bar" class="post-header">
    <h2 class="post-title">{post.title}</h2>
    <div class="post-meta">
      <span>作者：{post.author}</span>
      <span>{post.date}</span>
    </div>
  </div>
  
  <div class="post-content">
    <p>{post.excerpt}</p>
    <div class="tags">
      {#each post.tags as tag}
        <span class="tag">#{tag}</span>
      {/each}
    </div>
  </div>
</Card>
```

### 联系人卡片

```svelte
<script>
const contact = {
  name: '王小红',
  role: '项目经理',
  email: 'wang@company.com',
  phone: '+86 138-0013-8000',
  avatar: '/sarah.jpg'
};

const contactActions = [
  {
    icon: 'fas fa-envelope',
    hint: '发送邮件',
    callback: (data) => sendEmail(data.email)
  },
  {
    icon: 'fas fa-phone',
    hint: '拨打电话',
    callback: (data) => makeCall(data.phone)
  },
  {
    icon: 'fas fa-edit',
    hint: '编辑联系人',
    callback: (data) => editContact(data)
  }
];
</script>

<Card 
  actions={contactActions}
  data={contact}
  variant="3d"
>
  <div class="contact-card">
    <img src={contact.avatar} alt={contact.name} class="contact-avatar" />
    <h3>{contact.name}</h3>
    <p class="contact-role">{contact.role}</p>
    <div class="contact-info">
      <div class="contact-item">
        <i class="fas fa-envelope"></i>
        <span>{contact.email}</span>
      </div>
      <div class="contact-item">
        <i class="fas fa-phone"></i>
        <span>{contact.phone}</span>
      </div>
    </div>
  </div>
</Card>
```

### 设置卡片

```svelte
<script>
let notifications = true;
let darkMode = false;

const settingsData = { notifications, darkMode };

const saveSettings = (data) => {
  console.log('保存设置:', data);
  // 保存设置逻辑
};

const resetSettings = (data) => {
  notifications = true;
  darkMode = false;
};

const settingsActions = [
  {
    icon: 'fas fa-save',
    hint: '保存设置',
    callback: saveSettings
  },
  {
    icon: 'fas fa-undo',
    hint: '重置为默认值',
    callback: resetSettings
  }
];
</script>

<Card 
  title="偏好设置"
  actions={settingsActions}
  data={settingsData}
>
  <div class="settings-form">
    <div class="setting-item">
      <label>
        <input type="checkbox" bind:checked={notifications} />
        启用通知
      </label>
    </div>
    <div class="setting-item">
      <label>
        <input type="checkbox" bind:checked={darkMode} />
        深色模式
      </label>
    </div>
  </div>
</Card>
```

## 操作类型

### 图标操作

```svelte
<script>
const iconActions = [
  {
    icon: 'fas fa-star',
    hint: '标记为收藏',
    callback: (data) => toggleFavorite(data)
  },
  {
    icon: 'fas fa-download',
    hint: '下载',
    callback: (data) => downloadFile(data)
  }
];
</script>
```

### 图片操作

```svelte
<script>
const imageActions = [
  {
    img: '/icons/custom-icon.svg',
    hint: '自定义操作',
    callback: (data) => customAction(data)
  }
];
</script>
```

### 禁用操作

```svelte
<script>
const mixedActions = [
  {
    icon: 'fas fa-edit',
    hint: '编辑（可用）',
    callback: (data) => editItem(data)
  },
  {
    icon: 'fas fa-trash',
    hint: '删除（不可用）',
    disabled: true,
    callback: (data) => deleteItem(data)
  }
];
</script>
```

## 样式定制

组件使用以下CSS类：

- `.uniface-card` - 主卡片容器
- `.shadowBox` - 当variant="3d"时应用
- `.card-header` - 头部部分容器
- `.card-header.simple` - 仅标题的简单头部
- `.card-content` - 主要内容区域
- `.card-action-bar` - 操作栏容器
- `.card-action-bar.simple` - 内置操作栏
- `.action-item` - 单个操作按钮
- `.action-item.disabled` - 禁用操作样式

### CSS示例

```css
.uniface-card {
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  background: white;
  overflow: hidden;
}

.uniface-card.shadowBox {
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.card-header {
  border-bottom: 1px solid #e5e7eb;
  padding: 16px;
  background: #f9fafb;
}

.card-content {
  padding: 16px;
}

.card-action-bar {
  border-top: 1px solid #e5e7eb;
  padding: 8px 16px;
  background: #f9fafb;
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}

.action-item {
  cursor: pointer;
  padding: 8px;
  border-radius: 4px;
  transition: background-color 0.2s;
}

.action-item:hover:not(.disabled) {
  background: rgba(0, 0, 0, 0.05);
}

.action-item.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
```

## 最佳实践

1. **一致的数据结构**: 为类似的卡片类型使用一致的数据对象
2. **有意义的操作**: 提供清晰、可操作的操作，并配有描述性提示
3. **适当的变体**: 谨慎使用3D变体以强调重点
4. **可访问的内容**: 确保内容可读且操作标签清晰
5. **响应式设计**: 考虑卡片在不同屏幕尺寸上的堆叠和调整
6. **加载状态**: 为动态内容显示加载指示器
7. **错误处理**: 优雅地处理操作回调错误

## 常见模式

### 卡片网格

```svelte
<div class="card-grid">
  {#each items as item}
    <Card title={item.title} actions={cardActions} data={item}>
      <p>{item.description}</p>
    </Card>
  {/each}
</div>

<style>
  .card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 16px;
    padding: 16px;
  }
</style>
```

### 卡片列表

```svelte
<div class="card-list">
  {#each items as item}
    <Card variant="plain" actions={listActions} data={item}>
      <div class="list-item">
        <h4>{item.title}</h4>
        <p>{item.description}</p>
      </div>
    </Card>
  {/each}
</div>
```

### 仪表板布局

```svelte
<div class="dashboard">
  <div class="dashboard-row">
    <Card title="收入" variant="3d">
      <div class="metric">¥45,230</div>
    </Card>
    <Card title="用户" variant="3d">
      <div class="metric">1,234</div>
    </Card>
  </div>
</div>
```

## 无障碍访问

- 在卡片内容中使用语义化HTML
- 为屏幕阅读器提供有意义的操作提示
- 确保足够的颜色对比度
- 支持操作的键盘导航
- 在卡片内容中使用适当的标题层级

## 浏览器支持

Card组件在支持以下特性的所有现代浏览器中工作：
- ES6+ JavaScript
- CSS Grid 和 Flexbox
- 现代DOM API

## 性能

- 高效的操作处理，内置防抖功能
- 通过正确的key使用实现最小重新渲染
- 轻量级DOM结构
- 可选的卡片内容懒加载