feat: 🚀 动态语言类型
This commit is contained in:
parent
d303cbce44
commit
013eb326c3
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"Version": "5.8.0",
|
||||
"Title": "PureAdmin",
|
||||
"Title": "BunnyAdmin",
|
||||
"Copyright": "Copyright © 2020-present",
|
||||
"FixedHeader": true,
|
||||
"HiddenSideBar": false,
|
||||
"MultiTagsCache": false,
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
import { getConfig } from '@/config';
|
||||
|
||||
const TITLE = getConfig('Title');
|
||||
const Copyright = getConfig('Copyright');
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="layout-footer text-[rgba(0,0,0,0.6)] dark:text-[rgba(220,220,242,0.8)]">
|
||||
Copyright © 2020-present
|
||||
{{ Copyright }}
|
||||
<a class="hover:text-primary" href="https://github.com/pure-admin" target="_blank"> {{ TITLE }} </a>
|
||||
</footer>
|
||||
</template>
|
||||
|
|
|
@ -13,10 +13,13 @@ import LogoutCircleRLine from '@iconify-icons/ri/logout-circle-r-line';
|
|||
import Setting from '@iconify-icons/ri/settings-3-line';
|
||||
import Check from '@iconify-icons/ep/check';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { userI18nTypeStore } from '@/store/i18n/i18nType';
|
||||
|
||||
const { layout, device, logout, onPanel, pureApp, username, userAvatar, avatarsStyle, toggleSideBar, getDropdownItemStyle, getDropdownItemClass } = useNav();
|
||||
|
||||
const { t, locale, translationCh, translationEn } = useTranslationLang();
|
||||
const { locale, translation } = useTranslationLang();
|
||||
|
||||
const i18nTypeStore = userI18nTypeStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -35,15 +38,17 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
|||
<GlobalizationIcon class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none" />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu class="translation">
|
||||
<el-dropdown-item :class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]" :style="getDropdownItemStyle(locale, 'zh')" @click="translationCh">
|
||||
<IconifyIconOffline v-show="locale === 'zh'" :icon="Check" class="check-zh" />
|
||||
简体中文
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :class="['dark:!text-white', getDropdownItemClass(locale, 'en')]" :style="getDropdownItemStyle(locale, 'en')" @click="translationEn">
|
||||
<span v-show="locale === 'en'" class="check-en">
|
||||
<el-dropdown-item
|
||||
v-for="item in i18nTypeStore.translationTypeList"
|
||||
:key="item.key"
|
||||
:class="['dark:!text-white', getDropdownItemClass(locale, item.key)]"
|
||||
:style="getDropdownItemStyle(locale, item.key)"
|
||||
@click="translation(item.key)"
|
||||
>
|
||||
<span v-show="locale === item.key" class="check">
|
||||
<IconifyIconOffline :icon="Check" />
|
||||
</span>
|
||||
English
|
||||
{{ item.value }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
|
@ -127,12 +132,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
|
|||
padding: 5px 40px;
|
||||
}
|
||||
|
||||
.check-zh {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
}
|
||||
|
||||
.check-en {
|
||||
.check {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
}
|
||||
|
|
|
@ -1,97 +1,90 @@
|
|||
<script setup lang="ts">
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute } from "vue-router";
|
||||
import { ref, unref, watch, onMounted, nextTick } from "vue";
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { nextTick, onMounted, ref, unref, watch } from 'vue';
|
||||
|
||||
defineOptions({
|
||||
name: "LayFrame"
|
||||
name: 'LayFrame',
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
frameInfo?: {
|
||||
frameSrc?: string;
|
||||
fullPath?: string;
|
||||
};
|
||||
frameInfo?: {
|
||||
frameSrc?: string;
|
||||
fullPath?: string;
|
||||
};
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
const loading = ref(true);
|
||||
const currentRoute = useRoute();
|
||||
const frameSrc = ref<string>("");
|
||||
const frameSrc = ref<string>('');
|
||||
const frameRef = ref<HTMLElement | null>(null);
|
||||
if (unref(currentRoute.meta)?.frameSrc) {
|
||||
frameSrc.value = unref(currentRoute.meta)?.frameSrc as string;
|
||||
frameSrc.value = unref(currentRoute.meta)?.frameSrc as string;
|
||||
}
|
||||
unref(currentRoute.meta)?.frameLoading === false && hideLoading();
|
||||
|
||||
function hideLoading() {
|
||||
loading.value = false;
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
function init() {
|
||||
nextTick(() => {
|
||||
const iframe = unref(frameRef);
|
||||
if (!iframe) return;
|
||||
const _frame = iframe as any;
|
||||
if (_frame.attachEvent) {
|
||||
_frame.attachEvent("onload", () => {
|
||||
hideLoading();
|
||||
});
|
||||
} else {
|
||||
iframe.onload = () => {
|
||||
hideLoading();
|
||||
};
|
||||
}
|
||||
});
|
||||
nextTick(() => {
|
||||
const iframe = unref(frameRef);
|
||||
if (!iframe) return;
|
||||
const _frame = iframe as any;
|
||||
if (_frame.attachEvent) {
|
||||
_frame.attachEvent('onload', () => {
|
||||
hideLoading();
|
||||
});
|
||||
} else {
|
||||
iframe.onload = () => {
|
||||
hideLoading();
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
() => currentRoute.fullPath,
|
||||
path => {
|
||||
if (
|
||||
currentRoute.name === "Redirect" &&
|
||||
path.includes(props.frameInfo?.fullPath)
|
||||
) {
|
||||
frameSrc.value = path; // redirect时,置换成任意值,待重定向后 重新赋值
|
||||
loading.value = true;
|
||||
}
|
||||
// 重新赋值
|
||||
if (props.frameInfo?.fullPath === path) {
|
||||
frameSrc.value = props.frameInfo?.frameSrc;
|
||||
}
|
||||
}
|
||||
() => currentRoute.fullPath,
|
||||
path => {
|
||||
if (currentRoute.name === 'Redirect' && path.includes(props.frameInfo?.fullPath)) {
|
||||
frameSrc.value = path; // redirect时,置换成任意值,待重定向后 重新赋值
|
||||
loading.value = true;
|
||||
}
|
||||
// 重新赋值
|
||||
if (props.frameInfo?.fullPath === path) {
|
||||
frameSrc.value = props.frameInfo?.frameSrc;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-loading="loading"
|
||||
class="frame"
|
||||
:element-loading-text="t('status.pureLoad')"
|
||||
>
|
||||
<iframe ref="frameRef" :src="frameSrc" class="frame-iframe" />
|
||||
</div>
|
||||
<div v-loading="loading" :element-loading-text="t('status.pureLoad')" class="frame">
|
||||
<iframe ref="frameRef" :src="frameSrc" class="frame-iframe" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.frame {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
|
||||
.frame-iframe {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
}
|
||||
.frame-iframe {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin: 2px 0 0 !important;
|
||||
margin: 2px 0 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,40 +1,29 @@
|
|||
import { useNav } from "./useNav";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useRoute } from "vue-router";
|
||||
import { onBeforeMount, type Ref, watch } from "vue";
|
||||
import { useNav } from './useNav';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { onBeforeMount, type Ref, watch } from 'vue';
|
||||
|
||||
export function useTranslationLang(ref?: Ref) {
|
||||
const { $storage, changeTitle, handleResize } = useNav();
|
||||
const { locale } = useI18n();
|
||||
const route = useRoute();
|
||||
const { $storage, changeTitle, handleResize } = useNav();
|
||||
const { locale } = useI18n();
|
||||
const route = useRoute();
|
||||
|
||||
function translationCh() {
|
||||
$storage.locale = { locale: "zh" };
|
||||
locale.value = "zh";
|
||||
ref && handleResize(ref.value);
|
||||
}
|
||||
function translation(value: string) {
|
||||
$storage.locale = { locale: value };
|
||||
locale.value = value;
|
||||
ref && handleResize(ref.value);
|
||||
}
|
||||
|
||||
function translationEn() {
|
||||
$storage.locale = { locale: "en" };
|
||||
locale.value = "en";
|
||||
ref && handleResize(ref.value);
|
||||
}
|
||||
watch(
|
||||
() => locale.value,
|
||||
() => {
|
||||
changeTitle(route.meta);
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => locale.value,
|
||||
() => {
|
||||
changeTitle(route.meta);
|
||||
}
|
||||
);
|
||||
onBeforeMount(() => {
|
||||
locale.value = $storage.locale?.locale ?? 'zh';
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
locale.value = $storage.locale?.locale ?? "zh";
|
||||
});
|
||||
|
||||
return {
|
||||
route,
|
||||
locale,
|
||||
translationCh,
|
||||
translationEn
|
||||
};
|
||||
return { route, locale, translation };
|
||||
}
|
||||
|
|
|
@ -1,36 +1,23 @@
|
|||
<script lang="ts" setup>
|
||||
import "animate.css";
|
||||
import 'animate.css';
|
||||
// 引入 src/components/CommonIcon/src/offlineIcon.ts 文件中所有使用addIcon添加过的本地图标
|
||||
import "@/components/CommonIcon/src/offlineIcon";
|
||||
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
|
||||
import { useAppStoreHook } from "@/store/modules/app";
|
||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||
import {
|
||||
deviceDetection,
|
||||
useDark,
|
||||
useGlobal,
|
||||
useResizeObserver
|
||||
} from "@pureadmin/utils";
|
||||
import {
|
||||
computed,
|
||||
defineComponent,
|
||||
h,
|
||||
onBeforeMount,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref
|
||||
} from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useLayout } from "./hooks/useLayout";
|
||||
import { setType } from "./types";
|
||||
import '@/components/CommonIcon/src/offlineIcon';
|
||||
import { useDataThemeChange } from '@/layout/hooks/useDataThemeChange';
|
||||
import { useAppStoreHook } from '@/store/modules/app';
|
||||
import { useSettingStoreHook } from '@/store/modules/settings';
|
||||
import { deviceDetection, useDark, useGlobal, useResizeObserver } from '@pureadmin/utils';
|
||||
import { computed, defineComponent, h, onBeforeMount, onMounted, reactive, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useLayout } from './hooks/useLayout';
|
||||
import { setType } from './types';
|
||||
|
||||
import BackTopIcon from "@/assets/svg/back_top.svg?component";
|
||||
import LayContent from "./components/lay-content/index.vue";
|
||||
import LayNavbar from "./components/lay-navbar/index.vue";
|
||||
import LaySetting from "./components/lay-setting/index.vue";
|
||||
import NavHorizontal from "./components/lay-sidebar/NavHorizontal.vue";
|
||||
import NavVertical from "./components/lay-sidebar/NavVertical.vue";
|
||||
import LayTag from "./components/lay-tag/index.vue";
|
||||
import BackTopIcon from '@/assets/svg/back_top.svg?component';
|
||||
import LayContent from './components/lay-content/index.vue';
|
||||
import LayNavbar from './components/lay-navbar/index.vue';
|
||||
import LaySetting from './components/lay-setting/index.vue';
|
||||
import NavHorizontal from './components/lay-sidebar/NavHorizontal.vue';
|
||||
import NavVertical from './components/lay-sidebar/NavVertical.vue';
|
||||
import LayTag from './components/lay-tag/index.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
const appWrapperRef = ref();
|
||||
|
@ -41,197 +28,165 @@ const pureSetting = useSettingStoreHook();
|
|||
const { $storage } = useGlobal<GlobalPropertiesApi>();
|
||||
|
||||
const set: setType = reactive({
|
||||
sidebar: computed(() => {
|
||||
return useAppStoreHook().sidebar;
|
||||
}),
|
||||
sidebar: computed(() => {
|
||||
return useAppStoreHook().sidebar;
|
||||
}),
|
||||
|
||||
device: computed(() => {
|
||||
return useAppStoreHook().device;
|
||||
}),
|
||||
device: computed(() => {
|
||||
return useAppStoreHook().device;
|
||||
}),
|
||||
|
||||
fixedHeader: computed(() => {
|
||||
return pureSetting.fixedHeader;
|
||||
}),
|
||||
fixedHeader: computed(() => {
|
||||
return pureSetting.fixedHeader;
|
||||
}),
|
||||
|
||||
classes: computed(() => {
|
||||
return {
|
||||
hideSidebar: !set.sidebar.opened,
|
||||
openSidebar: set.sidebar.opened,
|
||||
withoutAnimation: set.sidebar.withoutAnimation,
|
||||
mobile: set.device === "mobile"
|
||||
};
|
||||
}),
|
||||
classes: computed(() => {
|
||||
return {
|
||||
hideSidebar: !set.sidebar.opened,
|
||||
openSidebar: set.sidebar.opened,
|
||||
withoutAnimation: set.sidebar.withoutAnimation,
|
||||
mobile: set.device === 'mobile',
|
||||
};
|
||||
}),
|
||||
|
||||
hideTabs: computed(() => {
|
||||
return $storage?.configure.hideTabs;
|
||||
})
|
||||
hideTabs: computed(() => {
|
||||
return $storage?.configure.hideTabs;
|
||||
}),
|
||||
});
|
||||
|
||||
function setTheme(layoutModel: string) {
|
||||
window.document.body.setAttribute("layout", layoutModel);
|
||||
$storage.layout = {
|
||||
layout: `${layoutModel}`,
|
||||
theme: $storage.layout?.theme,
|
||||
darkMode: $storage.layout?.darkMode,
|
||||
sidebarStatus: $storage.layout?.sidebarStatus,
|
||||
epThemeColor: $storage.layout?.epThemeColor,
|
||||
themeColor: $storage.layout?.themeColor,
|
||||
overallStyle: $storage.layout?.overallStyle
|
||||
};
|
||||
window.document.body.setAttribute('layout', layoutModel);
|
||||
$storage.layout = {
|
||||
layout: `${layoutModel}`,
|
||||
theme: $storage.layout?.theme,
|
||||
darkMode: $storage.layout?.darkMode,
|
||||
sidebarStatus: $storage.layout?.sidebarStatus,
|
||||
epThemeColor: $storage.layout?.epThemeColor,
|
||||
themeColor: $storage.layout?.themeColor,
|
||||
overallStyle: $storage.layout?.overallStyle,
|
||||
};
|
||||
}
|
||||
|
||||
function toggle(device: string, bool: boolean) {
|
||||
useAppStoreHook().toggleDevice(device);
|
||||
useAppStoreHook().toggleSideBar(bool, "resize");
|
||||
useAppStoreHook().toggleDevice(device);
|
||||
useAppStoreHook().toggleSideBar(bool, 'resize');
|
||||
}
|
||||
|
||||
// 判断是否可自动关闭菜单栏
|
||||
let isAutoCloseSidebar = true;
|
||||
|
||||
useResizeObserver(appWrapperRef, entries => {
|
||||
if (isMobile) return;
|
||||
const entry = entries[0];
|
||||
const [{ inlineSize: width, blockSize: height }] = entry.borderBoxSize;
|
||||
useAppStoreHook().setViewportSize({ width, height });
|
||||
width <= 760 ? setTheme("vertical") : setTheme(useAppStoreHook().layout);
|
||||
/** width app-wrapper类容器宽度
|
||||
* 0 < width <= 760 隐藏侧边栏
|
||||
* 760 < width <= 990 折叠侧边栏
|
||||
* width > 990 展开侧边栏
|
||||
*/
|
||||
if (width > 0 && width <= 760) {
|
||||
toggle("mobile", false);
|
||||
isAutoCloseSidebar = true;
|
||||
} else if (width > 760 && width <= 990) {
|
||||
if (isAutoCloseSidebar) {
|
||||
toggle("desktop", false);
|
||||
isAutoCloseSidebar = false;
|
||||
}
|
||||
} else if (width > 990 && !set.sidebar.isClickCollapse) {
|
||||
toggle("desktop", true);
|
||||
isAutoCloseSidebar = true;
|
||||
} else {
|
||||
toggle("desktop", false);
|
||||
isAutoCloseSidebar = false;
|
||||
}
|
||||
if (isMobile) return;
|
||||
const entry = entries[0];
|
||||
const [{ inlineSize: width, blockSize: height }] = entry.borderBoxSize;
|
||||
useAppStoreHook().setViewportSize({ width, height });
|
||||
width <= 760 ? setTheme('vertical') : setTheme(useAppStoreHook().layout);
|
||||
/** width app-wrapper类容器宽度
|
||||
* 0 < width <= 760 隐藏侧边栏
|
||||
* 760 < width <= 990 折叠侧边栏
|
||||
* width > 990 展开侧边栏
|
||||
*/
|
||||
if (width > 0 && width <= 760) {
|
||||
toggle('mobile', false);
|
||||
isAutoCloseSidebar = true;
|
||||
} else if (width > 760 && width <= 990) {
|
||||
if (isAutoCloseSidebar) {
|
||||
toggle('desktop', false);
|
||||
isAutoCloseSidebar = false;
|
||||
}
|
||||
} else if (width > 990 && !set.sidebar.isClickCollapse) {
|
||||
toggle('desktop', true);
|
||||
isAutoCloseSidebar = true;
|
||||
} else {
|
||||
toggle('desktop', false);
|
||||
isAutoCloseSidebar = false;
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (isMobile) {
|
||||
toggle("mobile", false);
|
||||
}
|
||||
if (isMobile) {
|
||||
toggle('mobile', false);
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeMount(() => {
|
||||
useDataThemeChange().dataThemeChange($storage.layout?.overallStyle);
|
||||
useDataThemeChange().dataThemeChange($storage.layout?.overallStyle);
|
||||
});
|
||||
|
||||
const LayHeader = defineComponent({
|
||||
name: "LayHeader",
|
||||
render() {
|
||||
return h(
|
||||
"div",
|
||||
{
|
||||
class: { "fixed-header": set.fixedHeader },
|
||||
style: [
|
||||
set.hideTabs && layout.value.includes("horizontal")
|
||||
? isDark.value
|
||||
? "box-shadow: 0 1px 4px #0d0d0d"
|
||||
: "box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08)"
|
||||
: ""
|
||||
]
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
!pureSetting.hiddenSideBar &&
|
||||
(layout.value.includes("vertical") || layout.value.includes("mix"))
|
||||
? h(LayNavbar)
|
||||
: null,
|
||||
!pureSetting.hiddenSideBar && layout.value.includes("horizontal")
|
||||
? h(NavHorizontal)
|
||||
: null,
|
||||
h(LayTag)
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
name: 'LayHeader',
|
||||
render() {
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
class: { 'fixed-header': set.fixedHeader },
|
||||
style: [set.hideTabs && layout.value.includes('horizontal') ? (isDark.value ? 'box-shadow: 0 1px 4px #0d0d0d' : 'box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08)') : ''],
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
!pureSetting.hiddenSideBar && (layout.value.includes('vertical') || layout.value.includes('mix')) ? h(LayNavbar) : null,
|
||||
!pureSetting.hiddenSideBar && layout.value.includes('horizontal') ? h(NavHorizontal) : null,
|
||||
h(LayTag),
|
||||
],
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="appWrapperRef" :class="['app-wrapper', set.classes]">
|
||||
<div
|
||||
v-show="
|
||||
set.device === 'mobile' &&
|
||||
set.sidebar.opened &&
|
||||
layout.includes('vertical')
|
||||
"
|
||||
class="app-mask"
|
||||
@click="useAppStoreHook().toggleSideBar()"
|
||||
/>
|
||||
<NavVertical
|
||||
v-show="
|
||||
!pureSetting.hiddenSideBar &&
|
||||
(layout.includes('vertical') || layout.includes('mix'))
|
||||
"
|
||||
/>
|
||||
<div
|
||||
:class="[
|
||||
'main-container',
|
||||
pureSetting.hiddenSideBar ? 'main-hidden' : ''
|
||||
]"
|
||||
>
|
||||
<div v-if="set.fixedHeader">
|
||||
<LayHeader />
|
||||
<!-- 主体内容 -->
|
||||
<LayContent :fixed-header="set.fixedHeader" />
|
||||
</div>
|
||||
<el-scrollbar v-else>
|
||||
<el-backtop
|
||||
:title="t('buttons.pureBackTop')"
|
||||
target=".main-container .el-scrollbar__wrap"
|
||||
>
|
||||
<BackTopIcon />
|
||||
</el-backtop>
|
||||
<LayHeader />
|
||||
<!-- 主体内容 -->
|
||||
<LayContent :fixed-header="set.fixedHeader" />
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<!-- 系统设置 -->
|
||||
<LaySetting />
|
||||
</div>
|
||||
<div ref="appWrapperRef" :class="['app-wrapper', set.classes]">
|
||||
<div v-show="set.device === 'mobile' && set.sidebar.opened && layout.includes('vertical')" class="app-mask" @click="useAppStoreHook().toggleSideBar()" />
|
||||
<NavVertical v-show="!pureSetting.hiddenSideBar && (layout.includes('vertical') || layout.includes('mix'))" />
|
||||
<div :class="['main-container', pureSetting.hiddenSideBar ? 'main-hidden' : '']">
|
||||
<div v-if="set.fixedHeader">
|
||||
<LayHeader />
|
||||
<!-- 主体内容 -->
|
||||
<LayContent :fixed-header="set.fixedHeader" />
|
||||
</div>
|
||||
<el-scrollbar v-else>
|
||||
<el-backtop :title="t('buttons.pureBackTop')" target=".main-container .el-scrollbar__wrap">
|
||||
<BackTopIcon />
|
||||
</el-backtop>
|
||||
<LayHeader />
|
||||
<!-- 主体内容 -->
|
||||
<LayContent :fixed-header="set.fixedHeader" />
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<!-- 系统设置 -->
|
||||
<LaySetting />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&::after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: "";
|
||||
}
|
||||
&::after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&.mobile.openSidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
&.mobile.openSidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.app-mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 2001;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 2001;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #000;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.re-screen {
|
||||
margin-top: 12px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { unref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
<script lang="ts" setup>
|
||||
import { unref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
defineOptions({
|
||||
name: "Redirect"
|
||||
name: 'Redirect',
|
||||
});
|
||||
|
||||
const { currentRoute, replace } = useRouter();
|
||||
|
@ -11,14 +11,14 @@ const { currentRoute, replace } = useRouter();
|
|||
const { params, query } = unref(currentRoute);
|
||||
const { path } = params;
|
||||
|
||||
const _path = Array.isArray(path) ? path.join("/") : path;
|
||||
const _path = Array.isArray(path) ? path.join('/') : path;
|
||||
|
||||
replace({
|
||||
path: "/" + _path,
|
||||
query
|
||||
path: '/' + _path,
|
||||
query,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div />
|
||||
<div />
|
||||
</template>
|
||||
|
|
|
@ -22,7 +22,11 @@ export const userI18nTypeStore = defineStore('i18nTypeStore', {
|
|||
loading: false,
|
||||
};
|
||||
},
|
||||
getters: {},
|
||||
getters: {
|
||||
translationTypeList(state) {
|
||||
return state.datalist.map(item => ({ key: item.typeName, value: item.summary }));
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
/**
|
||||
* * 获取多语言类型
|
||||
|
|
Loading…
Reference in New Issue