wjx 4 settimane fa
parent
commit
d2897d0ad9
4 ha cambiato i file con 239 aggiunte e 129 eliminazioni
  1. 32 15
      src/global.less
  2. 33 0
      src/mocks/video.ts
  3. 148 113
      src/pages/user/login/index.tsx
  4. 26 1
      src/utils/index.ts

+ 32 - 15
src/global.less

@@ -3,40 +3,39 @@
   font-style: normal;
   font-weight: 300;
   font-display: swap;
-  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*1GSgSYDD_aIAAAAAQsAAAAgAegCCAQ/AlibabaSans-Light.woff2")
-    format("woff2");
+  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*1GSgSYDD_aIAAAAAQsAAAAgAegCCAQ/AlibabaSans-Light.woff2") format("woff2");
 }
+
 @font-face {
   font-family: "AlibabaSans";
   font-style: normal;
   font-weight: 400;
   font-display: swap;
-  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*2zEUQqnPNesAAAAAQtAAAAgAegCCAQ/AlibabaSans-Regular.woff2")
-    format("woff2");
+  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*2zEUQqnPNesAAAAAQtAAAAgAegCCAQ/AlibabaSans-Regular.woff2") format("woff2");
 }
+
 @font-face {
   font-family: "AlibabaSans";
   font-style: normal;
   font-weight: 500;
   font-display: swap;
-  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Medium.woff2")
-    format("woff2");
+  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Medium.woff2") format("woff2");
 }
+
 @font-face {
   font-family: "AlibabaSans";
   font-style: normal;
   font-weight: 600;
   font-display: swap;
-  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Bold.woff2")
-    format("woff2");
+  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Bold.woff2") format("woff2");
 }
+
 @font-face {
   font-family: "AlibabaSans";
   font-style: normal;
   font-weight: 700;
   font-display: swap;
-  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Heavy.woff2")
-    format("woff2");
+  src: url("//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Heavy.woff2") format("woff2");
 }
 
 html,
@@ -57,6 +56,7 @@ body,
 .ant-layout {
   min-height: 100vh;
 }
+
 .ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed {
   left: unset;
 }
@@ -80,15 +80,32 @@ ol {
   .ant-table {
     width: 100%;
     overflow-x: auto;
-    &-thead > tr,
-    &-tbody > tr {
-      > th,
-      > td {
+
+    &-thead>tr,
+    &-tbody>tr {
+
+      >th,
+      >td {
         white-space: pre;
-        > span {
+
+        >span {
           display: block;
         }
       }
     }
   }
+}
+
+
+// 背景不同颜色不同
+.window_page {
+
+  .ant-pro-form-login-header,
+  .ant-pro-form-login-desc,
+  .ant-radio-label,
+  .ant-pro-global-footer-copyright {
+    // filter: invert(1) hue-rotate(180deg);
+    color: #FFF;
+    // mix-blend-mode: difference;
+  }
 }

+ 33 - 0
src/mocks/video.ts

@@ -0,0 +1,33 @@
+export const VIDEO_LIST = [
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/246AD11C157F4CCCABC17F7CA05936ED.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/10F451DF058D42BE8615B022CBD2284D.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/CA6A6D2138E347BFA3D0CBADB98D5094.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/90DE76344B244C57A61C9C6ABE91BC32.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/C3F318CF775A4C73899B227A2E393C7F.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/8401F6B289AF4F11A923A17EF9C8A3BF.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/6FFAEABEA38343759CD197958ADD71B4.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/C8C966EF8C1940F1B601ED0E0C92EF2B.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/B27ED67145E9466495A87406C0AB23A3.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/93CA7D8022AE477D82E351A855C150E7.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/B4669C7253514732885F60EE410B7D6C.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/8851A4C9114B453C9A8F9C6F3A801865.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/9D4D232E88674E4DB5C18E77CCFB6E3B.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/A00FEAF16F4A46E9BCA2BB24BFDDFF12.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/1D5E117AA32A4FB9BDD7C811190E00D7.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/56CE7C6958944C6EBDD41FC96B615D11.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/7463699D414F4822956676E4F42C7FEA.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/9da87253dd6864c47cddb125b5802a48_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/scene/dc688ae8b63418d07e63e57b0e0708ea_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/68a600702d6620ef61eb3d42f61e21db_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/scene/9ec3fddc01f8ac8e3c8fd32593caa45f_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/00fb2f0c5b3386fb8bdc6a09927c8f02_preview.mp4',
+    'https://img-baofun.zhhainiao.com/fs/scene/preview_video/547e199889415289542aaca9e30f2cb4_preview.mp4',
+    'https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/F5DBC23D42C944A9A04BC4BA235EE516.mp4',
+    'https://img-baofun.zhhainiao.com/fs/scene/preview_video/e0305cb9abb479a2865b269140140677_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/c1da28f04d77d120c8ba26e032c9aecd_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/64a73ef9e72d2e2564170ced01971df8_preview.mp4',
+    'https://img-baofun.zhhainiao.com/fs/live/preview_video/2875ba225ae5fc2acf93919b3a0bb469_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/60042d664fc1647bdf7b7e3671f7b686_preview.mp4',
+    'https://img-baofun.zhhainiao.com/fs/live/preview_video/b086d1dcef4a96e5c7b4e568166cd622_preview.mp4',
+    'https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/2c9a4dde0296d6ca199619b5d62636a8_preview.mp4',
+]

+ 148 - 113
src/pages/user/login/index.tsx

@@ -20,6 +20,8 @@ import Settings from '../../../../config/defaultSettings';
 import { api } from '@/services/env';
 import SelectCompany from './selectCompany';
 import { getCode } from '@/services/user/login';
+import { isInMobileMode } from '@/utils';
+import { VIDEO_LIST } from '@/mocks/video';
 
 const useStyles = createStyles(({ token }) => {
   return {
@@ -45,6 +47,12 @@ const useStyles = createStyles(({ token }) => {
         backgroundColor: token.colorBgTextHover,
       },
     },
+    login_page: {
+      position: 'relative',
+      width: '100%',
+      height: '100vh',
+      overflow: 'hidden'
+    },
     container: {
       display: 'flex',
       flexDirection: 'column',
@@ -53,7 +61,16 @@ const useStyles = createStyles(({ token }) => {
       backgroundImage:
         "url('https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr')",
       backgroundSize: '100% 100%',
+      position: 'absolute',
+      width: '100%',
+      top: 0,
+      left: 0
     },
+    top_video: {
+      width: '100%',
+      height: '100%',
+      objectFit: 'cover'
+    }
   };
 });
 
@@ -81,8 +98,14 @@ const Login: React.FC = () => {
   const { styles } = useStyles();
   const [codeType, setCodeType] = useState<1 | 2>(1)//1钉钉验证码 2短信验证码
   const [loading, setLoading] = useState<boolean>(false)
+  const [backUrl, setBackUrl] = useState<string>()
   /******************************/
 
+  useEffect(() => { 
+    const videoLength = VIDEO_LIST.length
+    setBackUrl(VIDEO_LIST[Math.floor(Math.random() * videoLength)])
+  }, [VIDEO_LIST])
+
   // 获取TOKEN
   useEffect(() => {
     const hash = window.location.hash
@@ -166,127 +189,139 @@ const Login: React.FC = () => {
   const { fail, code } = userLoginState;
 
   return (
-    <div className={styles.container}>
-      <Helmet>
-        <title>登录页 - {Settings.title}</title>
-      </Helmet>
-      <div style={{ flex: '1', padding: '32px 0' }}>
-        {(localStorage.getItem('Admin-Token') && companyList?.length > 0) ? <SelectCompany
-          companyList={companyList}
-          loading={false}
-          setCompanyHandle={setCompanyHandle}
-          logOut={logOut}
-        /> : <LoginForm
-          contentStyle={{
-            minWidth: 280,
-            maxWidth: '75vw',
-          }}
-          title={Settings.title}
-          subTitle={'趣程数字业务指挥中心(整合公众号/企微/广告投放)'}
-          onFinish={async (values) => {
-            await handleSubmit(values as API.LoginParams);
-          }}
-          // initialValues={{ phone: 15394409016 }}
-          loading={loading}
-        >
-          <Tabs
-            activeKey={type}
-            onChange={setType}
-            centered
-            items={[
-              {
-                key: 'mobile',
-                label: '手机号登录',
-              },
-            ]}
-          />
+    <div className={`${styles.login_page} ${isInMobileMode() ? 'mobile_page' : 'window_page'}`}>
+      {(!isInMobileMode() && backUrl) &&
+        <video
+          src={backUrl}
+          muted
+          loop
+          autoPlay
+          preload="metadata"
+          poster="https://mdn.alipayobjects.com/yuyan_qk0oxh/afts/img/V-_oS6r-i7wAAAAAAAAAAAAAFl94AQBr"
+          playsInline
+          className={styles.top_video}
+        ></video>}
+      <div className={styles.container}>
+        <Helmet>
+          <title>登录页 - {Settings.title}</title>
+        </Helmet>
+        <div style={{ flex: '1', padding: '32px 0' }}>
+          {(localStorage.getItem('Admin-Token') && companyList?.length > 0) ? <SelectCompany
+            companyList={companyList}
+            loading={false}
+            setCompanyHandle={setCompanyHandle}
+            logOut={logOut}
+          /> : <LoginForm
+            contentStyle={{
+              minWidth: 280,
+              maxWidth: '75vw',
+            }}
+            title={Settings.title}
+            subTitle={'趣程数字业务指挥中心(整合公众号/企微/广告投放)'}
+            onFinish={async (values) => {
+              await handleSubmit(values as API.LoginParams);
+            }}
+            loading={loading}
+          >
+            <Tabs
+              activeKey={type}
+              onChange={setType}
+              centered
+              items={[
+                {
+                  key: 'mobile',
+                  label: '手机号登录',
+                },
+              ]}
+            />
 
-          {fail && code === 500 && <LoginMessage content="验证码错误" />}
-          {type === 'mobile' && (
-            <>
-              <ProFormText
-                fieldProps={{
-                  size: 'large',
-                  prefix: <MobileOutlined />,
-                }}
-                name="phone"
-                placeholder={'手机号'}
-                rules={[
+            {fail && code === 500 && <LoginMessage content="验证码错误" />}
+            {type === 'mobile' && (
+              <>
+                <ProFormText
+                  fieldProps={{
+                    size: 'large',
+                    prefix: <MobileOutlined />,
+                  }}
+                  name="phone"
+                  placeholder={'手机号'}
+                  rules={[
+                    {
+                      required: true,
+                      message: '请输入手机号!',
+                    },
+                    {
+                      pattern: /^1\d{10}$/,
+                      message: '手机号格式错误!',
+                    },
+                  ]}
+                />
+                <ProFormCaptcha
+                  fieldProps={{
+                    size: 'large',
+                    prefix: <LockOutlined />,
+                  }}
+                  captchaProps={{
+                    size: 'large',
+                  }}
+                  placeholder={'请输入验证码'}
+                  captchaTextRender={(timing, count) => {
+                    if (timing) {
+                      return `${count} 获取验证码`;
+                    }
+                    return '获取验证码';
+                  }}
+                  name="code"
+                  rules={[
+                    {
+                      required: true,
+                      message: '请输入验证码!',
+                    },
+                  ]}
+                  phoneName={'phone'}
+                  onGetCaptcha={async (phone) => {
+                    try {
+                      if (!phone) {
+                        message.error('请输入手机号!');
+                        return Promise.reject('请输入手机号!');
+                      }
+                      const result = await getCode({ phone, code: codeType });
+                      if (result?.data) {
+                        message.success('获取验证码成功!');
+                        return;
+                      } else {
+                        return Promise.reject('获取验证码失败,请稍后再试!');
+                      }
+                    } catch (error) { }
+                  }}
+                />
+              </>
+            )}
+            <div
+              style={{
+                marginBlockEnd: 40,
+                textAlign: 'center'
+              }}
+            >
+              <Radio.Group
+                value={codeType}
+                onChange={(e) => setCodeType(e.target.value)}
+                options={[
                   {
-                    required: true,
-                    message: '请输入手机号!',
+                    label: '钉钉验证码',
+                    value: 1,
                   },
                   {
-                    pattern: /^1\d{10}$/,
-                    message: '手机号格式错误!',
-                  },
-                ]}
-              />
-              <ProFormCaptcha
-                fieldProps={{
-                  size: 'large',
-                  prefix: <LockOutlined />,
-                }}
-                captchaProps={{
-                  size: 'large',
-                }}
-                placeholder={'请输入验证码'}
-                captchaTextRender={(timing, count) => {
-                  if (timing) {
-                    return `${count} 获取验证码`;
+                    label: '手机验证码',
+                    value: 2,
                   }
-                  return '获取验证码';
-                }}
-                name="code"
-                rules={[
-                  {
-                    required: true,
-                    message: '请输入验证码!',
-                  },
                 ]}
-                phoneName={'phone'}
-                onGetCaptcha={async (phone) => {
-                  try {
-                    if (!phone) {
-                      message.error('请输入手机号!');
-                      return Promise.reject('请输入手机号!');
-                    }
-                    const result = await getCode({ phone, code: codeType });
-                    if (result?.data) {
-                      message.success('获取验证码成功!');
-                      return;
-                    } else {
-                      return Promise.reject('获取验证码失败,请稍后再试!');
-                    }
-                  } catch (error) { }
-                }}
               />
-            </>
-          )}
-          <div
-            style={{
-              marginBlockEnd: 40,
-              textAlign: 'center'
-            }}
-          >
-            <Radio.Group
-              value={codeType}
-              onChange={(e) => setCodeType(e.target.value)}
-              options={[
-                {
-                  label: '钉钉验证码',
-                  value: 1,
-                },
-                {
-                  label: '手机验证码',
-                  value: 2,
-                }
-              ]}
-            />
-          </div>
-        </LoginForm>}
+            </div>
+          </LoginForm>}
+        </div>
+        <Footer />
       </div>
-      <Footer />
     </div>
   );
 };

+ 26 - 1
src/utils/index.ts

@@ -70,4 +70,29 @@ export const getLocalStoragePage = ({
         }
     }
     return params
-}
+}
+
+/**
+ * 检测触控事件 可判断是否在pc模拟器中
+ * @returns 
+ */
+const isTouchDevice = () => {
+  return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
+};
+
+/**
+ * 检测是否在真实手机环境  
+ * @returns 
+ */
+export const isInMobileMode = () => {
+  const userAgent = navigator.userAgent;
+  // 检查 User-Agent  
+  const isMobileUserAgent = /Android|iPhone|iPad|iPod/i.test(userAgent);
+  // 检查触控事件  
+  const isTouch = isTouchDevice();
+  // 进行判断  
+  if (isMobileUserAgent && isTouch) {
+    return true; // 在真实手机环境  
+  }
+  return false;
+};