|
@@ -0,0 +1,214 @@
|
|
|
+<template>
|
|
|
+ <div :class="['container', { 'scrolled': isScrolled }]"
|
|
|
+ :style="{ backgroundColor: headerBackgroundColor, color: fontColor }">
|
|
|
+ <div class="header">
|
|
|
+ <div class="left">
|
|
|
+ <img alt="Double_X 考勤" src="/icon.png" @click="$router.push('/')">
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="right">
|
|
|
+ <button class="menu-toggle" @click="toggleMenu">
|
|
|
+ <el-icon :size="30">
|
|
|
+ <Menu />
|
|
|
+ </el-icon>
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <div class="menu-container" :class="{ 'show-menu': isMenuOpen }">
|
|
|
+ <div class="item" @click="$router.push('/')">
|
|
|
+ <el-icon>
|
|
|
+ <House />
|
|
|
+ </el-icon>
|
|
|
+ 首页
|
|
|
+ </div>
|
|
|
+ <div class="item" @click="$router.push('/ClockIn')">
|
|
|
+ <el-icon>
|
|
|
+ <Edit />
|
|
|
+ </el-icon>
|
|
|
+ 我的考勤
|
|
|
+ </div>
|
|
|
+ <div class="item" @click="$router.push('/MyOrder')">
|
|
|
+ <el-icon>
|
|
|
+ <Postcard />
|
|
|
+ </el-icon>
|
|
|
+ 补卡申请
|
|
|
+ </div>
|
|
|
+ <div class="item" v-if="app.user === undefined" @click="$router.push('/login')">
|
|
|
+ <el-icon>
|
|
|
+ <User />
|
|
|
+ </el-icon>
|
|
|
+ 用户登录
|
|
|
+ </div>
|
|
|
+ <div class="user" v-else @click="$router.push('/Mine')">
|
|
|
+ <el-avatar :src="app.user.avatar" v-if="app.user.avatar" :size="25" />
|
|
|
+ <div class="item">
|
|
|
+ {{ app.user.username }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { App } from '../app/app';
|
|
|
+import { ServerAPI } from '../app/lib/ServerAPI';
|
|
|
+import { useRouter} from 'vue-router';
|
|
|
+
|
|
|
+const app = reactive(App);
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+const props = defineProps({
|
|
|
+ color: {
|
|
|
+ type: String,
|
|
|
+ default: 'black'
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const isMenuOpen = ref(false);
|
|
|
+const isScrolled = ref(false);
|
|
|
+const headerBackgroundColor = ref('rgba(255, 255, 255, 0)');
|
|
|
+const fontColor = ref(props.color);
|
|
|
+
|
|
|
+function toggleMenu() {
|
|
|
+ isMenuOpen.value = !isMenuOpen.value;
|
|
|
+}
|
|
|
+
|
|
|
+function handleScroll() {
|
|
|
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
|
+ const maxScroll = 200; // 最大滚动距离
|
|
|
+ const opacity = Math.min(scrollTop / maxScroll, 1);
|
|
|
+ headerBackgroundColor.value = `rgba(255, 255, 255, ${opacity})`;
|
|
|
+ isScrolled.value = scrollTop > 0;
|
|
|
+ if (opacity > 0) {
|
|
|
+ fontColor.value = 'black';
|
|
|
+ } else {
|
|
|
+ fontColor.value = props.color;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ window.addEventListener('scroll', handleScroll);
|
|
|
+});
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ window.removeEventListener('scroll', handleScroll);
|
|
|
+});
|
|
|
+
|
|
|
+//修复登录过期问题
|
|
|
+const user = app.user;
|
|
|
+if (user != undefined) {
|
|
|
+ ServerAPI.checkLoginSession(user.uuid, user.session, (r) => {
|
|
|
+ if (r.code == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //自动退出登录
|
|
|
+ ElMessage.error('登录已过期,请重新登录');
|
|
|
+ app.cleanUser();
|
|
|
+ router.push('/login');
|
|
|
+ })
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.container {
|
|
|
+ position: sticky;
|
|
|
+ top: 0;
|
|
|
+ width: 100%;
|
|
|
+ z-index: 100;
|
|
|
+}
|
|
|
+
|
|
|
+.header {
|
|
|
+ width: 80%;
|
|
|
+ margin: 0 auto;
|
|
|
+ border: none !important;
|
|
|
+ z-index: 1000;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 10px 20px;
|
|
|
+ transition: background-color 0.3s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.header.scrolled {
|
|
|
+ backdrop-filter: blur(10px);
|
|
|
+ /* 添加模糊效果 */
|
|
|
+}
|
|
|
+
|
|
|
+.header .left img {
|
|
|
+ width: 60px;
|
|
|
+}
|
|
|
+
|
|
|
+.header .right {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.header .right .menu-toggle {
|
|
|
+ display: none;
|
|
|
+ /* 默认隐藏按钮 */
|
|
|
+ cursor: pointer;
|
|
|
+ background: none;
|
|
|
+ border: none;
|
|
|
+ font-size: 1.4em;
|
|
|
+}
|
|
|
+
|
|
|
+.header .right .menu-container {
|
|
|
+ display: flex;
|
|
|
+ gap: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.header .right .item {
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 1.2em;
|
|
|
+}
|
|
|
+
|
|
|
+.header .right .user {
|
|
|
+ display: flex;
|
|
|
+}
|
|
|
+
|
|
|
+.header .right .user .item {
|
|
|
+ margin-left: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.header .right .item:hover {
|
|
|
+ color: #337ecc;
|
|
|
+}
|
|
|
+
|
|
|
+@media only screen and (max-width: 768px) {
|
|
|
+ .header {
|
|
|
+ width: 90%;
|
|
|
+ height: 40px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .header .left img {
|
|
|
+ width: 50px
|
|
|
+ }
|
|
|
+
|
|
|
+ .header .right .menu-toggle {
|
|
|
+ display: block;
|
|
|
+ /* 在小屏幕下显示按钮 */
|
|
|
+ }
|
|
|
+
|
|
|
+ .header .right .menu-container {
|
|
|
+ display: none;
|
|
|
+ flex-direction: column;
|
|
|
+ position: absolute;
|
|
|
+ top: 100%;
|
|
|
+ right: 10px;
|
|
|
+ background-color: rgba(0, 0, 0, 0.5);
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 5px;
|
|
|
+ padding: 10px;
|
|
|
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
|
|
+ z-index: 999;
|
|
|
+ font-size: 0.8em;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .header .right .menu-container.show-menu {
|
|
|
+ display: flex;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|