Sfoglia il codice sorgente

♻️Refactor: Login Page

Apple\Apple 9 mesi fa
parent
commit
cb281dfc11

+ 1 - 1
web/src/components/Footer.js

@@ -22,7 +22,7 @@ const FooterBar = () => {
   const currentYear = new Date().getFullYear();
 
   const customFooter = useMemo(() => (
-    <footer className="relative bg-gray-900 dark:bg-[#1C1F23] mt-[60px] h-auto py-16 px-6 md:px-24 w-full flex flex-col items-center justify-between overflow-hidden">
+    <footer className="relative bg-gray-900 dark:bg-[#1C1F23] h-auto py-16 px-6 md:px-24 w-full flex flex-col items-center justify-between overflow-hidden">
       <div className="absolute hidden md:block top-[204px] left-[-100px] w-[151px] h-[151px] rounded-full bg-[#FFD166]"></div>
       <div className="absolute md:hidden bottom-[20px] left-[-50px] w-[80px] h-[80px] rounded-full bg-[#FFD166] opacity-60"></div>
 

+ 250 - 198
web/src/components/LoginForm.js

@@ -8,6 +8,7 @@ import {
   showInfo,
   showSuccess,
   updateAPI,
+  getSystemName,
 } from '../helpers';
 import {
   onGitHubOAuthClicked,
@@ -21,19 +22,19 @@ import {
   Divider,
   Form,
   Icon,
-  Layout,
   Modal,
 } from '@douyinfe/semi-ui';
 import Title from '@douyinfe/semi-ui/lib/es/typography/title';
 import Text from '@douyinfe/semi-ui/lib/es/typography/text';
 import TelegramLoginButton from 'react-telegram-login';
 
-import { IconGithubLogo, IconAlarm } from '@douyinfe/semi-icons';
+import { IconGithubLogo, IconMail } from '@douyinfe/semi-icons';
 import OIDCIcon from './OIDCIcon.js';
 import WeChatIcon from './WeChatIcon';
 import { setUserData } from '../helpers/data.js';
 import LinuxDoIcon from './LinuxDoIcon.js';
 import { useTranslation } from 'react-i18next';
+import Background from '../images/example.png';
 
 const LoginForm = () => {
   const [inputs, setInputs] = useState({
@@ -51,9 +52,12 @@ const LoginForm = () => {
   let navigate = useNavigate();
   const [status, setStatus] = useState({});
   const [showWeChatLoginModal, setShowWeChatLoginModal] = useState(false);
+  const [showEmailLogin, setShowEmailLogin] = useState(false);
+  const [showOtherOptions, setShowOtherOptions] = useState(false);
   const { t } = useTranslation();
 
   const logo = getLogo();
+  const systemName = getSystemName();
 
   let affCode = new URLSearchParams(window.location.search).get('aff');
   if (affCode) {
@@ -132,7 +136,7 @@ const LoginForm = () => {
             centered: true,
           });
         }
-        navigate('/token');
+        navigate('/console/token');
       } else {
         showError(message);
       }
@@ -173,211 +177,259 @@ const LoginForm = () => {
     }
   };
 
-  return (
-    <div>
-      <Layout>
-        <Layout.Header></Layout.Header>
-        <Layout.Content>
-          <div
-            style={{
-              justifyContent: 'center',
-              display: 'flex',
-              marginTop: 120,
-            }}
-          >
-            <div style={{ width: 500 }}>
-              <Card>
-                <Title heading={2} style={{ textAlign: 'center' }}>
-                  {t('用户登录')}
-                </Title>
-                <Form>
-                  <Form.Input
-                    field={'username'}
-                    label={t('用户名/邮箱')}
-                    placeholder={t('用户名/邮箱')}
-                    name='username'
-                    onChange={(value) => handleChange('username', value)}
-                  />
-                  <Form.Input
-                    field={'password'}
-                    label={t('密码')}
-                    placeholder={t('密码')}
-                    name='password'
-                    type='password'
-                    onChange={(value) => handleChange('password', value)}
-                  />
+  const renderOAuthOptions = () => {
+    return (
+      <div className="flex flex-col items-center">
+        <div className="w-full max-w-md">
+          <div className="flex items-center justify-center mb-6 gap-2">
+            <img src={logo} alt="Logo" className="h-10 rounded-full" />
+            <Title heading={3} className='!text-white'>{systemName}</Title>
+          </div>
 
+          <Card className="shadow-xl border-0 !rounded-2xl overflow-hidden">
+            <div className="flex justify-center pt-6 pb-2">
+              <Title heading={3} className="text-gray-800 dark:text-gray-200">{t('登 录')}</Title>
+            </div>
+            <div className="px-2 py-8">
+              <div className="space-y-3">
+                {status.wechat_login && (
                   <Button
-                    theme='solid'
-                    style={{ width: '100%' }}
-                    type={'primary'}
-                    size='large'
-                    htmlType={'submit'}
-                    onClick={handleSubmit}
+                    theme='outline'
+                    className="w-full h-12 flex items-center justify-center !rounded-full border border-gray-200 hover:bg-gray-50 transition-colors"
+                    type="tertiary"
+                    icon={<Icon svg={<WeChatIcon />} style={{ color: '#07C160' }} />}
+                    size="large"
+                    onClick={onWeChatLoginClicked}
                   >
-                    {t('登录')}
+                    <span className="ml-3">{t('使用 微信 继续')}</span>
                   </Button>
-                </Form>
-                <div
-                  style={{
-                    display: 'flex',
-                    justifyContent: 'space-between',
-                    marginTop: 20,
-                  }}
-                >
-                  <Text>
-                    {t('没有账户?')}{' '}
-                    <Link to='/register'>{t('点击注册')}</Link>
-                  </Text>
-                  <Text>
-                    {t('忘记密码?')} <Link to='/reset'>{t('点击重置')}</Link>
-                  </Text>
-                </div>
-                {status.github_oauth ||
-                status.oidc_enabled ||
-                status.wechat_login ||
-                status.telegram_oauth ||
-                status.linuxdo_oauth ? (
-                  <>
-                    <Divider margin='12px' align='center'>
-                      {t('第三方登录')}
-                    </Divider>
-                    <div
-                      style={{
-                        display: 'flex',
-                        justifyContent: 'center',
-                        marginTop: 20,
-                      }}
-                    >
-                      {status.github_oauth ? (
-                        <Button
-                          type='primary'
-                          icon={<IconGithubLogo />}
-                          onClick={() =>
-                            onGitHubOAuthClicked(status.github_client_id)
-                          }
-                        />
-                      ) : (
-                        <></>
-                      )}
-                      {status.oidc_enabled ? (
-                        <Button
-                          type='primary'
-                          icon={<OIDCIcon />}
-                          onClick={() =>
-                            onOIDCClicked(
-                              status.oidc_authorization_endpoint,
-                              status.oidc_client_id,
-                            )
-                          }
-                        />
-                      ) : (
-                        <></>
-                      )}
-                      {status.linuxdo_oauth ? (
-                        <Button
-                          icon={<LinuxDoIcon />}
-                          onClick={() =>
-                            onLinuxDOOAuthClicked(status.linuxdo_client_id)
-                          }
-                        />
-                      ) : (
-                        <></>
-                      )}
-                      {status.wechat_login ? (
-                        <Button
-                          type='primary'
-                          style={{ color: 'rgba(var(--semi-green-5), 1)' }}
-                          icon={<Icon svg={<WeChatIcon />} />}
-                          onClick={onWeChatLoginClicked}
-                        />
-                      ) : (
-                        <></>
-                      )}
-                    </div>
-                    {status.telegram_oauth ? (
-                      <>
-                        <div
-                          style={{
-                            display: 'flex',
-                            justifyContent: 'center',
-                            marginTop: 5,
-                          }}
-                        >
-                          <TelegramLoginButton
-                            dataOnauth={onTelegramLoginClicked}
-                            botName={status.telegram_bot_name}
-                          />
-                        </div>
-                      </>
-                    ) : (
-                      <></>
-                    )}
-                  </>
-                ) : (
-                  <></>
                 )}
-                <Modal
-                  title={t('微信扫码登录')}
-                  visible={showWeChatLoginModal}
-                  maskClosable={true}
-                  onOk={onSubmitWeChatVerificationCode}
-                  onCancel={() => setShowWeChatLoginModal(false)}
-                  okText={t('登录')}
-                  size={'small'}
-                  centered={true}
-                >
-                  <div
-                    style={{
-                      display: 'flex',
-                      alignItem: 'center',
-                      flexDirection: 'column',
-                    }}
+
+                {status.github_oauth && (
+                  <Button
+                    theme='outline'
+                    className="w-full h-12 flex items-center justify-center !rounded-full border border-gray-200 hover:bg-gray-50 transition-colors"
+                    type="tertiary"
+                    icon={<IconGithubLogo size="large" style={{ color: '#24292e' }} />}
+                    size="large"
+                    onClick={() => onGitHubOAuthClicked(status.github_client_id)}
                   >
-                    <img src={status.wechat_qrcode} />
-                  </div>
-                  <div style={{ textAlign: 'center' }}>
-                    <p>
-                      {t(
-                        '微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)',
-                      )}
-                    </p>
-                  </div>
-                  <Form size='large'>
-                    <Form.Input
-                      field={'wechat_verification_code'}
-                      placeholder={t('验证码')}
-                      label={t('验证码')}
-                      value={inputs.wechat_verification_code}
-                      onChange={(value) =>
-                        handleChange('wechat_verification_code', value)
-                      }
+                    <span className="ml-3">{t('使用 GitHub 继续')}</span>
+                  </Button>
+                )}
+
+                {status.oidc_enabled && (
+                  <Button
+                    theme='outline'
+                    className="w-full h-12 flex items-center justify-center !rounded-full border border-gray-200 hover:bg-gray-50 transition-colors"
+                    type="tertiary"
+                    icon={<OIDCIcon style={{ color: '#1877F2', width: '20px', height: '20px' }} />}
+                    size="large"
+                    onClick={() =>
+                      onOIDCClicked(
+                        status.oidc_authorization_endpoint,
+                        status.oidc_client_id
+                      )
+                    }
+                  >
+                    <span className="ml-3">{t('使用 OIDC 继续')}</span>
+                  </Button>
+                )}
+
+                {status.linuxdo_oauth && (
+                  <Button
+                    theme='outline'
+                    className="w-full h-12 flex items-center justify-center !rounded-full border border-gray-200 hover:bg-gray-50 transition-colors"
+                    type="tertiary"
+                    icon={<LinuxDoIcon style={{ color: '#E95420', width: '20px', height: '20px' }} />}
+                    size="large"
+                    onClick={() => onLinuxDOOAuthClicked(status.linuxdo_client_id)}
+                  >
+                    <span className="ml-3">{t('使用 LinuxDO 继续')}</span>
+                  </Button>
+                )}
+
+                {status.telegram_oauth && (
+                  <div className="flex justify-center my-2">
+                    <TelegramLoginButton
+                      dataOnauth={onTelegramLoginClicked}
+                      botName={status.telegram_bot_name}
                     />
-                  </Form>
-                </Modal>
-              </Card>
-              {turnstileEnabled ? (
-                <div
-                  style={{
-                    display: 'flex',
-                    justifyContent: 'center',
-                    marginTop: 20,
-                  }}
+                  </div>
+                )}
+
+                <Divider margin='12px' align='center'>
+                  {t('或')}
+                </Divider>
+
+                <Button
+                  theme="solid"
+                  type="primary"
+                  className="w-full h-12 flex items-center justify-center bg-black text-white !rounded-full hover:bg-gray-800 transition-colors"
+                  icon={<IconMail size="large" />}
+                  size="large"
+                  onClick={() => setShowEmailLogin(true)}
                 >
-                  <Turnstile
-                    sitekey={turnstileSiteKey}
-                    onVerify={(token) => {
-                      setTurnstileToken(token);
-                    }}
-                  />
-                </div>
-              ) : (
-                <></>
-              )}
+                  <span className="ml-3">{t('使用 邮箱 登录')}</span>
+                </Button>
+              </div>
+
+              <div className="mt-6 text-center text-sm">
+                <Text>{t('没有账户?')} <Link to="/register" className="text-blue-600 hover:text-blue-800 font-medium">{t('注册')}</Link></Text>
+              </div>
+            </div>
+          </Card>
+
+          {turnstileEnabled && (
+            <div className="flex justify-center mt-6">
+              <Turnstile
+                sitekey={turnstileSiteKey}
+                onVerify={(token) => {
+                  setTurnstileToken(token);
+                }}
+              />
             </div>
+          )}
+        </div>
+      </div>
+    );
+  };
+
+  const renderEmailLoginForm = () => {
+    return (
+      <div className="flex flex-col items-center">
+        <div className="w-full max-w-md">
+          <div className="flex items-center justify-center mb-6 gap-2">
+            <img src={logo} alt="Logo" className="h-10 rounded-full" />
+            <Title heading={3}>{systemName}</Title>
           </div>
-        </Layout.Content>
-      </Layout>
+
+          <Card className="shadow-xl border-0 !rounded-2xl overflow-hidden">
+            <div className="flex justify-center pt-6 pb-2">
+              <Title heading={3} className="text-gray-800 dark:text-gray-200">{t('登 录')}</Title>
+            </div>
+            <div className="px-2 py-8">
+              <Form className="space-y-3">
+                <Form.Input
+                  field="username"
+                  label={t('邮箱')}
+                  placeholder={t('请输入您的邮箱地址')}
+                  name="username"
+                  size="large"
+                  className="!rounded-md"
+                  onChange={(value) => handleChange('username', value)}
+                />
+
+                <Form.Input
+                  field="password"
+                  label={t('密码')}
+                  placeholder={t('请输入您的密码')}
+                  name="password"
+                  type="password"
+                  size="large"
+                  className="!rounded-md"
+                  onChange={(value) => handleChange('password', value)}
+                />
+
+                <div className="space-y-2 pt-2">
+                  <Button
+                    theme="solid"
+                    className="w-full !rounded-full"
+                    type="primary"
+                    htmlType="submit"
+                    size="large"
+                    onClick={handleSubmit}
+                  >
+                    {t('继续')}
+                  </Button>
+
+                  <Button
+                    theme="borderless"
+                    type='tertiary'
+                    className="w-full !rounded-full"
+                    size="large"
+                    onClick={() => navigate('/reset')}
+                  >
+                    {t('忘记密码?')}
+                  </Button>
+                </div>
+              </Form>
+
+              <Divider margin='12px' align='center'>
+                {t('或')}
+              </Divider>
+              
+              <div className="mt-4 text-center">
+                <Button
+                  theme="outline"
+                  type="tertiary"
+                  className="w-full !rounded-full"
+                  size="large"
+                  onClick={() => setShowEmailLogin(false)}
+                >
+                  {t('其他登录选项')}
+                </Button>
+              </div>
+            </div>
+          </Card>
+        </div>
+      </div>
+    );
+  };
+
+  // 微信登录模态框
+  const renderWeChatLoginModal = () => {
+    return (
+      <Modal
+        title={t('微信扫码登录')}
+        visible={showWeChatLoginModal}
+        maskClosable={true}
+        onOk={onSubmitWeChatVerificationCode}
+        onCancel={() => setShowWeChatLoginModal(false)}
+        okText={t('登录')}
+        size="small"
+        centered={true}
+      >
+        <div className="flex flex-col items-center">
+          <img src={status.wechat_qrcode} alt="微信二维码" className="mb-4" />
+        </div>
+
+        <div className="text-center mb-4">
+          <p>{t('微信扫码关注公众号,输入「验证码」获取验证码(三分钟内有效)')}</p>
+        </div>
+
+        <Form size="large">
+          <Form.Input
+            field="wechat_verification_code"
+            placeholder={t('验证码')}
+            label={t('验证码')}
+            value={inputs.wechat_verification_code}
+            onChange={(value) => handleChange('wechat_verification_code', value)}
+          />
+        </Form>
+      </Modal>
+    );
+  };
+
+  return (
+    <div className="min-h-screen relative flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8 overflow-hidden">
+      {/* 背景图片容器 - 放大并保持居中 */}
+      <div
+        className="absolute inset-0 z-0 bg-cover bg-center scale-125 opacity-100"
+        style={{
+          backgroundImage: `url(${Background})`
+        }}
+      ></div>
+
+      {/* 半透明遮罩层 */}
+      <div className="absolute inset-0 bg-gradient-to-br from-teal-500/30 via-blue-500/30 to-purple-500/30 backdrop-blur-sm z-0"></div>
+
+      <div className="w-full max-w-md relative z-10">
+        {showEmailLogin || !(status.github_oauth || status.oidc_enabled || status.wechat_login || status.linuxdo_oauth || status.telegram_oauth)
+          ? renderEmailLoginForm()
+          : renderOAuthOptions()}
+        {renderWeChatLoginModal()}
+      </div>
     </div>
   );
 };

+ 2 - 2
web/src/components/WeChatIcon.js

@@ -11,8 +11,8 @@ const WeChatIcon = () => {
         version='1.1'
         xmlns='http://www.w3.org/2000/svg'
         p-id='5091'
-        width='16'
-        height='16'
+        width='20'
+        height='20'
       >
         <path
           d='M690.1 377.4c5.9 0 11.8 0.2 17.6 0.5-24.4-128.7-158.3-227.1-319.9-227.1C209 150.8 64 271.4 64 420.2c0 81.1 43.6 154.2 111.9 203.6 5.5 3.9 9.1 10.3 9.1 17.6 0 2.4-0.5 4.6-1.1 6.9-5.5 20.3-14.2 52.8-14.6 54.3-0.7 2.6-1.7 5.2-1.7 7.9 0 5.9 4.8 10.8 10.8 10.8 2.3 0 4.2-0.9 6.2-2l70.9-40.9c5.3-3.1 11-5 17.2-5 3.2 0 6.4 0.5 9.5 1.4 33.1 9.5 68.8 14.8 105.7 14.8 6 0 11.9-0.1 17.8-0.4-7.1-21-10.9-43.1-10.9-66 0-135.8 132.2-245.8 295.3-245.8z m-194.3-86.5c23.8 0 43.2 19.3 43.2 43.1s-19.3 43.1-43.2 43.1c-23.8 0-43.2-19.3-43.2-43.1s19.4-43.1 43.2-43.1z m-215.9 86.2c-23.8 0-43.2-19.3-43.2-43.1s19.3-43.1 43.2-43.1 43.2 19.3 43.2 43.1-19.4 43.1-43.2 43.1z'

+ 11 - 0
web/src/i18n/locales/en.json

@@ -3,6 +3,17 @@
   "文档": "Docs",
   "控制台": "Console",
   "$%.6f 额度": "$%.6f quota",
+  "或": "or",
+  "登 录": "Log In",
+  "使用 邮箱 登录": "Sign in with Email",
+  "使用 GitHub 继续": "Continue with GitHub",
+  "使用 OIDC 继续": "Continue with OIDC",
+  "使用 微信 继续": "Continue with WeChat",
+  "使用 LinuxDO 继续": "Continue with LinuxDO",
+  "其他登录选项": "Other login options",
+  "请输入您的邮箱地址": "Please enter your email address",
+  "请输入您的密码": "Please enter your password",
+  "继续": "Continue",
   "%d 点额度": "%d point quota",
   "尚未实现": "Not yet implemented",
   "余额不足": "Insufficient quota",