From 2fae90b597575c791f15f500e5b0174f855dd335 Mon Sep 17 00:00:00 2001 From: john Date: Fri, 5 Jun 2026 10:10:40 +0800 Subject: [PATCH] Add word list edit mode with bulk delete and fix word deletion Show checkboxes and batch actions only after entering edit mode, and delete related quiz records before removing words to avoid foreign key failures. Co-authored-by: Cursor --- backend/services/word_service.py | 6 +- frontend/src/components/WordCard.vue | 52 +++++-- frontend/src/pages/WordLibrary.vue | 200 ++++++++++++++++++++++++++- 3 files changed, 246 insertions(+), 12 deletions(-) diff --git a/backend/services/word_service.py b/backend/services/word_service.py index d91b22a..3fd9113 100644 --- a/backend/services/word_service.py +++ b/backend/services/word_service.py @@ -4,7 +4,7 @@ from typing import Optional from fastapi import HTTPException from sqlalchemy.orm import Session -from models import Word, User +from models import QuizRecord, Word, User def utc_now_iso() -> str: @@ -68,6 +68,10 @@ class WordService: def delete_word(self, db: Session, user: User, word_id: int) -> None: word = self.get_word(db, user, word_id) + db.query(QuizRecord).filter(QuizRecord.word_id == word.id).delete( + synchronize_session=False + ) + db.flush() db.delete(word) db.commit() diff --git a/frontend/src/components/WordCard.vue b/frontend/src/components/WordCard.vue index d17d357..15daafa 100644 --- a/frontend/src/components/WordCard.vue +++ b/frontend/src/components/WordCard.vue @@ -4,10 +4,13 @@ import { formatTrainSeconds } from '../composables/useQuizTimer' defineProps<{ word: Word + selectable?: boolean + selected?: boolean }>() defineEmits<{ delete: [id: number] + 'toggle-select': [id: number] }>() const statusMap: Record = { @@ -33,14 +36,22 @@ function formatEnteredAt(iso: string) {