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