add user db
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
|
# 启动开发服务器
|
||||||
wrangler pages dev -- npm run dev
|
wrangler pages dev -- npm run dev
|
||||||
@@ -58,7 +58,7 @@ export async function onRequest(context) {
|
|||||||
const request = context.request;
|
const request = context.request;
|
||||||
const env = context.env;
|
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();
|
return await context.next();
|
||||||
}
|
}
|
||||||
const authHeader = request.headers.get('Authorization');
|
const authHeader = request.headers.get('Authorization');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
interface Env {
|
interface Env {
|
||||||
bgkv: KVNamespace;
|
bgkv: KVNamespace;
|
||||||
JWT_SECRET: string;
|
JWT_SECRET: string;
|
||||||
DB: D1Database;
|
bgdb: D1Database;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequestPost: PagesFunction<Env> = async (context) => {
|
export const onRequestPost: PagesFunction<Env> = async (context) => {
|
||||||
@@ -46,7 +46,6 @@ export const onRequestPost: PagesFunction<Env> = async (context) => {
|
|||||||
|
|
||||||
// 从 KV 中获取存储的验证码
|
// 从 KV 中获取存储的验证码
|
||||||
const storedCode = await env.bgkv.get(`sms:${phone}`);
|
const storedCode = await env.bgkv.get(`sms:${phone}`);
|
||||||
|
|
||||||
if (!storedCode || storedCode !== code) {
|
if (!storedCode || storedCode !== code) {
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@@ -63,13 +62,13 @@ export const onRequestPost: PagesFunction<Env> = async (context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证成功后,处理用户数据
|
// 验证成功后,处理用户数据
|
||||||
const db = env.DB; // 假设你的 D1 数据库实例名为 DB
|
const db = env.bgdb; // 假设你的 D1 数据库实例名为 DB
|
||||||
|
|
||||||
// 查询用户是否存在
|
// 查询用户是否存在
|
||||||
const existingUser = await db.prepare(
|
const existingUser = await db.prepare(
|
||||||
"SELECT id, phone, nickname FROM users WHERE phone = ?"
|
"SELECT id, phone, nickname FROM users WHERE phone = ?"
|
||||||
).bind(phone).first();
|
).bind(phone).first();
|
||||||
|
|
||||||
|
console.log('existingUser', existingUser);
|
||||||
let userId;
|
let userId;
|
||||||
if (!existingUser) {
|
if (!existingUser) {
|
||||||
// 用户不存在,创建新用户
|
// 用户不存在,创建新用户
|
||||||
|
|||||||
@@ -28,11 +28,10 @@ export const onRequestPost: PagesFunction<Env> = async (context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 开发环境使用固定验证码
|
// 开发环境使用固定验证码
|
||||||
const verificationCode = env.CF_PAGES_ENVIRONMENT === 'preview'
|
const verificationCode = env.CF_PAGES_ENVIRONMENT !== 'production'
|
||||||
? '123456'
|
? '123456'
|
||||||
: Math.random().toString().slice(-6);
|
: Math.random().toString().slice(-6);
|
||||||
|
if (env.CF_PAGES_ENVIRONMENT === 'production') {
|
||||||
if (env.CF_PAGES_ENVIRONMENT !== 'preview') {
|
|
||||||
try {
|
try {
|
||||||
await sendSMS(phone, verificationCode, {
|
await sendSMS(phone, verificationCode, {
|
||||||
accessKeyId: env.ALIYUN_ACCESS_KEY_ID,
|
accessKeyId: env.ALIYUN_ACCESS_KEY_ID,
|
||||||
|
|||||||
32
functions/api/test-db.ts
Normal file
32
functions/api/test-db.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
interface Env {
|
||||||
|
bgdb: D1Database;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const onRequestGet: PagesFunction<Env> = 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' }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
41
init-db.sh
Normal file
41
init-db.sh
Normal file
@@ -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"
|
||||||
@@ -6,6 +6,7 @@ import GitHubButton from 'react-github-btn';
|
|||||||
import '@fontsource/audiowide';
|
import '@fontsource/audiowide';
|
||||||
//import { groups } from "@/config/groups";
|
//import { groups } from "@/config/groups";
|
||||||
import { AdSection } from './AdSection';
|
import { AdSection } from './AdSection';
|
||||||
|
import { UserSection } from './UserSection';
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
@@ -123,6 +124,9 @@ const Sidebar = ({ isOpen, toggleSidebar, selectedGroupIndex = 0, onSelectGroup,
|
|||||||
{/* 广告位 */}
|
{/* 广告位 */}
|
||||||
<AdSection isOpen={isOpen} />
|
<AdSection isOpen={isOpen} />
|
||||||
|
|
||||||
|
{/* 用户信息模块 */}
|
||||||
|
<UserSection isOpen={isOpen} />
|
||||||
|
|
||||||
{/* GitHub Star Button - 只在侧边栏打开时显示,放在底部 */}
|
{/* GitHub Star Button - 只在侧边栏打开时显示,放在底部 */}
|
||||||
<div className="px-3 py-2 mt-auto">
|
<div className="px-3 py-2 mt-auto">
|
||||||
{/* 标题移至底部 */}
|
{/* 标题移至底部 */}
|
||||||
|
|||||||
73
src/pages/chat/components/UserSection.tsx
Normal file
73
src/pages/chat/components/UserSection.tsx
Normal file
@@ -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<UserSectionProps> = ({ isOpen }) => {
|
||||||
|
const [isHovering, setIsHovering] = useState(false);
|
||||||
|
|
||||||
|
if (!isOpen) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"px-3 py-3 border-t border-b border-border/40",
|
||||||
|
"flex items-center gap-3 hover:bg-accent/50 transition-colors"
|
||||||
|
)}
|
||||||
|
onMouseEnter={() => setIsHovering(true)}
|
||||||
|
onMouseLeave={() => setIsHovering(false)}
|
||||||
|
>
|
||||||
|
{/* 头像区域 */}
|
||||||
|
<div className="relative group cursor-pointer">
|
||||||
|
<div className="w-10 h-10 rounded-full bg-gradient-to-br from-orange-400 to-rose-400 flex items-center justify-center shadow-sm">
|
||||||
|
<span className="text-base font-medium text-white">游</span>
|
||||||
|
</div>
|
||||||
|
{/* 头像hover效果 */}
|
||||||
|
<div className="absolute inset-0 rounded-full bg-black/40 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
|
<Edit2Icon className="w-4 h-4 text-white" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 用户信息区域 */}
|
||||||
|
<div className="flex flex-col relative flex-1">
|
||||||
|
<div className="flex items-center gap-1 group cursor-pointer">
|
||||||
|
<span className="text-sm font-semibold group-hover:text-primary transition-colors">
|
||||||
|
游客用户
|
||||||
|
</span>
|
||||||
|
<Edit2Icon
|
||||||
|
className={cn(
|
||||||
|
"w-3 h-3 text-muted-foreground/50",
|
||||||
|
"opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 退出登录按钮 */}
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex items-center gap-0.5 mt-0.5 text-xs text-muted-foreground/70",
|
||||||
|
"hover:text-rose-500 transition-all duration-200 group",
|
||||||
|
"rounded-md cursor-pointer"
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
// 这里添加退出登录的处理逻辑
|
||||||
|
console.log('退出登录');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LogOutIcon
|
||||||
|
className={cn(
|
||||||
|
"w-3 h-3",
|
||||||
|
"group-hover:animate-pulse"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<span className="group-hover:tracking-wide transition-all duration-200">
|
||||||
|
退出登录
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user