瀏覽代碼

Merge branch 'iteration-authentication' into online

lex 1 年之前
父節點
當前提交
0e10161afb
共有 29 個文件被更改,包括 530 次插入52 次删除
  1. 55 37
      dev-dist/sw.js
  2. 1 1
      public/version.json
  3. 二進制
      src/components/TheAuth/images/auth-title-bg.png
  4. 二進制
      src/components/TheAuth/images/icon-close.png
  5. 二進制
      src/components/TheAuth/images/mac/1.png
  6. 二進制
      src/components/TheAuth/images/mac/2.png
  7. 二進制
      src/components/TheAuth/images/mac/3.png
  8. 二進制
      src/components/TheAuth/images/mac/4.png
  9. 二進制
      src/components/TheAuth/images/mac/5.png
  10. 二進制
      src/components/TheAuth/images/window/1.png
  11. 二進制
      src/components/TheAuth/images/window/2.png
  12. 二進制
      src/components/TheAuth/images/window/3.png
  13. 二進制
      src/components/TheAuth/images/window/4.png
  14. 二進制
      src/components/TheAuth/images/window/5.png
  15. 二進制
      src/components/TheAuth/images/window/6.png
  16. 二進制
      src/components/TheAuth/images/window/7.png
  17. 177 0
      src/components/TheAuth/index.module.less
  18. 174 0
      src/components/TheAuth/index.tsx
  19. 11 0
      src/components/layout/index.tsx
  20. 11 1
      src/utils/request.ts
  21. 8 2
      src/views/content-information/content-instrument/index.module.less
  22. 15 2
      src/views/content-information/content-instrument/index.tsx
  23. 9 1
      src/views/content-information/content-music/index.module.less
  24. 15 2
      src/views/content-information/content-music/index.tsx
  25. 10 2
      src/views/content-information/content-musician/index.module.less
  26. 15 2
      src/views/content-information/content-musician/index.tsx
  27. 11 0
      src/views/login/api.ts
  28. 16 0
      src/views/login/index.tsx
  29. 2 2
      vite.config.ts

+ 55 - 37
dev-dist/sw.js

@@ -13,31 +13,29 @@
 
 // If the loader is already loaded, just stop.
 if (!self.define) {
-  let registry = {};
+  const registry = {};
 
   // Used for `eval` and `importScripts` where we can't get script URL by other means.
   // In both cases, it's safe to use a global var because those functions are synchronous.
   let nextDefineUri;
 
   const singleRequire = (uri, parentUri) => {
-    uri = new URL(uri + ".js", parentUri).href;
-    return registry[uri] || (
-      
-        new Promise(resolve => {
-          if ("document" in self) {
-            const script = document.createElement("script");
-            script.src = uri;
-            script.onload = resolve;
-            document.head.appendChild(script);
-          } else {
-            nextDefineUri = uri;
-            importScripts(uri);
-            resolve();
-          }
-        })
-      
-      .then(() => {
-        let promise = registry[uri];
+    uri = new URL(uri + '.js', parentUri).href;
+    return (
+      registry[uri] ||
+      new Promise(resolve => {
+        if ('document' in self) {
+          const script = document.createElement('script');
+          script.src = uri;
+          script.onload = resolve;
+          document.head.appendChild(script);
+        } else {
+          nextDefineUri = uri;
+          importScripts(uri);
+          resolve();
+        }
+      }).then(() => {
+        const promise = registry[uri];
         if (!promise) {
           throw new Error(`Module ${uri} didn’t register its module`);
         }
@@ -47,27 +45,31 @@ if (!self.define) {
   };
 
   self.define = (depsNames, factory) => {
-    const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href;
+    const uri =
+      nextDefineUri ||
+      ('document' in self ? document.currentScript.src : '') ||
+      location.href;
     if (registry[uri]) {
       // Module is already loading or loaded.
       return;
     }
-    let exports = {};
+    const exports = {};
     const require = depUri => singleRequire(depUri, uri);
     const specialDeps = {
       module: { uri },
       exports,
       require
     };
-    registry[uri] = Promise.all(depsNames.map(
-      depName => specialDeps[depName] || require(depName)
-    )).then(deps => {
+    registry[uri] = Promise.all(
+      depsNames.map(depName => specialDeps[depName] || require(depName))
+    ).then(deps => {
       factory(...deps);
       return exports;
     });
   };
 }
-define(['./workbox-5357ef54'], (function (workbox) { 'use strict';
+define(['./workbox-5357ef54'], function (workbox) {
+  ('use strict');
 
   self.skipWaiting();
   workbox.clientsClaim();
@@ -77,16 +79,32 @@ define(['./workbox-5357ef54'], (function (workbox) { 'use strict';
    * requests for URLs in the manifest.
    * See https://goo.gl/S9QRab
    */
-  workbox.precacheAndRoute([{
-    "url": "registerSW.js",
-    "revision": "3ca0b8505b4bec776b69afdba2768812"
-  }, {
-    "url": "index.html",
-    "revision": "0.p9rb3ikv53"
-  }], {});
+  workbox.precacheAndRoute(
+    [
+      {
+        url: 'registerSW.js',
+        revision: '3ca0b8505b4bec776b69afdba2768812'
+      },
+      {
+        url: 'index.html',
+        revision: '0.p9rb3ikv53'
+      }
+    ],
+    {}
+  );
+  /**
+   * https://juejin.cn/post/6844903881189621767
+   * 缓存策略 有5种
+   */
   workbox.cleanupOutdatedCaches();
-  workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
-    allowlist: [/^\/$/]
-  }));
-
-}));
+  workbox.registerRoute(
+    new workbox.NavigationRoute(workbox.createHandlerBoundToURL('index.html'), {
+      allowlist: [/^\/$/]
+    }),
+    workbox.strategies.NetworkFirst()
+  );
+  workbox.routing.registerRoute(
+    new RegExp('.*.html|css|js'),
+    workbox.strategies.NetworkFirst()
+  );
+});

+ 1 - 1
public/version.json

@@ -1 +1 @@
-{"version":1708515617550}
+{"version":1708672804468}

二進制
src/components/TheAuth/images/auth-title-bg.png


二進制
src/components/TheAuth/images/icon-close.png


二進制
src/components/TheAuth/images/mac/1.png


二進制
src/components/TheAuth/images/mac/2.png


二進制
src/components/TheAuth/images/mac/3.png


二進制
src/components/TheAuth/images/mac/4.png


二進制
src/components/TheAuth/images/mac/5.png


二進制
src/components/TheAuth/images/window/1.png


二進制
src/components/TheAuth/images/window/2.png


二進制
src/components/TheAuth/images/window/3.png


二進制
src/components/TheAuth/images/window/4.png


二進制
src/components/TheAuth/images/window/5.png


二進制
src/components/TheAuth/images/window/6.png


二進制
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;
+    }
+  }
+}

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

@@ -0,0 +1,174 @@
+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/安全证书.cer');
+      } else {
+        window.open('https://oss.dayaedu.com/https-ssl/安全证书.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>
+                        按钮(若浏览器没有弹出该弹窗请
+                        <span class={styles.red}>重启电脑</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>
+                        按钮(若浏览器没有弹出该弹窗请
+                        <span class={styles.red}>重启电脑</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();

+ 8 - 2
src/views/content-information/content-instrument/index.module.less

@@ -100,8 +100,14 @@
   padding: 32px 20px;
   background-color: #fff;
   border-radius: 20px;
-  min-height: 100%;
-  // min-height: calc(100% - 104px);
+  // min-height: 100%;
+  min-height: calc(100vh - 192px);
+
+  &.listWrapEmpty {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
 
   :global {
     .n-tabs-tab-pad {

+ 15 - 2
src/views/content-information/content-instrument/index.tsx

@@ -12,6 +12,7 @@ import icon_back from '../../xiaoku-music/images/icon_back.png';
 import { useRoute, useRouter } from 'vue-router';
 import List from './components/list';
 import { api_knowledgeWikiCategoryType_page } from '../api';
+import TheEmpty from '/src/components/TheEmpty';
 
 export default defineComponent({
   name: 'content-instrument',
@@ -20,10 +21,12 @@ export default defineComponent({
     const router = useRouter();
     const state = reactive({
       tabValue: '',
-      categoryList: [] as any
+      categoryList: [] as any,
+      loading: false
     });
 
     const getCategoryList = async () => {
+      state.loading = true;
       try {
         const { data } = await api_knowledgeWikiCategoryType_page({
           type: 'INSTRUMENT',
@@ -40,6 +43,7 @@ export default defineComponent({
       } catch {
         //
       }
+      state.loading = false;
     };
 
     getCategoryList();
@@ -58,7 +62,16 @@ export default defineComponent({
         </NSpace>
 
         <div class={styles.wrap}>
-          <div class={styles.listWrap}>
+          <div
+            class={[
+              styles.listWrap,
+              !state.loading &&
+                state.categoryList.length <= 0 &&
+                styles.listWrapEmpty
+            ]}>
+            {!state.loading && state.categoryList.length <= 0 && (
+              <TheEmpty description="暂无乐器百科" />
+            )}
             <NTabs
               defaultValue="myResources"
               paneClass={styles.paneTitle}

+ 9 - 1
src/views/content-information/content-music/index.module.less

@@ -100,8 +100,16 @@
   padding: 32px 20px;
   background-color: #fff;
   border-radius: 20px;
-  min-height: 100%;
+  // min-height: 100%;
   width: calc(100vw - 164px); // min-height: calc(100% - 104px);
+  // min-height: 100%;
+  min-height: calc(100vh - 192px);
+
+  &.listWrapEmpty {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
 
   :global {
     .n-tabs-tab-pad {

+ 15 - 2
src/views/content-information/content-music/index.tsx

@@ -11,6 +11,7 @@ import icon_back from '../../xiaoku-music/images/icon_back.png';
 import { useRouter } from 'vue-router';
 import List from './components/list';
 import { api_knowledgeWikiCategoryType_page } from '../api';
+import TheEmpty from '/src/components/TheEmpty';
 
 // 164px 244px
 export default defineComponent({
@@ -20,10 +21,12 @@ export default defineComponent({
     const router = useRouter();
     const state = reactive({
       tabValue: '',
-      categoryList: [] as any
+      categoryList: [] as any,
+      loading: false
     });
 
     const getCategoryList = async () => {
+      state.loading = true;
       try {
         const { data } = await api_knowledgeWikiCategoryType_page({
           type: 'MUSIC',
@@ -40,6 +43,7 @@ export default defineComponent({
       } catch {
         //
       }
+      state.loading = false;
     };
 
     getCategoryList();
@@ -58,7 +62,16 @@ export default defineComponent({
         </NSpace>
 
         <div class={styles.wrap}>
-          <div class={styles.listWrap}>
+          <div
+            class={[
+              styles.listWrap,
+              !state.loading &&
+                state.categoryList.length <= 0 &&
+                styles.listWrapEmpty
+            ]}>
+            {!state.loading && state.categoryList.length <= 0 && (
+              <TheEmpty description="暂无名曲鉴赏" />
+            )}
             <NTabs
               defaultValue="myResources"
               paneClass={styles.paneTitle}

+ 10 - 2
src/views/content-information/content-musician/index.module.less

@@ -100,8 +100,16 @@
   padding: 32px 20px;
   background-color: #fff;
   border-radius: 20px;
-  min-height: 100%;
-  // min-height: calc(100% - 104px);
+
+
+  // min-height: 100%;
+  min-height: calc(100vh - 192px);
+
+  &.listWrapEmpty {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+  }
 
   :global {
     .n-tabs-tab-pad {

+ 15 - 2
src/views/content-information/content-musician/index.tsx

@@ -12,6 +12,7 @@ import icon_back from '../../xiaoku-music/images/icon_back.png';
 import { useRoute, useRouter } from 'vue-router';
 import List from './components/list';
 import { api_knowledgeWikiCategoryType_page } from '../api';
+import TheEmpty from '/src/components/TheEmpty';
 
 export default defineComponent({
   name: 'content-musician',
@@ -20,10 +21,12 @@ export default defineComponent({
     const router = useRouter();
     const state = reactive({
       tabValue: '',
-      categoryList: [] as any
+      categoryList: [] as any,
+      loading: false
     });
 
     const getCategoryList = async () => {
+      state.loading = true;
       try {
         const { data } = await api_knowledgeWikiCategoryType_page({
           type: 'MUSICIAN',
@@ -40,6 +43,7 @@ export default defineComponent({
       } catch {
         //
       }
+      state.loading = false;
     };
 
     getCategoryList();
@@ -58,7 +62,16 @@ export default defineComponent({
         </NSpace>
 
         <div class={styles.wrap}>
-          <div class={styles.listWrap}>
+          <div
+            class={[
+              styles.listWrap,
+              !state.loading &&
+                state.categoryList.length <= 0 &&
+                styles.listWrapEmpty
+            ]}>
+            {!state.loading && state.categoryList.length <= 0 && (
+              <TheEmpty description="暂无音乐家" />
+            )}
             <NTabs
               defaultValue="myResources"
               paneClass={styles.paneTitle}

+ 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

@@ -28,6 +28,8 @@ import dingPng from './images/ding.png';
 import closeAble from './images/closeAble.png';
 import infoIcon from './images/infoIcon.png';
 import { state } from '/src/state';
+import TheAuth from '/src/components/TheAuth';
+import { mutualTLSQuery } from './api';
 export default defineComponent({
   name: 'login-page',
   setup() {
@@ -39,6 +41,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);
@@ -103,6 +106,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();
@@ -214,6 +226,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(() => {