You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by ju...@apache.org on 2020/05/30 09:42:24 UTC

[incubator-apisix-dashboard] branch next updated: feature: new settings page (#217)

This is an automated email from the ASF dual-hosted git repository.

juzhiyuan pushed a commit to branch next
in repository https://gitbox.apache.org/repos/asf/incubator-apisix-dashboard.git


The following commit(s) were added to refs/heads/next by this push:
     new d5a4372  feature: new settings page (#217)
d5a4372 is described below

commit d5a4372269e7b69c5c025c98291821389e8a3ae1
Author: bzp2010 <bz...@gmail.com>
AuthorDate: Sat May 30 17:42:18 2020 +0800

    feature: new settings page (#217)
    
    * feature: move the settings page
    
    * feature: change logout button to settings
    
    * fix: clean code
---
 config/routes.ts                                   |  18 +--
 src/app.tsx                                        |   8 +-
 src/components/RightContent/AvatarDropdown.tsx     |  31 ++---
 src/locales/en-US/settings.ts                      |   1 +
 src/locales/zh-CN/settings.ts                      |   1 +
 src/pages/Settings/Settings.tsx                    | 121 ------------------
 src/pages/Settings/typing.d.ts                     |   9 --
 src/pages/settings/Settings.tsx                    | 129 +++++++++++++++++++
 src/pages/{Settings => settings}/index.ts          |   0
 src/pages/{Settings => settings}/service.ts        |   0
 src/pages/{user/login => settings}/style.less      |  10 ++
 .../user/login/components/Login/LoginContext.tsx   |  13 --
 .../user/login/components/Login/LoginItem.tsx      | 107 ----------------
 .../user/login/components/Login/LoginSubmit.tsx    |  23 ----
 src/pages/user/login/components/Login/LoginTab.tsx |  44 -------
 src/pages/user/login/components/Login/index.less   |  49 -------
 src/pages/user/login/components/Login/index.tsx    | 114 -----------------
 src/pages/user/login/components/Login/map.tsx      |  72 -----------
 src/pages/user/login/index.tsx                     | 142 ---------------------
 src/services/API.d.ts                              |   1 -
 src/services/user.ts                               |  20 +--
 21 files changed, 173 insertions(+), 740 deletions(-)

diff --git a/config/routes.ts b/config/routes.ts
index 79aa5ee..67c1a72 100644
--- a/config/routes.ts
+++ b/config/routes.ts
@@ -1,24 +1,14 @@
 const routes = [
   {
-    path: '/user',
-    layout: false,
-    routes: [
-      {
-        name: 'login',
-        path: '/user/login',
-        component: './user/login',
-      },
-    ],
-  },
-  {
     path: '/',
-    redirect: '/settings',
+    redirect: '/ssl',
   },
   {
     name: 'settings',
     path: '/settings',
-    icon: 'setting',
-    component: './Settings',
+    component: './settings',
+    layout: false,
+    hideInMenu: true,
   },
   {
     name: 'ssl',
diff --git a/src/app.tsx b/src/app.tsx
index 9971333..6336e81 100644
--- a/src/app.tsx
+++ b/src/app.tsx
@@ -3,7 +3,7 @@ import { notification } from 'antd';
 import { RequestConfig, history } from 'umi';
 import { BasicLayoutProps, Settings as LayoutSettings } from '@ant-design/pro-layout';
 
-import { getAdminAPIConfig } from '@/pages/Settings';
+import { getAdminAPIConfig } from '@/pages/settings';
 import RightContent from '@/components/RightContent';
 import Footer from '@/components/Footer';
 import { queryCurrent } from '@/services/user';
@@ -13,8 +13,8 @@ export async function getInitialState(): Promise<{
   currentUser?: API.CurrentUser;
   settings?: LayoutSettings;
 }> {
-  // 如果是登录页面,不执行
-  if (history.location.pathname !== '/user/login') {
+  // 如果是设置页面,不执行
+  if (history.location.pathname !== '/settings') {
     try {
       const currentUser = await queryCurrent();
       return {
@@ -22,7 +22,7 @@ export async function getInitialState(): Promise<{
         settings: defaultSettings,
       };
     } catch (error) {
-      history.push('/user/login');
+      history.push('/settings');
     }
   }
   return {
diff --git a/src/components/RightContent/AvatarDropdown.tsx b/src/components/RightContent/AvatarDropdown.tsx
index 5555355..9f3a674 100644
--- a/src/components/RightContent/AvatarDropdown.tsx
+++ b/src/components/RightContent/AvatarDropdown.tsx
@@ -1,9 +1,8 @@
 import React, { useCallback } from 'react';
-import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
+import { SettingOutlined, UserOutlined, SettingFilled } from '@ant-design/icons';
 import { Avatar, Menu, Spin } from 'antd';
 import { ClickParam } from 'antd/es/menu';
 import { history, useModel } from 'umi';
-import { getPageQuery } from '@/utils/utils';
 
 import { stringify } from 'querystring';
 import HeaderDropdown from '../HeaderDropdown';
@@ -16,17 +15,13 @@ export interface GlobalHeaderRightProps {
 /**
  * 退出登录,并且将当前的 url 保存
  */
-const loginOut = async () => {
-  const { redirect } = getPageQuery();
-  // Note: There may be security issues, please note
-  if (window.location.pathname !== '/user/login' && !redirect) {
-    history.replace({
-      pathname: '/user/login',
-      search: stringify({
-        redirect: window.location.href,
-      }),
-    });
-  }
+const settings = async () => {
+  history.replace({
+    pathname: '/settings',
+    search: stringify({
+      redirect: window.location.href,
+    }),
+  });
 };
 
 const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
@@ -34,9 +29,9 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
 
   const onMenuClick = useCallback((event: ClickParam) => {
     const { key } = event;
-    if (key === 'logout') {
+    if (key === 'settings') {
       setInitialState({ ...initialState, currentUser: undefined });
-      loginOut();
+      settings();
       return;
     }
     history.push(`/account/${key}`);
@@ -80,9 +75,9 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
       )}
       {menu && <Menu.Divider />}
 
-      <Menu.Item key="logout">
-        <LogoutOutlined />
-        退出登录
+      <Menu.Item key="settings">
+        <SettingFilled />
+        修改设置
       </Menu.Item>
     </Menu>
   );
diff --git a/src/locales/en-US/settings.ts b/src/locales/en-US/settings.ts
index fe2cff7..0c7081c 100644
--- a/src/locales/en-US/settings.ts
+++ b/src/locales/en-US/settings.ts
@@ -1,4 +1,5 @@
 export default {
+  'app.settings.admin-api': 'Admin API Config',
   'app.settings.item.admin-api-schema': 'Admin API Schema',
   'app.settings.item.admin-api-host': 'Admin API Host',
   'app.settings.item.admin-api-path': 'Admin API Path',
diff --git a/src/locales/zh-CN/settings.ts b/src/locales/zh-CN/settings.ts
index 03bc5f8..34d2fa2 100644
--- a/src/locales/zh-CN/settings.ts
+++ b/src/locales/zh-CN/settings.ts
@@ -1,4 +1,5 @@
 export default {
+  'app.settings.admin-api': '管理 API 配置',
   'app.settings.item.admin-api-schema': '管理 API 协议',
   'app.settings.item.admin-api-host': '管理 API 地址',
   'app.settings.item.admin-api-path': '管理 API 路径',
diff --git a/src/pages/Settings/Settings.tsx b/src/pages/Settings/Settings.tsx
deleted file mode 100644
index 4589c79..0000000
--- a/src/pages/Settings/Settings.tsx
+++ /dev/null
@@ -1,121 +0,0 @@
-import React, { useEffect } from 'react';
-import { useForm } from 'antd/es/form/util';
-import { Button, Card, Form, Input, notification, Select } from 'antd';
-import { useIntl, FormattedMessage, history } from 'umi';
-import { PageHeaderWrapper } from '@ant-design/pro-layout';
-
-import { getAdminAPIConfig } from './service';
-
-const { Option } = Select;
-
-const layout = {
-  labelCol: {
-    span: 4,
-  },
-  wrapperCol: {
-    span: 8,
-  },
-};
-
-const tailLayout = {
-  wrapperCol: {
-    offset: 4,
-  },
-};
-
-const Settings: React.FC = () => {
-  const [form] = useForm();
-  const { formatMessage } = useIntl();
-
-  useEffect(() => {
-    const adminAPIConfig = getAdminAPIConfig();
-    form.setFieldsValue({
-      adminAPISchema: adminAPIConfig.schema,
-      adminAPIHost: adminAPIConfig.host,
-      adminAPIPath: adminAPIConfig.path,
-      adminAPIKey: adminAPIConfig.key,
-    });
-  }, []);
-
-  const onFinish = (values: any) => {
-    localStorage.setItem('GLOBAL_ADMIN_API_SCHEMA', values.adminAPISchema);
-    localStorage.setItem('GLOBAL_ADMIN_API_HOST', values.adminAPIHost);
-    localStorage.setItem('GLOBAL_ADMIN_API_PATH', values.adminAPIPath);
-    localStorage.setItem('GLOBAL_ADMIN_API_KEY', values.adminAPIKey);
-
-    notification.success({
-      message: `${formatMessage({ id: 'component.global.update' })} Admin API ${formatMessage({
-        id: 'component.status.success',
-      }).toLowerCase()}`,
-    });
-  };
-
-  return (
-    <PageHeaderWrapper>
-      <Card>
-        <Form {...layout} form={form} onFinish={onFinish}>
-          <Form.Item
-            label={formatMessage({ id: 'app.settings.item.admin-api-schema' })}
-            name="adminAPISchema"
-            rules={[
-              {
-                required: true,
-                message: formatMessage({ id: 'app.settings.description.invalid-admin-api-schema' }),
-              },
-            ]}
-          >
-            <Select>
-              <Option value="http">HTTP</Option>
-              <Option value="https">HTTPS</Option>
-            </Select>
-          </Form.Item>
-
-          <Form.Item
-            label={formatMessage({ id: 'app.settings.item.admin-api-host' })}
-            name="adminAPIHost"
-            rules={[
-              {
-                required: true,
-                message: formatMessage({ id: 'app.settings.description.invalid-admin-api-host' }),
-              },
-            ]}
-          >
-            <Input />
-          </Form.Item>
-
-          <Form.Item
-            label={formatMessage({ id: 'app.settings.item.admin-api-path' })}
-            name="adminAPIPath"
-            rules={[
-              {
-                required: true,
-                message: formatMessage({ id: 'app.settings.description.invalid-admin-api-path' }),
-              },
-            ]}
-          >
-            <Input />
-          </Form.Item>
-
-          <Form.Item
-            label={formatMessage({ id: 'app.settings.item.admin-api-key' })}
-            name="adminAPIKey"
-          >
-            <Input />
-          </Form.Item>
-
-          <Form.Item {...tailLayout}>
-            <Button style={{ marginRight: 10 }} onClick={() => history.goBack()}>
-              <FormattedMessage id="component.global.cancel" />
-            </Button>
-
-            <Button htmlType="submit" type="primary">
-              <FormattedMessage id="component.global.save" />
-            </Button>
-          </Form.Item>
-        </Form>
-      </Card>
-    </PageHeaderWrapper>
-  );
-};
-
-export default Settings;
diff --git a/src/pages/Settings/typing.d.ts b/src/pages/Settings/typing.d.ts
deleted file mode 100644
index e846281..0000000
--- a/src/pages/Settings/typing.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-declare namespace SettingModule {
-  interface AdminAPIConfig {
-    schema: string;
-    host: string;
-    path: string;
-    prefix: string;
-    key: string;
-  }
-}
diff --git a/src/pages/settings/Settings.tsx b/src/pages/settings/Settings.tsx
new file mode 100644
index 0000000..5405c98
--- /dev/null
+++ b/src/pages/settings/Settings.tsx
@@ -0,0 +1,129 @@
+import { Button, Form, Input, notification, Select, Tabs } from 'antd';
+import React, { useEffect } from 'react';
+import { Link, SelectLang, FormattedMessage, useIntl } from 'umi';
+import logo from '@/assets/logo.svg';
+import styles from './style.less';
+import { useForm } from 'antd/es/form/util';
+import { getAdminAPIConfig } from './service';
+
+const { Option } = Select;
+const { TabPane } = Tabs;
+
+const Settings: React.FC<{}> = () => {
+  const [form] = useForm();
+  const { formatMessage } = useIntl();
+
+  useEffect(() => {
+    const adminAPIConfig = getAdminAPIConfig();
+    form.setFieldsValue({
+      adminAPISchema: adminAPIConfig.schema,
+      adminAPIHost: adminAPIConfig.host,
+      adminAPIPath: adminAPIConfig.path,
+      adminAPIKey: adminAPIConfig.key,
+    });
+  }, []);
+
+  const onFinish = (values: any) => {
+    localStorage.setItem('GLOBAL_ADMIN_API_SCHEMA', values.adminAPISchema);
+    localStorage.setItem('GLOBAL_ADMIN_API_HOST', values.adminAPIHost);
+    localStorage.setItem('GLOBAL_ADMIN_API_PATH', values.adminAPIPath);
+    localStorage.setItem('GLOBAL_ADMIN_API_KEY', values.adminAPIKey);
+
+    notification.success({
+      duration: 1,
+      message: `${formatMessage({ id: 'component.global.update' })} Admin API ${formatMessage({
+        id: 'component.status.success',
+      }).toLowerCase()}`,
+      onClose: () => {
+        document.location.href = '/';
+      },
+    });
+  };
+
+  return (
+    <div className={styles.container}>
+      <div className={styles.lang}>
+        <SelectLang />
+      </div>
+      <div className={styles.content}>
+        <div className={styles.top}>
+          <div className={styles.header}>
+            <Link to="/">
+              <img alt="logo" className={styles.logo} src={logo} />
+              <span className={styles.title}>APISIX Dashboard</span>
+            </Link>
+          </div>
+          <div className={styles.desc}>Cloud-Native Microservices API Gateway</div>
+        </div>
+
+        <div className={styles.main}>
+          <Tabs>
+            <TabPane tab={formatMessage({ id: 'app.settings.admin-api' })}>
+              <Form form={form} onFinish={onFinish}>
+                <Form.Item
+                  name="adminAPISchema"
+                  rules={[
+                    {
+                      required: true,
+                      message: formatMessage({
+                        id: 'app.settings.description.invalid-admin-api-schema',
+                      }),
+                    },
+                  ]}
+                >
+                  <Select
+                    placeholder={formatMessage({ id: 'app.settings.item.admin-api-schema' })}
+                    allowClear
+                  >
+                    <Option value="http">HTTP</Option>
+                    <Option value="https">HTTPS</Option>
+                  </Select>
+                </Form.Item>
+
+                <Form.Item
+                  name="adminAPIHost"
+                  rules={[
+                    {
+                      required: true,
+                      message: formatMessage({
+                        id: 'app.settings.description.invalid-admin-api-host',
+                      }),
+                    },
+                  ]}
+                >
+                  <Input placeholder={formatMessage({ id: 'app.settings.item.admin-api-host' })} />
+                </Form.Item>
+
+                <Form.Item
+                  name="adminAPIPath"
+                  rules={[
+                    {
+                      required: true,
+                      message: formatMessage({
+                        id: 'app.settings.description.invalid-admin-api-path',
+                      }),
+                    },
+                  ]}
+                >
+                  <Input placeholder={formatMessage({ id: 'app.settings.item.admin-api-path' })} />
+                </Form.Item>
+
+                <Form.Item name="adminAPIKey">
+                  <Input placeholder={formatMessage({ id: 'app.settings.item.admin-api-key' })} />
+                </Form.Item>
+
+                <Form.Item>
+                  <Button size="large" type="primary" htmlType="submit" block>
+                    <FormattedMessage id="component.global.save" />
+                  </Button>
+                </Form.Item>
+              </Form>
+            </TabPane>
+          </Tabs>
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default Settings;
diff --git a/src/pages/Settings/index.ts b/src/pages/settings/index.ts
similarity index 100%
rename from src/pages/Settings/index.ts
rename to src/pages/settings/index.ts
diff --git a/src/pages/Settings/service.ts b/src/pages/settings/service.ts
similarity index 100%
rename from src/pages/Settings/service.ts
rename to src/pages/settings/service.ts
diff --git a/src/pages/user/login/style.less b/src/pages/settings/style.less
similarity index 91%
rename from src/pages/user/login/style.less
rename to src/pages/settings/style.less
index c195315..539f1ee 100644
--- a/src/pages/user/login/style.less
+++ b/src/pages/settings/style.less
@@ -1,5 +1,15 @@
 @import '~antd/es/style/themes/default.less';
 
+.login {
+  :global {
+    .ant-tabs .ant-tabs-bar {
+      margin-bottom: 24px;
+      text-align: center;
+      border-bottom: 0;
+    }
+  }
+}
+
 .container {
   display: flex;
   flex-direction: column;
diff --git a/src/pages/user/login/components/Login/LoginContext.tsx b/src/pages/user/login/components/Login/LoginContext.tsx
deleted file mode 100644
index ae571e0..0000000
--- a/src/pages/user/login/components/Login/LoginContext.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { createContext } from 'react';
-
-export interface LoginContextProps {
-  tabUtil?: {
-    addTab: (id: string) => void;
-    removeTab: (id: string) => void;
-  };
-  updateActive?: (activeItem: { [key: string]: string } | string) => void;
-}
-
-const LoginContext: React.Context<LoginContextProps> = createContext({});
-
-export default LoginContext;
diff --git a/src/pages/user/login/components/Login/LoginItem.tsx b/src/pages/user/login/components/Login/LoginItem.tsx
deleted file mode 100644
index 9473240..0000000
--- a/src/pages/user/login/components/Login/LoginItem.tsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import { Input, Form } from 'antd';
-import React from 'react';
-import { FormItemProps } from 'antd/es/form/FormItem';
-
-import ItemMap from './map';
-import LoginContext, { LoginContextProps } from './LoginContext';
-
-export type WrappedLoginItemProps = LoginItemProps;
-export type LoginItemKeyType = keyof typeof ItemMap;
-export interface LoginItemType {
-  UserName: React.FC<WrappedLoginItemProps>;
-  Password: React.FC<WrappedLoginItemProps>;
-  Mobile: React.FC<WrappedLoginItemProps>;
-  Captcha: React.FC<WrappedLoginItemProps>;
-}
-
-export interface LoginItemProps extends Partial<FormItemProps> {
-  name?: string;
-  style?: React.CSSProperties;
-  placeholder?: string;
-  buttonText?: React.ReactNode;
-  countDown?: number;
-  getCaptchaButtonText?: string;
-  getCaptchaSecondText?: string;
-  updateActive?: LoginContextProps['updateActive'];
-  type?: string;
-  defaultValue?: string;
-  customProps?: { [key: string]: unknown };
-  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
-  tabUtil?: LoginContextProps['tabUtil'];
-}
-
-const FormItem = Form.Item;
-
-const getFormItemOptions = ({
-  onChange,
-  defaultValue,
-  customProps = {},
-  rules,
-}: LoginItemProps) => {
-  const options: {
-    rules?: LoginItemProps['rules'];
-    onChange?: LoginItemProps['onChange'];
-    initialValue?: LoginItemProps['defaultValue'];
-  } = {
-    rules: rules || (customProps.rules as LoginItemProps['rules']),
-  };
-  if (onChange) {
-    options.onChange = onChange;
-  }
-  if (defaultValue) {
-    options.initialValue = defaultValue;
-  }
-  return options;
-};
-
-const LoginItem: React.FC<LoginItemProps> = (props) => {
-  // 这么写是为了防止restProps中 带入 onChange, defaultValue, rules props tabUtil
-  const {
-    onChange,
-    customProps,
-    defaultValue,
-    rules,
-    name,
-    getCaptchaButtonText,
-    getCaptchaSecondText,
-    updateActive,
-    type,
-    tabUtil,
-    ...restProps
-  } = props;
-
-  if (!name) {
-    return null;
-  }
-  // get getFieldDecorator props
-  const options = getFormItemOptions(props);
-  const otherProps = restProps || {};
-
-  return (
-    <FormItem name={name} {...options}>
-      <Input {...customProps} {...otherProps} />
-    </FormItem>
-  );
-};
-
-const LoginItems: Partial<LoginItemType> = {};
-
-Object.keys(ItemMap).forEach((key) => {
-  const item = ItemMap[key];
-  LoginItems[key] = (props: LoginItemProps) => (
-    <LoginContext.Consumer>
-      {(context) => (
-        <LoginItem
-          customProps={item.props}
-          rules={item.rules}
-          {...props}
-          type={key}
-          {...context}
-          updateActive={context.updateActive}
-        />
-      )}
-    </LoginContext.Consumer>
-  );
-});
-
-export default LoginItems as LoginItemType;
diff --git a/src/pages/user/login/components/Login/LoginSubmit.tsx b/src/pages/user/login/components/Login/LoginSubmit.tsx
deleted file mode 100644
index 280fb0f..0000000
--- a/src/pages/user/login/components/Login/LoginSubmit.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import { Button, Form } from 'antd';
-
-import { ButtonProps } from 'antd/es/button';
-import React from 'react';
-import classNames from 'classnames';
-import styles from './index.less';
-
-const FormItem = Form.Item;
-
-interface LoginSubmitProps extends ButtonProps {
-  className?: string;
-}
-
-const LoginSubmit: React.FC<LoginSubmitProps> = ({ className, ...rest }) => {
-  const clsString = classNames(styles.submit, className);
-  return (
-    <FormItem>
-      <Button size="large" className={clsString} type="primary" htmlType="submit" {...rest} />
-    </FormItem>
-  );
-};
-
-export default LoginSubmit;
diff --git a/src/pages/user/login/components/Login/LoginTab.tsx b/src/pages/user/login/components/Login/LoginTab.tsx
deleted file mode 100644
index adbed2a..0000000
--- a/src/pages/user/login/components/Login/LoginTab.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React, { useEffect } from 'react';
-import { TabPaneProps } from 'antd/es/tabs';
-import { Tabs } from 'antd';
-import LoginContext, { LoginContextProps } from './LoginContext';
-
-const { TabPane } = Tabs;
-
-const generateId = (() => {
-  let i = 0;
-  return (prefix = '') => {
-    i += 1;
-    return `${prefix}${i}`;
-  };
-})();
-
-interface LoginTabProps extends TabPaneProps {
-  tabUtil: LoginContextProps['tabUtil'];
-  active?: boolean;
-}
-
-const LoginTab: React.FC<LoginTabProps> = (props) => {
-  useEffect(() => {
-    const uniqueId = generateId('login-tab-');
-    const { tabUtil } = props;
-    if (tabUtil) {
-      tabUtil.addTab(uniqueId);
-    }
-  }, []);
-  const { children } = props;
-  return <TabPane {...props}>{props.active && children}</TabPane>;
-};
-
-const WrapContext: React.FC<TabPaneProps> & {
-  typeName: string;
-} = (props) => (
-  <LoginContext.Consumer>
-    {(value) => <LoginTab tabUtil={value.tabUtil} {...props} />}
-  </LoginContext.Consumer>
-);
-
-// 标志位 用来判断是不是自定义组件
-WrapContext.typeName = 'LoginTab';
-
-export default WrapContext;
diff --git a/src/pages/user/login/components/Login/index.less b/src/pages/user/login/components/Login/index.less
deleted file mode 100644
index dc16aab..0000000
--- a/src/pages/user/login/components/Login/index.less
+++ /dev/null
@@ -1,49 +0,0 @@
-@import '~antd/es/style/themes/default.less';
-
-.login {
-  :global {
-    .ant-tabs .ant-tabs-bar {
-      margin-bottom: 24px;
-      text-align: center;
-      border-bottom: 0;
-    }
-  }
-
-  .getCaptcha {
-    display: block;
-    width: 100%;
-  }
-
-  .icon {
-    margin-left: 16px;
-    color: rgba(0, 0, 0, 0.2);
-    font-size: 24px;
-    vertical-align: middle;
-    cursor: pointer;
-    transition: color 0.3s;
-
-    &:hover {
-      color: @primary-color;
-    }
-  }
-
-  .other {
-    margin-top: 24px;
-    line-height: 22px;
-    text-align: left;
-
-    .register {
-      float: right;
-    }
-  }
-
-  .prefixIcon {
-    color: @disabled-color;
-    font-size: @font-size-base;
-  }
-
-  .submit {
-    width: 100%;
-    margin-top: 24px;
-  }
-}
diff --git a/src/pages/user/login/components/Login/index.tsx b/src/pages/user/login/components/Login/index.tsx
deleted file mode 100644
index 8c550e3..0000000
--- a/src/pages/user/login/components/Login/index.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import { Tabs, Form } from 'antd';
-import React, { useState } from 'react';
-import useMergeValue from 'use-merge-value';
-import classNames from 'classnames';
-import { FormInstance } from 'antd/es/form';
-import { LoginParamsType } from '@/services/login';
-
-import LoginContext from './LoginContext';
-import LoginItem, { LoginItemProps } from './LoginItem';
-import LoginSubmit from './LoginSubmit';
-import LoginTab from './LoginTab';
-import styles from './index.less';
-
-export interface LoginProps {
-  activeKey?: string;
-  onTabChange?: (key: string) => void;
-  style?: React.CSSProperties;
-  onSubmit?: (values: LoginParamsType) => void;
-  className?: string;
-  from?: FormInstance;
-  children: React.ReactElement<typeof LoginTab>[];
-}
-
-interface LoginType extends React.FC<LoginProps> {
-  Tab: typeof LoginTab;
-  Submit: typeof LoginSubmit;
-  UserName: React.FunctionComponent<LoginItemProps>;
-  Password: React.FunctionComponent<LoginItemProps>;
-}
-
-const Login: LoginType = (props) => {
-  const { className } = props;
-  const [tabs, setTabs] = useState<string[]>([]);
-  const [active, setActive] = useState({});
-  const [type, setType] = useMergeValue('', {
-    value: props.activeKey,
-    onChange: props.onTabChange,
-  });
-  const TabChildren: React.ReactComponentElement<typeof LoginTab>[] = [];
-  const otherChildren: React.ReactElement<unknown>[] = [];
-  React.Children.forEach(
-    props.children,
-    (child: React.ReactComponentElement<typeof LoginTab> | React.ReactElement<unknown>) => {
-      if (!child) {
-        return;
-      }
-      if ((child.type as { typeName: string }).typeName === 'LoginTab') {
-        TabChildren.push(child as React.ReactComponentElement<typeof LoginTab>);
-      } else {
-        otherChildren.push(child);
-      }
-    },
-  );
-  return (
-    <LoginContext.Provider
-      value={{
-        tabUtil: {
-          addTab: (id) => {
-            setTabs([...tabs, id]);
-          },
-          removeTab: (id) => {
-            setTabs(tabs.filter((currentId) => currentId !== id));
-          },
-        },
-        updateActive: (activeItem) => {
-          if (!active) return;
-          if (active[type]) {
-            active[type].push(activeItem);
-          } else {
-            active[type] = [activeItem];
-          }
-          setActive(active);
-        },
-      }}
-    >
-      <div className={classNames(className, styles.login)}>
-        <Form
-          form={props.from}
-          onFinish={(values) => {
-            if (props.onSubmit) {
-              props.onSubmit(values as LoginParamsType);
-            }
-          }}
-        >
-          {tabs.length ? (
-            <React.Fragment>
-              <Tabs
-                animated={false}
-                className={styles.tabs}
-                activeKey={type}
-                onChange={(activeKey) => {
-                  setType(activeKey);
-                }}
-              >
-                {TabChildren}
-              </Tabs>
-              {otherChildren}
-            </React.Fragment>
-          ) : (
-            props.children
-          )}
-        </Form>
-      </div>
-    </LoginContext.Provider>
-  );
-};
-
-Login.Tab = LoginTab;
-Login.Submit = LoginSubmit;
-
-Login.UserName = LoginItem.UserName;
-Login.Password = LoginItem.Password;
-
-export default Login;
diff --git a/src/pages/user/login/components/Login/map.tsx b/src/pages/user/login/components/Login/map.tsx
deleted file mode 100644
index bf2f55f..0000000
--- a/src/pages/user/login/components/Login/map.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import { LockTwoTone, MailTwoTone, MobileTwoTone, UserOutlined } from '@ant-design/icons';
-import React from 'react';
-import styles from './index.less';
-
-export default {
-  UserName: {
-    props: {
-      size: 'large',
-      id: 'userName',
-      prefix: (
-        <UserOutlined
-          style={{
-            color: '#1890ff',
-          }}
-          className={styles.prefixIcon}
-        />
-      ),
-      placeholder: 'admin',
-    },
-    rules: [
-      {
-        required: true,
-        message: 'Please enter username!',
-      },
-    ],
-  },
-  Password: {
-    props: {
-      size: 'large',
-      prefix: <LockTwoTone className={styles.prefixIcon} />,
-      type: 'password',
-      id: 'password',
-      placeholder: '888888',
-    },
-    rules: [
-      {
-        required: true,
-        message: 'Please enter password!',
-      },
-    ],
-  },
-  Mobile: {
-    props: {
-      size: 'large',
-      prefix: <MobileTwoTone className={styles.prefixIcon} />,
-      placeholder: 'mobile number',
-    },
-    rules: [
-      {
-        required: true,
-        message: 'Please enter mobile number!',
-      },
-      {
-        pattern: /^1\d{10}$/,
-        message: 'Wrong mobile number format!',
-      },
-    ],
-  },
-  Captcha: {
-    props: {
-      size: 'large',
-      prefix: <MailTwoTone className={styles.prefixIcon} />,
-      placeholder: 'captcha',
-    },
-    rules: [
-      {
-        required: true,
-        message: 'Please enter Captcha!',
-      },
-    ],
-  },
-};
diff --git a/src/pages/user/login/index.tsx b/src/pages/user/login/index.tsx
deleted file mode 100644
index 238dee8..0000000
--- a/src/pages/user/login/index.tsx
+++ /dev/null
@@ -1,142 +0,0 @@
-import { Alert, Checkbox, message } from 'antd';
-import React, { useState } from 'react';
-import { Link, SelectLang, history, useModel } from 'umi';
-import { getPageQuery } from '@/utils/utils';
-import logo from '@/assets/logo.svg';
-import { fakeAccountLogin } from '@/services/login';
-import LoginFrom from './components/Login';
-import styles from './style.less';
-
-const { Tab, UserName, Password, Submit } = LoginFrom;
-
-const LoginMessage: React.FC<{
-  content: string;
-}> = ({ content }) => (
-  <Alert
-    style={{
-      marginBottom: 24,
-    }}
-    message={content}
-    type="error"
-    showIcon
-  />
-);
-
-/**
- * 此方法会跳转到 redirect 参数所在的位置
- */
-const replaceGoto = () => {
-  const urlParams = new URL(window.location.href);
-  const params = getPageQuery();
-  let { redirect } = params as { redirect: string };
-  if (redirect) {
-    const redirectUrlParams = new URL(redirect);
-    if (redirectUrlParams.origin === urlParams.origin) {
-      redirect = redirect.substr(urlParams.origin.length);
-      if (redirect.match(/^\/.*#/)) {
-        redirect = redirect.substr(redirect.indexOf('#') + 1);
-      }
-    } else {
-      window.location.href = '/';
-      return;
-    }
-  }
-  history.replace(redirect || '/');
-};
-
-const Login: React.FC<{}> = () => {
-  const [userLoginState, setUserLoginState] = useState<API.LoginStateType>({});
-  const [submitting, setSubmitting] = useState(false);
-
-  const { refresh } = useModel('@@initialState');
-  const [autoLogin, setAutoLogin] = useState(true);
-  const [type, setType] = useState<string>('account');
-
-  const handleSubmit = async () => {
-    setSubmitting(true);
-    try {
-      // 登录
-      const msg = await fakeAccountLogin();
-      if (msg.status === 'ok') {
-        message.success('登陆成功!');
-        replaceGoto();
-        setTimeout(() => {
-          refresh();
-        }, 0);
-        return;
-      }
-      // 如果失败去设置用户错误信息
-      setUserLoginState(msg);
-    } catch (error) {
-      message.error('登陆失败,请重试!');
-    }
-    setSubmitting(false);
-  };
-
-  const { status, type: loginType } = userLoginState;
-
-  return (
-    <div className={styles.container}>
-      <div className={styles.lang}>
-        <SelectLang />
-      </div>
-      <div className={styles.content}>
-        <div className={styles.top}>
-          <div className={styles.header}>
-            <Link to="/">
-              <img alt="logo" className={styles.logo} src={logo} />
-              <span className={styles.title}>APISIX Dashboard</span>
-            </Link>
-          </div>
-          <div className={styles.desc}>Cloud-Native Microservices API Gateway</div>
-        </div>
-
-        <div className={styles.main}>
-          <LoginFrom activeKey={type} onTabChange={setType} onSubmit={handleSubmit}>
-            <Tab key="account" tab="账户密码登录">
-              {status === 'error' && loginType === 'account' && !submitting && (
-                <LoginMessage content="账户或密码错误" />
-              )}
-
-              <UserName
-                name="userName"
-                placeholder="请输入用户名"
-                rules={[
-                  {
-                    required: true,
-                    message: '请输入用户名!',
-                  },
-                ]}
-              />
-              <Password
-                name="password"
-                placeholder="请输入密码"
-                rules={[
-                  {
-                    required: true,
-                    message: '请输入密码!',
-                  },
-                ]}
-              />
-            </Tab>
-            <div>
-              <Checkbox checked={autoLogin} onChange={(e) => setAutoLogin(e.target.checked)}>
-                自动登录
-              </Checkbox>
-              <a
-                style={{
-                  float: 'right',
-                }}
-              >
-                忘记密码
-              </a>
-            </div>
-            <Submit loading={submitting}>登录</Submit>
-          </LoginFrom>
-        </div>
-      </div>
-    </div>
-  );
-};
-
-export default Login;
diff --git a/src/services/API.d.ts b/src/services/API.d.ts
index d31fb9e..d66825d 100644
--- a/src/services/API.d.ts
+++ b/src/services/API.d.ts
@@ -4,7 +4,6 @@ declare namespace API {
     name?: string;
     userid?: string;
     access?: 'user' | 'guest' | 'admin';
-    unreadCount?: number;
   }
 
   export interface LoginStateType {
diff --git a/src/services/user.ts b/src/services/user.ts
index 2734525..d22fb44 100644
--- a/src/services/user.ts
+++ b/src/services/user.ts
@@ -1,19 +1,21 @@
 import { request } from 'umi';
+import logo from '@/assets/logo.svg';
 
 export async function query() {
   return request<API.CurrentUser[]>('/api/users');
 }
 
 export async function queryCurrent(): Promise<API.CurrentUser> {
-  return Promise.resolve({
-    name: 'APISIX User',
-    avatar:
-      'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjxzdmcgdmlld0JveD0iMCAwIDUwMCA1MDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQogIDxkZWZzPg0KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iaWQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjI1MTE5LjgiIHkxPSIxMTA1Mi41IiB4Mj0iMjE3MjUuNyIgeTI9IjIxNTUxLjciIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMC4wMjgwOTUsIDAsIDAsIDAuMDI4MDk1LCAtNDkyLjg2NzA5NiwgLTE0NC43Njk4MjEpIj4NCiAgICAgIDxzdG9wIG9mZnNldD0iMCIgc3R5bGU9InN0b3AtY29 [...]
-    userid: '00000001',
-    notifyCount: 12,
-    unreadCount: 11,
-    access: 'admin',
-  });
+  if (!localStorage.getItem('GLOBAL_ADMIN_API_HOST')) {
+    throw new Error('Need Settings');
+  } else {
+    return Promise.resolve({
+      name: 'APISIX User',
+      avatar: logo,
+      userid: '00000001',
+      access: 'admin',
+    });
+  }
 }
 
 export async function queryNotices(): Promise<any> {