导航栏/菜单栏显示逻辑修改
This commit is contained in:
8
frontend/src/api/plan/static.ts
Normal file
8
frontend/src/api/plan/static.ts
Normal 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
|
||||
};
|
||||
1296
frontend/src/assets/images/dashboard/1.svg
Normal file
1296
frontend/src/assets/images/dashboard/1.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 71 KiB |
67
frontend/src/assets/images/dashboard/2.svg
Normal file
67
frontend/src/assets/images/dashboard/2.svg
Normal 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 |
2104
frontend/src/assets/images/dashboard/3.svg
Normal file
2104
frontend/src/assets/images/dashboard/3.svg
Normal file
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 81 KiB |
109
frontend/src/components/echarts/pie/default.vue
Normal file
109
frontend/src/components/echarts/pie/default.vue
Normal 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>
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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),
|
||||
});
|
||||
|
||||
89
frontend/src/views/home/components/table.vue
Normal file
89
frontend/src/views/home/components/table.vue
Normal 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>
|
||||
70
frontend/src/views/home/components/tree.vue
Normal file
70
frontend/src/views/home/components/tree.vue
Normal 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>
|
||||
@@ -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>
|
||||
|
||||
406
frontend/src/views/home/tabs/dashboard.vue
Normal file
406
frontend/src/views/home/tabs/dashboard.vue
Normal 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>
|
||||
242
frontend/src/views/home/tabs/model.vue
Normal file
242
frontend/src/views/home/tabs/model.vue
Normal 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>
|
||||
@@ -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;
|
||||
|
||||
16
frontend/src/views/plan/detection/index.vue
Normal file
16
frontend/src/views/plan/detection/index.vue
Normal 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>
|
||||
Reference in New Issue
Block a user