From 04d6a2f9af11ac295b1a08c402851ea63ff0f008 Mon Sep 17 00:00:00 2001 From: maojindao55 Date: Wed, 26 Mar 2025 20:00:31 +0800 Subject: [PATCH] add user db --- devrun.sh | 1 + functions/api/_middleware.js | 2 +- functions/api/login.ts | 7 +-- functions/api/sendCode.ts | 5 +- functions/api/test-db.ts | 32 ++++++++++ init-db.sh | 41 +++++++++++++ src/pages/chat/components/Sidebar.tsx | 4 ++ src/pages/chat/components/UserSection.tsx | 73 +++++++++++++++++++++++ 8 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 functions/api/test-db.ts create mode 100644 init-db.sh create mode 100644 src/pages/chat/components/UserSection.tsx diff --git a/devrun.sh b/devrun.sh index 40cad01..c573936 100644 --- a/devrun.sh +++ b/devrun.sh @@ -1 +1,2 @@ +# 启动开发服务器 wrangler pages dev -- npm run dev \ No newline at end of file diff --git a/functions/api/_middleware.js b/functions/api/_middleware.js index fe638db..cfa42fb 100644 --- a/functions/api/_middleware.js +++ b/functions/api/_middleware.js @@ -58,7 +58,7 @@ export async function onRequest(context) { const request = context.request; const env = context.env; //跳过登录页面 - if (request.url.includes('/login') || request.url.includes('/sendcode') || request.url.includes('/login')) { + if (request.url.includes('/login') || request.url.includes('/sendcode') || request.url.includes('/login') || request.url.includes('/test-db')) { return await context.next(); } const authHeader = request.headers.get('Authorization'); diff --git a/functions/api/login.ts b/functions/api/login.ts index b97c933..288d049 100644 --- a/functions/api/login.ts +++ b/functions/api/login.ts @@ -1,7 +1,7 @@ interface Env { bgkv: KVNamespace; JWT_SECRET: string; - DB: D1Database; + bgdb: D1Database; } export const onRequestPost: PagesFunction = async (context) => { @@ -46,7 +46,6 @@ export const onRequestPost: PagesFunction = async (context) => { // 从 KV 中获取存储的验证码 const storedCode = await env.bgkv.get(`sms:${phone}`); - if (!storedCode || storedCode !== code) { return new Response( JSON.stringify({ @@ -63,13 +62,13 @@ export const onRequestPost: PagesFunction = async (context) => { } // 验证成功后,处理用户数据 - const db = env.DB; // 假设你的 D1 数据库实例名为 DB - + const db = env.bgdb; // 假设你的 D1 数据库实例名为 DB // 查询用户是否存在 const existingUser = await db.prepare( "SELECT id, phone, nickname FROM users WHERE phone = ?" ).bind(phone).first(); + console.log('existingUser', existingUser); let userId; if (!existingUser) { // 用户不存在,创建新用户 diff --git a/functions/api/sendCode.ts b/functions/api/sendCode.ts index 3710215..2cca299 100644 --- a/functions/api/sendCode.ts +++ b/functions/api/sendCode.ts @@ -28,11 +28,10 @@ export const onRequestPost: PagesFunction = async (context) => { } // 开发环境使用固定验证码 - const verificationCode = env.CF_PAGES_ENVIRONMENT === 'preview' + const verificationCode = env.CF_PAGES_ENVIRONMENT !== 'production' ? '123456' : Math.random().toString().slice(-6); - - if (env.CF_PAGES_ENVIRONMENT !== 'preview') { + if (env.CF_PAGES_ENVIRONMENT === 'production') { try { await sendSMS(phone, verificationCode, { accessKeyId: env.ALIYUN_ACCESS_KEY_ID, diff --git a/functions/api/test-db.ts b/functions/api/test-db.ts new file mode 100644 index 0000000..e816d3f --- /dev/null +++ b/functions/api/test-db.ts @@ -0,0 +1,32 @@ +interface Env { + bgdb: D1Database; +} + +export const onRequestGet: PagesFunction = async (context) => { + try { + const { env } = context; + const db = env.bgdb; + + // 测试数据库连接 + const result = await db.prepare( + "SELECT * FROM users" + ).all(); + + return new Response(JSON.stringify({ + success: true, + tables: result, + env: Object.keys(env) + }), { + headers: { 'Content-Type': 'application/json' } + }); + } catch (error) { + return new Response(JSON.stringify({ + success: false, + error: error.message, + stack: error.stack + }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } +}; \ No newline at end of file diff --git a/init-db.sh b/init-db.sh new file mode 100644 index 0000000..ef79f74 --- /dev/null +++ b/init-db.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# 文件名: init-db.sh + +rm -rf .local-db + +# 重新创建目录 +mkdir -p .local-db + +# 删除旧数据库(如果存在) +wrangler d1 delete friends --local + +# 创建新数据库 +wrangler d1 create friends --local --persist-to=.local-db + +# 创建表 +wrangler d1 execute friends --local --persist-to=.local-db --command=" +CREATE TABLE IF NOT EXISTS users ( + id INTEGER PRIMARY KEY, + phone VARCHAR(11) NOT NULL UNIQUE, + nickname VARCHAR(50), + avatar_url TEXT, + status INTEGER DEFAULT 1, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + last_login_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +);" + +# 插入测试数据 +wrangler d1 execute friends --local --persist-to=.local-db --command=" +INSERT OR IGNORE INTO users (phone, nickname) +VALUES ('13800138000', '测试用户');" + +# 验证表是否创建成功 +echo "验证表结构:" +wrangler d1 execute friends --local --persist-to=.local-db --command="PRAGMA table_info(users);" + +echo "验证数据:" +wrangler d1 execute friends --local --persist-to=.local-db --command="SELECT * FROM users;" + +echo "数据库初始化完成。使用以下命令启动开发服务器:" +echo "wrangler pages dev --d1 bgdb=friends --persist-to=.local-db -- npm run dev" diff --git a/src/pages/chat/components/Sidebar.tsx b/src/pages/chat/components/Sidebar.tsx index 9415f0a..70b960f 100644 --- a/src/pages/chat/components/Sidebar.tsx +++ b/src/pages/chat/components/Sidebar.tsx @@ -6,6 +6,7 @@ import GitHubButton from 'react-github-btn'; import '@fontsource/audiowide'; //import { groups } from "@/config/groups"; import { AdSection } from './AdSection'; +import { UserSection } from './UserSection'; import { Tooltip, TooltipContent, @@ -123,6 +124,9 @@ const Sidebar = ({ isOpen, toggleSidebar, selectedGroupIndex = 0, onSelectGroup, {/* 广告位 */} + {/* 用户信息模块 */} + + {/* GitHub Star Button - 只在侧边栏打开时显示,放在底部 */}
{/* 标题移至底部 */} diff --git a/src/pages/chat/components/UserSection.tsx b/src/pages/chat/components/UserSection.tsx new file mode 100644 index 0000000..03af019 --- /dev/null +++ b/src/pages/chat/components/UserSection.tsx @@ -0,0 +1,73 @@ +import React, { useState } from 'react'; +import { cn } from "@/lib/utils"; +import { Edit2Icon, LogOutIcon } from 'lucide-react'; + +interface UserSectionProps { + isOpen: boolean; +} + +export const UserSection: React.FC = ({ isOpen }) => { + const [isHovering, setIsHovering] = useState(false); + + if (!isOpen) return null; + + return ( +
setIsHovering(true)} + onMouseLeave={() => setIsHovering(false)} + > + {/* 头像区域 */} +
+
+ +
+ {/* 头像hover效果 */} +
+ +
+
+ + {/* 用户信息区域 */} +
+
+ + 游客用户 + + +
+ + {/* 退出登录按钮 */} +
{ + // 这里添加退出登录的处理逻辑 + console.log('退出登录'); + }} + > + + + 退出登录 + +
+
+
+ ); +}; \ No newline at end of file