|
@@ -1,47 +1,132 @@
|
|
|
<script lang="ts" setup>
|
|
|
-import { onMounted } from "vue";
|
|
|
-import menuData from "./menu.json";
|
|
|
-console.log(menuData);
|
|
|
+import { computed, onMounted, watch } from "vue";
|
|
|
+import { store } from "@/store/store";
|
|
|
+import {
|
|
|
+ appDownloadApi,
|
|
|
+ appEnableApi,
|
|
|
+ studentClientMenuApi,
|
|
|
+} from "@/api/mainLayout";
|
|
|
+import { useRoute, useRouter } from "vue-router";
|
|
|
+import QM_LOGO from "./qm-logo.png";
|
|
|
+import VueQrcode from "@chenfengyuan/vue-qrcode";
|
|
|
|
|
|
-type MenuOption = {
|
|
|
+const router = useRouter();
|
|
|
+const route = useRoute();
|
|
|
+
|
|
|
+const user = store.user;
|
|
|
+
|
|
|
+// computed
|
|
|
+const customMenuLogo = computed(() =>
|
|
|
+ store.QECSConfig.IS_CUSTOM_MENU_LOGO
|
|
|
+ ? store.QECSConfig.CUS_MENU_LOGO_FILE_URL
|
|
|
+ : QM_LOGO
|
|
|
+);
|
|
|
+const bindUserQrcodeUrl = computed(() => {
|
|
|
+ const { rootOrgId, studentCodeList, identityNumber } = store.user;
|
|
|
+ return JSON.stringify({
|
|
|
+ rootOrgId,
|
|
|
+ studentCode: studentCodeList.join(),
|
|
|
+ identityNumber,
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+let appDownloadUrl = $ref("");
|
|
|
+let appEnable = $ref(false);
|
|
|
+// 页面初始化
|
|
|
+const initData = async () => {
|
|
|
+ const res1 = await appEnableApi(user.rootOrgId);
|
|
|
+ appEnable = res1.data;
|
|
|
+ if (appEnable) {
|
|
|
+ const res2 = await appDownloadApi();
|
|
|
+ appDownloadUrl = res2.data;
|
|
|
+ }
|
|
|
+};
|
|
|
+// 菜单相关
|
|
|
+interface MenuOption {
|
|
|
id: string;
|
|
|
- code: string;
|
|
|
name: string;
|
|
|
- routeCode: string;
|
|
|
+ routeName: string;
|
|
|
+}
|
|
|
+const menuRouterDict: Record<string, string> = {
|
|
|
+ STU_ONLINE_EXAM: "/online-exam",
|
|
|
+ STU_ONLINE_HOMEWORK: "/online-homework",
|
|
|
+ STU_ONLINE_PRACTICE: "/online-practice",
|
|
|
+ STU_OFFLINE_EXAM: "/offline-exam",
|
|
|
+ STU_NOTICE: "/site-message",
|
|
|
+ STU_MODIFY_PWD: "ChangePassword",
|
|
|
};
|
|
|
-
|
|
|
let curMenu = $ref("");
|
|
|
-let menuOptions = $ref<any[]>([]);
|
|
|
+let menuOptions = $ref<MenuOption[]>([]);
|
|
|
+let curMenuOption = $ref<MenuOption | undefined>();
|
|
|
+let breadcrumbs = $ref<MenuOption[]>([]);
|
|
|
|
|
|
-const getMenus = () => {
|
|
|
- menuOptions = menuData.map((item) => {
|
|
|
- return { ...item };
|
|
|
- });
|
|
|
+const getMenus = async () => {
|
|
|
+ const res = await studentClientMenuApi(store.user.rootOrgId);
|
|
|
+ menuOptions = res.data
|
|
|
+ .sort((a, b) => b.weight - a.weight)
|
|
|
+ .map((item) => {
|
|
|
+ return {
|
|
|
+ id: item.id,
|
|
|
+ name: item.name,
|
|
|
+ routeName: menuRouterDict[item.routeCode.toUpperCase()],
|
|
|
+ };
|
|
|
+ });
|
|
|
};
|
|
|
const swithMenu = (menu: MenuOption) => {
|
|
|
// console.log(menu);
|
|
|
- curMenu = menu.routeCode;
|
|
|
- console.log(curMenu);
|
|
|
+ console.log(menu.routeName);
|
|
|
+ void router.push({ name: menu.routeName });
|
|
|
};
|
|
|
|
|
|
-const breadcrumbs = $ref([
|
|
|
- {
|
|
|
- id: "1",
|
|
|
- url: "1",
|
|
|
- name: "考试",
|
|
|
- },
|
|
|
-]);
|
|
|
+// route change
|
|
|
+const routerChange = () => {
|
|
|
+ curMenuOption = menuOptions.find((item) => item.routeName === route.name);
|
|
|
+ if (!curMenuOption) return;
|
|
|
+ curMenu = curMenuOption.routeName;
|
|
|
+ breadcrumbs = [{ ...curMenuOption }];
|
|
|
+};
|
|
|
|
|
|
const toModifyPwd = () => {
|
|
|
- console.log("logout");
|
|
|
+ logger({
|
|
|
+ cnl: ["console"],
|
|
|
+ pgn: curMenuOption?.name,
|
|
|
+ act: "点击",
|
|
|
+ stk: "修改密码",
|
|
|
+ });
|
|
|
+
|
|
|
+ void router.push({ name: "ChangePassword" });
|
|
|
};
|
|
|
const toLogout = () => {
|
|
|
- console.log("logout");
|
|
|
+ logger({
|
|
|
+ cnl: ["console"],
|
|
|
+ pgn: curMenuOption?.name,
|
|
|
+ act: "点击",
|
|
|
+ stk: "退出登录",
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
-onMounted(() => {
|
|
|
- getMenus();
|
|
|
+onMounted(async () => {
|
|
|
+ void initData();
|
|
|
+ await getMenus();
|
|
|
+ console.log(route.name);
|
|
|
+
|
|
|
+ if (menuOptions.length && route.name === "MainLayout") {
|
|
|
+ void router.push({ name: menuOptions.slice(-1)[0].routeName });
|
|
|
+ // void router.push({ name: menuOptions[0].routeName });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ routerChange();
|
|
|
});
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => route,
|
|
|
+ (val) => {
|
|
|
+ console.log(val);
|
|
|
+
|
|
|
+ if (val.name === "MainLayout") return;
|
|
|
+ routerChange();
|
|
|
+ }
|
|
|
+);
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
@@ -49,7 +134,7 @@ onMounted(() => {
|
|
|
<!-- header -->
|
|
|
<div class="home-header">
|
|
|
<div class="header-infos">
|
|
|
- <div class="header-info">
|
|
|
+ <div v-if="appEnable" class="header-info">
|
|
|
<n-popover placement="bottom" trigger="hover">
|
|
|
<template #trigger>
|
|
|
<p class="header-info-cont">手机端登录(Android)</p>
|
|
@@ -58,12 +143,18 @@ onMounted(() => {
|
|
|
<n-tabs type="segment">
|
|
|
<n-tab-pane name="android" tab="下载安卓Apk">
|
|
|
<div class="qr-code">
|
|
|
- <img src="" alt="" />
|
|
|
+ <vue-qrcode
|
|
|
+ :value="appDownloadUrl"
|
|
|
+ :options="{ width: 200 }"
|
|
|
+ ></vue-qrcode>
|
|
|
</div>
|
|
|
</n-tab-pane>
|
|
|
<n-tab-pane name="bindUser" tab="绑定用户">
|
|
|
<div class="qr-code">
|
|
|
- <img src="" alt="" />
|
|
|
+ <vue-qrcode
|
|
|
+ :value="bindUserQrcodeUrl"
|
|
|
+ :options="{ width: 200 }"
|
|
|
+ ></vue-qrcode>
|
|
|
</div>
|
|
|
</n-tab-pane>
|
|
|
</n-tabs>
|
|
@@ -73,24 +164,28 @@ onMounted(() => {
|
|
|
<div class="header-info">
|
|
|
<n-popover placement="bottom" trigger="hover">
|
|
|
<template #trigger>
|
|
|
- <p class="header-info-cont">username</p>
|
|
|
+ <p class="header-info-cont">{{ user.displayName }}</p>
|
|
|
</template>
|
|
|
<div class="user-info">
|
|
|
<div class="user-info-item">
|
|
|
<span>底照</span>
|
|
|
- <img class="user-avatar" src="" alt="" />
|
|
|
+ <img
|
|
|
+ class="user-avatar"
|
|
|
+ :src="user.photoPath"
|
|
|
+ :alt="user.displayName"
|
|
|
+ />
|
|
|
</div>
|
|
|
<div class="user-info-item">
|
|
|
<span>学号</span>
|
|
|
- <span>学号1212</span>
|
|
|
+ <span>{{ user.studentCodeList.join() }}</span>
|
|
|
</div>
|
|
|
<div class="user-info-item">
|
|
|
<span>身份证号</span>
|
|
|
- <span>身份证号11</span>
|
|
|
+ <span>{{ user.identityNumber }}</span>
|
|
|
</div>
|
|
|
<div class="user-info-item">
|
|
|
<span>学习中心</span>
|
|
|
- <span>学习中心11</span>
|
|
|
+ <span>{{ user.orgName }}</span>
|
|
|
</div>
|
|
|
<div class="user-info-item">
|
|
|
<n-button type="success" block @click="toModifyPwd"
|
|
@@ -108,16 +203,14 @@ onMounted(() => {
|
|
|
<!-- navs -->
|
|
|
<div class="home-navs">
|
|
|
<div class="home-logo">
|
|
|
- <div class="home-logo-content">
|
|
|
- <!-- <img v-if="schoolLogo" :src="schoolLogo" alt="知学知考" /> -->
|
|
|
- </div>
|
|
|
+ <img :src="customMenuLogo" />
|
|
|
</div>
|
|
|
<div class="home-menu">
|
|
|
<div v-for="menu in menuOptions" :key="menu.id" class="home-menu-item">
|
|
|
<div
|
|
|
:class="[
|
|
|
'home-menu-content',
|
|
|
- { 'is-active': curMenu === menu.routeCode },
|
|
|
+ { 'is-active': curMenu === menu.routeName },
|
|
|
]"
|
|
|
@click="swithMenu(menu)"
|
|
|
>
|
|
@@ -134,7 +227,10 @@ onMounted(() => {
|
|
|
</span>
|
|
|
<div class="breadcrumb-body">
|
|
|
<n-breadcrumb>
|
|
|
- <n-breadcrumb-item v-for="bread in breadcrumbs" :key="bread.url">
|
|
|
+ <n-breadcrumb-item
|
|
|
+ v-for="bread in breadcrumbs"
|
|
|
+ :key="bread.routeName"
|
|
|
+ >
|
|
|
{{ bread.name }}
|
|
|
</n-breadcrumb-item>
|
|
|
</n-breadcrumb>
|
|
@@ -181,7 +277,7 @@ onMounted(() => {
|
|
|
vertical-align: middle;
|
|
|
font-size: var(--app-font-size);
|
|
|
position: relative;
|
|
|
- padding: 0 15px;
|
|
|
+ padding: 0 20px;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
.header-info-cont:hover {
|
|
@@ -205,14 +301,16 @@ onMounted(() => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
|
- padding: 10px 0;
|
|
|
+ padding: 12px 0;
|
|
|
+}
|
|
|
+.user-info-item:not(:last-child) {
|
|
|
border-bottom: 1px solid var(--app-color-border);
|
|
|
}
|
|
|
.user-avatar {
|
|
|
display: block;
|
|
|
width: 80px;
|
|
|
height: 80px;
|
|
|
- box-shadow: 0 0 1px var(--app-color-border);
|
|
|
+ box-shadow: 0 0 1px var(--app-color-border-dark);
|
|
|
}
|
|
|
.qr-list {
|
|
|
width: 240px;
|
|
@@ -221,7 +319,7 @@ onMounted(() => {
|
|
|
width: 200px;
|
|
|
height: 200px;
|
|
|
margin: 0 auto;
|
|
|
- padding: 10px 0;
|
|
|
+ padding: 0 0 20px;
|
|
|
}
|
|
|
.qr-code > img {
|
|
|
display: block;
|
|
@@ -244,11 +342,16 @@ onMounted(() => {
|
|
|
}
|
|
|
.home-logo {
|
|
|
width: 80px;
|
|
|
- height: 68px;
|
|
|
+ min-height: 62px;
|
|
|
+ max-height: 100px;
|
|
|
margin: 30px auto;
|
|
|
- background-color: var(--app-color-white);
|
|
|
border-radius: var(--app-border-radius);
|
|
|
}
|
|
|
+.home-logo > img {
|
|
|
+ display: block;
|
|
|
+ width: 100%;
|
|
|
+ height: auto;
|
|
|
+}
|
|
|
.home-menu {
|
|
|
color: var(--app-color-white);
|
|
|
}
|