| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- import * as React from 'react';
- // import { observer } from 'mobx-react';
- import { Form, Input, Checkbox, Button, Row, Col, Select, message } from 'antd';
- import { UserOutlined, LockOutlined, SafetyOutlined } from '@ant-design/icons';
- // import Copyright from './components/Copyright';
- // import backgroundSrc from '@/assets/login/background.jpg';
- import { regex } from '../../utils';
- // import store from './store';
- import './style.scss';
- // import logoSrc from '@/assets/public/logo.png';
- import logoSrc from "../../icons/logo.png";
- import api from "@/app/api/api";
- import { isIOS, useMobileScreen, getContrastColor } from "../../utils";
- import { useAppConfig, useChatStore, useGlobalStore } from "../../store";
- import {replaceUrl} from '@/app/utils/index'
- const FormItem = Form.Item;
- const Login: React.FC = () => {
- const chatStore = useChatStore();
- const globalStore = useGlobalStore();
- const isMobileScreen = useMobileScreen();
- const [form] = Form.useForm();
- const [isTab, setIsTab] = React.useState(true);
- const [captchaData, setCaptchaData] = React.useState({
- img: '',
- uuid: ''
- });
- const apis: any = {
- // 验证码
- captchaImag: async () => {
- console.log('验证码图片加载')
- try {
- const res: any = await api.get('/auth/code');
- if (res?.code === 200) {
- setCaptchaData(res?.data || {});
- } else {
- message.error(res?.msg || '获取验证码失败');
- }
- } catch (error: any) {
- console.log('error', error)
- }
- },
- }
- const init = () => {
- apis.captchaImag();
- }
- const fetchUserInfoApi = async (token:string) => {
- const res:any =await api.get(`/system/user/getInfo`);
- if (res?.code === 200) {
- const info = res.data;
- localStorage.setItem('userInfo', JSON.stringify({
- nickName: info?.user?.nickName,
- userId: info?.user?.userId,
- token: token
- }));
- chatStore.clearSessions()
- globalStore.setSelectedAppId('');
- const originUrl = window.location.origin;
- window.open(`${originUrl}/#/welcome`, '_self');
- } else {
- message.error(res?.msg || '获取用户信息失败');
- }
- }
- // 点击登录
- const onClickLogin = async (data: any, remember: any) => {
- try {
- const res:any = await api.post('/auth/login', data, {
- headers: {
- isEncrypt: true
- }
- });
- if (res?.code === 200) {
- const info = res.data;
- localStorage.setItem('token', info.access_token);
- if( remember) {
- localStorage.setItem('accountPassword', JSON.stringify({
- account: data.username,
- password: data.password
- }));
- } else {
- localStorage.removeItem('accountPassword');
- }
- fetchUserInfoApi(info.access_token);
- } else {
- console.log('1111',res);
- message.error(res?.msg || '获取验证码失败');
- }
- } catch (error: any) {
- init();
- }
- }
- React.useEffect(() => {
- window.location.replace(`${replaceUrl}?redirectUrl=${window.location.href}`);
- // init();
- // return () => reset();
- }, []);
- // 校验密码
- const validatorPassword = (rule: any, value: string) => {
- if (value) {
- const passwordRegex = new RegExp(regex.password);
- if (passwordRegex.test(value)) {
- return Promise.resolve();
- } else {
- return Promise.reject('密码格式不正确');
- }
- } else {
- return Promise.reject('密码不能为空');
- }
- };
- // 集团统一登录
- const group = () => {
- return <div id="group-login-form" className="space-y-6">
- <div className="text-center">
- <div className="w-20 h-20 bg-blue-50 rounded-full flex items-center justify-center mx-auto mb-6">
- <i className="fa fa-building text-3xl text-primary"></i>
- </div>
- <h4 className="text-xl font-medium text-neutral-700 mb-3">集团统一身份认证</h4>
- <p className="text-neutral-400 max-w-md mx-auto text-base">
- 点击下方按钮,将<span className="font-bold">跳转至集团统一登录平台</span>进行身份验证
- </p>
- </div>
- <div className="p-5 bg-neutral-50 rounded-lg border border-neutral-200">
- <div className="flex items-start">
- <div className="flex-shrink-0 mt-0.5">
- <i className="fa fa-info-circle text-primary text-xl"></i>
- </div>
- <div className="ml-4">
- <p className="text-base text-neutral-500">
- 集团统一登录将使用您的集团账号密码进行验证,无需重复注册
- </p>
- </div>
- </div>
- </div>
- <Button color="primary" size='large' className="w-full py-4 bg-white border-2 border-primary text-primary font-medium rounded-lg hover:bg-primary/5" variant="outlined">
- 前往集团统一登录平台
- </Button>
- </div>
- }
- return (
- // Mobile (H5) optimized layout
- isMobileScreen ? (
- <div className="mobile-login p-4 bg-white min-h-screen flex flex-col justify-center">
- <div className="mobile-login-header text-center mb-6">
- <img src={logoSrc.src} alt="Logo" className="w-20 h-20 mx-auto mb-2" />
- <h1 className="text-2xl font-bold">盈科</h1>
- <p className="text-sm text-neutral-500">安全登录,高效办公</p>
- </div>
- <div className="mobile-login-tabs mb-4 flex items-center justify-center gap-2">
- <Button type={isTab ? 'primary' : 'default'} size="middle" onClick={() => setIsTab(true)}>
- 本地登录
- </Button>
- <Button type={!isTab ? 'primary' : 'default'} size="middle" onClick={() => setIsTab(false)}>
- 集团统一登录
- </Button>
- </div>
- <div className="mobile-login-form bg-white">
- {isTab ? (
- <Form form={form} layout="vertical">
- <FormItem name="account" label="账号" rules={[{ required: true, message: '账号不能为空' }]}>
- <Input size='large' placeholder='请输入账号' prefix={<UserOutlined />} />
- </FormItem>
- <FormItem name="password" label="密码" rules={[{ required: true, validator: validatorPassword }]}>
- <Input.Password size='large' placeholder='请输入密码' className='password-input' prefix={<LockOutlined />} />
- </FormItem>
- <FormItem name='code' label='验证码' rules={[{ required: true, message: '验证码不能为空' }]}>
- <Row gutter={8}>
- <Col span={14}>
- <Input size='large' className='w-full yzm_input' placeholder='请输入验证码' />
- </Col>
- <Col span={10}>
- <div onClick={() => apis.captchaImag()} style={{ cursor: 'pointer' }}>
- <img src={`data:image/png;base64,${captchaData.img}`} alt="验证码" style={{ width: '100%', height: 38, borderRadius: 4 }} />
- </div>
- </Col>
- </Row>
- </FormItem>
- <FormItem name='remember' valuePropName='checked'>
- <Checkbox>记住密码</Checkbox>
- </FormItem>
- <FormItem>
- <Button type='primary' size='large' block onClick={() => {
- form.validateFields().then(async (values) => {
- const data = {
- username: values.account,
- password: values.password,
- code: values.code,
- uuid: captchaData.uuid,
- clientId: 'e5cd7e4891bf95d1d19206ce24a7b32e',
- grantType: 'password'
- }
- onClickLogin(data, values.remember);
- }).catch((error) => {
- console.error(error);
- });
- }}>登录</Button>
- </FormItem>
- </Form>
- ) : (
- <div>
- {group()}
- </div>
- )}
- </div>
- </div>
- ) : (
- <div className='login'>
- {/* <img src={backgroundSrc} /> */}
- <div className="w-[55%] bg-gradient-primary text-white p-1 md:p-16 flex flex-col justify-center relative overflow-hidden">
- <div className="relative z-10 max-w-xl mx-auto md:mx-0">
- <div className="flex items-end mb-12">
- <div className="flex items-center justify-center mr-4">
- <img src={logoSrc.src} alt="Logo" className="w-36 h-36" />
- </div>
- <h1 className="text-5xl font-bold">盈科</h1>
- </div>
- <h2 className="text-[clamp(2.5rem,5vw,3.5rem)] font-bold mb-6 leading-tight">
- 安全登录,<br />高效办公
- </h2>
- <p className="text-white/80 text-lg mb-10 max-w-lg">
- 提供多种安全登录方式,保障您的信息安全,提升工作效率
- </p>
- <div className="grid grid-cols-2 gap-6 mt-10">
- <div className="flex items-start">
- <div className="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center mr-4 flex-shrink-0">
- <i className="fa fa-lock text-white"></i>
- </div>
- <div>
- <h3 className="text-xl font-semibold mb-2">安全可靠</h3>
- <p className="text-white/70">多重加密保障,保护您的账号安全</p>
- </div>
- </div>
- <div className="flex items-start">
- <div className="w-10 h-10 rounded-full bg-white/20 flex items-center justify-center mr-4 flex-shrink-0">
- <i className="fa fa-bolt text-white"></i>
- </div>
- <div>
- <h3 className="text-xl font-semibold mb-2">高效便捷</h3>
- <p className="text-white/70">简化登录流程,提升工作效率</p>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div className='login-right'>
- <div className='login-right-content h-[700px]'>
- <div className="mb-2">
- <h3 className="text-[clamp(1.5rem,3vw,2.25rem)] font-bold text-neutral-700 mb-3 mt-0">账户登录</h3>
- <p className="text-neutral-400 text-lg">请选择登录方式并完成验证</p>
- </div>
- <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-10">
- <Button type={isTab ? 'primary' : 'default'} size='large' onClick={() => {
- setIsTab(true);
- }} >
- <i className="fa fa-user-circle text-2xl"></i>
- <span>本地登录</span>
- </Button>
- <Button type={!isTab ? 'primary' : 'default'} size='large' onClick={() => {
- setIsTab(false);
- }} >
- <i className="fa fa-building text-2xl"></i>
- <span>集团统一登录</span>
- </Button>
- </div>
- {isTab && <Form form={form}>
- <FormItem
- name='account'
- label='账号'
- colon={false}
- rules={[{ required: true, message: '账号不能为空', whitespace: true }]}
- labelCol={{ span: 24 }} // 标签占满整行
- wrapperCol={{ span: 24 }} // 输入框占满整行
- >
- <Input size='large' placeholder='请输入账号' prefix={<UserOutlined />} />
- </FormItem>
- <FormItem
- name='password'
- label='密码'
- colon={false}
- rules={[{ required: true, validator: validatorPassword }]}
- labelCol={{ span: 24 }} // 标签占满整行
- wrapperCol={{ span: 24 }} // 输入框占满整行
- >
- <Input.Password size='large' placeholder='请输入密码' prefix={<LockOutlined />} className='password-input' />
- </FormItem>
- <FormItem
- name='code'
- label='验证码'
- colon={false}
- rules={[{ required: true, message: '验证码' }]}
- labelCol={{ span: 24 }} // 标签占满整行
- wrapperCol={{ span: 24 }} // 输入框占满整行
- >
- <Row gutter={8} >
- {/* 输入框占大部分宽度 */}
- <Col span={17}>
- <Input size='large' placeholder='请输入验证码' prefix={<SafetyOutlined />} />
- </Col>
- {/* 验证码图片固定宽度 */}
- <Col span={7}>
- <div>
- <img
- src={`data:image/png;base64,${captchaData.img}`}
- alt="验证码"
- style={{
- width: '100%',
- height: '38px',
- borderRadius: '2px',
- cursor: 'pointer' // 提示可点击刷新
- }}
- onClick={() => { apis.captchaImag() }}
- />
- </div>
- </Col>
- </Row>
- </FormItem>
- <FormItem
- name='remember'
- valuePropName='checked'
- >
- <Checkbox>
- 记住密码
- </Checkbox>
- </FormItem>
- <FormItem>
- <Button
- type='primary'
- size='large'
- block={true}
- // loading={buttonLoading}
- onClick={() => {
- form.validateFields().then(async (values) => {
- const data = {
- username: values.account,
- password: values.password,
- // tenantId: values.tenantId,
- code: values.code,
- uuid: captchaData.uuid,
- clientId: 'e5cd7e4891bf95d1d19206ce24a7b32e',
- grantType: 'password'
- }
- onClickLogin(data, values.remember);
- }).catch((error) => {
- console.error(error);
- });
- }}
- >
- 登录
- </Button>
- </FormItem>
- </Form>}
- {!isTab && group()}
- </div>
- {/* <Copyright /> */}
- </div>
- </div>
- ));
- };
- // export default observer(Login);
- export default Login;
|