Merge branch 'develop' into pages
This commit is contained in:
@@ -2130,6 +2130,8 @@ The GanttChart component exposes a series of methods through `defineExpose`, all
|
|||||||
| `setTheme` <sup class="version-badge">1.7.1</sup> | `mode: 'light' \| 'dark'` | `void` | Set theme mode |
|
| `setTheme` <sup class="version-badge">1.7.1</sup> | `mode: 'light' \| 'dark'` | `void` | Set theme mode |
|
||||||
| `currentTheme` <sup class="version-badge">1.7.1</sup> | - | `'light' \| 'dark'` | Get current theme mode |
|
| `currentTheme` <sup class="version-badge">1.7.1</sup> | - | `'light' \| 'dark'` | Get current theme mode |
|
||||||
| `setTimeScale` <sup class="version-badge">1.7.1</sup> | `scale: TimelineScale` | `void` | Set time scale (`'hour' \| 'day' \| 'week' \| 'month' \| 'quarter' \| 'year'`) |
|
| `setTimeScale` <sup class="version-badge">1.7.1</sup> | `scale: TimelineScale` | `void` | Set time scale (`'hour' \| 'day' \| 'week' \| 'month' \| 'quarter' \| 'year'`) |
|
||||||
|
| `zoomIn` <sup class="version-badge">1.7.1</sup> | - | `void` | zoom in time scale(`'year' -> 'quarter' -> 'month' -> 'week' -> 'day' -> 'hour'`) |
|
||||||
|
| `zoomOut` <sup class="version-badge">1.7.1</sup> | - | `void` | zoom out time scale(`'hour' -> 'day' -> 'week' -> 'month' -> 'quarter' -> 'year'`) |
|
||||||
| `currentScale` <sup class="version-badge">1.7.1</sup> | - | `TimelineScale` | Get current time scale |
|
| `currentScale` <sup class="version-badge">1.7.1</sup> | - | `TimelineScale` | Get current time scale |
|
||||||
| `toggleFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | Toggle fullscreen state |
|
| `toggleFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | Toggle fullscreen state |
|
||||||
| `enterFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | Enter fullscreen mode |
|
| `enterFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | Enter fullscreen mode |
|
||||||
|
|||||||
@@ -2121,6 +2121,8 @@ GanttChart 组件通过 `defineExpose` 暴露了一系列方法,允许父组
|
|||||||
| `setTheme` <sup class="version-badge">1.7.1</sup> | `mode: 'light' \| 'dark'` | `void` | 设置主题模式 |
|
| `setTheme` <sup class="version-badge">1.7.1</sup> | `mode: 'light' \| 'dark'` | `void` | 设置主题模式 |
|
||||||
| `currentTheme` <sup class="version-badge">1.7.1</sup> | - | `'light' \| 'dark'` | 获取当前主题模式 |
|
| `currentTheme` <sup class="version-badge">1.7.1</sup> | - | `'light' \| 'dark'` | 获取当前主题模式 |
|
||||||
| `setTimeScale` <sup class="version-badge">1.7.1</sup> | `scale: TimelineScale` | `void` | 设置时间刻度(`'hour' \| 'day' \| 'week' \| 'month' \| 'quarter' \| 'year'`) |
|
| `setTimeScale` <sup class="version-badge">1.7.1</sup> | `scale: TimelineScale` | `void` | 设置时间刻度(`'hour' \| 'day' \| 'week' \| 'month' \| 'quarter' \| 'year'`) |
|
||||||
|
| `zoomIn` <sup class="version-badge">1.7.1</sup> | - | `void` | 缩小时间刻度(`'year' -> 'quarter' -> 'month' -> 'week' -> 'day' -> 'hour'`) |
|
||||||
|
| `zoomOut` <sup class="version-badge">1.7.1</sup> | - | `void` | 放大时间刻度(`'hour' -> 'day' -> 'week' -> 'month' -> 'quarter' -> 'year'`) |
|
||||||
| `currentScale` <sup class="version-badge">1.7.1</sup> | - | `TimelineScale` | 获取当前时间刻度 |
|
| `currentScale` <sup class="version-badge">1.7.1</sup> | - | `TimelineScale` | 获取当前时间刻度 |
|
||||||
| `toggleFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | 切换全屏状态 |
|
| `toggleFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | 切换全屏状态 |
|
||||||
| `enterFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | 进入全屏模式 |
|
| `enterFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | 进入全屏模式 |
|
||||||
|
|||||||
@@ -196,7 +196,6 @@ const handleCancel = () => {
|
|||||||
.btn-confirm:active {
|
.btn-confirm:active {
|
||||||
background: #3a8ee6;
|
background: #3a8ee6;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ref, computed, watch } from 'vue'
|
|||||||
import { GanttChart, TaskListColumn, useI18n, TaskListContextMenu, TaskBarContextMenu } from 'jordium-gantt-vue3'
|
import { GanttChart, TaskListColumn, useI18n, TaskListContextMenu, TaskBarContextMenu } from 'jordium-gantt-vue3'
|
||||||
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
|
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
|
||||||
|
|
||||||
const { t, getTranslation } = useI18n();
|
const { t, getTranslation } = useI18n()
|
||||||
|
|
||||||
// GanttChart ref
|
// GanttChart ref
|
||||||
const ganttRef = ref(null)
|
const ganttRef = ref(null)
|
||||||
@@ -114,7 +114,7 @@ const tasks = ref([
|
|||||||
department: '管理部',
|
department: '管理部',
|
||||||
departmentCode: 'D001',
|
departmentCode: 'D001',
|
||||||
type: 'task',
|
type: 'task',
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const milestones = ref([
|
const milestones = ref([
|
||||||
@@ -123,8 +123,8 @@ const milestones = ref([
|
|||||||
name: '项目立项',
|
name: '项目立项',
|
||||||
startDate: '2025-10-29',
|
startDate: '2025-10-29',
|
||||||
type: 'milestone',
|
type: 'milestone',
|
||||||
icon: 'diamond'
|
icon: 'diamond',
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const customMessages = {
|
const customMessages = {
|
||||||
@@ -139,7 +139,7 @@ const customMessages = {
|
|||||||
gantt: {
|
gantt: {
|
||||||
planStartDate: '计划开始时间',
|
planStartDate: '计划开始时间',
|
||||||
//planEndDate: '计划结束时间',
|
//planEndDate: '计划结束时间',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
'en-US': {
|
'en-US': {
|
||||||
department: 'Department',
|
department: 'Department',
|
||||||
@@ -152,16 +152,16 @@ const customMessages = {
|
|||||||
gantt: {
|
gantt: {
|
||||||
planStartDate: 'Plan Start Date',
|
planStartDate: 'Plan Start Date',
|
||||||
planEndDate: 'Plan End Date',
|
planEndDate: 'Plan End Date',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
// const tasks = ref([])
|
// const tasks = ref([])
|
||||||
|
|
||||||
// const milestones = ref([])
|
// const milestones = ref([])
|
||||||
|
|
||||||
const showAddTaskDrawer = ref(false);
|
const showAddTaskDrawer = ref(false)
|
||||||
const showAddMilestoneDialog = ref(false);
|
const showAddMilestoneDialog = ref(false)
|
||||||
const showTodayLocate = ref(true);
|
const showTodayLocate = ref(true)
|
||||||
|
|
||||||
// 定义可动态配置的列
|
// 定义可动态配置的列
|
||||||
const availableColumns = ref<TaskListColumnConfig[]>([
|
const availableColumns = ref<TaskListColumnConfig[]>([
|
||||||
@@ -186,7 +186,7 @@ const taskListConfig = {
|
|||||||
defaultWidth: '50%', // 默认展开宽度50%
|
defaultWidth: '50%', // 默认展开宽度50%
|
||||||
minWidth: '300px', // 最小宽度300px(默认280px)
|
minWidth: '300px', // 最小宽度300px(默认280px)
|
||||||
maxWidth: '1200px', // 最大宽度1200px(默认1160px)
|
maxWidth: '1200px', // 最大宽度1200px(默认1160px)
|
||||||
columns: availableColumns.value
|
columns: availableColumns.value,
|
||||||
}
|
}
|
||||||
|
|
||||||
// toolbar配置示例
|
// toolbar配置示例
|
||||||
@@ -201,18 +201,17 @@ const toolbarConfig: ToolbarConfig = {
|
|||||||
showFullscreen: true, // 显示全屏按钮
|
showFullscreen: true, // 显示全屏按钮
|
||||||
showTimeScale: true, // 显示时间刻度按钮组
|
showTimeScale: true, // 显示时间刻度按钮组
|
||||||
timeScaleDimensions: [ // 显示所有时间刻度维度
|
timeScaleDimensions: [ // 显示所有时间刻度维度
|
||||||
'hour', 'day', 'week', 'month', 'quarter', 'year'
|
'hour', 'day', 'week', 'month', 'quarter', 'year',
|
||||||
],
|
],
|
||||||
defaultTimeScale: 'week', // 默认选中周视图
|
defaultTimeScale: 'week', // 默认选中周视图
|
||||||
showExpandCollapse: false // 显示展开/折叠按钮
|
showExpandCollapse: false, // 显示展开/折叠按钮
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const newTask = ref({
|
const newTask = ref({
|
||||||
name: '',
|
name: '',
|
||||||
startDate: '',
|
startDate: '',
|
||||||
endDate: ''
|
endDate: '',
|
||||||
});
|
})
|
||||||
|
|
||||||
const addTask = () => {
|
const addTask = () => {
|
||||||
tasks.value.push({
|
tasks.value.push({
|
||||||
@@ -221,10 +220,10 @@ const addTask = () => {
|
|||||||
startDate: newTask.value.startDate,
|
startDate: newTask.value.startDate,
|
||||||
endDate: newTask.value.endDate,
|
endDate: newTask.value.endDate,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
});
|
})
|
||||||
newTask.value = { name: '', startDate: '', endDate: '' };
|
newTask.value = { name: '', startDate: '', endDate: '' }
|
||||||
showAddTaskDrawer.value = false;
|
showAddTaskDrawer.value = false
|
||||||
};
|
}
|
||||||
|
|
||||||
const addMilestone = () => {
|
const addMilestone = () => {
|
||||||
milestones.value.push({
|
milestones.value.push({
|
||||||
@@ -233,11 +232,11 @@ const addMilestone = () => {
|
|||||||
startDate: newTask.value.startDate,
|
startDate: newTask.value.startDate,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
type: 'milestone',
|
type: 'milestone',
|
||||||
icon: 'diamond'
|
icon: 'diamond',
|
||||||
});
|
})
|
||||||
console.log('milestones: ', milestones.value)
|
console.log('milestones: ', milestones.value)
|
||||||
newTask.value = { name: '', startDate: '', endDate: '' };
|
newTask.value = { name: '', startDate: '', endDate: '' }
|
||||||
showAddMilestoneDialog.value = false;
|
showAddMilestoneDialog.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const onTaskDblclick = (task) => {
|
const onTaskDblclick = (task) => {
|
||||||
@@ -294,18 +293,18 @@ const handleTaskRowMoved = async (payload: {
|
|||||||
// 此回调仅用于补充业务逻辑,例如根据assignee填充assigneeName等
|
// 此回调仅用于补充业务逻辑,例如根据assignee填充assigneeName等
|
||||||
const onTaskAdded = (res) => {
|
const onTaskAdded = (res) => {
|
||||||
// 组件已自动添加任务,这里只需要找到并更新额外字段
|
// 组件已自动添加任务,这里只需要找到并更新额外字段
|
||||||
const addedTask = tasks.value.find(t => t.id === res.task.id);
|
const addedTask = tasks.value.find(t => t.id === res.task.id)
|
||||||
|
|
||||||
if (addedTask && addedTask.assignee) {
|
if (addedTask && addedTask.assignee) {
|
||||||
// 根据assignee值查找对应的label并赋值给assigneeName
|
// 根据assignee值查找对应的label并赋值给assigneeName
|
||||||
const assigneeOption = assigneeOptions.value.find(option => option.value === addedTask.assignee);
|
const assigneeOption = assigneeOptions.value.find(option => option.value === addedTask.assignee)
|
||||||
if (assigneeOption) {
|
if (assigneeOption) {
|
||||||
addedTask.assigneeName = assigneeOption.label;
|
addedTask.assigneeName = assigneeOption.label
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 不需要手动push,组件已处理
|
// 不需要手动push,组件已处理
|
||||||
};
|
}
|
||||||
|
|
||||||
// 自定义右键菜单操作处理
|
// 自定义右键菜单操作处理
|
||||||
const handleCustomMenuAction = (action: string, task: Task, onClose: () => void) => {
|
const handleCustomMenuAction = (action: string, task: Task, onClose: () => void) => {
|
||||||
@@ -656,8 +655,8 @@ const handleCustomMenuAction = (action: string, task: Task, onClose: () => void)
|
|||||||
|
|
||||||
<!-- 自定义Dialog组件基于element plus -->
|
<!-- 自定义Dialog组件基于element plus -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="自定义添加里程碑组件 - Element Plus"
|
|
||||||
v-model="showAddMilestoneDialog"
|
v-model="showAddMilestoneDialog"
|
||||||
|
title="自定义添加里程碑组件 - Element Plus"
|
||||||
width="400px"
|
width="400px"
|
||||||
@close="newTask = { name: '', startDate: '', endDate: '' }"
|
@close="newTask = { name: '', startDate: '', endDate: '' }"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,3 +1,287 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, watch } from 'vue'
|
||||||
|
import { GanttChart, Task } from 'jordium-gantt-vue3'
|
||||||
|
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
|
||||||
|
|
||||||
|
// GanttChart ref
|
||||||
|
const ganttRef = ref(null)
|
||||||
|
|
||||||
|
// 控制模式:'expose' 使用expose方法,'props' 使用Props
|
||||||
|
const controlMode = ref<'expose' | 'props'>('expose')
|
||||||
|
|
||||||
|
// 状态变量
|
||||||
|
const fullscreenStatus = ref(false)
|
||||||
|
const expandStatus = ref(false)
|
||||||
|
const currentLocaleStatus = ref<'zh-CN' | 'en-US'>('zh-CN')
|
||||||
|
const currentScaleStatus = ref<'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'>('week')
|
||||||
|
const currentThemeStatus = ref<'light' | 'dark'>('light')
|
||||||
|
|
||||||
|
// Props控制变量
|
||||||
|
const propsLocale = ref<'zh-CN' | 'en-US'>('zh-CN')
|
||||||
|
const propsTheme = ref<'light' | 'dark'>('light')
|
||||||
|
const propsTimeScale = ref<'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'>('week')
|
||||||
|
const propsFullscreen = ref(false)
|
||||||
|
const propsExpandAll = ref(false)
|
||||||
|
|
||||||
|
// 监听 Props 变化,同步 status
|
||||||
|
watch(propsLocale, (newLocale) => {
|
||||||
|
currentLocaleStatus.value = newLocale
|
||||||
|
})
|
||||||
|
watch(propsTheme, (newTheme) => {
|
||||||
|
currentThemeStatus.value = newTheme
|
||||||
|
})
|
||||||
|
watch(propsTimeScale, (newScale) => {
|
||||||
|
currentScaleStatus.value = newScale
|
||||||
|
})
|
||||||
|
watch(propsFullscreen, (newFullscreen) => {
|
||||||
|
fullscreenStatus.value = newFullscreen
|
||||||
|
})
|
||||||
|
watch(propsExpandAll, (newExpandAll) => {
|
||||||
|
expandStatus.value = newExpandAll
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更新状态函数
|
||||||
|
const updateStatus = () => {
|
||||||
|
if (ganttRef.value) {
|
||||||
|
fullscreenStatus.value = ganttRef.value.isFullscreen()
|
||||||
|
expandStatus.value = ganttRef.value.isExpandAll()
|
||||||
|
currentLocaleStatus.value = ganttRef.value.currentLocale()
|
||||||
|
currentScaleStatus.value = ganttRef.value.currentScale()
|
||||||
|
currentThemeStatus.value = ganttRef.value.currentTheme()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose 方法处理器
|
||||||
|
const handleToggleFullscreen = () => {
|
||||||
|
ganttRef.value?.toggleFullscreen()
|
||||||
|
updateStatus()
|
||||||
|
propsFullscreen.value = ganttRef.value?.isFullscreen() ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleToggleExpandAll = () => {
|
||||||
|
ganttRef.value?.toggleExpandAll()
|
||||||
|
updateStatus()
|
||||||
|
propsExpandAll.value = ganttRef.value?.isExpandAll() ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetLocale = (locale: 'zh-CN' | 'en-US') => {
|
||||||
|
ganttRef.value?.setLocale(locale)
|
||||||
|
currentLocaleStatus.value = locale
|
||||||
|
propsLocale.value = locale
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetTimeScale = (scale: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year') => {
|
||||||
|
ganttRef.value?.setTimeScale(scale)
|
||||||
|
updateStatus()
|
||||||
|
propsTimeScale.value = scale
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetTheme = (mode: 'light' | 'dark') => {
|
||||||
|
ganttRef.value?.setTheme(mode)
|
||||||
|
updateStatus()
|
||||||
|
propsTheme.value = mode
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义类型接口
|
||||||
|
interface TaskListColumnConfig {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
visible: boolean;
|
||||||
|
width?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ToolbarConfig {
|
||||||
|
showAddTask?: boolean;
|
||||||
|
showAddMilestone?: boolean;
|
||||||
|
showTodayLocate?: boolean;
|
||||||
|
showExportCsv?: boolean;
|
||||||
|
showExportPdf?: boolean;
|
||||||
|
showLanguage?: boolean;
|
||||||
|
showTheme?: boolean;
|
||||||
|
showFullscreen?: boolean;
|
||||||
|
showTimeScale?: boolean;
|
||||||
|
timeScaleDimensions?: string[];
|
||||||
|
defaultTimeScale?: string;
|
||||||
|
showExpandCollapse?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasks = ref([
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '项目启动',
|
||||||
|
startDate: '2025-10-30',
|
||||||
|
endDate: '2025-11-5',
|
||||||
|
progress: 100,
|
||||||
|
department: '管理部',
|
||||||
|
departmentCode: 'D001',
|
||||||
|
type: 'task',
|
||||||
|
assignee: '',
|
||||||
|
assigneeName: '',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const milestones = ref([
|
||||||
|
{
|
||||||
|
id: 101,
|
||||||
|
name: '项目立项',
|
||||||
|
startDate: '2025-10-29',
|
||||||
|
type: 'milestone',
|
||||||
|
icon: 'diamond',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const customMessages = {
|
||||||
|
'zh-CN': {
|
||||||
|
department: '部门',
|
||||||
|
departmentCode: '部门编号',
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
department: 'Department',
|
||||||
|
departmentCode: 'Department Code',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
// const tasks = ref([])
|
||||||
|
|
||||||
|
// const milestones = ref([])
|
||||||
|
const showAddTaskDrawer = ref(false)
|
||||||
|
const showAddMilestoneDialog = ref(false)
|
||||||
|
|
||||||
|
// 定义可动态配置的列
|
||||||
|
const availableColumns = ref<TaskListColumnConfig[]>([
|
||||||
|
{ key: 'startDate', label: '开始日期', visible: true },
|
||||||
|
{ key: 'endDate', label: '结束日期', visible: true },
|
||||||
|
{ key: 'progress', label: '进度', visible: true },
|
||||||
|
{ key: 'department', label: '部门', visible: true, width: 120 },
|
||||||
|
{ key: 'departmentCode', label: '部门编号', visible: true },
|
||||||
|
{ key: 'assigneeName', label: '负责人', visible: true },
|
||||||
|
])
|
||||||
|
|
||||||
|
// 自定义负责人列表
|
||||||
|
const assigneeOptions = ref([
|
||||||
|
{ value: 'zhangsan', label: '张三' },
|
||||||
|
{ value: 'lisi', label: '李四' },
|
||||||
|
{ value: 'wangwu', label: '王五' },
|
||||||
|
])
|
||||||
|
|
||||||
|
// TaskList宽度配置示例
|
||||||
|
const taskListConfig = {
|
||||||
|
defaultWidth: '50%', // 默认展开宽度50%
|
||||||
|
minWidth: '300px', // 最小宽度300px(默认280px)
|
||||||
|
maxWidth: '1200px', // 最大宽度1200px(默认1160px)
|
||||||
|
columns: availableColumns.value,
|
||||||
|
}
|
||||||
|
|
||||||
|
// toolbar配置示例
|
||||||
|
const toolbarConfig: ToolbarConfig = {
|
||||||
|
showAddTask: true, // 显示添加任务按钮
|
||||||
|
showAddMilestone: true, // 显示添加里程碑按钮
|
||||||
|
showTodayLocate: true, // 显示定位到今天按钮
|
||||||
|
showExportCsv: true, // 显示导出CSV按钮
|
||||||
|
showExportPdf: true, // 显示导出PDF按钮
|
||||||
|
showLanguage: true, // 显示语言切换按钮
|
||||||
|
showTheme: true, // 显示主题切换按钮
|
||||||
|
showFullscreen: true, // 显示全屏按钮
|
||||||
|
showTimeScale: true, // 显示时间刻度按钮组
|
||||||
|
timeScaleDimensions: [ // 显示所有时间刻度维度
|
||||||
|
'hour', 'day', 'week', 'month', 'quarter', 'year',
|
||||||
|
],
|
||||||
|
defaultTimeScale: 'week', // 默认选中周视图
|
||||||
|
showExpandCollapse: false, // 显示展开/折叠按钮
|
||||||
|
}
|
||||||
|
|
||||||
|
const newTask = ref({
|
||||||
|
name: '',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const addTask = () => {
|
||||||
|
tasks.value.push({
|
||||||
|
id: tasks.value.length + 1,
|
||||||
|
name: newTask.value.name,
|
||||||
|
startDate: newTask.value.startDate,
|
||||||
|
endDate: newTask.value.endDate,
|
||||||
|
progress: 0,
|
||||||
|
department: '未分配',
|
||||||
|
departmentCode: 'D000',
|
||||||
|
assignee: '',
|
||||||
|
assigneeName: '',
|
||||||
|
type: 'task',
|
||||||
|
})
|
||||||
|
newTask.value = { name: '', startDate: '', endDate: '' }
|
||||||
|
showAddTaskDrawer.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const addMilestone = () => {
|
||||||
|
milestones.value.push({
|
||||||
|
id: milestones.value.length + 101,
|
||||||
|
name: newTask.value.name,
|
||||||
|
startDate: newTask.value.startDate,
|
||||||
|
type: 'milestone',
|
||||||
|
icon: 'diamond',
|
||||||
|
})
|
||||||
|
console.log('milestones: ', milestones.value)
|
||||||
|
newTask.value = { name: '', startDate: '', endDate: '' }
|
||||||
|
showAddMilestoneDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const onTaskDblclick = (task: any) => {
|
||||||
|
alert(`双击任务: ${task.name}`)
|
||||||
|
}
|
||||||
|
const onTaskClick = (task: any) => {
|
||||||
|
alert(`单击任务: ${task.name}`)
|
||||||
|
}
|
||||||
|
const onMilestoneDblclick = (milestone: any) => {
|
||||||
|
alert(`双击里程碑: ${milestone.name}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 任务行拖拽完成事件
|
||||||
|
const handleTaskRowMoved = (payload: {
|
||||||
|
draggedTask: Task
|
||||||
|
targetTask: Task
|
||||||
|
position: 'after' | 'child'
|
||||||
|
}) => {
|
||||||
|
const { draggedTask, targetTask, position } = payload
|
||||||
|
|
||||||
|
alert(`任务 [${draggedTask.name}] 被拖拽到任务 [${targetTask.name}] ${position === 'after' ? '之后' : '下方作为子任务'}`)
|
||||||
|
|
||||||
|
// 组件已自动更新任务的层级关系和位置
|
||||||
|
// position === 'after': 任务被放置在目标任务之后(同级)
|
||||||
|
// position === 'child': 任务被放置为目标任务的子任务(第一个子任务位置)
|
||||||
|
|
||||||
|
// 这里可以:
|
||||||
|
// 1. 显示确认对话框,让用户确认是否移动
|
||||||
|
// 2. 调用后端 API 保存新的任务层级关系
|
||||||
|
// 3. 更新相关的依赖关系
|
||||||
|
|
||||||
|
// 示例:调用后端 API
|
||||||
|
// await api.updateTaskHierarchy({
|
||||||
|
// taskId: draggedTask.id,
|
||||||
|
// targetTaskId: targetTask.id,
|
||||||
|
// position: position
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 任务添加后回调
|
||||||
|
const onTaskAdded = (res) => {
|
||||||
|
const addedTask = tasks.value.find(t => t.id === res.task.id)
|
||||||
|
if (addedTask) {
|
||||||
|
// 使用addedTask.assignee去查找assigneeOptions的label进行赋值
|
||||||
|
const assigneeOption = assigneeOptions.value.find(option => option.value === addedTask.assignee)
|
||||||
|
if (assigneeOption) {
|
||||||
|
addedTask.assigneeName = assigneeOption.label
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 使用addedTask.assignee去查找assigneeOptions的label进行赋值
|
||||||
|
const assigneeOption = assigneeOptions.value.find(option => option.value === res.task.assignee)
|
||||||
|
if (assigneeOption) {
|
||||||
|
res.task.assigneeName = assigneeOption.label
|
||||||
|
}
|
||||||
|
tasks.value.push(res.task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<!-- 工具设置面板 -->
|
<!-- 工具设置面板 -->
|
||||||
@@ -290,8 +574,8 @@
|
|||||||
|
|
||||||
<!-- 自定义Dialog组件基于element plus -->
|
<!-- 自定义Dialog组件基于element plus -->
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="自定义添加里程碑组件 - Element Plus"
|
|
||||||
v-model="showAddMilestoneDialog"
|
v-model="showAddMilestoneDialog"
|
||||||
|
title="自定义添加里程碑组件 - Element Plus"
|
||||||
width="400px"
|
width="400px"
|
||||||
@close="newTask = { name: '', startDate: '', endDate: '' }"
|
@close="newTask = { name: '', startDate: '', endDate: '' }"
|
||||||
>
|
>
|
||||||
@@ -315,291 +599,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, computed, watch } from 'vue';
|
|
||||||
import { GanttChart, Task } from 'jordium-gantt-vue3'
|
|
||||||
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
|
|
||||||
|
|
||||||
// GanttChart ref
|
|
||||||
const ganttRef = ref(null)
|
|
||||||
|
|
||||||
// 控制模式:'expose' 使用expose方法,'props' 使用Props
|
|
||||||
const controlMode = ref<'expose' | 'props'>('expose')
|
|
||||||
|
|
||||||
// 状态变量
|
|
||||||
const fullscreenStatus = ref(false)
|
|
||||||
const expandStatus = ref(false)
|
|
||||||
const currentLocaleStatus = ref<'zh-CN' | 'en-US'>('zh-CN')
|
|
||||||
const currentScaleStatus = ref<'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'>('week')
|
|
||||||
const currentThemeStatus = ref<'light' | 'dark'>('light')
|
|
||||||
|
|
||||||
// Props控制变量
|
|
||||||
const propsLocale = ref<'zh-CN' | 'en-US'>('zh-CN')
|
|
||||||
const propsTheme = ref<'light' | 'dark'>('light')
|
|
||||||
const propsTimeScale = ref<'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'>('week')
|
|
||||||
const propsFullscreen = ref(false)
|
|
||||||
const propsExpandAll = ref(false)
|
|
||||||
|
|
||||||
// 监听 Props 变化,同步 status
|
|
||||||
watch(propsLocale, (newLocale) => {
|
|
||||||
currentLocaleStatus.value = newLocale
|
|
||||||
})
|
|
||||||
watch(propsTheme, (newTheme) => {
|
|
||||||
currentThemeStatus.value = newTheme
|
|
||||||
})
|
|
||||||
watch(propsTimeScale, (newScale) => {
|
|
||||||
currentScaleStatus.value = newScale
|
|
||||||
})
|
|
||||||
watch(propsFullscreen, (newFullscreen) => {
|
|
||||||
fullscreenStatus.value = newFullscreen
|
|
||||||
})
|
|
||||||
watch(propsExpandAll, (newExpandAll) => {
|
|
||||||
expandStatus.value = newExpandAll
|
|
||||||
})
|
|
||||||
|
|
||||||
// 更新状态函数
|
|
||||||
const updateStatus = () => {
|
|
||||||
if (ganttRef.value) {
|
|
||||||
fullscreenStatus.value = ganttRef.value.isFullscreen()
|
|
||||||
expandStatus.value = ganttRef.value.isExpandAll()
|
|
||||||
currentLocaleStatus.value = ganttRef.value.currentLocale()
|
|
||||||
currentScaleStatus.value = ganttRef.value.currentScale()
|
|
||||||
currentThemeStatus.value = ganttRef.value.currentTheme()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Expose 方法处理器
|
|
||||||
const handleToggleFullscreen = () => {
|
|
||||||
ganttRef.value?.toggleFullscreen()
|
|
||||||
updateStatus()
|
|
||||||
propsFullscreen.value = ganttRef.value?.isFullscreen() ?? false
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleToggleExpandAll = () => {
|
|
||||||
ganttRef.value?.toggleExpandAll()
|
|
||||||
updateStatus()
|
|
||||||
propsExpandAll.value = ganttRef.value?.isExpandAll() ?? false
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSetLocale = (locale: 'zh-CN' | 'en-US') => {
|
|
||||||
ganttRef.value?.setLocale(locale)
|
|
||||||
currentLocaleStatus.value = locale
|
|
||||||
propsLocale.value = locale
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSetTimeScale = (scale: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year') => {
|
|
||||||
ganttRef.value?.setTimeScale(scale)
|
|
||||||
updateStatus()
|
|
||||||
propsTimeScale.value = scale
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSetTheme = (mode: 'light' | 'dark') => {
|
|
||||||
ganttRef.value?.setTheme(mode)
|
|
||||||
updateStatus()
|
|
||||||
propsTheme.value = mode
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定义类型接口
|
|
||||||
interface TaskListColumnConfig {
|
|
||||||
key: string;
|
|
||||||
label: string;
|
|
||||||
visible: boolean;
|
|
||||||
width?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ToolbarConfig {
|
|
||||||
showAddTask?: boolean;
|
|
||||||
showAddMilestone?: boolean;
|
|
||||||
showTodayLocate?: boolean;
|
|
||||||
showExportCsv?: boolean;
|
|
||||||
showExportPdf?: boolean;
|
|
||||||
showLanguage?: boolean;
|
|
||||||
showTheme?: boolean;
|
|
||||||
showFullscreen?: boolean;
|
|
||||||
showTimeScale?: boolean;
|
|
||||||
timeScaleDimensions?: string[];
|
|
||||||
defaultTimeScale?: string;
|
|
||||||
showExpandCollapse?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tasks = ref([
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: '项目启动',
|
|
||||||
startDate: '2025-10-30',
|
|
||||||
endDate: '2025-11-5',
|
|
||||||
progress: 100,
|
|
||||||
department: '管理部',
|
|
||||||
departmentCode: 'D001',
|
|
||||||
type: 'task',
|
|
||||||
assignee: '',
|
|
||||||
assigneeName: ''
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const milestones = ref([
|
|
||||||
{
|
|
||||||
id: 101,
|
|
||||||
name: '项目立项',
|
|
||||||
startDate: '2025-10-29',
|
|
||||||
type: 'milestone',
|
|
||||||
icon: 'diamond'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const customMessages = {
|
|
||||||
'zh-CN': {
|
|
||||||
department: '部门',
|
|
||||||
departmentCode: '部门编号',
|
|
||||||
},
|
|
||||||
'en-US': {
|
|
||||||
department: 'Department',
|
|
||||||
departmentCode: 'Department Code',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// const tasks = ref([])
|
|
||||||
|
|
||||||
// const milestones = ref([])
|
|
||||||
const showAddTaskDrawer = ref(false);
|
|
||||||
const showAddMilestoneDialog = ref(false);
|
|
||||||
|
|
||||||
// 定义可动态配置的列
|
|
||||||
const availableColumns = ref<TaskListColumnConfig[]>([
|
|
||||||
{ key: 'startDate', label: '开始日期', visible: true },
|
|
||||||
{ key: 'endDate', label: '结束日期', visible: true },
|
|
||||||
{ key: 'progress', label: '进度', visible: true },
|
|
||||||
{ key: 'department', label: '部门', visible: true, width: 120 },
|
|
||||||
{ key: 'departmentCode', label: '部门编号', visible: true },
|
|
||||||
{ key: 'assigneeName', label: '负责人', visible: true },
|
|
||||||
])
|
|
||||||
|
|
||||||
// 自定义负责人列表
|
|
||||||
const assigneeOptions = ref([
|
|
||||||
{ value: 'zhangsan', label: '张三' },
|
|
||||||
{ value: 'lisi', label: '李四' },
|
|
||||||
{ value: 'wangwu', label: '王五' },
|
|
||||||
])
|
|
||||||
|
|
||||||
// TaskList宽度配置示例
|
|
||||||
const taskListConfig = {
|
|
||||||
defaultWidth: '50%', // 默认展开宽度50%
|
|
||||||
minWidth: '300px', // 最小宽度300px(默认280px)
|
|
||||||
maxWidth: '1200px', // 最大宽度1200px(默认1160px)
|
|
||||||
columns: availableColumns.value
|
|
||||||
}
|
|
||||||
|
|
||||||
// toolbar配置示例
|
|
||||||
const toolbarConfig: ToolbarConfig = {
|
|
||||||
showAddTask: true, // 显示添加任务按钮
|
|
||||||
showAddMilestone: true, // 显示添加里程碑按钮
|
|
||||||
showTodayLocate: true, // 显示定位到今天按钮
|
|
||||||
showExportCsv: true, // 显示导出CSV按钮
|
|
||||||
showExportPdf: true, // 显示导出PDF按钮
|
|
||||||
showLanguage: true, // 显示语言切换按钮
|
|
||||||
showTheme: true, // 显示主题切换按钮
|
|
||||||
showFullscreen: true, // 显示全屏按钮
|
|
||||||
showTimeScale: true, // 显示时间刻度按钮组
|
|
||||||
timeScaleDimensions: [ // 显示所有时间刻度维度
|
|
||||||
'hour', 'day', 'week', 'month', 'quarter', 'year'
|
|
||||||
],
|
|
||||||
defaultTimeScale: 'week', // 默认选中周视图
|
|
||||||
showExpandCollapse: false // 显示展开/折叠按钮
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const newTask = ref({
|
|
||||||
name: '',
|
|
||||||
startDate: '',
|
|
||||||
endDate: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const addTask = () => {
|
|
||||||
tasks.value.push({
|
|
||||||
id: tasks.value.length + 1,
|
|
||||||
name: newTask.value.name,
|
|
||||||
startDate: newTask.value.startDate,
|
|
||||||
endDate: newTask.value.endDate,
|
|
||||||
progress: 0,
|
|
||||||
department: '未分配',
|
|
||||||
departmentCode: 'D000',
|
|
||||||
assignee: '',
|
|
||||||
assigneeName: '',
|
|
||||||
type: 'task',
|
|
||||||
});
|
|
||||||
newTask.value = { name: '', startDate: '', endDate: '' };
|
|
||||||
showAddTaskDrawer.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const addMilestone = () => {
|
|
||||||
milestones.value.push({
|
|
||||||
id: milestones.value.length + 101,
|
|
||||||
name: newTask.value.name,
|
|
||||||
startDate: newTask.value.startDate,
|
|
||||||
type: 'milestone',
|
|
||||||
icon: 'diamond'
|
|
||||||
});
|
|
||||||
console.log('milestones: ', milestones.value)
|
|
||||||
newTask.value = { name: '', startDate: '', endDate: '' };
|
|
||||||
showAddMilestoneDialog.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const onTaskDblclick = (task: any) => {
|
|
||||||
alert(`双击任务: ${task.name}`)
|
|
||||||
}
|
|
||||||
const onTaskClick = (task: any) => {
|
|
||||||
alert(`单击任务: ${task.name}`)
|
|
||||||
}
|
|
||||||
const onMilestoneDblclick = (milestone: any) => {
|
|
||||||
alert(`双击里程碑: ${milestone.name}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 任务行拖拽完成事件
|
|
||||||
const handleTaskRowMoved = (payload: {
|
|
||||||
draggedTask: Task
|
|
||||||
targetTask: Task
|
|
||||||
position: 'after' | 'child'
|
|
||||||
}) => {
|
|
||||||
const { draggedTask, targetTask, position } = payload
|
|
||||||
|
|
||||||
alert(`任务 [${draggedTask.name}] 被拖拽到任务 [${targetTask.name}] ${position === 'after' ? '之后' : '下方作为子任务'}`)
|
|
||||||
|
|
||||||
// 组件已自动更新任务的层级关系和位置
|
|
||||||
// position === 'after': 任务被放置在目标任务之后(同级)
|
|
||||||
// position === 'child': 任务被放置为目标任务的子任务(第一个子任务位置)
|
|
||||||
|
|
||||||
// 这里可以:
|
|
||||||
// 1. 显示确认对话框,让用户确认是否移动
|
|
||||||
// 2. 调用后端 API 保存新的任务层级关系
|
|
||||||
// 3. 更新相关的依赖关系
|
|
||||||
|
|
||||||
// 示例:调用后端 API
|
|
||||||
// await api.updateTaskHierarchy({
|
|
||||||
// taskId: draggedTask.id,
|
|
||||||
// targetTaskId: targetTask.id,
|
|
||||||
// position: position
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 任务添加后回调
|
|
||||||
const onTaskAdded = (res) => {
|
|
||||||
const addedTask = tasks.value.find(t => t.id === res.task.id);
|
|
||||||
if (addedTask) {
|
|
||||||
// 使用addedTask.assignee去查找assigneeOptions的label进行赋值
|
|
||||||
const assigneeOption = assigneeOptions.value.find(option => option.value === addedTask.assignee);
|
|
||||||
if (assigneeOption) {
|
|
||||||
addedTask.assigneeName = assigneeOption.label;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 使用addedTask.assignee去查找assigneeOptions的label进行赋值
|
|
||||||
const assigneeOption = assigneeOptions.value.find(option => option.value === res.task.assignee);
|
|
||||||
if (assigneeOption) {
|
|
||||||
res.task.assigneeName = assigneeOption.label;
|
|
||||||
}
|
|
||||||
tasks.value.push(res.task);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
/* 工具设置面板 */
|
/* 工具设置面板 */
|
||||||
.tool-settings-panel {
|
.tool-settings-panel {
|
||||||
|
|||||||
@@ -10,6 +10,18 @@ defineOptions({
|
|||||||
name: 'TaskListColumn',
|
name: 'TaskListColumn',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
align: 'left',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义 slot
|
||||||
|
defineSlots<{
|
||||||
|
// 列头部插槽
|
||||||
|
header?:() => any
|
||||||
|
// 列内容默认插槽,接收 scope 对象 { row: Task, $index: number }
|
||||||
|
default?: (scope: { row: any; $index: number }) => any
|
||||||
|
}>()
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
// 列的属性名(用于访问任务数据)
|
// 列的属性名(用于访问任务数据)
|
||||||
prop?: string
|
prop?: string
|
||||||
@@ -23,18 +35,6 @@ interface Props {
|
|||||||
cssClass?: string
|
cssClass?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
withDefaults(defineProps<Props>(), {
|
|
||||||
align: 'left',
|
|
||||||
})
|
|
||||||
|
|
||||||
// 定义 slot
|
|
||||||
defineSlots<{
|
|
||||||
// 列头部插槽
|
|
||||||
header?: () => any
|
|
||||||
// 列内容默认插槽,接收 scope 对象 { row: Task, $index: number }
|
|
||||||
default?: (scope: { row: any; $index: number }) => any
|
|
||||||
}>()
|
|
||||||
|
|
||||||
// 注意:此组件不渲染任何内容,仅用于声明列配置
|
// 注意:此组件不渲染任何内容,仅用于声明列配置
|
||||||
// 实际渲染由 TaskList 和 TaskRow 处理
|
// 实际渲染由 TaskList 和 TaskRow 处理
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -9,23 +9,23 @@ defineOptions({
|
|||||||
name: 'TaskListContextMenu',
|
name: 'TaskListContextMenu',
|
||||||
})
|
})
|
||||||
|
|
||||||
interface Props {
|
|
||||||
// 指定哪些任务类型显示此右键菜单
|
|
||||||
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
|
|
||||||
taskType?: string | string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
|
|
||||||
// 定义 slot
|
// 定义 slot
|
||||||
defineSlots<{
|
defineSlots<{
|
||||||
// 默认插槽,接收菜单上下文对象
|
// 默认插槽,接收菜单上下文对象
|
||||||
default?: (scope: {
|
default?:(scope: {
|
||||||
row: any
|
row: any
|
||||||
$index: number
|
$index: number
|
||||||
}) => any
|
}) => any
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
// 指定哪些任务类型显示此右键菜单
|
||||||
|
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
|
||||||
|
taskType?: string | string[]
|
||||||
|
}
|
||||||
|
|
||||||
// 注意:此组件不渲染任何内容,仅用于声明菜单配置
|
// 注意:此组件不渲染任何内容,仅用于声明菜单配置
|
||||||
// 实际渲染由 TaskRow 处理,菜单定位和显示状态由内部自动管理
|
// 实际渲染由 TaskRow 处理,菜单定位和显示状态由内部自动管理
|
||||||
// 菜单会在点击外部或滚动时自动关闭
|
// 菜单会在点击外部或滚动时自动关闭
|
||||||
|
|||||||
@@ -311,21 +311,21 @@ const slotPayload = computed(() => ({
|
|||||||
|
|
||||||
<TaskRowNameContent
|
<TaskRowNameContent
|
||||||
:task="props.task"
|
:task="props.task"
|
||||||
:isParentTask="isParentTask"
|
:is-parent-task="isParentTask"
|
||||||
:hasChildren="hasChildren"
|
:has-children="hasChildren"
|
||||||
:isStoryTask="isStoryTask"
|
:is-story-task="isStoryTask"
|
||||||
:isMilestoneGroup="isMilestoneGroup"
|
:is-milestone-group="isMilestoneGroup"
|
||||||
:isMilestoneTask="isMilestoneTask"
|
:is-milestone-task="isMilestoneTask"
|
||||||
:showTaskIcon="showTaskIcon !== false"
|
:show-task-icon="showTaskIcon !== false"
|
||||||
:formattedTimer="formattedTimer"
|
:formatted-timer="formattedTimer"
|
||||||
:isOvertime="!!isOvertime()"
|
:is-overtime="!!isOvertime()"
|
||||||
:overdueDays="overdueDays()"
|
:overdue-days="overdueDays()"
|
||||||
:overtimeText="overtimeText"
|
:overtime-text="overtimeText"
|
||||||
:overdueText="overdueText"
|
:overdue-text="overdueText"
|
||||||
:daysText="daysText"
|
:days-text="daysText"
|
||||||
:hasContentSlot="hasContentSlot"
|
:has-content-slot="hasContentSlot"
|
||||||
:renderColumnSlot="renderColumnSlot"
|
:render-column-slot="renderColumnSlot"
|
||||||
:hasColumnSlot="hasColumnSlot"
|
:has-column-slot="hasColumnSlot"
|
||||||
>
|
>
|
||||||
<template #custom-task-content>
|
<template #custom-task-content>
|
||||||
<slot
|
<slot
|
||||||
|
|||||||
@@ -56,11 +56,11 @@ defineSlots<{
|
|||||||
<!-- 优先级2: custom-task-content Slot (向后兼容) - 仅替换文本部分 -->
|
<!-- 优先级2: custom-task-content Slot (向后兼容) - 仅替换文本部分 -->
|
||||||
<template v-else-if="hasContentSlot">
|
<template v-else-if="hasContentSlot">
|
||||||
<TaskRowIcon
|
<TaskRowIcon
|
||||||
:isMilestoneGroup="isMilestoneGroup"
|
:is-milestone-group="isMilestoneGroup"
|
||||||
:isParentTask="isParentTask"
|
:is-parent-task="isParentTask"
|
||||||
:hasChildren="hasChildren"
|
:has-children="hasChildren"
|
||||||
:isStoryTask="isStoryTask"
|
:is-story-task="isStoryTask"
|
||||||
:showIcon="showTaskIcon"
|
:show-icon="showTaskIcon"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
@@ -70,14 +70,14 @@ defineSlots<{
|
|||||||
>
|
>
|
||||||
<slot name="custom-task-content" />
|
<slot name="custom-task-content" />
|
||||||
<TaskRowBadges
|
<TaskRowBadges
|
||||||
:formattedTimer="formattedTimer"
|
:formatted-timer="formattedTimer"
|
||||||
:isTimerRunning="!!task.isTimerRunning"
|
:is-timer-running="!!task.isTimerRunning"
|
||||||
:timerElapsedTime="task.timerElapsedTime"
|
:timer-elapsed-time="task.timerElapsedTime"
|
||||||
:isOvertime="isOvertime"
|
:is-overtime="isOvertime"
|
||||||
:overdueDays="overdueDays"
|
:overdue-days="overdueDays"
|
||||||
:overtimeText="overtimeText"
|
:overtime-text="overtimeText"
|
||||||
:overdueText="overdueText"
|
:overdue-text="overdueText"
|
||||||
:daysText="daysText"
|
:days-text="daysText"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -85,11 +85,11 @@ defineSlots<{
|
|||||||
<!-- 优先级3: 默认渲染 -->
|
<!-- 优先级3: 默认渲染 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<TaskRowIcon
|
<TaskRowIcon
|
||||||
:isMilestoneGroup="isMilestoneGroup"
|
:is-milestone-group="isMilestoneGroup"
|
||||||
:isParentTask="isParentTask"
|
:is-parent-task="isParentTask"
|
||||||
:hasChildren="hasChildren"
|
:has-children="hasChildren"
|
||||||
:isStoryTask="isStoryTask"
|
:is-story-task="isStoryTask"
|
||||||
:showIcon="showTaskIcon"
|
:show-icon="showTaskIcon"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
@@ -99,14 +99,14 @@ defineSlots<{
|
|||||||
>
|
>
|
||||||
{{ task.name }}
|
{{ task.name }}
|
||||||
<TaskRowBadges
|
<TaskRowBadges
|
||||||
:formattedTimer="formattedTimer"
|
:formatted-timer="formattedTimer"
|
||||||
:isTimerRunning="!!task.isTimerRunning"
|
:is-timer-running="!!task.isTimerRunning"
|
||||||
:timerElapsedTime="task.timerElapsedTime"
|
:timer-elapsed-time="task.timerElapsedTime"
|
||||||
:isOvertime="isOvertime"
|
:is-overtime="isOvertime"
|
||||||
:overdueDays="overdueDays"
|
:overdue-days="overdueDays"
|
||||||
:overtimeText="overtimeText"
|
:overtime-text="overtimeText"
|
||||||
:overdueText="overdueText"
|
:overdue-text="overdueText"
|
||||||
:daysText="daysText"
|
:days-text="daysText"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1049,7 +1049,7 @@ const hasCircularDependency = (taskId: number, targetId: number): boolean => {
|
|||||||
|
|
||||||
// 创建连接
|
// 创建连接
|
||||||
const createLink = (sourceTask: Task, targetTask: Task, mode: 'predecessor' | 'successor') => {
|
const createLink = (sourceTask: Task, targetTask: Task, mode: 'predecessor' | 'successor') => {
|
||||||
console.log("----> hello:", {
|
console.log('----> hello:', {
|
||||||
mode,
|
mode,
|
||||||
sourceTask,
|
sourceTask,
|
||||||
targetTask,
|
targetTask,
|
||||||
|
|||||||
@@ -9,23 +9,23 @@ defineOptions({
|
|||||||
name: 'TaskBarContextMenu',
|
name: 'TaskBarContextMenu',
|
||||||
})
|
})
|
||||||
|
|
||||||
interface Props {
|
|
||||||
// 指定哪些任务类型显示此右键菜单
|
|
||||||
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
|
|
||||||
taskType?: string | string[]
|
|
||||||
}
|
|
||||||
|
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
|
|
||||||
// 定义 slot
|
// 定义 slot
|
||||||
defineSlots<{
|
defineSlots<{
|
||||||
// 默认插槽,接收菜单上下文对象
|
// 默认插槽,接收菜单上下文对象
|
||||||
default?: (scope: {
|
default?:(scope: {
|
||||||
row: any
|
row: any
|
||||||
$index: number
|
$index: number
|
||||||
}) => any
|
}) => any
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
// 指定哪些任务类型显示此右键菜单
|
||||||
|
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
|
||||||
|
taskType?: string | string[]
|
||||||
|
}
|
||||||
|
|
||||||
// 注意:此组件不渲染任何内容,仅用于声明菜单配置
|
// 注意:此组件不渲染任何内容,仅用于声明菜单配置
|
||||||
// 实际渲染由 TaskBar 处理,菜单定位和显示状态由内部自动管理
|
// 实际渲染由 TaskBar 处理,菜单定位和显示状态由内部自动管理
|
||||||
// 菜单会在点击外部或滚动时自动关闭
|
// 菜单会在点击外部或滚动时自动关闭
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export type {
|
|||||||
TaskListConfig,
|
TaskListConfig,
|
||||||
TaskListColumnConfig,
|
TaskListColumnConfig,
|
||||||
TaskListColumnType,
|
TaskListColumnType,
|
||||||
ColumnFormatter
|
ColumnFormatter,
|
||||||
} from './models/configs/TaskListConfig'
|
} from './models/configs/TaskListConfig'
|
||||||
export type { TaskBarConfig } from './models/configs/TaskBarConfig'
|
export type { TaskBarConfig } from './models/configs/TaskBarConfig'
|
||||||
export type { ToolbarConfig } from './models/configs/ToolbarConfig'
|
export type { ToolbarConfig } from './models/configs/ToolbarConfig'
|
||||||
|
|||||||
18
tests/fixtures/columns.ts
vendored
18
tests/fixtures/columns.ts
vendored
@@ -4,7 +4,7 @@ import { TaskListColumnConfig } from '@/models/configs/TaskListConfig'
|
|||||||
* 创建基础列配置
|
* 创建基础列配置
|
||||||
*/
|
*/
|
||||||
export function createColumn(
|
export function createColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
key: 'name',
|
key: 'name',
|
||||||
@@ -19,7 +19,7 @@ export function createColumn(
|
|||||||
* 创建名称列配置
|
* 创建名称列配置
|
||||||
*/
|
*/
|
||||||
export function createNameColumn(
|
export function createNameColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
type: 'name',
|
type: 'name',
|
||||||
@@ -35,7 +35,7 @@ export function createNameColumn(
|
|||||||
* 创建前置任务列配置
|
* 创建前置任务列配置
|
||||||
*/
|
*/
|
||||||
export function createPredecessorColumn(
|
export function createPredecessorColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
type: 'predecessor',
|
type: 'predecessor',
|
||||||
@@ -51,7 +51,7 @@ export function createPredecessorColumn(
|
|||||||
* 创建负责人列配置
|
* 创建负责人列配置
|
||||||
*/
|
*/
|
||||||
export function createAssigneeColumn(
|
export function createAssigneeColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
type: 'assignee',
|
type: 'assignee',
|
||||||
@@ -67,7 +67,7 @@ export function createAssigneeColumn(
|
|||||||
* 创建开始日期列配置
|
* 创建开始日期列配置
|
||||||
*/
|
*/
|
||||||
export function createStartDateColumn(
|
export function createStartDateColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
type: 'startDate',
|
type: 'startDate',
|
||||||
@@ -83,7 +83,7 @@ export function createStartDateColumn(
|
|||||||
* 创建结束日期列配置
|
* 创建结束日期列配置
|
||||||
*/
|
*/
|
||||||
export function createEndDateColumn(
|
export function createEndDateColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
type: 'endDate',
|
type: 'endDate',
|
||||||
@@ -99,7 +99,7 @@ export function createEndDateColumn(
|
|||||||
* 创建进度列配置
|
* 创建进度列配置
|
||||||
*/
|
*/
|
||||||
export function createProgressColumn(
|
export function createProgressColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
type: 'progress',
|
type: 'progress',
|
||||||
@@ -115,7 +115,7 @@ export function createProgressColumn(
|
|||||||
* 创建自定义列配置
|
* 创建自定义列配置
|
||||||
*/
|
*/
|
||||||
export function createCustomColumn(
|
export function createCustomColumn(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
key: 'customField',
|
key: 'customField',
|
||||||
@@ -130,7 +130,7 @@ export function createCustomColumn(
|
|||||||
* 创建带格式化函数的列配置
|
* 创建带格式化函数的列配置
|
||||||
*/
|
*/
|
||||||
export function createColumnWithFormatter(
|
export function createColumnWithFormatter(
|
||||||
overrides: Partial<TaskListColumnConfig> = {}
|
overrides: Partial<TaskListColumnConfig> = {},
|
||||||
): TaskListColumnConfig {
|
): TaskListColumnConfig {
|
||||||
return {
|
return {
|
||||||
key: 'formatted',
|
key: 'formatted',
|
||||||
|
|||||||
4
tests/fixtures/tasks.ts
vendored
4
tests/fixtures/tasks.ts
vendored
@@ -36,7 +36,7 @@ export function createParentTask(overrides: Partial<Task> = {}): Task {
|
|||||||
*/
|
*/
|
||||||
export function createChildTask(
|
export function createChildTask(
|
||||||
parentId: number,
|
parentId: number,
|
||||||
overrides: Partial<Task> = {}
|
overrides: Partial<Task> = {},
|
||||||
): Task {
|
): Task {
|
||||||
return {
|
return {
|
||||||
id: 2,
|
id: 2,
|
||||||
@@ -200,7 +200,7 @@ export function createTaskTree(): Task[] {
|
|||||||
/**
|
/**
|
||||||
* 创建扁平任务列表
|
* 创建扁平任务列表
|
||||||
*/
|
*/
|
||||||
export function createFlatTaskList(count: number = 10): Task[] {
|
export function createFlatTaskList(count = 10): Task[] {
|
||||||
return Array.from({ length: count }, (_, index) => ({
|
return Array.from({ length: count }, (_, index) => ({
|
||||||
id: index + 1,
|
id: index + 1,
|
||||||
name: `Task ${index + 1}`,
|
name: `Task ${index + 1}`,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type { ComponentPublicInstance } from 'vue'
|
|||||||
*/
|
*/
|
||||||
export function mountComponent<T extends ComponentPublicInstance>(
|
export function mountComponent<T extends ComponentPublicInstance>(
|
||||||
component: any,
|
component: any,
|
||||||
options = {}
|
options = {},
|
||||||
): VueWrapper<T> {
|
): VueWrapper<T> {
|
||||||
return mount(component, {
|
return mount(component, {
|
||||||
global: {
|
global: {
|
||||||
@@ -48,7 +48,7 @@ export function sleep(ms: number): Promise<void> {
|
|||||||
export function triggerMouseEvent(
|
export function triggerMouseEvent(
|
||||||
element: Element,
|
element: Element,
|
||||||
eventType: string,
|
eventType: string,
|
||||||
options: MouseEventInit = {}
|
options: MouseEventInit = {},
|
||||||
) {
|
) {
|
||||||
const event = new MouseEvent(eventType, {
|
const event = new MouseEvent(eventType, {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user