统一组件slot的使用方式

This commit is contained in:
qiuchengw
2025-09-25 10:31:49 +08:00
parent b83e643060
commit 69ec4df7da
3 changed files with 69 additions and 23 deletions
+41 -21
View File
@@ -25,6 +25,25 @@ interface Props {
currentTimeScale?: TimelineScale
}
interface TaskStatus {
type: string
color: string
bgColor: string
borderColor: string
}
interface TaskBarSlotProps {
type: string
task: Task
status: TaskStatus
statusType: string
isParent?: boolean
progress: number
currentTimeScale?: TimelineScale
rowHeight: number
dayWidth: number
}
const props = defineProps<Props>()
const emit = defineEmits([
@@ -42,13 +61,17 @@ const emit = defineEmits([
'context-menu',
])
defineSlots<{
'custom-task-content'(props: TaskBarSlotProps): unknown
}>()
const slots = useSlots()
const { getTranslation } = useI18n()
const t = (key: string): string => {
return getTranslation(key)
}
const hasContentSlot = computed(() => Boolean(slots.content))
const hasContentSlot = computed(() => Boolean(slots['custom-task-content']))
// 日期工具函数 - 处理时区安全的日期创建和操作
const createLocalDate = (dateString: string | Date | undefined | null): Date | null => {
@@ -340,6 +363,19 @@ const taskStatus = computed(() => {
}
})
// Slot payload for content slot - 使用 v-bind 方式传递所有属性
const slotPayload = computed(() => ({
type: 'task-bar',
task: props.task,
status: taskStatus.value,
statusType: taskStatus.value.type,
isParent: props.isParent ?? false,
progress: props.task.progress || 0,
currentTimeScale: props.currentTimeScale,
rowHeight: props.rowHeight,
dayWidth: props.dayWidth,
}))
// 判断是否已完成
const isCompleted = computed(() => (props.task.progress || 0) >= 100)
@@ -1320,16 +1356,8 @@ onUnmounted(() => {
<div v-if="isParent" class="parent-label">
<slot
v-if="hasContentSlot"
name="content"
type="task-bar"
:task="task"
:status="taskStatus"
:status-type="taskStatus.type"
:is-parent="isParent"
:progress="task.progress || 0"
:current-time-scale="currentTimeScale"
:row-height="rowHeight"
:day-width="dayWidth"
name="custom-task-content"
v-bind="slotPayload"
/>
<template v-else>
{{ task.name }} ({{ task.progress || 0 }}%)
@@ -1363,16 +1391,8 @@ onUnmounted(() => {
<!-- 任务名称 -->
<slot
v-if="hasContentSlot"
name="content"
type="task-bar"
:task="task"
:status="taskStatus"
:status-type="taskStatus.type"
:is-parent="isParent"
:progress="task.progress || 0"
:current-time-scale="currentTimeScale"
:row-height="rowHeight"
:day-width="dayWidth"
name="custom-task-content"
v-bind="slotPayload"
/>
<div v-else class="task-name" :style="getNameStyles()">
{{ task.name }}
+27 -1
View File
@@ -6,6 +6,28 @@ import type { Task } from '../models/classes/Task'
import type { TaskListColumnConfig } from '../models/configs/TaskListConfig'
import TaskContextMenu from './TaskContextMenu.vue'
interface TaskRowSlotProps {
isRowContent: boolean
task: Task
level: number
indent: string
isHovered: boolean
hoveredTaskId: number | null
isParent: boolean
hasChildren: boolean
collapsed: boolean
formattedTimer: string
timerRunning: boolean
timerElapsed: number
isOvertime: number | boolean | undefined
overdueDays: number
overtimeText: string
overdueText: string
daysText: string
progressClass: string
type?: string
}
interface Props {
task: Task
level: number
@@ -26,6 +48,10 @@ const emit = defineEmits([
'add-successor',
'delete',
])
defineSlots<{
'custom-task-content'(props: TaskRowSlotProps): unknown
}>()
const { t } = useI18n()
const overtimeText = computed(() => t.value?.overtime ?? '')
const overdueText = computed(() => t.value?.overdue ?? '')
@@ -466,7 +492,7 @@ onUnmounted(() => {
@delete="handleTaskDelete"
>
<template v-if="hasContentSlot" #custom-task-content="slotProps">
<slot name="custom-task-content" v-bind="slotProps" />
<slot name="custom-task-content" v-bind="(slotProps as TaskRowSlotProps)" />
</template>
</TaskRow>
</template>
+1 -1
View File
@@ -2750,7 +2750,7 @@ const handleAddSuccessor = (task: Task) => {
@add-successor="handleAddSuccessor"
@delete="handleTaskDelete"
>
<template v-if="$slots['custom-task-content']" #content="barScope">
<template v-if="$slots['custom-task-content']" #custom-task-content="barScope">
<slot name="custom-task-content" v-bind="barScope" />
</template>
</TaskBar>