Files
jordium-gantt-vue3/README.md
2025-06-29 20:21:53 +08:00

30 KiB
Raw Blame History

jordium-gantt-vue3

Vue3 甘特图/Gantt 组件库,支持任务、里程碑、虚拟滚动、主题切换、弹窗交互、全局样式共通化等。

特性

  • 任务/里程碑可视化、可编辑
  • 虚拟滚动与性能优化
  • 全局样式统一与主题变量
  • 删除确认弹窗统一美化
  • 组件/类型解耦,命名规范
  • 支持多语言与自定义扩展

快速开始

npm install jordium-gantt-vue3
import { GanttChart } from 'jordium-gantt-vue3'

主要组件

  • GanttChart
  • TaskList / TaskRow
  • MilestonePoint
  • GanttToolbar
  • GanttConfirmDialog

License

MIT

Gantt Chart API 使用指南

📖 概述

Jordium Gantt Vue3 组件提供了灵活的API接口允许开发者自定义TaskBar双击事件的处理逻辑可以完全替换默认的编辑行为。组件采用Vue3 + TypeScript构建样式延续Element Plus设计风格但不依赖Element Plus组件库。

🚀 API 接口

GanttChart Props

属性名 类型 默认值 描述
tasks Task[] [] 任务数据数组,支持嵌套结构(树形数据)
onTaskDoubleClick (task: Task) => void undefined 自定义双击事件处理器当TaskBar被双击时触发
editComponent any undefined 自定义编辑组件(预留接口,暂未实现)
useDefaultDrawer boolean true 是否使用默认的TaskDrawer抽屉组件进行编辑
onTaskDelete (task: Task) => void undefined 自定义删除事件处理器,当删除按钮被点击时触发
showToolbar boolean true 是否显示工具栏
toolbarConfig ToolbarConfig {} 工具栏配置选项
onAddTask () => void undefined 新增任务按钮点击事件处理器
onExportCsv () => void | boolean undefined 导出CSV按钮点击事件处理器返回false使用默认实现
onExportPdf () => void undefined 导出PDF按钮点击事件处理器
onLanguageChange (lang: 'zh' | 'en') => void undefined 语言切换事件处理器
onThemeChange (isDark: boolean) => void undefined 主题切换事件处理器
onFullscreenChange (isFullscreen: boolean) => void undefined 全屏切换事件处理器

ToolbarConfig 接口定义

interface ToolbarConfig {
  showAddTask?: boolean        // 是否显示新增任务按钮默认true
  showExportCsv?: boolean      // 是否显示导出CSV按钮默认true
  showExportPdf?: boolean      // 是否显示导出PDF按钮默认true
  showLanguage?: boolean       // 是否显示语言切换按钮默认true
  showTheme?: boolean          // 是否显示主题切换按钮默认true
  showFullscreen?: boolean     // 是否显示全屏切换按钮默认true
}

API 工作机制

  1. 双击优先级: 当提供 onTaskDoubleClick将优先调用自定义处理器默认的TaskDrawer不会打开
  2. 双击一致性: TaskList中任务行的双击与Timeline中TaskBar的双击具有完全相同的效果和优先级
  3. 删除优先级: 当提供 onTaskDelete 时,将优先调用自定义删除处理器,否则使用默认删除行为
  4. 默认行为: 当未提供 onTaskDoubleClickuseDefaultDrawertrue双击TaskBar或TaskRow会打开内置的TaskDrawer
  5. 完全自定义: 设置 useDefaultDrawer: false 可以完全禁用默认抽屉,只使用自定义处理器
  6. 数据更新机制:
    • TaskDrawer更新任务 → Timeline本地更新 → 发送task-updated事件 → TaskList更新数据源
    • TaskList数据更新 → 发送tasks-changed事件 → Timeline重新渲染TaskBar
    • TaskBar位置变化 → 自动重新报告位置 → 依赖关系线自动重新计算
  7. CSV导出机制:
    • 当提供 onExportCsv 时,优先调用自定义处理器
    • 如果自定义处理器返回 false,则使用内置的默认导出功能
    • 默认导出支持UTF-8编码、多语言头部、安全字符转义等特性
    • 导出内容包含所有任务字段,递归处理子任务
  8. 工具栏功能:
    • 新增任务按钮:独立的主要操作按钮,具有醒目的主色调样式
    • 导出按钮组CSV和PDF导出按钮采用button group样式左右相连统一的视觉效果
    • 设置按钮:语言、主题、全屏等图标按钮,位于右侧,支持响应式布局
    • 国际化支持:内置中英文切换,所有按钮文本和提示自动适配

Task 接口定义

interface Task {
  id: number                    // 任务唯一标识
  name: string                  // 任务名称
  predecessor?: string          // 前置任务ID
  assignee?: string            // 负责人
  startDate?: string           // 开始日期 (YYYY-MM-DD格式)
  endDate?: string             // 结束日期 (YYYY-MM-DD格式)
  progress?: number            // 完成进度 (0-100)
  estimatedHours?: number      // 预估工时
  actualHours?: number         // 实际工时
  children?: Task[]            // 子任务数组(支持嵌套结构)
  collapsed?: boolean          // 是否折叠子任务
  isParent?: boolean           // 是否为父级任务
  type?: string               // 任务类型 (task/story/bug/milestone)
  description?: string         // 任务描述
}

💡 使用示例

1. 默认模式使用内置TaskDrawer

<template>
  <!-- 最简单的使用方式双击TaskBar会打开默认的编辑抽屉 -->
  <GanttChart :tasks="tasks" />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import GanttChart from './components/GanttChart.vue'

// 定义任务数据
const tasks = ref([
  {
    id: 1,
    name: '项目启动',
    assignee: '张三',
    startDate: '2025-06-15',
    endDate: '2025-06-25',
    progress: 100,
    type: 'story',
    children: [
      {
        id: 2,
        name: '需求分析',
        assignee: '李四',
        startDate: '2025-06-16',
        endDate: '2025-06-20',
        progress: 100,
        type: 'task'
      }
    ]
  }
])
</script>

2. 自定义双击处理器

<script setup lang="ts">
import { ref } from 'vue'
import GanttChart from './components/GanttChart.vue'

// 定义Task接口与组件内部保持一致
interface Task {
  id: number
  name: string
  startDate: string
  endDate: string
  progress?: number
  isParent?: boolean
  predecessor?: number
  type?: string
}

// 自定义双击事件处理器
const handleTaskDoubleClick = (task: Task) => {
  console.log('双击了任务:', task)
  // 注意此处理器会同时响应TaskBar和TaskList中任务行的双击事件

  // 自定义逻辑示例:
  // 1. 打开自定义模态框
  openCustomModal(task)

  // 2. 跳转到详情页面
  // router.push(`/task/${task.id}`)

  // 3. 调用外部API
  // await updateTaskAPI(task)

  // 4. 显示自定义消息
  // showCustomMessage(task)
}

const openCustomModal = (task: Task) => {
  // 实现自定义模态框逻辑
  alert(`自定义处理: ${task.name}`)
}
</script>

<template>
  <!-- 使用自定义处理器禁用默认抽屉 -->
  <GanttChart
    :on-task-double-click="handleTaskDoubleClick"
    :use-default-drawer="false"
  />
</template>

3. TaskList与TaskBar双击一致性

<script setup lang="ts">
import { ref } from 'vue'
import GanttChart from './components/GanttChart.vue'

const handleTaskDoubleClick = (task: Task) => {
  console.log('任务双击事件:', task)
  // 此处理器会同时响应:
  // 1. Timeline中TaskBar的双击
  // 2. TaskList中任务行的双击

  // 无论用户双击任务条还是任务行,都会执行相同的逻辑
  openTaskEditor(task)
}

const openTaskEditor = (task: Task) => {
  // 打开自定义任务编辑器
  console.log(`正在编辑任务: ${task.name}`)
}
</script>

<template>  <!-- TaskList和Timeline的双击行为保持一致 -->
  <GanttChart
    :tasks="tasks"
    :on-task-double-click="handleTaskDoubleClick"
    :use-default-drawer="false"
  />
</template>

4. CSV导出功能使用

CSV导出功能支持自定义处理器和默认实现具有完整的多语言和UTF-8编码支持。详细文档请参考 CSV_EXPORT.md

基本使用

<script setup lang="ts">
import { ref } from 'vue'

const tasks = ref([/* 你的任务数据 */])

// 启用CSV导出
const toolbarConfig = {
  showExportCsv: true,
  showLanguage: true, // 启用语言切换影响CSV头部语言
}

// 可选自定义CSV导出处理器
const handleCsvExport = () => {
  console.log('CSV导出')
  // 返回false使用默认实现
  return false
}
</script>

<template>
  <GanttChart
    :tasks="tasks"
    :toolbar-config="toolbarConfig"
    :on-export-csv="handleCsvExport"
  />
</template>

5. 工具栏配置与使用

工具栏采用了全新的设计新增任务按钮独立显示导出CSV和PDF按钮采用button group样式相连右侧为设置类按钮。

<script setup lang="ts">
import { ref } from 'vue'
import GanttChart from './components/GanttChart.vue'

// 工具栏配置
const toolbarConfig = ref({
  showAddTask: true,      // 显示新增任务按钮(主色调独立按钮)
  showExportCsv: true,    // 显示导出CSV按钮button group左侧
  showExportPdf: true,    // 显示导出PDF按钮button group右侧
  showLanguage: true,     // 显示语言切换按钮
  showTheme: true,        // 显示主题切换按钮
  showFullscreen: true    // 显示全屏切换按钮
})

// 工具栏事件处理器
const handleAddTask = () => {
  console.log('新增任务按钮被点击')
  // 实现新增任务逻辑
  // 例如:打开新增任务对话框
  openAddTaskDialog()
}

const handleExportCsv = () => {
  console.log('导出CSV按钮被点击')
  // 实现CSV导出逻辑
  exportToCsv()
}

const handleExportPdf = () => {
  console.log('导出PDF按钮被点击')
  // 实现PDF导出逻辑
  exportToPdf()
}

const handleLanguageChange = (lang: 'zh' | 'en') => {
  console.log('语言切换为:', lang)
  // 实现语言切换逻辑
}

const handleThemeChange = (isDark: boolean) => {
  console.log('主题切换为:', isDark ? '暗色' : '明亮')
  // 实现主题切换逻辑
}

const handleFullscreenChange = (isFullscreen: boolean) => {
  console.log('全屏状态:', isFullscreen ? '已进入' : '已退出')
  // 实现全屏状态处理逻辑
}

// 业务逻辑函数示例
const openAddTaskDialog = () => {
  // 打开新增任务对话框的具体实现
}

const exportToCsv = () => {
  // 导出CSV的具体实现
  // 可以调用后端API或者前端处理
}

const exportToPdf = () => {
  // 导出PDF的具体实现
  // 可以调用后端API或者前端处理
}
</script>

<template>
  <GanttChart
    :tasks="tasks"
    :show-toolbar="true"
    :toolbar-config="toolbarConfig"
    :on-add-task="handleAddTask"
    :on-export-csv="handleExportCsv"
    :on-export-pdf="handleExportPdf"
    :on-language-change="handleLanguageChange"
    :on-theme-change="handleThemeChange"
    :on-fullscreen-change="handleFullscreenChange"
  />
</template>

工具栏样式特点

  • Button Group设计: 导出CSV和PDF按钮采用连接式设计视觉上更加统一
  • 主操作突出: 新增任务按钮使用主色调,突出重要操作
  • 图标化右侧: 设置类按钮采用纯图标设计,节省空间
  • 响应式布局: 在小屏幕设备上自动调整按钮尺寸和间距
  • 国际化支持: 所有按钮文本和提示自动适配当前语言

选择性显示工具栏项

<script setup lang="ts">
// 仅显示新增任务和导出功能,隐藏其他按钮
const minimalToolbarConfig = ref({
  showAddTask: true,
  showExportCsv: true,
  showExportPdf: true,
  showLanguage: false,    // 隐藏语言切换
  showTheme: false,       // 隐藏主题切换
  showFullscreen: false   // 隐藏全屏切换
})
</script>

<template>
  <!-- 最小化工具栏配置 -->
  <GanttChart
    :toolbar-config="minimalToolbarConfig"
    :on-add-task="handleAddTask"
    :on-export-csv="handleExportCsv"
    :on-export-pdf="handleExportPdf"
  />
</template>

完全隐藏工具栏

<template>
  <!-- 隐藏工具栏使用纯甘特图 -->
  <GanttChart
    :show-toolbar="false"
    :tasks="tasks"
  />
</template>

说明: TaskList中任务行的双击与Timeline中TaskBar的双击具有完全相同的API行为和优先级机制确保用户体验的一致性。

4. 条件性使用不同处理器

<script setup lang="ts">
import { ref, computed } from 'vue'
import GanttChart from './components/GanttChart.vue'

const useCustomHandler = ref(false)

const handleCustomTaskDoubleClick = (task: Task) => {
  // 自定义处理逻辑
  console.log('使用自定义处理器:', task)
}

// 根据条件决定使用哪种处理器
const doubleClickHandler = computed(() => {
  return useCustomHandler.value ? handleCustomTaskDoubleClick : undefined
})
</script>

<template>
  <div>
    <label>
      <input type="checkbox" v-model="useCustomHandler" />
      使用自定义处理器
    </label>

    <GanttChart
      :on-task-double-click="doubleClickHandler"
      :use-default-drawer="!useCustomHandler"
    />
  </div>
</template>

4. 自定义删除处理器

<script setup lang="ts">
import { ref } from 'vue'
import GanttChart from './components/GanttChart.vue'

// 自定义删除事件处理器
const handleCustomTaskDelete = async (task: Task) => {
  console.log('自定义删除处理器被调用:', task)

  // 自定义删除逻辑示例:
  try {
    // 1. 调用后端API删除
    await fetch(`/api/tasks/${task.id}`, { method: 'DELETE' })

    // 2. 更新本地状态
    // store.dispatch('deleteTask', task.id)

    // 3. 显示自定义成功消息
    showNotification(`任务 "${task.name}" 已成功删除`, 'success')

    // 4. 可以触发其他业务逻辑
    // trackDeleteEvent(task)

  } catch (error) {
    console.error('删除失败:', error)
    showNotification('删除失败,请重试', 'error')
  }
}

const showNotification = (message: string, type: string) => {
  // 实现自定义通知逻辑
  console.log(`${type}: ${message}`)
}
</script>

<template>
  <GanttChart
    :on-task-delete="handleCustomTaskDelete"
  />
</template>

5. 完整的自定义处理器组合

<script setup lang="ts">
import { ref } from 'vue'
import GanttChart from './components/GanttChart.vue'

// 自定义双击处理器
const handleTaskDoubleClick = (task: Task) => {
  // 打开自定义编辑界面
  router.push(`/tasks/${task.id}/edit`)
}

// 自定义删除处理器
const handleTaskDelete = async (task: Task) => {
  // 使用自定义确认对话框
  const confirmed = await showCustomConfirm(
    '删除确认',
    `确定要删除任务 "${task.name}" 吗?`,
    'warning'
  )

  if (confirmed) {
    await api.deleteTask(task.id)
    showMessage('删除成功', 'success')
  }
}
</script>

<template>
  <GanttChart
    :on-task-double-click="handleTaskDoubleClick"
    :on-task-delete="handleTaskDelete"
    :use-default-drawer="false"
  />
</template>

🏗️ 组件架构

组件层次结构

GanttChart (入口组件API配置)
├── TaskList (左侧任务列表)
├── Timeline (右侧时间轴区域)
    ├── TaskBar (任务条,支持双击事件)
    ├── Milestone (里程碑)
    └── TaskDrawer (默认编辑抽屉)

API 数据流

  1. GanttChart 接收API配置props
  2. 透传给 Timeline 组件
  3. Timeline 将API配置传递给 TaskBar
  4. TaskBar 双击时调用API处理器或触发默认行为

内置功能

  • 拖拽调整任务时间
  • 调整任务条长度
  • 任务进度显示
  • 前置任务依赖关系
  • 父子任务层级结构
  • 时间轴缩放和导航
  • 自定义双击事件API

🔧 技术特性

  • Framework: Vue 3 + TypeScript + Vite
  • 样式: 延续Element Plus设计风格无外部依赖
  • 响应式: 完全使用Vue 3 Composition API
  • 类型安全: 完整的TypeScript接口定义
  • 可扩展: 灵活的API设计支持自定义扩展

🛠️ 高级用法

完整示例:集成自定义编辑功能

<template>
  <div class="gantt-container">
    <!-- Gantt图表 -->
    <GanttChart
      :on-task-double-click="handleTaskDoubleClick"
      :use-default-drawer="!useCustomEditor"
    />

    <!-- 自定义编辑模态框 -->
    <div v-if="showCustomModal" class="custom-modal-overlay" @click="closeModal">
      <div class="custom-modal" @click.stop>
        <div class="modal-header">
          <h3>编辑任务: {{ currentTask?.name }}</h3>
          <button @click="closeModal" class="close-btn">×</button>
        </div>
        <div class="modal-body">
          <form @submit.prevent="saveTask">
            <div class="form-group">
              <label>任务名称:</label>
              <input v-model="editingTask.name" type="text" required />
            </div>
            <div class="form-group">
              <label>开始日期:</label>
              <input v-model="editingTask.startDate" type="date" required />
            </div>
            <div class="form-group">
              <label>结束日期:</label>
              <input v-model="editingTask.endDate" type="date" required />
            </div>
            <div class="form-group">
              <label>完成进度:</label>
              <input v-model.number="editingTask.progress" type="number" min="0" max="100" />
            </div>
          </form>
        </div>
        <div class="modal-footer">
          <button @click="closeModal" class="btn-cancel">取消</button>
          <button @click="saveTask" class="btn-save">保存</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive } from 'vue'
import GanttChart from './components/GanttChart.vue'

interface Task {
  id: number
  name: string
  startDate: string
  endDate: string
  progress?: number
  isParent?: boolean
  predecessor?: number
  type?: string
}

// 状态管理
const useCustomEditor = ref(true)
const showCustomModal = ref(false)
const currentTask = ref<Task | null>(null)
const editingTask = reactive<Partial<Task>>({})

// 自定义双击处理器
const handleTaskDoubleClick = (task: Task) => {
  currentTask.value = task

  // 复制任务数据到编辑状态
  Object.assign(editingTask, {
    id: task.id,
    name: task.name,
    startDate: task.startDate,
    endDate: task.endDate,
    progress: task.progress || 0
  })

  showCustomModal.value = true
}

// 关闭模态框
const closeModal = () => {
  showCustomModal.value = false
  currentTask.value = null
  Object.keys(editingTask).forEach(key => {
    delete editingTask[key as keyof typeof editingTask]
  })
}

// 保存任务
const saveTask = () => {
  if (!currentTask.value) return

  // 这里可以调用API保存数据
  console.log('保存任务:', editingTask)

  // 触发任务更新事件
  window.dispatchEvent(new CustomEvent('task-updated', {
    detail: { ...currentTask.value, ...editingTask }
  }))

  closeModal()
}
</script>

<style scoped>
.gantt-container {
  width: 100%;
  height: 100%;
  position: relative;
}

.custom-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.custom-modal {
  background: white;
  border-radius: 8px;
  width: 500px;
  max-width: 90vw;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #eee;
}

.modal-header h3 {
  margin: 0;
  color: #333;
}

.close-btn {
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
  color: #999;
}

.modal-body {
  padding: 20px;
}

.form-group {
  margin-bottom: 16px;
}

.form-group label {
  display: block;
  margin-bottom: 4px;
  color: #333;
  font-weight: 500;
}

.form-group input {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  padding: 20px;
  border-top: 1px solid #eee;
}

.btn-cancel, .btn-save {
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}

.btn-cancel {
  background: #f5f5f5;
  color: #666;
}

.btn-save {
  background: #409eff;
  color: white;
}
</style>

性能优化建议

  1. 事件处理器缓存: 使用 computeduseMemo 缓存事件处理器,避免不必要的重新渲染

  2. 异步处理: 对于复杂的双击处理逻辑,建议使用异步函数

<script setup lang="ts">
const handleTaskDoubleClick = async (task: Task) => {
  try {
    // 显示加载状态
    loading.value = true

    // 异步处理
    await processTask(task)
  } catch (error) {
    console.error('处理任务失败:', error)
  } finally {
    loading.value = false
  }
}
</script>
  1. 防抖处理: 对于可能触发频繁操作的场景,考虑添加防抖
<script setup lang="ts">
import { debounce } from 'lodash-es'

const debouncedHandler = debounce((task: Task) => {
  // 实际处理逻辑
  console.log('处理任务:', task)
}, 300)
</script>

🔧 故障排除

常见问题

  1. Q: 双击事件不触发?

    • A: 检查是否正确传递了 onTaskDoubleClick 属性,并确保 useDefaultDrawer 设置正确
  2. Q: 同时使用自定义处理器和默认Drawer

    • A: 当 onTaskDoubleClick 存在时会优先调用自定义处理器默认Drawer不会打开
  3. Q: 如何在自定义处理器中获取更多任务信息?

    • A: 可以通过全局状态管理或者父组件传递更多上下文信息
  4. Q: 自定义处理器中的异步操作报错?

    • A: 确保在异步操作中添加try-catch错误处理避免未捕获的异常

调试技巧

<script setup lang="ts">
// 启用调试模式
const debugMode = ref(true)

const handleTaskDoubleClick = (task: Task) => {
  if (debugMode.value) {
    console.log('双击事件触发:', {
      task,
      timestamp: new Date().toISOString(),
      component: 'TaskBar'
    })
  }

  // 你的处理逻辑...
}
</script>

性能优化

1. 事件处理器缓存

<script setup lang="ts">
import { computed } from 'vue'

// 使用computed缓存处理器避免不必要的重新渲染
const taskDoubleClickHandler = computed(() => {
  return (task: Task) => {
    // 处理逻辑
  }
})
</script>

<template>
  <GanttChart :on-task-double-click="taskDoubleClickHandler" />
</template>

2. 异步处理优化

<script setup lang="ts">
const loading = ref(false)

const handleTaskDoubleClick = async (task: Task) => {
  try {
    // 显示加载状态
    loading.value = true

    // 异步处理
    await processTaskAsync(task)
  } catch (error) {
    console.error('处理任务失败:', error)
    // 显示错误提示
  } finally {
    loading.value = false
  }
}
</script>

3. 防抖处理

<script setup lang="ts">
import { debounce } from 'lodash-es'

const debouncedHandler = debounce((task: Task) => {
  // 实际处理逻辑
  console.log('处理任务:', task)
}, 300)
</script>

🎯 最佳实践

1. 代码组织

  • 保持处理器简洁: 双击处理器应该保持轻量,复杂逻辑建议抽取到单独的函数中
  • 类型安全: 充分利用TypeScript的类型检查确保Task接口一致性
  • 职责分离: 将业务逻辑与UI逻辑分离

2. 用户体验

  • 即时反馈: 为用户操作提供即时的视觉反馈
  • 错误处理: 始终为异步操作添加错误处理和用户友好的错误提示
  • 加载状态: 为长时间运行的操作提供适当的加载提示
  • 可访问性: 确保自定义交互也支持键盘导航和屏幕阅读器

3. 性能考虑

  • 避免内存泄漏: 及时清理事件监听器和定时器
  • 合理使用响应式: 不要过度使用reactive对于简单数据使用ref
  • 组件懒加载: 对于复杂的自定义组件考虑懒加载

4. 兼容性设计

<script setup lang="ts">
// 提供降级方案
const handleTaskDoubleClick = (task: Task) => {
  try {
    // 主要逻辑
    processTask(task)
  } catch (error) {
    // 降级处理
    console.warn('使用降级方案')
    fallbackHandler(task)
  }
}
</script>

🚀 扩展开发

自定义事件系统

<script setup lang="ts">
// 定义自定义事件
const emit = defineEmits<{
  'task-clicked': [task: Task]
  'task-updated': [task: Task]
  'task-deleted': [taskId: number]
}>()

const handleTaskDoubleClick = (task: Task) => {
  // 处理双击逻辑

  // 发出自定义事件
  emit('task-clicked', task)
}
</script>

插件化架构

// 定义插件接口
interface GanttPlugin {
  name: string
  onTaskDoubleClick?: (task: Task) => void
  onTaskCreate?: (task: Task) => void
  onTaskUpdate?: (task: Task) => void
}

// 使用插件
const ganttPlugins: GanttPlugin[] = [
  {
    name: 'analytics',
    onTaskDoubleClick: (task) => {
      // 分析统计逻辑
    }
  }
]

🤝 贡献指南

欢迎提交Issue和Pull Request来改进这个组件

开发环境设置

# 克隆项目
git clone <repository-url>

# 安装依赖
npm install

# 启动开发服务器
npm run dev

# 构建项目
npm run build

代码规范

  • 使用TypeScript进行类型安全开发
  • 遵循Vue 3 Composition API最佳实践
  • 保持代码简洁和可读性
  • 添加适当的注释和文档

🎉 通过这些API您可以完全自定义TaskBar的交互行为打造符合您项目需求的甘特图体验

如有问题或建议欢迎提交Issue或联系开发团队。

GanttChart 属性Props

属性名 说明 类型 默认值
tasks 任务数据 Task[] []
milestones 里程碑数据 Milestone[] []
toolbarConfig 工具栏配置 ToolbarConfig {}
showToolbar 是否显示工具栏 boolean true
editComponent 自定义编辑组件 Component undefined
useDefaultDrawer 是否使用默认TaskDrawer boolean true
localeMessages 自定义多语言配置 object undefined
isDark 主题模式(受控) boolean false
onLanguageChange 语言切换回调 `(lang: 'zh-CN' 'en-US') => void`
onThemeChange 主题切换回调 (isDark: boolean) => void undefined
onFullscreenChange 全屏/退出全屏回调 (isFullscreen: boolean) => void undefined
onTaskDoubleClick 任务双击回调 (task: Task) => void undefined
onTaskDelete 任务删除回调 (task: Task) => void undefined
onTaskUpdate 任务更新回调 (task: Task) => void undefined
onTaskAdd 任务添加回调 (task: Task) => void undefined
onTaskbarDragEnd 任务条拖拽结束 (task: Task) => void undefined
onTaskbarResizeEnd 任务条拉伸结束 (task: Task) => void undefined
onMilestoneSave 里程碑保存回调 (milestone: Milestone) => void undefined
onMilestoneDelete 里程碑删除回调 (milestoneId: number) => void undefined
onMilestoneIconChange 里程碑图标变更回调 (milestoneId: number, icon: string) => void undefined
onMilestoneDragEnd 里程碑拖拽结束 (milestone: Milestone) => void undefined
onAddTask 工具栏“新增任务”回调 () => void undefined
onAddMilestone 工具栏“新增里程碑”回调 () => void undefined
onExportCsv 导出CSV回调 `() => boolean void`
onExportPdf 导出PDF回调 () => void undefined
onTodayLocate 定位到今天回调 () => void undefined
事件名 说明 回调参数类型
taskbar-drag-end 任务条拖拽结束 task: Task
taskbar-resize-end 任务条拉伸结束 task: Task
milestone-drag-end 里程碑拖拽结束 milestone: Milestone
milestone-double-click 里程碑双击 milestone: Milestone
...其它见源码

详细类型定义请参考源码 src/models/classes/Task.tssrc/models/classes/Milestone.tssrc/models/configs/ToolbarConfig.ts