vue3 vue-ganttastic 使用

简介

vue3 原生开源甘特图:地址:https://zunnzunn.github.io/vue-ganttastic/
功能相对简单;做项目进度展示,会议室预定展示还可以;不支持复杂粒度控制;

1、安装

pnpm install @infectoone/vue-ganttastic

2、配置

src/main.js 配置

import { createApp } from "vue"
import App from "./App.vue"
...
import ganttastic from '@infectoone/vue-ganttastic'
...
createApp(App)
  .use(ganttastic)
  .mount('#app')

官方样例:https://zunnzunn.github.io/vue-ganttastic/examples.html

3、使用

element-pluis +vue-ganttastic 静态使用样例

<template>
  <g-gantt-chart
      :chart-start="`${applicationDate} 07:00:00`"
      :chart-end="`${applicationDate} 23:59:59`"
      precision="hour"
      date-format="YYYY-MM-DD HH:mm:ss"
      bar-start="startTime"
      bar-end="endTime"
      color-scheme="sky"
      :push-on-overlap="false"
      :no-overlap="true"
      :grid="true"
      :row-height="40"
      label-column-title="会议室"
      label-column-width="300px"
      style="width: 87vw;"
  >
    <template #upper-timeunit="{ date }">
      <el-date-picker
          v-model="applicationDate"
          type="date"
          placeholder="选择时间"
          value-format="YYYY-MM-DD"
          :clearable="false"
          style="width: 130px;"
      />
    </template>
    <template #timeunit="{label, value}">
      <el-text style="text-align: left;width: 100%;">{{ label }}</el-text>
    </template>
    <template #label-column-row="{label}">
      <el-tooltip
          class="box-item"
          effect="dark"
          :content="`${label.roomName},可容纳:${label.capacity}人`"
          placement="right"
      >
        <el-text style="width: 270px;" :truncated="true">{{
            label.roomName
          }},{{ label.capacity }}人
        </el-text>
      </el-tooltip>
    </template>

    <g-gantt-row v-for="(item,index) in meetingRoomRequestStatusList" :label="item" :bars="item.rowBarList ">
      <template #bar-label="{bar}">
        <el-tooltip
            class="box-item"
            effect="dark"
            :content="`${bar.ganttBarConfig?.label}`"
            raw-content
            placement="top"
        >
          <el-text style="width: 100%;text-align: center"> {{ bar.ganttBarConfig?.label }}</el-text>
        </el-tooltip>
      </template>
    </g-gantt-row>
  </g-gantt-chart>
</template>

<script setup>
import {ref} from "vue"

// 当选选择的时间
const applicationDate = ref('2025-05-12')

// 会议室申请列表:api见:https://zunnzunn.github.io/vue-ganttastic/
const meetingRoomRequestStatusList = ref([{
  "id": 1,
  "roomName": "1#310会议室",
  "capacity": 30,
  "rowBarList": [{
    "startTime": "2025-05-12 11:00:00",
    "endTime": "2025-05-12 12:00:00",
    "ganttBarConfig": {
      "id": 2,
      "label": "XXX",
      // 是否有操作条
      "hasHandles": false,
      // 是否可移动:true 为不可一定
      "immobile": true,
      "style": {
        "background": "#2CABE3",
        "borderRadius": "5px",
        "color": "black"
      }
    }
  }]
}, {
  "id": 2,
  "roomName": "1#303-会议室",
  "capacity": 8,
  "rowBarList": [{
    "startTime": "2025-05-12 09:30:00",
    "endTime": "2025-05-12 11:00:00",
    "ganttBarConfig": {
      "id": 6,
      "label": "XXXXX",
      "hasHandles": false,
      "immobile": true,
      "style": {
        "background": "#2CABE3",
        "borderRadius": "5px",
        "color": "black"
      }
    }
  }]
}, {
  "id": 3,
  "roomName": "1#3F录播室",
  "rowBarList": [{
    "startTime": "2025-05-12 07:00:00",
    "endTime": "2025-05-12 08:00:00",
    "ganttBarConfig": {
      "id": 3,
      "label": "XXX",
      "hasHandles": false,
      "immobile": true,
      "style": {
        "background": "#2CABE3",
        "borderRadius": "5px",
        "color": "black"
      }
    }
  }, {
    "startTime": "2025-05-12 07:00:00",
    "endTime": "2025-05-12 08:00:00",
    "ganttBarConfig": {
      "id": 7,
      "label": "XXX",
      "hasHandles": false,
      "immobile": true,
      "style": {
        "background": "#2CABE3",
        "borderRadius": "5px",
        "color": "black"
      }
    }
  }, {
    "startTime": "2025-05-12 10:00:00",
    "endTime": "2025-05-12 11:30:00",
    "ganttBarConfig": {
      "id": 8,
      "label": "XXXX",
      "hasHandles": false,
      "immobile": true,
      "style": {
        "background": "#2CABE3",
        "borderRadius": "5px",
        "color": "black"
      }
    }
  }]
}, {
  "id": 4,
  "roomName": "1#2F实操室",
  "capacity": 12,
  "rowBarList": [{
    "startTime": "2025-05-12 07:00:00",
    "endTime": "2025-05-12 08:00:00",
    "ganttBarConfig": {
      "id": 4,
      "label": "XXX",
      "hasHandles": false,
      "immobile": true,
      "style": {
        "background": "#2CABE3",
        "borderRadius": "5px",
        "color": "black"
      }
    }
  }]
}, {
  "id": 5,
  "roomName": "1@2F教研室",
  "rowBarList": []
}, {
  "id": 6,
  "roomName": "3F连廊会客区",
  "rowBarList": [{
    "startTime": "2025-05-12 07:00:00",
    "endTime": "2025-05-12 08:00:00",
    "ganttBarConfig": {
      "id": 5,
      "label": "XX",
      "hasHandles": false,
      "immobile": true,
      "style": {
        "background": "#2CABE3",
        "borderRadius": "5px",
        "color": "black"
      }
    }
  }]
}, {
  "id": 7,
  "roomName": "1#5F西侧小会议室",
  "rowBarList": []
}, {
  "id": 8,
  "roomName": "1#5F西侧大会议室",
  "rowBarList": []
}, {
  "id": 9,
  "roomName": "2号楼会议室",
  "isSupportVideo": false,
  "rowBarList": []
}, {
  "id": 10,
  "roomName": "2号楼报告厅",
  "rowBarList": []
}])
</script>

效果图:
在这里插入图片描述

4、常用属性介绍

4.1 g-gantt-chart 主属性介绍

来源:https://zunnzunn.github.io/vue-ganttastic/GGanttChart.html

1)chart-start、chart-start ,图标时间范围
2)precision:最小单位,枚举:hour, day, date, week and month
3)date-format:传入的时间格式:"YYYY-MM-DD HH:mm:ss"
4)bar-start、bar-end 甘特图的开始结束指向的字段
5)color-scheme:配色方案,可每个区域指定颜色,见官方文档
6)push-on-overlap:false,拖动和重叠时条不“相互推动”
7)no-overlap:true,不允许进度条覆盖
8)grid:网格是否显示
9)row-height:行高
10)label-column-title:该属性不为空,则左侧列独立成列
11)label-column-width:指定label-column-title的宽度
12)支持事件:
click-bar:点击进度条
drag-bar:拖拽进度条中
dragend-bar 拖动进度条结束后:可拿到时间范围;
mouseenter-bar:鼠标覆盖事件;还支持单击、双击进度条;不支持点击空白区域;

<g-gantt-chart
                :chart-start="`${applicationDate} 07:00:00`"
                :chart-start="`${applicationDate} 23:59:59`"
                precision="hour"
                date-format="YYYY-MM-DD HH:mm:ss"
                bar-start="startTime"
                bar-end="endTime"
                color-scheme="sky"
                :push-on-overlap="false"
                :no-overlap="true"
                :grid="true"
                :row-height="40"
                label-column-title="会议室"
                label-column-width="300px"
                @click-bar="handleGanttBarClick"
                @drag-bar="handleGanttDrag"
                @dragend-bar="handleGanttDragend"
                @mouseenter-bar="handleGanttMouseenter">
 </g-gantt-chart>

4.2 插槽

常用插槽

1)g-gantt-chart 的 upper-timeunit :时间轴显示日期的部分
2)g-gantt-chart 的 timeunit :时间轴上的刻度部分
3)g-gantt-chart 的 label-column-row :g-gantt-chart 的 label-column-title属性不为空,标题列的插槽;假设 label-column-title 属性为空,则插槽为:label-column-title
4)g-gantt-row 的 bar-label:甘特图进度条的插槽
注:g-gantt-row 的 label 可以把整个对象传递过去,来控制 g-gantt-chart 的 label-column-row 的接受label对象;

<g-gantt-chart>
  <template #upper-timeunit="{ date }">
	时间轴显示日期的部分{{date}}
  </template>
  <template #timeunit="{label, value}">
	<el-text style="text-align: left;width: 100%;">时间刻度:{{ label }}</el-text>
  </template>

  <template #label-column-row="{label}">
	标题列:
	  <el-text style="width: 270px;" :truncated="true">{{
		  label.roomName
		}},{{ label.capacity }}人,{{ label.adminList?.map(item => item.userName).join('、') || '' }}
	  </el-text>
  </template>

  <g-gantt-row v-for="(item,index) in meetingRoomRequestStatusList" :label="item" :bars="item.rowBarList ">
	<template #bar-label="{bar}">
		甘特图上的项目进度条
	  {{bar.ganttBarConfig?.label}}
	</template>
  </g-gantt-row>
</g-gantt-chart>

5、动态增行

给在 meetingRoomRequestStatusList.value 中 某个会议室的 rowBarList 添加一个进度条属性即可

// 添加会议室单行
const addGanttRow = () => {
  editMeetingRoomRequestStatus.value.rowBarList.push({
    startTime: formData.value.startTime,
    endTime: formData.value.endTime,
    ganttBarConfig: {
      id: formData.value.id,
      label: '当前',
      hasHandles: true,
      immobile: false,
      style: {
        background: "#00ff00",
        borderRadius: "20px",
        color: "black"
      }
    }
  })
}

6 判断点击了哪个会议室的几点

handleChartClick 为实际点击事件,但为了防止拖拽事件和点击事件的冲突
所以: 使用变量 isDragging + 3个事件,来避免误判;

  <g-gantt-chart
		@click-bar="handleGanttBarClick"
		@drag-bar="handleGanttDrag"
		@dragend-bar="handleGanttDragend"
  >
    <g-gantt-row v-for="(item,index) in meetingRoomRequestStatusList" :label="item" :bars="item.rowBarList" 
	@click="(event) => handleChartClick(event, item, index)">
    </g-gantt-row>
</g-gantt-chart>

<script setup>
	import dayjs from "dayjs";
	
	// 记录是否在拖拽
	const isDragging = ref(false)
	// 鼠标点击甘特图进度条
	const handleGanttBarClick = ({bar, e, datetime})=>{
	  isDragging.value = true;
	}
	// 拖拽甘特图,标记正在拖拽
	const handleGanttDrag = ({bar, e}) => {
	  isDragging.value = true;
	}
	// 拖拽结束后
	const handleGanttDragend = (e) => {
	  // 拖拽结束后 1s 后允许点击
	  setTimeout(() => {
	    isDragging.value = false;
	  }, 500)
	}
	
	// 点击
	const handleChartClick = (event, row, rowIndex) => {
	  setTimeout(() => {
		isDragging.value = false;
	  }, 500)
	  
	  // 正在拖拽,则排除此次点击
	  if (isDragging.value) {
		return
	  }
	 
	  // 图表可点击的宽度(右侧时间轴区域)
	  const chartStart = new Date(`${applicationDate.value} 07:00:00`).getTime();
	  const chartEnd = new Date(`${applicationDate.value} 23:59:59`).getTime();
	  const totalTimeMs = chartEnd - chartStart;
	
	  // 计算点击在该行那个位置:offsetX 相对开始,target.offsetWidth:控件宽度
	  let radio = event.offsetX / event.target.offsetWidth;
	  if (radio < 0.0 || radio > 1.0) {
		return;
	  }
	  // 计算点击的时间点
	  const clickedTime = new Date(chartStart + radio * totalTimeMs)
	
	  console.log("点击的时间:", dayjs(clickedTime).format('YYYY-MM-DD HH:mm:ss'));
	  console.log("点击的行:", rowIndex, row);
	}
</script>
### Vue-Ganttastic 组件概述 Vue-Ganttastic 是一个基于 Vue.js 的开源组件库,专注于创建功能强大且易于使用甘特图[^3]。此组件的设计目的是为了提供一种简便的方法来集成到现代 Web 应用程序中,以便更好地支持任务管理和进度跟踪。 ### 安装与基本设置 要开始使用 Vue-Ganttastic,在项目中安装依赖项: ```bash npm install vue-ganttastic ``` 接着可以在主文件 `main.js` 中全局注册这个插件: ```javascript import Vue from &#39;vue&#39;; import Ganttastic from &#39;vue-ganttastic&#39;; Vue.use(Ganttastic); ``` 对于局部使用的情况,则可以直接导入并作为子组件引入特定页面或模块内。 ### 基本属性配置 以下是几个常用的初始化选项参数说明(具体更多细节可以查阅官方文档): | 属性名 | 类型 | 默认值 | 描述 | | -- | --- | --- | | tasks | Array<Object> | [] | 表示所有待显示的任务列表对象数组 | 每个任务对象通常至少包含如下字段: - id (String/Number): 每个条目的唯一标识符; - name (String): 显示名称; - start (Date/String): 开始日期时间戳或者ISO8601字符串形式; - end (Date/String): 结束日期时间戳或者ISO8601字符串形式; 这些是最基础的数据结构定义方式之一,实际应用可根据业务场景调整扩展其他必要的元数据信息。 ### 实际案例演示 这里给出一段简单的 HTML 和 JavaScript 代码片段用来展示如何快速构建一张带有两个任务记录的基础版甘特图: ```html <template> <div class="example"> <!-- 使用 gantt 图表 --> <gantt :tasks="taskList"></gantt> </div> </template> <script> export default { data() { return { taskList: [ {id: 1, name: "Task A", start: new Date(), end: new Date(Date.now()+7*24*60*60*1000)}, {id: 2, name: "Task B", start: new Date(Date.now()-3*24*60*60*1000), end: new Date()} ] }; } }; </script> ``` 这段代码展示了怎样通过传递给 `<gantt>` 标签内的 `tasks` 属性一组预设好的任务集合从而渲染出可视化的甘特图界面效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值