- 新增用户登录页面与API端点(/api/auth/login、/api/auth/logout、/api/auth/me) - 引入基于密码哈希的认证机制,支持默认管理员账号登录 - 创建访问控制模块(lib/access-control.ts),实现基于角色的权限验证 - 在现有API端点中集成权限检查,限制非管理员用户只能访问其所属项目数据 - 更新应用布局,要求用户登录后才能访问主界面 - 扩展用户表结构,增加用户名和密码哈希字段 - 调整项目、KR、目标、会议记录等资源的查询逻辑,根据用户权限过滤数据 - 改进管理页面(指标、模板)的删除操作,使用确认对话框替代直接确认 - 优化“我的KR”页面,为管理员提供全员KR概览视图 - 修复.gitignore文件中的拼写错误(.trae → .travis) - 添加数据库迁移脚本,支持任务直接关联项目、禁用RLS、添加求助字段等 - 配置Next.js以支持独立输出和子路径部署
107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from 'react';
|
||
import { Button } from '@/components/ui/button';
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||
import { Target, Loader2, Sparkles, CheckCircle } from 'lucide-react';
|
||
|
||
interface InitWizardProps {
|
||
onComplete: () => void;
|
||
}
|
||
|
||
export function InitWizard({ onComplete }: InitWizardProps) {
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
const [success, setSuccess] = useState(false);
|
||
|
||
const handleInit = async () => {
|
||
setIsLoading(true);
|
||
setError(null);
|
||
|
||
try {
|
||
const res = await fetch('/api/seed', { method: 'POST' });
|
||
const data = await res.json();
|
||
|
||
if (!res.ok) {
|
||
throw new Error(data.error || '初始化失败');
|
||
}
|
||
|
||
if (data.ownerId) {
|
||
localStorage.setItem('currentUserId', data.ownerId);
|
||
}
|
||
|
||
setSuccess(true);
|
||
setTimeout(() => {
|
||
onComplete();
|
||
}, 1500);
|
||
} catch (err) {
|
||
setError(err instanceof Error ? err.message : '初始化失败');
|
||
} finally {
|
||
setIsLoading(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="min-h-screen flex items-center justify-center bg-gradient-to-br from-slate-50 to-slate-100 p-4">
|
||
<Card className="w-full max-w-lg">
|
||
<CardHeader className="text-center space-y-4">
|
||
<div className="mx-auto w-16 h-16 bg-teal-100 rounded-full flex items-center justify-center">
|
||
<Target className="h-8 w-8 text-teal-600" />
|
||
</div>
|
||
<CardTitle className="text-2xl">欢迎使用 兜爸目标管理</CardTitle>
|
||
<CardDescription className="text-base">
|
||
系统检测到数据库为空,点击下方按钮初始化演示数据,开始体验完整功能
|
||
</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="space-y-4">
|
||
{success ? (
|
||
<div className="flex flex-col items-center gap-3 py-4 text-emerald-600">
|
||
<CheckCircle className="h-12 w-12" />
|
||
<p className="font-medium">初始化成功!正在跳转...</p>
|
||
</div>
|
||
) : (
|
||
<>
|
||
<div className="bg-slate-50 rounded-lg p-4 space-y-2 text-sm text-slate-600">
|
||
<p className="font-medium text-slate-800">演示数据包含:</p>
|
||
<ul className="space-y-1 list-disc list-inside">
|
||
<li>3 位用户(老板、项目经理、工程师)</li>
|
||
<li>2 个项目及成员配置</li>
|
||
<li>1 个阶段目标(Objective)</li>
|
||
<li>多个执行目标(KR)含不同周期</li>
|
||
<li>历史打卡记录和会议纪要</li>
|
||
<li>指标库和模板库</li>
|
||
</ul>
|
||
</div>
|
||
|
||
{error && (
|
||
<div className="bg-rose-50 text-rose-700 rounded-lg p-3 text-sm">
|
||
{error}
|
||
</div>
|
||
)}
|
||
|
||
<Button
|
||
onClick={handleInit}
|
||
disabled={isLoading}
|
||
className="w-full bg-teal-600 hover:bg-teal-700"
|
||
size="lg"
|
||
>
|
||
{isLoading ? (
|
||
<>
|
||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||
正在初始化...
|
||
</>
|
||
) : (
|
||
<>
|
||
<Sparkles className="mr-2 h-4 w-4" />
|
||
生成演示数据
|
||
</>
|
||
)}
|
||
</Button>
|
||
</>
|
||
)}
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
);
|
||
}
|