From aa3a011e9f63baadb9192d72f93a2fbb777db641 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sat, 27 Jun 2026 03:28:06 +0800 Subject: [PATCH] feat: add ideas API with CRUD operations and database schema - Implemented GET endpoint for listing ideas with pagination. - Implemented POST endpoint for creating new ideas with validation. - Added service functions for listing and creating ideas, including random color assignment. - Created database schema for ideas in the migration files. - Updated migration journal to reflect new versioning and changes. --- .env.example | 2 +- app/components/index/IdeaCard.vue | 207 +++ app/pages/index/index.vue | 498 ++++++- db.sqlite | 0 packages/drizzle-pkg/db.sqlite | Bin 282624 -> 282624 bytes packages/drizzle-pkg/lib/schema/content.ts | 18 + .../migrations/0007_add_card_content.sql | 1 - .../drizzle-pkg/migrations/0008_chat_messages.sql | 8 - .../migrations/0008_magical_black_knight.sql | 10 + packages/drizzle-pkg/migrations/0009_ideas.sql | 9 + .../migrations/0010_broken_machine_man.sql | 1 + .../drizzle-pkg/migrations/meta/0008_snapshot.json | 1303 +++++++++++++++++++ .../drizzle-pkg/migrations/meta/0010_snapshot.json | 1364 ++++++++++++++++++++ packages/drizzle-pkg/migrations/meta/_journal.json | 20 +- server/api/ideas/index.get.ts | 10 + server/api/ideas/index.post.ts | 18 + server/service/ideas/index.ts | 106 ++ 17 files changed, 3534 insertions(+), 41 deletions(-) create mode 100644 app/components/index/IdeaCard.vue delete mode 100644 db.sqlite delete mode 100644 packages/drizzle-pkg/migrations/0007_add_card_content.sql delete mode 100644 packages/drizzle-pkg/migrations/0008_chat_messages.sql create mode 100644 packages/drizzle-pkg/migrations/0008_magical_black_knight.sql create mode 100644 packages/drizzle-pkg/migrations/0009_ideas.sql create mode 100644 packages/drizzle-pkg/migrations/0010_broken_machine_man.sql create mode 100644 packages/drizzle-pkg/migrations/meta/0008_snapshot.json create mode 100644 packages/drizzle-pkg/migrations/meta/0010_snapshot.json create mode 100644 server/api/ideas/index.get.ts create mode 100644 server/api/ideas/index.post.ts create mode 100644 server/service/ideas/index.ts diff --git a/.env.example b/.env.example index 5a95d73..7e831e4 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,6 @@ DATABASE_URL=file:./db.sqlite STATIC_DIR=static UPLOAD_SUBDIR=upload -NITRO_PORT=3399 SCHEDULER_MAX_CONCURRENCY=5 SCHEDULER_LOG_RETENTION_DAYS=30 BOOTSTRAP_ADMIN_USERNAME=admin @@ -11,4 +10,5 @@ GITHUB_CLIENT_SECRET=your_github_client_secret GITEA_CLIENT_ID=your_gitea_client_id GITEA_CLIENT_SECRET=your_gitea_client_secret GITEA_URL=https://gitea.com +NITRO_PORT=3399 APP_URL=http://localhost:3399 \ No newline at end of file diff --git a/app/components/index/IdeaCard.vue b/app/components/index/IdeaCard.vue new file mode 100644 index 0000000..f558341 --- /dev/null +++ b/app/components/index/IdeaCard.vue @@ -0,0 +1,207 @@ + + + + + diff --git a/app/pages/index/index.vue b/app/pages/index/index.vue index d6d5b1d..100b90a 100644 --- a/app/pages/index/index.vue +++ b/app/pages/index/index.vue @@ -2,57 +2,499 @@ definePageMeta({ layout: 'home', }) + +const { $toast } = useNuxtApp() + +// ── Form state ── +const author = ref('') +const content = ref('') +const platform = ref(null) +const submitting = ref(false) + +// Platform options +const platforms = ['网站', 'Windows 应用', 'App', '小程序', '插件/扩展', '命令行工具', '其他'] + +// ── Ideas list ── +const page = ref(1) +const { data, refresh, pending } = await useFetch('/api/ideas', { + query: computed(() => ({ page: page.value, pageSize: 30 })), +}) + +const ideas = computed(() => (data.value as any)?.data?.items ?? []) +const hasMore = computed(() => (data.value as any)?.data?.hasMore ?? false) + +// ── Detail dialog ── +const selectedIdea = ref(null) +const showDetail = ref(false) + +function openDetail(idea: any) { + selectedIdea.value = idea + showDetail.value = true +} + +function closeDetail() { + showDetail.value = false +} + +// ── Submit ── +async function submitIdea() { + const trimmedAuthor = author.value.trim() + const trimmedContent = content.value.trim() + + if (!trimmedContent) { + $toast.warning('请输入你的想法') + return + } + + submitting.value = true + try { + await $fetch('/api/ideas', { + method: 'POST', + body: { author: trimmedAuthor, content: trimmedContent, platform: platform.value }, + }) + author.value = '' + content.value = '' + platform.value = null + $toast.success('想法已发布 ✨') + await refresh() + } catch (e: any) { + $toast.error(e?.data?.message || '发布失败,请重试') + } finally { + submitting.value = false + } +} + +// ── Load more ── +async function loadMore() { + page.value++ + await refresh() +}