黄琪勇 1 年之前
父节点
当前提交
5a22283734

+ 3 - 1
.env.development

@@ -1,3 +1,5 @@
-# 开发环境
+# 开发环境  管乐团和管乐迷 接口需要跨域  所以代理了一下
 
 VUE_APP_URL = "https://dev.resource.colexiu.com/cbs-app"
+VUE_APP_URL_GYM = "/gym/api-teacher"
+VUE_APP_URL_GYT = "/gyt/api-teacher"

+ 16 - 5
src/api/ApiInstance.ts

@@ -1,14 +1,25 @@
 import Http from "@/libs/axios"
 import { getToken } from "@/libs/auth"
-import { URL_API } from "@/config"
+import { URL_API, URL_API_GYM, URL_API_GYT } from "@/config"
 
 /** axios实例 */
-export const httpAxios = new Http(URL_API, {
-   tokenName: "Token",
-   getTokenFun: getToken
-})
+
+/* 中台 */
+export const httpAxios = new Http(URL_API)
 
 // 不带滚动条的
 export const httpAxiosNoNprogress = new Http(URL_API, {
    nprogress: false
 })
+
+/* 管乐迷 */
+export const httpAxios_gym = new Http(URL_API_GYM, {
+   tokenName: "Authorization",
+   getTokenFun: getToken
+})
+
+/* 管乐团 */
+export const httpAxios_gyt = new Http(URL_API_GYT, {
+   tokenName: "Authorization",
+   getTokenFun: getToken
+})

+ 19 - 9
src/api/user.api.ts

@@ -1,4 +1,4 @@
-import { httpAxios, httpAxiosNoNprogress } from "@/api/ApiInstance"
+import { httpAxios, httpAxiosNoNprogress, httpAxios_gym, httpAxios_gyt } from "@/api/ApiInstance"
 
 /** 获取二维码 */
 export const createQrcodeApi = () => {
@@ -16,14 +16,6 @@ export const queryQrcodeStatusApi = (uuid: string) => {
    })
 }
 
-/** 获取用户信息 */
-export const getUserInfo = () => {
-   return httpAxios.axioseRquest({
-      method: "get",
-      url: "/api/v1/useraccounts/getInfo"
-   })
-}
-
 /** 退出登录 */
 export const logout = () => {
    return httpAxios.axioseRquest({
@@ -42,3 +34,21 @@ export const getDictionary = (key: string) => {
       }
    })
 }
+
+/** 管乐迷 */
+
+//获取用户信息
+export const queryUserInfo_gym = () => {
+   return httpAxios_gym.axioseRquest({
+      method: "get",
+      url: "/teacher/queryUserInfo"
+   })
+}
+/** 管乐团*/
+// 获取用户信息
+export const getUserInfo_gyt = () => {
+   return httpAxios_gyt.axioseRquest({
+      method: "get",
+      url: "/user/getUserInfo"
+   })
+}

+ 1 - 1
src/assets/normalize.css

@@ -14,7 +14,7 @@ body {
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
-   font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
+   font-family: PingFang SC, Helvetica Neue, Helvetica, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
 }
 
 a:focus,

+ 2 - 0
src/config/index.ts

@@ -1 +1,3 @@
 export const URL_API = process.env.VUE_APP_URL as string
+export const URL_API_GYT = process.env.VUE_APP_URL_GYT as string
+export const URL_API_GYM = process.env.VUE_APP_URL_GYM as string

+ 11 - 85
src/config/menus.ts

@@ -1,99 +1,25 @@
-//固定tags设置,根据角色来自己设置需要固定到上面的tags
-export const affixtagsPaths: string[] = []
-//需要缓存的视图name
-export const constCachedViewNames: string[] = []
 //模拟数据 实际不需要由api提供
-export const menus: menuType[] = [
+export const menus_gyt: menuType[] = [
    {
-      path: "/menus",
-      component: "menus",
-      title: "菜单",
+      path: "/homePage_gyt",
+      component: "homePage_gyt",
+      title: "管乐团首页",
       icon: "",
-      children: [],
       meta: {
-         routeType: "layout"
-      }
-   },
-   {
-      path: "/useraccounts",
-      component: "useraccounts",
-      title: "用户",
-      icon: "",
-      children: [],
-      meta: {
-         routeType: "layout"
-      }
-   },
-   {
-      path: "/roles",
-      component: "roles",
-      title: "roles",
-      icon: "",
-      meta: {
-         routeType: "layout"
-      },
-      children: []
-   },
-   {
-      path: "/test",
-      component: "test",
-      title: "test",
-      icon: "",
-      meta: {
-         routeType: "layout"
+         routeType: "singlepage"
       },
       children: []
-   },
+   }
+]
+export const menus_gym: menuType[] = [
    {
-      path: "/editor",
-      component: "editor",
-      title: "编辑器",
+      path: "/homePage_gym",
+      component: "homePage_gym",
+      title: "管乐迷首页",
       icon: "",
       meta: {
          routeType: "singlepage"
       },
       children: []
-   },
-   {
-      path: "/system",
-      title: "系统管理",
-      icon: "iconxitongguanli",
-      component: "layout",
-      meta: {
-         routeType: "layout"
-      },
-      children: [
-         {
-            path: "/organizations",
-            component: "organizations",
-            title: "单位",
-            icon: "",
-            children: [],
-            meta: {
-               routeType: "singlepage"
-            }
-         },
-         {
-            path: "/appointmentQuery",
-            title: "查询",
-            icon: "iconxitongguanli",
-            component: "",
-            meta: {
-               routeType: "layout"
-            },
-            children: [
-               {
-                  path: "/visitingQuery",
-                  component: "visitingQuery",
-                  title: "会见查询",
-                  icon: "",
-                  children: [],
-                  meta: {
-                     routeType: "layout"
-                  }
-               }
-            ]
-         }
-      ]
    }
 ]

二进制
src/img/loginErr/bStar.png


二进制
src/img/loginErr/bg.png


二进制
src/img/loginErr/border.png


二进制
src/img/loginErr/jiantou1.png


二进制
src/img/loginErr/jiantou2.png


二进制
src/img/loginErr/loginBox.png


二进制
src/img/loginErr/music.png


二进制
src/img/loginErr/paw.png


二进制
src/img/loginErr/refresh.png


二进制
src/img/loginErr/scanned.png


二进制
src/img/loginErr/star.png


二进制
src/img/loginErr/userName.png


二进制
src/img/loginErr/xiaoren.png


二进制
src/img/public/logo.png


二进制
src/img/public/yonghujuese.png


+ 25 - 3
src/libs/auth.ts

@@ -1,15 +1,19 @@
 import Cookies from "js-cookie"
 
 /* code */
-export const CODE401 = 5000 //没有权限
+// eslint-disable-next-line prefer-const
+export let CODE401 = 401 //没有权限   管乐迷为401  管乐团为5000
+export function setCODE401(code: number) {
+   CODE401 = code
+}
 
 /** cookie */
-const TokenKey = "demo-Token"
+const TokenKey = "classroom-Token"
 const expiresDate = 7
 
 export let TokenInvalidFlag = true //令牌是否有效
 export function getToken() {
-   return Cookies.get(TokenKey)
+   return Cookies.get(TokenKey) && "bearer " + Cookies.get(TokenKey)
 }
 
 export function setToken(token: string) {
@@ -22,6 +26,24 @@ export function removeToken() {
    return Cookies.remove(TokenKey)
 }
 
+/**
+ * 设置 用户类型
+ */
+
+const userType = "userType"
+
+export function getUserType() {
+   return Cookies.get(userType)
+}
+
+export function setUserType(type: string) {
+   return Cookies.set(userType, type, { expires: expiresDate })
+}
+
+export function removeUserType() {
+   return Cookies.remove(userType)
+}
+
 /** 密码加上正则 */
 import md5 from "md5"
 const code = "plzh@"

+ 3 - 3
src/libs/axios.ts

@@ -41,7 +41,7 @@ class HttpAsynAxios {
             Nprogress.done()
             const rejectData: apiResDataType = {
                code: 500,
-               msg: "系统运行异常,请联系管理员处理",
+               message: "系统运行异常,请联系管理员处理",
                data: null
             }
             return Promise.reject(rejectData)
@@ -56,7 +56,7 @@ class HttpAsynAxios {
                //如果token登录状态 才提示和退出
                if (TokenInvalidFlag) {
                   const responseData: apiResDataType = response.data
-                  ElMessage.error(responseData.msg)
+                  ElMessage.error(responseData.message)
                   //登出
                   userStore().resetUser()
                }
@@ -74,7 +74,7 @@ class HttpAsynAxios {
             // }
             const rejectData: apiResDataType = {
                code: 500,
-               msg: "系统运行异常,请联系管理员处理",
+               message: "系统运行异常,请联系管理员处理",
                data: null
             }
             return Promise.reject(rejectData) // 返回接口返回的错误信息

+ 9 - 29
src/libs/utils.ts

@@ -1,25 +1,4 @@
 /**
- * 递归查询  通过url查询出菜单中的menu
-   path  url
-   menus   菜单
- */
-export const generateMenus = (path: string, menus: menuType[]): menuType | null => {
-   let menu = null
-   function findMenu(path: string, menus: menuType[]) {
-      for (const item of menus) {
-         if (item.path === path) {
-            menu = item
-            return
-         } else if (item.children && item.children.length) {
-            findMenu(path, item.children)
-         }
-      }
-   }
-   findMenu(path, menus)
-   return menu
-}
-
-/**
  * 通过menus 计算出asyncRoutes 动态路由
  */
 import { RouteRecordRaw } from "vue-router"
@@ -54,15 +33,16 @@ export const generateAsyncRoutes = (menus: menuType[], components: asyncComponen
          singlepageRoutes
       }
    }
-   const { layoutRoutes, singlepageRoutes } = menusAsyncRoutes(menus)
+   //const { layoutRoutes, singlepageRoutes } = menusAsyncRoutes(menus)
+   const { singlepageRoutes } = menusAsyncRoutes(menus)
    const asyncRoutes: RouteRecordRaw[] = [
-      {
-         path: "/layout",
-         name: "layout",
-         redirect: "/noRedirect",
-         component: components["layout"],
-         children: layoutRoutes
-      },
+      // {
+      //    path: "/layout",
+      //    name: "layout",
+      //    redirect: "/noRedirect",
+      //    component: components["layout"],
+      //    children: layoutRoutes
+      // },
       ...singlepageRoutes
    ]
    //默认获取第一个菜单为首页

+ 11 - 11
src/plugin/httpAjax.ts

@@ -25,7 +25,7 @@ export const httpAjaxErrMsg = function <T extends axiosApiType, P extends Parame
             if (data.code !== 200) {
                ElMessage({
                   showClose: true,
-                  message: data.msg,
+                  message: data.message,
                   type: "error"
                })
             }
@@ -34,7 +34,7 @@ export const httpAjaxErrMsg = function <T extends axiosApiType, P extends Parame
          .catch(err => {
             ElMessage({
                showClose: true,
-               message: err.msg,
+               message: err.message,
                type: "error"
             })
             resolve(err)
@@ -69,7 +69,7 @@ export const httpAjaxLoadingErrMsg = function <T extends axiosApiType, P extends
             if (data.code !== 200) {
                ElMessage({
                   showClose: true,
-                  message: data.msg,
+                  message: data.message,
                   type: "error"
                })
             }
@@ -79,7 +79,7 @@ export const httpAjaxLoadingErrMsg = function <T extends axiosApiType, P extends
             LoadingBar.loading(false)
             ElMessage({
                showClose: true,
-               message: err.msg,
+               message: err.message,
                type: "error"
             })
             resolve(err)
@@ -98,7 +98,7 @@ export const httpAjaxCrud = function <T extends axiosApiType, P extends Paramete
                ElNotification({
                   type: "success",
                   title: "成功",
-                  message: data.msg,
+                  message: data.message,
                   position: "top-right",
                   duration: 3000
                })
@@ -106,7 +106,7 @@ export const httpAjaxCrud = function <T extends axiosApiType, P extends Paramete
                ElNotification({
                   type: "error",
                   title: "失败",
-                  message: data.msg,
+                  message: data.message,
                   position: "top-right",
                   duration: 3000
                })
@@ -118,7 +118,7 @@ export const httpAjaxCrud = function <T extends axiosApiType, P extends Paramete
             ElNotification({
                type: "error",
                title: "失败",
-               message: err.msg,
+               message: err.message,
                position: "top-right",
                duration: 3000
             })
@@ -136,12 +136,12 @@ export const httpAjaxAlert = function <T extends axiosApiType, P extends Paramet
             LoadingBar.loading(false)
             const data = res.data as apiResDataType
             if (data.code === 200) {
-               ElMessageBox.alert(data.msg, "提示", {
+               ElMessageBox.alert(data.message, "提示", {
                   confirmButtonText: "关闭",
                   type: "success"
                })
             } else {
-               ElMessageBox.alert(data.msg, "提示", {
+               ElMessageBox.alert(data.message, "提示", {
                   confirmButtonText: "关闭",
                   type: "error"
                })
@@ -150,7 +150,7 @@ export const httpAjaxAlert = function <T extends axiosApiType, P extends Paramet
          })
          .catch(err => {
             LoadingBar.loading(false)
-            ElMessageBox.alert(err.msg, "提示", {
+            ElMessageBox.alert(err.message, "提示", {
                confirmButtonText: "关闭",
                type: "error"
             })
@@ -180,7 +180,7 @@ export const httpAjaxDownload = function <T extends axiosApiType, P extends Para
          LoadingBar.loading(false)
          ElMessage({
             showClose: true,
-            message: err.msg,
+            message: err.message,
             type: "error"
          })
       })

+ 1 - 1
src/router/index.ts

@@ -50,7 +50,7 @@ router.beforeEach((to, from, next) => {
             .catch((err: apiResDataType) => {
                //退出 清空,当是登录权限问题时候 axios 里面会清空
                if (err.code !== CODE401) {
-                  ElMessage.error(err.msg)
+                  ElMessage.error(err.message)
                   userStoreHook.resetUser()
                }
             })

+ 4 - 1
src/router/modules.ts

@@ -1 +1,4 @@
-export default {}
+export default {
+   homePage_gym: () => import("@/views/homePage/homePage_gym.vue"),
+   homePage_gyt: () => import("@/views/homePage/homePage_gyt.vue")
+}

+ 23 - 32
src/store/modules/user.ts

@@ -1,14 +1,15 @@
 import { defineStore } from "pinia"
 import { store } from "../index"
 // eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { createQrcodeApi, getUserInfo, logout } from "@/api/user.api"
-import { removeToken, setToken } from "@/libs/auth"
+import { logout, getUserInfo_gyt, queryUserInfo_gym } from "@/api/user.api"
+import { removeToken, setToken, setUserType, getUserType, removeUserType, setCODE401 } from "@/libs/auth"
 import router, { resetRouter } from "@/router"
 import { httpAjax } from "@/plugin/httpAjax"
-import { menus } from "@/config/menus"
+import { menus_gym, menus_gyt } from "@/config/menus"
+
 interface userDataType {
-   loginname: string
-   password: string
+   appKey: string
+   data: any
 }
 interface userType {
    userInfo: Record<string, any>
@@ -24,45 +25,34 @@ const useStore = defineStore("user", {
    },
    actions: {
       /** 登录 */
-      // eslint-disable-next-line @typescript-eslint/no-unused-vars
-      async login(user: userDataType) {
-         // const loginRes = await httpAjax(login, user)
-         const loginRes = {
-            code: 200,
-            data: {
-               token: "xxx"
-            }
-         }
-         if (loginRes.code !== 200) {
-            return Promise.reject(loginRes)
-         }
-         setToken(loginRes.data.token)
-         return Promise.resolve(loginRes)
+      async login({ data, appKey }: userDataType) {
+         // GYM 和 GYT 区分   获取token的区分
+         setToken(appKey === "GYM" ? data : data.access_token)
+         setUserType(appKey)
+         return Promise.resolve()
       },
       /** 获取用户信息 */
       async getUserInfo(): Promise<menuType[]> {
-         // const userInfoRes = await httpAjax(getUserInfo)
-         const userInfoRes = {
-            code: 200,
-            data: {
-               roleId: "123",
-               menus
-            }
-         }
+         const userType = getUserType()
+         // GYM 和 GYT 区分 code验证错误码的区分
+         userType !== "GYM" || setCODE401(5000)
+         // GYM 和 GYT 区分 获取用户信息的接口区分
+         const userInfoRes = await httpAjax(userType === "GYM" ? queryUserInfo_gym : getUserInfo_gyt)
          if (userInfoRes.code !== 200) {
             return Promise.reject(userInfoRes)
          }
-         const userInfo = userInfoRes.data || {}
-         if (!userInfo.roleId) {
+         if (!userType) {
             return Promise.reject({
                code: "500",
                data: null,
-               msg: "获取用户信息出错,请联系管理员!"
+               message: "获取用户信息出错,请联系管理员!"
             })
          }
+         const userInfo = userInfoRes.data || {}
          this.userInfo = userInfo
-         this.roles = userInfo.roleId
-         return Promise.resolve(userInfo.menus || [])
+         this.roles = userType
+         // GYM 和 GYT 区分  区分菜单然后分配路由
+         return Promise.resolve(userType === "GYM" ? menus_gym : menus_gyt)
       },
       /** 退出登录 */
       async loginOut() {
@@ -78,6 +68,7 @@ const useStore = defineStore("user", {
          this.userInfo = {}
          this.roles = ""
          removeToken()
+         removeUserType()
          resetRouter()
          router.push({
             path: "/login"

+ 1 - 1
src/type.d.ts

@@ -6,7 +6,7 @@
 declare interface apiResDataType {
    code: number
    data: any
-   msg: string
+   message: string
 }
 
 /*

+ 12 - 0
src/views/homePage/homePage_gym.vue

@@ -0,0 +1,12 @@
+<!--
+* @FileDescription: 管乐迷首页
+* @Author: 黄琪勇
+* @Date:2024-03-20 17:26:35
+-->
+<template>
+   <div class="homePage_gym">homePage_gym</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style lang="scss" scoped></style>

+ 12 - 0
src/views/homePage/homePage_gyt.vue

@@ -0,0 +1,12 @@
+<!--
+* @FileDescription: 管乐团首页
+* @Author: 黄琪勇
+* @Date:2024-03-20 17:26:35
+-->
+<template>
+   <div class="homePage_gyt">homePage_gyt</div>
+</template>
+
+<script setup lang="ts"></script>
+
+<style lang="scss" scoped></style>

+ 155 - 16
src/viewsframe/login/login.vue

@@ -5,9 +5,25 @@
 -->
 <template>
    <div class="login">
-      <ElButton @click="handleCreateQrcode">点击</ElButton>
-      <div v-loading="loading" class="qrcodeBox">
-         <qrcode-vue v-if="!loading" :value="qrcode" :size="220" />
+      <div class="decoration">
+         <img class="star" src="@/img/loginErr/star.png" />
+         <img class="bStar" src="@/img/loginErr/bStar.png" />
+         <img class="music" src="@/img/loginErr/music.png" />
+      </div>
+      <div class="loginBox">
+         <img v-show="qrcodeStatus === 2" class="scanned" src="@/img/loginErr/scanned.png" />
+         <div v-show="qrcodeStatus !== 2" v-loading="!uuid" class="qrcodeBox">
+            <div class="qrCodeCon" :class="{ refresh: qrcodeStatus === 3 }">
+               <qrcode-vue class="qrCode" v-if="uuid" :value="qrcode" :size="164" />
+               <img @click="handleRefresh" src="@/img/loginErr/refresh.png" />
+            </div>
+         </div>
+         <div class="dsc">
+            <img src="@/img/loginErr/jiantou1.png" />
+            <div>{{ qrcodeStatus === 2 ? "扫码完成,请在手机上操作" : "使用客户端扫描二维码登录乐教通" }}</div>
+            <img src="@/img/loginErr/jiantou2.png" />
+         </div>
+         <div class="refreshBtn" @click="handleRefresh">{{ qrcodeStatus === 2 ? "重新扫码" : "刷新二维码" }}</div>
       </div>
    </div>
 </template>
@@ -17,55 +33,178 @@ import { createQrcodeApi, queryQrcodeStatusApi } from "@/api/user.api"
 import { httpAjax } from "@/plugin/httpAjax"
 import QrcodeVue from "qrcode.vue"
 import { ref, computed } from "vue"
+import userStore from "@/store/modules/user"
+import { useRouter } from "vue-router"
+
+const userStoreHook = userStore()
+const router = useRouter()
 
-const uuid = ref<string>()
+const uuid = ref<string>("")
 const qrcode = computed(() => {
+   console.log(JSON.stringify({ action: "login", uuid: uuid.value }))
    return JSON.stringify({ action: "login", uuid: uuid.value })
 })
-const loading = ref(true)
+const qrcodeStatus = ref<1 | 2 | 3>(1) // 1 未扫码  2 扫码完成  3 二维码过期
+let _time: number
 
+handleCreateQrcode()
 function handleCreateQrcode() {
    httpAjax(createQrcodeApi).then(res => {
       if (res.code === 200) {
-         loading.value = false
          uuid.value = res.data.uuid
          handleQrcodeStatus()
       }
    })
 }
-
 function handleQrcodeStatus() {
    httpAjax(queryQrcodeStatusApi, uuid.value as string).then(res => {
       if (res.code === 200) {
          const { status } = res.data
          if (status === "FINISH") {
             // 登录成功
+            userStoreHook.login(res.data).then(() => {
+               router.push({ path: "/" })
+            })
             return
          }
          if (status === "SCANNED") {
             // 扫码完成
-            console.log("扫码完成")
+            qrcodeStatus.value = 2
          } else if (status === "VERIFIED") {
             // 已验证
-            console.log("已验证")
+            qrcodeStatus.value = 2
          } else if (status === "EXPIRED") {
-            // 已经失效
-            console.log("已经失效")
+            // 二维码过期
+            qrcodeStatus.value = 3
+            return
+         } else if (status === "NOT_SCAN") {
+            // 未扫码
+            qrcodeStatus.value = 1
          }
-         const _time = setTimeout(() => {
+         _time = setTimeout(() => {
             clearTimeout(_time)
             handleQrcodeStatus()
          }, 1000)
       } else if (res.code === 5440) {
-         console.log("已过期")
+         // 二维码过期
+         qrcodeStatus.value = 3
       }
    })
 }
+function handleRefresh() {
+   _time && clearTimeout(_time)
+   handleCreateQrcode()
+}
 </script>
 
 <style lang="scss" scoped>
-.qrcodeBox {
-   width: 250px;
-   height: 250px;
+.login {
+   width: 100%;
+   min-height: 100%;
+   background: url("@/img/loginErr/bg.png") no-repeat;
+   background-size: cover;
+   position: relative;
+   .loginBox {
+      position: absolute;
+      top: 166px;
+      right: 280px;
+      width: 440px;
+      height: 498px;
+      background: url("@/img/loginErr/loginBox.png") no-repeat;
+      background-size: cover;
+      z-index: 2;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      .scanned {
+         margin-top: 132px;
+      }
+      .qrcodeBox {
+         margin-top: 154px;
+         width: 188px;
+         height: 188px;
+         display: flex;
+         justify-content: center;
+         align-items: center;
+         background: url("@/img/loginErr/border.png") no-repeat;
+         background-size: cover;
+         .qrCodeCon {
+            position: relative;
+            &.refresh {
+               background-color: rgba(255, 255, 255, 0.8);
+               > .qrCode {
+                  opacity: 0.3;
+               }
+               > img {
+                  cursor: pointer;
+                  position: absolute;
+                  left: 50%;
+                  top: 50%;
+                  transform: translate(-50%, -50%);
+                  display: block;
+               }
+            }
+            > img {
+               display: none;
+            }
+         }
+      }
+      .dsc {
+         margin-top: 28px;
+         display: flex;
+         justify-content: center;
+         align-items: center;
+         > div {
+            width: 240px;
+            text-align: center;
+            font-size: 16px;
+            color: #777;
+            margin: 0 14px;
+         }
+      }
+      .refreshBtn {
+         margin-top: 14px;
+         line-height: 22px;
+         font-size: 16px;
+         color: #f67146;
+         display: inline;
+         font-weight: bold;
+         cursor: pointer;
+         &:hover {
+            opacity: $opacity-hover;
+         }
+      }
+   }
+   .decoration {
+      position: absolute;
+      top: 158px;
+      left: 346px;
+      width: 522px;
+      height: 626px;
+      background: url("@/img/loginErr/xiaoren.png") no-repeat;
+      background-size: cover;
+      z-index: 1;
+      .star {
+         position: absolute;
+         right: 0;
+         top: 0;
+         width: 26px;
+         height: 38px;
+      }
+      .bStar {
+         position: absolute;
+         left: -20px;
+         top: 178px;
+         width: 60px;
+         height: 58px;
+      }
+      .music {
+         position: absolute;
+         right: -26px;
+         top: 24px;
+         width: 28px;
+         height: 56px;
+      }
+   }
 }
 </style>

+ 16 - 0
vue.config.js

@@ -9,5 +9,21 @@ module.exports = defineConfig({
             additionalData: `@use "@/assets/variables.scss" as *;`
          }
       }
+   },
+   devServer: {
+      proxy: {
+         "/gym/api-teacher": {
+            target: "https://dev.dayaedu.com",
+            pathRewrite: {
+               "^/gym": ""
+            }
+         },
+         "/gyt/api-teacher": {
+            target: "https://dev.lexiaoya.cn",
+            pathRewrite: {
+               "^/gyt": ""
+            }
+         }
+      }
    }
 })