Integrate the Nuxt UI component library and completely revamp the application's user interface to improve usability, aesthetics, and maintainability. - Replace all custom components and native browser dialogs (`alert`, `prompt`, `confirm`) with Nuxt UI components like `UCard`, `UButton`, `UModal`, and `UNotifications`. - Refactor the main page by extracting the sidebar into dedicated panel components: `CategoryPanel`, `BoardSummaryPanel`, and `HistoryPanel`. - Redesign all major components (Toolbar, Board, Stage, Task) for a cleaner layout and improved information hierarchy. - Implement user-friendly modals for all creation, editing, and deletion flows, providing a more consistent user experience. - Add toast notifications to provide immediate feedback for user actions.
77 lines
2.2 KiB
Vue
77 lines
2.2 KiB
Vue
<template>
|
||
<UModal v-model="open">
|
||
<UCard>
|
||
<template #header>
|
||
<div class="flex items-center gap-2">
|
||
<UIcon name="i-heroicons-plus-circle-20-solid" class="h-5 w-5 text-sky-400" />
|
||
<span class="font-semibold">添加阶段</span>
|
||
</div>
|
||
</template>
|
||
|
||
<form class="space-y-4" @submit.prevent="handleSubmit">
|
||
<UFormGroup label="阶段名称" name="title">
|
||
<UInput v-model="form.title" placeholder="例如:待办、进行中、已完成…" autofocus />
|
||
</UFormGroup>
|
||
|
||
<UFormGroup v-if="columnOptions.length" label="放置到列" name="column">
|
||
<USelectMenu
|
||
v-model="form.column"
|
||
:options="columnOptions"
|
||
value-attribute="value"
|
||
option-attribute="label"
|
||
/>
|
||
</UFormGroup>
|
||
<p v-else class="text-xs text-slate-400">
|
||
尚未创建列,新增阶段时系统会自动建立第一列。
|
||
</p>
|
||
|
||
<div class="flex justify-end gap-2">
|
||
<UButton color="neutral" variant="ghost" @click="open = false">取消</UButton>
|
||
<UButton type="submit" color="primary">创建阶段</UButton>
|
||
</div>
|
||
</form>
|
||
</UCard>
|
||
</UModal>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { useBoardStore } from '~/stores/board'
|
||
|
||
const store = useBoardStore()
|
||
const toast = useToast()
|
||
|
||
const props = defineProps<{ defaultColumn?: number }>()
|
||
const open = defineModel<boolean>('open', { required: true })
|
||
const emit = defineEmits<{ (e: 'submit', payload: { title: string; column: number }): void }>()
|
||
|
||
const form = reactive({
|
||
title: '',
|
||
column: 0
|
||
})
|
||
|
||
const columnOptions = computed(() =>
|
||
(store.board.layout?.columns || []).map((_, index) => ({
|
||
label: `列 ${index + 1}`,
|
||
value: index
|
||
}))
|
||
)
|
||
|
||
watch(
|
||
() => open.value,
|
||
(value) => {
|
||
if (!value) return
|
||
form.title = ''
|
||
const defaultColumn = props.defaultColumn ?? 0
|
||
form.column = columnOptions.value[defaultColumn] ? defaultColumn : 0
|
||
}
|
||
)
|
||
|
||
function handleSubmit() {
|
||
if (!form.title.trim()) {
|
||
toast.add({ color: 'rose', title: '请输入阶段名称' })
|
||
return
|
||
}
|
||
emit('submit', { title: form.title.trim(), column: form.column })
|
||
}
|
||
</script>
|