新增: 项目归档

This commit is contained in:
lxy
2026-10-05 14:59:12 +08:00
parent 63c5c3d4f0
commit 24d6803ecc
19 changed files with 250 additions and 17 deletions
+52
View File
@@ -19,6 +19,7 @@
>▦</button>
</div>
<button class="btn btn-ghost" @click="openImportModal">{{ $t('projects.importHistory') }}</button>
<button class="btn btn-ghost" @click="openArchiveBox">{{ $t('projects.archiveBox') }}</button>
<button class="btn btn-ghost" @click="openTrash">{{ $t('projects.trash') }}</button>
<button class="btn btn-primary" @click="showCreateModal = true">{{ $t('projects.create') }}</button>
</div>
@@ -91,6 +92,28 @@
</div>
</div>
<!-- 归档箱模态框(归档功能 P2,V48;对齐回收站 Modal 模式:列表+恢复,无彻底删除——归档可逆) -->
<div v-if="showArchiveModal" class="modal-overlay" @click.self="showArchiveModal = false">
<div class="modal-box" style="width: 520px">
<h3 class="modal-title">{{ $t('projects.archiveBoxTitle') }}</h3>
<div v-if="store.archivedProjects.length === 0" class="empty-state" style="padding: 30px 0">{{ $t('projects.archiveBoxEmpty') }}</div>
<div v-else class="trash-list">
<div class="trash-item" v-for="p in store.archivedProjects" :key="p.id">
<div class="trash-info">
<span class="trash-name">{{ p.name }}</span>
<span class="trash-date">{{ $t('projects.archivedAt') }} {{ formatDate(p.updated_at) }}</span>
</div>
<div class="trash-actions">
<button class="btn btn-ghost btn-sm" :disabled="!!unarchivingId" @click="handleUnarchive(p.id)">{{ $t('projects.unarchive') }}</button>
</div>
</div>
</div>
<div class="modal-actions">
<button class="btn btn-ghost" @click="showArchiveModal = false">{{ $t('common.close') }}</button>
</div>
</div>
</div>
<!-- 导入历史项目模态框(F-260614-06 scan 第二步) -->
<div v-if="showImportModal" class="modal-overlay" @click.self="closeImportModal">
<div class="modal-box import-box">
@@ -162,6 +185,7 @@
:project="project"
:view="viewMode"
@delete="handleDelete"
@archive="handleArchive"
/>
</div>
@@ -348,6 +372,34 @@ async function handlePurge(project: ProjectRecord) {
}
}
// ── 归档箱(归档功能 P2,V48;卡片 📦 归档 + 归档箱 Modal 恢复,对齐回收站动线) ──
const showArchiveModal = ref(false)
const unarchivingId = ref<string | null>(null)
/** 归档项目:确认后退出主列表(可从归档箱恢复) */
async function handleArchive(project: ProjectRecord) {
if (!await confirmDialog(t('projects.confirmArchive', { name: project.name }))) return
await store.archiveProject(project.id, true)
showToast(t('projects.archivedToast'), 'info')
}
async function openArchiveBox() {
await store.loadArchivedProjects()
showArchiveModal.value = true
}
/** 归档箱内恢复:回主列表 */
async function handleUnarchive(id: string) {
if (unarchivingId.value) return
unarchivingId.value = id
try {
await store.unarchiveProject(id)
showToast(t('projects.unarchivedToast'), 'success')
} finally {
unarchivingId.value = null
}
}
// ── 加载 ──
onMounted(() => {
store.loadProjects()