diff --git a/.dev.err.log b/.dev.err.log
new file mode 100644
index 0000000..ad19159
--- /dev/null
+++ b/.dev.err.log
@@ -0,0 +1,2 @@
+⚠ Cross origin request detected from 127.0.0.1 to /_next/* resource. In a future major version of Next.js, you will need to explicitly configure "allowedDevOrigins" in next.config to allow this.
+Read more: https://nextjs.org/docs/app/api-reference/config/next-config-js/allowedDevOrigins
diff --git a/.dev.log b/.dev.log
new file mode 100644
index 0000000..100a218
--- /dev/null
+++ b/.dev.log
@@ -0,0 +1,72 @@
+
+> note-ai@1.0.0105 dev
+> next dev -p 3001
+
+▲ Next.js 16.1.1 (Turbopack)
+- Local: http://localhost:3001
+- Network: http://198.18.0.1:3001
+- Environments: .env
+
+✓ Starting...
+✓ Ready in 1339ms
+ GET / 200 in 2.5s (compile: 1896ms, proxy.ts: 145ms, render: 479ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 164ms (compile: 104ms, proxy.ts: 9ms, render: 51ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 32ms (compile: 3ms, proxy.ts: 6ms, render: 22ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 29ms (compile: 3ms, proxy.ts: 4ms, render: 21ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 29ms (compile: 3ms, proxy.ts: 5ms, render: 21ms)
+prisma:query SELECT `main`.`Page`.`id` FROM `main`.`Page` WHERE (`main`.`Page`.`id` = ? AND 1=1) LIMIT ? OFFSET ?
+prisma:query UPDATE `main`.`Page` SET `content` = ?, `updatedAt` = ? WHERE (`main`.`Page`.`id` = ? AND 1=1) RETURNING `id` AS `id`, `title` AS `title`, `content` AS `content`, `tags` AS `tags`, `icon` AS `icon`, `type` AS `type`, `parentId` AS `parentId`, `createdAt` AS `createdAt`, `updatedAt` AS `updatedAt`, `order` AS `order`, `isLocked` AS `isLocked`
+ PUT /api/pages/d039b54a-ab1c-4341-a14a-70b1b1786118 200 in 898ms (compile: 865ms, proxy.ts: 8ms, render: 25ms)
+ GET /settings 200 in 208ms (compile: 182ms, proxy.ts: 5ms, render: 21ms)
+prisma:query SELECT 1
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 42ms (compile: 7ms, proxy.ts: 14ms, render: 21ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 31ms (compile: 4ms, proxy.ts: 10ms, render: 17ms)
+✓ Compiled in 180ms
+ GET /settings 200 in 116ms (compile: 64ms, proxy.ts: 5ms, render: 47ms)
+ GET /settings 200 in 38ms (compile: 4ms, proxy.ts: 5ms, render: 29ms)
+✓ Compiled in 135ms
+ GET /settings 200 in 200ms (compile: 61ms, proxy.ts: 4ms, render: 135ms)
+prisma:query SELECT 1
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 38ms (compile: 4ms, proxy.ts: 8ms, render: 25ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 23ms (compile: 3ms, proxy.ts: 9ms, render: 11ms)
+✓ Compiled in 100ms
+prisma:query SELECT 1
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 20ms (compile: 3ms, proxy.ts: 5ms, render: 12ms)
+ GET /settings 200 in 92ms (compile: 69ms, proxy.ts: 6ms, render: 17ms)
+ GET / 200 in 129ms (compile: 101ms, proxy.ts: 6ms, render: 22ms)
+prisma:query SELECT 1
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 36ms (compile: 10ms, proxy.ts: 13ms, render: 14ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 28ms (compile: 7ms, proxy.ts: 11ms, render: 10ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 25ms (compile: 5ms, proxy.ts: 9ms, render: 11ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 18ms (compile: 3ms, proxy.ts: 7ms, render: 8ms)
+✓ Compiled in 455ms
+✓ Compiled in 121ms
+✓ Compiled in 87ms
+ GET /settings 200 in 76ms (compile: 57ms, proxy.ts: 5ms, render: 15ms)
+prisma:query SELECT 1
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 40ms (compile: 4ms, proxy.ts: 11ms, render: 26ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 38ms (compile: 5ms, proxy.ts: 8ms, render: 25ms)
+ GET / 200 in 93ms (compile: 73ms, proxy.ts: 4ms, render: 17ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 22ms (compile: 3ms, proxy.ts: 7ms, render: 12ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 20ms (compile: 6ms, proxy.ts: 6ms, render: 8ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 29ms (compile: 1969µs, proxy.ts: 4ms, render: 22ms)
+prisma:query SELECT `main`.`Page`.`id`, `main`.`Page`.`title`, `main`.`Page`.`content`, `main`.`Page`.`tags`, `main`.`Page`.`icon`, `main`.`Page`.`type`, `main`.`Page`.`parentId`, `main`.`Page`.`createdAt`, `main`.`Page`.`updatedAt`, `main`.`Page`.`order`, `main`.`Page`.`isLocked` FROM `main`.`Page` WHERE 1=1 ORDER BY `main`.`Page`.`order` ASC, `main`.`Page`.`createdAt` DESC LIMIT ? OFFSET ?
+ GET /api/pages 200 in 28ms (compile: 1741µs, proxy.ts: 4ms, render: 22ms)
diff --git a/prisma/dev.db b/prisma/dev.db
index 9c2ae12..1c28709 100644
Binary files a/prisma/dev.db and b/prisma/dev.db differ
diff --git a/src/app/globals.css b/src/app/globals.css
index 18a69b1..67f0062 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -66,11 +66,95 @@
body {
background-color: hsl(var(--background));
color: hsl(var(--foreground));
+ background-image:
+ radial-gradient(circle at 10% 10%, hsl(var(--primary) / 0.05), transparent 35%),
+ radial-gradient(circle at 90% 0%, hsl(var(--accent-foreground) / 0.04), transparent 25%);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
+@layer components {
+ .ui-card {
+ @apply rounded-2xl border border-border/70 bg-card/95 shadow-sm backdrop-blur-sm;
+ }
+
+ .ui-input {
+ @apply w-full rounded-xl border border-input bg-background/75 px-3 py-2 text-sm outline-none transition-colors placeholder:text-muted-foreground focus:border-ring focus:ring-2 focus:ring-ring/20;
+ }
+
+ .ui-select {
+ @apply w-full rounded-xl border border-input bg-background/75 px-3 py-2 text-sm outline-none transition-colors focus:border-ring focus:ring-2 focus:ring-ring/20;
+ }
+
+ .ui-btn {
+ @apply inline-flex items-center justify-center gap-2 rounded-xl px-4 py-2 text-sm font-medium transition-all active:scale-[0.98];
+ }
+
+ .ui-btn-primary {
+ @apply ui-btn bg-primary text-primary-foreground hover:opacity-90 shadow-sm;
+ }
+
+ .ui-btn-secondary {
+ @apply ui-btn bg-secondary text-secondary-foreground hover:bg-secondary/80;
+ }
+
+ .ui-btn-danger {
+ @apply ui-btn bg-destructive text-destructive-foreground hover:opacity-90;
+ }
+
+ .ui-icon-btn {
+ @apply inline-flex h-9 w-9 items-center justify-center rounded-lg border border-transparent text-muted-foreground transition-colors hover:border-border hover:bg-muted/60 hover:text-foreground;
+ }
+
+ .ui-kbd {
+ @apply inline-flex h-5 select-none items-center gap-1 rounded border border-border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground;
+ }
+
+ .ui-enter {
+ animation: ui-enter 220ms ease-out both;
+ }
+
+ .ui-enter-delayed {
+ animation: ui-enter 300ms ease-out both;
+ }
+
+ .ui-float {
+ animation: ui-float 4s ease-in-out infinite;
+ }
+}
+
+@keyframes ui-enter {
+ from {
+ opacity: 0;
+ transform: translateY(6px) scale(0.99);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+@keyframes ui-float {
+ 0%,
+ 100% {
+ transform: translateY(0);
+ }
+ 50% {
+ transform: translateY(-4px);
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .ui-enter,
+ .ui-enter-delayed,
+ .ui-float,
+ .animate-in {
+ animation: none !important;
+ transition: none !important;
+ }
+}
+
/* Editor Specific Styles for Notion-like feel */
.ProseMirror {
outline: none;
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index a7bb326..2ac2944 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,4 +1,4 @@
-import type { Metadata } from "next";
+import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { ThemeProvider } from "@/components/theme-provider";
@@ -7,8 +7,8 @@ import { ConfirmProvider } from "@/components/confirm-provider";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
- title: "NoteAI - 轻量级个人笔记网站",
- description: "基于 Next.js 的 AI 驱动笔记应用",
+ title: "NoteAI - 轻量级个人笔记应用",
+ description: "基于 Next.js 的 AI 驱动笔记工具",
};
export default function RootLayout({
@@ -19,12 +19,7 @@ export default function RootLayout({
return (
-
+
{children}
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
index 8406200..eee5d14 100644
--- a/src/app/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -39,9 +39,9 @@ export default function LoginPage() {
return (
-
+
-
+
欢迎回来
@@ -57,7 +57,7 @@ export default function LoginPage() {
placeholder="访问密码"
value={password}
onChange={(e) => setPassword(e.target.value)}
- className="w-full pl-10 pr-4 py-3 bg-muted/50 border rounded-xl focus:ring-2 focus:ring-primary outline-none transition-all"
+ className="ui-input pl-10 pr-4 py-3"
required
/>
@@ -79,7 +79,7 @@ export default function LoginPage() {