npm package: @squallfire/vuegantt
Description: A powerful Gantt chart component built with Vue 3 and Canvas
Latest version: 0.0.4

# VueGantt

一个功能强大的 Vue 3 甘特图组件库，基于 Canvas 高性能渲染，支持任务管理、依赖关系、主题切换和国际化。

![Vue 3](https://img.shields.io/badge/Vue-3.5+-42b883?style=flat&logo=vue.js)
![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178c6?style=flat&logo=typescript)
![License](https://img.shields.io/badge/license-MIT-green)

## 📷 预览

![VueGantt Preview](docs/screenshot.png)

## ✨ 功能特性

### 核心功能

- 📊 **任务管理** - 支持创建、编辑、删除任务
- 🎯 **拖拽调整** - 拖拽任务条调整日期和进度
- 🔗 **依赖关系** - 支持 FS/SS/FF/SF 四种依赖类型
- 🏁 **里程碑** - 支持里程碑节点显示
- 📁 **任务分组** - 支持父子任务层级关系

### 视图与显示

- 📅 **多种视图** - 支持日/周/月/季度四种视图模式
- 🎨 **主题切换** - 支持亮色和暗色主题
- 🌍 **国际化** - 支持中文和英文
- 📱 **响应式** - 灵活适应不同屏幕尺寸

### 交互功能

- ⌨️ **键盘快捷键** - Delete 删除、Ctrl+C/V 复制粘贴、←→ 移动任务
- 🖱️ **快捷操作面板** - 内置快捷键帮助和滚动操作提示
- 🎡 **鼠标滚轮滚动** - 时间轴区域垂直滚动可触发水平滚动
- 🔄 **滚动同步** - 时间轴滚动时同步更新 Canvas 渲染

## 🚀 快速开始

### 安装

```bash
# 使用 npm
npm install @squallfire/vuegantt

# 使用 pnpm
pnpm add @squallfire/vuegantt
```

### 基础用法

```vue
<script setup lang="ts">
import { GanttChart } from '@squallfire/vuegantt'
import type { GanttTask } from '@squallfire/vuegantt'

const tasks: GanttTask[] = [
  {
    id: '1',
    name: '项目启动',
    startDate: new Date('2024-01-01'),
    endDate: new Date('2024-01-05'),
    progress: 100,
  },
  {
    id: '2',
    name: '需求分析',
    startDate: new Date('2024-01-06'),
    endDate: new Date('2024-01-10'),
    progress: 60,
    dependencies: ['1'],
  },
]
</script>

<template>
  <GanttChart :tasks="tasks" />
</template>
```

## 📖 使用文档

### 任务数据类型

```typescript
interface GanttTask {
  id: string // 唯一标识
  name: string // 任务名称
  startDate: Date // 开始日期
  endDate: Date // 结束日期
  progress: number // 进度 (0-100)
  type?: 'task' | 'milestone' | 'group' // 任务类型
  isMilestone?: boolean // 是否为里程碑
  dependencies?: string[] // 依赖任务ID数组
  dependencyDetails?: TaskDependency[] // 依赖详情
  assignee?: string // 负责人
  description?: string // 描述
  color?: string // 自定义颜色
  isExpanded?: boolean // 是否展开（分组任务）
  children?: GanttTask[] // 子任务
  parentId?: string // 父任务ID
}
```

### 视图模式

```typescript
type ViewMode = 'day' | 'week' | 'month' | 'quarter'
```

| 模式      | 说明     | 适用场景               |
| --------- | -------- | ---------------------- |
| `day`     | 日视图   | 短期任务、详细进度跟踪 |
| `week`    | 周视图   | 中期项目规划（默认）   |
| `month`   | 月视图   | 月度计划、里程碑追踪   |
| `quarter` | 季度视图 | 长期战略规划           |

### Props 配置

| 属性              | 类型                | 默认值    | 说明                 |
| ----------------- | ------------------- | --------- | -------------------- |
| `tasks`           | `GanttTask[]`       | `[]`      | 任务列表             |
| `columns`         | `Column[]`          | 默认列    | 任务列表列配置       |
| `viewMode`        | `ViewMode`          | `'week'`  | 视图模式             |
| `startDate`       | `Date \| undefined` | 自动计算  | 甘特图开始日期       |
| `endDate`         | `Date \| undefined` | 自动计算  | 甘特图结束日期       |
| `theme`           | `'light' \| 'dark'` | `'light'` | 主题                 |
| `locale`          | `'en' \| 'zh-CN'`   | `'zh-CN'` | 语言                 |
| `rowHeight`       | `number`            | `36`      | 行高（像素）         |
| `showWeekends`    | `boolean`           | `true`    | 是否显示周末背景     |
| `showToday`       | `boolean`           | `true`    | 是否高亮今天         |
| `enableDrag`      | `boolean`           | `true`    | 是否启用任务拖拽     |
| `enableResize`    | `boolean`           | `true`    | 是否启用任务调整大小 |
| `enableCreate`    | `boolean`           | `true`    | 是否允许创建任务     |
| `enableEdit`      | `boolean`           | `true`    | 是否允许编辑任务     |
| `enableShortcuts` | `boolean`           | `true`    | 是否启用键盘快捷键   |

### 事件处理

```vue
<script setup lang="ts">
import { GanttChart } from '@squallfire/vuegantt'
import type { GanttTask } from '@squallfire/vuegantt'

function handleTaskClick(task: GanttTask, event: MouseEvent) {
  console.log('点击任务:', task.name)
}

function handleDateChange(task: GanttTask, start: Date, end: Date) {
  console.log('日期变更:', task.name, start, end)
}

function handleProgressChange(task: GanttTask, progress: number) {
  console.log('进度变更:', task.name, progress)
}

function handleTaskAdd(task: Partial<GanttTask>) {
  console.log('新增任务:', task)
}

function handleTaskDelete(taskId: string) {
  console.log('删除任务:', taskId)
}
</script>

<template>
  <GanttChart
    :tasks="tasks"
    @task-click="handleTaskClick"
    @task-date-change="handleDateChange"
    @task-progress-change="handleProgressChange"
    @task-add="handleTaskAdd"
    @task-delete="handleTaskDelete"
  />
</template>
```

| 事件名                 | 参数                 | 说明             |
| ---------------------- | -------------------- | ---------------- |
| `task-click`           | `(task, event)`      | 点击任务         |
| `task-dblclick`        | `(task, event)`      | 双击任务（编辑） |
| `task-change`          | `(task)`             | 任务内容变化     |
| `task-date-change`     | `(task, start, end)` | 任务日期变化     |
| `task-progress-change` | `(task, progress)`   | 任务进度变化     |
| `task-add`             | `(task)`             | 新增任务         |
| `task-delete`          | `(taskId)`           | 删除任务         |
| `view-mode-change`     | `(mode)`             | 视图模式变化     |
| `theme-change`         | `(theme)`            | 主题变化         |
| `locale-change`        | `(locale)`           | 语言变化         |

## 💻 示例代码

### 示例 1：基础甘特图

```vue
<script setup lang="ts">
import { GanttChart } from '@squallfire/vuegantt'
import type { GanttTask } from '@squallfire/vuegantt'
import { ref } from 'vue'

const tasks: GanttTask[] = [
  {
    id: '1',
    name: '项目规划',
    startDate: new Date('2024-01-01'),
    endDate: new Date('2024-01-07'),
    progress: 100,
  },
  {
    id: '2',
    name: '需求分析',
    startDate: new Date('2024-01-08'),
    endDate: new Date('2024-01-14'),
    progress: 80,
    dependencies: ['1'],
  },
  {
    id: '3',
    name: 'UI 设计',
    startDate: new Date('2024-01-15'),
    endDate: new Date('2024-01-21'),
    progress: 50,
    dependencies: ['2'],
  },
  {
    id: '4',
    name: '开发实现',
    startDate: new Date('2024-01-22'),
    endDate: new Date('2024-02-05'),
    progress: 30,
    dependencies: ['3'],
  },
  {
    id: '5',
    name: '测试验收',
    startDate: new Date('2024-02-06'),
    endDate: new Date('2024-02-15'),
    progress: 0,
    dependencies: ['4'],
  },
]

const viewMode = ref<ViewMode>('week')
</script>

<template>
  <div style="height: 500px;">
    <GanttChart :tasks="tasks" v-model:viewMode="viewMode" />
  </div>
</template>
```

### 示例 2：带依赖关系的任务

```vue
<script setup lang="ts">
import { GanttChart } from '@squallfire/vuegantt'
import type { GanttTask, TaskDependency } from '@squallfire/vuegantt'

const tasks: GanttTask[] = [
  {
    id: 'task-1',
    name: '需求收集',
    startDate: new Date('2024-01-01'),
    endDate: new Date('2024-01-05'),
    progress: 100,
  },
  {
    id: 'task-2',
    name: '系统设计',
    startDate: new Date('2024-01-06'),
    endDate: new Date('2024-01-12'),
    progress: 60,
    // 简化版依赖
    dependencies: ['task-1'],
  },
  {
    id: 'task-3',
    name: '编码开发',
    startDate: new Date('2024-01-13'),
    endDate: new Date('2024-01-25'),
    progress: 30,
    // 详细依赖配置
    dependencyDetails: [
      {
        taskId: 'task-3',
        dependsOn: 'task-2',
        type: 'FS', // Finish to Start
        style: 'solid',
      },
    ],
  },
]
</script>

<template>
  <div style="height: 400px;">
    <GanttChart :tasks="tasks" />
  </div>
</template>
```

### 示例 3：里程碑和自定义颜色

```vue
<script setup lang="ts">
import { GanttChart } from '@squallfire/vuegantt'
import type { GanttTask } from '@squallfire/vuegantt'

const tasks: GanttTask[] = [
  {
    id: 'milestone-1',
    name: '项目启动会',
    startDate: new Date('2024-01-01'),
    endDate: new Date('2024-01-01'),
    progress: 100,
    isMilestone: true,
    color: '#f59e0b', // 橙色里程碑
  },
  {
    id: 'task-1',
    name: '第一阶段开发',
    startDate: new Date('2024-01-02'),
    endDate: new Date('2024-01-20'),
    progress: 50,
    color: '#3b82f6', // 蓝色
  },
  {
    id: 'milestone-2',
    name: '阶段验收',
    startDate: new Date('2024-01-21'),
    endDate: new Date('2024-01-21'),
    progress: 100,
    isMilestone: true,
    color: '#10b981', // 绿色里程碑
    dependencies: ['task-1'],
  },
  {
    id: 'task-2',
    name: '第二阶段开发',
    startDate: new Date('2024-01-22'),
    endDate: new Date('2024-02-10'),
    progress: 0,
    color: '#8b5cf6', // 紫色
    dependencies: ['task-1'],
  },
]
</script>

<template>
  <div style="height: 400px;">
    <GanttChart :tasks="tasks" />
  </div>
</template>
```

### 示例 4：主题切换

```vue
<script setup lang="ts">
import { GanttChart } from '@squallfire/vuegantt'
import type { GanttTask } from '@squallfire/vuegantt'
import { ref } from 'vue'

const tasks: GanttTask[] = [...]

const theme = ref<'light' | 'dark'>('light')

function toggleTheme() {
  theme.value = theme.value === 'light' ? 'dark' : 'light'
}

function handleThemeChange(newTheme: 'light' | 'dark') {
  console.log('主题已切换:', newTheme)
}
</script>

<template>
  <div>
    <button @click="toggleTheme">
      {{ theme === 'light' ? '🌙 切换暗色' : '☀️ 切换亮色' }}
    </button>
    <GanttChart
      :tasks="tasks"
      :theme="theme"
      @theme-change="handleThemeChange"
      style="height: 500px;"
    />
  </div>
</template>
```

### 示例 5：国际化

```vue
<script setup lang="ts">
import { GanttChart } from '@squallfire/vuegantt'
import type { GanttTask, ViewMode } from '@squallfire/vuegantt'
import { ref } from 'vue'

const tasks: GanttTask[] = [...]

const locale = ref<'en' | 'zh-CN'>('zh-CN')
const viewMode = ref<ViewMode>('week')
</script>

<template>
  <div>
    <div class="controls">
      <select v-model="locale">
        <option value="zh-CN">中文</option>
        <option value="en">English</option>
      </select>
      <select v-model="viewMode">
        <option value="day">日视图</option>
        <option value="week">周视图</option>
        <option value="month">月视图</option>
        <option value="quarter">季度视图</option>
      </select>
    </div>
    <GanttChart
      :tasks="tasks"
      :locale="locale"
      v-model:viewMode="viewMode"
      style="height: 500px;"
    />
  </div>
</template>
```

> 📁 更多示例请参考 `examples/` 文件夹

## ⌨️ 键盘快捷键

| 快捷键     | 功能                 |
| ---------- | -------------------- |
| `Delete`   | 删除选中任务         |
| `Ctrl + C` | 复制任务             |
| `Ctrl + V` | 粘贴任务             |
| `←`        | 向左移动任务（一天） |
| `→`        | 向右移动任务（一天） |
| `Esc`      | 取消选中 / 关闭弹窗  |

## 📁 项目结构

```
@squallfire/vuegantt/
├── src/
│   ├── components/
│   │   └── gantt/
│   │       ├── GanttChart.vue      # 主组件
│   │       ├── TaskList.vue       # 任务列表
│   │       ├── TimeAxis.vue       # 时间轴
│   │       ├── interaction/       # 交互组件
│   │       └── dialogs/           # 对话框
│   ├── renderer/
│   │   └── canvas/                # Canvas 渲染器
│   ├── stores/                    # Pinia 状态管理
│   ├── composables/               # Vue 组合式函数
│   ├── types/                    # TypeScript 类型定义
│   └── i18n/                     # 国际化
├── examples/                      # 示例代码
│   ├── basic/                     # 基础示例
│   ├── theme/                     # 主题切换示例
│   ├── view-mode/                 # 视图模式示例
│   └── i18n/                      # 国际化示例
├── docs/                         # 文档
└── package.json
```

## 🧪 在线示例

项目提供了完整的在线示例，可以直接运行：

```bash
# 进入示例目录
cd examples/basic     # 基础示例
cd examples/theme     # 主题切换示例
cd examples/view-mode # 视图模式示例
cd examples/i18n      # 国际化示例

# 运行示例
pnpm dev
```

| 示例目录             | 说明                                     |
| -------------------- | ---------------------------------------- |
| `examples/basic`     | 基础甘特图，包含任务创建、拖拽、依赖关系 |
| `examples/theme`     | 亮色/暗色主题切换                        |
| `examples/view-mode` | 日/周/月/季度视图切换                    |
| `examples/i18n`      | 中英文国际化                             |

## 🛠️ 开发命令

```bash
# 安装依赖
pnpm install

# 开发模式
pnpm dev

# 构建
pnpm build

# 运行测试
pnpm test

# 代码格式检查
pnpm lint
```

## 📄 许可证

MIT License - 请随意使用和修改。

## 🤝 贡献

欢迎提交 Issue 和 Pull Request！