背景:

  1. 项目中用到甘特图, 找到了 gantt-schedule-timeline-calendar 可以满足项目需求;

  2. 项目前端原本使用 vue 2.x, 使用vue-cli3 初始化项目;

使用步骤:

  1. 安装依赖 npm i gantt-schedule-timeline-calendar

  2. Demo代码:

// xxx.vue

<template>
  <gstc />
</template>

<script>
import GSTCComponent from './components/GSTC.vue'

export default {
  name: 'App',
  components: {
    'gstc':GSTCComponent
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}
</style>

// GSTC.vue


<template>
  <div>
    <div class="toolbox">
      <button @click="updateFirstRow">Update first row</button>
      <button @click="changeZoomLevel">Change zoom level</button>
    </div>
    <div class="gstc-wrapper" ref="gstc"></div>
  </div>
</template>

<script>
import GSTC from "gantt-schedule-timeline-calendar/dist/gstc.wasm.esm.min.js";
import { Plugin as TimelinePointer } from "gantt-schedule-timeline-calendar/dist/plugins/timeline-pointer.esm.min.js";
import { Plugin as Selection } from "gantt-schedule-timeline-calendar/dist/plugins/selection.esm.min.js";
import { Plugin as ItemResizing } from "gantt-schedule-timeline-calendar/dist/plugins/item-resizing.esm.min.js";
import { Plugin as ItemMovement } from "gantt-schedule-timeline-calendar/dist/plugins/item-movement.esm.min.js";
import { Plugin as Bookmarks } from "gantt-schedule-timeline-calendar/dist/plugins/time-bookmarks.esm.min.js";
import "gantt-schedule-timeline-calendar/dist/style.css";

let gstc, state;

// helper functions

function generateRows() {
  /**
   * @type { import("gantt-schedule-timeline-calendar").Rows }
   */
  const rows = {};
  for (let i = 0; i < 100; i++) {
    const id = GSTC.api.GSTCID(i.toString());
    rows[id] = {
      id,
      label: `Row ${i}`,
    };
  }
  return rows;
}

function generateItems() {
  /**
   * @type { import("gantt-schedule-timeline-calendar").Items }
   */
  const items = {};
  let start = GSTC.api.date().startOf("day").subtract(6, "day");
  for (let i = 0; i < 100; i++) {
    const id = GSTC.api.GSTCID(i.toString());
    const rowId = GSTC.api.GSTCID(Math.floor(Math.random() * 100).toString());
    start = start.add(1, "day");
    items[id] = {
      id,
      label: `Item ${i}`,
      rowId,
      time: {
        start: start.valueOf(),
        end: start.add(1, "day").endOf("day").valueOf(),
      },
    };
  }
  return items;
}

// main component

export default {
  name: "GSTC",
  mounted() {
    /**
     * @type { import("gantt-schedule-timeline-calendar").Config }
     */
    const config = {
      licenseKey:"====BEGIN LICENSE KEY====\nXYG2o42jRw/a3iH7h39MBWXdWsATAZBgws/mJX892QlqbN6WLZvBgL1l6x+SKTr3ANwuQszW088abYVwBdd/5+B1kBuW0iJJjWg6ihwE5DsVLC5d4fqKB0FAwTZqueuUOLugBMG1yPZMoRFoPtLTDh5z31bqI6oQ+TRctu6iFxKKKXPSSUh0dZRHQGmiVxVRkhCzXmuapCtlg/Jl1VGXFfQl1Exh2UQbeLKTzwTtYe5UN8QlMpYRzotE7KL0xGKWPfky9U7dR5+MSKqzWxbhkdBLICrw0SB1LQGJHY0Rfzt4RFI09+Z0+nU++IWgLSlzWw/4D2XFqXdI+Tv9gUdE8Q==||U2FsdGVkX19FoN1+oTq3VLUZkK6jGoCbafXwFt2h7C2LxfkJcUuMuOgP3l401AeDBOLQGM5lKwMSZTkLQc7NBh4BbIeYi1FDgJeuPrRuwuM=\nEOyfVBx2egIO890fGpZtc9LWIwOfi6SSeYgV45dY6sgLfOrbvevr4zWS69TdN3cfFgDhGsuZqeWy4ZWUdVGmeYc1lbG8zI6uYEyqQS2KvoeOo56E8ZzhjGvfBZ5sZVilJQIeUEP9SjK0cPcUJX4BgPUD1hxMqxpBeUV4Mki7uXC3OpO4x1eoKl0+oEtPvndJinFdpNxBtZI+tksVKaHOnOghMSK54Yd6rOzfJ8pcHjFRmq/1+OikEvXOOGvtYk1F719gM8HGPVd1POr3bJDj64NCRtZ4LXdQRwelNbd+uM7xHdp1l6916pwVgf55FOGNXAHVIRaiarYenr/S6IEIIQ==\n====END LICENSE KEY====",
       plugins: [TimelinePointer(), Selection(), ItemResizing(), ItemMovement(), Bookmarks()],
      list: {
          // 行属性
          rows: {
            "1": {
              id: "1",
              order: '订单1',
              label: "压缩机",
              line: '线体1',
              expanded: true
            },
            "3": {
              id: "3",
              order: '订单3',
              label: "箱体",
              line: '线体3',
              parentId: '2',
            },
            "4": {
              id: "4",
              order: '订单4',
              label: "空调总装",
              line: '线体4',
            },
            "2": {
              id: "2",
              order: '订单2',
              label: "门体",
              parentId: '1',
              line: '线体2',
              expanded: true
            },
            "5": {
              id: "5",
              order: '订单5',
              label: "冰箱总装",
              line: '线体5',
            },
            "6": {
              id: "6",
              order: '订单6',
              label: "洗衣机总装",
              line: '线体6',
            },
          },
          // 列定义
          columns: {
            data: {
              id: {
                id: "id",
                data: "id",
                width: 50,
                header: {
                  content: "序号"
                }
              },
              order: {
                id: "order",
                data: "order",
                width: 120,
                header: {
                  content: "生产订单"
                }
              },
              label: {
                id: "label",
                data: "label",
                width: 120,
                expander: true,
                header: {
                  content: "描述"
                }
              },
              line: {
                id: "line",
                data: "line",
                width: 120,
                header: {
                  content: "线体"
                }
              },
            }
          }
        },
        chart: {
          time: {  // 时间轴开始截至,
            from: new Date().getTime() - 2 * 24 * 60 * 60 * 1000,
            to: new Date().getTime() + 8 * 24 * 60 * 60 * 1000,
            zoom: 22,    // 10-22 缩放,默认 Shift + 滚轮, 默认缩放展示时间粒度, 一共有 小时、天、周、月、年
          },
          items: {
            "1": {
              id: "1",
              rowId: "1",
              label: "Item 1",
              time: {
                start: new Date().getTime() + 1 * 24 * 60 * 60 * 1000,
                end: new Date().getTime() + 2 * 24 * 60 * 60 * 1000
              },
              style: {  // 每个块的样式
                background: 'blue'
              }
            },
            "21": {
              id: "21",
              rowId: "2",
              label: "Item 2-1",
              time: {
                start: new Date().getTime() + 2 * 24 * 60 * 60 * 1000,
                end: new Date().getTime() + 3 * 24 * 60 * 60 * 1000
              }
            },
            "22": {
              id: "22",
              rowId: "2",
              label: "Item 2-2",
              time: {
                start: new Date().getTime() + 3 * 24 * 60 * 60 * 1000,
                end: new Date().getTime() + 4 * 24 * 60 * 60 * 1000
              }
            },
            "3": {
              id: "3",
              rowId: "3",
              label: "Item 3",
              time: {
                start: new Date().getTime() + 3 * 24 * 60 * 60 * 1000,
                end: new Date().getTime() + 5 * 24 * 60 * 60 * 1000
              }
            },
            "4": {
              id: "4",
              rowId: "4",
              label: "Item 4",
              time: {
                start: new Date().getTime() + 2 * 24 * 60 * 60 * 1000,
                end: new Date().getTime() + 5 * 24 * 60 * 60 * 1000
              }
            },
            "5": {
              id: "5",
              rowId: "5",
              label: "Item 5",
              time: {
                start: new Date().getTime() + 3 * 24 * 60 * 60 * 1000,
                end: new Date().getTime() + 5 * 24 * 60 * 60 * 1000
              }
            },
            "6": {
              id: "6",
              rowId: "6",
              label: "Item 6",
              time: {
                start: new Date().getTime() + 5 * 24 * 60 * 60 * 1000,
                end: new Date().getTime() + 6 * 24 * 60 * 60 * 1000
              }
            },
          }
        },
        locale: {
          name: "zh",
          Now: "Now",
          weekdays:["周日","周一","周二","周三","周四","周五","周六"],
          months:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],
        },
        actions: {
          'chart-timeline-items-row-item': [this.addListenClick] // 监听右击事件
        },
    };

    state = GSTC.api.stateFromConfig(config);

    gstc = GSTC({
      element: this.$refs.gstc,
      state,
    });
  },

  beforeUnmount() {
    if (gstc) gstc.destroy();
  },

  methods: {
    updateFirstRow() {
      state.update(`config.list.rows.${GSTC.api.GSTCID("0")}`, (row) => {
        row.label = "Changed dynamically";
        return row;
      });
    },

    changeZoomLevel() {
      state.update("config.chart.time.zoom", 21);
    },
  },
};
</script>
<style scoped>
.gstc-component {
  margin: 0;
  padding: 0;
}
.toolbox {
  padding: 10px;
}
</style>

​报错

查看报错信息, 里面有 license 相关的提示, 就一直照着那条线在往下找, 一直以为是写法不对或者license 问题;

ERROR  Failed to compile with 1 error                                                                                                                       下午2:38:14

 error  in ./node_modules/gantt-schedule-timeline-calendar/dist/gstc.esm.min.js

Module parse failed: Unexpected token (538:102)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|  * @license   SEE LICENSE IN LICENSE FILE
|  */
> const At=async function(t={}){let{importHook:e,serverPath:o}=t,s=new URL("assets/92ad4dd3.wasm",import.meta.url).href;return null!=o&&(s=o+/[^\/\\]*$/.exec(s)[0]),null!=e&&(s=e(s)),await zt(s),Rt};function Lt(t){const e=t.state,o=new S(e),s={treeMap:{},itemRowMap:{},list:{visibleRows:[],

在这里插入图片描述

根本原因

仔细查看报错, 其中第一句就是提示缺少loader
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

那到底是缺少什么loader, 继续往下看 发现第一个提示的文件是 new URL(“assets/92ad4dd3.wasm”, wasm 结尾的, 基本判定问题就出在这里了, 代码里有引用 .wasm 文件, 但项目中没有相应的loader 可以处理, 所以就报错;

解决办法

  1. 安装 wasm-loader ;
  2. 修改vue.config.js , 增加 wasm-loader;
npm install --save wasm-loader
chainWebpack: config => {   
    config.module
      .rule('wasm')
      .test(/\.wasm$/)
      .use('wasm-loader')
      .loader('wasm-loader')
      .end()
}


或早期版本可以使用
loaders: [
    {
      test: /\.wasm$/,
      loaders: ['wasm-loader']
    }
  ]
    

最终效果

在这里插入图片描述

Logo

前往低代码交流专区

更多推荐