v1.0.10 - UX upgrades

This commit is contained in:
LINING-PC\lining
2025-07-06 11:03:03 +08:00
parent 94ee66cbb4
commit af4a35254f
20 changed files with 2026 additions and 191 deletions
+23 -90
View File
@@ -4,6 +4,7 @@ import TaskList from './TaskList.vue'
import Timeline from './Timeline.vue'
import GanttToolbar from './GanttToolbar.vue'
import { useI18n, setCustomMessages } from '../composables/useI18n'
import { formatPredecessorDisplay } from '../utils/predecessorUtils'
import jsPDF from 'jspdf'
import html2canvas from 'html2canvas'
import type { Task } from '../models/classes/Task'
@@ -222,16 +223,35 @@ const toggleTaskList = () => {
isTaskListVisible.value = !isTaskListVisible.value
}, 200)
// 动画结束后清理状态
// 动画结束后清理状态,并通知Timeline容器变化
setTimeout(() => {
isAnimating.value = false
animationClass.value = ''
// 手动切换TaskList后,通知Timeline重新计算半圆
nextTick(() => {
window.dispatchEvent(
new CustomEvent('timeline-container-resized', {
detail: { source: 'manual-task-list-toggle' },
}),
)
})
}, 400)
}
// 监听Timeline的TaskList切换事件
const handleToggleTaskList = (event: CustomEvent) => {
isTaskListVisible.value = event.detail
// TaskList切换会改变Timeline容器宽度,需要通知Timeline重新计算半圆
// 派发事件通知Timeline容器宽度发生了变化
nextTick(() => {
window.dispatchEvent(
new CustomEvent('timeline-container-resized', {
detail: { source: 'task-list-toggle' },
}),
)
})
}
// --- 事件链路:监听 Timeline 传递上来的拖拽/拉伸事件,并通过 props 回调暴露 ---
@@ -716,7 +736,7 @@ const generateCsvContent = (tasks: Task[]): string => {
result.push({
id: task.id,
name: task.name || '',
predecessor: task.predecessor || '',
predecessor: formatPredecessorDisplay(task.predecessor),
assignee: task.assignee || '',
startDate: task.startDate || '',
endDate: task.endDate || '',
@@ -747,7 +767,7 @@ const generateCsvContent = (tasks: Task[]): string => {
return [
escapeCSVField(task.id),
escapeCSVField(task.name),
escapeCSVField(task.predecessor),
escapeCSVField(formatPredecessorDisplay(task.predecessor)),
escapeCSVField(task.assignee),
escapeCSVField(task.startDate),
escapeCSVField(task.endDate),
@@ -1181,12 +1201,6 @@ watch(
</div>
<div class="gantt-panel gantt-panel-right" :class="{ 'full-width': !isTaskListVisible }">
<!-- 左侧渐隐效果覆盖层 -->
<div class="timeline-fade-overlay timeline-fade-left"></div>
<!-- 右侧渐隐效果覆盖层 -->
<div class="timeline-fade-overlay timeline-fade-right"></div>
<Timeline
ref="timelineRef"
:tasks="tasksForTimeline"
@@ -1204,38 +1218,6 @@ watch(
</div>
</template>
<!-- 独立的无scoped样式块处理暗色主题渐隐效果 -->
<style>
/* 暗色主题下的渐隐效果 */
html[data-theme='dark'] .timeline-fade-left {
background: linear-gradient(
to right,
var(--gantt-bg-primary, rgb(35, 35, 35)) 0%,
rgba(35, 35, 35, 0.95) 0%,
rgba(35, 35, 35, 0.85) 20%,
rgba(35, 35, 35, 0.7) 35%,
rgba(35, 35, 35, 0.5) 50%,
rgba(35, 35, 35, 0.3) 70%,
rgba(35, 35, 35, 0.15) 85%,
transparent 100%
) !important;
}
html[data-theme='dark'] .timeline-fade-right {
background: linear-gradient(
to left,
var(--gantt-bg-primary, rgb(35, 35, 35)) 0%,
rgba(35, 35, 35, 0.95) 0%,
rgba(35, 35, 35, 0.85) 20%,
rgba(35, 35, 35, 0.7) 35%,
rgba(35, 35, 35, 0.5) 50%,
rgba(35, 35, 35, 0.3) 70%,
rgba(35, 35, 35, 0.15) 85%,
transparent 100%
) !important;
}
</style>
<style scoped>
@import '../styles/theme-variables.css';
.gantt-root {
@@ -1308,55 +1290,6 @@ html[data-theme='dark'] .timeline-fade-right {
font-size: 18px;
}
/* Timeline区域左右两侧渐隐覆盖层 */
.timeline-fade-overlay {
position: absolute;
top: 0;
bottom: 0;
width: 120px;
pointer-events: none;
z-index: 100;
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);
opacity: 0.8;
}
/* 左侧渐隐效果 - 增强版 */
.timeline-fade-left {
left: 0;
background: linear-gradient(
to right,
var(--gantt-bg-primary, #ffffff) 0%,
rgba(255, 255, 255, 0.9) 15%,
rgba(255, 255, 255, 0.7) 30%,
rgba(255, 255, 255, 0.5) 50%,
rgba(255, 255, 255, 0.3) 70%,
rgba(255, 255, 255, 0.1) 85%,
transparent 100%
);
}
/* 右侧渐隐效果 - 增强版 */
.timeline-fade-right {
right: 0;
background: linear-gradient(
to left,
var(--gantt-bg-primary, #ffffff) 0%,
rgba(255, 255, 255, 0.9) 15%,
rgba(255, 255, 255, 0.7) 30%,
rgba(255, 255, 255, 0.5) 50%,
rgba(255, 255, 255, 0.3) 70%,
rgba(255, 255, 255, 0.1) 85%,
transparent 100%
);
}
/* 响应式调整 */
@media (max-width: 768px) {
.timeline-fade-overlay {
width: 60px;
}
}
/* 左侧撞击动画 */
@keyframes slideLeftImpact {
0% {