Merge branch 'develop' into pages

This commit is contained in:
LINING-PC\lining
2026-01-11 22:23:34 +08:00
15 changed files with 399 additions and 398 deletions

View File

@@ -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 |
| `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'`) |
| `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 |
| `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 |

View File

@@ -2121,6 +2121,8 @@ GanttChart 组件通过 `defineExpose` 暴露了一系列方法,允许父组
| `setTheme` <sup class="version-badge">1.7.1</sup> | `mode: 'light' \| 'dark'` | `void` | 设置主题模式 |
| `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'` |
| `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` | 获取当前时间刻度 |
| `toggleFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | 切换全屏状态 |
| `enterFullscreen` <sup class="version-badge">1.7.1</sup> | - | `void` | 进入全屏模式 |

View File

@@ -196,7 +196,6 @@ const handleCancel = () => {
.btn-confirm:active {
background: #3a8ee6;
}
</style>
<style>

View File

@@ -3,7 +3,7 @@ import { ref, computed, watch } from 'vue'
import { GanttChart, TaskListColumn, useI18n, TaskListContextMenu, TaskBarContextMenu } from 'jordium-gantt-vue3'
import 'jordium-gantt-vue3/dist/assets/jordium-gantt-vue3.css'
const { t, getTranslation } = useI18n();
const { t, getTranslation } = useI18n()
// GanttChart ref
const ganttRef = ref(null)
@@ -114,7 +114,7 @@ const tasks = ref([
department: '管理部',
departmentCode: 'D001',
type: 'task',
}
},
])
const milestones = ref([
@@ -123,8 +123,8 @@ const milestones = ref([
name: '项目立项',
startDate: '2025-10-29',
type: 'milestone',
icon: 'diamond'
}
icon: 'diamond',
},
])
const customMessages = {
@@ -139,7 +139,7 @@ const customMessages = {
gantt: {
planStartDate: '计划开始时间',
//planEndDate: '计划结束时间',
}
},
},
'en-US': {
department: 'Department',
@@ -152,16 +152,16 @@ const customMessages = {
gantt: {
planStartDate: 'Plan Start Date',
planEndDate: 'Plan End Date',
}
}
},
},
}
// const tasks = ref([])
// const milestones = ref([])
const showAddTaskDrawer = ref(false);
const showAddMilestoneDialog = ref(false);
const showTodayLocate = ref(true);
const showAddTaskDrawer = ref(false)
const showAddMilestoneDialog = ref(false)
const showTodayLocate = ref(true)
// 定义可动态配置的列
const availableColumns = ref<TaskListColumnConfig[]>([
@@ -186,7 +186,7 @@ const taskListConfig = {
defaultWidth: '50%', // 默认展开宽度50%
minWidth: '300px', // 最小宽度300px默认280px
maxWidth: '1200px', // 最大宽度1200px默认1160px
columns: availableColumns.value
columns: availableColumns.value,
}
// toolbar配置示例
@@ -201,18 +201,17 @@ const toolbarConfig: ToolbarConfig = {
showFullscreen: true, // 显示全屏按钮
showTimeScale: true, // 显示时间刻度按钮组
timeScaleDimensions: [ // 显示所有时间刻度维度
'hour', 'day', 'week', 'month', 'quarter', 'year'
'hour', 'day', 'week', 'month', 'quarter', 'year',
],
defaultTimeScale: 'week', // 默认选中周视图
showExpandCollapse: false // 显示展开/折叠按钮
showExpandCollapse: false, // 显示展开/折叠按钮
}
const newTask = ref({
name: '',
startDate: '',
endDate: ''
});
endDate: '',
})
const addTask = () => {
tasks.value.push({
@@ -221,10 +220,10 @@ const addTask = () => {
startDate: newTask.value.startDate,
endDate: newTask.value.endDate,
progress: 0,
});
newTask.value = { name: '', startDate: '', endDate: '' };
showAddTaskDrawer.value = false;
};
})
newTask.value = { name: '', startDate: '', endDate: '' }
showAddTaskDrawer.value = false
}
const addMilestone = () => {
milestones.value.push({
@@ -233,11 +232,11 @@ const addMilestone = () => {
startDate: newTask.value.startDate,
progress: 0,
type: 'milestone',
icon: 'diamond'
});
icon: 'diamond',
})
console.log('milestones: ', milestones.value)
newTask.value = { name: '', startDate: '', endDate: '' };
showAddMilestoneDialog.value = false;
newTask.value = { name: '', startDate: '', endDate: '' }
showAddMilestoneDialog.value = false
}
const onTaskDblclick = (task) => {
@@ -294,18 +293,18 @@ const handleTaskRowMoved = async (payload: {
// 此回调仅用于补充业务逻辑例如根据assignee填充assigneeName等
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) {
// 根据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) {
addedTask.assigneeName = assigneeOption.label;
addedTask.assigneeName = assigneeOption.label
}
}
// 不需要手动push组件已处理
};
}
// 自定义右键菜单操作处理
const handleCustomMenuAction = (action: string, task: Task, onClose: () => void) => {
@@ -656,8 +655,8 @@ const handleCustomMenuAction = (action: string, task: Task, onClose: () => void)
<!-- 自定义Dialog组件基于element plus -->
<el-dialog
title="自定义添加里程碑组件 - Element Plus"
v-model="showAddMilestoneDialog"
title="自定义添加里程碑组件 - Element Plus"
width="400px"
@close="newTask = { name: '', startDate: '', endDate: '' }"
>

View File

@@ -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>
<div>
<!-- 工具设置面板 -->
@@ -290,8 +574,8 @@
<!-- 自定义Dialog组件基于element plus -->
<el-dialog
title="自定义添加里程碑组件 - Element Plus"
v-model="showAddMilestoneDialog"
title="自定义添加里程碑组件 - Element Plus"
width="400px"
@close="newTask = { name: '', startDate: '', endDate: '' }"
>
@@ -315,291 +599,6 @@
</div>
</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>
/* 工具设置面板 */
.tool-settings-panel {

View File

@@ -10,6 +10,18 @@ defineOptions({
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 {
// 列的属性名(用于访问任务数据)
prop?: string
@@ -23,18 +35,6 @@ interface Props {
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 处理
</script>

View File

@@ -9,23 +9,23 @@ defineOptions({
name: 'TaskListContextMenu',
})
interface Props {
// 指定哪些任务类型显示此右键菜单
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
taskType?: string | string[]
}
defineProps<Props>()
// 定义 slot
defineSlots<{
// 默认插槽,接收菜单上下文对象
default?: (scope: {
default?:(scope: {
row: any
$index: number
}) => any
}>()
interface Props {
// 指定哪些任务类型显示此右键菜单
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
taskType?: string | string[]
}
// 注意:此组件不渲染任何内容,仅用于声明菜单配置
// 实际渲染由 TaskRow 处理,菜单定位和显示状态由内部自动管理
// 菜单会在点击外部或滚动时自动关闭

View File

@@ -311,21 +311,21 @@ const slotPayload = computed(() => ({
<TaskRowNameContent
:task="props.task"
:isParentTask="isParentTask"
:hasChildren="hasChildren"
:isStoryTask="isStoryTask"
:isMilestoneGroup="isMilestoneGroup"
:isMilestoneTask="isMilestoneTask"
:showTaskIcon="showTaskIcon !== false"
:formattedTimer="formattedTimer"
:isOvertime="!!isOvertime()"
:overdueDays="overdueDays()"
:overtimeText="overtimeText"
:overdueText="overdueText"
:daysText="daysText"
:hasContentSlot="hasContentSlot"
:renderColumnSlot="renderColumnSlot"
:hasColumnSlot="hasColumnSlot"
:is-parent-task="isParentTask"
:has-children="hasChildren"
:is-story-task="isStoryTask"
:is-milestone-group="isMilestoneGroup"
:is-milestone-task="isMilestoneTask"
:show-task-icon="showTaskIcon !== false"
:formatted-timer="formattedTimer"
:is-overtime="!!isOvertime()"
:overdue-days="overdueDays()"
:overtime-text="overtimeText"
:overdue-text="overdueText"
:days-text="daysText"
:has-content-slot="hasContentSlot"
:render-column-slot="renderColumnSlot"
:has-column-slot="hasColumnSlot"
>
<template #custom-task-content>
<slot

View File

@@ -56,11 +56,11 @@ defineSlots<{
<!-- 优先级2: custom-task-content Slot (向后兼容) - 仅替换文本部分 -->
<template v-else-if="hasContentSlot">
<TaskRowIcon
:isMilestoneGroup="isMilestoneGroup"
:isParentTask="isParentTask"
:hasChildren="hasChildren"
:isStoryTask="isStoryTask"
:showIcon="showTaskIcon"
:is-milestone-group="isMilestoneGroup"
:is-parent-task="isParentTask"
:has-children="hasChildren"
:is-story-task="isStoryTask"
:show-icon="showTaskIcon"
/>
<span
@@ -70,14 +70,14 @@ defineSlots<{
>
<slot name="custom-task-content" />
<TaskRowBadges
:formattedTimer="formattedTimer"
:isTimerRunning="!!task.isTimerRunning"
:timerElapsedTime="task.timerElapsedTime"
:isOvertime="isOvertime"
:overdueDays="overdueDays"
:overtimeText="overtimeText"
:overdueText="overdueText"
:daysText="daysText"
:formatted-timer="formattedTimer"
:is-timer-running="!!task.isTimerRunning"
:timer-elapsed-time="task.timerElapsedTime"
:is-overtime="isOvertime"
:overdue-days="overdueDays"
:overtime-text="overtimeText"
:overdue-text="overdueText"
:days-text="daysText"
/>
</span>
</template>
@@ -85,11 +85,11 @@ defineSlots<{
<!-- 优先级3: 默认渲染 -->
<template v-else>
<TaskRowIcon
:isMilestoneGroup="isMilestoneGroup"
:isParentTask="isParentTask"
:hasChildren="hasChildren"
:isStoryTask="isStoryTask"
:showIcon="showTaskIcon"
:is-milestone-group="isMilestoneGroup"
:is-parent-task="isParentTask"
:has-children="hasChildren"
:is-story-task="isStoryTask"
:show-icon="showTaskIcon"
/>
<span
@@ -99,14 +99,14 @@ defineSlots<{
>
{{ task.name }}
<TaskRowBadges
:formattedTimer="formattedTimer"
:isTimerRunning="!!task.isTimerRunning"
:timerElapsedTime="task.timerElapsedTime"
:isOvertime="isOvertime"
:overdueDays="overdueDays"
:overtimeText="overtimeText"
:overdueText="overdueText"
:daysText="daysText"
:formatted-timer="formattedTimer"
:is-timer-running="!!task.isTimerRunning"
:timer-elapsed-time="task.timerElapsedTime"
:is-overtime="isOvertime"
:overdue-days="overdueDays"
:overtime-text="overtimeText"
:overdue-text="overdueText"
:days-text="daysText"
/>
</span>
</template>

View File

@@ -1049,7 +1049,7 @@ const hasCircularDependency = (taskId: number, targetId: number): boolean => {
// 创建连接
const createLink = (sourceTask: Task, targetTask: Task, mode: 'predecessor' | 'successor') => {
console.log("----> hello:", {
console.log('----> hello:', {
mode,
sourceTask,
targetTask,

View File

@@ -9,23 +9,23 @@ defineOptions({
name: 'TaskBarContextMenu',
})
interface Props {
// 指定哪些任务类型显示此右键菜单
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
taskType?: string | string[]
}
defineProps<Props>()
// 定义 slot
defineSlots<{
// 默认插槽,接收菜单上下文对象
default?: (scope: {
default?:(scope: {
row: any
$index: number
}) => any
}>()
interface Props {
// 指定哪些任务类型显示此右键菜单
// 不设置时遵循现有逻辑,设置后仅对指定类型任务显示
taskType?: string | string[]
}
// 注意:此组件不渲染任何内容,仅用于声明菜单配置
// 实际渲染由 TaskBar 处理,菜单定位和显示状态由内部自动管理
// 菜单会在点击外部或滚动时自动关闭

View File

@@ -21,7 +21,7 @@ export type {
TaskListConfig,
TaskListColumnConfig,
TaskListColumnType,
ColumnFormatter
ColumnFormatter,
} from './models/configs/TaskListConfig'
export type { TaskBarConfig } from './models/configs/TaskBarConfig'
export type { ToolbarConfig } from './models/configs/ToolbarConfig'

View File

@@ -4,7 +4,7 @@ import { TaskListColumnConfig } from '@/models/configs/TaskListConfig'
* 创建基础列配置
*/
export function createColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
key: 'name',
@@ -19,7 +19,7 @@ export function createColumn(
* 创建名称列配置
*/
export function createNameColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
type: 'name',
@@ -35,7 +35,7 @@ export function createNameColumn(
* 创建前置任务列配置
*/
export function createPredecessorColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
type: 'predecessor',
@@ -51,7 +51,7 @@ export function createPredecessorColumn(
* 创建负责人列配置
*/
export function createAssigneeColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
type: 'assignee',
@@ -67,7 +67,7 @@ export function createAssigneeColumn(
* 创建开始日期列配置
*/
export function createStartDateColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
type: 'startDate',
@@ -83,7 +83,7 @@ export function createStartDateColumn(
* 创建结束日期列配置
*/
export function createEndDateColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
type: 'endDate',
@@ -99,7 +99,7 @@ export function createEndDateColumn(
* 创建进度列配置
*/
export function createProgressColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
type: 'progress',
@@ -115,7 +115,7 @@ export function createProgressColumn(
* 创建自定义列配置
*/
export function createCustomColumn(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
key: 'customField',
@@ -130,7 +130,7 @@ export function createCustomColumn(
* 创建带格式化函数的列配置
*/
export function createColumnWithFormatter(
overrides: Partial<TaskListColumnConfig> = {}
overrides: Partial<TaskListColumnConfig> = {},
): TaskListColumnConfig {
return {
key: 'formatted',

View File

@@ -36,7 +36,7 @@ export function createParentTask(overrides: Partial<Task> = {}): Task {
*/
export function createChildTask(
parentId: number,
overrides: Partial<Task> = {}
overrides: Partial<Task> = {},
): Task {
return {
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) => ({
id: index + 1,
name: `Task ${index + 1}`,

View File

@@ -8,7 +8,7 @@ import type { ComponentPublicInstance } from 'vue'
*/
export function mountComponent<T extends ComponentPublicInstance>(
component: any,
options = {}
options = {},
): VueWrapper<T> {
return mount(component, {
global: {
@@ -48,7 +48,7 @@ export function sleep(ms: number): Promise<void> {
export function triggerMouseEvent(
element: Element,
eventType: string,
options: MouseEventInit = {}
options: MouseEventInit = {},
) {
const event = new MouseEvent(eventType, {
bubbles: true,