UNPKG

vxe-gantt

Version:
430 lines (429 loc) 24.3 kB
import { h, inject, ref, onMounted, onUnmounted } from 'vue'; import { defineVxeComponent } from '../../ui/src/comp'; import { VxeUI } from '@vxe-ui/core'; import XEUtils from 'xe-utils'; import { getCellRestHeight, hasMilestoneTask, getTaskType, hasSubviewTask } from './util'; import { getStringValue, isEnableConf, hasEnableConf } from '../../ui/src/utils'; const { getIcon, renderEmptyElement } = VxeUI; const sourceType = 'gantt'; const viewType = 'chart'; export default defineVxeComponent({ name: 'VxeGanttViewChart', setup() { const $xeGantt = inject('$xeGantt', {}); const $xeGanttView = inject('$xeGanttView', {}); const { props: ganttProps, context: ganttContext, reactData: ganttReactData, internalData: ganttInternalData } = $xeGantt; const { reactData: ganttViewReactData, internalData: ganttViewInternalData } = $xeGanttView; const { computeProgressField, computeTitleField, computeTypeField, computeTaskBarOpts, computeScaleUnit, computeTaskLinkOpts, computeTaskBarMilestoneOpts, computeTaskBarSubviewOpts } = $xeGantt.getComputeMaps(); const { computeNowLineLeft } = $xeGanttView.getComputeMaps(); const refElem = ref(); const refTaskWrapperElem = ref(); const refChartBeforeWrapperElem = ref(); const refChartAfterWrapperElem = ref(); const refNowLineElem = ref(); const renderTaskBar = ($xeTable, row, rowid, rowIndex, $rowIndex, _rowIndex, rowChildren, isExpandTree) => { const tableReactData = $xeTable.reactData; const { resizeHeightFlag, pendingRowFlag } = tableReactData; const tableInternalData = $xeTable.internalData; const { fullAllDataRowIdData, pendingRowMaps } = tableInternalData; const { computeCellOpts, computeRowOpts, computeDefaultRowHeight } = $xeTable.getComputeMaps(); const cellOpts = computeCellOpts.value; const rowOpts = computeRowOpts.value; const defaultRowHeight = computeDefaultRowHeight.value; const { computeTreeOpts } = $xeTable.getComputeMaps(); const treeOpts = computeTreeOpts.value; const childrenField = treeOpts.children || treeOpts.childrenField; const ganttSlots = $xeGantt.context.slots; const taskBarSlot = ganttSlots.taskBar || ganttSlots['task-bar']; const taskBarOverviewSlot = ganttSlots.taskBarOverview || ganttSlots['task-bar-overview']; const { treeConfig, taskBarMilestoneConfig, taskBarSubviewConfig } = ganttProps; const { activeLink, activeBarRowid } = ganttReactData; const titleField = computeTitleField.value; const progressField = computeProgressField.value; const typeField = computeTypeField.value; const taskBarOpts = computeTaskBarOpts.value; const taskBarMilestoneOpts = computeTaskBarMilestoneOpts.value; const taskBarSubviewOpts = computeTaskBarSubviewOpts.value; const { showOverview, barStyle: subBarStyle } = taskBarSubviewOpts; const scaleUnit = computeScaleUnit.value; const barParams = { $gantt: $xeGantt, row, scaleType: scaleUnit }; const { showProgress, showContent, contentMethod, barStyle, moveable, showTooltip } = taskBarOpts; const isBarRowStyle = XEUtils.isFunction(barStyle); const barStyObj = (barStyle ? (isBarRowStyle ? barStyle(barParams) || undefined : barStyle) : {}) || {}; const { round } = barStyObj; const rowRest = fullAllDataRowIdData[rowid] || {}; const cellHeight = resizeHeightFlag ? getCellRestHeight(rowRest, cellOpts, rowOpts, defaultRowHeight) : 0; let title = getStringValue(XEUtils.get(row, titleField)); const progressValue = showProgress ? Math.min(100, Math.max(0, XEUtils.toNumber(XEUtils.get(row, progressField)))) : 0; const renderTaskType = getTaskType(XEUtils.get(row, typeField)); const vbStyle = {}; const vpStyle = { width: `${progressValue || 0}%` }; if (isBarRowStyle) { const { bgColor, completedBgColor } = barStyObj; if (bgColor) { vbStyle.backgroundColor = bgColor; } if (completedBgColor) { vpStyle.backgroundColor = completedBgColor; } } const ctParams = { $gantt: $xeGantt, source: sourceType, type: viewType, scaleType: scaleUnit, row, $rowIndex, rowIndex, _rowIndex }; let cbVNs = []; if ($xeGantt.renderGanttTaskBarContent) { cbVNs = $xeGantt.renderGanttTaskBarContent(ctParams, { $gantt: $xeGantt, $table: $xeTable, rowid }); } else { const isMilestone = !!(hasEnableConf(taskBarMilestoneConfig, taskBarMilestoneOpts) && hasMilestoneTask(renderTaskType)); const isSubview = !!(hasEnableConf(taskBarSubviewConfig, taskBarSubviewOpts) && hasSubviewTask(renderTaskType)); if (contentMethod) { title = getStringValue(contentMethod({ row, title, scaleType: scaleUnit })); } const ctOns = {}; if (showTooltip) { ctOns.onMouseover = (evnt) => { const { dragBarRow } = ganttInternalData; const ttParams = Object.assign({ $event: evnt }, ctParams); if (!dragBarRow) { $xeGantt.triggerTaskBarTooltipEvent(evnt, ttParams); } $xeGantt.dispatchEvent('task-bar-mouseenter', ttParams, evnt); }; ctOns.onMouseleave = (evnt) => { const { dragBarRow } = ganttInternalData; const ttParams = Object.assign({ $event: evnt }, ctParams); if (!dragBarRow) { $xeGantt.handleTaskBarTooltipLeaveEvent(evnt, ttParams); } $xeGantt.dispatchEvent('task-bar-mouseleave', ttParams, evnt); }; } if (isSubview && treeConfig && rowChildren && rowChildren.length) { if (isExpandTree) { if (showOverview) { cbVNs.push(h('div', { key: 'vcso', class: 'vxe-gantt-view--chart-subview-wrapper is--overview' }, [ h('div', { key: rowid, rowid: rowid, class: ['vxe-gantt-view--chart-subview-row', { 'is--progress': showProgress, 'is--round': round, 'is--move': moveable }] }, [ h('div', { rowid: rowid, class: [taskBarOverviewSlot ? 'vxe-gantt-view--chart-subview-custom-bar' : 'vxe-gantt-view--chart-subview-bar', `is--${renderTaskType}`] }, [ taskBarOverviewSlot ? h('div', { key: 'cbc', class: 'vxe-gantt-view--chart-subview-custom-bar-content-wrapper' }, $xeGantt.callSlot(taskBarOverviewSlot, barParams)) : h('div', { class: 'vxe-gantt-view--chart-subview-bar-content-wrapper' }, [ showContent ? h('div', { class: 'vxe-gantt-view--chart-content' }, title) : renderEmptyElement($xeGantt) ]) ]) ]) ])); } } else { const cbcVNs = []; XEUtils.eachTree(rowChildren, childRow => { const childBarParams = { $gantt: $xeGantt, row: childRow, scaleType: scaleUnit }; const childBarStyObj = (barStyle ? (isBarRowStyle ? barStyle(childBarParams) : barStyle) : {}) || {}; const { round } = childBarStyObj; const childRowid = $xeTable.getRowid(childRow); let childTitle = getStringValue(XEUtils.get(childRow, titleField)); const childProgressValue = showProgress ? Math.min(100, Math.max(0, XEUtils.toNumber(XEUtils.get(childRow, progressField)))) : 0; const childRenderTaskType = getTaskType(XEUtils.get(childRow, typeField)); const isChildSubview = !!(hasEnableConf(taskBarSubviewConfig, taskBarSubviewOpts) && hasSubviewTask(childRenderTaskType)); if (isChildSubview) { return; } const childVbStyle = {}; const childVpStyle = { width: `${childProgressValue || 0}%` }; if (isBarRowStyle) { const { bgColor, completedBgColor } = childBarStyObj; if (bgColor) { childVbStyle.backgroundColor = bgColor; } if (completedBgColor) { childVpStyle.backgroundColor = completedBgColor; } } const childCtParams = XEUtils.assign({}, ctParams, { row: childRow, rowIndex: $xeTable.getRowIndex(childRow), $rowIndex: $xeTable.getVMRowIndex(childRow), _rowIndex: $xeTable.getVTRowIndex(childRow) }); if (contentMethod) { childTitle = getStringValue(contentMethod({ row: childRow, title: childTitle, scaleType: scaleUnit })); } cbcVNs.push(h('div', { key: childRowid, rowid: childRowid, class: ['vxe-gantt-view--chart-subview-row', `is--${childRenderTaskType}`, { 'is--progress': showProgress, 'is--round': round, 'is--move': moveable, 'row--pending': !!pendingRowFlag && !!pendingRowMaps[childRowid] }] }, [ h('div', { rowid: childRowid, class: [taskBarSlot ? 'vxe-gantt-view--chart-subview-custom-bar' : 'vxe-gantt-view--chart-subview-bar', `is--${childRenderTaskType}`], style: subBarStyle ? (XEUtils.isFunction(subBarStyle) ? subBarStyle(childCtParams) : subBarStyle) : undefined, onClick(evnt) { evnt.stopPropagation(); $xeGantt.handleTaskBarClickEvent(evnt, childCtParams); }, onDblclick(evnt) { evnt.stopPropagation(); $xeGantt.handleTaskBarDblclickEvent(evnt, childCtParams); }, onMousedown(evnt) { evnt.stopPropagation(); if ($xeGantt.handleTaskBarMousedownEvent) { $xeGantt.handleTaskBarMousedownEvent(evnt, childCtParams); } } }, [ taskBarSlot ? h('div', Object.assign({ key: 'cbc', class: 'vxe-gantt-view--chart-subview-custom-bar-content-wrapper' }, ctOns), $xeGantt.callSlot(taskBarSlot, childCtParams)) : h('div', Object.assign({ class: 'vxe-gantt-view--chart-subview-bar-content-wrapper' }, ctOns), [ showProgress ? h('div', { class: 'vxe-gantt-view--chart-progress', style: childVpStyle }) : renderEmptyElement($xeGantt), showContent ? h('div', { class: 'vxe-gantt-view--chart-content' }, childTitle) : renderEmptyElement($xeGantt) ]) ]) ])); }, { children: childrenField }); cbVNs.push(h('div', { key: 'vcsc', class: 'vxe-gantt-view--chart-subview-wrapper is--inline' }, cbcVNs)); } } else { if (taskBarSlot) { cbVNs.push(h('div', Object.assign({ key: 'cbc', class: 'vxe-gantt-view--chart-custom-bar-content-wrapper' }, ctOns), $xeGantt.callSlot(taskBarSlot, barParams))); } else if (isMilestone) { const { icon, iconStatus, iconStyle } = taskBarMilestoneOpts; const tbmParams = { $gantt: $xeGantt, row }; cbVNs.push(h('div', Object.assign({ key: 'vcm', class: 'vxe-gantt-view--chart-milestone-wrapper' }, ctOns), [ h('div', { class: ['vxe-gantt-view--chart-milestone-icon', iconStatus ? `theme--${XEUtils.isFunction(iconStatus) ? iconStatus(tbmParams) : iconStatus}` : ''], style: iconStyle ? Object.assign({}, XEUtils.isFunction(iconStyle) ? iconStyle(tbmParams) : iconStyle) : undefined }, [ h('i', { class: (icon ? (XEUtils.isFunction(icon) ? icon(tbmParams) : icon) : '') || getIcon().GANTT_VIEW_TASK_MILESTONE }) ]), showContent ? h('div', { class: 'vxe-gantt-view--chart-milestone-content' }, title) : renderEmptyElement($xeGantt) ])); } else { cbVNs.push(h('div', Object.assign({ key: 'vbc', class: 'vxe-gantt-view--chart-bar-content-wrapper' }, ctOns), [ showProgress ? h('div', { class: 'vxe-gantt-view--chart-progress', style: vpStyle }) : renderEmptyElement($xeGantt), showContent ? h('div', { class: 'vxe-gantt-view--chart-content' }, title) : renderEmptyElement($xeGantt) ])); } } } return h('div', { key: rowid, rowid, class: ['vxe-gantt-view--chart-row', `is--${renderTaskType}`, { 'is--progress': showProgress, 'row--pending': !!pendingRowFlag && !!pendingRowMaps[rowid], 'is--round': round, 'is--move': moveable }], style: { height: `${cellHeight}px` }, onDragstart(evnt) { if (ganttInternalData.dragBarRow) { evnt.preventDefault(); } }, onContextmenu(evnt) { $xeGantt.handleTaskBarContextmenuEvent(evnt, ctParams); } }, [ h('div', { class: [taskBarSlot ? 'vxe-gantt-view--chart-custom-bar' : 'vxe-gantt-view--chart-bar', `is--${renderTaskType}`, { 'is--active': activeBarRowid === rowid, 'active--link': activeLink && (rowid === `${activeLink.from}` || rowid === `${activeLink.to}`) }], style: vbStyle, rowid, onClick(evnt) { $xeGantt.handleTaskBarClickEvent(evnt, barParams); }, onDblclick(evnt) { $xeGantt.handleTaskBarDblclickEvent(evnt, barParams); }, onMousedown(evnt) { if ($xeGantt.handleTaskBarMousedownEvent) { $xeGantt.handleTaskBarMousedownEvent(evnt, barParams); } } }, cbVNs) ]); }; const renderTaskRows = ($xeTable, tableData) => { const tableProps = $xeTable.props; const { treeConfig } = tableProps; const tableReactData = $xeTable.reactData; const { treeExpandedFlag } = tableReactData; const tableInternalData = $xeTable.internalData; const { fullAllDataRowIdData, treeExpandedMaps } = tableInternalData; const { computeTreeOpts } = $xeTable.getComputeMaps(); const treeOpts = computeTreeOpts.value; const { transform } = treeOpts; const childrenField = treeOpts.children || treeOpts.childrenField; const { scrollYLoad } = ganttViewReactData; const trVNs = []; tableData.forEach((row, $rowIndex) => { const rowid = $xeTable.getRowid(row); const rowRest = fullAllDataRowIdData[rowid] || {}; let rowIndex = $rowIndex; let _rowIndex = -1; if (rowRest) { rowIndex = rowRest.index; _rowIndex = rowRest._index; } let isExpandTree = false; let rowChildren = []; if (treeConfig) { rowChildren = row[childrenField]; isExpandTree = !!treeExpandedFlag && rowChildren && rowChildren.length > 0 && !!treeExpandedMaps[rowid]; } trVNs.push(renderTaskBar($xeTable, row, rowid, rowIndex, $rowIndex, _rowIndex, rowChildren, isExpandTree)); // 如果是树形表格 if (treeConfig && isExpandTree && !scrollYLoad && !transform) { trVNs.push(...renderTaskRows($xeTable, rowChildren)); } }); return trVNs; }; const renderVN = () => { const $xeTable = ganttViewInternalData.xeTable; const { slots: ganttSlots } = ganttContext; const { dragLinkFromStore } = ganttReactData; const { tableData } = ganttViewReactData; const taskLinkOpts = computeTaskLinkOpts.value; const taskBarOpts = computeTaskBarOpts.value; const nowLineLeft = computeNowLineLeft.value; const { isCurrent, isHover } = taskLinkOpts; const { linkCreatable } = taskBarOpts; const taskNowLineSlot = ganttSlots.taskNowLine || ganttSlots['task-now-line']; return h('div', { ref: refElem, class: ['vxe-gantt-view--chart-wrapper', { 'is--cl-drag': dragLinkFromStore.rowid }] }, [ nowLineLeft > 0 ? h('div', { ref: refNowLineElem, class: 'vxe-gantt-view--chart-now-line', style: { left: nowLineLeft + 'px' } }, taskNowLineSlot ? taskNowLineSlot({}) : []) : renderEmptyElement($xeGantt), $xeGantt.renderGanttTaskChartBefores ? h('div', { ref: refChartBeforeWrapperElem, class: ['vxe-gantt-view--chart-before-wrapper', { 'link--current': isCurrent, 'link--hover': isHover }] }, $xeTable && isEnableConf(taskLinkOpts) ? $xeGantt.renderGanttTaskChartBefores() : []) : renderEmptyElement($xeGantt), h('div', { ref: refTaskWrapperElem, class: ['vxe-gantt-view--chart-task-wrapper', { 'link--current': isCurrent, 'link--create': linkCreatable }] }, $xeTable ? renderTaskRows($xeTable, tableData) : []), $xeGantt.renderGanttTaskChartAfters ? h('div', { ref: refChartAfterWrapperElem, class: 'vxe-gantt-view--chart-after-wrapper' }, $xeTable && isEnableConf(taskLinkOpts) ? $xeGantt.renderGanttTaskChartAfters() : []) : renderEmptyElement($xeGantt) ]); }; onMounted(() => { const { elemStore } = ganttViewInternalData; const prefix = 'main-chart-'; elemStore[`${prefix}now-line`] = refNowLineElem; elemStore[`${prefix}task-wrapper`] = refTaskWrapperElem; elemStore[`${prefix}before-wrapper`] = refChartBeforeWrapperElem; elemStore[`${prefix}after-wrapper`] = refChartAfterWrapperElem; }); onUnmounted(() => { const { elemStore } = ganttViewInternalData; const prefix = 'main-chart-'; elemStore[`${prefix}now-line`] = null; elemStore[`${prefix}task-wrapper`] = null; elemStore[`${prefix}before-wrapper`] = null; elemStore[`${prefix}after-wrapper`] = null; }); return renderVN; } });