feat: AI Worker 平台 MVP v1.0.0 - 多租户/项目管理/AI Worker/任务编排/HITL审核/成本治理

This commit is contained in:
2026-08-12 13:31:18 +08:00
parent 976b2a3e4e
commit 0d74675de0
+210
View File
@@ -0,0 +1,210 @@
import { useState } from 'react';
import { Card, Form, Input, Button, Tabs, Select, Typography, Space, message } from 'antd';
import { RobotOutlined } from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import { useAuthStore } from '@/stores/auth';
import type { UserRole } from '@/types';
const { Title, Text, Link } = Typography;
const roles: { value: UserRole; label: string }[] = [
{ value: 'tenant_admin', label: '租户管理员' },
{ value: 'project_manager', label: '项目经理' },
{ value: 'reviewer', label: '审核员' },
{ value: 'worker', label: '执行者' },
];
export default function Login() {
const navigate = useNavigate();
const { login, register } = useAuthStore();
const [activeTab, setActiveTab] = useState('login');
const [loading, setLoading] = useState(false);
// Login form
const [loginForm] = Form.useForm();
// Register form
const [regForm] = Form.useForm();
const handleLogin = async (values: { email: string; password: string }) => {
setLoading(true);
try {
await login(values);
message.success('登录成功');
navigate('/dashboard');
} catch (err) {
message.error(err instanceof Error ? err.message : '登录失败');
} finally {
setLoading(false);
}
};
const handleRegister = async (values: {
email: string;
username: string;
password: string;
role: UserRole;
tenant_slug: string;
tenant_name: string;
}) => {
setLoading(true);
try {
await register(values);
message.success('注册成功,欢迎使用!');
navigate('/dashboard');
} catch (err) {
message.error(err instanceof Error ? err.message : '注册失败');
} finally {
setLoading(false);
}
};
return (
<div className="login-bg">
<Card
style={{
width: 460,
boxShadow: '0 8px 32px rgba(0,0,0,0.2)',
borderRadius: 12,
}}
>
<div style={{ textAlign: 'center', marginBottom: 24 }}>
<Space direction="vertical" size={4}>
<RobotOutlined style={{ fontSize: 48, color: '#1677ff' }} />
<Title level={3} style={{ margin: 0 }}>
AI Worker
</Title>
<Text type="secondary">AI </Text>
</Space>
</div>
<Tabs
activeKey={activeTab}
onChange={setActiveTab}
centered
items={[
{
key: 'login',
label: '登录',
children: (
<Form
form={loginForm}
layout="vertical"
onFinish={handleLogin}
size="large"
>
<Form.Item
name="email"
label="邮箱"
rules={[
{ required: true, message: '请输入邮箱' },
{ type: 'email', message: '请输入有效邮箱' },
]}
>
<Input placeholder="请输入邮箱" />
</Form.Item>
<Form.Item
name="password"
label="密码"
rules={[{ required: true, message: '请输入密码' }]}
>
<Input.Password placeholder="请输入密码" />
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
loading={loading}
block
>
</Button>
</Form.Item>
</Form>
),
},
{
key: 'register',
label: '注册',
children: (
<Form
form={regForm}
layout="vertical"
onFinish={handleRegister}
size="middle"
>
<Form.Item
name="email"
label="邮箱"
rules={[
{ required: true, message: '请输入邮箱' },
{ type: 'email', message: '请输入有效邮箱' },
]}
>
<Input placeholder="请输入邮箱" />
</Form.Item>
<Form.Item
name="username"
label="用户名"
rules={[{ required: true, message: '请输入用户名' }]}
>
<Input placeholder="请输入用户名" />
</Form.Item>
<Form.Item
name="password"
label="密码"
rules={[
{ required: true, message: '请输入密码' },
{ min: 6, message: '密码至少6位' },
]}
>
<Input.Password placeholder="至少6位" />
</Form.Item>
<Form.Item
name="role"
label="角色"
rules={[{ required: true, message: '请选择角色' }]}
>
<Select options={roles} placeholder="选择角色" />
</Form.Item>
<Form.Item
name="tenant_name"
label="组织名称"
rules={[{ required: true, message: '请输入组织名称' }]}
>
<Input placeholder="例如:我的团队" />
</Form.Item>
<Form.Item
name="tenant_slug"
label="组织标识"
rules={[
{ required: true, message: '请输入组织标识' },
{ pattern: /^[a-z0-9-]+$/, message: '仅限小写字母、数字和连字符' },
]}
>
<Input placeholder="例如:my-team" />
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
loading={loading}
block
>
</Button>
</Form.Item>
</Form>
),
},
]}
/>
<div style={{ textAlign: 'center' }}>
<Text type="secondary" style={{ fontSize: 12 }}>
</Text>
</div>
</Card>
</div>
);
}