Files
kanban/components/panels/BoardSummaryPanel.vue
xiaomai 485d75820b 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.
2025-10-22 17:52:17 +08:00

74 lines
2.6 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>