UNPKG

vue-gantt-3

Version:

A gantt component for Vue 3

272 lines (271 loc) 11.5 kB
"use strict"; Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); const vue = require("vue"); const dayjs = require("dayjs"); const quarterOfYear = require("dayjs/plugin/quarterOfYear"); const common = require("../../../utils/common.js"); const index = require("../../../locale/index.js"); const _hoisted_1 = ["title"]; const _hoisted_2 = { class: "vg-header-block-text" }; const _hoisted_3 = ["title"]; const _hoisted_4 = { class: "vg-header-block-text" }; const bufferWidth = 200; const _sfc_main = /* @__PURE__ */ vue.defineComponent({ __name: "GanttHeader", props: { headerHeight: {}, edgeSpacing: {}, perHourSpacing: {}, ganttMinDate: {}, ganttViewWidth: {}, locale: {}, headerTextRender: { type: Function }, headerTipRender: { type: Function } }, setup(__props, { expose: __expose }) { dayjs.extend(quarterOfYear); const props = __props; const firstLevelBlocks = vue.shallowRef([]); const secondLevelBlocks = vue.shallowRef([]); const units = ["hour", "day", "week", "month", "quarter", "year"]; const scrollViewScrollLeft = vue.ref(0); const ganttHeaderRef = vue.ref(); const scrollLeftOffset = vue.ref(0); const showSecondLevel = vue.inject("showSecondLevel"); const showFirstLevel = vue.inject("showFirstLevel"); const localeRef = vue.computed(() => { if (props.locale) { return props.locale; } else { const language = navigator.language; if (language.startsWith("zh")) { return "zh-cn"; } else { return language; } } }); const ganttHeaderLevelWidth = vue.computed(() => { if (!ganttHeaderRef.value) return "100%"; const minWidth = ganttHeaderRef.value.offsetWidth; return Math.max(minWidth, props.ganttViewWidth + scrollLeftOffset.value) + "px"; }); const getUnit = vue.computed(() => { const { perHourSpacing } = props; let firstLevelUnitIndex = 0; const perMonthSpacing = perHourSpacing * 24 * 30; let canShowSecondLevel = true; if (perMonthSpacing >= 3e4) { firstLevelUnitIndex = units.indexOf("day"); } else if (perMonthSpacing >= 800) { firstLevelUnitIndex = units.indexOf("week"); } else if (perMonthSpacing >= 400) { firstLevelUnitIndex = units.indexOf("month"); } else if (perMonthSpacing >= 40) { firstLevelUnitIndex = units.indexOf("quarter"); } else if (perMonthSpacing >= 24) { firstLevelUnitIndex = units.indexOf("year"); } else if (perMonthSpacing >= 5) { firstLevelUnitIndex = units.indexOf("year"); canShowSecondLevel = false; } return { firstLevelUnit: units[firstLevelUnitIndex], secondLevelUnit: units[firstLevelUnitIndex - 1], canShowSecondLevel }; }); const startInfo = vue.computed(() => { const { perHourSpacing, edgeSpacing, ganttMinDate } = props; const { firstLevelUnit, secondLevelUnit } = getUnit.value; const diffSpacing = edgeSpacing / perHourSpacing; const startDate = ganttMinDate.subtract(diffSpacing, "hour"); const firstLevelStartUnitDate = startDate.endOf(firstLevelUnit); const secondLevelStartUnitDate = startDate.endOf(secondLevelUnit); const firstLevelStartLeft = firstLevelStartUnitDate.diff(startDate, "hour", true) * perHourSpacing; const secondLevelStartLeft = secondLevelStartUnitDate.diff(startDate, "hour", true) * perHourSpacing; return { firstLevelStartUnitDate, secondLevelStartUnitDate, firstLevelStartLeft, secondLevelStartLeft }; }); const freshBlocks = () => { if (!ganttHeaderRef.value) return; const { firstLevelStartUnitDate, secondLevelStartUnitDate, firstLevelStartLeft, secondLevelStartLeft } = startInfo.value; const { firstLevelUnit, secondLevelUnit, canShowSecondLevel } = getUnit.value; firstLevelBlocks.value = getNewBlocks(firstLevelStartLeft, firstLevelStartUnitDate, firstLevelUnit); showSecondLevel.value = canShowSecondLevel; if (canShowSecondLevel) { secondLevelBlocks.value = getNewBlocks(secondLevelStartLeft, secondLevelStartUnitDate, secondLevelUnit); } }; const getNewBlocks = (startLeft, startDate, currentUnit) => { const ganttHeaderWidth = ganttHeaderRef.value.offsetWidth; const startLeftInView = scrollViewScrollLeft.value - bufferWidth; const endLeftInView = scrollViewScrollLeft.value + ganttHeaderWidth + bufferWidth; const { perHourSpacing } = props; const newLevelBlocks = []; let levelStart = startLeft; let levelStartDateInView = startDate; if (startLeftInView > startLeft) { const diffHour = (startLeftInView - startLeft) / perHourSpacing; const startDateInView = startDate.add(diffHour, "hour"); const endDateInView = startDateInView.endOf(currentUnit); const diff = endDateInView.diff(startDate, "hour", true); levelStart = startLeft + diff * perHourSpacing; levelStartDateInView = endDateInView; } let currentLevelStartDateInView = levelStartDateInView; const limitMinLeft = scrollViewScrollLeft.value; const limintMaxLeft = scrollViewScrollLeft.value + ganttHeaderWidth; let blockSpacing = getBlockSpacingByUnit(currentLevelStartDateInView, currentUnit); while (levelStart - blockSpacing <= endLeftInView) { let width = blockSpacing; let offset = width; let hideRightBorder = false; if (levelStart > limitMinLeft && levelStart - blockSpacing < limitMinLeft) { offset = width = levelStart - limitMinLeft; if (width > ganttHeaderWidth) { width = ganttHeaderWidth; hideRightBorder = true; } } else if (levelStart > limintMaxLeft && levelStart - blockSpacing < limintMaxLeft) { width = blockSpacing - (levelStart - limintMaxLeft); hideRightBorder = true; } newLevelBlocks.push({ left: common.getRound(levelStart - offset), width: common.getRound(width), text: getBlockText(currentLevelStartDateInView, currentUnit), key: common.getRound(levelStart), tip: getBlockTip(currentLevelStartDateInView, currentUnit), hideRightBorder }); currentLevelStartDateInView = currentLevelStartDateInView.add(1, currentUnit).endOf(currentUnit); blockSpacing = getBlockSpacingByUnit(currentLevelStartDateInView, currentUnit); levelStart += blockSpacing; } return newLevelBlocks; }; const getBlockText = (date, unit) => { if (props.headerTextRender) { return props.headerTextRender(date, unit); } const currentLang = index.default[localeRef.value]; switch (unit) { case "hour": return date.hour(); case "day": return date.date(); case "month": return currentLang.month[date.month() + 1]; case "year": return date.year(); case "week": return `${date.startOf("week").format("YYYY.MM.DD")}-${date.endOf("week").format("YYYY.MM.DD")}`; case "quarter": return `${currentLang.month[date.startOf("quarter").month() + 1]}-${currentLang.month[date.endOf("quarter").month() + 1]}`; } }; const getBlockTip = (date, unit) => { if (props.headerTipRender) { return props.headerTipRender(date, unit); } const dateFormat = index.default[localeRef.value].dateFormat; switch (unit) { case "hour": return date.format(dateFormat["hour"]); case "day": return date.format(dateFormat["day"]); case "month": return date.format(dateFormat["month"]); case "year": return date.format(dateFormat["year"]); case "week": return `${date.startOf("week").format("YYYY.MM.DD")}-${date.endOf("week").format("YYYY.MM.DD")}`; case "quarter": return `${date.startOf("quarter").format(dateFormat["month"])}-${date.endOf("quarter").format(dateFormat["month"])}`; } }; const getBlockSpacingByUnit = (date, unit) => { const { perHourSpacing } = props; switch (unit) { case "hour": return perHourSpacing; case "day": return perHourSpacing * 24; case "week": return perHourSpacing * 24 * 7; } const startDate = date.startOf(unit); const diffHour = date.diff(startDate, "hour", true); return diffHour * perHourSpacing; }; vue.watch([localeRef, startInfo, scrollViewScrollLeft], freshBlocks); const onScroll = ({ scrollLeft }) => { scrollViewScrollLeft.value = scrollLeft; ganttHeaderRef.value && (ganttHeaderRef.value.scrollLeft = scrollLeft); }; const updateGanttHeaderWidth = (show, scrollbarWidth) => { if (show) { scrollLeftOffset.value = scrollbarWidth; } else { scrollLeftOffset.value = 0; } }; const onResize = () => { freshBlocks(); }; __expose({ onScroll, updateGanttHeaderWidth, onResize }); return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("div", { ref_key: "ganttHeaderRef", ref: ganttHeaderRef, class: "vg-header" }, [ vue.withDirectives(vue.createElementVNode("div", { class: "vg-header-first-level", style: vue.normalizeStyle({ width: ganttHeaderLevelWidth.value, height: `${_ctx.headerHeight + 1}px` }) }, [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(firstLevelBlocks.value, (item) => { return vue.openBlock(), vue.createElementBlock("div", { key: item.key, class: vue.normalizeClass(["vg-header-block", { "vg-header-block-hide-right-border": item.hideRightBorder }]), title: item.tip, style: vue.normalizeStyle({ width: item.width + "px", left: item.left + "px" }) }, [ vue.createElementVNode("span", _hoisted_2, vue.toDisplayString(item.text), 1) ], 14, _hoisted_1); }), 128)) ], 4), [ [vue.vShow, vue.unref(showFirstLevel) || !vue.unref(showSecondLevel)] ]), vue.withDirectives(vue.createElementVNode("div", { class: "vg-header-second-level", style: vue.normalizeStyle({ width: ganttHeaderLevelWidth.value, height: `${_ctx.headerHeight + 1}px` }) }, [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(secondLevelBlocks.value, (item) => { return vue.openBlock(), vue.createElementBlock("div", { key: item.key, class: vue.normalizeClass(["vg-header-block", { "vg-header-block-hide-right-border": item.hideRightBorder }]), title: item.tip, style: vue.normalizeStyle({ width: item.width + "px", left: item.left + "px" }) }, [ vue.createElementVNode("span", _hoisted_4, vue.toDisplayString(item.text), 1) ], 14, _hoisted_3); }), 128)) ], 4), [ [vue.vShow, vue.unref(showSecondLevel)] ]) ], 512); }; } }); exports.default = _sfc_main; //# sourceMappingURL=GanttHeader.vue.js.map