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.
96 lines
3.4 KiB
Vue
96 lines
3.4 KiB
Vue
<template>
|
||
<UCard class="flex h-full flex-col">
|
||
<template #header>
|
||
<div class="flex flex-wrap items-center gap-3">
|
||
<div class="flex flex-col">
|
||
<span class="text-sm font-medium text-slate-200">看板阶段</span>
|
||
<span class="text-xs text-slate-400">
|
||
共 {{ totalStages }} 个阶段,分布在 {{ columns.length }} 列
|
||
</span>
|
||
</div>
|
||
<div class="flex-1" />
|
||
<UTooltip text="新增阶段">
|
||
<UButton color="primary" icon="i-heroicons-plus-circle-20-solid" @click="openStageModal()">
|
||
添加阶段
|
||
</UButton>
|
||
</UTooltip>
|
||
<UTooltip text="新增列(用于分组阶段)">
|
||
<UButton color="neutral" variant="soft" icon="i-heroicons-view-columns-20-solid" @click="addColumn">
|
||
添加列
|
||
</UButton>
|
||
</UTooltip>
|
||
</div>
|
||
</template>
|
||
|
||
<div class="relative flex-1">
|
||
<div class="flex h-full gap-4 overflow-x-auto pb-6 pr-2">
|
||
<div
|
||
v-for="(col, colIndex) in columns"
|
||
:key="`column-${colIndex}`"
|
||
class="flex min-w-[320px] flex-col gap-4"
|
||
>
|
||
<div class="flex items-center justify-between text-xs uppercase tracking-wide text-slate-400">
|
||
<span>列 {{ colIndex + 1 }}</span>
|
||
<UBadge color="neutral" variant="soft" :label="`${col.length} 个阶段`" />
|
||
</div>
|
||
<StageColumn
|
||
v-for="sid in col"
|
||
:key="sid"
|
||
:stage-id="sid"
|
||
:query="query"
|
||
:category="category"
|
||
:column-index="colIndex"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
v-if="!columns.length || !totalStages"
|
||
class="absolute inset-0 flex flex-col items-center justify-center gap-4 text-slate-400"
|
||
>
|
||
<UIcon name="i-heroicons-queue-list-20-solid" class="h-10 w-10 text-slate-600" />
|
||
<div class="text-sm">暂无阶段。点击“添加阶段”开始构建看板。</div>
|
||
</div>
|
||
</div>
|
||
</UCard>
|
||
|
||
<StageModal v-model:open="stageModalOpen" :default-column="stageModalColumn" @submit="createStage" />
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { useBoardStore } from '~/stores/board'
|
||
import StageColumn from './StageColumn.vue'
|
||
import StageModal from '~/components/dialogs/StageModal.vue'
|
||
|
||
const store = useBoardStore()
|
||
|
||
const props = defineProps<{ query: string; category: string | '' }>()
|
||
|
||
const toast = useToast()
|
||
|
||
const columns = computed(() => store.board.layout?.columns || [])
|
||
const totalStages = computed(() => store.board.stages.length)
|
||
|
||
const stageModalOpen = ref(false)
|
||
const stageModalColumn = ref(0)
|
||
|
||
function openStageModal(column = 0) {
|
||
stageModalColumn.value = column
|
||
stageModalOpen.value = true
|
||
}
|
||
|
||
function createStage(payload: { title: string; column: number }) {
|
||
stageModalOpen.value = false
|
||
const column = Math.max(0, Math.min(payload.column, columns.value.length ? columns.value.length - 1 : 0))
|
||
store.addStage(payload.title.trim(), column)
|
||
toast.add({ color: 'primary', title: `已创建阶段「${payload.title}」` })
|
||
}
|
||
|
||
function addColumn() {
|
||
if (!store.board.layout.columns) store.board.layout.columns = []
|
||
store.board.layout.columns.push([])
|
||
store.log('column-add', { count: store.board.layout.columns.length })
|
||
toast.add({ color: 'neutral', title: `新增列,当前共有 ${store.board.layout.columns.length} 列` })
|
||
}
|
||
</script>
|