2025-02-03 23:58:33 +08:00
|
|
|
<template>
|
|
|
|
<div class="common-layout">
|
|
|
|
<el-container>
|
|
|
|
<el-aside
|
|
|
|
:width="isCollapse ? '63px' : '200px'"
|
|
|
|
style="background: #1d3043"
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
class="collapse white"
|
|
|
|
:style="{
|
|
|
|
fontSize: isCollapse ? '35px' : '20px',
|
|
|
|
background: '#18222c',
|
|
|
|
}"
|
|
|
|
>
|
|
|
|
{{ isCollapse ? "管" : "管理系统" }}
|
|
|
|
</div>
|
|
|
|
<div class="flex-a p5">
|
|
|
|
<div class="person_img2" style="display: flex; align-items: center">
|
|
|
|
<el-avatar
|
|
|
|
:style="{
|
|
|
|
width: isCollapse ? '40px' : '80px',
|
|
|
|
height: isCollapse ? '40px' : '80px',
|
|
|
|
}"
|
|
|
|
src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div class="f14 white" v-if="!isCollapse">
|
|
|
|
<div>管理员</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<el-menu
|
|
|
|
:default-active="state.activePath"
|
|
|
|
class="el-menu-vertical-demo"
|
|
|
|
:collapse="isCollapse"
|
|
|
|
router
|
|
|
|
background-color="#1d3043"
|
|
|
|
active-color="red"
|
|
|
|
active-text-color="#ffd04b"
|
|
|
|
>
|
|
|
|
<div v-for="item in state.menuList" :key="item.id">
|
|
|
|
<el-menu-item
|
|
|
|
:index="'/' + item.browserUrl"
|
|
|
|
v-if="item.children.length == 0"
|
|
|
|
>
|
|
|
|
<el-icon><Link /></el-icon>
|
|
|
|
<template #title>{{ item.name }} </template>
|
|
|
|
</el-menu-item>
|
|
|
|
<el-sub-menu v-else>
|
|
|
|
<template #title>
|
|
|
|
<el-icon><Link /></el-icon>
|
|
|
|
<span class="ml15">{{ item.name }}</span>
|
|
|
|
</template>
|
|
|
|
<div v-for="item2 in item.children" :key="item2.id">
|
|
|
|
<el-menu-item-group>
|
|
|
|
<el-menu-item :index="'/' + item2.browserUrl">
|
|
|
|
<el-icon><Link /></el-icon>{{ item2.name }}</el-menu-item
|
|
|
|
>
|
|
|
|
</el-menu-item-group>
|
|
|
|
</div>
|
|
|
|
</el-sub-menu>
|
|
|
|
</div>
|
|
|
|
</el-menu>
|
|
|
|
</el-aside>
|
|
|
|
<el-container
|
|
|
|
:style="{
|
|
|
|
height: '100vh',
|
|
|
|
}"
|
|
|
|
>
|
|
|
|
<el-header
|
|
|
|
:style="{
|
|
|
|
height: '50px',
|
|
|
|
background: '#1d3043',
|
|
|
|
}"
|
|
|
|
class="flex-s white"
|
|
|
|
>
|
|
|
|
<div class="flex">
|
|
|
|
<el-radio-group v-model="isCollapse">
|
|
|
|
<el-radio-button :value="false" v-if="isCollapse"
|
|
|
|
><el-icon :size="25"><Fold /></el-icon
|
|
|
|
></el-radio-button>
|
|
|
|
<el-radio-button :value="true" v-if="!isCollapse"
|
|
|
|
><el-icon :size="25"><Fold /></el-icon
|
|
|
|
></el-radio-button>
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
|
|
<div @click="reload" class="flex mlr10">
|
|
|
|
<el-icon :size="20"><RefreshRight /></el-icon>刷新
|
|
|
|
</div>
|
|
|
|
<div @click="toggleFullScreen" class="flex ml20">
|
|
|
|
<el-icon :size="19" class=""><FullScreen /></el-icon>全屏
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="flex">
|
|
|
|
<div class="header_info">
|
2025-02-04 00:13:16 +08:00
|
|
|
<!-- <div class="flex" @click="state.userVisible = true">
|
2025-02-03 23:58:33 +08:00
|
|
|
<el-icon size="20"><EditPen /></el-icon>修改密码
|
2025-02-04 00:13:16 +08:00
|
|
|
</div> -->
|
2025-02-03 23:58:33 +08:00
|
|
|
<div class="flex ml20" @click="loginOut">
|
|
|
|
<el-icon size="20"><SwitchButton /></el-icon>退出
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</el-header>
|
|
|
|
<el-main class="p5">
|
|
|
|
<el-tabs
|
|
|
|
@tab-click="tabClick"
|
|
|
|
@tab-remove="tabRemove"
|
|
|
|
v-model="state.activeTab"
|
|
|
|
type="border-card"
|
|
|
|
>
|
|
|
|
<el-tab-pane
|
|
|
|
v-for="item in state.tabsItem"
|
|
|
|
:label="item.title"
|
|
|
|
:name="item.name"
|
|
|
|
:ref="item.ref"
|
|
|
|
:closable="item.closable"
|
|
|
|
>
|
|
|
|
<keepAlive>
|
|
|
|
<component
|
|
|
|
v-if="isRouterAlive"
|
|
|
|
:is="dom[state.tabsItem.content]"
|
|
|
|
:key="state.activeTab"
|
|
|
|
/>
|
|
|
|
</keepAlive>
|
|
|
|
</el-tab-pane>
|
|
|
|
</el-tabs>
|
|
|
|
</el-main>
|
|
|
|
<!-- <el-footer
|
|
|
|
:style="{
|
|
|
|
height: '30px',
|
|
|
|
lineHeight: '30px',
|
|
|
|
}"
|
|
|
|
><div>
|
|
|
|
<strong>
|
|
|
|
Copyright © 2016-2020
|
|
|
|
<a href="javascript:;">管理系统</a>
|
|
|
|
</strong>
|
|
|
|
. All rights reserved.
|
|
|
|
</div></el-footer
|
|
|
|
> -->
|
|
|
|
</el-container>
|
|
|
|
</el-container>
|
|
|
|
<el-dialog
|
|
|
|
title="修改密码"
|
|
|
|
v-model="state.userVisible"
|
|
|
|
@close="userDialog"
|
|
|
|
width="25%"
|
|
|
|
>
|
|
|
|
<el-form
|
|
|
|
label-width="100px"
|
|
|
|
ref="userRef"
|
|
|
|
:model="alterUserInfo"
|
|
|
|
size="mini"
|
|
|
|
:rules="rules"
|
|
|
|
>
|
|
|
|
<div>
|
|
|
|
<el-form-item
|
|
|
|
style="width: 89%"
|
|
|
|
prop="currentPassword"
|
|
|
|
label="旧密码"
|
|
|
|
>
|
|
|
|
<el-input
|
|
|
|
show-password
|
|
|
|
v-model="alterUserInfo.currentPassword"
|
|
|
|
></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item style="width: 89%" prop="password" label="新密码">
|
|
|
|
<el-input show-password v-model="alterUserInfo.password"></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item
|
|
|
|
style="width: 89%"
|
|
|
|
prop="confirmPassword"
|
|
|
|
label="再次确定"
|
|
|
|
>
|
|
|
|
<el-input
|
|
|
|
show-password
|
|
|
|
v-model="alterUserInfo.confirmPassword"
|
|
|
|
></el-input>
|
|
|
|
</el-form-item>
|
|
|
|
</div>
|
|
|
|
</el-form>
|
|
|
|
<template #footer>
|
|
|
|
<div class="dialog-footer">
|
|
|
|
<el-button @click="state.userVisible = false">取消</el-button>
|
|
|
|
<el-button type="primary" @click="alterPassword(userRef)">
|
|
|
|
保存
|
|
|
|
</el-button>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</el-dialog>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
import {
|
|
|
|
ref,
|
|
|
|
watch,
|
|
|
|
shallowRef,
|
|
|
|
onMounted,
|
|
|
|
reactive,
|
|
|
|
nextTick,
|
|
|
|
getCurrentInstance,
|
|
|
|
} from "vue";
|
|
|
|
import { useRouter } from "vue-router";
|
|
|
|
import type { FormInstance, FormRules } from "element-plus";
|
|
|
|
import index from "./index.vue";
|
|
|
|
import about from "./about.vue";
|
2025-02-04 00:13:16 +08:00
|
|
|
import order from "./order.vue";
|
2025-02-03 23:58:33 +08:00
|
|
|
|
|
|
|
const { appContext } = getCurrentInstance();
|
|
|
|
const dom = shallowRef({
|
2025-02-04 00:13:16 +08:00
|
|
|
order,
|
2025-02-03 23:58:33 +08:00
|
|
|
about,
|
|
|
|
index,
|
|
|
|
});
|
|
|
|
const proxy = appContext.config.globalProperties;
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
|
|
const state = reactive({
|
|
|
|
userVisible: false,
|
|
|
|
activePath: "/index",
|
|
|
|
activeTab: "index",
|
|
|
|
tabsItem: [
|
|
|
|
{
|
|
|
|
title: "租户管理",
|
|
|
|
name: "index",
|
|
|
|
// 导入的组件
|
|
|
|
content: "index",
|
|
|
|
ref: "tabs",
|
|
|
|
closable: false,
|
|
|
|
query: "",
|
|
|
|
path: "/index",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
menuList: [
|
|
|
|
{
|
|
|
|
action: "index",
|
|
|
|
appIcon: null,
|
|
|
|
browserUrl: "index",
|
|
|
|
children: [],
|
|
|
|
icon: "fa fa-link",
|
|
|
|
name: "租户管理",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
action: "about",
|
|
|
|
appIcon: null,
|
|
|
|
browserUrl: "about",
|
|
|
|
children: [],
|
|
|
|
icon: "fa fa-link",
|
2025-02-04 00:13:16 +08:00
|
|
|
name: "产品",
|
2025-02-03 23:58:33 +08:00
|
|
|
},
|
|
|
|
{
|
2025-02-04 00:13:16 +08:00
|
|
|
action: "order",
|
2025-02-03 23:58:33 +08:00
|
|
|
appIcon: null,
|
2025-02-04 00:13:16 +08:00
|
|
|
browserUrl: "order",
|
2025-02-03 23:58:33 +08:00
|
|
|
children: [],
|
|
|
|
icon: "fa fa-link",
|
2025-02-04 00:13:16 +08:00
|
|
|
name: "订单管理",
|
2025-02-03 23:58:33 +08:00
|
|
|
},
|
|
|
|
] as any,
|
|
|
|
});
|
|
|
|
const validatePass = (rule: any, value: any, callback: any) => {
|
|
|
|
console.log(value);
|
|
|
|
if (value.length < 6) {
|
|
|
|
callback(new Error("密码长度不能小于6位"));
|
|
|
|
} else {
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
const alterUserInfo = reactive({
|
|
|
|
currentPassword: "",
|
|
|
|
password: "",
|
|
|
|
confirmPassword: "",
|
|
|
|
});
|
|
|
|
const userRef = ref<FormInstance>();
|
|
|
|
const rules = {
|
|
|
|
currentPassword: [
|
|
|
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
|
|
|
{ validator: validatePass, trigger: "blur" },
|
|
|
|
],
|
|
|
|
password: [
|
|
|
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
|
|
|
{ validator: validatePass, trigger: "blur" },
|
|
|
|
],
|
|
|
|
confirmPassword: [
|
|
|
|
{ required: true, message: "请确认密码", trigger: "blur" },
|
|
|
|
{
|
|
|
|
validator: (rule: any, value: any, callback: any) => {
|
|
|
|
if (value !== alterUserInfo.password) {
|
|
|
|
callback(new Error("两次输入的密码不一致"));
|
|
|
|
} else {
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
trigger: "blur",
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
const isRouterAlive = ref(true);
|
|
|
|
// 在组件挂载时获取用户信息
|
|
|
|
let isCollapse = ref<Boolean>(false);
|
|
|
|
onMounted(async () => {
|
|
|
|
console.log(8888);
|
|
|
|
});
|
|
|
|
// 刷新
|
|
|
|
const reload = () => {
|
|
|
|
// router.go(0);
|
|
|
|
isRouterAlive.value = false;
|
|
|
|
nextTick(() => {
|
|
|
|
isRouterAlive.value = true;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
// 退出登录
|
|
|
|
const loginOut = () => {
|
|
|
|
router.push("/login");
|
|
|
|
};
|
|
|
|
// 关闭dialog
|
|
|
|
const userDialog = () => {
|
|
|
|
for (let i in alterUserInfo) {
|
|
|
|
alterUserInfo[i] = "";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
//修改密码
|
|
|
|
const alterPassword = (formEl: FormInstance | undefined) => {
|
|
|
|
if (!formEl) return;
|
|
|
|
formEl.validate(async (valid: any, fields: any) => {
|
|
|
|
if (valid) {
|
|
|
|
state.userVisible = false;
|
|
|
|
router.push("/login");
|
|
|
|
} else {
|
|
|
|
return proxy.$messageE("请完善信息");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
// 全屏
|
|
|
|
const isFullScreen = ref(false);
|
|
|
|
function toggleFullScreen() {
|
|
|
|
if (!document.fullscreenElement && !isFullScreen.value) {
|
|
|
|
// 进入全屏
|
|
|
|
document.documentElement.requestFullscreen().then(() => {
|
|
|
|
isFullScreen.value = true;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// 退出全屏
|
|
|
|
if (document.exitFullscreen) {
|
|
|
|
document.exitFullscreen().then(() => {
|
|
|
|
isFullScreen.value = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 监听全屏状态变化
|
|
|
|
document.addEventListener("fullscreenchange", () => {
|
|
|
|
isFullScreen.value = !!document.fullscreenElement;
|
|
|
|
});
|
|
|
|
// 点击tab
|
|
|
|
const tabClick = (tab: any) => {
|
|
|
|
let val = state.tabsItem.filter((item) => tab.props.label == item.title);
|
|
|
|
router.push(val[0].path);
|
|
|
|
state.activePath = val[0].path;
|
|
|
|
};
|
|
|
|
// 关闭tab
|
|
|
|
const tabRemove = (tab: any) => {
|
|
|
|
state.tabsItem.forEach((val: any, index: Number) => {
|
|
|
|
if (val.name === tab) {
|
|
|
|
state.tabsItem.splice(index, 1);
|
|
|
|
if (tab === state.activeTab) {
|
|
|
|
router.push(state.tabsItem[index - 1].path);
|
|
|
|
state.activePath = state.tabsItem[index - 1].path;
|
|
|
|
state.activeTab = state.tabsItem[index - 1].name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
// 监听当前路由
|
|
|
|
watch(
|
|
|
|
() => router.currentRoute.value,
|
|
|
|
(val: any) => {
|
|
|
|
console.log(8888, val);
|
|
|
|
state.activePath = val.path;
|
|
|
|
state.tabsItem.title = val.meta.name;
|
|
|
|
state.tabsItem.name = val.meta.comp;
|
|
|
|
state.tabsItem.closable = true;
|
|
|
|
state.tabsItem.ref = "tabs";
|
|
|
|
state.tabsItem.content = val.meta.comp;
|
|
|
|
state.tabsItem.query = val.query.id;
|
|
|
|
state.tabsItem.path = val.path;
|
|
|
|
|
|
|
|
console.log(56696, state.tabsItem);
|
|
|
|
let result = state.tabsItem.some((item) => item.title == val.meta.name);
|
|
|
|
console.log(result);
|
|
|
|
state.activeTab = val.meta.comp;
|
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
state.tabsItem.push({
|
|
|
|
title: val.meta.name,
|
|
|
|
name: val.meta.comp,
|
|
|
|
// 导入的组件
|
|
|
|
content: val.meta.comp,
|
|
|
|
ref: "tabs",
|
|
|
|
closable: true,
|
|
|
|
query: "",
|
|
|
|
path: "/" + val.meta.comp,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{ immediate: true }
|
|
|
|
);
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.header_info {
|
|
|
|
display: flex;
|
|
|
|
justify-content: right;
|
|
|
|
align-items: center;
|
|
|
|
width: auto;
|
|
|
|
}
|
|
|
|
.collapse {
|
|
|
|
text-align: center;
|
|
|
|
cursor: pointer;
|
|
|
|
align-items: center;
|
|
|
|
width: 100%;
|
|
|
|
height: 50px;
|
|
|
|
line-height: 50px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.person_img2 img {
|
|
|
|
margin: 0 auto;
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
|
|
/* background: #ffffff; */
|
|
|
|
}
|
|
|
|
|
|
|
|
.el-tab-pane {
|
|
|
|
max-height: calc(100vh - 150px);
|
|
|
|
overflow-y: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
.el-radio-button__inner {
|
|
|
|
background: #1d3043;
|
|
|
|
color: white;
|
|
|
|
border-color: #1d3043;
|
|
|
|
}
|
|
|
|
.el-radio-button__original-radio:checked + .el-radio-button__inner {
|
|
|
|
background: #1d3043;
|
|
|
|
border-color: #1d3043;
|
|
|
|
}
|
|
|
|
.el-radio-button:first-child .el-radio-button__inner {
|
|
|
|
border-left: #1d3043;
|
|
|
|
}
|
|
|
|
.el-menu {
|
|
|
|
border-right: none;
|
|
|
|
}
|
|
|
|
.el-menu-item-group__title {
|
|
|
|
padding: 0 !important;
|
|
|
|
}
|
|
|
|
.el-menu-item {
|
|
|
|
color: white;
|
|
|
|
}
|
|
|
|
.el-main {
|
|
|
|
padding: 0;
|
|
|
|
}
|
|
|
|
</style>
|