Explorar el Código

feat(login): update login view

Lind hace 4 años
padre
commit
e1db3e50b6

BIN
public/images/login.png


+ 5 - 4
src/locales/zh-CN/pages.ts

@@ -1,5 +1,5 @@
 export default {
-  'pages.layouts.userLayout.title': 'Jetlinks 物联网基础平台',
+  'pages.layouts.userLayout.title': '开源物联网基础平台',
   'pages.login.failure': '登录失败,请重试!',
   'pages.login.success': '登录成功!',
   'pages.login.username.placeholder': '用户名',
@@ -133,10 +133,11 @@ export default {
   'pages.system.datasource.': '数据源管理',
 
   // 设备管理-物模型
-  'pages.device.metadata.function': '功能',
-  'pages.device.metadata.property': '属性',
+  'pages.device.metadata.functions': '功能',
+  'pages.device.metadata.properties': '属性',
   'pages.device.metadata.events': '事件',
-  'pages.device.metadata.tag': '标签',
+  'pages.device.metadata.tags': '标签',
+
   // 设备管理-产品
   'pages.device.product': '产品',
   'pages.device.product.status.published': '已发布',

+ 65 - 5
src/pages/user/Login/index.less

@@ -2,12 +2,57 @@
 
 .container {
   display: flex;
-  flex-direction: column;
+  flex-direction: row-reverse;
   height: 100vh;
   overflow: auto;
   background: @layout-body-background;
 }
 
+.left {
+  width: 27%;
+  background: #fff;
+}
+
+.right {
+  //background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg');
+  width: 73%;
+  height: 100%;
+  background-image: url('/images/login.png');
+  background-repeat: no-repeat;
+  background-position: center;
+  background-size: 100% 100%;
+
+  .systemName {
+    position: absolute;
+    top: 112px;
+    left: 85px;
+    width: 377px;
+    height: 110px;
+    font-weight: 600;
+    font-size: 90px;
+    font-family: Montserrat, fangsong;
+    font-style: normal;
+    line-height: 110px;
+    letter-spacing: 0.03em;
+  }
+
+  .systemDesc {
+    position: absolute;
+    top: 231px;
+    left: 86px;
+    width: 513px;
+    height: 17px;
+    color: #3dc239;
+    font-weight: normal;
+    font-size: 14px;
+    font-family: Montserrat, system-ui;
+    font-style: normal;
+    line-height: 17px;
+    letter-spacing: 0.19em;
+    text-transform: uppercase;
+  }
+}
+
 .lang {
   width: 100%;
   height: 40px;
@@ -20,13 +65,21 @@
 }
 
 .content {
-  flex: 1;
-  padding: 32px 0;
+  display: flex;
+  flex-direction: row-reverse;
+  justify-content: center;
+  padding: 40px 0;
+}
+
+.remember {
+  display: flex;
+  flex-direction: row;
+  margin-bottom: 30px;
 }
 
 @media (min-width: @screen-md-min) {
   .container {
-    background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg');
+    //background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg');
     background-repeat: no-repeat;
     background-position: center 110px;
     background-size: 100%;
@@ -38,7 +91,14 @@
 }
 
 .top {
+  width: 100%;
+  margin-top: 100px;
   text-align: center;
+
+  .footer {
+    position: absolute;
+    bottom: 0;
+  }
 }
 
 .header {
@@ -74,7 +134,7 @@
 
 .main {
   width: 328px;
-  margin: 0 auto;
+  margin: 60px auto 0;
   @media screen and (max-width: @screen-sm) {
     width: 95%;
     max-width: 328px;

+ 76 - 61
src/pages/user/Login/index.tsx

@@ -1,13 +1,12 @@
-import { message } from 'antd';
+import { message, Spin } from 'antd';
 import React, { useEffect, useRef, useState } from 'react';
 import { Link, history } from 'umi';
-import Footer from '@/components/Footer';
 import styles from './index.less';
 import Token from '@/utils/token';
 import Service from '@/pages/user/Login/service';
 import { createForm } from '@formily/core';
 import { createSchemaField } from '@formily/react';
-import { Form, Submit, Input, Password, FormItem } from '@formily/antd';
+import { Checkbox, Form, Submit, Input, Password, FormItem } from '@formily/antd';
 import { filter, mergeMap } from 'rxjs/operators';
 import * as ICONS from '@ant-design/icons';
 import { useModel } from '@@/plugin-model/useModel';
@@ -61,15 +60,14 @@ const Login: React.FC = () => {
       .subscribe(setCaptcha);
   };
 
-  useEffect(() => {
-    getCode();
-  }, []);
+  useEffect(getCode, []);
 
   const SchemaField = createSchemaField({
     components: {
       FormItem,
       Input,
       Password,
+      Checkbox,
     },
     scope: {
       icon(name: any) {
@@ -83,7 +81,6 @@ const Login: React.FC = () => {
     properties: {
       username: {
         type: 'string',
-        // title: '用户名',
         'x-decorator': 'FormItem',
         'x-validator': { required: true, message: '请输入用户名!' },
         'x-component': 'Input',
@@ -97,7 +94,6 @@ const Login: React.FC = () => {
       },
       password: {
         type: 'string',
-        // title: '密码',
         'x-validator': { required: true, message: '请输入用户名!' },
         'x-decorator': 'FormItem',
         'x-component': 'Password',
@@ -111,7 +107,6 @@ const Login: React.FC = () => {
       },
       verifyCode: {
         type: 'string',
-        // title: '验证码',
         'x-visible': !!captcha.key,
         'x-decorator': 'FormItem',
         'x-component': 'Input',
@@ -126,65 +121,85 @@ const Login: React.FC = () => {
     },
   };
 
-  const doLogin = async (data: LoginParam) =>
-    Service.login({ expires: -1, verifyKey: captcha.key, ...data }).subscribe({
-      next: async (userInfo: UserInfo) => {
-        message.success(
-          intl.formatMessage({
-            id: 'pages.login.success',
-            defaultMessage: '登录成功!',
-          }),
-        );
-        Token.set(userInfo.token);
-        await fetchUserInfo();
-        goto();
-      },
-      error: () =>
-        message.error(
-          intl.formatMessage({
-            id: 'pages.login.failure',
-            defaultMessage: '登录失败,请重试!',
-          }),
-        ),
-      complete: () => {
-        getCode();
+  const [loading, setLoading] = useState<boolean>(false);
+  const doLogin = async (data: LoginParam) => {
+    setLoading(true);
+    Service.login({ expires: loginRef.current.expires, verifyKey: captcha.key, ...data }).subscribe(
+      {
+        next: async (userInfo: UserInfo) => {
+          Token.set(userInfo.token);
+          await fetchUserInfo();
+          goto();
+          setLoading(false);
+        },
+        error: () => {
+          message.error(
+            intl.formatMessage({
+              id: 'pages.login.failure',
+              defaultMessage: '登录失败,请重试!',
+            }),
+          );
+          getCode();
+          setLoading(false);
+        },
+        complete: () => {
+          getCode();
+          setLoading(false);
+        },
       },
-    });
+    );
+  };
   return (
-    <div className={styles.container}>
-      <div className={styles.lang} data-lang="">
-        {SelectLang && <SelectLang />}
-      </div>
-      <div className={styles.content}>
-        <div className={styles.top}>
-          <div className={styles.header}>
-            <Link to="/">
-              <img alt="logo" className={styles.logo} src="/logo.svg" />
-              <span className={styles.title}>{SystemConst.SYSTEM_NAME}</span>
-            </Link>
+    <Spin spinning={loading}>
+      <div className={styles.container}>
+        <div className={styles.left}>
+          <div className={styles.lang} data-lang="">
+            {SelectLang && <SelectLang />}
           </div>
-          <div className={styles.desc}>
-            {intl.formatMessage({
-              id: 'pages.layouts.userLayout.title',
-              defaultMessage: 'Jetlinks',
-            })}
+          <div className={styles.content}>
+            <div className={styles.top}>
+              <div className={styles.header}>
+                <Link to="/">
+                  <img alt="logo" className={styles.logo} src="/logo.svg" />
+                  <span className={styles.title}>{SystemConst.SYSTEM_NAME}</span>
+                </Link>
+              </div>
+              <div className={styles.desc}>
+                {intl.formatMessage({
+                  id: 'pages.layouts.userLayout.title',
+                  defaultMessage: 'Jetlinks',
+                })}
+              </div>
+              <div className={styles.main}>
+                <Form form={loginForm} layout="horizontal" size="large" onAutoSubmit={doLogin}>
+                  <SchemaField schema={schema} />
+                  <div className={styles.remember}>
+                    <Checkbox
+                      onChange={(e) => {
+                        loginRef.current.expires = e.target.checked ? -1 : 3600000;
+                      }}
+                    >
+                      {' '}
+                      记住密码
+                    </Checkbox>
+                  </div>
+                  <Submit block size="large">
+                    {intl.formatMessage({
+                      id: 'pages.login.submit',
+                      defaultMessage: '登录',
+                    })}
+                  </Submit>
+                </Form>
+              </div>
+            </div>
           </div>
         </div>
-
-        <div className={styles.main}>
-          <Form form={loginForm} layout="vertical" size="large" onAutoSubmit={doLogin}>
-            <SchemaField schema={schema} />
-            <Submit block size="large">
-              {intl.formatMessage({
-                id: 'pages.login.submit',
-                defaultMessage: '登录',
-              })}
-            </Submit>
-          </Form>
+        <div className={styles.right}>
+          <div className={styles.systemName}>{SystemConst.SYSTEM_NAME}</div>
+          <div className={styles.systemDesc}>OPEN SOURCE INTERNET OF THINGS BASIC PLATFORM</div>
         </div>
       </div>
-      <Footer />
-    </div>
+    </Spin>
   );
 };