效果图:
代码:
<template><div class="app-layout"><div class="app-box"><div class="header"><div class="header-left"></div><div class="title">室外智能健身房数据中心</div><div class="header-right"><p class="p2"><i class="iconfont icon-home_icon_position"></i>{{ curInfo.siteName }}<div class="dropdown-box"><imgsrc="~@/assets/images/icon/drop_down.png"@click="isOpen = !isOpen"alt=""/><div class="dropdown-cont"><transition name="fade"><div v-if="isOpen" class="dropdown"><div class="dropdown-item" :class="{activeMenu:index === menuIdx}" v-for="(item,index) in menuList" :key="index" @click="changeMenu(index,item.path)">{{ item.name }}</div></div></transition></div></div></p></div></div><div class="main-container"><router-view></router-view></div></div></div>
</template><script setup lang="ts">
import { reactive, onUnmounted,onMounted, ref } from "vue";
import * as dayjs from "dayjs";
import { getUrlKey } from "@/utils";
import axios from "axios";
import { useRouter,useRoute } from "vue-router";
const router = useRouter();
const route = useRoute();
const menuList = [{ name: '首页', path: '/chartApp/home' },{ name: '查看运动记录', path: '/chartApp/sportsList' },{ name: '用户管理', path: '/chartApp/userList' },
]
const menuIdx = ref(0);
let curInfo = reactive({deviceNo: "",time: "2023-00-00 00:00:00",// 天气weather: "",temperature: "",// 空气质量aqi: "",category: "",weekday: "",siteName: "中国航发北京航空材料研究院",cityName: "",
});
const isOpen = ref(false);//下拉框
let curTimer = null;
const getCurTime = () => {curTimer = setTimeout(() => {curInfo.time = dayjs().format("YYYY-MM-DD HH:mm:ss");getCurTime();}, 1000);
};const wKEY = "ef38ffd9e9804ae77f5f9342ca2c3975";
let weatherTimer = null;
const getWeather = (adcode: string) => {axios.get(`https://restapi.amap.com/v3/weather/weatherInfo?key=${wKEY}&city=${adcode}`).then((res3) => {let resultTq = res3.data;if (resultTq.lives[0].weather) {curInfo.weather = resultTq.lives[0].weather;curInfo.temperature = resultTq.lives[0].temperature;}});weatherTimer = setTimeout(() => {getWeather(adcode);}, 1000 * 60 * 15);
};
// 获取天气
const getWeatherData = () => {axios.get(`https://restapi.amap.com/v3/config/district?keywords=${curInfo.cityName}&key=${wKEY}`).then((res) => {let result = res.data;if (result?.districts[0].adcode) {// 此处需轮询 每15分钟获取一次getWeather(result?.districts[0].adcode);}});
};
// 获取天气质量
const getCategoryData = () => {const KEY = "a815396d62d043a2bd19395d35997d49";axios.get(`https://geoapi.qweather.com/v2/city/lookup?location=${curInfo.cityName}&key=${KEY}&number=1`).then((res) => {let result = res.data;if (result?.location[0].id) {// 当天获取一次axios.get(`https://devapi.qweather.com/v7/air/now?key=${KEY}&location=${result?.location[0].id}`).then((res3) => {let resultObj = res3.data?.now;curInfo.aqi = resultObj.aqi;curInfo.category = resultObj.category;});}});
};
// 查看运动记录
const changeMenu = (index, path) => {menuIdx.value = index;router.push(path);isOpen.value = false;
}const initLayout = () => {// 优点取url 设备号if (getUrlKey("dNo")) {localStorage.setItem("DEVICE_NO",JSON.stringify({devNo: getUrlKey("dNo"),}));}curInfo.deviceNo = JSON.parse(localStorage.getItem("DEVICE_NO"))?.devNo;getCurTime();
};
initLayout();
onMounted(() => {// 刷新页面保持下拉框选择效果switch (route.name) {case "home":menuIdx.value = 0;break;case "userList":menuIdx.value = 2;break;case "sportsList":menuIdx.value = 1;break;default:menuIdx.value = 0;break;}
});
// 销毁
onUnmounted(() => {clearTimeout(curTimer);clearTimeout(weatherTimer);curTimer = null;weatherTimer = null;
});
</script>
<style lang="scss" scoped>
.app-layout {position: relative;padding: 30px;width: 100vw;min-height: 100vh;overflow: hidden;background: url("@/assets/images/back/them_bg.png") no-repeat;background-size: 100% 100%;color: #d3ffff;font-family: PingFang SC, PingFang SC-Medium;scrollbar-width: none; height: 0;overflow-y: scroll;
}
.app-layout::-webkit-scrollbar {/*滚动条整体样式*/width: 0 !important;}.app-layout::-webkit-scrollbar-thumb {/*滚动条里面小方块*/width: 0 !important;}
.app-box {width: 100%;height: auto;border: 1px solid #005989;border-radius: 30px;box-shadow: 0px 0px 8px 0px #004789 inset;
}
.header {display: flex;width: 100%;height: 86px;background: url("@/assets/images/back/heard.png") no-repeat;background-size: 100% 100%;.title {padding-bottom: 20px;display: flex;justify-content: center;align-items: center;width: 550px;height: 100%;font-family: PingFang SC, PingFang SC-Bold;font-size: 30px;font-weight: 700;text-align: CENTER;line-height: 42px;letter-spacing: 6px;}.header-left,.header-right {padding: 20px 0 10px 0;width: 655px;height: 100%;display: flex;align-items: center;justify-content: center;}.header-left {.p1 {margin-bottom: 6px;padding-left: 124px;font-size: 18px;}.p2 {text-align: right;padding-right: 30px;font-size: 20px;.tq-one {margin-right: 24px;}.iconfont {margin: 0 3px;font-size: 22px;}}}.score {display: inline-block;vertical-align: top;margin-top: 1px;margin-left: 8px;padding: 2px 4px;font-size: 15px;color: #ffffff;border-radius: 2px;}.bg-color1 {background: #29cd94;}.bg-color2 {background: #f7d631;}.bg-color3 {background: #ff9933;}.bg-color4 {background: #ff2626;}.bg-color5 {background: #b133ff;}.bg-color6 {background: #b21b1b;}.header-right {.p1 {margin-bottom: 6px;text-align: right;padding-right: 124px;font-size: 14px;span {padding: 2px 10px;background: rgba(112, 217, 250, 0.1);border: 1px solid rgba(77, 243, 243, 0.3);border-radius: 12px;box-shadow: 0px 0px 8px 0px #004789 inset;}}.p2 {display: flex;align-items: center;font-size: 18px;.dropdown-box{display: flex;flex-direction: column;align-items: flex-start;justify-content: flex-start;margin-left: 30px;position: relative;.dropdown-cont{position: absolute;left: 0;top: 0.14rem;z-index: 9999;}.dropdown{white-space: nowrap;background: rgba(18,60,92,0.60);border: 1px solid #005989;box-shadow: 0px 0px 8px 0px #004789 inset; padding: 0.08rem 0.1rem;font-size: 0.0938rem;.dropdown-item{cursor: pointer;}.dropdown-item:not(:last-child){margin-bottom: 0.06rem;}.activeMenu{color: rgb(53, 204, 151);font-weight: 700;}}}.iconfont {font-size: 20px;margin-right: 10px;}img {width: 20px;height: 20px;cursor: pointer;}}}
}
.main-container {position: relative;padding: 30px;width: 100%;box-sizing: border-box;
}
</style>