vue-gantt-3
Version:
A gantt component for Vue 3
1 lines • 14.9 kB
Source Map (JSON)
{"version":3,"file":"GanttTimeLineView.vue.mjs","sources":["../../../../../../src/components/ganttView/ganttBody/ganttTimeLineView/GanttTimeLineView.vue"],"sourcesContent":["<template>\n <div class=\"vg-time-line-view\">\n <div v-for=\"row in visibleRows\"\n :key=\"row.id\"\n class=\"vg-time-line-row vg-row\"\n :data-row-id=\"row.id\"\n :class=\"{'vg-selected-row': selectedRowIds.has(row.id)}\"\n :style=\"{height: rowHeightRef + 'px', transform: `translateY(${row.translateY}px)`}\">\n <div v-for=\"timeLine in visibleTimeLineMap.get(row.id)\"\n :key=\"timeLine.id\"\n :style=\"{width: timeLine.width + 'px', transform: `translateX(${timeLine.translateX}px)`}\"\n class=\"vg-time-line-row-time-line\">\n <div v-if=\"timeLine.type === 'normal'\"\n class=\"vg-time-line-normal\"\n :class=\"{moving: timeLine.moving === true, disabledMove: timeLine.disableMove || disableMove}\"\n @mousedown=\"e => startTimeLineMove(e, timeLine, row.id)\">\n <div v-show=\"!timeLine.disableStretch && !disableStretch\" class=\"vg-move-block\" @mousedown=\"e => startTimeLineStretch(e, timeLine, row.id, 'left')\"></div>\n <component :is=\"timeLineRender\" v-if=\"timeLineRender\" :params=\"timeLineRenderParams\" \n :visibleTimeLine=\"timeLine\" :timeLineWidth=\"timeLine.width\" :rowNode=\"row.rowNode\"></component>\n <div class=\"vg-time-line-normal-body\" v-if=\"!timeLineRender\" \n :style=\"{ backgroundColor: getTimeLineBackgroundColor(timeLine)}\"\n >\n <div v-show=\"styleOption?.barsLabeling !== 'none'\"\n class=\"vg-time-line-label\"\n :class=\"{toLeft: styleOption?.barsLabeling === 'beforeTheBar', toRight: styleOption?.barsLabeling === 'afterTheBar'}\">\n <img v-show=\"styleOption?.barsLabeling === 'insideBarWithIcon' && timeLine.icon\" :src=\"timeLine.icon\" alt=\"\">\n <span>{{ timeLine.label || '' }}</span>\n </div>\n </div>\n <div v-show=\"!timeLine.disableStretch && !disableStretch\" class=\"vg-move-block\" @mousedown=\"e => startTimeLineStretch(e, timeLine, row.id, 'right')\"></div>\n <div v-for=\"timePoint in timeLine.timePointNodes?.filter((() => styleOption?.showTimePoints))\"\n :key=\"timePoint.id\"\n class=\"vg-time-line-normal-time-points\"\n :style=\"{transform: `translate(${timePoint.translateX - timePointSize / 2 - 1}px, -50%)`, width: `${timePointSize}px`, height: `${timePointSize}px`}\"\n @contextmenu.stop=\"e => onTimePointContextMenu(e, timeLine, timePoint, row.id)\"\n @mousedown.stop=\"e => onTimePointMouseDown(e, timeLine, timePoint)\">\n <component :is=\"timePointComp\" v-if=\"timePoint.useTimePointComp\" v-bind=\"timePoint.compParams\"></component>\n <img v-else :src=\"timePoint.icon || timePointSvg\" alt=\"\">\n </div>\n </div>\n <div v-if=\"timeLine.type === 'parentTimeLineNode'\" class=\"vg-time-line-parentNode\">\n <div class=\"vg-time-line-parentNode-bar\"></div>\n <img class=\"vg-time-line-parentNode-triangle vg-time-line-parentNode-triangle-left\" width=\"12\" src=\"../../../../assets/images/BlackTriangle.svg\">\n <img class=\"vg-time-line-parentNode-triangle vg-time-line-parentNode-triangle-right\" width=\"12\" src=\"../../../../assets/images/BlackTriangle.svg\">\n </div>\n <div v-if=\"timeLine.type === 'sameDateTimeLineNode'\" class=\"vg-time-line-sameNode\"></div>\n </div>\n </div>\n </div>\n</template>\n<script lang=\"ts\" setup>\nimport { ref, inject, Ref, computed, watch, toRef } from 'vue';\nimport dayjs from 'dayjs';\nimport { GanttRowNode, VisibleTimeLine, GanttStyleOption } from '@/types';\nimport minMax from 'dayjs/plugin/minMax';\nimport isBetween from 'dayjs/plugin/isBetween';\nimport { useTimeLine } from './useTimeLine';\nimport { useTimePoint, createTimePointNodes } from './useTimePoint';\nimport { useTimeLineStretch } from './useTimeLineStretch';\nimport { useTimeLineMove } from './useTimeLineMove';\nimport timePointSvg from '../../../../assets/images/timePoint.svg';\n\ndayjs.extend(minMax);\ndayjs.extend(isBetween);\n\nexport interface Props {\n rowHeight: number,\n ganttMinDate: dayjs.Dayjs,\n ganttMaxDate: dayjs.Dayjs | null,\n perHourSpacing: number,\n rowBuffer: number,\n visibleRowIds: string[],\n rowNodeMap: Map<string, GanttRowNode>,\n ganttViewWidth: number,\n edgeSpacing: number,\n styleOption?: GanttStyleOption,\n timePointComp?: any,\n timeLineRender?: any,\n timeLineRenderParams?: Record<string, any>,\n}\n\nconst props = defineProps<Props>();\n\nconst emit = defineEmits<{\n (event: 'updateMinDate', date: dayjs.Dayjs): void,\n (event: 'updateMaxDate', date: dayjs.Dayjs): void,\n}>();\n\nconst wrapRef = inject('wrapRef') as Ref<HTMLDivElement | undefined>;\nconst scrollViewScrollTop = ref(0);\nconst scrollViewScrollLeft = ref(0);\nconst currentVisibleRowIds = toRef(props, 'visibleRowIds');\n\nconst selectedRowIds = inject('selectedRowIds') as Ref<Set<string>>;\nconst timeLineMoving = ref(false);\nconst movingTimeLine: Ref<VisibleTimeLine | null> = ref(null);\nconst movingTimeLineRowId = ref('');\nconst perHourSpacingRef = toRef(props, 'perHourSpacing');\nconst ganttViewWidthRef = toRef(props, 'ganttViewWidth');\nconst rowHeightRef = toRef(props, 'rowHeight');\nconst rowNodeMapRef = toRef(props, 'rowNodeMap');\nconst timePointSize = computed(() => {\n return props.styleOption?.timePointSize || 28;\n});\n\nconst disableStretch = computed(() => {\n return props.styleOption?.disableStretch;\n});\n\nconst disableMove = computed(() => {\n return props.styleOption?.disableMove;\n});\n\nconst getTimeLineBackgroundColor = (timeLine: VisibleTimeLine) => {\n return (timeLine.styleOption?.backgroundColor || props.styleOption?.barColor || '') as string;\n};\n\nconst startInfo = computed(() => {\n const { perHourSpacing, edgeSpacing, ganttMinDate } = props;\n const diffHour = edgeSpacing / perHourSpacing;\n const startDate = ganttMinDate.subtract(diffHour, 'hour');\n\n return {\n startDate,\n };\n});\n\nconst onScroll = ({ scrollTop, scrollLeft }: {scrollTop: number, scrollLeft: number}) => {\n scrollViewScrollTop.value = scrollTop;\n scrollViewScrollLeft.value = scrollLeft;\n};\n\nconst onResize = () => {\n freshTimeLineView();\n\n};\n\nconst emitUpdateMinDate = (date: dayjs.Dayjs) => {\n emit('updateMinDate', date);\n};\n\nconst emitUpdateMaxDate = (date: dayjs.Dayjs) => {\n emit('updateMaxDate', date);\n};\n\nconst getDiffSecondByDistance = (distance: number, startDate: dayjs.Dayjs) => {\n const { perHourSpacing } = props;\n\n const diffSecond = distance / perHourSpacing * 60 * 60;\n return startDate.add(diffSecond, 'second');\n};\n\nconst closeEdgeScroll = (perMoveSpacing: number, callBack: (moveSpacing: number) => any) => {\n if (timeLineMoving.value) {\n wrapRef.value!.scrollLeft += perMoveSpacing;\n callBack(perMoveSpacing);\n requestAnimationFrame(() => {\n closeEdgeScroll(perMoveSpacing, callBack);\n });\n }\n};\n\nconst {\n freshTimeLineView,\n freshTimeLineViewAfterScrollTop,\n freshTimeLines,\n freshVisibleTimeLines,\n sortTimeLineNodes,\n mergeOverlapTimeLine,\n visibleTimeLineMap,\n visibleRows,\n updateParentTimeLine\n} = useTimeLine({\n rowHeight: rowHeightRef,\n rowBuffer: props.rowBuffer,\n perHourSpacing: perHourSpacingRef,\n scrollViewScrollTop,\n scrollViewScrollLeft,\n rowNodeMap: rowNodeMapRef,\n currentVisibleRowIds,\n startInfo,\n movingTimeLineRowId,\n movingTimeLine,\n createTimePointNodes\n});\n\nwatch([currentVisibleRowIds, scrollViewScrollTop], freshTimeLineViewAfterScrollTop);\nwatch([startInfo, scrollViewScrollLeft], () => freshVisibleTimeLines(true));\n\nconst {\n onTimePointContextMenu,\n onTimePointMouseDown\n} = useTimePoint({\n timePointSize,\n perHourSpacing: perHourSpacingRef,\n rowNodeMap: rowNodeMapRef,\n visibleTimeLineMap\n});\n\nconst { startTimeLineStretch } = useTimeLineStretch({\n edgeSpacing: props.edgeSpacing,\n ganttViewWidth: ganttViewWidthRef,\n rowNodeMap: rowNodeMapRef,\n movingTimeLineRowId,\n movingTimeLine,\n timeLineMoving,\n visibleTimeLineMap,\n disableStretch,\n closeEdgeScroll,\n sortTimeLineNodes,\n mergeOverlapTimeLine,\n freshVisibleTimeLines,\n getDiffSecondByDistance,\n emitUpdateMinDate,\n emitUpdateMaxDate,\n updateParentTimeLine\n});\n\nconst { startTimeLineMove } = useTimeLineMove({\n edgeSpacing: props.edgeSpacing,\n ganttViewWidth: ganttViewWidthRef,\n rowNodeMap: rowNodeMapRef,\n movingTimeLineRowId,\n movingTimeLine,\n timeLineMoving,\n visibleTimeLineMap,\n disableMove,\n closeEdgeScroll,\n sortTimeLineNodes,\n mergeOverlapTimeLine,\n freshVisibleTimeLines,\n getDiffSecondByDistance,\n emitUpdateMinDate,\n emitUpdateMaxDate,\n updateParentTimeLine\n});\n\ndefineExpose({\n onScroll,\n onResize,\n freshTimeLines\n});\n</script>\n<style lang=\"scss\">\n.vg-time-line-view {\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n position: absolute;\n font-size: 16px;\n .vg-time-line-row {\n position: absolute;\n width: 100%;\n &.vg-selected-row {\n background-color: #0078d7;\n }\n .vg-time-line-row-time-line {\n position: absolute;\n left: 0;\n height: 100%;\n user-select: none;\n .vg-time-line-normal {\n position: absolute;\n width: 100%;\n left: 0;\n top: 50%;\n transform: translateY(-50%); \n cursor: grab;\n &.moving {\n cursor: grabbing;\n }\n &.disabledMove {\n cursor: default;\n }\n .vg-time-line-normal-body {\n height: 16px;\n border-radius: 6px;\n border: 1px solid #000;\n background: #fff;\n }\n .vg-time-line-normal-time-points {\n cursor: move;\n position: absolute;\n left: 0;\n top: 50%;\n > img {\n width: 100%;\n height: 100%;\n }\n }\n .vg-move-block {\n position: absolute;\n width: 6px;\n height: 100%;\n top: 0;\n cursor: ew-resize;\n &:first-of-type {\n left: 0;\n transform: translateX(-100%);\n }\n &:last-of-type {\n right: 0;\n transform: translateX(100%);\n }\n }\n }\n .vg-time-line-sameNode {\n width: 8px;\n height: 8px;\n position: absolute;\n left: 0;\n top: 50%;\n background-color: #000;\n transform: translate(-50%, -50%) rotate(45deg);\n }\n .vg-time-line-parentNode {\n position: absolute;\n width: 100%;\n left: 0;\n top: 50%;\n transform: translateY(-50%);\n height: 16px;\n .vg-time-line-parentNode-bar {\n position: absolute;\n width: 100%;\n top: 3px;\n height: 5px;\n background-color: #000;\n }\n .vg-time-line-parentNode-triangle {\n position: absolute;\n top: 50%;\n &.vg-time-line-parentNode-triangle-left {\n left: 0;\n transform: translateX(-50%) translateY(-50%);\n }\n &.vg-time-line-parentNode-triangle-right {\n right: 0;\n transform: translateX(50%) translateY(-50%);\n }\n }\n }\n .vg-time-line-label {\n position: absolute;\n height: 100%;\n max-width: 100%;\n display: inline-flex;\n align-items: center;\n white-space: nowrap;\n overflow: hidden;\n &.toLeft {\n max-width: unset;\n left: -4px;\n transform: translateX(-100%);\n }\n &.toRight {\n max-width: unset;\n right: -4px;\n transform: translateX(100%);\n }\n span {\n overflow: hidden;\n text-overflow: ellipsis;\n }\n }\n }\n }\n}\n</style>"],"names":[],"mappings":"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"}