v1.0.9 - Add Story and sub-tasks deletion logic; l18n updates; GanttConfirmDialog updates

This commit is contained in:
LINING-PC\lining
2025-07-04 21:41:06 +08:00
parent 06c049f49c
commit 94ee66cbb4
15 changed files with 651 additions and 292 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ interface Props {
// 是否使用默认的TaskDrawer
useDefaultDrawer?: boolean
// 自定义删除处理器API
onTaskDelete?: (task: Task) => void
onTaskDelete?: (task: Task, deleteChildren?: boolean) => void
// 里程碑保存处理器API
onMilestoneSave?: (milestone: Task) => void
// 里程碑删除处理器API
+34 -8
View File
@@ -7,10 +7,15 @@ const props = defineProps({
message: { type: String, default: '' },
confirmText: { type: String, default: '确认' },
cancelText: { type: String, default: '取消' },
yesText: { type: String, default: '是' },
noText: { type: String, default: '否' },
type: { type: String, default: 'confirm-cancel' }, // 'confirm-cancel' | 'yes-no-cancel'
})
const emit = defineEmits(['confirm', 'cancel'])
const emit = defineEmits(['confirm', 'cancel', 'yes', 'no'])
const onConfirm = () => emit('confirm')
const onCancel = () => emit('cancel')
const onYes = () => emit('yes')
const onNo = () => emit('no')
</script>
<template>
@@ -23,12 +28,27 @@ const onCancel = () => emit('cancel')
<p>{{ props.message }}</p>
</div>
<div class="gantt-confirm-footer">
<button type="button" class="btn btn-default" @click="onCancel">
{{ props.cancelText }}
</button>
<button type="button" class="btn btn-danger" @click="onConfirm">
{{ props.confirmText }}
</button>
<template v-if="props.type === 'yes-no-cancel'">
<button type="button" class="btn btn-default" @click="onCancel">
{{ props.cancelText }}
</button>
<div class="gantt-confirm-footer-right">
<button type="button" class="btn btn-warning" @click="onNo">
{{ props.noText }}
</button>
<button type="button" class="btn btn-danger" @click="onYes">
{{ props.yesText }}
</button>
</div>
</template>
<template v-else>
<button type="button" class="btn btn-default" @click="onCancel">
{{ props.cancelText }}
</button>
<button type="button" class="btn btn-danger" @click="onConfirm">
{{ props.confirmText }}
</button>
</template>
</div>
</div>
</div>
@@ -73,7 +93,13 @@ const onCancel = () => emit('cancel')
}
.gantt-confirm-footer {
display: flex;
justify-content: flex-end;
justify-content: space-between;
align-items: center;
gap: 12px;
}
.gantt-confirm-footer-right {
display: flex;
gap: 12px;
}
+55 -5
View File
@@ -25,7 +25,7 @@ const emit = defineEmits<{
'update:visible': [value: boolean]
submit: [task: Task]
close: []
delete: [task: Task]
delete: [task: Task, deleteChildren?: boolean]
}>()
const { t } = useI18n()
@@ -35,6 +35,19 @@ const submitting = ref(false)
const isVisible = ref(props.visible)
const showDeleteConfirm = ref(false)
// 根据任务类型确定dialog类型
const dialogType = computed(() => {
return props.task?.type === 'story' ? 'yes-no-cancel' : 'confirm-cancel'
})
// 根据任务类型确定dialog消息
const dialogMessage = computed(() => {
if (props.task?.type === 'story') {
return t.value.confirmDeleteStory.replace('{name}', props.task?.name || '')
}
return t.value.confirmDeleteTask.replace('{name}', props.task?.name || '')
})
// 表单数据
const formData = reactive<Task>({
id: 0, // 默认值,创建时会被重新分配
@@ -156,7 +169,7 @@ const handleProgressKeydown = (event: KeyboardEvent) => {
]
// 允许数字
const isNumber = /^[0-9]$/.test(key)
const isNumber = /^\d$/.test(key)
const isAllowedKey = allowedKeys.includes(key)
// 如果是Ctrl+A、Ctrl+C、Ctrl+V、Ctrl+X等组合键,允许通过
@@ -167,7 +180,6 @@ const handleProgressKeydown = (event: KeyboardEvent) => {
// 如果不是允许的按键或数字,阻止输入
if (!isNumber && !isAllowedKey) {
event.preventDefault()
return
}
}
@@ -311,6 +323,39 @@ const cancelDelete = () => {
showDeleteConfirm.value = false
}
// Story删除:选择"是" - 删除story及其所有子任务
const handleDeleteYes = () => {
showDeleteConfirm.value = false
if (props.task && props.isEdit) {
try {
submitting.value = true
emit('delete', props.task, true) // 传递true表示删除所有子任务
handleClose()
} catch (error) {
showMessage(t.value.taskDeleteFailed, 'error')
} finally {
submitting.value = false
}
}
}
// Story删除:选择"否" - 仅删除story,保留子任务
// Story删除:选择"否" - 仅删除story,保留子任务
const handleDeleteNo = () => {
showDeleteConfirm.value = false
if (props.task && props.isEdit) {
try {
submitting.value = true
emit('delete', props.task, false) // 传递false表示仅删除story
handleClose()
} catch (error) {
showMessage(t.value.taskDeleteFailed, 'error')
} finally {
submitting.value = false
}
}
}
// 获取任务数据的事件处理器
const handleTasksChanged = (event: CustomEvent) => {
allTasks.value = event.detail || []
@@ -390,7 +435,7 @@ watch(
<div class="form-group">
<label class="form-label" for="task-assignee">{{ t.assignee }}</label>
<select id="task-assignee" v-model="formData.assignee" class="form-select">
<option value="">请选择负责人</option>
<option value="">{{ t.selectAssignee }}</option>
<option value="张三">张三</option>
<option value="李四">李四</option>
<option value="王五">王五</option>
@@ -546,10 +591,15 @@ watch(
<GanttConfirmDialog
:visible="showDeleteConfirm"
:title="t.delete"
:message="t.confirmDeleteTask.replace('{name}', task?.name || '')"
:type="dialogType"
:message="dialogMessage"
:confirm-text="t.confirm"
:cancel-text="t.cancel"
:yes-text="t.storyDeleteYes"
:no-text="t.storyDeleteNo"
@confirm="confirmDelete"
@yes="handleDeleteYes"
@no="handleDeleteNo"
@cancel="cancelDelete"
/>
</div>
+5 -5
View File
@@ -22,7 +22,7 @@ interface Props {
// 是否使用默认的TaskDrawer
useDefaultDrawer?: boolean
// 自定义删除处理器
onTaskDelete?: (task: Task) => void
onTaskDelete?: (task: Task, deleteChildren?: boolean) => void
// 里程碑保存事件处理器
onMilestoneSave?: (milestone: Task) => void
// 新增:外部传入的时间轴起止
@@ -810,12 +810,12 @@ onUnmounted(() => {
}
})
const handleTaskDelete = (taskId: number) => {
const handleTaskDelete = (taskId: number, deleteChildren?: boolean) => {
// 调用父组件传入的删除处理器
if (props.onTaskDelete && typeof props.onTaskDelete === 'function') {
const taskToDelete = tasks.value.find(task => task.id === taskId)
if (taskToDelete) {
props.onTaskDelete(taskToDelete)
props.onTaskDelete(taskToDelete, deleteChildren)
}
}
@@ -833,8 +833,8 @@ const handleTaskDelete = (taskId: number) => {
}
// TaskDrawer删除事件适配器
const handleDrawerTaskDelete = (task: Task) => {
handleTaskDelete(task.id)
const handleDrawerTaskDelete = (task: Task, deleteChildren?: boolean) => {
handleTaskDelete(task.id, deleteChildren)
}
// 暴露公共API