Prechádzať zdrojové kódy

Merge branch 'iteration-authentication' into jenkins

lex 1 rok pred
rodič
commit
90db809c79

+ 1 - 11
dev-dist/sw.js

@@ -79,7 +79,6 @@ define(['./workbox-5357ef54'], function (workbox) {
    * requests for URLs in the manifest.
    * See https://goo.gl/S9QRab
    */
-<<<<<<< HEAD
   workbox.precacheAndRoute(
     [
       {
@@ -88,20 +87,11 @@ define(['./workbox-5357ef54'], function (workbox) {
       },
       {
         url: 'index.html',
-        revision: '0.gkfi3u3c598'
+        revision: '0.p9rb3ikv53'
       }
     ],
     {}
   );
-=======
-  workbox.precacheAndRoute([{
-    "url": "registerSW.js",
-    "revision": "3ca0b8505b4bec776b69afdba2768812"
-  }, {
-    "url": "index.html",
-    "revision": "0.p9rb3ikv53"
-  }], {});
->>>>>>> iteration-large-version
   workbox.cleanupOutdatedCaches();
   workbox.registerRoute(
     new workbox.NavigationRoute(workbox.createHandlerBoundToURL('index.html'), {

+ 1 - 1
public/version.json

@@ -1 +1 @@
-{"version":1708567404485}
+{"version":1708568466915}

BIN
src/components/TheAuth/images/auth-title-bg.png


BIN
src/components/TheAuth/images/icon-close.png


BIN
src/components/TheAuth/images/mac/1.png


BIN
src/components/TheAuth/images/mac/2.png


BIN
src/components/TheAuth/images/mac/3.png


BIN
src/components/TheAuth/images/mac/4.png


BIN
src/components/TheAuth/images/mac/5.png


BIN
src/components/TheAuth/images/window/1.png


BIN
src/components/TheAuth/images/window/2.png


BIN
src/components/TheAuth/images/window/3.png


BIN
src/components/TheAuth/images/window/4.png


BIN
src/components/TheAuth/images/window/5.png


BIN
src/components/TheAuth/images/window/6.png


BIN
src/components/TheAuth/images/window/7.png


+ 177 - 0
src/components/TheAuth/index.module.less

@@ -0,0 +1,177 @@
+.theAuth {
+  // background-color: #fff;
+  width: 892px;
+  padding-top: 160px;
+  box-shadow: none;
+  position: relative;
+  // overflow: hidden;
+
+
+  .iconClose {
+    position: absolute;
+    right: 38px;
+    top: 145px;
+    width: max(20px, 16Px);
+    height: max(20px, 16Px);
+    background: url('./images/icon-close.png') no-repeat center;
+    background-size: contain;
+    cursor: pointer;
+  }
+}
+
+.theTitle {
+  position: absolute;
+  top: 0;
+  left: 0;
+  background: url('./images/auth-title-bg.png') top center no-repeat;
+  background-size: 100%;
+  width: 100%;
+  height: 174px;
+}
+
+.authContent {
+  background: linear-gradient(180deg, #E1F8FF 0%, #BBE7FD 100%);
+  border-radius: 0 0 23px 23px;
+}
+
+.steps {
+  margin: 14px 27px 0;
+  padding-top: 34px;
+
+  background: linear-gradient(180deg, rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0.7) 88%, #CDF0FF 100%);
+  border-radius: 23px;
+  border: 1px solid #FFFFFF;
+
+  :global {
+    .n-scrollbar {
+      margin: 0 0 25px;
+      padding: 14px 34px 34px;
+      min-height: calc(55vh - 28px);
+      max-height: calc(55vh - 28px);
+    }
+  }
+}
+
+.step {
+  display: flex;
+  align-items: flex-start;
+  padding-bottom: 35px;
+
+  .stepNum {
+    width: 33px;
+    height: 33px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    text-align: center;
+    background: #B9EAFF;
+    border: 1px solid #FFFFFF;
+    font-size: 17px;
+    font-weight: 600;
+    color: #131415;
+    border-radius: 50%;
+    margin-right: 14px;
+    flex-shrink: 0;
+  }
+
+  .stepContent {
+    .txt {
+      font-size: max(15px, 12Px);
+      font-family: PingFangSC, PingFang SC;
+      font-weight: 600;
+      color: #000000;
+      line-height: 33px;
+
+      span {
+        color: #1F6DEC;
+      }
+
+      .red {
+        color: #E80000;
+      }
+    }
+  }
+
+  img {
+    border-radius: 8px;
+  }
+
+  .w1 {
+    width: 90px;
+    height: 98px;
+    margin: 8px 0 12px;
+  }
+
+  .w6 {
+    width: 196px;
+    height: 207px;
+  }
+
+  .w7 {
+    margin-top: 8px;
+    width: 100%;
+  }
+
+  .m1 {
+    width: 113px;
+    height: 98px;
+    margin: 8px 0 0;
+  }
+
+  .m2 {
+    margin-top: 8px;
+    width: 333px
+  }
+
+  .m3 {
+    margin-top: 8px;
+    width: 358px;
+  }
+
+  .m4,
+  .m5 {
+    margin-top: 8px;
+    width: 100%;
+  }
+
+  .moreImg {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+
+    img {
+      width: 47%;
+      margin-bottom: 32px;
+
+      &:nth-child(2n + 2) {
+        margin-left: 6%;
+      }
+    }
+  }
+}
+
+.btnGroup {
+  padding: 25px 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  :global {
+    .n-button {
+      height: 45px !important;
+      width: 275px !important;
+      --n-border: none !important;
+      --n-border-hover: none !important;
+      --n-border-pressed: none !important;
+      --n-border-focus: none !important;
+      background: linear-gradient(305deg, #15BBFF 0%, #1784FF 100%);
+      border-radius: 22px;
+      font-size: max(18px, 15Px);
+      font-family: AlimamaShuHeiTi, AlimamaShuHeiTi;
+      font-weight: bold;
+      color: #FFFFFF;
+      line-height: 22px;
+      letter-spacing: 1px;
+    }
+  }
+}

+ 168 - 0
src/components/TheAuth/index.tsx

@@ -0,0 +1,168 @@
+import { defineComponent } from 'vue';
+import styles from './index.module.less';
+import { NButton, NScrollbar } from 'naive-ui';
+import w1 from './images/window/1.png';
+import w2 from './images/window/2.png';
+import w3 from './images/window/3.png';
+import w4 from './images/window/4.png';
+import w5 from './images/window/5.png';
+import w6 from './images/window/6.png';
+import w7 from './images/window/7.png';
+
+import m1 from './images/mac/1.png';
+import m2 from './images/mac/2.png';
+import m3 from './images/mac/3.png';
+import m4 from './images/mac/4.png';
+import m5 from './images/mac/5.png';
+import { browser } from '/src/helpers/utils';
+
+export default defineComponent({
+  name: 'the-auth',
+  emits: ['close'],
+  setup(props, { emit }) {
+    // 下载证书
+    const onDownload = () => {
+      // const agent = navigator.userAgent.toLowerCase();
+      const isMac = (function () {
+        return /macintosh|mac os x/i.test(navigator.userAgent);
+      })();
+      if (isMac) {
+        window.open('https://oss.dayaedu.com/https-ssl/Mac-安全证书.cer');
+      } else {
+        window.open('https://oss.dayaedu.com/https-ssl/Win-安全证书.pfx');
+      }
+      // emit('close');
+    };
+    return () => (
+      <div class={styles.theAuth}>
+        <div class={styles.theTitle}></div>
+        <i class={styles.iconClose} onClick={() => emit('close')}></i>
+        <div class={styles.authContent}>
+          <div class={styles.steps}>
+            <NScrollbar>
+              <div class={styles.step}>
+                <div class={styles.stepNum}>01</div>
+                <div class={styles.stepContent}>
+                  <p class={styles.txt}>
+                    点击下方下载按钮,下载数据安全证书安装包
+                  </p>
+                </div>
+              </div>
+              {browser().ios ? (
+                <>
+                  <div class={styles.step}>
+                    <div class={styles.stepNum}>02</div>
+                    <div class={styles.stepContent}>
+                      <p class={styles.txt}>
+                        双击<span>《安全证书.cer》</span>
+                      </p>
+                      <div class={styles.imgs}>
+                        <img src={m1} class={styles.m1} />
+                      </div>
+                      <p class={styles.txt}>
+                        输入钥匙串密码,点击<span>【修改钥匙串】</span>
+                        (若无此步骤则忽略)
+                      </p>
+                      <div class={styles.imgs}>
+                        <img src={m2} class={styles.m2} />
+                      </div>
+                    </div>
+                  </div>
+
+                  <div class={styles.step}>
+                    <div class={styles.stepNum}>03</div>
+                    <div class={styles.stepContent}>
+                      <p class={styles.txt}>
+                        <span class={styles.red}>重启浏览器</span>
+                        (在电脑屏幕左上方选择当前浏览器并点击
+                        <span>【退出】</span>),再重新打开音乐数字课堂网址
+                      </p>
+                      <div class={styles.imgs}>
+                        <img src={m3} class={styles.m3} />
+                      </div>
+                    </div>
+                  </div>
+
+                  <div class={styles.step}>
+                    <div class={styles.stepNum}>04</div>
+                    <div class={styles.stepContent}>
+                      <p class={styles.txt}>
+                        在【选择证书】弹窗中点击<span>【确定】</span>按钮
+                      </p>
+                      <div class={styles.imgs}>
+                        <img src={m4} class={styles.m4} />
+                      </div>
+                      <p class={styles.txt}>
+                        输入电脑的用户名和密码(若无此步骤则忽略)
+                      </p>
+                      <div class={styles.imgs}>
+                        <img src={m5} class={styles.m5} />
+                      </div>
+                    </div>
+                  </div>
+                </>
+              ) : (
+                <>
+                  <div class={styles.step}>
+                    <div class={styles.stepNum}>02</div>
+                    <div class={styles.stepContent}>
+                      <p class={styles.txt}>
+                        双击<span>《安全证书.pfx》</span>,一直点击
+                        <span>【下一步】</span>,直至<span>【完成】</span>
+                      </p>
+                      <div class={styles.imgs}>
+                        <img src={w1} class={styles.w1} />
+
+                        <div class={styles.moreImg}>
+                          <img src={w2} />
+                          <img src={w3} />
+                          <img src={w4} />
+                          <img src={w5} />
+                        </div>
+                        <img src={w6} class={styles.w6} />
+                      </div>
+                    </div>
+                  </div>
+
+                  <div class={styles.step}>
+                    <div class={styles.stepNum}>03</div>
+                    <div class={styles.stepContent}>
+                      <p class={styles.txt}>
+                        <span class={styles.red}>重启浏览器</span>
+                        ,打开音乐数字课堂网址
+                      </p>
+                    </div>
+                  </div>
+
+                  <div class={styles.step}>
+                    <div class={styles.stepNum}>04</div>
+                    <div class={styles.stepContent}>
+                      <p class={styles.txt}>
+                        在【选择证书】弹窗中点击<span>【确定】</span>按钮
+                      </p>
+                      <img src={w7} class={styles.w7} />
+                    </div>
+                  </div>
+                </>
+              )}
+              <div class={styles.step}>
+                <div class={styles.stepNum}>05</div>
+                <div class={styles.stepContent}>
+                  <p class={styles.txt}>
+                    证书安装完成,开始使用音乐数字课堂吧。
+                  </p>
+                </div>
+              </div>
+            </NScrollbar>
+          </div>
+
+          <div class={styles.btnGroup}>
+            <NButton round type="primary" onClick={onDownload}>
+              下载证书
+            </NButton>
+          </div>
+        </div>
+      </div>
+    );
+  }
+});

+ 11 - 0
src/components/layout/index.tsx

@@ -37,6 +37,7 @@ import { fscreen } from '@/utils/index';
 import AttendClass from '/src/views/prepare-lessons/model/attend-class';
 import Pen from '/src/views/attend-class/component/tools/pen';
 import study from '/src/views/home/components/study';
+import TheAuth from '../TheAuth';
 export default defineComponent({
   name: 'layoutView',
   setup() {
@@ -46,6 +47,7 @@ export default defineComponent({
     const directionType = ref('left');
     const showClass = ref(false);
 
+    const showAuthMask = ref(false);
     const showModalBeat = ref(false);
     const showModalTone = ref(false);
     const showModalTime = ref(false);
@@ -395,6 +397,11 @@ export default defineComponent({
       eventGlobal.on('base-setting-emit', (val: string) => {
         helpNoteList.baseListTab = val;
       });
+
+      // 判断是否显示证书提示
+      eventGlobal.on('auth-not-installed', () => {
+        showAuthMask.value = true;
+      });
     });
 
     const resetSize = () => {
@@ -816,6 +823,10 @@ export default defineComponent({
           type="attend"
           params={previewItem.value}
         />
+
+        <NModal v-model:show={showAuthMask.value}>
+          <TheAuth onClose={() => (showAuthMask.value = false)} />
+        </NModal>
       </div>
     );
   }

+ 11 - 1
src/utils/request.ts

@@ -2,12 +2,15 @@ import { extend } from 'umi-request';
 import cleanDeep from 'clean-deep';
 import { useUserStore } from '../store/modules/users';
 import router from '@/router';
+import { eventGlobal } from '.';
 
 export interface SearchInitParams {
   rows?: string | number;
   page?: string | number;
 }
 
+let hideErrorMesage = false; // 是否显示错误信息
+
 const request = extend({
   // requestType: 'form',
   hideLoading: true, // 默认都不显示加载
@@ -17,6 +20,7 @@ const request = extend({
 
 request.interceptors.request.use(
   (url, options: any) => {
+    hideErrorMesage = options.hideErrorMesage || false;
     if (!options.hideLoading) {
       window.$message.loading('加载中...');
     }
@@ -77,7 +81,13 @@ request.interceptors.response.use(
     const userStore = useUserStore();
     if (res.status > 299 || res.status < 200) {
       const msg = '服务器错误,状态码' + res.status;
-      window.$message.error(msg);
+      // 判断是否有资源需要证书,不提示错误信息
+      if (res.status === 511) {
+        eventGlobal.emit('auth-not-installed');
+      } else {
+        !hideErrorMesage && window.$message.error(msg);
+      }
+
       throw new Error(msg);
     }
     const data = await res.clone().json();

+ 11 - 0
src/views/login/api.ts

@@ -28,6 +28,7 @@ export const sendImgCode = (params: any) => {
     requestType: 'form'
   });
 };
+
 /**
  * 发送验证码
  */
@@ -37,3 +38,13 @@ export const sendSmsVerify = (params: any) => {
     requestType: 'form'
   });
 };
+
+/**
+ * 检测是否安装证书 - 通过code码为511判断
+ */
+export const mutualTLSQuery = (params: any) => {
+  return request.get('/edu-app/open/mutualTLS/query', {
+    data: params,
+    hideErrorMesage: true
+  });
+};

+ 16 - 0
src/views/login/index.tsx

@@ -29,6 +29,8 @@ import closeAble from './images/closeAble.png';
 import infoIcon from './images/infoIcon.png';
 import { state } from '/src/state';
 import dayjs from 'dayjs';
+import TheAuth from '/src/components/TheAuth';
+import { mutualTLSQuery } from './api';
 export default defineComponent({
   name: 'login-page',
   setup() {
@@ -40,6 +42,7 @@ export default defineComponent({
     const dialog = useDialog();
     const userPhone = ref(); // 用户手机号
     const showModalMask = ref(false);
+    const showAuthMask = ref(false);
     const checkInstall = async (event: any) => {
       event.preventDefault();
       console.log('checkInstall', event);
@@ -104,6 +107,15 @@ export default defineComponent({
       sessionStorage.removeItem('task-upload-music');
       // const relatedApps = await navigator?.getInstalledRelatedApps();
       //
+
+      try {
+        await mutualTLSQuery({});
+      } catch (err: any) {
+        console.log(err);
+        if (err.message.indexOf('511')) {
+          showAuthMask.value = true;
+        }
+      }
     });
     const downChrome = () => {
       const agent = navigator.userAgent.toLowerCase();
@@ -215,6 +227,10 @@ export default defineComponent({
             </NSpace>
           </div>
         </NModal>
+
+        <NModal v-model:show={showAuthMask.value}>
+          <TheAuth onClose={() => (showAuthMask.value = false)} />
+        </NModal>
       </div>
     );
   }

+ 2 - 2
vite.config.ts

@@ -23,8 +23,8 @@ function resolve(dir: string) {
 }
 // https://vitejs.dev/config/
 // https://github.com/vitejs/vite/issues/1930 .env
-// const proxyUrl = 'https://dev.kt.colexiu.com/';
-const proxyUrl = 'https://test.lexiaoya.cn';
+const proxyUrl = 'https://dev.kt.colexiu.com/';
+// const proxyUrl = 'https://test.lexiaoya.cn';
 // const proxyUrl = 'http://192.168.3.14:7989';
 const now = new Date().getTime();
 export default defineConfig(() => {