Merge - merge updates from gitmigor fork

This commit is contained in:
LINING-PC\lining
2025-08-12 22:38:30 +08:00
parent 63f03ec9d8
commit 221f20e322
6 changed files with 166 additions and 50 deletions

61
docs/GITHUB-PAGES-EN.md Normal file
View 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

View File

@@ -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(() => {
&lt;&lt; &lt;&lt;
</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">
&gt;&gt; &gt;&gt;
@@ -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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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是dayWidth12是图标半径 const left = startDiff * 30 + 30 / 2 - 12 // 30是dayWidth12是图标半径
@@ -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>

View File

@@ -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 },
}), })
) )
} }