v2.6.6版本发布 (#1784)
* 前端支持顶部菜单栏模式 * 自动化代码单条获取方法不再需要取data.xxx直接取用data * 自动化代码支持选择索引 * 自动化代码回滚支持自行选择是否删除菜单、API、表 * 日志增加定期清理功能 * 权限配置API部分,支持根据API真实path进行筛选 * 修复了一些已知bug * 修复了一个sql注入漏洞 --------- Co-authored-by: xuedinge <781408517@qq.com> Co-authored-by: Qing Liang <106448173+xue-ding-e@users.noreply.github.com> Co-authored-by: wall-js <wall_js@foxmail.com> Co-authored-by: Wall <307606056@qq.com> Co-authored-by: leooza <leooza@163.com> Co-authored-by: piexlMax(奇淼 <qimiaojiangjizhao@gmail.com> Co-authored-by: hxl <52553624@qq.com> Co-authored-by: zsc1003 <11476303+zsc1003@user.noreply.gitee.com>
This commit is contained in:
co-authored by
xuedinge
Qing Liang
wall-js
Wall
leooza
piexlMax(奇淼
hxl
zsc1003
parent
b336529d42
commit
03e5bc515f
@@ -2,7 +2,7 @@
|
||||
<el-sub-menu
|
||||
ref="subMenu"
|
||||
:index="routerInfo.name"
|
||||
class="gva-sub-menu dark:text-slate-300"
|
||||
class="gva-sub-menu dark:text-slate-300 relative"
|
||||
>
|
||||
<template #title>
|
||||
<div
|
||||
@@ -52,7 +52,9 @@ const isCollapse = inject('isCollapse', {
|
||||
default: false,
|
||||
})
|
||||
|
||||
const sideHeight = computed(() => config.value.layout_side_item_height + 'px')
|
||||
const sideHeight = computed(() => {
|
||||
return config.value.layout_side_item_height + 'px'
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ const props = defineProps({
|
||||
type: Object,
|
||||
default: () => null,
|
||||
},
|
||||
mode :{
|
||||
type : String,
|
||||
default: "vertical"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,9 @@ defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const sideHeight = computed(() => config.value.layout_side_item_height + 'px')
|
||||
const sideHeight = computed(() => {
|
||||
return config.value.layout_side_item_height + 'px'
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<div class="bg-white h-[calc(100%-4px)] text-slate-700 dark:text-slate-300 mx-2 dark:bg-slate-900 flex items-center w-full overflow-auto">
|
||||
<el-menu
|
||||
:default-active="active"
|
||||
mode="horizontal"
|
||||
class="border-r-0 w-[calc(100%-100px)] flex gap-1 items-center box-border h-[calc(100%-1px)]"
|
||||
unique-opened
|
||||
@select="selectMenuItem"
|
||||
>
|
||||
<template v-for="item in routerStore.asyncRouters[0].children">
|
||||
<aside-component
|
||||
v-if="!item.hidden"
|
||||
:key="item.name"
|
||||
:router-info="item"
|
||||
mode="horizontal"
|
||||
/>
|
||||
</template>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import AsideComponent from "@/view/layout/aside/asideComponent/index.vue";
|
||||
import { ref, provide, watchEffect, computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useRouterStore } from "@/pinia/modules/router";
|
||||
import { useAppStore } from "@/pinia";
|
||||
import { storeToRefs } from "pinia";
|
||||
const appStore = useAppStore();
|
||||
const { device, config } = storeToRefs(appStore);
|
||||
|
||||
defineOptions({
|
||||
name: "GvaAside",
|
||||
});
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const routerStore = useRouterStore();
|
||||
const isCollapse = ref(false);
|
||||
const active = ref("");
|
||||
watchEffect(() => {
|
||||
active.value = route.meta.activeName || route.name;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (device.value === "mobile") {
|
||||
isCollapse.value = true;
|
||||
} else {
|
||||
isCollapse.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
provide("isCollapse", isCollapse);
|
||||
|
||||
const selectMenuItem = (index, _, ele, aaa) => {
|
||||
const query = {};
|
||||
const params = {};
|
||||
routerStore.routeMap[index]?.parameters &&
|
||||
routerStore.routeMap[index]?.parameters.forEach((item) => {
|
||||
if (item.type === "query") {
|
||||
query[item.key] = item.value;
|
||||
} else {
|
||||
params[item.key] = item.value;
|
||||
}
|
||||
});
|
||||
if (index === route.name) return;
|
||||
if (index.indexOf("http://") > -1 || index.indexOf("https://") > -1) {
|
||||
window.open(index);
|
||||
} else {
|
||||
router.push({ name: index, query, params });
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-menu--horizontal.el-menu,
|
||||
.el-menu--horizontal > .el-menu-item.is-active{
|
||||
border-bottom : none !important;
|
||||
|
||||
}
|
||||
|
||||
.el-menu-item.is-active{
|
||||
background-color: var(--el-color-primary-light-8) !important;
|
||||
}
|
||||
|
||||
.dark{
|
||||
.el-menu-item.is-active{
|
||||
background-color: var(--el-color-primary-bg) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,116 +1,15 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative h-full bg-white text-slate-700 dark:text-slate-300 dark:bg-slate-900 border-r shadow dark:shadow-gray-700"
|
||||
:class="isCollapse ? '' : ' px-2'"
|
||||
:style="{
|
||||
width : layoutSideWidth + 'px',
|
||||
}"
|
||||
>
|
||||
<el-scrollbar>
|
||||
<transition
|
||||
:duration="{ enter: 800, leave: 100 }"
|
||||
mode="out-in"
|
||||
name="el-fade-in-linear"
|
||||
>
|
||||
<el-menu
|
||||
:collapse="isCollapse"
|
||||
:collapse-transition="false"
|
||||
:default-active="active"
|
||||
class="border-r-0 w-full"
|
||||
unique-opened
|
||||
@select="selectMenuItem"
|
||||
>
|
||||
<template v-for="item in routerStore.asyncRouters[0].children">
|
||||
<aside-component
|
||||
v-if="!item.hidden"
|
||||
:key="item.name"
|
||||
:router-info="item"
|
||||
/>
|
||||
</template>
|
||||
</el-menu>
|
||||
</transition>
|
||||
</el-scrollbar>
|
||||
<div
|
||||
class="absolute bottom-8 right-2 w-8 h-8 bg-gray-50 dark:bg-slate-800 flex items-center justify-center rounded cursor-pointer "
|
||||
:class="isCollapse ? 'right-0 left-0 mx-auto' : 'right-2'"
|
||||
@click="toggleCollapse"
|
||||
>
|
||||
<el-icon v-if="!isCollapse">
|
||||
<DArrowLeft />
|
||||
</el-icon>
|
||||
<el-icon v-else>
|
||||
<DArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div>
|
||||
<normal-mode v-if="config.side_mode != 'head' || (device === 'mobile'&& config.side_mode == 'head' )" />
|
||||
<head-mode v-if="config.side_mode === 'head' && device !== 'mobile'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import AsideComponent from "@/view/layout/aside/asideComponent/index.vue";
|
||||
import { ref, provide, watchEffect, computed} from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useRouterStore } from "@/pinia/modules/router";
|
||||
import { useAppStore } from "@/pinia"
|
||||
import { storeToRefs } from "pinia"
|
||||
const appStore = useAppStore()
|
||||
const { device, config } = storeToRefs(appStore)
|
||||
|
||||
defineOptions({
|
||||
name: "GvaAside",
|
||||
});
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const routerStore = useRouterStore();
|
||||
const isCollapse = ref(false)
|
||||
const active = ref("");
|
||||
const layoutSideWidth = computed(() =>{
|
||||
if (!isCollapse.value) {
|
||||
return config.value.layout_side_width
|
||||
}else{
|
||||
return config.value.layout_side_collapsed_width
|
||||
}
|
||||
})
|
||||
watchEffect(() => {
|
||||
active.value = route.meta.activeName || route.name;
|
||||
});
|
||||
|
||||
watchEffect(() =>{
|
||||
if (device.value === 'mobile') {
|
||||
isCollapse.value = true
|
||||
}else{
|
||||
isCollapse.value = false
|
||||
}
|
||||
})
|
||||
|
||||
provide("isCollapse", isCollapse);
|
||||
|
||||
|
||||
|
||||
const selectMenuItem = (index, _, ele, aaa) => {
|
||||
const query = {};
|
||||
const params = {};
|
||||
routerStore.routeMap[index]?.parameters &&
|
||||
routerStore.routeMap[index]?.parameters.forEach((item) => {
|
||||
if (item.type === "query") {
|
||||
query[item.key] = item.value;
|
||||
} else {
|
||||
params[item.key] = item.value;
|
||||
}
|
||||
});
|
||||
if (index === route.name) return;
|
||||
if (index.indexOf("http://") > -1 || index.indexOf("https://") > -1) {
|
||||
window.open(index);
|
||||
} else {
|
||||
router.push({ name: index, query, params });
|
||||
}
|
||||
};
|
||||
|
||||
const toggleCollapse = () => {
|
||||
isCollapse.value = !isCollapse.value;
|
||||
};
|
||||
|
||||
import NormalMode from "./normalMode.vue"
|
||||
import HeadMode from "./headMode.vue"
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useAppStore } from "@/pinia";
|
||||
const appStore = useAppStore();
|
||||
const { config, device } = storeToRefs(appStore);
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<template>
|
||||
<div
|
||||
class="relative h-full bg-white text-slate-700 dark:text-slate-300 dark:bg-slate-900 border-r shadow dark:shadow-gray-700"
|
||||
:class="isCollapse ? '' : ' px-2'"
|
||||
:style="{
|
||||
width: layoutSideWidth + 'px',
|
||||
}"
|
||||
>
|
||||
<el-menu
|
||||
:collapse="isCollapse"
|
||||
:collapse-transition="false"
|
||||
:default-active="active"
|
||||
class="border-r-0 w-full"
|
||||
unique-opened
|
||||
@select="selectMenuItem"
|
||||
>
|
||||
<template v-for="item in routerStore.asyncRouters[0].children">
|
||||
<aside-component
|
||||
v-if="!item.hidden"
|
||||
:key="item.name"
|
||||
:router-info="item"
|
||||
/>
|
||||
</template>
|
||||
</el-menu>
|
||||
<div
|
||||
class="absolute bottom-8 right-2 w-8 h-8 bg-gray-50 dark:bg-slate-800 flex items-center justify-center rounded cursor-pointer"
|
||||
:class="isCollapse ? 'right-0 left-0 mx-auto' : 'right-2'"
|
||||
@click="toggleCollapse"
|
||||
>
|
||||
<el-icon v-if="!isCollapse">
|
||||
<DArrowLeft />
|
||||
</el-icon>
|
||||
<el-icon v-else>
|
||||
<DArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import AsideComponent from "@/view/layout/aside/asideComponent/index.vue";
|
||||
import { ref, provide, watchEffect, computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useRouterStore } from "@/pinia/modules/router";
|
||||
import { useAppStore } from "@/pinia";
|
||||
import { storeToRefs } from "pinia";
|
||||
const appStore = useAppStore();
|
||||
const { device, config } = storeToRefs(appStore);
|
||||
|
||||
defineOptions({
|
||||
name: "GvaAside",
|
||||
});
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const routerStore = useRouterStore();
|
||||
const isCollapse = ref(false);
|
||||
const active = ref("");
|
||||
const layoutSideWidth = computed(() => {
|
||||
if (!isCollapse.value) {
|
||||
return config.value.layout_side_width;
|
||||
} else {
|
||||
return config.value.layout_side_collapsed_width;
|
||||
}
|
||||
});
|
||||
watchEffect(() => {
|
||||
active.value = route.meta.activeName || route.name;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (device.value === "mobile") {
|
||||
isCollapse.value = true;
|
||||
} else {
|
||||
isCollapse.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
provide("isCollapse", isCollapse);
|
||||
|
||||
const selectMenuItem = (index, _, ele, aaa) => {
|
||||
const query = {};
|
||||
const params = {};
|
||||
routerStore.routeMap[index]?.parameters &&
|
||||
routerStore.routeMap[index]?.parameters.forEach((item) => {
|
||||
if (item.type === "query") {
|
||||
query[item.key] = item.value;
|
||||
} else {
|
||||
params[item.key] = item.value;
|
||||
}
|
||||
});
|
||||
if (index === route.name) return;
|
||||
if (index.indexOf("http://") > -1 || index.indexOf("https://") > -1) {
|
||||
window.open(index);
|
||||
} else {
|
||||
router.push({ name: index, query, params });
|
||||
}
|
||||
};
|
||||
|
||||
const toggleCollapse = () => {
|
||||
isCollapse.value = !isCollapse.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
<div
|
||||
v-if="!isMobile"
|
||||
class="inline-flex font-bold text-2xl ml-2"
|
||||
:class="config.side_mode === 'head'&&'min-w-fit'"
|
||||
>
|
||||
{{ $GIN_VUE_ADMIN.appName }}
|
||||
</div>
|
||||
|
||||
<gva-aside v-if="config.side_mode === 'head' && !isMobile" />
|
||||
|
||||
<el-breadcrumb v-show="!isMobile" class="ml-4">
|
||||
<el-breadcrumb v-show="!isMobile" v-else class="ml-4">
|
||||
<el-breadcrumb-item
|
||||
v-for="item in matched.slice(1, matched.length)"
|
||||
:key="item.path"
|
||||
@@ -46,7 +48,7 @@
|
||||
<CustomPic />
|
||||
<span
|
||||
v-show="!isMobile"
|
||||
style="margin-left: 5px"
|
||||
class="w-16"
|
||||
>{{ userStore.userInfo.nickName }}</span>
|
||||
<el-icon>
|
||||
<arrow-down />
|
||||
@@ -103,11 +105,12 @@ import { storeToRefs } from "pinia"
|
||||
import { computed, ref } from 'vue'
|
||||
import { setUserAuthority } from '@/api/user'
|
||||
import { fmtTitle } from "@/utils/fmtRouterTitle";
|
||||
import gvaAside from "@/view/layout/aside/index.vue"
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const appStore = useAppStore()
|
||||
const { device } = storeToRefs(appStore)
|
||||
const { device , config } = storeToRefs(appStore)
|
||||
const isMobile = computed(() =>{
|
||||
return device.value === 'mobile'
|
||||
})
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
!-->
|
||||
|
||||
<template>
|
||||
<div class="flex items-center mx-8 gap-4">
|
||||
<div class="flex items-center mx-4 gap-4">
|
||||
<el-tooltip
|
||||
class=""
|
||||
effect="dark"
|
||||
|
||||
@@ -1,14 +1,29 @@
|
||||
<template>
|
||||
<div class="bg-gray-50 text-slate-700 dark:text-slate-500 dark:bg-slate-800 w-screen h-screen">
|
||||
<el-watermark v-if="config.show_watermark" :font="font" :z-index="9999" :gap="[180,150]" class="absolute inset-0 pointer-events-none" :content="userStore.userInfo.nickName" />
|
||||
<div
|
||||
class="bg-gray-50 text-slate-700 dark:text-slate-500 dark:bg-slate-800 w-screen h-screen"
|
||||
>
|
||||
<el-watermark
|
||||
v-if="config.show_watermark"
|
||||
:font="font"
|
||||
:z-index="9999"
|
||||
:gap="[180, 150]"
|
||||
class="absolute inset-0 pointer-events-none"
|
||||
:content="userStore.userInfo.nickName"
|
||||
/>
|
||||
<gva-header />
|
||||
<div class="flex flex-row w-full gva-container pt-16">
|
||||
<gva-aside />
|
||||
<div class="flex-1 w-0 h-full">
|
||||
<div class="flex flex-row w-full gva-container pt-16">
|
||||
<gva-aside v-if="config.side_mode != 'head' || (device === 'mobile'&& config.side_mode == 'head' )" />
|
||||
<div class="flex-1 p-2 w-0 h-full">
|
||||
<gva-tabs v-if="config.showTabs" />
|
||||
<div class="overflow-auto" :class="config.showTabs? 'gva-container2' :'gva-container pt-1'">
|
||||
<div
|
||||
class="overflow-auto"
|
||||
:class="config.showTabs ? 'gva-container2' : 'gva-container pt-1'"
|
||||
>
|
||||
<router-view v-if="reloadFlag" v-slot="{ Component }">
|
||||
<div id="gva-base-load-dom" class="gva-body-h bg-gray-50 dark:bg-slate-800">
|
||||
<div
|
||||
id="gva-base-load-dom"
|
||||
class="gva-body-h bg-gray-50 dark:bg-slate-800"
|
||||
>
|
||||
<transition mode="out-in" name="el-fade-in-linear">
|
||||
<keep-alive :include="routerStore.keepAliveRouters">
|
||||
<component :is="Component" />
|
||||
@@ -26,32 +41,32 @@
|
||||
<script setup>
|
||||
import GvaAside from "@/view/layout/aside/index.vue";
|
||||
import GvaHeader from "@/view/layout/header/index.vue";
|
||||
import useResponsive from "@/hooks/responsive";
|
||||
import GvaTabs from "./tabs/index.vue"
|
||||
import useResponsive from "@/hooks/responsive";
|
||||
import GvaTabs from "./tabs/index.vue";
|
||||
import BottomInfo from "@/components/bottomInfo/bottomInfo.vue";
|
||||
import { emitter } from "@/utils/bus.js";
|
||||
import { ref, onMounted, nextTick, reactive, watchEffect} from "vue";
|
||||
import { ref, onMounted, nextTick, reactive, watchEffect } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { useRouterStore } from "@/pinia/modules/router";
|
||||
import { useUserStore } from "@/pinia/modules/user";
|
||||
import { useAppStore } from '@/pinia'
|
||||
import { storeToRefs } from 'pinia'
|
||||
const appStore = useAppStore()
|
||||
const { config, theme } = storeToRefs(appStore)
|
||||
import { useAppStore } from "@/pinia";
|
||||
import { storeToRefs } from "pinia";
|
||||
const appStore = useAppStore();
|
||||
const { config, theme, device } = storeToRefs(appStore);
|
||||
|
||||
defineOptions({
|
||||
name: "GvaLayout",
|
||||
});
|
||||
|
||||
useResponsive(true)
|
||||
useResponsive(true);
|
||||
const font = reactive({
|
||||
color: 'rgba(0, 0, 0, .15)',
|
||||
})
|
||||
color: "rgba(0, 0, 0, .15)",
|
||||
});
|
||||
|
||||
watchEffect(()=>{
|
||||
font.color = theme.value === 'dark' ? 'rgba(255,255,255, .15)' : 'rgba(0, 0, 0, .15)'
|
||||
|
||||
})
|
||||
watchEffect(() => {
|
||||
font.color =
|
||||
theme.value === "dark" ? "rgba(255,255,255, .15)" : "rgba(0, 0, 0, .15)";
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
@@ -84,13 +99,7 @@ const reload = async () => {
|
||||
}
|
||||
}, 400);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,40 +1,46 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
v-model="drawer"
|
||||
title="系统配置"
|
||||
direction="rtl"
|
||||
:size="width"
|
||||
>
|
||||
<el-drawer v-model="drawer" title="系统配置" direction="rtl" :size="width">
|
||||
<div class="flex flex-col">
|
||||
<div class="mb-8">
|
||||
<div class=" text-gray-800 dark:text-gray-100">
|
||||
默认主题
|
||||
</div>
|
||||
<div class="text-gray-800 dark:text-gray-100">默认主题</div>
|
||||
<div class="mt-2 text-sm p-2 flex items-center gap-2">
|
||||
<el-segmented v-model="config.darkMode" :options="options" size="default" @change="appStore.toggleDarkMode" />
|
||||
<el-segmented
|
||||
v-model="config.darkMode"
|
||||
:options="options"
|
||||
size="default"
|
||||
@change="appStore.toggleDarkMode"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<div class=" text-gray-800 dark:text-gray-100">
|
||||
主题色
|
||||
</div>
|
||||
<div class="text-gray-800 dark:text-gray-100">主题色</div>
|
||||
<div class="mt-2 text-sm p-2 flex items-center gap-2">
|
||||
<div v-for="item in colors" :key="item" class=" w-5 h-5 rounded cursor-pointer flex items-center justify-center" :style="`background:${item}`" @click="appStore.togglePrimaryColor(item)">
|
||||
<div
|
||||
v-for="item in colors"
|
||||
:key="item"
|
||||
class="w-5 h-5 rounded cursor-pointer flex items-center justify-center"
|
||||
:style="`background:${item}`"
|
||||
@click="appStore.togglePrimaryColor(item)"
|
||||
>
|
||||
<el-icon v-if="config.primaryColor === item">
|
||||
<Select />
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-color-picker v-model="customColor" @change="appStore.togglePrimaryColor" />
|
||||
<el-color-picker
|
||||
v-model="customColor"
|
||||
@change="appStore.togglePrimaryColor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-8">
|
||||
<div class=" text-gray-800 dark:text-gray-100">
|
||||
界面显示
|
||||
</div>
|
||||
<div class="text-gray-800 dark:text-gray-100">界面显示</div>
|
||||
<div class="mt-2 text-sm p-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>展示水印</div>
|
||||
<el-switch v-model="config.show_watermark" @change="appStore.toggleConfigWatermark" />
|
||||
<el-switch
|
||||
v-model="config.show_watermark"
|
||||
@change="appStore.toggleConfigWatermark"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>灰色模式</div>
|
||||
@@ -42,95 +48,144 @@
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>色弱模式</div>
|
||||
<el-switch v-model="config.weakness" @change="appStore.toggleWeakness" />
|
||||
<el-switch
|
||||
v-model="config.weakness"
|
||||
@change="appStore.toggleWeakness"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>菜单模式</div>
|
||||
<el-segmented
|
||||
v-model="config.side_mode"
|
||||
:options="sideModes"
|
||||
size="default"
|
||||
@change="appStore.toggleSideModel"
|
||||
/>
|
||||
<!-- <el-select
|
||||
v-model="config.side_mode"
|
||||
@change="handleSideModelChange"
|
||||
>
|
||||
<el-option value="normal" label="标准模式" />
|
||||
<el-option value="head" label="顶部导航栏" />
|
||||
<el-option value="multilayer" disabled label="多侧边导航模式" />
|
||||
</el-select> -->
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<div>显示标签页</div>
|
||||
<el-switch v-model="config.showTabs" @change="appStore.toggleTabs" />
|
||||
<el-switch
|
||||
v-model="config.showTabs"
|
||||
@change="appStore.toggleTabs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-8">
|
||||
<div class=" text-gray-800 dark:text-gray-100">
|
||||
layout 大小配置
|
||||
</div>
|
||||
<div class="text-gray-800 dark:text-gray-100">layout 大小配置</div>
|
||||
<div class="mt-2 text-sm p-2">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div>侧边栏展开宽度</div>
|
||||
<el-input-number v-model="config.layout_side_width" :min="150" :max="400" :step="10"></el-input-number>
|
||||
<el-input-number
|
||||
v-model="config.layout_side_width"
|
||||
:min="150"
|
||||
:max="400"
|
||||
:step="10"
|
||||
></el-input-number>
|
||||
</div>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div>侧边栏收缩宽度</div>
|
||||
<el-input-number v-model="config.layout_side_collapsed_width" :min="60" :max="100"></el-input-number>
|
||||
<el-input-number
|
||||
v-model="config.layout_side_collapsed_width"
|
||||
:min="60"
|
||||
:max="100"
|
||||
></el-input-number>
|
||||
</div>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div>侧边栏子项高度</div>
|
||||
<el-input-number v-model="config.layout_side_item_height" :min="30" :max="50"></el-input-number>
|
||||
<el-input-number
|
||||
v-model="config.layout_side_item_height"
|
||||
:min="30"
|
||||
:max="50"
|
||||
></el-input-number>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<el-alert type="warning" :closable="false">
|
||||
请注意,所有配置请保存到本地文件的 <el-tag>config.json</el-tag> 文件中,否则刷新页面后会丢失配置
|
||||
请注意,所有配置请保存到本地文件的
|
||||
<el-tag>config.json</el-tag> 文件中,否则刷新页面后会丢失配置
|
||||
</el-alert>
|
||||
|
||||
<el-button type="primary" class="mt-4 " @click="copyConfig">复制配置json</el-button>
|
||||
<el-button type="primary" class="mt-4" @click="copyConfig"
|
||||
>复制配置json</el-button
|
||||
>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useAppStore } from "@/pinia"
|
||||
import { storeToRefs } from "pinia"
|
||||
import { ref, computed } from "vue"
|
||||
import { ElMessage } from 'element-plus'
|
||||
const appStore = useAppStore()
|
||||
const { config, device } = storeToRefs(appStore)
|
||||
import { useAppStore } from "@/pinia";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
const appStore = useAppStore();
|
||||
const { config, device } = storeToRefs(appStore);
|
||||
defineOptions({
|
||||
name: 'GvaSetting',
|
||||
})
|
||||
name: "GvaSetting",
|
||||
});
|
||||
|
||||
const width = computed(() => {
|
||||
return device.value === 'mobile' ? '100%' : '500px'
|
||||
})
|
||||
return device.value === "mobile" ? "100%" : "500px";
|
||||
});
|
||||
|
||||
const colors = [
|
||||
'#EB2F96',
|
||||
'#3b82f6',
|
||||
'#2FEB54',
|
||||
'#EBEB2F',
|
||||
'#EB2F2F',
|
||||
'#2FEBEB',
|
||||
]
|
||||
"#EB2F96",
|
||||
"#3b82f6",
|
||||
"#2FEB54",
|
||||
"#EBEB2F",
|
||||
"#EB2F2F",
|
||||
"#2FEBEB",
|
||||
];
|
||||
|
||||
const drawer = defineModel('drawer',{
|
||||
const drawer = defineModel("drawer", {
|
||||
default: true,
|
||||
type : Boolean
|
||||
})
|
||||
type: Boolean,
|
||||
});
|
||||
|
||||
const options = ['dark','light','auto']
|
||||
const options = ["dark", "light", "auto"];
|
||||
const sideModes = [
|
||||
{
|
||||
label : "正常模式",
|
||||
value : "normal"
|
||||
},
|
||||
{
|
||||
label : "顶部菜单栏模式",
|
||||
value: "head"
|
||||
}
|
||||
];
|
||||
|
||||
const copyConfig = () => {
|
||||
const input = document.createElement('textarea')
|
||||
input.value = JSON.stringify(config.value)
|
||||
const input = document.createElement("textarea");
|
||||
input.value = JSON.stringify(config.value);
|
||||
// 添加回车
|
||||
input.value = input.value.replace(/,/g, ',\n')
|
||||
document.body.appendChild(input)
|
||||
input.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(input)
|
||||
ElMessage.success('复制成功, 请自行保存到本地文件中')
|
||||
}
|
||||
input.value = input.value.replace(/,/g, ",\n");
|
||||
document.body.appendChild(input);
|
||||
input.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(input);
|
||||
ElMessage.success("复制成功, 请自行保存到本地文件中");
|
||||
};
|
||||
|
||||
const customColor = ref("")
|
||||
const customColor = ref("");
|
||||
|
||||
const handleSideModelChange = (e) => {
|
||||
console.log(e);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep(.el-drawer__header){
|
||||
::v-deep(.el-drawer__header) {
|
||||
@apply border-gray-400 dark:border-gray-600;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user