1158 lines
38 KiB
Vue
1158 lines
38 KiB
Vue
<template>
|
||
<div id="vol-container" :class="['vol-theme-' + theme]">
|
||
<!-- 顶部一级导航栏 -->
|
||
<div class="vol-top-header">
|
||
<div class="top-logo">
|
||
<img v-bind:src="logo" />
|
||
<span>跃动智慧体育平台</span>
|
||
</div>
|
||
<div class="top-nav-menus" ref="topNavMenusRef">
|
||
<span
|
||
v-for="item in topLevelMenus"
|
||
:key="item.id"
|
||
:class="['top-nav-item', { 'is-active': activeTopMenuId == item.id }]"
|
||
@click="selectTopMenu(item)"
|
||
>{{ item.name }}</span>
|
||
</div>
|
||
<div class="header-info">
|
||
<div class="h-link">
|
||
<a href="javascript:void(0)" @click="to(item)" v-for="(item, index) in links.filter((c) => { return c.icon; })" :key="index">
|
||
<span v-if="!item.icon"> {{ item.text }}</span>
|
||
<i v-else :class="item.icon"></i>
|
||
</a>
|
||
</div>
|
||
<div>
|
||
<img class="user-header" :src="userImg" :onerror="errorImg" />
|
||
</div>
|
||
<div class="user">
|
||
<span>{{ userName }}</span>
|
||
<br />
|
||
<span id="index-date"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 侧边二级导航栏 -->
|
||
<div v-show="activeTopMenuHasChildren" class="vol-aside" :style="{ width: menuWidth + 'px' }">
|
||
<div class="vol-menu">
|
||
<el-scrollbar style="height: 100%">
|
||
<VolMenu
|
||
:rootId="activeTopMenuId + ''"
|
||
:currentMenuId="currentMenuId"
|
||
:on-select="onSelect"
|
||
:enable="true"
|
||
:open-select="false"
|
||
:isCollapse="isCollapse"
|
||
:list="menuOptions"
|
||
></VolMenu>
|
||
</el-scrollbar>
|
||
</div>
|
||
</div>
|
||
<div class="vol-container" :style="{ left: activeTopMenuHasChildren ? (menuWidth - 1) + 'px' : '0px' }">
|
||
<div class="vol-path">
|
||
<el-tabs @tab-click="selectNav" @tab-remove="removeNav" @contextmenu.prevent="bindRightClickMenu(false)"
|
||
type="border-card" class="header-navigation" v-model="selectId" :strtch="false">
|
||
<el-tab-pane v-for="(item, navIndex) in navigation" type="card" :name="navIndex + ''" :closable="navIndex > 0"
|
||
:key="navIndex" :label="item.name">
|
||
<span style="display: none">{{ navIndex }}</span>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
<!-- 右键菜单 -->
|
||
<div v-show="contextMenuVisible">
|
||
<ul :style="{ left: menuLeft + 'px', top: menuTop + 'px' }" class="contextMenu">
|
||
<li v-show="visibleItem.all">
|
||
<el-button type="info" @click="closeTabs()" size="default">
|
||
<i class="el-icon-close"></i>
|
||
{{
|
||
navigation.length == 2 ? "关闭菜单" : "关闭所有"
|
||
}}</el-button>
|
||
</li>
|
||
<li v-show="visibleItem.left">
|
||
<el-button type="info" @click="closeTabs('left')" size="default"><i
|
||
class="el-icon-back"></i>关闭左边</el-button>
|
||
</li>
|
||
<li v-show="visibleItem.right">
|
||
<el-button type="info" @click="closeTabs('right')" size="default">
|
||
<i class="el-icon-right"></i>关闭右边</el-button>
|
||
</li>
|
||
<li v-show="visibleItem.other">
|
||
<el-button type="info" @click="closeTabs('other')"><i class="el-icon-right"></i>关闭其他
|
||
</el-button>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="vol-main" id="vol-main">
|
||
<el-scrollbar style="height: 100%" v-if="permissionInited">
|
||
<loading v-show="$store.getters.isLoading()"></loading>
|
||
<router-view v-if="!$route.meta ||
|
||
($route.meta && !$route.meta.hasOwnProperty('keepAlive'))
|
||
" v-slot="{ Component }">
|
||
<transition name="page-fade" mode="out-in">
|
||
<component :is="Component" :key="$route.path" />
|
||
</transition>
|
||
</router-view>
|
||
<router-view v-if="$route.meta && $route.meta.hasOwnProperty('keepAlive')"></router-view>
|
||
</el-scrollbar>
|
||
</div>
|
||
</div>
|
||
<!-- 溢出菜单已改为水平滚动,Teleport 面板保留备用 -->
|
||
|
||
<el-drawer title="选择主题" v-model="drawer_model" direction="rtl" destroy-on-close>
|
||
<div class="theme-selector">
|
||
<div @click="changeTheme(item.name)" class="item" v-for="(item, index) in theme_color" :key="index"
|
||
:style="{ background: item.color }">
|
||
<div v-show="item.leftColor" :style="{ background: item.leftColor }" style="height: 100%; width: 20px"
|
||
class="t-left"></div>
|
||
<div class="t-right"></div>
|
||
</div>
|
||
</div>
|
||
</el-drawer>
|
||
|
||
<el-drawer title="消息列表" v-model="messageModel" direction="rtl" destroy-on-close>
|
||
<Message :list="messageList"></Message>
|
||
</el-drawer>
|
||
</div>
|
||
</template>
|
||
<style lang="less" scoped>
|
||
@import "./index/index.less";
|
||
</style>
|
||
|
||
<!-- 页面切换动画:必须非 scoped,否则无法作用于子路由组件根元素 -->
|
||
<style lang="less">
|
||
/* ====== 页面切换动画 ====== */
|
||
.page-fade-enter-active {
|
||
transition: opacity 0.22s cubic-bezier(0.25, 0.46, 0.45, 0.94),
|
||
transform 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||
will-change: opacity, transform;
|
||
}
|
||
.page-fade-leave-active {
|
||
transition: opacity 0.15s cubic-bezier(0.55, 0, 0.55, 0.2),
|
||
transform 0.15s cubic-bezier(0.55, 0, 0.55, 0.2);
|
||
will-change: opacity, transform;
|
||
}
|
||
.page-fade-enter-from {
|
||
opacity: 0;
|
||
transform: translateY(12px);
|
||
}
|
||
.page-fade-leave-to {
|
||
opacity: 0;
|
||
transform: translateY(-6px);
|
||
}
|
||
/* ====== 页面切换动画 END ====== */
|
||
</style>
|
||
<script>
|
||
import loading from "@/components/basic/RouterLoading.vue";
|
||
import VolMenu from "@/components/basic/VolElementMenu.vue";
|
||
import Message from "./index/Message.vue";
|
||
import MessageConfig from "./index/MessageConfig.js";
|
||
import eventBus from '@/eventBus.js'; // 导入事件总线
|
||
// import { openDB } from 'idb';
|
||
// const dbName = 'videoImg';
|
||
// const storeName = 'videofusion';
|
||
var imgUrl = require("@/assets/imgs/logo.png");
|
||
var $this;
|
||
var $interval;
|
||
var $indexDate;
|
||
import {
|
||
defineComponent,
|
||
reactive,
|
||
ref,
|
||
watch,
|
||
computed,
|
||
nextTick,
|
||
onMounted,
|
||
getCurrentInstance,
|
||
} from "vue";
|
||
import { useRouter, useRoute } from "vue-router";
|
||
import store from "../store/index";
|
||
import http from "@/../src/api/http.js";
|
||
import { ElMessage } from "element-plus";
|
||
export default defineComponent({
|
||
components: {
|
||
VolMenu,
|
||
loading,
|
||
Message,
|
||
},
|
||
|
||
data() {
|
||
return {
|
||
allTabs: true,
|
||
leftTabs: true,
|
||
rightTabs: true,
|
||
otherTabs: true,
|
||
menuLeft: 0,
|
||
menuTop: 0,
|
||
// contextMenuVisible: false, // 右键关闭显/隐
|
||
};
|
||
},
|
||
setup(props, context) {
|
||
// 获取全局属性和方法
|
||
const { proxy } = getCurrentInstance();
|
||
// 菜单导航默认宽度
|
||
const menuWidth = ref(200);
|
||
const topNavMenusRef = ref(null);
|
||
const contextMenuVisible = ref(false);
|
||
const isCollapse = ref(false);
|
||
const drawer_model = ref(false);
|
||
const messageModel = ref(false);
|
||
const theme_color = ref([
|
||
{ name: "blue", color: "rgb(45, 140, 240)" },
|
||
{ name: "blue2", color: "rgb(45, 140, 240)", leftColor: "#0068d6" },
|
||
{ name: "red", color: "rgb(237, 64, 20)" },
|
||
{ name: "red2", color: "rgb(237, 64, 20)", leftColor: "#a90000" },
|
||
{ name: "dark", color: "#272929" },
|
||
{ name: "orange", color: "#ff9900" },
|
||
{ name: "orange2", color: "#ff9900", leftColor: "rgb(232 141 5)" },
|
||
{ name: "green", color: "rgb(25, 190, 107)" },
|
||
{ name: "green2", color: "rgb(25, 190, 107)", leftColor: "#019e4f" },
|
||
{ name: "white", color: "#fff" },
|
||
]);
|
||
const links = ref([
|
||
{ text: "个人中心", path: "/UserInfo", id: -1, icon: "el-icon-s-custom" },
|
||
{
|
||
text: "安全退出",
|
||
path: "/login",
|
||
id: -4,
|
||
icon: "el-icon-switch-button",
|
||
},
|
||
]);
|
||
const errorImg = ref(
|
||
'this.src="' + require("@/assets/imgs/error-img.png") + '"'
|
||
);
|
||
const selectId = ref("1");
|
||
// 【首页】标签序号(当前右键选中的菜单)
|
||
const selectMenuIndex = ref("0");
|
||
//2022.05.29增加tab选项与菜单联动功能
|
||
const currentMenuId = ref(0);
|
||
const userName = ref("--");
|
||
const userInfo = ref({});
|
||
const visibleItem = reactive({
|
||
left: false,
|
||
right: false,
|
||
all: false,
|
||
other: false,
|
||
});
|
||
const userImg = ref("");
|
||
const navigation = reactive([
|
||
{ orderNo: "0", id: "1", name: "看板", path: "/bigScreen" },
|
||
// { orderNo: "0", id: "1", name: "双碳评估汇总", path: "/evaluationSummary" },
|
||
|
||
]);
|
||
const logo = ref(imgUrl);
|
||
const theme = ref("blue2");
|
||
const menuOptions = ref([]);
|
||
const activeTopMenuId = ref(0);
|
||
const topLevelMenus = computed(() => {
|
||
return menuOptions.value.filter(item => item.parentId == 0 && item.enable != 2);
|
||
});
|
||
const activeTopMenuHasChildren = computed(() => {
|
||
return menuOptions.value.some(item => item.parentId == activeTopMenuId.value);
|
||
});
|
||
const findTopLevelParent = (itemId) => {
|
||
const flatList = menuOptions.value;
|
||
let current = flatList.find(x => x.id == itemId);
|
||
while (current && current.parentId != 0 && current.parentId !== undefined && current.parentId !== null) {
|
||
current = flatList.find(x => x.id == current.parentId);
|
||
}
|
||
return current ? current.id : null;
|
||
};
|
||
const selectTopMenu = (item) => {
|
||
activeTopMenuId.value = item.id;
|
||
// 没有二级子菜单时直接跳转到该菜单对应的页面
|
||
const hasChildren = menuOptions.value.some(x => x.parentId == item.id);
|
||
if (!hasChildren && item.path) {
|
||
open(item , true);
|
||
router.push({ path: item.path});
|
||
}
|
||
};
|
||
// ====== 溢出菜单逻辑已移除(改为水平滚动)======
|
||
const routerList = ref(JSON.parse(localStorage.getItem("routerList")))
|
||
const permissionInited = ref(false);
|
||
const messageList = reactive([]);
|
||
let _config = getCurrentInstance().appContext.config.globalProperties;
|
||
let router = useRouter();
|
||
const toggleLeft = () => {
|
||
isCollapse.value = !isCollapse.value;
|
||
menuWidth.value = isCollapse.value ? 63 : 200;
|
||
};
|
||
//2021.08.28开放手动折叠菜单方法
|
||
_config.menu = {
|
||
show() {
|
||
toggleLeft();
|
||
},
|
||
hide() {
|
||
toggleLeft();
|
||
},
|
||
};
|
||
const changeTheme = (name) => {
|
||
if (theme.value != name) {
|
||
theme.value = name;
|
||
}
|
||
localStorage.setItem("vol3_theme", blue);
|
||
};
|
||
const to = (item) => {
|
||
if (item.path.indexOf("http") != -1) {
|
||
window.open(item.path);
|
||
return;
|
||
}
|
||
if (typeof item == "string" || item.path == "/login") {
|
||
if (item == "/login" || item.path == "/login") {
|
||
store.commit("clearUserInfo", "");
|
||
window.location.href = "/";
|
||
return;
|
||
}
|
||
router.push({ path: item });
|
||
return;
|
||
}
|
||
if (item.path == "#") return;
|
||
open(item);
|
||
};
|
||
const open = (item, useRoute) => {
|
||
/* 2020.07.31增加手动打开tabs*/
|
||
let _index = navigation?.findIndex((x) => {
|
||
return x.path == item.path;
|
||
});
|
||
|
||
if (_index == -1) {
|
||
navigation.push({
|
||
// orderNo: String(navigation.length),// 序号
|
||
id: item.id + "",
|
||
name: item.name || item.text || "无标题",
|
||
path: item.path,
|
||
query: item.query, //2021.03.20修复自定义二次打开$tabs时参数丢失的问题
|
||
});
|
||
//新打开的tab移至最后一个选项
|
||
selectId.value = navigation.length - 1 + "";
|
||
} else {
|
||
selectId.value = _index + "";
|
||
}
|
||
if (useRoute === undefined) {
|
||
//非标准菜单,记录最后一次跳转的页面,用于刷新
|
||
setItem(item);
|
||
router.push(item);
|
||
// this.$router.push(item);
|
||
}
|
||
currentMenuId.value = item.id * 1;
|
||
// tab菜单绑定右键事件
|
||
proxy.$nextTick(function (e) {
|
||
proxy.bindRightClickMenu(true);
|
||
});
|
||
};
|
||
const close = (path) => {
|
||
/* 2020.07.31增加手动打开tabs*/
|
||
let index = navigation.findIndex((x) => {
|
||
return x.path == path;
|
||
});
|
||
if (index == -1) {
|
||
return _config.$Message.error("未找到菜单");
|
||
}
|
||
removeNav(index);
|
||
};
|
||
const setItem = (item) => {
|
||
/* 2020.07.31增加手动打开tabs*/
|
||
localStorage.setItem(
|
||
window.location.origin + "_tabs",
|
||
JSON.stringify(item)
|
||
);
|
||
};
|
||
const getItem = () => {
|
||
/* 2020.07.31增加手动打开tabs*/
|
||
let nav = localStorage.getItem(window.location.origin + "_tabs");
|
||
return nav ? JSON.parse(nav) : null;
|
||
};
|
||
const selectNav = (item) => {
|
||
//升级element正式版修改
|
||
selectId.value = item.props.name;
|
||
let _path = navigation[item.index].path;
|
||
currentMenuId.value = (
|
||
menuOptions.value.find((c) => {
|
||
return c.path == _path;
|
||
}) || { id: 0 }
|
||
).id;
|
||
|
||
router.push({
|
||
path: navigation[item.index].path,
|
||
query: navigation[item.index].query,
|
||
});
|
||
};
|
||
|
||
const removeNav = (_index) => {
|
||
return new Promise(() => {
|
||
//关闭的当前项,跳转到前一个页面
|
||
if (selectId.value == _index + "") {
|
||
setItem(navigation[_index - 1]);
|
||
router.push({
|
||
path: navigation[_index - 1].path,
|
||
//2022.06.27修复tabs二次切换后参数丢失的问题
|
||
query: navigation[_index - 1].query,
|
||
});
|
||
navigation.splice(_index, 1);
|
||
selectId.value = selectId.value - 1 + "";
|
||
return;
|
||
}
|
||
if (_index < selectId.value) {
|
||
selectId.value = selectId.value - 1 + "";
|
||
}
|
||
navigation.splice(_index, 1);
|
||
currentMenuId.value = (
|
||
menuOptions.value.find((c) => {
|
||
return c.path == navigation[selectId.value * 1].path;
|
||
}) || { id: 0 }
|
||
).id;
|
||
});
|
||
};
|
||
|
||
const getSelectMenuName = (id) => {
|
||
return menuOptions.value.find(function (x) {
|
||
return x.id == id;
|
||
});
|
||
};
|
||
eventBus.on('toViewGrade', (res) => {
|
||
console.log(res, 'resss')
|
||
menuOptions.value.push({
|
||
"name": "年级数据统计",
|
||
"path": "/gradeView1",
|
||
"id": 240,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(240, ['240'])
|
||
localStorage.setItem('gradeId', JSON.stringify(res))
|
||
router.push({ name: 'gradeView1', params: res })
|
||
});
|
||
// 年级详情跳转班级详情
|
||
eventBus.on('toStudentView', (res) => {
|
||
console.log(res, 'ressstoStudentView')
|
||
let k = {
|
||
id:res.classId,
|
||
gradeId:res.gradeId
|
||
}
|
||
menuOptions.value.push({
|
||
"name": "班级数据统计",
|
||
"path": "/classView1",
|
||
"id": 242,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(242, ['242'])
|
||
localStorage.setItem('classView1', JSON.stringify(k))
|
||
router.push({ name: 'classView1', params: k })
|
||
});
|
||
eventBus.on('toView1', (res) => {
|
||
console.log(res, 'resss')
|
||
menuOptions.value.push({
|
||
"name": "教师数据统计",
|
||
"path": "/teacherView",
|
||
"id": 244,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(244, ['244'])
|
||
localStorage.setItem('teacherView', JSON.stringify(res))
|
||
router.push({ name: 'teacherView', params: res })
|
||
});
|
||
eventBus.on('toDetail', (res) => {
|
||
menuOptions.value.push({
|
||
"name": "班级数据统计",
|
||
"path": "/classView1",
|
||
"id": 242,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(242, ['242'])
|
||
localStorage.setItem('classId', JSON.stringify(res))
|
||
router.push({ name: 'classView1', params: res })
|
||
});
|
||
eventBus.on('toViewStudent', (res) => {
|
||
console.log(res,'ressstoViewStudent')
|
||
menuOptions.value.push({
|
||
"name": "学生数据统计",
|
||
"path": "/StudentDataStatistics",
|
||
"id": 245,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(245, ['245'])
|
||
localStorage.setItem('studentNo', JSON.stringify(res))
|
||
router.push({ name: 'StudentDataStatistics', params: res })
|
||
});
|
||
// 学生数据统计中的跳转训练记录 toRecord
|
||
eventBus.on('toRecord', (res) => {
|
||
menuOptions.value.push({
|
||
"name": "训练记录",
|
||
"path": "/trainingRecords",
|
||
"id": 286,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(286, ['286'])
|
||
localStorage.setItem('toRecord', JSON.stringify(res))
|
||
router.push({ name: 'trainingRecords', params: res })
|
||
});
|
||
// 学生数据统计中的跳转体测记录 toRecord
|
||
eventBus.on('toPhysical', (res) => {
|
||
menuOptions.value.push({
|
||
"name": "体测记录",
|
||
"path": "/examinationRecords",
|
||
"id": 287,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(287, ['287'])
|
||
localStorage.setItem('toRecord', JSON.stringify(res))
|
||
router.push({ name: 'examinationRecords', params: res })
|
||
});
|
||
eventBus.on('toEventDetail', (res) => {
|
||
menuOptions.value.push({
|
||
"name": "赛事活动详情",
|
||
"path": "/eventDetail",
|
||
"id": 255,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(255, ['255'])
|
||
router.push({ name: 'eventDetail', params: res })
|
||
});
|
||
// 跳转运动数据详情
|
||
eventBus.on('classRoomDetail', (res) => {
|
||
console.log(res, 'classRoomDetailclassRoomDetail')
|
||
menuOptions.value.push({
|
||
"name": "运动数据详情",
|
||
"path": "/trainingDetail",
|
||
"id": 276,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(276, ['276'])
|
||
localStorage.setItem('classRoomDetail', JSON.stringify(res))
|
||
router.push({ name: 'trainingDetail', params: res })
|
||
});
|
||
// 跳转体测数据详情
|
||
eventBus.on('phyClassRoomDetail', (res) => {
|
||
console.log(res, 'phyClassRoomDetail')
|
||
menuOptions.value.push({
|
||
"name": "体测数据详情",
|
||
"path": "/physicalDetail",
|
||
"id": 277,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(277, ['277'])
|
||
localStorage.setItem('physicalDetail', res)
|
||
router.push({ name: 'physicalDetail', params: res })
|
||
});
|
||
// 跳转专项管理详情
|
||
eventBus.on('specialDetails', (res) => {
|
||
console.log(res, 'specialDetails')
|
||
menuOptions.value.push({
|
||
"name": "专项管理详情",
|
||
"path": "/specialDetails",
|
||
"id": 280,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(280, ['280'])
|
||
localStorage.setItem('specialDetails', JSON.stringify(res))
|
||
router.push({ name: 'specialDetails', params: res })
|
||
});
|
||
|
||
eventBus.on('trainingDetails', (res) => {
|
||
console.log(res, 'trainingDetailstrainingDetails')
|
||
menuOptions.value.push({
|
||
"name": "训练详情",
|
||
"path": "/trainingDetails",
|
||
"id": 259,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(259, ['259'])
|
||
localStorage.setItem('studentNo', JSON.stringify(res))
|
||
router.push({ name: 'trainingDetails', params: res })
|
||
});
|
||
// 班级记录整体数据
|
||
eventBus.on('toExamEvaluation', (res) => {
|
||
console.log(res, 'examEvaluation')
|
||
menuOptions.value.push({
|
||
"name": "整体数据",
|
||
"path": "/overallData",
|
||
"id": 268,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(268, ['268'])
|
||
localStorage.setItem('studentNo', JSON.stringify(res))
|
||
router.push({ name: 'overallData', params: res })
|
||
});
|
||
// 班级记录表格详情
|
||
eventBus.on('ExamEvaluationTable', (res) => {
|
||
console.log(res, 'physicalDetails')
|
||
menuOptions.value.push({
|
||
"name": "体测详情",
|
||
"path": "/physicalDetails",
|
||
"id": 269,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(269, ['269'])
|
||
localStorage.setItem('studentNo', JSON.stringify(res))
|
||
router.push({ name: 'physicalDetails', params: res })
|
||
});
|
||
// 训练详情下的学生详情
|
||
eventBus.on('toStudentDetail', (res) => {
|
||
console.log(res, 'toStudentDetail')
|
||
menuOptions.value.push({
|
||
"name": "体测详情",
|
||
"path": "/studentDetails",
|
||
"id": 271,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(271, ['271'])
|
||
localStorage.setItem('studentNoDetail', JSON.stringify(res))
|
||
router.push({ name: 'studentDetails', params: res })
|
||
});
|
||
|
||
eventBus.on('toClassroomReportDetail', (res) => {
|
||
menuOptions.value.push({
|
||
"name": "课堂报告详情",
|
||
"path": "/ClassroomReportDetail",
|
||
"id": 272,
|
||
"icon": "iconfont icon-shuangtanyuce1"
|
||
})
|
||
onSelect(272, ['272'])
|
||
localStorage.setItem('ClassroomReportDetail', JSON.stringify(res))
|
||
router.push({ name: 'ClassroomReportDetail', params: res })
|
||
});
|
||
const onSelect = (treeId) => {
|
||
/* 2020.07.31增加手动打开tabs*/
|
||
var item = getSelectMenuName(treeId);
|
||
open(item, false);
|
||
const topId = findTopLevelParent(treeId);
|
||
if (topId !== null) activeTopMenuId.value = topId;
|
||
};
|
||
|
||
/**
|
||
* 显示右键菜单
|
||
* @param {*} e 事件对象
|
||
*/
|
||
const openTabsMenu = function (e) {
|
||
e.preventDefault(); // 防止默认菜单弹出
|
||
let tabId = e.target.id.split("-")[1] * 1;
|
||
|
||
//记录当前选中的菜单index
|
||
selectMenuIndex.value =
|
||
document.getElementById("pane-" + tabId).children[0].textContent * 1;
|
||
//只有首页时不显示
|
||
if (navigation.length == 1) {
|
||
return;
|
||
}
|
||
|
||
//首页设置显示关闭右边菜单
|
||
if (!selectMenuIndex.value) {
|
||
visibleItem.all = false;
|
||
visibleItem.right = true;
|
||
visibleItem.left = false;
|
||
visibleItem.other = false;
|
||
} else {
|
||
visibleItem.all = true;
|
||
//不是最后一个显示关闭右边菜单
|
||
visibleItem.right = selectMenuIndex.value != navigation.length - 1;
|
||
//只有两个菜单时不显示关闭左边
|
||
visibleItem.left = navigation.length != 2;
|
||
//只有两个菜单时不显示关闭其他
|
||
visibleItem.other = navigation.length != 2;
|
||
}
|
||
contextMenuVisible.value = true;
|
||
// 设置右键菜单显示的位置
|
||
proxy.menuLeft =
|
||
e.target.getBoundingClientRect().left - (isCollapse.value ? 63 : 198); //-e.target.clientWidth
|
||
proxy.menuTop = 36;
|
||
};
|
||
|
||
/**
|
||
* 关闭右键菜单
|
||
*/
|
||
const closeTabsMenu = () => {
|
||
contextMenuVisible.value = false;
|
||
};
|
||
const toHome = () => {
|
||
open({
|
||
text: navigation[0].name,
|
||
path: navigation[0].path,
|
||
});
|
||
};
|
||
|
||
setInterval(() => {
|
||
leftList.value.map((i) => {
|
||
deleteData(i.id)
|
||
})
|
||
rightList.value.map((i) => {
|
||
deleteData(i.id)
|
||
})
|
||
}, 24 * 60 * 60 * 1000)
|
||
/**
|
||
* 关闭其它标签页
|
||
* @param {*} par 关闭类型(left,right,other)
|
||
*/
|
||
const closeTabs = (value) => {
|
||
let _menuId = navigation[selectId.value * 1].id;
|
||
let currnetIndex = selectId.value * 1; // navigation.findIndex(c => { return c.id == selectId.value });
|
||
switch (value) {
|
||
case "left": {
|
||
// 删除左侧tab标签
|
||
navigation.splice(1, currnetIndex - 1); // 删除左侧tab标签
|
||
break;
|
||
}
|
||
case "right": {
|
||
// 删除右侧tab标签
|
||
if (selectMenuIndex.value == 0) {
|
||
navigation.splice(currnetIndex); // 删除右侧tab标签
|
||
toHome();
|
||
} else {
|
||
navigation.splice(currnetIndex + 1); // 删除右侧tab标签
|
||
if (selectMenuIndex.value < currnetIndex) {
|
||
navigation.splice(
|
||
selectMenuIndex.value,
|
||
currnetIndex - selectMenuIndex.value
|
||
);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
case "other": {
|
||
// 删除其他所有tab标签
|
||
navigation.splice(currnetIndex + 1); // 删除右侧tab标签(这里必须按照右→左顺序删除)
|
||
navigation.splice(1, currnetIndex - 1); // 删除左侧tab标签
|
||
break;
|
||
}
|
||
default: {
|
||
//关闭所有
|
||
navigation.splice(1, navigation.length);
|
||
toHome();
|
||
break;
|
||
}
|
||
}
|
||
selectId.value =
|
||
navigation.findIndex((c) => {
|
||
return c.id == _menuId;
|
||
}) + "";
|
||
closeTabsMenu();
|
||
};
|
||
|
||
watch(
|
||
() => contextMenuVisible.value,
|
||
(newVal, oldVal) => {
|
||
// 监视
|
||
if (newVal) {
|
||
document.body.addEventListener("click", closeTabsMenu);
|
||
} else {
|
||
document.body.removeEventListener("click", closeTabsMenu);
|
||
}
|
||
}
|
||
);
|
||
|
||
/**
|
||
* 系统创建开始
|
||
*/
|
||
const created = () => {
|
||
let _theme = localStorage.getItem("vol3_theme");
|
||
if (_theme) {
|
||
theme.value = _theme;
|
||
}
|
||
|
||
let _userInfo = store.getters.getUserInfo();
|
||
if (_userInfo) {
|
||
userName.value = _userInfo.userName;
|
||
if (_userInfo.img) {
|
||
userImg.value = _config.base.getImgSrc(_userInfo.img, http.ipAddress);
|
||
}
|
||
}
|
||
Object.assign(_config.$tabs, { open: open, close: close });
|
||
|
||
http.get("api/menu/getTreeMenu", {}, true).then((data) => {
|
||
// data = JSON.parse(data);
|
||
console.log(typeof (data), 'data.code')
|
||
|
||
if (typeof (data) != 'string') {
|
||
console.log(data, 'datatatagetTreeMenu')
|
||
data.push({ id: "1", name: "看板", url: "/bigScreen" }); // 为了获取选中id使用
|
||
// 页面路径与图标映射表
|
||
const iconMap = {
|
||
'/bigScreen': 'el-icon-s-home',
|
||
'/userManage': 'el-icon-user-solid',
|
||
'/teacherManage': 'el-icon-s-custom',
|
||
'/classManage': 'el-icon-s-grid',
|
||
'/studentsManage': 'el-icon-user',
|
||
'/gradeManage': 'el-icon-s-data',
|
||
'/schoolManage': 'el-icon-s-platform',
|
||
'/physicalManagement': 'el-icon-s-check',
|
||
'/gameManagement': 'el-icon-s-flag',
|
||
'/eventRegistration': 'el-icon-s-order',
|
||
'/eventRelease': 'el-icon-s-release',
|
||
'/eventStatistics': 'el-icon-s-marketing',
|
||
'/projectManage': 'el-icon-s-operation',
|
||
'/bodySideData': 'el-icon-s-data',
|
||
'/trainingRecords': 'el-icon-s-cooperation',
|
||
'/examinationRecords': 'el-icon-s-check',
|
||
'/ropeSkipping': 'el-icon-s-cooperation',
|
||
'/agile': 'el-icon-s-opportunity',
|
||
'/speed': 'el-icon-s-opportunity',
|
||
'/power': 'el-icon-s-opportunity',
|
||
'/balance': 'el-icon-s-opportunity',
|
||
'/heartRate': 'el-icon-s-opportunity',
|
||
'/examEvaluation': 'el-icon-s-data',
|
||
'/level': 'el-icon-s-flag',
|
||
'/record': 'el-icon-s-order',
|
||
'/studentResultRecord': 'el-icon-s-data',
|
||
'/articleManage': 'el-icon-s-comment',
|
||
'/resourceLibrary': 'el-icon-s-management',
|
||
'/homeWork': 'el-icon-s-order',
|
||
'/classroomReport': 'el-icon-s-data',
|
||
'/stadiumManage': 'el-icon-s-platform',
|
||
'/curricularTaxonomy': 'el-icon-s-grid',
|
||
'/curricularManage': 'el-icon-s-management',
|
||
'/popularCurricular': 'el-icon-star-on',
|
||
'/userActivity': 'el-icon-s-marketing',
|
||
'/physicalTestData': 'el-icon-s-data',
|
||
'/trainingData': 'el-icon-s-data',
|
||
'/visionData': 'el-icon-s-check',
|
||
'/specialManagement': 'el-icon-s-management',
|
||
'/ropeJumping': 'el-icon-s-cooperation',
|
||
'/sportsHallClass': 'el-icon-s-grid',
|
||
'/sportHallReport': 'el-icon-s-data',
|
||
'/TempTcc': 'el-icon-s-check',
|
||
'/summaryOfGrades': 'el-icon-s-data',
|
||
'/openReservation': 'el-icon-s-release',
|
||
'/PhysicalTestReport': 'el-icon-s-data',
|
||
'/AITraining': 'el-icon-s-opportunity',
|
||
'/Aitest': 'el-icon-s-opportunity',
|
||
'/eventDetail': 'el-icon-s-flag',
|
||
'/studentDetails': 'el-icon-user',
|
||
'/trainingDetail': 'el-icon-s-data',
|
||
'/physicalDetail': 'el-icon-s-data',
|
||
'/physicalDetails': 'el-icon-s-data',
|
||
'/overallData': 'el-icon-s-data',
|
||
'/classroomReportDetail': 'el-icon-s-data',
|
||
'/specialDetails': 'el-icon-s-data',
|
||
'/trainingDetails': 'el-icon-s-data',
|
||
'/StudentDataStatistics': 'el-icon-s-data',
|
||
'/classView1': 'el-icon-s-data',
|
||
'/gradeView1': 'el-icon-s-data',
|
||
'/teacherView': 'el-icon-s-data',
|
||
'/classDetail': 'el-icon-s-data',
|
||
'/enterHigh': 'el-icon-s-data',
|
||
'/signalR': 'el-icon-bell',
|
||
'/littleScreen': 'el-icon-s-home',
|
||
'/mapBigscreen': 'el-icon-s-home',
|
||
'/Sys_Log': 'el-icon-s-order',
|
||
'/Sys_User': 'el-icon-user-solid',
|
||
'/permission': 'el-icon-s-check',
|
||
'/Sys_Dictionary': 'el-icon-s-management',
|
||
'/Sys_Role': 'el-icon-s-custom',
|
||
'/Sys_Role1': 'el-icon-s-custom',
|
||
'/Sys_DictionaryList': 'el-icon-s-grid',
|
||
'/SellOrder': 'el-icon-s-order',
|
||
'/SellOrder2': 'el-icon-s-order',
|
||
'/SellOrder3': 'el-icon-s-order',
|
||
'/UserInfo': 'el-icon-s-custom',
|
||
'/sysMenu': 'el-icon-s-operation',
|
||
'/formDraggable': 'el-icon-s-operation',
|
||
'/formSubmit': 'el-icon-s-release',
|
||
'/formCollectionResultTree': 'el-icon-s-data',
|
||
};
|
||
data.forEach((d) => {
|
||
d.path = (d.url || "").replace("/Manager", "");
|
||
d.to = (d.url || "").replace("/Manager", "");
|
||
// 如果后端没有设置图标或图标不是 el- 开头,则从映射表匹配
|
||
if ((!d.icon || d.icon.substring(0, 3) !== 'el-') && iconMap[d.path]) {
|
||
d.icon = iconMap[d.path];
|
||
}
|
||
});
|
||
store.dispatch("setPermission", data);
|
||
// 过滤导航栏:隐藏 id < 200 的页面,但保留"用户管理"、"权限管理"、"角色管理"
|
||
const keepNames = ["用户管理", "权限管理", "角色管理"];
|
||
menuOptions.value = data.filter(item => item.id >= 200 && item.name != '我的' && item.name != 'AI赛场' && item.name != '学练赛评一体化平台' && item.name != '活跃度统计' && item.name != 'AI测试' && item.name != 'AI体适能训练系统' && item.name != '数据驾驶舱' && item.name != '考级测评' && item.name != '区域级看板' || keepNames.includes(item.name));
|
||
// 初始化顶部导航选中项
|
||
const topItems = menuOptions.value.filter(x => x.parentId == 0);
|
||
if (topItems.length > 0) {
|
||
activeTopMenuId.value = topItems[0].id;
|
||
}
|
||
permissionInited.value = true;
|
||
|
||
//开启消息推送(main.js中设置是否开启signalR)2022.05.05
|
||
if (_config.$global.signalR) {
|
||
MessageConfig(http, (result) => {
|
||
messageList.unshift(result);
|
||
});
|
||
}
|
||
//当前刷新是不是首页
|
||
if (router.currentRoute.value.path != navigation[0].path) {
|
||
//查找系统菜单
|
||
let item = menuOptions.value.find((x) => {
|
||
return x.path == router.currentRoute.value.path; //this.$route.path;
|
||
});
|
||
if (item) return onSelect(item.id);
|
||
//查找顶部快捷连接
|
||
item = links.value.find((x) => {
|
||
return x.path == router.currentRoute.value.path; //this.$route.path;
|
||
});
|
||
//查找最后一次跳转的页面
|
||
if (!item) {
|
||
item = getItem();
|
||
}
|
||
if (item) {
|
||
return open(item, false);
|
||
}
|
||
}
|
||
selectId.value = "1";
|
||
} else {
|
||
ElMessage.error('登录已过期,请重新登录')
|
||
router.push({ path: '/login' })
|
||
}
|
||
|
||
});
|
||
};
|
||
created();
|
||
return {
|
||
menuWidth,
|
||
isCollapse,
|
||
topNavMenusRef,
|
||
activeTopMenuId,
|
||
activeTopMenuHasChildren,
|
||
topLevelMenus,
|
||
selectTopMenu,
|
||
drawer_model,
|
||
theme_color,
|
||
errorImg,
|
||
userInfo,
|
||
userName,
|
||
userImg,
|
||
selectId,
|
||
selectMenuIndex,
|
||
navigation,
|
||
links,
|
||
onSelect,
|
||
openTabsMenu,
|
||
selectNav,
|
||
getSelectMenuName,
|
||
removeNav,
|
||
logo,
|
||
theme,
|
||
menuOptions,
|
||
permissionInited,
|
||
changeTheme,
|
||
to,
|
||
toggleLeft,
|
||
messageModel,
|
||
messageList,
|
||
contextMenuVisible,
|
||
visibleItem,
|
||
closeTabsMenu,
|
||
closeTabs,
|
||
currentMenuId,
|
||
};
|
||
},
|
||
/**
|
||
* 挂载钩子函数
|
||
*/
|
||
mounted() {
|
||
let _date = showTime();
|
||
this.bindRightClickMenu(true);
|
||
|
||
// 顶部导航栏:将鼠标竖向滚轮转换为横向滚动
|
||
const nav = this.topNavMenusRef;
|
||
if (nav) {
|
||
this._navWheelHandler = (e) => {
|
||
if (e.deltaY !== 0) {
|
||
e.preventDefault();
|
||
nav.scrollLeft += e.deltaY;
|
||
}
|
||
};
|
||
nav.addEventListener('wheel', this._navWheelHandler, { passive: false });
|
||
}
|
||
},
|
||
|
||
methods: {
|
||
/**
|
||
* 绑定右键事件
|
||
* @param {*} enable 是否启用右键事件[true:启用;false:禁用;]
|
||
* @param {*} $event 事件
|
||
*/
|
||
bindRightClickMenu(enable) {
|
||
if (!enable) return;
|
||
let that = this;
|
||
// 使用原生js 为单个dom绑定鼠标右击事件
|
||
that.$nextTick(() => {
|
||
let tab_top_dom = Object.assign(
|
||
[],
|
||
document.getElementsByClassName("el-tabs__item is-top")
|
||
);
|
||
tab_top_dom.forEach((item, index) => {
|
||
item.oncontextmenu = that.openTabsMenu;
|
||
});
|
||
});
|
||
},
|
||
},
|
||
|
||
/**
|
||
* 销毁钩子函数
|
||
*/
|
||
destroyed() {
|
||
$this = null;
|
||
clearInterval($interval);
|
||
if (this._navWheelHandler && this.topNavMenusRef) {
|
||
this.topNavMenusRef.removeEventListener('wheel', this._navWheelHandler);
|
||
}
|
||
},
|
||
});
|
||
const week = new Array(
|
||
"星期一",
|
||
"星期二",
|
||
"星期三",
|
||
"星期四",
|
||
"星期五",
|
||
"星期六",
|
||
"星期日"
|
||
);
|
||
function showTime() {
|
||
let date = new Date();
|
||
let year = date.getFullYear();
|
||
let month = date.getMonth() + 1;
|
||
let day = date.getDate();
|
||
let hour = date.getHours();
|
||
let minutes = date.getMinutes();
|
||
let second = date.getSeconds();
|
||
|
||
return (
|
||
year +
|
||
"." +
|
||
(month < 10 ? "0" + month : month) +
|
||
"." +
|
||
(day < 10 ? "0" + day : day) + //202.08.08修复日期天数小于10时添加0
|
||
"" +
|
||
" " +
|
||
(hour < 10 ? "0" + hour : hour) +
|
||
":" +
|
||
(minutes < 10 ? "0" + minutes : minutes) +
|
||
":" +
|
||
(second < 10 ? "0" + second : second) +
|
||
" " + //2020.08.30修复首页日期星期天不显示的问题
|
||
(week[date.getDay() - 1] || week[6])
|
||
);
|
||
}
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.vol-container .vol-path ::v-deep(.el-tabs__content) {
|
||
padding: 0;
|
||
// border-bottom: 1px solid #e4e4e7;
|
||
}
|
||
|
||
.contextMenu {
|
||
width: 130px;
|
||
margin: 0;
|
||
border: 1px solid #e8ecf2;
|
||
background: #fff;
|
||
z-index: 30000;
|
||
position: absolute;
|
||
list-style-type: none;
|
||
padding: 4px;
|
||
border-radius: 10px;
|
||
font-size: 13px;
|
||
color: #333;
|
||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.06);
|
||
|
||
i,
|
||
button {
|
||
font-size: 13px !important;
|
||
}
|
||
}
|
||
|
||
.contextMenu li {
|
||
margin: 0;
|
||
padding: 2px 4px;
|
||
}
|
||
|
||
.contextMenu li:hover {
|
||
background: #f0f7ff;
|
||
cursor: pointer;
|
||
border-radius: 6px;
|
||
}
|
||
|
||
.contextMenu li button {
|
||
color: #626060;
|
||
font-size: 14px;
|
||
letter-spacing: 1px;
|
||
}
|
||
|
||
.el-tabs.el-tabs--top.el-tabs--border-card.header-navigation>.el-tabs__header .el-tabs__item:last-child,
|
||
.el-tabs--top.el-tabs--border-card.header-navigation>.el-tabs__header .el-tabs__item:nth-child(2) {
|
||
padding: 0 12px !important;
|
||
}
|
||
|
||
.header-navigation ::v-deep(.el-tabs__item.is-top) {
|
||
padding: 0 12px !important;
|
||
}
|
||
</style>
|
||
<style>
|
||
.horizontal-collapse-transition {
|
||
transition: 0s width ease-in-out, 0s padding-left ease-in-out,
|
||
0s padding-right ease-in-out;
|
||
}
|
||
|
||
/* ── 溢出导航下拉面板(Teleport 到 body,需全局样式) ── */
|
||
.top-nav-overflow-panel {
|
||
min-width: 160px;
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
box-shadow: 0 10px 32px rgba(0, 0, 0, 0.14), 0 2px 8px rgba(0, 0, 0, 0.06);
|
||
padding: 5px;
|
||
border: 1px solid rgba(0, 0, 0, 0.06);
|
||
}
|
||
.top-nav-overflow-item {
|
||
padding: 9px 14px;
|
||
cursor: pointer;
|
||
border-radius: 8px;
|
||
color: #333;
|
||
font-size: 14px;
|
||
transition: all 0.18s;
|
||
white-space: nowrap;
|
||
}
|
||
.top-nav-overflow-item:hover {
|
||
background: #f0f7ff;
|
||
color: #2d8cf0;
|
||
}
|
||
.top-nav-overflow-item.is-active {
|
||
color: #2d8cf0;
|
||
font-weight: 600;
|
||
background: #e8f4ff;
|
||
}
|
||
.top-nav-more-fade-enter-active,
|
||
.top-nav-more-fade-leave-active {
|
||
transition: opacity 0.2s ease, transform 0.2s ease;
|
||
}
|
||
.top-nav-more-fade-enter-from,
|
||
.top-nav-more-fade-leave-to {
|
||
opacity: 0;
|
||
transform: translateY(-8px);
|
||
}
|
||
|
||
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item .is-icon-close{
|
||
margin-left: 8px;
|
||
color: #000;
|
||
}
|
||
|
||
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item .is-icon-close:hover{
|
||
color: #fff;
|
||
}
|
||
|
||
/* ── 标签栏 Chrome 风格激活色(全局高优先级,压过 EP border-card 内置样式) ── */
|
||
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item {
|
||
color: #5f6368;
|
||
background: transparent;
|
||
border: none !important;
|
||
border-radius: 8px 8px 0 0 !important;
|
||
overflow: visible !important;
|
||
}
|
||
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
|
||
color: #2d8cf0 !important;
|
||
background: linear-gradient(90deg, #dbeeff 0%, #f0f8ff 100%) !important;
|
||
font-weight: normal;
|
||
border: none !important;
|
||
}
|
||
.header-navigation.el-tabs--border-card > .el-tabs__header .el-tabs__item:not(.is-active):hover {
|
||
color: #2d8cf0 !important;
|
||
background: #ebf4ff !important;
|
||
border-radius: 8px !important;
|
||
}
|
||
.header-navigation.el-tabs--border-card > .el-tabs__header {
|
||
background: #fff;
|
||
border-bottom: none;
|
||
}
|
||
</style>
|