release: update 2.8.0
This commit is contained in:
@@ -27,12 +27,23 @@ const transitions = computed(() => {
|
||||
});
|
||||
|
||||
const hideTabs = computed(() => {
|
||||
return instance?.sets.hideTabs;
|
||||
return instance?.configure.hideTabs;
|
||||
});
|
||||
|
||||
const layout = computed(() => {
|
||||
return instance?.layout.layout === "vertical";
|
||||
});
|
||||
|
||||
const getSectionStyle = computed(() => {
|
||||
return [
|
||||
hideTabs.value && layout ? "padding-top: 48px;" : "",
|
||||
!hideTabs.value && layout ? "padding-top: 85px;" : "",
|
||||
hideTabs.value && !layout.value ? "padding-top: 48px" : "",
|
||||
!hideTabs.value && !layout.value ? "padding-top: 85px;" : "",
|
||||
props.fixedHeader ? "" : "padding-top: 0;"
|
||||
];
|
||||
});
|
||||
|
||||
const transitionMain = defineComponent({
|
||||
render() {
|
||||
return h(
|
||||
@@ -71,12 +82,7 @@ const transitionMain = defineComponent({
|
||||
<template>
|
||||
<section
|
||||
:class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
|
||||
:style="[
|
||||
hideTabs && layout ? 'padding-top: 48px;' : '',
|
||||
!hideTabs && layout ? 'padding-top: 85px;' : '',
|
||||
hideTabs && !layout ? 'padding-top: 48px' : '',
|
||||
!hideTabs && !layout ? 'padding-top: 85px;' : ''
|
||||
]"
|
||||
:style="getSectionStyle"
|
||||
>
|
||||
<router-view>
|
||||
<template #default="{ Component, route }">
|
||||
|
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
import Notice from "./notice/index.vue";
|
||||
@@ -22,6 +23,15 @@ const route = useRoute();
|
||||
let usename = storageSession.getItem("info")?.username;
|
||||
const { locale } = useI18n();
|
||||
|
||||
const getDropdownItemStyle = computed(() => {
|
||||
return t => {
|
||||
return {
|
||||
background: locale.value === t ? "#1b2a47" : "",
|
||||
color: locale.value === t ? "#f4f4f5" : "#000"
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
() => locale.value,
|
||||
() => {
|
||||
@@ -73,29 +83,23 @@ function translationEn() {
|
||||
|
||||
<div class="vertical-header-right">
|
||||
<!-- 通知 -->
|
||||
<Notice />
|
||||
<Notice id="header-notice" />
|
||||
<!-- 全屏 -->
|
||||
<screenfull v-show="!deviceDetection()" />
|
||||
<screenfull id="header-screenfull" v-show="!deviceDetection()" />
|
||||
<!-- 国际化 -->
|
||||
<el-dropdown trigger="click">
|
||||
<el-dropdown id="header-translation" trigger="click">
|
||||
<globalization />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'zh' ? '#1b2a47' : '',
|
||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('zh')"
|
||||
@click="translationCh"
|
||||
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||
><check /></el-icon
|
||||
>简体中文</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'en' ? '#1b2a47' : '',
|
||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('en')"
|
||||
@click="translationEn"
|
||||
><el-icon class="check-en" v-show="locale === 'en'"
|
||||
><check /></el-icon
|
||||
@@ -114,14 +118,14 @@ function translationEn() {
|
||||
<el-dropdown-menu class="logout">
|
||||
<el-dropdown-item @click="logout">
|
||||
<i class="ri-logout-circle-r-line"></i
|
||||
>{{ $t("message.hsLoginOut") }}</el-dropdown-item
|
||||
>{{ $t("buttons.hsLoginOut") }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-icon
|
||||
class="el-icon-setting"
|
||||
:title="$t('message.hssystemSet')"
|
||||
:title="$t('buttons.hssystemSet')"
|
||||
@click="onPanel"
|
||||
>
|
||||
<Setting />
|
||||
@@ -230,7 +234,7 @@ function translationEn() {
|
||||
|
||||
.translation {
|
||||
.el-dropdown-menu__item {
|
||||
padding: 0 40px !important;
|
||||
padding: 5px 40px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
@@ -242,12 +246,10 @@ function translationEn() {
|
||||
.check-zh {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.check-en {
|
||||
position: absolute;
|
||||
bottom: 13px;
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
@@ -259,7 +261,6 @@ function translationEn() {
|
||||
min-width: 100%;
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 18px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
|
@@ -8,8 +8,8 @@ const { isFullscreen, toggle } = useFullscreen();
|
||||
<i
|
||||
:title="
|
||||
isFullscreen
|
||||
? $t('message.hsexitfullscreen')
|
||||
: $t('message.hsfullscreen')
|
||||
? $t('buttons.hsexitfullscreen')
|
||||
: $t('buttons.hsfullscreen')
|
||||
"
|
||||
:class="
|
||||
isFullscreen
|
||||
|
@@ -11,9 +11,9 @@ import {
|
||||
} from "vue";
|
||||
import rgbHex from "rgb-hex";
|
||||
import { find } from "lodash-es";
|
||||
import panel from "../panel/index.vue";
|
||||
import { getConfig } from "/@/config";
|
||||
import { useRouter } from "vue-router";
|
||||
import panel from "../panel/index.vue";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
import { templateRef } from "@vueuse/core";
|
||||
import dayIcon from "/@/assets/svg/day.svg";
|
||||
@@ -79,19 +79,33 @@ if (unref(layoutTheme)) {
|
||||
}
|
||||
|
||||
// 默认灵动模式
|
||||
const markValue = ref(storageLocal.getItem("showModel") || "smart");
|
||||
const markValue = ref(instance.configure?.showModel ?? "smart");
|
||||
|
||||
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
|
||||
const logoVal = ref(instance.configure?.showLogo ?? true);
|
||||
|
||||
const epThemeColor = ref(useEpThemeStoreHook().getEpThemeColor);
|
||||
|
||||
const settings = reactive({
|
||||
greyVal: instance.sets.grey,
|
||||
weakVal: instance.sets.weak,
|
||||
tabsVal: instance.sets.hideTabs,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
greyVal: instance.configure.grey,
|
||||
weakVal: instance.configure.weak,
|
||||
tabsVal: instance.configure.hideTabs,
|
||||
showLogo: instance.configure.showLogo,
|
||||
showModel: instance.configure.showModel,
|
||||
multiTagsCache: instance.configure.multiTagsCache
|
||||
});
|
||||
|
||||
const getThemeColorStyle = computed(() => {
|
||||
return rgb => {
|
||||
return { background: `rgb(${rgb})` };
|
||||
};
|
||||
});
|
||||
|
||||
function changeStorageConfigure(key, val) {
|
||||
const storageConfigure = instance.configure;
|
||||
storageConfigure[key] = val;
|
||||
instance.configure = storageConfigure;
|
||||
}
|
||||
|
||||
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
||||
const targetEl = target || document.body;
|
||||
let { className } = targetEl;
|
||||
@@ -102,12 +116,7 @@ function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
||||
// 灰色模式设置
|
||||
const greyChange = (value): void => {
|
||||
toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
|
||||
instance.sets = {
|
||||
grey: value,
|
||||
weak: instance.sets.weak,
|
||||
hideTabs: instance.sets.hideTabs,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("grey", value);
|
||||
};
|
||||
|
||||
// 色弱模式设置
|
||||
@@ -117,33 +126,18 @@ const weekChange = (value): void => {
|
||||
"html-weakness",
|
||||
document.querySelector("html")
|
||||
);
|
||||
instance.sets = {
|
||||
grey: instance.sets.grey,
|
||||
weak: value,
|
||||
hideTabs: instance.sets.hideTabs,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("weak", value);
|
||||
};
|
||||
|
||||
const tagsChange = () => {
|
||||
let showVal = settings.tabsVal;
|
||||
instance.sets = {
|
||||
grey: instance.sets.grey,
|
||||
weak: instance.sets.weak,
|
||||
hideTabs: showVal,
|
||||
multiTagsCache: instance.sets.multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("hideTabs", showVal);
|
||||
emitter.emit("tagViewsChange", showVal);
|
||||
};
|
||||
|
||||
const multiTagsCacheChange = () => {
|
||||
let multiTagsCache = settings.multiTagsCache;
|
||||
instance.sets = {
|
||||
grey: instance.sets.grey,
|
||||
weak: instance.sets.weak,
|
||||
hideTabs: instance.sets.hideTabs,
|
||||
multiTagsCache: multiTagsCache
|
||||
};
|
||||
changeStorageConfigure("multiTagsCache", multiTagsCache);
|
||||
useMultiTagsStoreHook().multiTagsCacheChange(multiTagsCache);
|
||||
};
|
||||
|
||||
@@ -160,30 +154,30 @@ function onReset() {
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
icon: "el-icon-s-home",
|
||||
title: "menus.hshome",
|
||||
icon: "HomeFilled",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
}
|
||||
]);
|
||||
useMultiTagsStoreHook().multiTagsCacheChange(getConfig().MultiTagsCache);
|
||||
useEpThemeStoreHook().setEpThemeColor("#409EFF");
|
||||
useEpThemeStoreHook().setEpThemeColor(getConfig().EpThemeColor);
|
||||
storageLocal.clear();
|
||||
storageSession.clear();
|
||||
router.push("/login");
|
||||
}
|
||||
|
||||
function onChange(label) {
|
||||
storageLocal.setItem("showModel", label);
|
||||
changeStorageConfigure("showModel", label);
|
||||
emitter.emit("tagViewsShowModel", label);
|
||||
}
|
||||
|
||||
// 侧边栏Logo
|
||||
function logoChange() {
|
||||
unref(logoVal) === "1"
|
||||
? storageLocal.setItem("logoVal", "1")
|
||||
: storageLocal.setItem("logoVal", "-1");
|
||||
unref(logoVal)
|
||||
? changeStorageConfigure("showLogo", true)
|
||||
: changeStorageConfigure("showLogo", false);
|
||||
emitter.emit("logoChange", unref(logoVal));
|
||||
}
|
||||
|
||||
@@ -232,13 +226,19 @@ function setLayoutModel(layout: string) {
|
||||
instance.layout = {
|
||||
layout,
|
||||
theme: layoutTheme.value.theme,
|
||||
darkMode: instance.layout.darkMode
|
||||
darkMode: instance.layout.darkMode,
|
||||
sidebarStatus: instance.layout.sidebarStatus,
|
||||
epThemeColor: instance.layout.epThemeColor
|
||||
};
|
||||
useAppStoreHook().setLayout(layout);
|
||||
}
|
||||
|
||||
// 存放夜间主题切换前的导航主题色
|
||||
let tempLayoutThemeColor;
|
||||
|
||||
// 设置导航主题色
|
||||
function setLayoutThemeColor(theme: string) {
|
||||
tempLayoutThemeColor = instance.layout.theme;
|
||||
layoutTheme.value.theme = theme;
|
||||
toggleTheme({
|
||||
scopeName: `layout-theme-${theme}`
|
||||
@@ -246,11 +246,13 @@ function setLayoutThemeColor(theme: string) {
|
||||
instance.layout = {
|
||||
layout: useAppStoreHook().layout,
|
||||
theme,
|
||||
darkMode: dataTheme.value
|
||||
darkMode: dataTheme.value,
|
||||
sidebarStatus: instance.layout.sidebarStatus,
|
||||
epThemeColor: instance.layout.epThemeColor
|
||||
};
|
||||
|
||||
if (theme === "default" || theme === "light") {
|
||||
setEpThemeColor("#409EFF");
|
||||
setEpThemeColor(getConfig().EpThemeColor);
|
||||
} else {
|
||||
const colors = find(themeColors.value, { themeColor: theme });
|
||||
const color = "#" + rgbHex(colors.rgb);
|
||||
@@ -274,10 +276,13 @@ function dataThemeChange() {
|
||||
setLayoutThemeColor("light");
|
||||
} else {
|
||||
body.setAttribute("data-theme", "");
|
||||
tempLayoutThemeColor && setLayoutThemeColor(tempLayoutThemeColor);
|
||||
instance.layout = {
|
||||
layout: useAppStoreHook().layout,
|
||||
theme: instance.layout.theme,
|
||||
darkMode: dataTheme.value
|
||||
darkMode: dataTheme.value,
|
||||
sidebarStatus: instance.layout.sidebarStatus,
|
||||
epThemeColor: instance.layout.epThemeColor
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -338,7 +343,7 @@ nextTick(() => {
|
||||
<li
|
||||
v-for="(item, index) in themeColors"
|
||||
:key="index"
|
||||
:style="{ background: `rgb(${item.rgb})` }"
|
||||
:style="getThemeColorStyle(item.rgb)"
|
||||
@click="setLayoutThemeColor(item.themeColor)"
|
||||
>
|
||||
<el-icon
|
||||
@@ -394,8 +399,8 @@ nextTick(() => {
|
||||
<el-switch
|
||||
v-model="logoVal"
|
||||
inline-prompt
|
||||
active-value="1"
|
||||
inactive-value="-1"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
inactive-color="#a6a6a6"
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
|
@@ -65,7 +65,7 @@ const getBreadcrumb = (): void => {
|
||||
{
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: { title: "message.hshome", i18n: true }
|
||||
meta: { title: "menus.hshome", i18n: true }
|
||||
} as unknown as RouteLocationMatched
|
||||
].concat(matched);
|
||||
}
|
||||
|
@@ -35,6 +35,15 @@ const routers = useRouter().options.routes;
|
||||
let usename = storageSession.getItem("info")?.username;
|
||||
const { locale, t } = useI18n();
|
||||
|
||||
const getDropdownItemStyle = computed(() => {
|
||||
return t => {
|
||||
return {
|
||||
background: locale.value === t ? "#1b2a47" : "",
|
||||
color: locale.value === t ? "#f4f4f5" : "#000"
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
() => locale.value,
|
||||
() => {
|
||||
@@ -140,29 +149,23 @@ onMounted(() => {
|
||||
</el-menu>
|
||||
<div class="horizontal-header-right">
|
||||
<!-- 通知 -->
|
||||
<Notice />
|
||||
<Notice id="header-notice" />
|
||||
<!-- 全屏 -->
|
||||
<screenfull v-show="!deviceDetection()" />
|
||||
<screenfull id="header-screenfull" v-show="!deviceDetection()" />
|
||||
<!-- 国际化 -->
|
||||
<el-dropdown trigger="click">
|
||||
<el-dropdown id="header-translation" trigger="click">
|
||||
<globalization />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'zh' ? '#1b2a47' : '',
|
||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('zh')"
|
||||
@click="translationCh"
|
||||
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||
><check /></el-icon
|
||||
>简体中文</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
:style="{
|
||||
background: locale === 'en' ? '#1b2a47' : '',
|
||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
:style="getDropdownItemStyle('en')"
|
||||
@click="translationEn"
|
||||
><el-icon class="check-en" v-show="locale === 'en'"
|
||||
><check /></el-icon
|
||||
@@ -181,14 +184,14 @@ onMounted(() => {
|
||||
<el-dropdown-menu class="logout">
|
||||
<el-dropdown-item @click="logout">
|
||||
<i class="ri-logout-circle-r-line"></i
|
||||
>{{ $t("message.hsLoginOut") }}</el-dropdown-item
|
||||
>{{ $t("buttons.hsLoginOut") }}</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-icon
|
||||
class="el-icon-setting"
|
||||
:title="$t('message.hssystemSet')"
|
||||
:title="$t('buttons.hssystemSet')"
|
||||
@click="onPanel"
|
||||
>
|
||||
<Setting />
|
||||
@@ -200,7 +203,7 @@ onMounted(() => {
|
||||
<style lang="scss" scoped>
|
||||
.translation {
|
||||
.el-dropdown-menu__item {
|
||||
padding: 0 40px !important;
|
||||
padding: 5px 40px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
@@ -212,12 +215,10 @@ onMounted(() => {
|
||||
.check-zh {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.check-en {
|
||||
position: absolute;
|
||||
bottom: 13px;
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
@@ -229,7 +230,6 @@ onMounted(() => {
|
||||
min-width: 100%;
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 18px !important;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item:focus,
|
||||
|
@@ -1,11 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
ref,
|
||||
PropType,
|
||||
nextTick,
|
||||
computed,
|
||||
CSSProperties,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import path from "path";
|
||||
import { PropType, ref, nextTick, getCurrentInstance } from "vue";
|
||||
import { childrenType } from "../../types";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||
import { transformI18n } from "/@/plugins/i18n";
|
||||
import { findIconReg } from "/@/components/ReIcon";
|
||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
|
||||
const instance = getCurrentInstance().appContext.app.config.globalProperties;
|
||||
const menuMode = instance.$storage.layout?.layout === "vertical";
|
||||
const pureApp = useAppStoreHook();
|
||||
@@ -24,6 +32,48 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const getNoDropdownStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
display: "flex",
|
||||
alignItems: "center"
|
||||
};
|
||||
});
|
||||
|
||||
const getDivStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: pureApp.sidebar.opened ? "" : "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
overflow: "hidden"
|
||||
};
|
||||
});
|
||||
|
||||
const getMenuTextStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: pureApp.sidebar.opened ? "125px" : "",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
outline: "none"
|
||||
};
|
||||
});
|
||||
|
||||
const getSubTextStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: pureApp.sidebar.opened ? "125px" : "",
|
||||
display: "inline-block",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis"
|
||||
};
|
||||
});
|
||||
|
||||
const getSpanStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis"
|
||||
};
|
||||
});
|
||||
|
||||
const onlyOneChild: childrenType = ref(null);
|
||||
// 存放菜单是否存在showTooltip属性标识
|
||||
const hoverMenuMap = new WeakMap();
|
||||
@@ -88,7 +138,7 @@ function resolvePath(routePath) {
|
||||
<el-menu-item
|
||||
:index="resolvePath(onlyOneChild.path)"
|
||||
:class="{ 'submenu-title-noDropdown': !isNest }"
|
||||
style="display: flex; align-items: center"
|
||||
:style="getNoDropdownStyle"
|
||||
>
|
||||
<el-icon v-show="props.item.meta.icon">
|
||||
<component
|
||||
@@ -101,15 +151,7 @@ function resolvePath(routePath) {
|
||||
></component>
|
||||
</el-icon>
|
||||
<template #title>
|
||||
<div
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '' : '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
overflow: 'hidden'
|
||||
}"
|
||||
>
|
||||
<div :style="getDivStyle">
|
||||
<span v-if="!menuMode">{{
|
||||
transformI18n(onlyOneChild.meta.title, onlyOneChild.meta.i18n)
|
||||
}}</span>
|
||||
@@ -126,12 +168,7 @@ function resolvePath(routePath) {
|
||||
</template>
|
||||
<span
|
||||
ref="menuTextRef"
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '125px' : '',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
outline: 'none'
|
||||
}"
|
||||
:style="getMenuTextStyle"
|
||||
@mouseover="hoverMenu(onlyOneChild)"
|
||||
>
|
||||
{{
|
||||
@@ -175,15 +212,10 @@ function resolvePath(routePath) {
|
||||
</template>
|
||||
<div
|
||||
ref="menuTextRef"
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '125px' : '',
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}"
|
||||
:style="getSubTextStyle"
|
||||
@mouseover="hoverMenu(props.item)"
|
||||
>
|
||||
<span style="overflow: hidden; text-overflow: ellipsis">
|
||||
<span :style="getSpanStyle">
|
||||
{{ transformI18n(props.item.meta.title, props.item.meta.i18n) }}
|
||||
</span>
|
||||
</div>
|
||||
|
@@ -12,7 +12,9 @@ import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
const route = useRoute();
|
||||
const pureApp = useAppStoreHook();
|
||||
const router = useRouter().options.routes;
|
||||
const showLogo = ref(storageLocal.getItem("logoVal") || "1");
|
||||
const showLogo = ref(
|
||||
storageLocal.getItem("responsive-configure")?.showLogo ?? true
|
||||
);
|
||||
const isCollapse = computed(() => {
|
||||
return !pureApp.getSidebarStatus;
|
||||
});
|
||||
@@ -58,7 +60,7 @@ onBeforeMount(() => {
|
||||
|
||||
<template>
|
||||
<div :class="['sidebar-container', showLogo ? 'has-logo' : '']">
|
||||
<Logo v-if="showLogo === '1'" :collapse="isCollapse" />
|
||||
<Logo v-if="showLogo" :collapse="isCollapse" />
|
||||
<el-scrollbar wrap-class="scrollbar-wrapper">
|
||||
<el-menu
|
||||
:default-active="activeMenu"
|
||||
|
@@ -207,7 +207,6 @@
|
||||
li {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0 12px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@@ -2,12 +2,13 @@
|
||||
import {
|
||||
ref,
|
||||
watch,
|
||||
onBeforeMount,
|
||||
unref,
|
||||
nextTick,
|
||||
computed,
|
||||
getCurrentInstance,
|
||||
ComputedRef
|
||||
ComputedRef,
|
||||
CSSProperties,
|
||||
onBeforeMount,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
|
||||
import close from "/@/assets/svg/close.svg";
|
||||
@@ -17,6 +18,7 @@ import closeLeft from "/@/assets/svg/close_left.svg";
|
||||
import closeOther from "/@/assets/svg/close_other.svg";
|
||||
import closeRight from "/@/assets/svg/close_right.svg";
|
||||
|
||||
import { $t as t } from "/@/plugins/i18n";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
import { isEqual, isEmpty } from "lodash-es";
|
||||
import { transformI18n } from "/@/plugins/i18n";
|
||||
@@ -187,42 +189,42 @@ const handleScroll = (offset: number): void => {
|
||||
const tagsViews = ref<Array<tagsViewsType>>([
|
||||
{
|
||||
icon: refresh,
|
||||
text: "message.hsreload",
|
||||
text: t("buttons.hsreload"),
|
||||
divided: false,
|
||||
disabled: false,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: close,
|
||||
text: "message.hscloseCurrentTab",
|
||||
text: t("buttons.hscloseCurrentTab"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeLeft,
|
||||
text: "message.hscloseLeftTabs",
|
||||
text: t("buttons.hscloseLeftTabs"),
|
||||
divided: true,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeRight,
|
||||
text: "message.hscloseRightTabs",
|
||||
text: t("buttons.hscloseRightTabs"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeOther,
|
||||
text: "message.hscloseOtherTabs",
|
||||
text: t("buttons.hscloseOtherTabs"),
|
||||
divided: true,
|
||||
disabled: multiTags.value.length > 2 ? false : true,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
icon: closeAll,
|
||||
text: "message.hscloseAllTabs",
|
||||
text: t("buttons.hscloseAllTabs"),
|
||||
divided: false,
|
||||
disabled: multiTags.value.length > 1 ? false : true,
|
||||
show: true
|
||||
@@ -230,9 +232,13 @@ const tagsViews = ref<Array<tagsViewsType>>([
|
||||
]);
|
||||
|
||||
// 显示模式,默认灵动模式显示
|
||||
const showModel = ref(storageLocal.getItem("showModel") || "smart");
|
||||
const showModel = ref(
|
||||
storageLocal.getItem("responsive-configure")?.showModel || "smart"
|
||||
);
|
||||
if (!showModel.value) {
|
||||
storageLocal.setItem("showModel", "card");
|
||||
const configure = storageLocal.getItem("responsive-configure");
|
||||
configure.showModel = "card";
|
||||
storageLocal.setItem("responsive-configure", configure);
|
||||
}
|
||||
|
||||
let visible = ref(false);
|
||||
@@ -306,7 +312,7 @@ function deleteDynamicTag(obj: any, current: any, tag?: string) {
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: "menus.hshome",
|
||||
i18n: true,
|
||||
icon: "el-icon-s-home",
|
||||
showLink: true
|
||||
@@ -609,17 +615,23 @@ onBeforeMount(() => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const getTabStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
transform: `translateX(${translateX.value}px)`
|
||||
};
|
||||
});
|
||||
|
||||
const getContextMenuStyle = computed((): CSSProperties => {
|
||||
return { left: buttonLeft.value + "px", top: buttonTop.value + "px" };
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="containerDom" class="tags-view" v-if="!showTags">
|
||||
<i class="ri-arrow-left-s-line" @click="handleScroll(200)"></i>
|
||||
<div ref="scrollbarDom" class="scroll-container">
|
||||
<div
|
||||
class="tab"
|
||||
ref="tabDom"
|
||||
:style="{ transform: `translateX(${translateX}px)` }"
|
||||
>
|
||||
<div class="tab" ref="tabDom" :style="getTabStyle">
|
||||
<div
|
||||
:ref="'dynamic' + index"
|
||||
v-for="(item, index) in multiTags"
|
||||
@@ -663,7 +675,7 @@ onBeforeMount(() => {
|
||||
<ul
|
||||
v-show="visible"
|
||||
:key="Math.random()"
|
||||
:style="{ left: buttonLeft + 'px', top: buttonTop + 'px' }"
|
||||
:style="getContextMenuStyle"
|
||||
class="contextmenu"
|
||||
>
|
||||
<div
|
||||
@@ -682,7 +694,7 @@ onBeforeMount(() => {
|
||||
<ul class="right-button">
|
||||
<li>
|
||||
<el-icon
|
||||
:title="$t('message.hsrefreshRoute')"
|
||||
:title="$t('buttons.hsrefreshRoute')"
|
||||
class="el-icon-refresh-right rotate"
|
||||
@click="onFresh"
|
||||
>
|
||||
|
@@ -16,8 +16,8 @@ import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import fullScreen from "/@/assets/svg/full_screen.svg";
|
||||
import exitScreen from "/@/assets/svg/exit_screen.svg";
|
||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||
import { useSettingStoreHook } from "/@/store/modules/settings";
|
||||
import { useMultiTagsStore } from "/@/store/modules/multiTags";
|
||||
import { useSettingStoreHook } from "/@/store/modules/settings";
|
||||
|
||||
import navbar from "./components/navbar.vue";
|
||||
import tag from "./components/tag/index.vue";
|
||||
@@ -52,16 +52,20 @@ const layout = computed(() => {
|
||||
instance.$storage.layout = {
|
||||
layout: instance.$config?.Layout ?? "vertical",
|
||||
theme: instance.$config?.Theme ?? "default",
|
||||
darkMode: instance.$config?.DarkMode ?? false
|
||||
darkMode: instance.$config?.DarkMode ?? false,
|
||||
sidebarStatus: instance.$config?.SidebarStatus ?? true,
|
||||
epThemeColor: instance.$config?.EpThemeColor ?? "#409EFF"
|
||||
};
|
||||
}
|
||||
// 灰色模式、色弱模式、隐藏标签页
|
||||
if (!instance.$storage.sets) {
|
||||
if (!instance.$storage.configure) {
|
||||
// eslint-disable-next-line
|
||||
instance.$storage.sets = {
|
||||
instance.$storage.configure = {
|
||||
grey: instance.$config?.Grey ?? false,
|
||||
weak: instance.$config?.Weak ?? false,
|
||||
hideTabs: instance.$config?.HideTabs ?? false,
|
||||
showLogo: instance.$config?.ShowLogo ?? true,
|
||||
showModel: instance.$config?.ShowModel ?? "smart",
|
||||
multiTagsCache: instance.$config?.MultiTagsCache ?? false
|
||||
};
|
||||
}
|
||||
@@ -91,7 +95,7 @@ const set: setType = reactive({
|
||||
}),
|
||||
|
||||
hideTabs: computed(() => {
|
||||
return instance.$storage?.sets.hideTabs;
|
||||
return instance.$storage?.configure.hideTabs;
|
||||
})
|
||||
});
|
||||
|
||||
@@ -100,7 +104,9 @@ function setTheme(layoutModel: string) {
|
||||
instance.$storage.layout = {
|
||||
layout: `${layoutModel}`,
|
||||
theme: instance.$storage.layout?.theme,
|
||||
darkMode: instance.$storage.layout?.darkMode
|
||||
darkMode: instance.$storage.layout?.darkMode,
|
||||
sidebarStatus: instance.$storage.layout?.sidebarStatus,
|
||||
epThemeColor: instance.$storage.layout?.epThemeColor
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -3,9 +3,9 @@ export const routerArrays: Array<RouteConfigs> = [
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: "menus.hshome",
|
||||
i18n: true,
|
||||
icon: "el-icon-s-home",
|
||||
icon: "HomeFilled",
|
||||
showLink: true
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,7 @@ import {
|
||||
ElEmpty,
|
||||
ElCollapse,
|
||||
ElCollapseItem,
|
||||
ElTreeV2,
|
||||
// 指令
|
||||
ElLoading,
|
||||
ElInfiniteScroll
|
||||
@@ -94,7 +95,8 @@ const components = [
|
||||
ElAvatar,
|
||||
ElEmpty,
|
||||
ElCollapse,
|
||||
ElCollapseItem
|
||||
ElCollapseItem,
|
||||
ElTreeV2
|
||||
];
|
||||
|
||||
// https://element-plus.org/zh-CN/component/icon.html
|
||||
@@ -113,7 +115,14 @@ import {
|
||||
ArrowDown,
|
||||
Close,
|
||||
CloseBold,
|
||||
Bell
|
||||
Bell,
|
||||
Guide,
|
||||
User,
|
||||
Iphone,
|
||||
Location,
|
||||
Tickets,
|
||||
OfficeBuilding,
|
||||
Notebook
|
||||
} from "@element-plus/icons-vue";
|
||||
|
||||
// Icon
|
||||
@@ -132,7 +141,14 @@ export const iconComponents = [
|
||||
ArrowDown,
|
||||
Close,
|
||||
CloseBold,
|
||||
Bell
|
||||
Bell,
|
||||
Guide,
|
||||
User,
|
||||
Iphone,
|
||||
Location,
|
||||
Tickets,
|
||||
OfficeBuilding,
|
||||
Notebook
|
||||
];
|
||||
|
||||
export function useElementPlus(app: App) {
|
||||
|
@@ -1,104 +1,20 @@
|
||||
import { siphonI18n } from "./index";
|
||||
|
||||
// element-plus国际化
|
||||
import enLocale from "element-plus/lib/locale/lang/en";
|
||||
import zhLocale from "element-plus/lib/locale/lang/zh-cn";
|
||||
|
||||
// 导航菜单配置
|
||||
export const menusConfig = {
|
||||
zh: {
|
||||
message: {
|
||||
hshome: "首页",
|
||||
hserror: "错误页面",
|
||||
hsfourZeroFour: "404",
|
||||
hsfourZeroOne: "401",
|
||||
permission: "权限管理",
|
||||
permissionPage: "页面权限",
|
||||
permissionButton: "按钮权限",
|
||||
externalLink: "外链"
|
||||
}
|
||||
},
|
||||
en: {
|
||||
message: {
|
||||
hshome: "Home",
|
||||
hserror: "Error Page",
|
||||
hsfourZeroFour: "404",
|
||||
hsfourZeroOne: "401",
|
||||
permission: "Permission Manage",
|
||||
permissionPage: "Page Permission",
|
||||
permissionButton: "Button Permission",
|
||||
externalLink: "External Link"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 按钮配置
|
||||
export const buttonConfig = {
|
||||
zh: {
|
||||
message: {
|
||||
hsLoginOut: "退出系统",
|
||||
hsfullscreen: "全屏",
|
||||
hsexitfullscreen: "退出全屏",
|
||||
hsrefreshRoute: "刷新路由",
|
||||
hslogin: "登陆",
|
||||
hsadd: "新增",
|
||||
hsmark: "标记/取消",
|
||||
hssave: "保存",
|
||||
hssearch: "搜索",
|
||||
hsexpendAll: "全部展开",
|
||||
hscollapseAll: "全部折叠",
|
||||
hssystemSet: "打开项目配置",
|
||||
hsdelete: "删除",
|
||||
hsreload: "重新加载",
|
||||
hscloseCurrentTab: "关闭当前标签页",
|
||||
hscloseLeftTabs: "关闭左侧标签页",
|
||||
hscloseRightTabs: "关闭右侧标签页",
|
||||
hscloseOtherTabs: "关闭其他标签页",
|
||||
hscloseAllTabs: "关闭全部标签页"
|
||||
}
|
||||
},
|
||||
en: {
|
||||
message: {
|
||||
hsLoginOut: "loginOut",
|
||||
hsfullscreen: "fullScreen",
|
||||
hsexitfullscreen: "exitFullscreen",
|
||||
hsrefreshRoute: "refreshRoute",
|
||||
hslogin: "login",
|
||||
hsadd: "Add",
|
||||
hsmark: "Mark/Cancel",
|
||||
hssave: "Save",
|
||||
hssearch: "Search",
|
||||
hsexpendAll: "Expand All",
|
||||
hscollapseAll: "Collapse All",
|
||||
hssystemSet: "Open ProjectConfig",
|
||||
hsdelete: "Delete",
|
||||
hsreload: "Reload",
|
||||
hscloseCurrentTab: "Close CurrentTab",
|
||||
hscloseLeftTabs: "Close LeftTabs",
|
||||
hscloseRightTabs: "Close RightTabs",
|
||||
hscloseOtherTabs: "Close OtherTabs",
|
||||
hscloseAllTabs: "Close AllTabs"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 配置
|
||||
// export const xxxx = {
|
||||
// zh: {
|
||||
// message: {},
|
||||
// },
|
||||
// en: {
|
||||
// message: {},
|
||||
// },
|
||||
// };
|
||||
|
||||
const localesList = [menusConfig, buttonConfig];
|
||||
// 项目内自定义国际化
|
||||
const zhModules = import.meta.globEager("./zh-CN/**/*.ts");
|
||||
const enModules = import.meta.globEager("./en/**/*.ts");
|
||||
|
||||
export const localesConfigs = {
|
||||
zh: {
|
||||
message: Object.assign({}, ...localesList.map(v => v.zh.message)),
|
||||
...siphonI18n(zhModules, "zh-CN"),
|
||||
...zhLocale
|
||||
},
|
||||
en: {
|
||||
message: Object.assign({}, ...localesList.map(v => v.en.message)),
|
||||
...siphonI18n(enModules, "en"),
|
||||
...enLocale
|
||||
}
|
||||
};
|
||||
|
21
src/plugins/i18n/en/buttons.ts
Normal file
21
src/plugins/i18n/en/buttons.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export default {
|
||||
hsLoginOut: "LoginOut",
|
||||
hsfullscreen: "FullScreen",
|
||||
hsexitfullscreen: "ExitFullscreen",
|
||||
hsrefreshRoute: "RefreshRoute",
|
||||
hslogin: "Login",
|
||||
hsadd: "Add",
|
||||
hsmark: "Mark/Cancel",
|
||||
hssave: "Save",
|
||||
hssearch: "Search",
|
||||
hsexpendAll: "Expand All",
|
||||
hscollapseAll: "Collapse All",
|
||||
hssystemSet: "Open ProjectConfig",
|
||||
hsdelete: "Delete",
|
||||
hsreload: "Reload",
|
||||
hscloseCurrentTab: "Close CurrentTab",
|
||||
hscloseLeftTabs: "Close LeftTabs",
|
||||
hscloseRightTabs: "Close RightTabs",
|
||||
hscloseOtherTabs: "Close OtherTabs",
|
||||
hscloseAllTabs: "Close AllTabs"
|
||||
};
|
38
src/plugins/i18n/en/menus.ts
Normal file
38
src/plugins/i18n/en/menus.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export default {
|
||||
hshome: "Home",
|
||||
hslogin: "Login",
|
||||
hssysManagement: "System Manage",
|
||||
hsBaseinfo: "Base Info",
|
||||
hsDict: "Dict Manage",
|
||||
hseditor: "Editor",
|
||||
hserror: "Error Page",
|
||||
hsfourZeroFour: "404",
|
||||
hsfourZeroOne: "401",
|
||||
hscomponents: "Components",
|
||||
hsvideo: "Video Components",
|
||||
hsmap: "Map Components",
|
||||
hsdraggable: "Draggable Components",
|
||||
hssplitPane: "Split Pane",
|
||||
hsbutton: "Button Components",
|
||||
hscropping: "Picture Cropping",
|
||||
hscountTo: "Digital Animation",
|
||||
hsselector: "Selector Components",
|
||||
hsflowChart: "Flow Chart",
|
||||
hsseamless: "Seamless Scroll",
|
||||
hscontextmenu: "Context Menu",
|
||||
hsmenus: "MultiLevel Menu",
|
||||
hsmenu1: "Menu1",
|
||||
"hsmenu1-1": "Menu1-1",
|
||||
"hsmenu1-2": "Menu1-2",
|
||||
"hsmenu1-2-1": "Menu1-2-1",
|
||||
"hsmenu1-2-2": "Menu1-2-2",
|
||||
"hsmenu1-3": "Menu1-3",
|
||||
hsmenu2: "Menu2",
|
||||
permission: "Permission Manage",
|
||||
permissionPage: "Page Permission",
|
||||
permissionButton: "Button Permission",
|
||||
hstabs: "Tabs Operate",
|
||||
hsMenuTree: "Menu Tree",
|
||||
hsguide: "Guide",
|
||||
externalLink: "External Link"
|
||||
};
|
@@ -1,19 +1,10 @@
|
||||
// 多组件库的国际化和本地项目国际化兼容
|
||||
import { App } from "vue";
|
||||
import { set } from "lodash-es";
|
||||
import { createI18n } from "vue-i18n";
|
||||
import { localesConfigs } from "./config";
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
|
||||
export const i18n = createI18n({
|
||||
locale: storageLocal.getItem("responsive-locale")?.locale ?? "zh",
|
||||
fallbackLocale: "en",
|
||||
messages: localesConfigs
|
||||
});
|
||||
|
||||
export function usI18n(app: App) {
|
||||
app.use(i18n);
|
||||
}
|
||||
|
||||
/**
|
||||
* 国际化转换工具函数
|
||||
* @param message message
|
||||
@@ -37,3 +28,47 @@ export function transformI18n(message: string | object = "", isI18n = false) {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从模块中抽取国际化
|
||||
* @param langs 存放国际化模块
|
||||
* @param prefix 语言 默认 zh-CN
|
||||
* @returns obj 格式:{模块名.**}
|
||||
*/
|
||||
export function siphonI18n(
|
||||
langs: Record<string, Record<string, any>>,
|
||||
prefix = "zh-CN"
|
||||
) {
|
||||
const langsObj: Recordable = {};
|
||||
Object.keys(langs).forEach((key: string) => {
|
||||
let fileName = key.replace(`./${prefix}/`, "").replace(/^\.\//, "");
|
||||
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
||||
const keyList = fileName.split("/");
|
||||
const moduleName = keyList.shift();
|
||||
const objKey = keyList.join(".");
|
||||
const langFileModule = langs[key].default;
|
||||
|
||||
if (moduleName) {
|
||||
if (objKey) {
|
||||
set(langsObj, moduleName, langsObj[moduleName] || {});
|
||||
set(langsObj[moduleName], objKey, langFileModule);
|
||||
} else {
|
||||
set(langsObj, moduleName, langFileModule || {});
|
||||
}
|
||||
}
|
||||
});
|
||||
return langsObj;
|
||||
}
|
||||
|
||||
// 此函数只是配合i18n Ally插件来进行国际化智能提示,并无实际意义(只对提示起作用),如果不需要国际化可删除
|
||||
export const $t = (key: string) => key;
|
||||
|
||||
export const i18n = createI18n({
|
||||
locale: storageLocal.getItem("responsive-locale")?.locale ?? "zh",
|
||||
fallbackLocale: "en",
|
||||
messages: localesConfigs
|
||||
});
|
||||
|
||||
export function usI18n(app: App) {
|
||||
app.use(i18n);
|
||||
}
|
||||
|
21
src/plugins/i18n/zh-CN/buttons.ts
Normal file
21
src/plugins/i18n/zh-CN/buttons.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export default {
|
||||
hsLoginOut: "退出系统",
|
||||
hsfullscreen: "全屏",
|
||||
hsexitfullscreen: "退出全屏",
|
||||
hsrefreshRoute: "刷新路由",
|
||||
hslogin: "登陆",
|
||||
hsadd: "新增",
|
||||
hsmark: "标记/取消",
|
||||
hssave: "保存",
|
||||
hssearch: "搜索",
|
||||
hsexpendAll: "全部展开",
|
||||
hscollapseAll: "全部折叠",
|
||||
hssystemSet: "打开项目配置",
|
||||
hsdelete: "删除",
|
||||
hsreload: "重新加载",
|
||||
hscloseCurrentTab: "关闭当前标签页",
|
||||
hscloseLeftTabs: "关闭左侧标签页",
|
||||
hscloseRightTabs: "关闭右侧标签页",
|
||||
hscloseOtherTabs: "关闭其他标签页",
|
||||
hscloseAllTabs: "关闭全部标签页"
|
||||
};
|
38
src/plugins/i18n/zh-CN/menus.ts
Normal file
38
src/plugins/i18n/zh-CN/menus.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export default {
|
||||
hshome: "首页",
|
||||
hslogin: "登陆",
|
||||
hssysManagement: "系统管理",
|
||||
hsBaseinfo: "基础信息",
|
||||
hsDict: "字典管理",
|
||||
hseditor: "编辑器",
|
||||
hserror: "错误页面",
|
||||
hsfourZeroFour: "404",
|
||||
hsfourZeroOne: "401",
|
||||
hscomponents: "组件",
|
||||
hsvideo: "视频组件",
|
||||
hsmap: "地图组件",
|
||||
hsdraggable: "拖拽组件",
|
||||
hssplitPane: "切割面板",
|
||||
hsbutton: "按钮组件",
|
||||
hscropping: "图片裁剪",
|
||||
hscountTo: "数字动画",
|
||||
hsselector: "选择器组件",
|
||||
hsflowChart: "流程图",
|
||||
hsseamless: "无缝滚动",
|
||||
hscontextmenu: "右键菜单",
|
||||
hsmenus: "多级菜单",
|
||||
hsmenu1: "菜单1",
|
||||
"hsmenu1-1": "菜单1-1",
|
||||
"hsmenu1-2": "菜单1-2",
|
||||
"hsmenu1-2-1": "菜单1-2-1",
|
||||
"hsmenu1-2-2": "菜单1-2-2",
|
||||
"hsmenu1-3": "菜单1-3",
|
||||
hsmenu2: "菜单2",
|
||||
permission: "权限管理",
|
||||
permissionPage: "页面权限",
|
||||
permissionButton: "按钮权限",
|
||||
hstabs: "标签页操作",
|
||||
hsMenuTree: "菜单树结构",
|
||||
hsguide: "引导页",
|
||||
externalLink: "外链"
|
||||
};
|
@@ -117,8 +117,9 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
||||
route?.meta?.rank !== 0 &&
|
||||
routePartent.length === 0
|
||||
) {
|
||||
if (!route?.meta?.refreshRedirect) return;
|
||||
const { name, meta } = findRouteByPath(
|
||||
route?.meta?.refreshRedirect,
|
||||
route.meta.refreshRedirect,
|
||||
routes
|
||||
);
|
||||
handTag(
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const errorRouter = {
|
||||
@@ -7,7 +8,7 @@ const errorRouter = {
|
||||
redirect: "/error/401",
|
||||
meta: {
|
||||
icon: "Position",
|
||||
title: "message.hserror",
|
||||
title: $t("menus.hserror"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 7
|
||||
@@ -18,7 +19,7 @@ const errorRouter = {
|
||||
name: "401",
|
||||
component: () => import("/@/views/error/401.vue"),
|
||||
meta: {
|
||||
title: "message.hsfourZeroOne",
|
||||
title: $t("menus.hsfourZeroOne"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
@@ -28,7 +29,7 @@ const errorRouter = {
|
||||
name: "404",
|
||||
component: () => import("/@/views/error/404.vue"),
|
||||
meta: {
|
||||
title: "message.hsfourZeroFour",
|
||||
title: $t("menus.hsfourZeroFour"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const externalLink = {
|
||||
@@ -6,7 +7,7 @@ const externalLink = {
|
||||
component: Layout,
|
||||
meta: {
|
||||
icon: "Link",
|
||||
title: "message.externalLink",
|
||||
title: $t("menus.externalLink"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 190
|
||||
@@ -15,7 +16,7 @@ const externalLink = {
|
||||
{
|
||||
path: "https://github.com/xiaoxian521/vue-pure-admin",
|
||||
meta: {
|
||||
title: "message.externalLink",
|
||||
title: $t("menus.externalLink"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 191
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const homeRouter = {
|
||||
@@ -7,6 +8,7 @@ const homeRouter = {
|
||||
redirect: "/welcome",
|
||||
meta: {
|
||||
icon: "HomeFilled",
|
||||
title: $t("menus.hshome"),
|
||||
showLink: true,
|
||||
i18n: true,
|
||||
rank: 0
|
||||
@@ -17,7 +19,7 @@ const homeRouter = {
|
||||
name: "welcome",
|
||||
component: () => import("/@/views/welcome.vue"),
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: $t("menus.hshome"),
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import { $t } from "/@/plugins/i18n";
|
||||
import Layout from "/@/layout/index.vue";
|
||||
|
||||
const remainingRouter = [
|
||||
@@ -6,7 +7,7 @@ const remainingRouter = [
|
||||
name: "login",
|
||||
component: () => import("/@/views/login.vue"),
|
||||
meta: {
|
||||
title: "message.hslogin",
|
||||
title: $t("menus.hslogin"),
|
||||
showLink: false,
|
||||
i18n: true,
|
||||
rank: 101
|
||||
@@ -18,7 +19,7 @@ const remainingRouter = [
|
||||
component: Layout,
|
||||
meta: {
|
||||
icon: "HomeFilled",
|
||||
title: "message.hshome",
|
||||
title: $t("menus.hshome"),
|
||||
i18n: true,
|
||||
showLink: false,
|
||||
rank: 104
|
||||
|
@@ -13,7 +13,7 @@ import { useTimeoutFn } from "@vueuse/core";
|
||||
import { RouteConfigs } from "/@/layout/types";
|
||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
// https://cn.vitejs.dev/guide/features.html#glob-import
|
||||
const modulesRoutes = import.meta.glob("/src/views/*/*/*.vue");
|
||||
const modulesRoutes = import.meta.glob("/src/views/**/*.{vue,tsx}");
|
||||
|
||||
// 动态路由
|
||||
import { getAsyncRoutes } from "/@/api/routes";
|
||||
@@ -212,11 +212,13 @@ const handleAliveRoute = (matched: RouteRecordNormalized[], mode?: string) => {
|
||||
// 过滤后端传来的动态路由 重新生成规范路由
|
||||
const addAsyncRoutes = (arrRoutes: Array<RouteRecordRaw>) => {
|
||||
if (!arrRoutes || !arrRoutes.length) return;
|
||||
const modulesRoutesKeys = Object.keys(modulesRoutes);
|
||||
arrRoutes.forEach((v: RouteRecordRaw) => {
|
||||
if (v.redirect) {
|
||||
v.component = Layout;
|
||||
} else {
|
||||
v.component = modulesRoutes[`/src/views${v.path}/index.vue`];
|
||||
const index = modulesRoutesKeys.findIndex(ev => ev.includes(v.path));
|
||||
v.component = modulesRoutes[modulesRoutesKeys[index]];
|
||||
}
|
||||
if (v.children) {
|
||||
addAsyncRoutes(v.children);
|
||||
|
@@ -1,17 +1,17 @@
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||
import { store } from "/@/store";
|
||||
import { appType } from "./types";
|
||||
import { defineStore } from "pinia";
|
||||
import { getConfig } from "/@/config";
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||
|
||||
export const useAppStore = defineStore({
|
||||
id: "pure-app",
|
||||
state: (): appType => ({
|
||||
sidebar: {
|
||||
opened: storageLocal.getItem("sidebarStatus")
|
||||
? !!+storageLocal.getItem("sidebarStatus")
|
||||
: true,
|
||||
opened:
|
||||
storageLocal.getItem("responsive-layout")?.sidebarStatus ??
|
||||
getConfig().SidebarStatus,
|
||||
withoutAnimation: false,
|
||||
isClickHamburger: false
|
||||
},
|
||||
@@ -30,20 +30,22 @@ export const useAppStore = defineStore({
|
||||
},
|
||||
actions: {
|
||||
TOGGLE_SIDEBAR(opened?: boolean, resize?: string) {
|
||||
const layout = storageLocal.getItem("responsive-layout");
|
||||
if (opened && resize) {
|
||||
this.sidebar.withoutAnimation = true;
|
||||
this.sidebar.opened = true;
|
||||
storageLocal.setItem("sidebarStatus", true);
|
||||
layout.sidebarStatus = true;
|
||||
} else if (!opened && resize) {
|
||||
this.sidebar.withoutAnimation = true;
|
||||
this.sidebar.opened = false;
|
||||
storageLocal.setItem("sidebarStatus", false);
|
||||
layout.sidebarStatus = false;
|
||||
} else if (!opened && !resize) {
|
||||
this.sidebar.withoutAnimation = false;
|
||||
this.sidebar.opened = !this.sidebar.opened;
|
||||
this.sidebar.isClickHamburger = !this.sidebar.opened;
|
||||
storageLocal.setItem("sidebarStatus", this.sidebar.opened);
|
||||
layout.sidebarStatus = this.sidebar.opened;
|
||||
}
|
||||
storageLocal.setItem("responsive-layout", layout);
|
||||
},
|
||||
TOGGLE_DEVICE(device: string) {
|
||||
this.device = device;
|
||||
|
@@ -1,11 +1,14 @@
|
||||
import { store } from "/@/store";
|
||||
import { defineStore } from "pinia";
|
||||
import { getConfig } from "/@/config";
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
|
||||
export const useEpThemeStore = defineStore({
|
||||
id: "pure-epTheme",
|
||||
state: () => ({
|
||||
epThemeColor: storageLocal.getItem("epThemeColor") || "#409EFF"
|
||||
epThemeColor:
|
||||
storageLocal.getItem("responsive-layout")?.epThemeColor ??
|
||||
getConfig().EpThemeColor
|
||||
}),
|
||||
getters: {
|
||||
getEpThemeColor() {
|
||||
@@ -14,8 +17,10 @@ export const useEpThemeStore = defineStore({
|
||||
},
|
||||
actions: {
|
||||
setEpThemeColor(newColor) {
|
||||
const layout = storageLocal.getItem("responsive-layout");
|
||||
this.epThemeColor = newColor;
|
||||
storageLocal.setItem("epThemeColor", newColor);
|
||||
layout.epThemeColor = newColor;
|
||||
storageLocal.setItem("responsive-layout", layout);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -8,21 +8,21 @@ export const useMultiTagsStore = defineStore({
|
||||
id: "pure-multiTags",
|
||||
state: () => ({
|
||||
// 存储标签页信息(路由信息)
|
||||
multiTags: storageLocal.getItem("responsive-sets").multiTagsCache
|
||||
multiTags: storageLocal.getItem("responsive-configure").multiTagsCache
|
||||
? storageLocal.getItem("responsive-tags")
|
||||
: [
|
||||
{
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
icon: "el-icon-s-home",
|
||||
title: "menus.hshome",
|
||||
icon: "HomeFilled",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
}
|
||||
],
|
||||
multiTagsCache: storageLocal.getItem("responsive-sets").multiTagsCache
|
||||
multiTagsCache: storageLocal.getItem("responsive-configure").multiTagsCache
|
||||
}),
|
||||
getters: {
|
||||
getMultiTagsCache() {
|
||||
|
@@ -58,8 +58,8 @@ export const useUserStore = defineStore({
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
icon: "el-icon-s-home",
|
||||
title: "menus.hshome",
|
||||
icon: "HomeFilled",
|
||||
i18n: true,
|
||||
showLink: true
|
||||
}
|
||||
|
@@ -18,15 +18,19 @@ export const injectResponsiveStorage = (app: App, config: ServerConfigs) => {
|
||||
default: Storage.getData(undefined, "layout") ?? {
|
||||
layout: config.Layout ?? "vertical",
|
||||
theme: config.Theme ?? "default",
|
||||
darkMode: config.DarkMode ?? false
|
||||
darkMode: config.DarkMode ?? false,
|
||||
sidebarStatus: config.SidebarStatus ?? true,
|
||||
epThemeColor: config.EpThemeColor ?? "409EFF"
|
||||
}
|
||||
},
|
||||
sets: {
|
||||
configure: {
|
||||
type: Object,
|
||||
default: Storage.getData(undefined, "sets") ?? {
|
||||
default: Storage.getData(undefined, "configure") ?? {
|
||||
grey: config.Grey ?? false,
|
||||
weak: config.Weak ?? false,
|
||||
hideTabs: config.HideTabs ?? false,
|
||||
showLogo: config.ShowLogo ?? true,
|
||||
showModel: config.ShowModel ?? "smart",
|
||||
multiTagsCache: config.MultiTagsCache ?? false
|
||||
}
|
||||
}
|
||||
@@ -41,7 +45,7 @@ export const injectResponsiveStorage = (app: App, config: ServerConfigs) => {
|
||||
path: "/welcome",
|
||||
parentPath: "/",
|
||||
meta: {
|
||||
title: "message.hshome",
|
||||
title: "menus.hshome",
|
||||
i18n: true,
|
||||
icon: "HomeFilled",
|
||||
showLink: true
|
||||
|
Reference in New Issue
Block a user