Merge - merge updates from gitmigor fork
This commit is contained in:
61
docs/GITHUB-PAGES-EN.md
Normal file
61
docs/GITHUB-PAGES-EN.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# GitHub Pages Deployment Guide
|
||||||
|
|
||||||
|
This project has been configured with automatic deployment of GitHub Pages, and users can experience the complete Gantt charting function online.
|
||||||
|
|
||||||
|
## 🌐 Online visit
|
||||||
|
|
||||||
|
**Demo Address**: https://nelson820125.github.io/jordium-gantt-vue3/
|
||||||
|
|
||||||
|
## 🔧 Deployment Configuration
|
||||||
|
|
||||||
|
### Automated deployment
|
||||||
|
|
||||||
|
Projects are automatically deployed to GitHub Pages using GitHub Actions:
|
||||||
|
|
||||||
|
- **Triggering condition**: Push to `main` or `master` branch
|
||||||
|
- **Build Command**: `npm run build:pages`
|
||||||
|
- **Deployment Directory**: `./dist`
|
||||||
|
- **Workflows**: `.github/workflows/deploy-github-pages.yml`
|
||||||
|
|
||||||
|
### Enable GitHub Pages manually
|
||||||
|
|
||||||
|
1. Enter the GitHub repository settings page
|
||||||
|
2. Find the "Pages" setting options
|
||||||
|
3. Select "Source" as "GitHub Actions"
|
||||||
|
4. Push code to the main branch and automatically trigger deployment
|
||||||
|
|
||||||
|
## 📁 Construct the product
|
||||||
|
|
||||||
|
- **Development and Construction**: `npm run build` → `dist/`
|
||||||
|
- **GitHub Pages**: `npm run build:pages` → `dist/` (contains the correct base path)
|
||||||
|
- **NPM package build**: `npm run build:lib` → `npm-package/dist/`
|
||||||
|
|
||||||
|
## 🛠️ Local Preview
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Installation dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Start the development server
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Build and preview the production version
|
||||||
|
npm run build:pages
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 Update deployment
|
||||||
|
|
||||||
|
GitHub Actions will automatically:
|
||||||
|
|
||||||
|
1. Check out the code
|
||||||
|
2. Install Node.js and dependencies
|
||||||
|
3. Build demo application
|
||||||
|
4. Deploy to GitHub Pages
|
||||||
|
|
||||||
|
## 📝 Notes
|
||||||
|
|
||||||
|
- Deployment usually takes 1-5 minutes to take effect
|
||||||
|
- Make sure GitHub Pages is enabled in repository settings
|
||||||
|
- Custom domain names need to be configured in the `demo/public/CNAME` file
|
||||||
|
- Static resource paths use relative paths to ensure normal loading in the Pages environment
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
||||||
|
import { useI18n } from '../composables/useI18n'
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
modelValue?: string | [string, string]
|
modelValue?: string | [string, string]
|
||||||
@@ -97,7 +99,7 @@ watch(
|
|||||||
singleValue.value = (newValue as string) || ''
|
singleValue.value = (newValue as string) || ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
// 处理单日期输入变化(预留,当前版本不使用)
|
// 处理单日期输入变化(预留,当前版本不使用)
|
||||||
@@ -464,6 +466,7 @@ const yearList = computed(() => {
|
|||||||
return years
|
return years
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
// 月份名称
|
// 月份名称
|
||||||
const monthNames = [
|
const monthNames = [
|
||||||
'一月',
|
'一月',
|
||||||
@@ -480,6 +483,7 @@ const monthNames = [
|
|||||||
'十二月',
|
'十二月',
|
||||||
]
|
]
|
||||||
const weekDays = ['日', '一', '二', '三', '四', '五', '六']
|
const weekDays = ['日', '一', '二', '三', '四', '五', '六']
|
||||||
|
*/
|
||||||
|
|
||||||
// 生命周期
|
// 生命周期
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -736,7 +740,7 @@ const panelStyle = computed(() => {
|
|||||||
<<
|
<<
|
||||||
</button>
|
</button>
|
||||||
<span class="el-month-picker__header-label" @click="showYearSelector($event)">
|
<span class="el-month-picker__header-label" @click="showYearSelector($event)">
|
||||||
{{ currentYear }}年
|
{{ currentYear }}
|
||||||
</span>
|
</span>
|
||||||
<button type="button" class="el-picker-panel__icon-btn" @click="nextYear">
|
<button type="button" class="el-picker-panel__icon-btn" @click="nextYear">
|
||||||
>>
|
>>
|
||||||
@@ -744,7 +748,7 @@ const panelStyle = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
<div class="el-month-picker__content">
|
<div class="el-month-picker__content">
|
||||||
<div
|
<div
|
||||||
v-for="(monthName, index) in monthNames"
|
v-for="(monthName, index) in t.monthNames"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="el-month-picker__item"
|
class="el-month-picker__item"
|
||||||
:class="{ 'is-current': index === currentMonth }"
|
:class="{ 'is-current': index === currentMonth }"
|
||||||
@@ -766,10 +770,10 @@ const panelStyle = computed(() => {
|
|||||||
</button>
|
</button>
|
||||||
<span class="el-date-picker__header-label">
|
<span class="el-date-picker__header-label">
|
||||||
<span class="el-date-picker__header-year" @click="showYearSelector($event)">
|
<span class="el-date-picker__header-year" @click="showYearSelector($event)">
|
||||||
{{ currentYear }}年
|
{{ currentYear }}
|
||||||
</span>
|
</span>
|
||||||
<span class="el-date-picker__header-month" @click="showMonthSelector($event)">
|
<span class="el-date-picker__header-month" @click="showMonthSelector($event)">
|
||||||
{{ monthNames[currentMonth] }}
|
{{ t.monthNames[currentMonth] }}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<button type="button" class="el-picker-panel__icon-btn" @click="nextMonth">
|
<button type="button" class="el-picker-panel__icon-btn" @click="nextMonth">
|
||||||
@@ -783,7 +787,7 @@ const panelStyle = computed(() => {
|
|||||||
<div class="el-date-picker__content">
|
<div class="el-date-picker__content">
|
||||||
<!-- 星期标题 -->
|
<!-- 星期标题 -->
|
||||||
<div class="el-date-table__header">
|
<div class="el-date-table__header">
|
||||||
<div v-for="day in weekDays" :key="day" class="el-date-table__header-cell">
|
<div v-for="day in t.weekDays" :key="day" class="el-date-table__header-cell">
|
||||||
{{ day }}
|
{{ day }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
import { computed, ref, onUnmounted } from 'vue'
|
import { computed, ref, onUnmounted } from 'vue'
|
||||||
import type { Milestone } from '../models/classes/Milestone'
|
import type { Milestone } from '../models/classes/Milestone'
|
||||||
import { TimelineScale } from '../models/types/TimelineScale'
|
import { TimelineScale } from '../models/types/TimelineScale'
|
||||||
|
import { useI18n } from '../composables/useI18n'
|
||||||
|
const { getTranslation } = useI18n()
|
||||||
|
|
||||||
|
const t = (key: string): string => {
|
||||||
|
return getTranslation(key)
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
date: string // 里程碑日期
|
date: string // 里程碑日期
|
||||||
@@ -151,7 +157,7 @@ const handleMouseMove = (e: MouseEvent) => {
|
|||||||
mouseX: e.clientX,
|
mouseX: e.clientX,
|
||||||
isDragging: isDragging.value,
|
isDragging: isDragging.value,
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
const deltaX = e.clientX - dragStartX.value
|
const deltaX = e.clientX - dragStartX.value
|
||||||
@@ -178,7 +184,7 @@ const handleMouseUp = () => {
|
|||||||
mouseX: 0,
|
mouseX: 0,
|
||||||
isDragging: false,
|
isDragging: false,
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
// 只有在真正拖拽了(有临时数据)且状态为拖拽中时才触发更新
|
// 只有在真正拖拽了(有临时数据)且状态为拖拽中时才触发更新
|
||||||
@@ -240,7 +246,7 @@ const handleMilestoneClick = (e: MouseEvent) => {
|
|||||||
scrollLeft: targetScrollLeft,
|
scrollLeft: targetScrollLeft,
|
||||||
smooth: true,
|
smooth: true,
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,13 +280,13 @@ const milestoneStyle = computed(() => {
|
|||||||
const centerPosition = calculateMilestonePositionFromTimelineData(
|
const centerPosition = calculateMilestonePositionFromTimelineData(
|
||||||
milestoneDate,
|
milestoneDate,
|
||||||
props.timelineData,
|
props.timelineData,
|
||||||
props.currentTimeScale,
|
props.currentTimeScale
|
||||||
)
|
)
|
||||||
left = centerPosition - size / 2 // 从中心位置偏移到图标左上角
|
left = centerPosition - size / 2 // 从中心位置偏移到图标左上角
|
||||||
} else {
|
} else {
|
||||||
// 日视图:保持原有逻辑
|
// 日视图:保持原有逻辑
|
||||||
const startDiff = Math.floor(
|
const startDiff = Math.floor(
|
||||||
(milestoneDate.getTime() - props.startDate.getTime()) / (1000 * 60 * 60 * 24),
|
(milestoneDate.getTime() - props.startDate.getTime()) / (1000 * 60 * 60 * 24)
|
||||||
)
|
)
|
||||||
left = startDiff * props.dayWidth + props.dayWidth / 2 - size / 2
|
left = startDiff * props.dayWidth + props.dayWidth / 2 - size / 2
|
||||||
}
|
}
|
||||||
@@ -346,7 +352,7 @@ const milestoneVisibility = computed(() => {
|
|||||||
if (iconRight <= leftBoundary + iconSize / 2) {
|
if (iconRight <= leftBoundary + iconSize / 2) {
|
||||||
// 检查左侧是否有其他停靠的里程碑,需要判断推挤优先级
|
// 检查左侧是否有其他停靠的里程碑,需要判断推挤优先级
|
||||||
const leftStickyMilestones = otherMilestones.filter(
|
const leftStickyMilestones = otherMilestones.filter(
|
||||||
m => m.id !== currentId && m.stickyPosition === 'left' && m.isSticky,
|
m => m.id !== currentId && m.stickyPosition === 'left' && m.isSticky
|
||||||
)
|
)
|
||||||
|
|
||||||
// 如果有其他里程碑已经停靠在左侧,比较优先级决定推挤顺序
|
// 如果有其他里程碑已经停靠在左侧,比较优先级决定推挤顺序
|
||||||
@@ -392,7 +398,7 @@ const milestoneVisibility = computed(() => {
|
|||||||
if (iconLeft >= rightBoundary - iconSize / 2) {
|
if (iconLeft >= rightBoundary - iconSize / 2) {
|
||||||
// 检查右侧是否有其他停靠的里程碑,需要判断推挤优先级
|
// 检查右侧是否有其他停靠的里程碑,需要判断推挤优先级
|
||||||
const rightStickyMilestones = otherMilestones.filter(
|
const rightStickyMilestones = otherMilestones.filter(
|
||||||
m => m.id !== currentId && m.stickyPosition === 'right' && m.isSticky,
|
m => m.id !== currentId && m.stickyPosition === 'right' && m.isSticky
|
||||||
)
|
)
|
||||||
|
|
||||||
// 如果有其他里程碑已经停靠在右侧,比较优先级决定推挤顺序
|
// 如果有其他里程碑已经停靠在右侧,比较优先级决定推挤顺序
|
||||||
@@ -478,26 +484,26 @@ const handleMilestoneMouseLeave = () => {
|
|||||||
|
|
||||||
// 格式化日期显示
|
// 格式化日期显示
|
||||||
const formatDisplayDate = (dateStr: string): string => {
|
const formatDisplayDate = (dateStr: string): string => {
|
||||||
if (!dateStr) return '未设置'
|
if (!dateStr) return t('dateNotSet') //Not Set
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const date = new Date(dateStr)
|
const date = new Date(dateStr)
|
||||||
if (isNaN(date.getTime())) return '未设置'
|
if (isNaN(date.getTime())) return t('dateNotSet')
|
||||||
|
|
||||||
const year = date.getFullYear()
|
const year = date.getFullYear()
|
||||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
const day = String(date.getDate()).padStart(2, '0')
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
return `${year}-${month}-${day}`
|
return `${year}-${month}-${day}`
|
||||||
} catch {
|
} catch {
|
||||||
return '未设置'
|
return t('dateNotSet')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tooltip内容
|
// Tooltip内容
|
||||||
const tooltipContent = computed(() => {
|
const tooltipContent = computed(() => {
|
||||||
const milestoneName = props.name || props.milestone?.name || '里程碑'
|
const milestoneName = props.name || props.milestone?.name || t('milestone')
|
||||||
const targetDate = formatDisplayDate(props.date || props.milestone?.startDate || '')
|
const targetDate = formatDisplayDate(props.date || props.milestone?.startDate || '')
|
||||||
return `里程碑:${milestoneName} - 目标日期:${targetDate}`
|
return `${t('milestone')}:${milestoneName} <br> ${t('targetDate')}:${targetDate}`
|
||||||
})
|
})
|
||||||
|
|
||||||
// 组件销毁时清理事件监听器
|
// 组件销毁时清理事件监听器
|
||||||
@@ -527,7 +533,7 @@ const calculateMilestonePositionFromTimelineData = (
|
|||||||
subDays: Array<{ date: Date; dayOfWeek?: number }>
|
subDays: Array<{ date: Date; dayOfWeek?: number }>
|
||||||
}>
|
}>
|
||||||
}>,
|
}>,
|
||||||
timeScale: TimelineScale,
|
timeScale: TimelineScale
|
||||||
) => {
|
) => {
|
||||||
let cumulativePosition = 0
|
let cumulativePosition = 0
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import type { Task } from '../models/classes/Task'
|
|||||||
import { TimelineScale } from '../models/types/TimelineScale'
|
import { TimelineScale } from '../models/types/TimelineScale'
|
||||||
import TaskContextMenu from './TaskContextMenu.vue'
|
import TaskContextMenu from './TaskContextMenu.vue'
|
||||||
|
|
||||||
|
import { useI18n } from '../composables/useI18n'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
task: Task
|
task: Task
|
||||||
rowHeight: number
|
rowHeight: number
|
||||||
@@ -31,6 +33,11 @@ interface Props {
|
|||||||
|
|
||||||
const props = defineProps<Props>()
|
const props = defineProps<Props>()
|
||||||
|
|
||||||
|
const { getTranslation } = useI18n()
|
||||||
|
const t = (key: string): string => {
|
||||||
|
return getTranslation(key)
|
||||||
|
}
|
||||||
|
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
'update:task',
|
'update:task',
|
||||||
'bar-mounted',
|
'bar-mounted',
|
||||||
@@ -833,9 +840,9 @@ const handleBubbleMouseDown = (event: MouseEvent) => {
|
|||||||
|
|
||||||
// 格式化日期显示
|
// 格式化日期显示
|
||||||
const formatDisplayDate = (dateStr: string | undefined): string => {
|
const formatDisplayDate = (dateStr: string | undefined): string => {
|
||||||
if (!dateStr) return '未设置'
|
if (!dateStr) return t('dateNotSet')
|
||||||
const date = createLocalDate(dateStr)
|
const date = createLocalDate(dateStr)
|
||||||
if (!date) return '未设置'
|
if (!date) return t('dateNotSet')
|
||||||
|
|
||||||
const year = date.getFullYear()
|
const year = date.getFullYear()
|
||||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
@@ -1120,23 +1127,23 @@ onUnmounted(() => {
|
|||||||
<div class="tooltip-title">{{ task.name }}</div>
|
<div class="tooltip-title">{{ task.name }}</div>
|
||||||
<div class="tooltip-content">
|
<div class="tooltip-content">
|
||||||
<div class="tooltip-row">
|
<div class="tooltip-row">
|
||||||
<span class="tooltip-label">计划开始:</span>
|
<span class="tooltip-label"> {{ t('startDate') }}:</span>
|
||||||
<span class="tooltip-value">{{ formatDisplayDate(task.startDate) }}</span>
|
<span class="tooltip-value">{{ formatDisplayDate(task.startDate) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tooltip-row">
|
<div class="tooltip-row">
|
||||||
<span class="tooltip-label">计划结束:</span>
|
<span class="tooltip-label">{{ t('endDate') }}:</span>
|
||||||
<span class="tooltip-value">{{ formatDisplayDate(task.endDate) }}</span>
|
<span class="tooltip-value">{{ formatDisplayDate(task.endDate) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tooltip-row">
|
<div class="tooltip-row">
|
||||||
<span class="tooltip-label">计划工时:</span>
|
<span class="tooltip-label">{{ t('estimatedHours') }}:</span>
|
||||||
<span class="tooltip-value">{{ workHourInfo.total }}h</span>
|
<span class="tooltip-value">{{ workHourInfo.total }}h</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tooltip-row">
|
<div class="tooltip-row">
|
||||||
<span class="tooltip-label">已用工时:</span>
|
<span class="tooltip-label"> {{ t('actualHours') }}:</span>
|
||||||
<span class="tooltip-value">{{ workHourInfo.used }}h</span>
|
<span class="tooltip-value">{{ workHourInfo.used }}h</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="tooltip-row">
|
<div class="tooltip-row">
|
||||||
<span class="tooltip-label">完成率:</span>
|
<span class="tooltip-label"> {{ t('progress') }}:</span>
|
||||||
<span class="tooltip-value">{{ task.progress || 0 }}%</span>
|
<span class="tooltip-value">{{ task.progress || 0 }}%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ const computeAllMilestonesPositions = () => {
|
|||||||
if (!isNaN(milestoneDate.getTime())) {
|
if (!isNaN(milestoneDate.getTime())) {
|
||||||
const startDiff = Math.floor(
|
const startDiff = Math.floor(
|
||||||
(milestoneDate.getTime() - timelineConfig.value.startDate.getTime()) /
|
(milestoneDate.getTime() - timelineConfig.value.startDate.getTime()) /
|
||||||
(1000 * 60 * 60 * 24),
|
(1000 * 60 * 60 * 24)
|
||||||
)
|
)
|
||||||
const left = startDiff * 30 + 30 / 2 - 12 // 30是dayWidth,12是图标半径
|
const left = startDiff * 30 + 30 / 2 - 12 // 30是dayWidth,12是图标半径
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ const computeAllMilestonesPositions = () => {
|
|||||||
if (!isNaN(milestoneDate.getTime())) {
|
if (!isNaN(milestoneDate.getTime())) {
|
||||||
const startDiff = Math.floor(
|
const startDiff = Math.floor(
|
||||||
(milestoneDate.getTime() - timelineConfig.value.startDate.getTime()) /
|
(milestoneDate.getTime() - timelineConfig.value.startDate.getTime()) /
|
||||||
(1000 * 60 * 60 * 24),
|
(1000 * 60 * 60 * 24)
|
||||||
)
|
)
|
||||||
const left = startDiff * 30 + 30 / 2 - 12
|
const left = startDiff * 30 + 30 / 2 - 12
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ const handleTaskRowHover = (taskId: number | null) => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('timeline-task-hover', {
|
new CustomEvent('timeline-task-hover', {
|
||||||
detail: taskId,
|
detail: taskId,
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ const handleMilestoneIconChange = (milestoneId: number, icon: string) => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('milestone-icon-changed', {
|
new CustomEvent('milestone-icon-changed', {
|
||||||
detail: { milestoneId, icon },
|
detail: { milestoneId, icon },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +442,7 @@ const handleMilestoneSave = (updatedMilestone: Milestone) => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('milestone-data-updated', {
|
new CustomEvent('milestone-data-updated', {
|
||||||
detail: { milestone: updatedMilestone },
|
detail: { milestone: updatedMilestone },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,14 +455,14 @@ const handleMilestoneDelete = (milestoneId: number) => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('milestone-deleted', {
|
new CustomEvent('milestone-deleted', {
|
||||||
detail: { milestoneId },
|
detail: { milestoneId },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
// 广播里程碑数据变化事件,确保Timeline重新渲染
|
// 广播里程碑数据变化事件,确保Timeline重新渲染
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('milestone-data-changed', {
|
new CustomEvent('milestone-data-changed', {
|
||||||
detail: { milestoneId },
|
detail: { milestoneId },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +477,7 @@ const handleMilestoneUpdate = (updatedMilestone: Milestone) => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('milestone-data-updated', {
|
new CustomEvent('milestone-data-updated', {
|
||||||
detail: { milestone: updatedMilestone },
|
detail: { milestone: updatedMilestone },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,7 +683,7 @@ watch(
|
|||||||
if (!isUpdatingTimelineConfig) {
|
if (!isUpdatingTimelineConfig) {
|
||||||
timelineData.value = generateTimelineData()
|
timelineData.value = generateTimelineData()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 保证每次时间轴数据变化后都自动居中今日(仅初始化和外部props变更时触发,不因任务/里程碑变更触发)
|
// 保证每次时间轴数据变化后都自动居中今日(仅初始化和外部props变更时触发,不因任务/里程碑变更触发)
|
||||||
@@ -698,7 +698,7 @@ watch(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
// 将今日定位到时间线中间位置
|
// 将今日定位到时间线中间位置
|
||||||
@@ -715,7 +715,7 @@ const scrollToTodayCenter = (retry = 0) => {
|
|||||||
const startNormalized = new Date(
|
const startNormalized = new Date(
|
||||||
timelineStart.getFullYear(),
|
timelineStart.getFullYear(),
|
||||||
timelineStart.getMonth(),
|
timelineStart.getMonth(),
|
||||||
timelineStart.getDate(),
|
timelineStart.getDate()
|
||||||
)
|
)
|
||||||
|
|
||||||
// 计算今天距离时间线开始日期的天数
|
// 计算今天距离时间线开始日期的天数
|
||||||
@@ -806,7 +806,7 @@ const scrollToToday = () => {
|
|||||||
const startNormalized = new Date(
|
const startNormalized = new Date(
|
||||||
timelineStart.getFullYear(),
|
timelineStart.getFullYear(),
|
||||||
timelineStart.getMonth(),
|
timelineStart.getMonth(),
|
||||||
timelineStart.getDate(),
|
timelineStart.getDate()
|
||||||
)
|
)
|
||||||
|
|
||||||
// 计算今天距离时间线开始日期的天数
|
// 计算今天距离时间线开始日期的天数
|
||||||
@@ -857,7 +857,7 @@ const updateTask = (updatedTask: Task) => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('task-updated', {
|
new CustomEvent('task-updated', {
|
||||||
detail: updatedTask,
|
detail: updatedTask,
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -917,7 +917,7 @@ const handleTaskBarContextMenu = (event: { task: Task; position: { x: number; y:
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('context-menu', {
|
new CustomEvent('context-menu', {
|
||||||
detail: event,
|
detail: event,
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1000,7 +1000,7 @@ onMounted(() => {
|
|||||||
// 监听TaskList的垂直滚动事件
|
// 监听TaskList的垂直滚动事件
|
||||||
window.addEventListener(
|
window.addEventListener(
|
||||||
'task-list-vertical-scroll',
|
'task-list-vertical-scroll',
|
||||||
handleTaskListVerticalScroll as EventListener,
|
handleTaskListVerticalScroll as EventListener
|
||||||
)
|
)
|
||||||
// 监听语言变化
|
// 监听语言变化
|
||||||
window.addEventListener('locale-changed', handleLocaleChange as EventListener)
|
window.addEventListener('locale-changed', handleLocaleChange as EventListener)
|
||||||
@@ -1010,7 +1010,7 @@ onMounted(() => {
|
|||||||
// 监听Timeline容器resize事件(TaskList切换等)
|
// 监听Timeline容器resize事件(TaskList切换等)
|
||||||
window.addEventListener(
|
window.addEventListener(
|
||||||
'timeline-container-resized',
|
'timeline-container-resized',
|
||||||
handleTimelineContainerResized as EventListener,
|
handleTimelineContainerResized as EventListener
|
||||||
)
|
)
|
||||||
|
|
||||||
// 监听里程碑点击定位事件
|
// 监听里程碑点击定位事件
|
||||||
@@ -1100,7 +1100,7 @@ const handleTimelineBodyScroll = (event: Event) => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('timeline-vertical-scroll', {
|
new CustomEvent('timeline-vertical-scroll', {
|
||||||
detail: { scrollTop },
|
detail: { scrollTop },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1113,7 +1113,7 @@ watch(
|
|||||||
updateSvgSize()
|
updateSvgSize()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
// 拖拽滑动相关状态
|
// 拖拽滑动相关状态
|
||||||
@@ -1281,7 +1281,7 @@ const startAutoScroll = (direction: 'left' | 'right') => {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('timeline-auto-scroll', {
|
new CustomEvent('timeline-auto-scroll', {
|
||||||
detail: { scrollDelta: newScrollLeft - currentScrollLeft },
|
detail: { scrollDelta: newScrollLeft - currentScrollLeft },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
autoScrollTimer = window.setTimeout(scroll, 16) // 约60fps
|
autoScrollTimer = window.setTimeout(scroll, 16) // 约60fps
|
||||||
@@ -1335,14 +1335,14 @@ onUnmounted(() => {
|
|||||||
window.removeEventListener('task-list-hover', handleTaskListHover as EventListener)
|
window.removeEventListener('task-list-hover', handleTaskListHover as EventListener)
|
||||||
window.removeEventListener(
|
window.removeEventListener(
|
||||||
'task-list-vertical-scroll',
|
'task-list-vertical-scroll',
|
||||||
handleTaskListVerticalScroll as EventListener,
|
handleTaskListVerticalScroll as EventListener
|
||||||
)
|
)
|
||||||
window.removeEventListener('locale-changed', handleLocaleChange as EventListener)
|
window.removeEventListener('locale-changed', handleLocaleChange as EventListener)
|
||||||
window.removeEventListener('splitter-drag-start', handleSplitterDragStart as EventListener)
|
window.removeEventListener('splitter-drag-start', handleSplitterDragStart as EventListener)
|
||||||
window.removeEventListener('splitter-drag-end', handleSplitterDragEnd as EventListener)
|
window.removeEventListener('splitter-drag-end', handleSplitterDragEnd as EventListener)
|
||||||
window.removeEventListener(
|
window.removeEventListener(
|
||||||
'timeline-container-resized',
|
'timeline-container-resized',
|
||||||
handleTimelineContainerResized as EventListener,
|
handleTimelineContainerResized as EventListener
|
||||||
)
|
)
|
||||||
window.removeEventListener('milestone-click-locate', handleMilestoneClickLocate as EventListener)
|
window.removeEventListener('milestone-click-locate', handleMilestoneClickLocate as EventListener)
|
||||||
window.removeEventListener('drag-boundary-check', handleDragBoundaryCheck as EventListener)
|
window.removeEventListener('drag-boundary-check', handleDragBoundaryCheck as EventListener)
|
||||||
@@ -1436,7 +1436,7 @@ watch(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{ deep: true },
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
// 处理里程碑点击定位事件
|
// 处理里程碑点击定位事件
|
||||||
@@ -1620,7 +1620,7 @@ const handleAddSuccessor = (task: Task) => {
|
|||||||
class="timeline-year"
|
class="timeline-year"
|
||||||
:style="{ width: '719px' }"
|
:style="{ width: '719px' }"
|
||||||
>
|
>
|
||||||
<div class="year-label">{{ yearValue }}年</div>
|
<div class="year-label">{{ yearValue }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export type Locale = 'zh-CN' | 'en-US'
|
|||||||
// 多语言配置
|
// 多语言配置
|
||||||
const messages = {
|
const messages = {
|
||||||
'zh-CN': {
|
'zh-CN': {
|
||||||
|
dateNotSet: '未设置',
|
||||||
// TaskList Header
|
// TaskList Header
|
||||||
taskName: '任务名称',
|
taskName: '任务名称',
|
||||||
predecessor: '前置任务',
|
predecessor: '前置任务',
|
||||||
@@ -38,8 +39,26 @@ const messages = {
|
|||||||
// 月份格式
|
// 月份格式
|
||||||
monthFormat: (month: number) => `${month}月`,
|
monthFormat: (month: number) => `${month}月`,
|
||||||
|
|
||||||
|
// 月份名称
|
||||||
|
monthNames: [
|
||||||
|
'一月',
|
||||||
|
'二月',
|
||||||
|
'三月',
|
||||||
|
'四月',
|
||||||
|
'五月',
|
||||||
|
'六月',
|
||||||
|
'七月',
|
||||||
|
'八月',
|
||||||
|
'九月',
|
||||||
|
'十月',
|
||||||
|
'十一月',
|
||||||
|
'十二月',
|
||||||
|
],
|
||||||
|
weekDays: ['日', '一', '二', '三', '四', '五', '六'],
|
||||||
|
|
||||||
// 其他
|
// 其他
|
||||||
milestone: '里程碑',
|
milestone: '里程碑',
|
||||||
|
targetDate: '目标日期',
|
||||||
today: '今天',
|
today: '今天',
|
||||||
// 里程碑对话框
|
// 里程碑对话框
|
||||||
milestoneDetails: '里程碑详情',
|
milestoneDetails: '里程碑详情',
|
||||||
@@ -169,6 +188,7 @@ const messages = {
|
|||||||
timerConfirmPlaceholder: '请输入计时说明',
|
timerConfirmPlaceholder: '请输入计时说明',
|
||||||
},
|
},
|
||||||
'en-US': {
|
'en-US': {
|
||||||
|
dateNotSet: 'Not set',
|
||||||
// TaskList Header
|
// TaskList Header
|
||||||
taskName: 'Task Name',
|
taskName: 'Task Name',
|
||||||
predecessor: 'Predecessor',
|
predecessor: 'Predecessor',
|
||||||
@@ -199,9 +219,27 @@ const messages = {
|
|||||||
// 月份格式
|
// 月份格式
|
||||||
monthFormat: (month: number) => `M${String(month).padStart(2, '0')}`,
|
monthFormat: (month: number) => `M${String(month).padStart(2, '0')}`,
|
||||||
|
|
||||||
|
// Month name
|
||||||
|
monthNames: [
|
||||||
|
'Jan',
|
||||||
|
'Feb',
|
||||||
|
'Mar',
|
||||||
|
'Apr',
|
||||||
|
'May',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Aug',
|
||||||
|
'Sep',
|
||||||
|
'Oct',
|
||||||
|
'Nov',
|
||||||
|
'Dec',
|
||||||
|
],
|
||||||
|
weekDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
||||||
|
|
||||||
// 其他
|
// 其他
|
||||||
milestone: 'Milestone',
|
milestone: 'Milestone',
|
||||||
today: 'Today',
|
today: 'Today',
|
||||||
|
targetDate: 'Target Date',
|
||||||
// 里程碑对话框
|
// 里程碑对话框
|
||||||
milestoneDetails: 'Milestone Details',
|
milestoneDetails: 'Milestone Details',
|
||||||
milestoneName: 'Milestone Name',
|
milestoneName: 'Milestone Name',
|
||||||
@@ -387,7 +425,7 @@ export function useI18n() {
|
|||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('locale-changed', {
|
new CustomEvent('locale-changed', {
|
||||||
detail: { locale },
|
detail: { locale },
|
||||||
}),
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user