效果图:
代码:
<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">
<img
src="~@/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>