refactor(app): rewrite application with Nuxt 4, Pinia, and TailwindCSS
This commit replaces the original vanilla JavaScript implementation with a modern frontend stack. The entire application has been rewritten to improve maintainability, developer experience, and leverage modern web technologies. Key changes include: - Replaced plain HTML, CSS, and JS with a Nuxt 4 project structure. - Migrated state management from a global state object to a Pinia store for better organization and reactivity. - Rebuilt the UI with Vue 3 components and styled with TailwindCSS. - Changed the primary persistence mechanism from manual file I/O to automatic LocalStorage saving, while retaining import/export functionality. - All core features, including drag-and-drop, task management, and the import/merge diffing logic, have been ported to the new architecture.
This commit is contained in:
66
components/MergeModal.vue
Normal file
66
components/MergeModal.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div v-if="open" class="fixed inset-0 bg-black/60 flex items-center justify-center p-4">
|
||||
<div class="w-[1000px] max-w-[95vw] max-h-[90vh] rounded-lg border border-border bg-panel flex flex-col">
|
||||
<div class="flex items-center justify-between px-3 py-2 border-b border-border">
|
||||
<h2 class="font-semibold">导入/合并 预览</h2>
|
||||
<button class="px-2 py-1 rounded bg-slate-800/60 border border-border hover:bg-slate-800" @click="close">✕</button>
|
||||
</div>
|
||||
<div class="p-3 overflow-auto space-y-3">
|
||||
<div class="flex items-center gap-3">
|
||||
<div>
|
||||
<label class="text-sm text-slate-400 mr-2">策略</label>
|
||||
<select v-model="policy" class="px-2 py-1 rounded bg-slate-900 border border-border">
|
||||
<option value="prefer-import">冲突优先:导入文件</option>
|
||||
<option value="prefer-current">冲突优先:当前看板</option>
|
||||
</select>
|
||||
</div>
|
||||
<label class="text-sm flex items-center gap-2">
|
||||
<input type="checkbox" v-model="removeMissing" /> 同步删除在导入文件中不存在的任务/阶段
|
||||
</label>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<div class="rounded border border-border bg-slate-900 p-3">
|
||||
<div class="text-sm text-slate-400">任务新增</div>
|
||||
<div class="text-2xl font-bold">{{ diff?.tasks?.added?.length || 0 }}</div>
|
||||
</div>
|
||||
<div class="rounded border border-border bg-slate-900 p-3">
|
||||
<div class="text-sm text-slate-400">任务删除</div>
|
||||
<div class="text-2xl font-bold">{{ diff?.tasks?.removed?.length || 0 }}</div>
|
||||
</div>
|
||||
<div class="rounded border border-border bg-slate-900 p-3">
|
||||
<div class="text-sm text-slate-400">任务修改</div>
|
||||
<div class="text-2xl font-bold">{{ diff?.tasks?.modified?.length || 0 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded border border-border bg-slate-900 p-3 text-xs whitespace-pre-wrap">
|
||||
<div>文件:{{ name }}</div>
|
||||
<div>Tasks: +{{ diff?.tasks?.added?.length || 0 }} -{{ diff?.tasks?.removed?.length || 0 }} ~{{ diff?.tasks?.modified?.length || 0 }}</div>
|
||||
<div>Stages: +{{ diff?.stages?.added?.length || 0 }} -{{ diff?.stages?.removed?.length || 0 }} ~{{ diff?.stages?.modified?.length || 0 }}</div>
|
||||
<div>Layout changed: {{ diff?.layout?.changed ? 'Yes' : 'No' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 px-3 py-2 border-t border-border">
|
||||
<button class="px-3 py-1 rounded bg-accent text-slate-900 font-medium hover:brightness-110" @click="apply">应用合并</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useBoardStore } from '~/stores/board'
|
||||
|
||||
const store = useBoardStore()
|
||||
const open = defineModel<boolean>('open', { required: true })
|
||||
const imported = defineModel<any>('imported', { required: true })
|
||||
const diff = defineModel<any>('diff', { required: true })
|
||||
const name = defineModel<string>('name', { required: true })
|
||||
|
||||
const policy = ref<'prefer-import' | 'prefer-current'>('prefer-import')
|
||||
const removeMissing = ref(false)
|
||||
function close(){ open.value = false }
|
||||
function apply(){
|
||||
store.applyMerge(imported.value, policy.value, removeMissing.value)
|
||||
close()
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user