fix(frontend): 修复任务关联字段持久化

This commit is contained in:
2026-08-29 23:59:11 +08:00
parent 4f9ebc55ec
commit d6f6b7e6e2
4 changed files with 9 additions and 11 deletions
@@ -6,8 +6,6 @@ const taskStore = useTaskStore()
<template> <template>
<div class="sidebar-panel filters"> <div class="sidebar-panel filters">
<div class="field"><label>状态</label><select v-model="taskStore.filterStatus" class="select"><option value="all">全部</option><option value="todo">待办</option><option value="in_progress">进行中</option><option value="done">已完成</option><option value="cancelled">已取消</option></select></div> <div class="field"><label>状态</label><select v-model="taskStore.filterStatus" class="select"><option value="all">全部</option><option value="todo">待办</option><option value="in_progress">进行中</option><option value="done">已完成</option><option value="cancelled">已取消</option></select></div>
<div class="field"><label>优先级</label><select v-model="taskStore.filterPriority" class="select"><option value="all">全部</option><option value="high">高</option><option value="medium">中</option><option value="low"></option></select></div>
<div class="field"><label>来源</label><select v-model="taskStore.filterSource" class="select"><option value="all">全部</option><option value="user">用户</option><option value="note">笔记</option><option value="agent">Agent</option></select></div>
<div class="task-counts"><p><span>待办</span><strong>{{ taskStore.todoTasks.length }}</strong></p><p><span>进行中</span><strong>{{ taskStore.inProgressTasks.length }}</strong></p><p><span>已完成</span><strong>{{ taskStore.doneTasks.length }}</strong></p></div> <div class="task-counts"><p><span>待办</span><strong>{{ taskStore.todoTasks.length }}</strong></p><p><span>进行中</span><strong>{{ taskStore.inProgressTasks.length }}</strong></p><p><span>已完成</span><strong>{{ taskStore.doneTasks.length }}</strong></p></div>
</div> </div>
</template> </template>
+6 -6
View File
@@ -7,17 +7,17 @@ const taskStore = useTaskStore()
const showForm = ref(false) const showForm = ref(false)
const editingId = ref<string | null>(null) const editingId = ref<string | null>(null)
const actionError = ref('') const actionError = ref('')
const form = reactive({ title: '', description: '', priority: 'medium' as TaskItem['priority'], due_date: '', note_id: '' }) const form = reactive({ title: '', description: '', due_date: '', note_id: '' })
onMounted(() => { void taskStore.loadTasks() }) onMounted(() => { void taskStore.loadTasks() })
function resetForm() { editingId.value = null; form.title = ''; form.description = ''; form.priority = 'medium'; form.due_date = ''; form.note_id = '' } function resetForm() { editingId.value = null; form.title = ''; form.description = ''; form.due_date = ''; form.note_id = '' }
function editTask(task: TaskItem) { editingId.value = task.task_id; Object.assign(form, { title: task.title, description: task.description ?? '', priority: task.priority, due_date: task.due_date?.slice(0, 16) ?? '', note_id: task.note_id ?? '' }); showForm.value = true } function editTask(task: TaskItem) { editingId.value = task.task_id; Object.assign(form, { title: task.title, description: task.description ?? '', due_date: task.due_date?.slice(0, 16) ?? '', note_id: task.note_id ?? '' }); showForm.value = true }
async function saveTask() { async function saveTask() {
actionError.value = '' actionError.value = ''
try { try {
if (editingId.value) await taskStore.updateTask(editingId.value, { ...form, due_date: form.due_date || undefined }) if (editingId.value) await taskStore.updateTask(editingId.value, { ...form, due_date: form.due_date || undefined, note_id: form.note_id || null })
else await taskStore.createTask({ ...form, due_date: form.due_date || undefined, note_id: form.note_id || undefined }) else await taskStore.createTask({ ...form, due_date: form.due_date || undefined, note_id: form.note_id || undefined })
showForm.value = false; resetForm() showForm.value = false; resetForm()
} catch (error) { actionError.value = error instanceof Error ? error.message : '任务保存失败' } } catch (error) { actionError.value = error instanceof Error ? error.message : '任务保存失败' }
@@ -40,12 +40,12 @@ async function remove(task: TaskItem) {
<div v-if="taskStore.filteredTasks.length" class="task-list"> <div v-if="taskStore.filteredTasks.length" class="task-list">
<article v-for="task in taskStore.filteredTasks" :key="task.task_id" class="item-card task-card"> <article v-for="task in taskStore.filteredTasks" :key="task.task_id" class="item-card task-card">
<button class="status-check" :class="{ done: task.status === 'done' }" title="切换完成状态" @click="setStatus(task, task.status === 'done' ? 'todo' : 'done')">{{ task.status === 'done' ? '' : '' }}</button> <button class="status-check" :class="{ done: task.status === 'done' }" title="切换完成状态" @click="setStatus(task, task.status === 'done' ? 'todo' : 'done')">{{ task.status === 'done' ? '' : '' }}</button>
<div class="task-content"><div class="task-title"><strong :class="{ completed: task.status === 'done' }">{{ task.title }}</strong><span class="badge" :class="{ error: task.priority === 'high', warning: task.priority === 'medium' }">{{ task.priority }}</span><span class="badge info">{{ task.source }}</span></div><p v-if="task.description" class="muted">{{ task.description }}</p><div class="subtle"><span>{{ task.status }}</span><span v-if="task.due_date">截止 {{ new Date(task.due_date).toLocaleString() }}</span><span v-if="task.note_title">关联{{ task.note_title }}</span></div></div> <div class="task-content"><div class="task-title"><strong :class="{ completed: task.status === 'done' }">{{ task.title }}</strong></div><p v-if="task.description" class="muted">{{ task.description }}</p><div class="subtle"><span>{{ task.status }}</span><span v-if="task.due_date">截止 {{ new Date(task.due_date).toLocaleString() }}</span><span v-if="task.note_id">关联 Note{{ task.note_id }}</span></div></div>
<div class="inline-actions"><button class="icon-button" @click="editTask(task)">编辑</button><button class="button-danger" @click="remove(task)">删除</button></div> <div class="inline-actions"><button class="icon-button" @click="editTask(task)">编辑</button><button class="button-danger" @click="remove(task)">删除</button></div>
</article> </article>
</div> </div>
<div v-else class="empty-state"><div><strong>{{ taskStore.isLoading ? '正在加载任务…' : '没有符合条件的任务' }}</strong><p>创建一项任务或调整左侧筛选条件</p></div></div> <div v-else class="empty-state"><div><strong>{{ taskStore.isLoading ? '正在加载任务…' : '没有符合条件的任务' }}</strong><p>创建一项任务或调整左侧筛选条件</p></div></div>
<div v-if="showForm" class="modal-backdrop" @click.self="showForm = false"><div class="modal"><h2>{{ editingId ? '编辑任务' : '新建任务' }}</h2><form @submit.prevent="saveTask"><div class="field"><label>标题</label><input v-model="form.title" class="input" required /></div><div class="field"><label>描述</label><textarea v-model="form.description" class="textarea" /></div><div class="form-grid"><div class="field"><label>优先级</label><select v-model="form.priority" class="select"><option value="high">高</option><option value="medium">中</option><option value="low">低</option></select></div><div class="field"><label>截止时间</label><input v-model="form.due_date" class="input" type="datetime-local" /></div></div><div class="field"><label>关联 Note ID</label><input v-model="form.note_id" class="input" /></div><div class="inline-actions"><button class="button-primary">保存</button><button type="button" class="button-secondary" @click="showForm = false">取消</button></div></form></div></div> <div v-if="showForm" class="modal-backdrop" @click.self="showForm = false"><div class="modal"><h2>{{ editingId ? '编辑任务' : '新建任务' }}</h2><form @submit.prevent="saveTask"><div class="field"><label>标题</label><input v-model="form.title" class="input" required /></div><div class="field"><label>描述</label><textarea v-model="form.description" class="textarea" /></div><div class="field"><label>截止时间</label><input v-model="form.due_date" class="input" type="datetime-local" /></div><div class="field"><label>关联 Note ID</label><input v-model="form.note_id" class="input" /></div><div class="inline-actions"><button class="button-primary">保存</button><button type="button" class="button-secondary" @click="showForm = false">取消</button></div></form></div></div>
</section> </section>
</template> </template>
+2 -1
View File
@@ -46,13 +46,14 @@ export async function createTask(data: {
export async function updateTask( export async function updateTask(
taskId: string, taskId: string,
data: Partial<Pick<TaskItem, 'title' | 'description' | 'status' | 'priority' | 'due_date'>> data: Partial<Pick<TaskItem, 'title' | 'description' | 'status' | 'due_date'>> & { note_id?: string | null }
): Promise<TaskItem> { ): Promise<TaskItem> {
return toTask(await apiClient.patch<ApiTask>(`/api/tasks/${taskId}`, { return toTask(await apiClient.patch<ApiTask>(`/api/tasks/${taskId}`, {
title: data.title, title: data.title,
description: data.description, description: data.description,
status: data.status, status: data.status,
due_at: data.due_date, due_at: data.due_date,
note_id: data.note_id,
})) }))
} }
+1 -2
View File
@@ -39,12 +39,11 @@ export const useTaskStore = defineStore('task', () => {
async function createTask(data: { title: string; description?: string; priority?: TaskPriority; due_date?: string; note_id?: string }) { async function createTask(data: { title: string; description?: string; priority?: TaskPriority; due_date?: string; note_id?: string }) {
const newTask = await createTaskRequest(data) const newTask = await createTaskRequest(data)
newTask.priority = data.priority || 'medium'
tasks.value.unshift(newTask) tasks.value.unshift(newTask)
return newTask return newTask
} }
async function updateTask(taskId: string, data: Partial<Pick<TaskItem, 'title' | 'description' | 'status' | 'priority' | 'due_date'>>) { async function updateTask(taskId: string, data: Partial<Pick<TaskItem, 'title' | 'description' | 'status' | 'due_date'>> & { note_id?: string | null }) {
const task = tasks.value.find((t) => t.task_id === taskId) const task = tasks.value.find((t) => t.task_id === taskId)
if (task) { if (task) {
const updated = await updateTaskRequest(taskId, data) const updated = await updateTaskRequest(taskId, data)