feat(ui): overhaul interface with Nuxt UI

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.
This commit is contained in:
xiaomai
2025-10-22 17:52:17 +08:00
parent 2384e42933
commit 485d75820b
19 changed files with 1823 additions and 318 deletions

View File

@@ -0,0 +1,73 @@
<template>
<UCard>
<template #header>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-chart-bar-20-solid" class="h-5 w-5 text-emerald-400" />
<span class="font-semibold">看板概览</span>
</div>
<UBadge
v-if="lastModified"
:label="`更新于:${lastModified}`"
color="neutral"
variant="soft"
class="text-xs"
/>
</div>
</template>
<div class="grid grid-cols-3 gap-3 text-sm">
<UCard variant="soft" class="border border-emerald-500/10 bg-emerald-500/5 text-emerald-200">
<div class="space-y-1">
<p class="text-xs uppercase tracking-wide opacity-80">任务</p>
<p class="text-2xl font-semibold">{{ tasksCount }}</p>
</div>
</UCard>
<UCard variant="soft" class="border border-sky-500/10 bg-sky-500/5 text-sky-200">
<div class="space-y-1">
<p class="text-xs uppercase tracking-wide opacity-80">阶段</p>
<p class="text-2xl font-semibold">{{ stagesCount }}</p>
</div>
</UCard>
<UCard variant="soft" class="border border-violet-500/10 bg-violet-500/5 text-violet-200">
<div class="space-y-1">
<p class="text-xs uppercase tracking-wide opacity-80"></p>
<p class="text-2xl font-semibold">{{ columnsCount }}</p>
</div>
</UCard>
</div>
<div class="mt-4 space-y-2 text-xs text-slate-400">
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-user-circle-20-solid" class="h-4 w-4 text-slate-500" />
<span>当前操作人{{ actor || '未设置' }}</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="i-heroicons-document-duplicate-20-solid" class="h-4 w-4 text-slate-500" />
<span>文件来源{{ filename }}</span>
</div>
</div>
</UCard>
</template>
<script setup lang="ts">
import { useBoardStore } from '~/stores/board'
const store = useBoardStore()
const columnsCount = computed(() => store.board.layout?.columns?.length || 0)
const stagesCount = computed(() => store.board.stages.length)
const tasksCount = computed(() => store.board.tasks.length)
const actor = computed(() => store.board.meta?.actor || '')
const filename = computed(() => store.filename || '未命名')
const lastModified = computed(() => {
const ts = store.board.meta?.modifiedAt
if (!ts) return ''
try {
return new Intl.DateTimeFormat('zh-CN', { dateStyle: 'short', timeStyle: 'short' }).format(new Date(ts))
} catch {
return ts
}
})
</script>