vue3+ts(<script setup lang=“ts“>)刷新页面后保持下拉框选中效果

效果图:

代码:

<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>
相关推荐
逐·風2 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫3 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦3 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子4 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山4 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享5 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果5 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄5 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
凉辰6 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
清灵xmf7 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询