v1.9.4 - bug fix
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.9.4] - 2026-03-06
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- 🔧 修复:日期视图下,SplitterBar拖拽以及TaskList收起/展开后,计算导致2月份周期丢失问题
|
||||||
|
- 🔧 修复:任务视图切换至资源视图后今日定位偏移问题
|
||||||
|
- 🔧 修复:任务视图切换至资源视图后最大和最小日期范围计算问题
|
||||||
|
- 🔧 修复:资源视图下,小时/日/周视图切换后,最大值和最小值范围问题
|
||||||
|
- 🔧 Fixed: In date view, after dragging the SplitterBar and collapsing/expanding the TaskList, the calculation caused the February cycle to be lost
|
||||||
|
- 🔧 Fixed: After switching from task view to resource view, the today marker offset issue
|
||||||
|
- 🔧 Fixed: After switching from task view to resource view, the max and min date range calculation issue
|
||||||
|
- 🔧 Fixed: In resource view, after switching between hourly/daily/weekly views, the max and min date range issue
|
||||||
|
|
||||||
## [1.9.3] - 2026-03-05
|
## [1.9.3] - 2026-03-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
37
demo/data-small.json
Normal file
37
demo/data-small.json
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"id": 1001,
|
||||||
|
"name": "上午会议",
|
||||||
|
"assignee": "测试用户",
|
||||||
|
"startDate": "2026-03-02 09:00",
|
||||||
|
"endDate": "2026-03-10 10:30",
|
||||||
|
"progress": 50,
|
||||||
|
"estimatedHours": 1.5,
|
||||||
|
"actualHours": 0.75,
|
||||||
|
"type": "task"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1002,
|
||||||
|
"name": "午后开发",
|
||||||
|
"assignee": "开发者",
|
||||||
|
"startDate": "2026-03-02 09:00",
|
||||||
|
"endDate": "2026-03-06 16:15",
|
||||||
|
"progress": 30,
|
||||||
|
"estimatedHours": 2.25,
|
||||||
|
"actualHours": 1.33,
|
||||||
|
"type": "task"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 1003,
|
||||||
|
"name": "测试任务",
|
||||||
|
"assignee": "测试员",
|
||||||
|
"startDate": "2026-03-02 09:00",
|
||||||
|
"endDate": "2026-03-08 17:45",
|
||||||
|
"progress": 0,
|
||||||
|
"estimatedHours": 1.25,
|
||||||
|
"actualHours": 0,
|
||||||
|
"type": "task"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -588,5 +588,21 @@
|
|||||||
"🔧 Fixed: TaskBar width (duration) shrinking after dragging left and right in weekly view",
|
"🔧 Fixed: TaskBar width (duration) shrinking after dragging left and right in weekly view",
|
||||||
"<span style=\"font-weight: bold; color: #f00;\">Special thanks to xuhang513@gitee for their use and feedback</span>"
|
"<span style=\"font-weight: bold; color: #f00;\">Special thanks to xuhang513@gitee for their use and feedback</span>"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "1.9.4",
|
||||||
|
"date": "2026-03-06",
|
||||||
|
"notes": [
|
||||||
|
"🔧 修复:日期视图下,SplitterBar拖拽以及TaskList收起/展开后,计算导致2月份周期丢失问题",
|
||||||
|
"🔧 修复:任务视图切换至资源视图后今日定位偏移问题",
|
||||||
|
"🔧 修复:任务视图切换至资源视图后最大和最小日期范围计算问题",
|
||||||
|
"🔧 修复:资源视图下,小时/日/周视图切换后,最大值和最小值范围问题",
|
||||||
|
"<span style=\"font-weight: bold; color: #f00;\">特别感谢来自jwuxin@gitee的使用与反馈</span>",
|
||||||
|
"🔧 Fixed: In date view, after dragging the SplitterBar and collapsing/expanding the TaskList, the calculation caused the February cycle to be lost",
|
||||||
|
"🔧 Fixed: After switching from task view to resource view, the today marker offset issue",
|
||||||
|
"🔧 Fixed: After switching from task view to resource view, the max and min date range calculation issue",
|
||||||
|
"🔧 Fixed: In resource view, after switching between hourly/daily/weekly views, the max and min date range issue",
|
||||||
|
"<span style=\"font-weight: bold; color: #f00;\">Special thanks to jwuxin@gitee for their use and feedback</span>"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "jordium-gantt-vue3",
|
"name": "jordium-gantt-vue3",
|
||||||
"version": "1.9.3",
|
"version": "1.9.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "npm-package/dist/jordium-gantt-vue3.cjs.js",
|
"main": "npm-package/dist/jordium-gantt-vue3.cjs.js",
|
||||||
"module": "npm-package/dist/jordium-gantt-vue3.es.js",
|
"module": "npm-package/dist/jordium-gantt-vue3.es.js",
|
||||||
|
|||||||
@@ -813,6 +813,10 @@ const dragging = ref(false)
|
|||||||
// v1.9.5 P2-4优化 - 提供Split Bar拖拽状态给子组件
|
// v1.9.5 P2-4优化 - 提供Split Bar拖拽状态给子组件
|
||||||
provide('isSplitBarDragging', dragging)
|
provide('isSplitBarDragging', dragging)
|
||||||
|
|
||||||
|
// TaskList 切换动画进行中的标志(提供给 Timeline,避免 toggle 期间误触发 resize 重算)
|
||||||
|
const isTaskListToggling = ref(false)
|
||||||
|
provide('isTaskListToggling', isTaskListToggling)
|
||||||
|
|
||||||
function onMouseDown(e: MouseEvent) {
|
function onMouseDown(e: MouseEvent) {
|
||||||
// 检查事件目标是否是task-list-toggle按钮或其子元素
|
// 检查事件目标是否是task-list-toggle按钮或其子元素
|
||||||
const target = e.target as HTMLElement
|
const target = e.target as HTMLElement
|
||||||
@@ -991,6 +995,9 @@ const toggleTaskList = () => {
|
|||||||
// 如果正在动画中,忽略点击
|
// 如果正在动画中,忽略点击
|
||||||
if (isAnimating.value) return
|
if (isAnimating.value) return
|
||||||
|
|
||||||
|
// 标记 toggle 进行中,阻止 Timeline 内 containerResizeObserver 误触发日期范围重算
|
||||||
|
isTaskListToggling.value = true
|
||||||
|
|
||||||
// 触发撞击动画
|
// 触发撞击动画
|
||||||
isAnimating.value = true
|
isAnimating.value = true
|
||||||
|
|
||||||
@@ -1012,7 +1019,9 @@ const toggleTaskList = () => {
|
|||||||
isAnimating.value = false
|
isAnimating.value = false
|
||||||
animationClass.value = ''
|
animationClass.value = ''
|
||||||
|
|
||||||
// 手动切换TaskList后,通知Timeline重新计算半圆
|
// toggle 结束:先清除标志(Timeline watch 会响应并只更新 sticky/bubble,跳过日期范围重算)
|
||||||
|
// 再通知 Timeline 重新计算半圆和 TaskBar 位置
|
||||||
|
isTaskListToggling.value = false
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('timeline-container-resized', {
|
new CustomEvent('timeline-container-resized', {
|
||||||
@@ -1025,11 +1034,14 @@ const toggleTaskList = () => {
|
|||||||
|
|
||||||
// 监听Timeline的TaskList切换事件
|
// 监听Timeline的TaskList切换事件
|
||||||
const handleToggleTaskList = (event: CustomEvent) => {
|
const handleToggleTaskList = (event: CustomEvent) => {
|
||||||
|
// 标记 toggle 进行中,阻止 Timeline 内 containerResizeObserver 误触发日期范围重算
|
||||||
|
isTaskListToggling.value = true
|
||||||
isTaskListVisible.value = event.detail
|
isTaskListVisible.value = event.detail
|
||||||
|
|
||||||
// TaskList切换会改变Timeline容器宽度,需要通知Timeline重新计算半圆
|
// TaskList切换会改变Timeline容器宽度,需要通知Timeline重新计算半圆
|
||||||
// 派发事件通知Timeline容器宽度发生了变化
|
// toggle 结束:清除标志后再派发事件,Timeline watch 响应时只更新 sticky/bubble
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
isTaskListToggling.value = false
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('timeline-container-resized', {
|
new CustomEvent('timeline-container-resized', {
|
||||||
detail: { source: 'task-list-toggle' },
|
detail: { source: 'task-list-toggle' },
|
||||||
@@ -1069,11 +1081,16 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 监听 timeline 容器宽度变化
|
// 监听 timeline 容器宽度变化
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
// 监听右侧面板(timeline 的可视容器)的宽度
|
// 监听 gantt-body(整体布局容器)宽度变化作为日期范围规划的基准
|
||||||
const rightPanel = document.querySelector('.gantt-panel-right')
|
// 使用 .gantt-body 而非 .gantt-panel-right,原因:
|
||||||
if (rightPanel) {
|
// 1. 拖拽 SplitterBar 和 TaskList toggle 只改变左右面板的内部分割,.gantt-body 总宽度不变
|
||||||
|
// → 不会误触发日期范围重算
|
||||||
|
// 2. 窗口 resize / 全屏切换才改变 .gantt-body 宽度 → 正确触发重算
|
||||||
|
// 3. 作为「最大可能宽度」兜底:TaskList 隐藏时 Timeline 最大可展开至此宽度
|
||||||
|
const ganttBody = document.querySelector('.gantt-body')
|
||||||
|
if (ganttBody) {
|
||||||
// 初始化宽度
|
// 初始化宽度
|
||||||
timelineContainerWidth.value = rightPanel.clientWidth
|
timelineContainerWidth.value = ganttBody.clientWidth
|
||||||
|
|
||||||
// 使用 ResizeObserver 监听宽度变化
|
// 使用 ResizeObserver 监听宽度变化
|
||||||
resizeObserver = new ResizeObserver(entries => {
|
resizeObserver = new ResizeObserver(entries => {
|
||||||
@@ -1081,7 +1098,7 @@ onMounted(() => {
|
|||||||
timelineContainerWidth.value = entry.contentRect.width
|
timelineContainerWidth.value = entry.contentRect.width
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
resizeObserver.observe(rightPanel)
|
resizeObserver.observe(ganttBody)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -1720,8 +1737,18 @@ const timelineDateRange = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let allTasks: Task[] = []
|
let allTasks: Task[] = []
|
||||||
if (props.tasks) allTasks = allTasks.concat(flattenTasks(props.tasks))
|
|
||||||
if (props.milestones) allTasks = allTasks.concat(props.milestones)
|
if (currentViewMode.value === 'resource' && props.resources) {
|
||||||
|
// 资源视图:从 resource.tasks 提取日期,避免传入基于任务视图的错误范围
|
||||||
|
for (const resource of (props.resources as Resource[])) {
|
||||||
|
if (resource.tasks && Array.isArray(resource.tasks)) {
|
||||||
|
allTasks = allTasks.concat(flattenTasks(resource.tasks as Task[]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (props.tasks) allTasks = allTasks.concat(flattenTasks(props.tasks))
|
||||||
|
if (props.milestones) allTasks = allTasks.concat(props.milestones)
|
||||||
|
}
|
||||||
|
|
||||||
// 过滤出有日期的任务
|
// 过滤出有日期的任务
|
||||||
const startDates = allTasks
|
const startDates = allTasks
|
||||||
|
|||||||
@@ -168,6 +168,9 @@ provide('positionCache', positionCache)
|
|||||||
// v1.9.5 P2-4优化 - 注入Split Bar拖拽状态
|
// v1.9.5 P2-4优化 - 注入Split Bar拖拽状态
|
||||||
const isSplitBarDragging = inject<Ref<boolean>>('isSplitBarDragging', ref(false))
|
const isSplitBarDragging = inject<Ref<boolean>>('isSplitBarDragging', ref(false))
|
||||||
|
|
||||||
|
// 注入 TaskList toggle 状态(toggle 期间阻止 containerResizeObserver 误触发日期范围重算)
|
||||||
|
const isTaskListToggling = inject<Ref<boolean>>('isTaskListToggling', ref(false))
|
||||||
|
|
||||||
// v1.9.5 注入showConflicts配置
|
// v1.9.5 注入showConflicts配置
|
||||||
const showConflicts = inject<ComputedRef<boolean>>('gantt-show-conflicts', computed(() => true))
|
const showConflicts = inject<ComputedRef<boolean>>('gantt-show-conflicts', computed(() => true))
|
||||||
|
|
||||||
@@ -292,7 +295,10 @@ const currentTimeScale = ref<TimelineScale>(TimelineScale.DAY)
|
|||||||
|
|
||||||
// 响应外部props变化,动态更新timelineConfig
|
// 响应外部props变化,动态更新timelineConfig
|
||||||
watch([timelineStartDate, timelineEndDate], ([newStart, newEnd]) => {
|
watch([timelineStartDate, timelineEndDate], ([newStart, newEnd]) => {
|
||||||
// 所有视图都正常响应props变化
|
// 资源视图下不响应 props 变化:
|
||||||
|
// GanttChart 的 timelineDateRange 计算可能传入基于任务视图的日期范围(已 computed 修复,但保留守卫作为二重保险)
|
||||||
|
// 资源视图的日期范围由 updateTimeScale / debouncedUpdateTimelineRange 内部管理
|
||||||
|
if (viewMode.value === 'resource') return
|
||||||
if (props.startDate || props.endDate) {
|
if (props.startDate || props.endDate) {
|
||||||
if (!isUpdatingTimelineConfig) {
|
if (!isUpdatingTimelineConfig) {
|
||||||
timelineConfig.value.startDate = newStart
|
timelineConfig.value.startDate = newStart
|
||||||
@@ -496,9 +502,13 @@ const getDayTimelineRange = () => {
|
|||||||
|
|
||||||
const { minDate, maxDate } = taskRange
|
const { minDate, maxDate } = taskRange
|
||||||
|
|
||||||
// 开始日期:任务最小开始日期-30天
|
// 开始日期:取任务最小日期所在月的前一个月月初(第1天)
|
||||||
let startDate = new Date(minDate)
|
// 采用月运算而非减30天,原因:
|
||||||
startDate.setDate(startDate.getDate() - 30)
|
// 减30天后若落在月末(如1月31日),normalize 到月初会多出一整个月(1月→1月1日),
|
||||||
|
// 而语义上只需在任务月份前保留一个完整月作为 buffer。
|
||||||
|
// 直接用 new Date(year, month-1, 1) 使 startDate 始终为月初且精确为前一个月,
|
||||||
|
// generateDayTimelineData 以月为单位迭代时 setMonth(+1) 不会因日期溢出跳过任何月份。
|
||||||
|
let startDate = new Date(minDate.getFullYear(), minDate.getMonth() - 1, 1)
|
||||||
|
|
||||||
// 结束日期:任务最大结束日期+30天
|
// 结束日期:任务最大结束日期+30天
|
||||||
let endDate = new Date(maxDate)
|
let endDate = new Date(maxDate)
|
||||||
@@ -1418,6 +1428,14 @@ let scrollTimeout: number | null = null
|
|||||||
const timelineScrollLeft = ref(0)
|
const timelineScrollLeft = ref(0)
|
||||||
const timelineContainerWidth = ref(0)
|
const timelineContainerWidth = ref(0)
|
||||||
|
|
||||||
|
// 跳过 debouncedUpdateTimelineRange 的一次性标志
|
||||||
|
// 用于 drag-end / toggle-end 配置 trigger 的宽度更新,只需要更新 sticky/bubble,无需重算日期范围
|
||||||
|
let skipTimelineRangeUpdate = false
|
||||||
|
|
||||||
|
// 允许 updateTimelineRange 在资源视图下执行一次的一次性标志
|
||||||
|
// 只在任务视图 → 资源视图切换时设置,计算完成后自动清除
|
||||||
|
let forceTimelineRangeInResourceView = false
|
||||||
|
|
||||||
// 半圆气泡控制状态
|
// 半圆气泡控制状态
|
||||||
const hideBubbles = ref(true) // 初始时隐藏半圆,等待初始滚动完成
|
const hideBubbles = ref(true) // 初始时隐藏半圆,等待初始滚动完成
|
||||||
const isInitialScrolling = ref(true) // 跟踪初始滚动状态
|
const isInitialScrolling = ref(true) // 跟踪初始滚动状态
|
||||||
@@ -2352,10 +2370,13 @@ const getOtherMilestonesInfo = (currentId: number) => {
|
|||||||
watch(isSplitBarDragging, (dragging) => {
|
watch(isSplitBarDragging, (dragging) => {
|
||||||
if (!dragging) {
|
if (!dragging) {
|
||||||
// v1.9.9 拖拽结束后,手动触发一次容器尺寸更新(因为拖拽期间ResizeObserver被暂停)
|
// v1.9.9 拖拽结束后,手动触发一次容器尺寸更新(因为拖拽期间ResizeObserver被暂停)
|
||||||
|
// 设置 skip 标志:拖拽不改变日期范围,只更新 sticky/bubble
|
||||||
if (timelineContainerElement.value) {
|
if (timelineContainerElement.value) {
|
||||||
const newWidth = timelineContainerElement.value.clientWidth
|
const newWidth = timelineContainerElement.value.clientWidth
|
||||||
if (Math.abs(newWidth - timelineContainerWidth.value) > 1) {
|
if (Math.abs(newWidth - timelineContainerWidth.value) > 1) {
|
||||||
|
skipTimelineRangeUpdate = true
|
||||||
timelineContainerWidth.value = newWidth
|
timelineContainerWidth.value = newWidth
|
||||||
|
nextTick(() => { skipTimelineRangeUpdate = false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2388,6 +2409,23 @@ const handleSplitterDragEnd = () => {
|
|||||||
// 清理工作已移至watch(isSplitBarDragging)
|
// 清理工作已移至watch(isSplitBarDragging)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听 TaskList toggle 结束,手动更新 Timeline 内部容器宽度
|
||||||
|
// 跳过日期范围重算,只让 sticky/bubble 重算和 TaskBar 重渲染生效
|
||||||
|
watch(isTaskListToggling, (toggling) => {
|
||||||
|
if (!toggling) {
|
||||||
|
// toggle 结束:读取 .timeline 滚动容器的真实新宽度
|
||||||
|
// 使用 skip 标志,避免 watch(timelineContainerWidth) 触发 debouncedUpdateTimelineRange
|
||||||
|
if (timelineContainerElement.value) {
|
||||||
|
const newWidth = timelineContainerElement.value.clientWidth
|
||||||
|
if (Math.abs(newWidth - timelineContainerWidth.value) > 1) {
|
||||||
|
skipTimelineRangeUpdate = true
|
||||||
|
timelineContainerWidth.value = newWidth
|
||||||
|
nextTick(() => { skipTimelineRangeUpdate = false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 处理Timeline容器resize事件(如TaskList切换等)
|
// 处理Timeline容器resize事件(如TaskList切换等)
|
||||||
const handleTimelineContainerResized = () => {
|
const handleTimelineContainerResized = () => {
|
||||||
// Timeline容器大小发生变化,需要强制重新计算半圆显示状态
|
// Timeline容器大小发生变化,需要强制重新计算半圆显示状态
|
||||||
@@ -3763,6 +3801,11 @@ onMounted(() => {
|
|||||||
if (isSplitBarDragging.value) {
|
if (isSplitBarDragging.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// TaskList toggle 期间不处理宽度变化,外层 .gantt-body 已屏蔽日期范围重算
|
||||||
|
// toggle 结束后由 watch(isTaskListToggling) 手动更新宽度
|
||||||
|
if (isTaskListToggling.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
const newWidth = entry.contentRect.width
|
const newWidth = entry.contentRect.width
|
||||||
@@ -4587,10 +4630,11 @@ const debouncedUpdateTimelineRange = (delay = 50) => {
|
|||||||
const updateTimelineRange = () => {
|
const updateTimelineRange = () => {
|
||||||
// 资源视图下不自动调整时间范围,保持Timeline背景层(header + 竖列)稳定
|
// 资源视图下不自动调整时间范围,保持Timeline背景层(header + 竖列)稳定
|
||||||
// 避免滚动时重新生成timelineData导致header闪烁
|
// 避免滚动时重新生成timelineData导致header闪烁
|
||||||
// 虚拟滚动通过visibleTimeRange过滤TaskBar即可
|
// 例外:任务视图 → 资源视图切换时,需要一次性重算以实现基于资源任务的日期范围
|
||||||
if (viewMode.value === 'resource') {
|
if (viewMode.value === 'resource' && !forceTimelineRangeInResourceView) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
forceTimelineRangeInResourceView = false
|
||||||
|
|
||||||
let newRange: { startDate: Date; endDate: Date } | null = null
|
let newRange: { startDate: Date; endDate: Date } | null = null
|
||||||
|
|
||||||
@@ -4625,6 +4669,9 @@ watch(
|
|||||||
// 拖拽 splitter 时跳过重新计算
|
// 拖拽 splitter 时跳过重新计算
|
||||||
if (isSplitterDragging.value) return
|
if (isSplitterDragging.value) return
|
||||||
|
|
||||||
|
// drag-end / toggle-end 触发的宽度更新:只需要 sticky/bubble/TaskBar 重渲染,跳过日期范围重算
|
||||||
|
if (skipTimelineRangeUpdate) return
|
||||||
|
|
||||||
// 只在容器宽度从 0 变为有效值,或容器宽度发生显著变化时重新计算
|
// 只在容器宽度从 0 变为有效值,或容器宽度发生显著变化时重新计算
|
||||||
if (!oldWidth || oldWidth === 0 || Math.abs(newWidth - oldWidth) > 50) {
|
if (!oldWidth || oldWidth === 0 || Math.abs(newWidth - oldWidth) > 50) {
|
||||||
if (newWidth > 0) {
|
if (newWidth > 0) {
|
||||||
@@ -4672,12 +4719,13 @@ watch(
|
|||||||
debouncedUpdateTimelineRange()
|
debouncedUpdateTimelineRange()
|
||||||
} else if (newViewMode === 'resource') {
|
} else if (newViewMode === 'resource') {
|
||||||
if (viewModeChanged) {
|
if (viewModeChanged) {
|
||||||
// bugfix: 切换到资源视图时直接调用 scrollToTodayCenter
|
// 切换到资源视图:基于资源任务重算日期范围,重算完成后由 watch([timelineData,...]) 触发滚到今日
|
||||||
// 原因:updateTimelineRange() 在 resource 视图下直接返回(不更新 timelineData/timelineConfig),
|
// 重置 hasInitialAutoScroll,确保 watch([timelineData, timelineConfig...]) 在重算完成后能滚到今日
|
||||||
// 导致内层 watch 无法触发,timeline 保留任务视图中拖拽后的偏移位置
|
// 不在此处直接调用 scrollToTodayCenter(),因为 debouncedUpdateTimelineRange 有 50ms 延迟,
|
||||||
// 注意:切换视图不重新挂载 DOM,timelineContainerElement 始终可用,
|
// nextTick 会在 50ms 之前就执行,导致用旧的 task 视图坐标滚到错误位置
|
||||||
// nextTick 后直接调用即可,scrollToTodayCenter 内部有重试机制无需额外 setTimeout
|
hasInitialAutoScroll = false
|
||||||
nextTick(() => scrollToTodayCenter())
|
forceTimelineRangeInResourceView = true
|
||||||
|
debouncedUpdateTimelineRange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -91,7 +91,21 @@ const canvasStyle = computed(() => ({
|
|||||||
// 监听任务列表变化
|
// 监听任务列表变化
|
||||||
watch(() => props.tasks, () => {
|
watch(() => props.tasks, () => {
|
||||||
if (isDraggingTaskBar.value) {
|
if (isDraggingTaskBar.value) {
|
||||||
|
// 拖拽进行中:标记需要重算,等拖拽结束后再执行
|
||||||
needsRecalculation.value = true
|
needsRecalculation.value = true
|
||||||
|
} else {
|
||||||
|
// 拖拽结束后的已提交数据变更:isDraggingTaskBar 已先于数据更新变为 false,
|
||||||
|
// 此处直接触发增量/全量重算,避免冲突层不刷新。
|
||||||
|
nextTick(() => {
|
||||||
|
if (lastChangedTaskId.value !== null) {
|
||||||
|
recalculateConflictsIncremental(lastChangedTaskId.value)
|
||||||
|
lastChangedTaskId.value = null
|
||||||
|
} else {
|
||||||
|
texturePatterns.value = { light: null, medium: null, severe: null }
|
||||||
|
coordsCache.clear()
|
||||||
|
recalculateConflicts()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user