1.2.1 • Published 8 months ago

ry-gantt-chart v1.2.1

Weekly downloads
-
License
MIT
Repository
-
Last release
8 months ago

⭐️一款基于Vue3结合Element Plus开发的实用性较强和支持大数据量操作的甘特图组件。

😇支持:
  • 查看项目和生产计划
  • 拖动或手动编辑计划任务
  • 拖动或手动调整计划进度
  • 拖动或手动移除计划任务
  • 拖动或手动新增计划任务
  • 聚焦到目标任务
  • 一键返回顶部
  • 可视区域伸展或折叠
  • 当前可视区域行数范围标记
  • 组件提供内置各种钩子函数以满足日常业务需求
  • 数据懒加载,支持大数据量(>1w条)任务展示或操作
  • ...
🙂安装
npm i ry-gantt-chart
😉引入
import { createApp } from "vue";
import App from "./App.vue";
import "./common/css/common.css";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";

import ryGanttChart from "ry-gantt-chart";
import 'ry-gantt-chart/dist/style.css'

const app = createApp(App)
  .use(ElementPlus)
  .use(ryGanttChart)
  .mount("#app");

😁使用

<script setup>
import { ref, onMounted, getCurrentInstance, computed } from "vue";
import mockGanttList from "../../mock/ganttList.js";
import unArrangeTableData from "../../mock/unArrangeTableData.js";
import dayjs from "dayjs";
const ctx = getCurrentInstance();

// 甘特图视图起始日期
const startDate = ref(
  dayjs()
    .subtract(2, "day")
    .format("YYYY-MM-DD") + " 00:00:00"
);

// 甘特图结束日期
const endDate = ref(
  dayjs()
    .add(3, "month")
    .format("YYYY-MM-DD") + " 00:00:00"
);

// 甘特图配置
const config = ref({
  type: "month", // year | month | date
  scaleWidth: 150, // px 下刻度每刻度长度
  divideBy: 2, // 上刻度
  rowHeight: 30, // 每条泳道高度
  viewHeight: 300, // 甘特图初始高度
  viewMaxHeight: 400, // 甘特图最大高度
  showCurrentTimeScaler: true, // 是否显示当前时间轴
  showRowsRange: true, // 是否显示当前可视区域显示行数范围
  showGoToTop: true, // 是否显示滚回视图顶部按钮
});

// 数据集合
const list = ref(mockGanttList(20).list);


// 甘特图左侧表格配置
const ganttTableConfig = ref({
  tableColumn: [
    {
      label: "项目",
      prop: "project",
    },
    {
      label: "生产线",
      prop: "prodLine",
    },
    {
      label: "区域",
      prop: "zone",
      "show-overflow-tooltip": true,
    },
  ],
});

// 下方待排区表格配置
const unArrangeConfig = ref({
  list: unArrangeTableData,
  tableColumn: [
    {
      label: "流水号",
      prop: "pkid",
    },
    {
      label: "工作任务",
      prop: "content",
    },
  ],
  // 待排区列表行按钮配置
  rowOperations: [
    {
      name: "查看",
      type: "success",
      click: (scope) => {
        console.log(scope);
      },
    },
  ],
  // 待排区列表操作列配置
  operationsConfig: {
    width: 100,
  },
});
const dateRange = ref([]);

const unitText = computed(() => {
  const units = {
    year: "年",
    month: "月",
    date: "日",
  };
  return units[config.value.type];
});


// 插入新任务
const insertNewTask = () => {
  const rowIndex = 2;
  ctx.refs.ryGanttChart.insertNewTask(rowIndex, {
    pkid: "8021",
    startTime: dayjs()
      .add("1", "day")
      .format("YYYY-MM-DD HH:mm:ss"),
    endTime: dayjs()
      .add("3", "day")
      .format("YYYY-MM-DD HH:mm:ss"),
    content: "检查燃油滤芯No7.",
    background: "rgb(223,102,2)",
  });
};

// 根据id删除某条任务
const handleDeleteTask = () => {
  ctx.refs.ryGanttChart.removeTaskById("23007");
};

// 点击了某条任务
const handleClickTask = (rowIndex, task) => {
  console.log("rowIndex, task: ", rowIndex, task);
};

// 获取操作过的任务集合
const handleGetModifiedData = () => {
  ctx.refs.ryGanttChart.getModifiedData((v) => console.log("v", v));
};

const toggleResults = (val, list) => {
  const idx = list.findIndex((v) => v === val);
  return idx >= list.length - 1 ? list[0] : list[idx + 1];
};
const handleChangeScaleUnit = () => {
  config.value.type = toggleResults(config.value.type, ["year", "month", "date"]);
};
const handleChangeRowHeight = () => {
  config.value.rowHeight = toggleResults(config.value.rowHeight, [30, 40, 55]);
};
const handleChangeTopScale = () => {
  config.value.divideBy = toggleResults(config.value.divideBy, [1, 2, 3, 4]);
};
const handleChangeDownScale = () => {
  config.value.scaleWidth = toggleResults(config.value.scaleWidth, [100, 150, 300]);
};
const handleChangeQty = () => {
  const qty = toggleResults(list.value.length, [20, 200, 500]);
  list.value = mockGanttList(qty)["list"];
};
const handleDateChange = () => {
  [startDate.value, endDate.value] = dateRange.value;
};
// 根据id聚焦到某条任务
const handleFouce = () => {
  ctx.refs.ryGanttChart.scrollToTaskById("23022");
};
</script>

<template>
  <h1 class="title">RY-GANTT-CHART</h1>
  <div class="ctrl-wrapper">
    <div style="width: 300px;overflow: hidden;padding-right:20px;">
      <el-date-picker
        style="width:95%"
        type="daterange"
        v-model="dateRange"
        range-separator="至"
        start-placeholder="开始时间"
        end-placeholder="结束时间"
        value-format="YYYY-MM-DD HH:mm:ss"
        :clearable="false"
        @change="handleDateChange"
      ></el-date-picker>
    </div>

    <el-button type="success" @click="handleChangeQty">数据量</el-button>
    <el-button type="success" @click="handleChangeTopScale">上刻度宽度</el-button>
    <el-button type="success" @click="handleChangeDownScale">下刻度宽度</el-button>
    <el-button type="success" @click="handleChangeRowHeight">行高</el-button>
    <el-button type="success" @click="handleDeleteTask">删除某条任务</el-button>
    <el-button type="success" @click="handleFouce">聚焦到某一任务</el-button>
    <el-button type="success" @click="insertNewTask">插入新增任务</el-button>
    <el-button type="success" @click="handleGetModifiedData">获取操作项</el-button>
    <el-button type="success" @click="handleChangeScaleUnit">{{ unitText }}</el-button>
  </div>
  <ryGanttChart
    ref="ryGanttChart"
    :config="config"
    :list="list"
    :startDate="startDate"
    :endDate="endDate"
    :ganttTableConfig="ganttTableConfig"
    :unArrangeConfig="unArrangeConfig"
  >
    <!-- 任务条内容插槽 -->
    <template v-slot:taskContent="slotProps">
      <div class="text" @click="handleClickTask(slotProps.rowIndex, slotProps.task)">
        {{ `${slotProps.task.content} (id:${slotProps.task.pkid})` }}
      </div>
    </template>
  </ryGanttChart>
</template>

<style scoped lang="scss">
.title {
  margin: 0;
  text-align: center;
  font-family: "Times New Roman", Times, serif;
}
.text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ctrl-wrapper {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 10px 0;

  h1 {
    margin: 0;
    width: 500px;
    font-size: 30px;
    flex: 1;
  }
}
</style>

🧐数据结构

import { dayjs } from "../common/utils";

export default (qty) => {
  let taskCount = 23000;
  let count = 0;
  return {
    list: Array.from({ length: qty }, (_, index) => {
      count += 3;

      return {
        pkid: index.toString(), // pkid ->当前行父任务主键
        project:
          "ROCKET" +
          dayjs()
            .add(count, "day")
            .format("MMDD"),
        prodLine: "生产线-" + index,
        zone: "月球",
        /* tasks -> 子任务对象属性  */
        tasks: [
          {
            pkid: (taskCount++).toString(), // 子任务主键
            startTime:
              dayjs()
                .subtract(1, "day")
                .format("YYYY-MM-DD") + " 00:00:00", // startTime -> 任务开始日期
            endTime:
              dayjs()
                .add(1, "day")
                .format("YYYY-MM-DD") + " 00:00:00", // endTime ->任务结束日期
            content: "Daily check", // 任务内容
            background: "rgb(182,220,22)", // background ->任务条背景色
            color: "black", // color ->任务条字体颜色
            disabled: false, // disabled ->当前任务是否无法被拖动或编辑
          },
          // ...
       
        ],
      };
    }),
  };
};
export default [
  {
    pkid: "1055",
    content: "安装车门",
    rangeDays: 3,
  },
  {
    pkid: "1056",
    content: "安装倒后镜",
    rangeDays: 3,
  },
  {
    pkid: "1067",
    content: "全车检查",
    rangeDays: 3,
  },
  {
    pkid: "1058",
    content: "更换ECU",
    rangeDays: 3,
  },
];

RY-GANTT-TABLE 属性

属性名参数 说明
list:Array数据结构见demo示例甘特图源数据
startDate:String"YYYY-MM-DD HH:mm:ss"刻度尺起始日期
endDate:String"YYYY-MM-DD HH:mm:ss"刻度尺结束日期
disabeld:Booleandefault:false甘特图是否只读
showSideExpanderdefault:false是否显示“展开收起”侧栏按钮
showBottomExpanderdefault:true是否显示“展开更多”甘特图视图按钮
showUnArrangeTabledefault:true是否显示待排区,默认true
config:Object甘特图视图区配置
type:String | 'year' ,'month' , 'date'刻度尺单位范围
scaleWidth:Number刻度尺下部每刻度间隔宽度(px)
divideBy:Number刻度尺上部刻度根据每间隔下部刻度多少个进行划分
rowHeight:Number泳道行高(px)
viewHeight:Number甘特图出初始高度
viewMaxHeight:Number甘特图最大高度
showCurrentTimeScaler:Boolean是否显示当前时间节点标线
showGoToTop:Boolean是否显示返回顶部按钮
showRowsRange:Boolean是否显示当前可视区域行数范围
topScaleFormatter(obj)obj:Object | 刻度尺上部每刻度内容格式化处理函数 | 需返回字符串
downScaleFormatter(obj)obj:Object | 刻度尺下部每刻度内容格式化处理函数 | 需返回字符串
unArrangeConfig:Object
待排区域表格配置
tableColumn:Array表头配置
data:Array待排区域表格源数据
rowOperations:Array行操作配置
operationsConfig:Object
ganttTableConfig:Object甘特图左侧表格配置
tableColumn:Array表头配置
beforeMountData:Function(data)=>data挂载甘特图视图层数据前调用,需返回数据对象。
afterMountedData:Function(data) =>{}挂载甘特图视图层数据完成后调用
beforeRemove:Function(task,next)=>{}完成移除任务前调用 | task:Object 当前任务对象 | next:Function 调用next执行后续逻辑
beforeHorizontalMove:Function(task,next)=>{}完成水平移动任务前调用 | task:Object 当前任务对象 | next:Function 调用next执行后续逻辑
beforeVerticalMove:Function(task,next)=>{}完成垂直移动任务前调用 | task:Object 当前任务对象 | next:Function 调用next执行后续逻辑
beforeInsertToGantt:Function(task,next)=>{}完成插入新数据前调用 | task:Object 当前任务对象 | next:Function 调用next执行后续逻辑
beforeDropToUnArrange(task,next)=>{}完成放置到待排区前校验 | task:Object 当前任务对象 | next:Function 调用next执行后续逻辑
afterDropToUnArrange(task)=>{}完成放置到待排区后调用 | task:Object 当前任务对象

RY-GANTT-CHART 方法

名称参数返回值
insertNewTask(rowIndex,task)插入任务task到某行rowrowIndex : Number | 行索引 task:Object 任务内容 (必要属性参考甘特图数据结构)
getModifiedData(res)(res)=>{} | res:变化过的任务数据集合Promise | 变化过的任务数据集合
getUnArrangeTableData()Array | 待排区表格数据
scrollToTaskById(id)id:string通过任务主键让视图滚动到该任务所在位置,并且会有高亮闪烁一次的圆点出现
removeTaskById(id)id:string根据任务id,从甘特图移除某条任务
editTask({targetRowIndex,task})targetRowIndex:number , task:Object手动编辑某条任务 | targetRowIndex :要把该任务移动到某行的索引 | task :任务对象,任务的pkid ,起始日期,结束日期字段不能为空。

RY-GANTT-CHART 事件

名称说明回调参数
expander-change收起展开按钮change事件type:String,isExpand:Boolean | type : side、bottom
scaler-click刻度尺区域点击事件

RY-GANTT-CHART SLOTS 插槽

名称说明类型
leftHeader-
taskContent任务内容作用域参数为 { task } ,该任务对象

**Demo: 1. npm run dev 启动这个项目,查看/examples/pages/demo 或 /examples/pages/demo1 的页面 2. 或 https://gitee.com/RYANLLL/ry-gantt-chart-demo

1.2.1

8 months ago

1.2.0

2 years ago

1.1.5

2 years ago

1.1.4

2 years ago

1.1.3

2 years ago

1.1.2

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago