导航栏/菜单栏显示逻辑修改

This commit is contained in:
zhujiyan
2024-08-23 13:19:20 +08:00
parent 976a7708cd
commit d0aaa24f90
17 changed files with 4751 additions and 44 deletions

View File

@@ -0,0 +1,8 @@
import http from "@/api";
export const getStaticTreeData = (data: any) => {
return http.post<Static.planData>(
"http://127.0.0.1:4523/m1/2573730-0-default/plan/static/planData",
data,
{ loading: false }
); // 正常 post json 请求 ==> application/json
};

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="246px" height="246px" viewBox="0 0 246 246" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Illustration/数据</title>
<defs>
<filter x="-36.7%" y="-46.4%" width="173.4%" height="192.7%" filterUnits="objectBoundingBox" id="filter-1">
<feGaussianBlur stdDeviation="17" in="SourceGraphic"></feGaussianBlur>
</filter>
<filter x="-187.5%" y="-187.5%" width="475.0%" height="475.0%" filterUnits="objectBoundingBox" id="filter-2">
<feGaussianBlur stdDeviation="10" in="SourceGraphic"></feGaussianBlur>
</filter>
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-3">
<stop stop-color="#92B7FF" offset="0%"></stop>
<stop stop-color="#ECE1F7" stop-opacity="0" offset="100%"></stop>
</linearGradient>
</defs>
<g id="Illustration/数据" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="数据">
<rect id="矩形备份-27" fill-opacity="0" fill="#D8D8D8" x="0" y="0" width="246" height="246"></rect>
<g id="img_yinliuillustration" transform="translate(17.000000, 17.000000)">
<rect id="矩形备份-15" fill-opacity="0" fill="#D8D8D8" x="0" y="0" width="212" height="212"></rect>
<g id="编组-18" transform="translate(1.000000, 4.000000)">
<circle id="椭圆形" fill="#E1E8F1" opacity="0.400000006" cx="113" cy="99" r="97"></circle>
<g id="编组-16">
<path d="M199.564662,169.0012 L30.4350385,169.0012 C26.8806694,169.0012 23.99985,165.163314 23.99985,160.431302 L23.99985,33.5710982 C23.99985,28.8376578 26.8806694,25.0012 30.4350385,25.0012 L199.564662,25.0012 C203.119031,25.0012 205.99985,28.8376578 205.99985,33.5710982 L205.99985,160.431302 C205.99985,165.163314 203.119031,169.0012 199.564662,169.0012" id="Fill-13" fill="#CED7E2"></path>
<path d="M179.59797,176 L50.4017301,176 C47.686587,176 45.4859611,173.068281 45.4859611,169.45355 L45.4859611,72.54645 C45.4859611,68.9306275 47.686587,66 50.4017301,66 L179.59797,66 C182.313113,66 184.513739,68.9306275 184.513739,72.54645 L184.513739,169.45355 C184.513739,173.068281 182.313113,176 179.59797,176" id="Fill-13" fill="#CED7E2" filter="url(#filter-1)"></path>
<path d="M193.98896,162.0012 L36.0107403,162.0012 C32.6907252,162.0012 29.99985,158.536442 29.99985,154.264486 L29.99985,39.7379137 C29.99985,35.4646688 32.6907252,32.0012 36.0107403,32.0012 L193.98896,32.0012 C197.308975,32.0012 199.99985,35.4646688 199.99985,39.7379137 L199.99985,154.264486 C199.99985,158.536442 197.308975,162.0012 193.98896,162.0012" id="Fill-13" fill="#FCFFFF"></path>
<path d="M181.08535,46.1782 L168.01735,46.1782 C165.80835,46.1782 164.01735,44.3882 164.01735,42.1782 L164.01735,29.1112 C164.01735,26.9022 165.80835,25.1112 168.01735,25.1112 L181.08535,25.1112 C183.29435,25.1112 185.08535,26.9022 185.08535,29.1112 L185.08535,42.1782 C185.08535,44.3882 183.29435,46.1782 181.08535,46.1782" id="Fill-27" fill="#2DC8CE"></path>
<path d="M179.513803,48.5335 L169.588897,48.5335 C167.911202,48.5335 166.55097,47.1740278 166.55097,45.4955734 L166.55097,35.5714266 C166.55097,33.8937316 167.911202,32.5335 169.588897,32.5335 L179.513803,32.5335 C181.191498,32.5335 182.55173,33.8937316 182.55173,35.5714266 L182.55173,45.4955734 C182.55173,47.1740278 181.191498,48.5335 179.513803,48.5335" id="Fill-27" fill="#2DC8CE" opacity="0.300000012" filter="url(#filter-2)"></path>
<path d="M175.23385,31.9732 L177.51085,33.3522 L175.73285,35.8302 L171.95985,34.6232 L166.73585,39.7782 C166.34185,40.1662 166.33885,40.7992 166.72685,41.1922 L166.72685,41.1922 C166.92185,41.3902 167.17985,41.4902 167.43885,41.4902 L167.43885,41.4902 C167.69185,41.4902 167.94585,41.3942 168.14185,41.2022 L168.14185,41.2022 L172.50285,36.8962 L176.50985,38.1772 L179.22585,34.3912 L181.39085,35.7032 L180.75985,29.7992 L175.23385,31.9732 Z" id="Fill-29" fill="#FCFFFF"></path>
<path d="M186.81635,17.893 L186.00635,15.702 C184.98935,12.946 182.81735,10.774 180.06235,9.756 L177.87035,8.947 L180.06235,8.137 C182.81735,7.12 184.98935,4.948 186.00635,2.193 L186.81635,1.42108547e-14 L187.62635,2.193 C188.64335,4.948 190.81535,7.12 193.57035,8.137 L195.76235,8.947 L193.57035,9.756 C190.81535,10.774 188.64335,12.946 187.62635,15.702 L186.81635,17.893 Z" id="Fill-31" fill="#B5E0FC"></path>
<path d="M67.16935,196.2299 C67.16935,200.6839 63.55935,204.2939 59.10535,204.2939 C54.65135,204.2939 51.04135,200.6839 51.04135,196.2299 C51.04135,191.7769 54.65135,188.1669 59.10535,188.1669 C63.55935,188.1669 67.16935,191.7769 67.16935,196.2299 Z" id="Stroke-33" stroke="#B5E0FC" stroke-width="2"></path>
<rect id="矩形" fill="#E3EBF3" x="40.99985" y="122.0012" width="4" height="29" rx="2"></rect>
<rect id="矩形备份-10" fill="#E3EBF3" x="178.99985" y="67.0012" width="4" height="84" rx="2"></rect>
<rect id="矩形备份-11" fill="#E3EBF3" x="163.99985" y="86.0012" width="4" height="65" rx="2"></rect>
<rect id="矩形备份-23" fill="#E3EBF3" x="147.99985" y="80.0012" width="4" height="71" rx="2"></rect>
<rect id="矩形备份-18" fill="#E3EBF3" x="132.99985" y="97.0012" width="4" height="54" rx="2"></rect>
<rect id="矩形备份-19" fill="#E3EBF3" x="117.99985" y="92.0012" width="4" height="59" rx="2"></rect>
<rect id="矩形备份-20" fill="#E3EBF3" x="101.99985" y="110.0012" width="4" height="41" rx="2"></rect>
<rect id="矩形备份-21" fill="#E3EBF3" x="86.99985" y="102.0012" width="4" height="49" rx="2"></rect>
<rect id="矩形备份-22" fill="#E3EBF3" x="71.99985" y="118.0012" width="4" height="33" rx="2"></rect>
<rect id="矩形备份-24" fill="#E3EBF3" x="55.99985" y="113.0012" width="4" height="38" rx="2"></rect>
<polygon id="路径-12" fill="url(#linearGradient-3)" points="40.99985 126.5012 57.99985 117.0012 73.99985 122.0012 88.99985 106.0012 103.99985 114.0012 119.99985 96.0012 134.99985 101.0012 149.99985 84.0012 165.99985 90.0012 182.99985 68.1758341 182.99985 151.0012 40.99985 151.0012"></polygon>
<circle id="椭圆形" fill="#1B68FF" cx="42.99985" cy="126.0012" r="4"></circle>
<circle id="椭圆形备份-104" fill="#1B68FF" cx="57.99985" cy="117.0012" r="4"></circle>
<circle id="椭圆形备份-105" fill="#1B68FF" cx="73.99985" cy="122.0012" r="4"></circle>
<circle id="椭圆形备份-106" fill="#1B68FF" cx="88.99985" cy="106.0012" r="4"></circle>
<circle id="椭圆形备份-107" fill="#1B68FF" cx="103.99985" cy="114.0012" r="4"></circle>
<circle id="椭圆形备份-108" fill="#1B68FF" cx="119.99985" cy="96.0012" r="4"></circle>
<circle id="椭圆形备份-109" fill="#1B68FF" cx="134.99985" cy="101.0012" r="4"></circle>
<circle id="椭圆形备份-110" fill="#1B68FF" cx="149.99985" cy="84.0012" r="4"></circle>
<circle id="椭圆形备份-111" fill="#1B68FF" cx="165.99985" cy="90.0012" r="4"></circle>
<circle id="椭圆形备份-112" fill="#1B68FF" cx="180.99985" cy="71.0012" r="4"></circle>
<polyline id="路径-12" stroke="#1B68FF" stroke-width="2" points="42.99985 126.5012 57.99985 117.0012 73.99985 122.0012 88.99985 106.0012 103.99985 114.0012 119.99985 96.0012 134.99985 101.0012 149.99985 84.0012 165.99985 90.0012 180.99985 71.0012"></polyline>
<path d="M9.69525,105.5121 L5.70125,109.5061 C5.31025,109.8971 4.67725,109.8971 4.28725,109.5061 L0.29325,105.5121 C-0.09775,105.1221 -0.09775,104.4891 0.29325,104.0981 L4.28725,100.1041 C4.67725,99.7131 5.31025,99.7131 5.70125,100.1041 L9.69525,104.0981 C10.08525,104.4891 10.08525,105.1221 9.69525,105.5121" id="Fill-9" fill="#BBD9FA"></path>
<path d="M25.66595,127.7612 L17.92695,135.4992 C17.53695,135.8902 16.90295,135.8902 16.51295,135.4992 L8.77395,127.7612 C8.38295,127.3702 8.38295,126.7372 8.77395,126.3462 L16.51295,118.6082 C16.90295,118.2172 17.53695,118.2172 17.92695,118.6082 L25.66595,126.3462 C26.05595,126.7372 26.05595,127.3702 25.66595,127.7612" id="Fill-11" fill="#FFBBD8"></path>
</g>
<circle id="椭圆形" stroke="#E6EDF5" stroke-width="4" cx="52.5" cy="55.5" r="8.5"></circle>
<circle id="椭圆形备份-113" stroke="#E6EDF5" stroke-width="4" cx="81.5" cy="55.5" r="8.5"></circle>
<circle id="椭圆形备份-114" stroke="#E6EDF5" stroke-width="4" cx="110.5" cy="55.5" r="8.5"></circle>
<path d="M115.711018,48.7841963 C114.271866,47.665895 112.463697,47 110.5,47 C105.80558,47 102,50.8055796 102,55.5 C102,60.1944204 105.80558,64 110.5,64 C115.19442,64 119,60.1944204 119,55.5" id="路径" stroke="#1A66FF" stroke-width="4" stroke-linecap="round"></path>
<path d="M55.3933785,47.5688975 C54.4568789,47.201476 53.4390082,47 52.3747736,47 C47.7495139,47 44,50.8055796 44,55.5 C44,60.1944204 47.7495139,64 52.3747736,64 C55.7630749,64 58.6814065,61.9577326 60,59.0198593" id="路径" stroke="#1A66FF" stroke-width="4" stroke-linecap="round"></path>
<path d="M73,55.5 C73,60.1944204 76.7495139,64 81.3747736,64 C83.0980037,64 84.6996733,63.4717554 86.0311639,62.5661069" id="路径" stroke="#1A66FF" stroke-width="4" stroke-linecap="round"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.8 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 81 KiB

View File

@@ -0,0 +1,109 @@
<!-- 默认饼图 -->
<template>
<div class="charts" ref="chartsRef"></div>
</template>
<script lang="ts" setup>
import { ref, onMounted, defineProps, defineExpose, watch } from "vue";
import * as echarts from "echarts";
const chartsRef = ref();
const props = defineProps({
//饼图数据
chartsData: {
type: Array,
default: () => [],
},
//自定义数据
customData: {
type: Object,
default: () => ({}),
},
//legend配置
legendData: {
type: Object,
default: () => ({}),
},
});
const customData: any = ref({}),
legendData: any = ref({});
const init = () => {
console.log("init", props.customData);
customData.value = {
title: "", //标题
textAlign: "left", //标题位置可选属性left 可选属性值 left,right,center
ratio: true, //是否显示数值占比,默认不显示
isRing: false, //是否环形图
isRadius: false, //是否圆角
isSpace: true, //是否显示间隔
isLabelLine: true, //是否显示引导线
...props.customData,
};
legendData.value = {
icon: "roundRect", // 图例项的icon,类型包括 circle(圆形),rect(正方形),//roundRect(圆角正方形),triangle(三角形),diamond(菱形),//pin(大头针行),arrow(箭头形),none(无图例项的icon)
orient: "vertical", //图例排列方向
left: "right", //可选属性left,right,top,bottom,可选属性值 left,right,top,bottom,px,百分比,数值,
...props.legendData,
};
var chart = chartsRef.value && echarts.init(chartsRef.value);
var option = {
title: {
text: customData.value.title,
left: customData.value.textAlign,
},
legend: legendData.value,
tooltip: {
show: true,
trigger: "item",
formatter: customData.value.ratio ? `{b} : {c} ({d}%)` : "{b} :{c} ",
borderWidth: 1,
},
series: [
{
type: "pie",
radius: customData.value.isRing ? ["45", "65"] : "65%",
data: props.chartsData,
center: ["50%", "60%"], // 设置饼图的中心位置
// padAngle: 2,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
itemStyle: {
borderRadius: customData.value.isRadius ? 10 : 0,
borderColor: customData.value.isSpace ? "#fff" : "",
borderWidth: customData.value.isSpace ? 2 : 0,
},
labelLine: {
show: customData.value.isLabelLine,
},
},
],
};
option && chart.setOption(option);
};
watch(
() => props.chartsData,
(val, oldVal) => {
if (val) {
init();
}
},
{
deep: true,
}
);
onMounted(() => {
init();
});
defineExpose({ init });
</script>
<style lang="scss" scoped>
.charts {
width: 100%;
height: 100%;
padding: 10px;
}
</style>

View File

@@ -11,7 +11,7 @@
/>
<span class="logo-text">{{ title }}</span>
</div>
<el-menu trigger="click" mode="horizontal" :router="false" :default-active="activeMenu">
<el-menu v-if="showMenuFlag" trigger="click" mode="horizontal" :router="false" :default-active="activeMenu">
<!-- 不能直接使用 SubMenu 组件无法触发 el-menu 隐藏省略功能 -->
<template v-for="subItem in menuList" :key="subItem.path">
<el-sub-menu
@@ -62,6 +62,7 @@ const route = useRoute();
const router = useRouter();
const authStore = useAuthStore();
const menuList = computed(() => authStore.showMenuListGet);
const showMenuFlag=computed(()=>authStore.showMenuFlagGet)
const activeMenu = computed(
() => (route.meta.activeMenu ? route.meta.activeMenu : route.path) as string
);

View File

@@ -1,6 +1,6 @@
<template>
<el-dropdown trigger="click">
<div class="userInfo">
<div class="userInfo">
<div class="icon">
<Icon><Avatar /></Icon>
</div>
@@ -16,7 +16,7 @@
<el-dropdown-item @click="openDialog('passwordRef')">
<el-icon><Edit /></el-icon>{{ $t("header.changePassword") }}
</el-dropdown-item>
<el-dropdown-item @click="openDialog('passwordRef')">
<el-dropdown-item @click="changeMode">
<el-icon><Edit /></el-icon>{{ $t("header.changeMode") }}
</el-dropdown-item>
</el-dropdown-menu>
@@ -48,10 +48,11 @@ import SearchMenu from "./components/SearchMenu.vue";
import ThemeSetting from "./components/ThemeSetting.vue";
import Message from "./components/Message.vue";
import Fullscreen from "./components/Fullscreen.vue";
import { useAuthStore } from "@/stores/modules/auth";
const userStore = useUserStore();
const username = computed(() => userStore.userInfo.name);
const router = useRouter();
const authStore = useAuthStore();
// 退出登录
const logout = () => {
ElMessageBox.confirm("您是否确认退出登录?", "温馨提示", {
@@ -61,12 +62,12 @@ const logout = () => {
}).then(async () => {
// 1.执行退出登录接口
await logoutApi();
// 2.清除 Token
userStore.setToken("");
// 3.重定向到登陆页
router.replace(LOGIN_URL);
//重置菜单/导航栏权限
authStore.resetAuthStore();
ElMessage.success("退出登录成功!");
});
};
@@ -78,6 +79,10 @@ const openDialog = (ref: string) => {
if (ref == "infoRef") infoRef.value?.openDialog();
if (ref == "passwordRef") passwordRef.value?.openDialog();
};
//模式切换
const changeMode = () => {
authStore.changeModel();
};
</script>
<style scoped lang="scss">

View File

@@ -1,11 +1,15 @@
<template>
<Maximize v-show="maximize" />
<Tabs v-show="tabs" />
<Tabs v-if="tabs && showMenuFlag" />
<el-main>
<router-view v-slot="{ Component, route }">
<transition appear name="fade-transform" mode="out-in">
<keep-alive :include="keepAliveName">
<component :is="Component" v-if="isRouterShow" :key="route.fullPath" />
<component
:is="Component"
v-if="isRouterShow"
:key="route.fullPath"
/>
</keep-alive>
</transition>
</router-view>
@@ -16,7 +20,7 @@
</template>
<script setup lang="ts">
import { ref, onBeforeUnmount, provide, watch } from "vue";
import { ref, onBeforeUnmount, provide, watch, computed } from "vue";
import { storeToRefs } from "pinia";
import { useDebounceFn } from "@vueuse/core";
import { useGlobalStore } from "@/stores/modules/global";
@@ -24,13 +28,15 @@ import { useKeepAliveStore } from "@/stores/modules/keepAlive";
import Maximize from "./components/Maximize.vue";
import Tabs from "@/layouts/components/Tabs/index.vue";
import Footer from "@/layouts/components/Footer/index.vue";
import { useAuthStore } from "@/stores/modules/auth";
const globalStore = useGlobalStore();
const authStore = useAuthStore();
const { maximize, isCollapse, layout, tabs, footer } = storeToRefs(globalStore);
const keepAliveStore = useKeepAliveStore();
const { keepAliveName } = storeToRefs(keepAliveStore);
//是否显示导航栏
const showMenuFlag = computed(() => authStore.showMenuFlagGet);
// 注入刷新页面方法
const isRouterShow = ref(true);
const refreshCurrentPage = (val: boolean) => (isRouterShow.value = val);
@@ -61,8 +67,10 @@ watch(
const screenWidth = ref(0);
const listeningWindow = useDebounceFn(() => {
screenWidth.value = document.body.clientWidth;
if (!isCollapse.value && screenWidth.value < 1200) globalStore.setGlobalState("isCollapse", true);
if (isCollapse.value && screenWidth.value > 1200) globalStore.setGlobalState("isCollapse", false);
if (!isCollapse.value && screenWidth.value < 1200)
globalStore.setGlobalState("isCollapse", true);
if (isCollapse.value && screenWidth.value > 1200)
globalStore.setGlobalState("isCollapse", false);
}, 100);
window.addEventListener("resize", listeningWindow, false);
onBeforeUnmount(() => {

View File

@@ -1,8 +1,12 @@
import {defineStore} from "pinia";
import {AuthState} from "@/stores/interface";
import {getAuthButtonListApi, getAuthMenuListApi} from "@/api/modules/login";
import {getFlatMenuList, getShowMenuList, getAllBreadcrumbList} from "@/utils";
import {AUTH_STORE_KEY} from "@/stores/constant";
import { defineStore } from "pinia";
import { AuthState } from "@/stores/interface";
import { getAuthButtonListApi, getAuthMenuListApi } from "@/api/modules/login";
import {
getFlatMenuList,
getShowMenuList,
getAllBreadcrumbList,
} from "@/utils";
import { AUTH_STORE_KEY } from "@/stores/constant";
export const useAuthStore = defineStore({
id: AUTH_STORE_KEY,
@@ -12,34 +16,57 @@ export const useAuthStore = defineStore({
// 菜单权限列表
authMenuList: [],
// 当前页面的 router name用来做按钮权限筛选
routeName: ""
routeName: "",
//登录不显示菜单栏和导航栏,点击进入测试的时候显示
showMenuFlag: JSON.parse(localStorage.getItem("showMenuFlag")),
}),
getters: {
// 按钮权限列表
authButtonListGet: state => state.authButtonList,
authButtonListGet: (state) => state.authButtonList,
// 菜单权限列表 ==> 这里的菜单没有经过任何处理
authMenuListGet: state => state.authMenuList,
authMenuListGet: (state) => state.authMenuList,
// 菜单权限列表 ==> 左侧菜单栏渲染,需要剔除 isHide == true
showMenuListGet: state => getShowMenuList(state.authMenuList),
showMenuListGet: (state) => getShowMenuList(state.authMenuList),
// 菜单权限列表 ==> 扁平化之后的一维数组菜单,主要用来添加动态路由
flatMenuListGet: state => getFlatMenuList(state.authMenuList),
flatMenuListGet: (state) => getFlatMenuList(state.authMenuList),
// 递归处理后的所有面包屑导航列表
breadcrumbListGet: state => getAllBreadcrumbList(state.authMenuList)
breadcrumbListGet: (state) => getAllBreadcrumbList(state.authMenuList),
//是否显示菜单和导航栏
showMenuFlagGet: (state) => state.showMenuFlag,
},
actions: {
// Get AuthButtonList
async getAuthButtonList() {
const {data} = await getAuthButtonListApi();
const { data } = await getAuthButtonListApi();
this.authButtonList = data;
},
// Get AuthMenuList
async getAuthMenuList() {
const {data} = await getAuthMenuListApi();
const { data } = await getAuthMenuListApi();
this.authMenuList = data;
},
// Set RouteName
async setRouteName(name: string) {
this.routeName = name;
},
//重置权限
async resetAuthStore() {
this.showMenuFlag=false;
localStorage.removeItem("showMenuFlag");
},
//修改判断菜单栏/导航栏显示条件
async setShowMenu() {
this.showMenuFlag = true;
localStorage.setItem("showMenuFlag", true);
},
//更改模式
async changeModel(){
this.showMenuFlag=!this.showMenuFlag;
if(this.showMenuFlag){
localStorage.setItem("showMenuFlag", true);
}else{
localStorage.removeItem("showMenuFlag");
}
}
}
},
});

View File

@@ -1,13 +1,13 @@
import { defineStore } from "pinia";
import { UserState } from "@/stores/interface";
import piniaPersistConfig from "@/stores/helper/persist";
import {USER_STORE_KEY} from "@/stores/constant";
import { USER_STORE_KEY } from "@/stores/constant";
export const useUserStore = defineStore({
id: USER_STORE_KEY,
state: (): UserState => ({
token: "",
userInfo: { name: "admin" }
userInfo: { name: "admin" },
}),
getters: {},
actions: {
@@ -18,7 +18,7 @@ export const useUserStore = defineStore({
// Set setUserInfo
setUserInfo(userInfo: UserState["userInfo"]) {
this.userInfo = userInfo;
}
},
},
persist: piniaPersistConfig(USER_STORE_KEY)
persist: piniaPersistConfig(USER_STORE_KEY),
});

View File

@@ -0,0 +1,89 @@
<template>
<div class="table">
<el-table :data="tableData" stripe style="width: 100%; height: 100%">
<el-table-column fixed type="selection" width="55" />
<el-table-column align="center" prop="date" label="设备序列号" fixed />
<el-table-column
align="center"
prop="name"
label="设备类型"
/>
<el-table-column
align="center"
prop="state"
label="制造厂商"
/>
<el-table-column
align="center"
prop="address"
label="MAC/IP"
show-overflow-tooltip
/>
<!-- <el-table-column align="center" fixed="right" label="操作" width="120">
<template #default>
<el-button link type="primary" size="small" @click="handleClick">
删除
</el-button>
<el-button link type="primary" size="small">修改</el-button>
</template>
</el-table-column> -->
</el-table>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
const handleClick = () => {
console.log("click");
};
const tableData = [
{
date: "B0000F03",
name: "PQS882",
state: "南京灿能",
city: "Los Angeles",
address: "192.168.0.0.0",
zip: "CA 90036",
tag: "Home",
},
{
date: "B0000F02",
name: "PQS882",
state: "南京灿能",
city: "Los Angeles",
address: "192.168.0.0.0",
zip: "CA 90036",
tag: "Office",
},
{
date: "B0000F04",
name: "PQS882",
state: "南京灿能",
city: "Los Angeles",
address: "192.168.0.0.0",
zip: "CA 90036",
tag: "Home",
},
{
date: "B0000F01",
name: "PQS882",
state: "南京灿能",
city: "Los Angeles",
address: "192.168.0.0.0",
zip: "CA 90036",
tag: "Office",
},
];
onMounted(() => {
console.log(
tableData,
"tableDatatableDatatableDatatableDatatableDatatableDatatableData"
);
});
</script>
<style lang="scss" scoped>
.table {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,70 @@
<template>
<div class="plan_tree">
<el-input
placeholder="请输入计划名称"
v-model="searchForm.planName"
></el-input>
<el-tree
:data="data"
ref="treeRef"
:filter-node-method="filterNode"
:props="defaultProps"
node-key="id"
@node-click="handleNodeClick"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, defineExpose, watch } from "vue";
const data: any = ref([]);
const defaultProps = {
children: "children",
label: "name",
};
const searchForm = ref({
planName: "",
});
const getTreeData = (val: any) => {
console.log(val, ",,,,");
data.value = val;
};
const filterText = ref("");
const treeRef = ref();
watch(
() => searchForm.value.planName,
(val) => {
treeRef.value!.filter(val);
},
{
deep: true,
}
);
const handleNodeClick = (data) => {
console.log(data);
};
const filterNode = (value: string, data) => {
if (!value) return true;
return data.name.includes(value);
};
onMounted(() => {
console.log();
});
defineExpose({ getTreeData });
</script>
<style lang="scss" scoped>
.plan_tree {
width: 200px;
height: 100%;
// display: flex;
// flex-direction: column;
padding: 5px;
.el-input {
width: 100%;
// height: 40px;
margin:0 10px 10px 0;
}
.el-tree {
height: calc(100% - 70px);
}
}
</style>

View File

@@ -1,12 +1,240 @@
<template>
<div>
<el-button type="primary">按钮</el-button>
<div class="home">
<model v-if="!authStore.showMenuFlag"></model>
<dashboard v-if="authStore.showMenuFlag"></dashboard>
</div>
<!-- <div class="main">
<div class="main_container">
<div class="mode" v-for="(item, index) in modeList" :key="index">
<div class="mode_top">
<div class="mode_name">
<p>
{{ item.name }}
</p>
</div>
<div class="test_button">
<el-button
size="small"
type="primary"
@click="handelOpen(item.isActive)"
>进入检测</el-button
>
</div>
</div>
<div class="mode_img">
<img :src="item.img" />
</div>
</div>
</div>
</div> -->
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { useAuthStore } from "@/stores/modules/auth.ts";
import model from "./tabs/model.vue";
import dashboard from "./tabs/dashboard.vue";
const authStore = useAuthStore();
console.log(authStore.showMenuFlagGet, "????????????????33333333");
const activeIndex = ref("1-1");
const router = useRouter();
const modeList = [
{
name: "模拟式模式",
subName: "未启用模拟式检测计划",
img: "/src/assets/images/dashboard/1.svg",
isActive: true,
},
{
name: "数字式模式",
subName: "启用数字检测计划",
img: "/src/assets/images/dashboard/2.svg",
isActive: false,
},
{
name: "对比式模式",
subName: "启用对比式检测计划",
img: "/src/assets/images/dashboard/3.svg",
isActive: false,
},
];
const handelOpen = async (isActive: any) => {
await authStore.setShowMenu();
return;
if (isActive) {
router.push({ path: "/static" });
} else {
ElMessage({
message: "当前模式未配置",
type: "warning",
});
}
};
const handleSelect = (key: string, keyPath: string[]) => {
console.log(key, keyPath);
};
onMounted(() => {
console.log();
});
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.main_container {
width: 100%;
height: calc(100vh - 120px);
// overflow-y: auto;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
// padding: 20px 2%;
.mode {
// width: 31.5%;
// height: 100%;
flex: none;
width: 32.5%;
height: 100%;
border: 1px solid #eee;
display: flex;
flex-direction: column;
align-items: center;
// justify-content: space-around;
background: #fff;
border-radius: 6px;
margin-bottom: 20px;
background: linear-gradient(
180deg,
rgba(0, 153, 255, 1) 0%,
rgba(0, 153, 255, 1) 0%,
rgba(0, 102, 255, 1) 65%,
rgba(0, 51, 255, 1) 100%,
rgba(0, 51, 255, 1) 100%
);
// padding: 40px 0;
.mode_top {
width: 100%;
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
background: #008aff;
border-radius: 6px 6px 0 0;
.mode_name {
width: 100%;
height: 40px;
flex: 1;
display: flex;
align-items: center;
justify-content: flex-start;
p {
font-family: "微软雅黑 Bold", "微软雅黑", "微软雅黑", sans-serif;
font-weight: 700;
font-style: normal;
font-size: 16px;
color: #ffffff;
text-align: center;
// background: #fff;
line-height: 40px;
text-align: left;
padding-left: 10px;
// margin-top: 20px;
}
.mode_subName {
font-family: "微软雅黑", sans-serif;
font-weight: 400;
font-style: normal;
font-size: 12px;
color: #ffffff;
line-height: 40px;
text-align: center;
padding: 5px 0 0 10px;
// margin-top: 10px;
}
}
.test_button {
width: 150px;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 5px;
}
}
.mode_img {
width: 100%;
height: auto;
display: flex;
align-items: center;
justify-content: center;
// padding: 30px 0 50px;
margin-top: 100px;
img:nth-child(1) {
width: 60%;
height: auto;
display: block;
}
img:nth-child(2) {
width: 70%;
height: auto;
display: block;
}
img:nth-child(3) {
width: 60%;
height: auto;
display: block;
}
}
.mode_test {
width: 100%;
height: 40px;
display: flex;
justify-content: center;
margin-bottom: 20px;
.test_button {
width: 120px;
height: 100%;
border: 1px solid rgba(121, 121, 121, 1);
border-radius: 5px;
font-family: "微软雅黑", sans-serif;
font-weight: 400;
font-style: normal;
color: #fff;
line-height: 20px;
text-align: center;
line-height: 40px;
cursor: pointer;
}
.test_button:hover {
background: rgba(0, 0, 0, 0.2);
}
}
}
.mode:nth-child(3n + 3) {
background: linear-gradient(
180deg,
rgba(0, 153, 255, 1) 0%,
rgba(0, 153, 255, 1) 0%,
rgba(0, 102, 255, 1) 39%,
rgba(102, 51, 204, 1) 100%,
rgba(102, 51, 204, 1) 100%
);
}
.mode_off {
.mode_name,
.mode_subName,
.test_button {
color: #fff !important;
}
.test_button:hover {
// background: rgba(0, 0, 0, 0.2) !important;
cursor: pointer;
}
}
}
::v-deep .el-sub-menu__title {
border-bottom: 0 !important;
outline: none !important;
}
</style>

View File

@@ -0,0 +1,406 @@
<!-- 真正的首页 -->
<template>
<div class="static">
<div class="left_tree">
<tree ref="treeRef" />
</div>
<!-- <span class="new_span">测试scss颜色</span> -->
<div class="right_container">
<div class="container_title">
<el-form :model="form" label-width="80px" :inline="true">
<el-form-item label="功能选择">
<el-select v-model="form.activeTabs" @change="changeSelect">
<el-option
v-for="(item, index) in tabsList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="检测状态" v-if="form.activeTabs != 5">
<el-select v-model="form.checkStatus" @change="changeSelect">
<el-option
v-for="(item, index) in checkStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="报告状态" v-if="form.activeTabs != 5">
<el-select v-model="form.checkReportStatus" @change="changeSelect">
<el-option
v-for="(item, index) in checkReportStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="检测结果" v-if="form.activeTabs != 5">
<el-select v-model="form.checkResult" @change="changeSelect">
<el-option
v-for="(item, index) in checkResultList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="绑定状态" v-if="form.activeTabs == 5">
<el-select v-model="form.deviceBindStatus" @change="changeSelect">
<el-option
v-for="(item, index) in deviceBindStatusList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="设备类型" v-if="form.activeTabs == 5">
<el-select v-model="form.deviceType" @change="changeSelect">
<el-option
v-for="(item, index) in deviceTypeList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="制造厂商" v-if="form.activeTabs == 5">
<el-select v-model="form.manufacturer" @change="changeSelect">
<el-option
v-for="(item, index) in manufacturerList"
:label="item.label"
:value="item.value"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary">查询</el-button>
<el-button type="primary" @click="handleDetection" v-if="form.activeTabs === 0"
>启动自动检测</el-button
>
<el-button type="primary" @click="handleDetection" v-if="form.activeTabs === 1"
>启动手动检测</el-button
>
<el-button type="primary" v-if="form.activeTabs === 2"
>报告生成</el-button
>
<el-button type="primary" v-if="form.activeTabs === 5"
>设备导入</el-button
>
</el-form-item>
</el-form>
</div>
<div class="container_charts">
<div class="charts_info">
<pie
:customData="{
title: '检测状态',
}"
:legendData="{
icon: 'circle',
}"
:chartsData="chartsData1"
ref="pieRef1"
></pie>
</div>
<div class="charts_info">
<pie
:customData="{
title: '检测结果',
}"
:legendData="{
icon: 'circle',
}"
:chartsData="chartsData2"
ref="pieRef2"
></pie>
</div>
<div class="charts_info">
<pie
:customData="{
title: '报告状态',
}"
:legendData="{
icon: 'circle',
}"
:chartsData="chartsData3"
ref="pieRef3"
></pie>
</div>
</div>
<div class="container_table">
<Table></Table>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { getStaticTreeData } from "@/api/plan/static";
import pie from "@/components/echarts/pie/default.vue";
import {useRouter} from 'vue-router'
import tree from "../components/tree.vue";
import Table from "../components/table.vue";
const treeRef = ref();
const form: any = ref({
activeTabs: 0, //功能选择
checkStatus: 0, //检测状态
checkReportStatus: 0, //检测报告状态
checkResult: 0, //检测结果
deviceBindStatus: 0, //绑定状态
deviceType: 0, //设备类型
manufacturer: 0, //制造厂商
});
const router=useRouter()
localStorage.setItem("color", "red");
//功能选择数据
const tabsList = [
{
label: "自动检测",
value: 0,
},
{
label: "手动检测",
value: 1,
},
{
label: "报告生成",
value: 2,
},
{
label: "设备归档",
value: 3,
},
{
label: "设备浏览",
value: 4,
},
{
label: "设备导入",
value: 5,
},
];
//检测状态数据
const checkStatusList = [
{
label: "未检测",
value: 0,
},
{
label: "检测中",
value: 1,
},
{
label: "检测完成",
value: 2,
},
{
label: "归档",
value: 3,
},
];
//检测报告状态数据
const checkReportStatusList = [
{
label: "未生成报告",
value: 0,
},
{
label: "已生成报告",
value: 1,
},
];
//检测结果数组
const checkResultList = [
{
label: "/",
value: null,
},
{
label: "不合格",
value: 0,
},
{
label: "合格",
value: 1,
},
];
//绑定状态数组
const deviceBindStatusList = [
{
label: "未绑定",
value: 0,
},
{
label: "已绑定",
value: 1,
},
];
//设备类型数组
const deviceTypeList = [
{
label: "PQS882A",
value: 0,
},
{
label: "PQS882B4",
value: 1,
},
{
label: "PQS882B5",
value: 2,
},
{
label: "PQS882B6",
value: 3,
},
{
label: "PQS882B7",
value: 4,
},
{
label: "PQS882B8",
value: 5,
},
];
//制造厂商数组
const manufacturerList = [
{
label: "南京灿能电力",
value: 0,
},
{
label: "南瑞继保",
value: 1,
},
{
label: "中电",
value: 2,
},
];
form.value.activeTabs = tabsList[0].value;
const pieRef1 = ref(),
pieRef2 = ref(),
pieRef3 = ref();
const changeSelect = () => {
console.log(form.value.activeTabs);
getPieData();
};
const chartsData1: any = ref([]),
chartsData2: any = ref([]),
chartsData3: any = ref([]);
const getPieData = () => {
chartsData1.value = [
{ value: Math.floor(Math.random() * 100) + 1, name: "未检测" },
{ value: Math.floor(Math.random() * 100) + 1, name: "检测中" },
{ value: Math.floor(Math.random() * 100) + 1, name: "检测完成" },
{ value: Math.floor(Math.random() * 100) + 1, name: "归档" },
];
chartsData2.value = [
{ value: Math.floor(Math.random() * 100) + 1, name: "/" },
{ value: Math.floor(Math.random() * 100) + 1, name: "合格" },
{ value: Math.floor(Math.random() * 100) + 1, name: "不合格" },
];
chartsData3.value = [
{ value: Math.floor(Math.random() * 100) + 1, name: "已生成报告" },
{ value: Math.floor(Math.random() * 100) + 1, name: "未生成报告" },
];
pieRef1.value.init();
pieRef2.value.init();
pieRef3.value.init();
};
const getTree = () => {
getStaticTreeData({ userName: 'zhangsan', planName: "111" }).then(
(res) => {
console.log(res, "99999999");
treeRef.value.getTreeData(res.data);
}
);
};
//前往检测
const handleDetection=()=>{
router.push({
path:"/detection"
})
}
onMounted(() => {
console.log();
getTree();
getPieData();
});
</script>
<style lang="scss" scoped>
.static {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
background-color: #eee;
.left_tree {
width: 200px;
height: 100%;
background-color: #fff;
}
.right_container {
flex: 1;
// width: 100%;
padding: 0 10px 0 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
.container_title {
width: 100%;
// min-height: 50px;
min-height: 100px;
background: #fff;
// padding-left: 20px;
display: flex;
align-items: center;
flex-wrap: wrap;
margin-bottom: 10px;
border-radius: 4px;
.el-form {
width: 100%;
.el-form-item {
// flex:1;
// margin: 0 !important;
// margin:10px 10px 10px 0;
// display: flex;
.el-button {
margin: 0 10px;
}
}
}
}
.container_charts {
width: 100%;
height: 300px;
// border: 2px solid green;
display: flex;
justify-content: space-between;
.charts_info {
width: 32.9%;
height: 100%;
// border: 2px solid pink;
background-color: #fff;
border-radius: 4px;
}
}
.container_table {
width: 100%;
height: 100%;
margin-top: 10px;
border-radius: 4px;
}
}
}
.el-select {
min-width: 180px;
}
</style>

View File

@@ -0,0 +1,242 @@
<!-- 模式切换页面 -->
<template>
<div class="main">
<div
class="main_container"
:style="{
height: authStore.showMenuFlag
? 'calc(100vh - 120px)'
: 'calc(100vh - 100px)',
}"
>
<div class="mode" v-for="(item, index) in modeList" :key="index">
<div class="mode_top">
<div class="mode_name">
<p>
{{ item.name }}
</p>
</div>
<div class="test_button">
<el-button
size="small"
type="primary"
@click="handelOpen(item.isActive)"
>进入检测</el-button
>
</div>
</div>
<div class="mode_img">
<img :src="item.img" />
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { useAuthStore } from "@/stores/modules/auth.ts";
const authStore = useAuthStore();
console.log(authStore.showMenuFlagGet, "????????????????33333333");
const activeIndex = ref("1-1");
const router = useRouter();
const modeList = [
{
name: "模拟式模式",
subName: "未启用模拟式检测计划",
img: "/src/assets/images/dashboard/1.svg",
isActive: true,
},
{
name: "数字式模式",
subName: "启用数字检测计划",
img: "/src/assets/images/dashboard/2.svg",
isActive: false,
},
{
name: "对比式模式",
subName: "启用对比式检测计划",
img: "/src/assets/images/dashboard/3.svg",
isActive: false,
},
];
const handelOpen = async (isActive: any) => {
await authStore.setShowMenu();
return;
if (isActive) {
router.push({ path: "/static" });
} else {
ElMessage({
message: "当前模式未配置",
type: "warning",
});
}
};
const handleSelect = (key: string, keyPath: string[]) => {
console.log(key, keyPath);
};
onMounted(() => {
console.log();
});
</script>
<style lang="scss" scoped>
.main_container {
width: 100%;
height: calc(100vh - 120px);
// overflow-y: auto;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
// padding: 20px 2%;
.mode {
// width: 31.5%;
// height: 100%;
flex: none;
width: 32.5%;
height: 100%;
border: 1px solid #eee;
display: flex;
flex-direction: column;
align-items: center;
// justify-content: space-around;
background: #fff;
border-radius: 6px;
margin-bottom: 20px;
background: linear-gradient(
180deg,
rgba(0, 153, 255, 1) 0%,
rgba(0, 153, 255, 1) 0%,
rgba(0, 102, 255, 1) 65%,
rgba(0, 51, 255, 1) 100%,
rgba(0, 51, 255, 1) 100%
);
// padding: 40px 0;
.mode_top {
width: 100%;
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
background: #008aff;
border-radius: 6px 6px 0 0;
.mode_name {
width: 100%;
height: 40px;
flex: 1;
display: flex;
align-items: center;
justify-content: flex-start;
p {
font-family: "微软雅黑 Bold", "微软雅黑", "微软雅黑", sans-serif;
font-weight: 700;
font-style: normal;
font-size: 16px;
color: #ffffff;
text-align: center;
// background: #fff;
line-height: 40px;
text-align: left;
padding-left: 10px;
// margin-top: 20px;
}
.mode_subName {
font-family: "微软雅黑", sans-serif;
font-weight: 400;
font-style: normal;
font-size: 12px;
color: #ffffff;
line-height: 40px;
text-align: center;
padding: 5px 0 0 10px;
// margin-top: 10px;
}
}
.test_button {
width: 150px;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 5px;
}
}
.mode_img {
width: 100%;
height: auto;
display: flex;
align-items: center;
justify-content: center;
// padding: 30px 0 50px;
margin-top: 100px;
img:nth-child(1) {
width: 60%;
height: auto;
display: block;
}
img:nth-child(2) {
width: 70%;
height: auto;
display: block;
}
img:nth-child(3) {
width: 60%;
height: auto;
display: block;
}
}
.mode_test {
width: 100%;
height: 40px;
display: flex;
justify-content: center;
margin-bottom: 20px;
.test_button {
width: 120px;
height: 100%;
border: 1px solid rgba(121, 121, 121, 1);
border-radius: 5px;
font-family: "微软雅黑", sans-serif;
font-weight: 400;
font-style: normal;
color: #fff;
line-height: 20px;
text-align: center;
line-height: 40px;
cursor: pointer;
}
.test_button:hover {
background: rgba(0, 0, 0, 0.2);
}
}
}
.mode:nth-child(3n + 3) {
background: linear-gradient(
180deg,
rgba(0, 153, 255, 1) 0%,
rgba(0, 153, 255, 1) 0%,
rgba(0, 102, 255, 1) 39%,
rgba(102, 51, 204, 1) 100%,
rgba(102, 51, 204, 1) 100%
);
}
.mode_off {
.mode_name,
.mode_subName,
.test_button {
color: #fff !important;
}
.test_button:hover {
// background: rgba(0, 0, 0, 0.2) !important;
cursor: pointer;
}
}
}
::v-deep .el-sub-menu__title {
border-bottom: 0 !important;
outline: none !important;
}
</style>

View File

@@ -1,5 +1,10 @@
<template>
<el-form ref="loginFormRef" :model="loginForm" :rules="loginRules" size="large">
<el-form
ref="loginFormRef"
:model="loginForm"
:rules="loginRules"
size="large"
>
<el-form-item prop="username">
<el-input v-model="loginForm.username" placeholder="用户名admin / user">
<template #prefix>
@@ -10,7 +15,13 @@
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input v-model="loginForm.password" type="password" placeholder="密码123456" show-password autocomplete="new-password">
<el-input
v-model="loginForm.password"
type="password"
placeholder="密码123456"
show-password
autocomplete="new-password"
>
<template #prefix>
<el-icon class="el-input__icon">
<lock />
@@ -20,8 +31,22 @@
</el-form-item>
</el-form>
<div class="login-btn">
<el-button :icon="CircleClose" round size="large" @click="resetForm(loginFormRef)"> 重置 </el-button>
<el-button :icon="UserFilled" round size="large" type="primary" :loading="loading" @click="login(loginFormRef)">
<el-button
:icon="CircleClose"
round
size="large"
@click="resetForm(loginFormRef)"
>
重置
</el-button>
<el-button
:icon="UserFilled"
round
size="large"
type="primary"
:loading="loading"
@click="login(loginFormRef)"
>
登录
</el-button>
</div>
@@ -40,9 +65,10 @@ import { useTabsStore } from "@/stores/modules/tabs";
import { useKeepAliveStore } from "@/stores/modules/keepAlive";
import { initDynamicRouter } from "@/routers/modules/dynamicRouter";
import { CircleClose, UserFilled } from "@element-plus/icons-vue";
import { useAuthStore } from "@/stores/modules/auth";
import type { ElForm } from "element-plus";
import md5 from "md5";
const authStore = useAuthStore();
const router = useRouter();
const userStore = useUserStore();
const tabsStore = useTabsStore();
@@ -52,24 +78,27 @@ type FormInstance = InstanceType<typeof ElForm>;
const loginFormRef = ref<FormInstance>();
const loginRules = reactive({
username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
password: [{ required: true, message: "请输入密码", trigger: "blur" }]
password: [{ required: true, message: "请输入密码", trigger: "blur" }],
});
const loading = ref(false);
const loginForm = reactive<Login.ReqLoginForm>({
username: "",
password: ""
password: "",
});
// login
const login = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.validate(async valid => {
formEl.validate(async (valid) => {
if (!valid) return;
loading.value = true;
try {
// 1.执行登录接口
const { data } = await loginApi({ ...loginForm, password: md5(loginForm.password) });
const { data } = await loginApi({
...loginForm,
password: md5(loginForm.password),
});
userStore.setToken(data.accessToken);
// 2.添加动态路由
@@ -81,11 +110,13 @@ const login = (formEl: FormInstance | undefined) => {
// 4.跳转到首页
router.push(HOME_URL);
// 5.登录默认不显示菜单和导航栏
authStore.resetAuthStore();
ElNotification({
title: getTimeState(),
message: "登录成功",
type: "success",
duration: 3000
duration: 3000,
});
} finally {
loading.value = false;

View File

@@ -0,0 +1,16 @@
<template>
<div class="detection"></div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
onMounted(() => {
console.log();
});
</script>
<style lang="scss" scoped>
.detection {
width: 100%;
height: 100%;
border: 2px solid green;
}
</style>