imetting/frontend/src/pages/HomePage.jsx

282 lines
8.4 KiB
JavaScript

import React, { useEffect, useState } from 'react';
import {
Row, Col, Typography, Button,
Form, Input, Space, Tabs, App
} from 'antd';
import {
UserOutlined,
LockOutlined,
ArrowRightOutlined,
} from '@ant-design/icons';
import httpService from '../services/httpService';
import { buildApiUrl, API_ENDPOINTS } from '../config/api';
import menuService from '../services/menuService';
import BrandLogo from '../components/BrandLogo';
import configService from '../utils/configService';
const { Title, Paragraph, Text } = Typography;
const BRAND_HIGHLIGHTS = [
'智能转录与结构化总结',
'时间轴回看与全文检索',
'沉淀可追踪的会议资产',
];
const HOME_TAGLINE = '让每一次谈话都产生价值';
const HomePage = ({ onLogin }) => {
const [loading, setLoading] = useState(false);
const [branding, setBranding] = useState(() => configService.getCachedBrandingConfig());
const { message } = App.useApp();
useEffect(() => {
if (branding) {
return;
}
let active = true;
configService.getBrandingConfig().then((nextBranding) => {
if (active) {
setBranding(nextBranding);
}
}).catch((error) => {
console.error('Load branding config failed:', error);
});
return () => {
active = false;
};
}, [branding]);
if (!branding) {
return null;
}
const handleLogin = async (values) => {
setLoading(true);
try {
const response = await httpService.post(buildApiUrl(API_ENDPOINTS.AUTH.LOGIN), {
username: values.username,
password: values.password
});
if (response.code === '200') {
message.success('登录成功');
menuService.clearCache();
onLogin(response.data);
} else {
message.error(response.message || '登录失败');
}
} catch (error) {
console.error('Login error:', error);
message.error(error.response?.data?.message || '账号或密码错误');
} finally {
setLoading(false);
}
};
return (
<div style={{ minHeight: '100vh', display: 'flex', background: '#fff' }}>
<Row style={{ width: '100%' }}>
{/* 左侧:品牌展示区 */}
<Col xs={0} lg={14} style={{
background: '#ebf2ff',
padding: '60px 80px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center'
}}>
<div style={{ maxWidth: 640 }}>
<div style={{ marginBottom: 64 }}>
<BrandLogo title={branding.app_name} size={48} titleSize={24} gap={12} titleColor="#6f42c1" />
</div>
<div
style={{
display: 'inline-flex',
alignItems: 'center',
padding: '8px 16px',
borderRadius: 999,
marginBottom: 24,
border: '1px solid rgba(37, 99, 235, 0.14)',
background: 'rgba(255, 255, 255, 0.55)',
boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.75)',
}}
>
<Text style={{ color: '#47658d', fontSize: 13, fontWeight: 700, letterSpacing: '0.08em' }}>
INTELLIGENT MEETING WORKSPACE
</Text>
</div>
<div style={{ maxWidth: 600 }}>
<div
style={{
marginBottom: 24,
display: 'flex',
alignItems: 'baseline',
gap: 18,
flexWrap: 'wrap',
}}
>
<Title
level={2}
style={{
margin: 0,
fontSize: 38,
lineHeight: 1.05,
fontWeight: 700,
letterSpacing: '0.02em',
color: '#365b8d',
}}
>
iMeeting
</Title>
<Title
level={1}
style={{
margin: 0,
fontSize: 48,
lineHeight: 1.04,
fontWeight: 800,
letterSpacing: '-0.03em',
color: '#1677ff',
}}
>
{branding.app_name}
</Title>
</div>
<Paragraph
style={{
fontSize: 22,
color: '#334e73',
lineHeight: 1.65,
marginBottom: 18,
maxWidth: 560,
}}
>
{HOME_TAGLINE}
</Paragraph>
<Paragraph
style={{
fontSize: 16,
color: '#5a718f',
lineHeight: 1.9,
marginBottom: 28,
maxWidth: 560,
}}
>
</Paragraph>
<Space size={[10, 12]} wrap>
{BRAND_HIGHLIGHTS.map((item) => (
<span
key={item}
style={{
display: 'inline-flex',
alignItems: 'center',
padding: '9px 14px',
borderRadius: 999,
border: '1px solid rgba(113, 140, 178, 0.18)',
background: 'rgba(255, 255, 255, 0.62)',
color: '#4d678b',
fontSize: 14,
fontWeight: 600,
boxShadow: '0 8px 18px rgba(40, 72, 120, 0.06)',
}}
>
{item}
</span>
))}
</Space>
</div>
</div>
</Col>
{/* 右侧:登录交互区 */}
<Col xs={24} lg={10} style={{
padding: '40px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
background: '#fff'
}}>
<div style={{ width: '100%', maxWidth: 400 }}>
<Tabs
className="console-tabs"
defaultActiveKey="login"
size="large"
style={{ marginBottom: 32 }}
items={[
{ key: 'login', label: '账号登录' },
{ key: 'register', label: '注册账号', disabled: true }
]}
/>
<div style={{ marginBottom: 40 }}>
<Paragraph type="secondary" style={{ fontSize: 16 }}>
{branding.login_welcome}
</Paragraph>
</div>
<Form layout="vertical" onFinish={handleLogin} size="large">
<Form.Item
label={<Text strong>用户名</Text>}
name="username"
rules={[{ required: true, message: '请输入用户名' }]}
>
<Input
prefix={<UserOutlined style={{ color: '#bfbfbf' }} />}
placeholder="请输入用户名"
style={{ borderRadius: 8, height: 50 }}
/>
</Form.Item>
<Form.Item
label={<Text strong>密码</Text>}
name="password"
rules={[{ required: true, message: '请输入密码' }]}
>
<Input.Password
prefix={<LockOutlined style={{ color: '#bfbfbf' }} />}
placeholder="请输入密码"
style={{ borderRadius: 8, height: 50 }}
/>
</Form.Item>
<Form.Item style={{ marginTop: 48 }}>
<Button
type="primary"
icon={<ArrowRightOutlined />}
htmlType="submit"
block
loading={loading}
style={{
height: 50,
fontSize: 16,
borderRadius: 8,
fontWeight: 600
}}
>
立即登录
</Button>
</Form.Item>
</Form>
<div style={{ marginTop: 100, textAlign: 'center' }}>
<Text type="secondary" style={{ fontSize: 13 }}>
{branding.footer_text}
</Text>
</div>
</div>
</Col>
</Row>
</div>
);
};
export default HomePage;