perf: login

This commit is contained in:
lrl 2022-07-27 15:08:44 +08:00
parent d824c99489
commit 114d5427cc
7 changed files with 293 additions and 196 deletions

View File

@ -1,52 +1,26 @@
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import { useNav } from "../hooks/nav";
import { useRoute } from "vue-router";
import Search from "./search/index.vue";
import Notice from "./notice/index.vue";
import mixNav from "./sidebar/mixNav.vue";
import avatars from "/@/assets/avatars.jpg";
import { watch, getCurrentInstance } from "vue";
import Breadcrumb from "./sidebar/breadCrumb.vue";
import { deviceDetection } from "@pureadmin/utils";
import screenfull from "../components/screenfull/index.vue";
import useTranslationLang from "../hooks/useTranslationLang";
import globalization from "/@/assets/svg/globalization.svg?component";
const route = useRoute();
const { locale, t } = useI18n();
const instance =
getCurrentInstance().appContext.config.globalProperties.$storage;
const {
logout,
onPanel,
changeTitle,
pureApp,
username,
avatarsStyle,
getDropdownItemStyle,
getDropdownItemClass,
changeWangeditorLanguage
getDropdownItemClass
} = useNav();
watch(
() => locale.value,
() => {
changeTitle(route.meta);
locale.value === "en"
? changeWangeditorLanguage(locale.value)
: changeWangeditorLanguage("zh-CN");
}
);
function translationCh() {
instance.locale = { locale: "zh" };
locale.value = "zh";
}
function translationEn() {
instance.locale = { locale: "en" };
locale.value = "en";
}
const { t, locale, translationCh, translationEn } = useTranslationLang();
</script>
<template>

View File

@ -6,33 +6,25 @@ import {
reactive,
computed,
nextTick,
useCssModule,
getCurrentInstance
useCssModule
} from "vue";
import { find } from "lodash-unified";
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 { TinyColor } from "@ctrl/tinycolor";
import { themeColorsType } from "../../types";
import { routerArrays } from "/@/layout/types";
import type { StorageConfigs } from "/#/index";
import { useAppStoreHook } from "/@/store/modules/app";
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
import { useMultiTagsStoreHook } from "/@/store/modules/multiTags";
import useDataThemeChange from "/@/layout/hooks/useDataThemeChange";
import {
useDark,
debounce,
storageLocal,
storageSession
} from "@pureadmin/utils";
import {
darken,
lighten,
toggleTheme
} from "@pureadmin/theme/dist/browser-utils";
import { toggleTheme } from "@pureadmin/theme/dist/browser-utils";
import dayIcon from "/@/assets/svg/day.svg?component";
import darkIcon from "/@/assets/svg/dark.svg?component";
@ -40,44 +32,20 @@ import darkIcon from "/@/assets/svg/dark.svg?component";
const router = useRouter();
const { isDark } = useDark();
const { isSelect } = useCssModule();
const body = document.documentElement as HTMLElement;
const instance =
getCurrentInstance().appContext.app.config.globalProperties.$storage;
const instanceConfig =
getCurrentInstance().appContext.app.config.globalProperties.$config;
let themeColors = ref<Array<themeColorsType>>([
/* 道奇蓝(默认) */
{ color: "#1b2a47", themeColor: "default" },
/* 亮白色 */
{ color: "#ffffff", themeColor: "light" },
/* 猩红色 */
{ color: "#f5222d", themeColor: "dusk" },
/* 橙红色 */
{ color: "#fa541c", themeColor: "volcano" },
/* 金色 */
{ color: "#fadb14", themeColor: "yellow" },
/* 绿宝石 */
{ color: "#13c2c2", themeColor: "mingQing" },
/* 酸橙绿 */
{ color: "#52c41a", themeColor: "auroraGreen" },
/* 深粉色 */
{ color: "#eb2f96", themeColor: "pink" },
/* 深紫罗兰色 */
{ color: "#722ed1", themeColor: "saucePurple" }
]);
const mixRef = templateRef<HTMLElement | null>("mixRef", null);
const verticalRef = templateRef<HTMLElement | null>("verticalRef", null);
const horizontalRef = templateRef<HTMLElement | null>("horizontalRef", null);
let layoutTheme =
ref(storageLocal.getItem<StorageConfigs>("responsive-layout")) ||
ref({
layout: instanceConfig?.Layout ?? "vertical",
theme: instanceConfig?.Theme ?? "default"
});
const {
body,
instance,
dataTheme,
layoutTheme,
themeColors,
dataThemeChange,
setLayoutThemeColor
} = useDataThemeChange();
/* body添加layout属性作用于src/style/sidebar.scss */
if (unref(layoutTheme)) {
@ -245,75 +213,6 @@ function setLayoutModel(layout: string) {
useAppStoreHook().setLayout(layout);
}
/** 设置导航主题色 */
function setLayoutThemeColor(theme: string) {
layoutTheme.value.theme = theme;
toggleTheme({
scopeName: `layout-theme-${theme}`
});
instance.layout = {
layout: useAppStoreHook().layout,
theme,
darkMode: dataTheme.value,
sidebarStatus: instance.layout.sidebarStatus,
epThemeColor: instance.layout.epThemeColor
};
if (theme === "default" || theme === "light") {
setEpThemeColor(getConfig().EpThemeColor);
} else {
const colors = find(themeColors.value, { themeColor: theme });
setEpThemeColor(colors.color);
}
}
/**
* @description 自动计算hover和active颜色
* @see {@link https://element-plus.org/zh-CN/component/button.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A2%9C%E8%89%B2}
*/
const shadeBgColor = (color: string): string => {
return new TinyColor(color).shade(10).toString();
};
/** 设置ep主题色 */
const setEpThemeColor = (color: string) => {
useEpThemeStoreHook().setEpThemeColor(color);
body.style.setProperty("--el-color-primary-active", shadeBgColor(color));
document.documentElement.style.setProperty("--el-color-primary", color);
for (let i = 1; i <= 9; i++) {
document.documentElement.style.setProperty(
`--el-color-primary-light-${i}`,
lighten(color, i / 10)
);
}
for (let i = 1; i <= 2; i++) {
document.documentElement.style.setProperty(
`--el-color-primary-dark-${i}`,
darken(color, i / 10)
);
}
};
let dataTheme = ref<boolean>(instance.layout.darkMode);
/** 日间、夜间主题切换 */
function dataThemeChange() {
/* 如果当前是light夜间主题默认切换到default主题 */
if (useEpThemeStoreHook().epTheme === "light" && dataTheme.value) {
setLayoutThemeColor("default");
} else {
setLayoutThemeColor(useEpThemeStoreHook().epTheme);
}
if (dataTheme.value) {
instance.layout.darkMode = true;
document.documentElement.classList.add("dark");
} else {
instance.layout.darkMode = false;
document.documentElement.classList.remove("dark");
}
}
/* 初始化项目配置 */
nextTick(() => {
settings.greyVal &&

View File

@ -0,0 +1,120 @@
import { getConfig } from "/@/config";
import { find } from "lodash-unified";
import useLayout from "./useLayout";
import { themeColorsType } from "../types";
import { TinyColor } from "@ctrl/tinycolor";
import { ref, getCurrentInstance } from "vue";
import { useAppStoreHook } from "/@/store/modules/app";
import { useEpThemeStoreHook } from "/@/store/modules/epTheme";
import {
darken,
lighten,
toggleTheme
} from "@pureadmin/theme/dist/browser-utils";
export default function useDataThemeChange() {
const { layoutTheme } = useLayout();
const themeColors = ref<Array<themeColorsType>>([
/* 道奇蓝(默认) */
{ color: "#1b2a47", themeColor: "default" },
/* 亮白色 */
{ color: "#ffffff", themeColor: "light" },
/* 猩红色 */
{ color: "#f5222d", themeColor: "dusk" },
/* 橙红色 */
{ color: "#fa541c", themeColor: "volcano" },
/* 金色 */
{ color: "#fadb14", themeColor: "yellow" },
/* 绿宝石 */
{ color: "#13c2c2", themeColor: "mingQing" },
/* 酸橙绿 */
{ color: "#52c41a", themeColor: "auroraGreen" },
/* 深粉色 */
{ color: "#eb2f96", themeColor: "pink" },
/* 深紫罗兰色 */
{ color: "#722ed1", themeColor: "saucePurple" }
]);
const body = document.documentElement as HTMLElement;
const instance =
getCurrentInstance().appContext.app.config.globalProperties.$storage;
/** 设置导航主题色 */
function setLayoutThemeColor(theme = "default") {
layoutTheme.value.theme = theme;
toggleTheme({
scopeName: `layout-theme-${theme}`
});
instance.layout = {
layout: useAppStoreHook().layout,
theme,
darkMode: dataTheme.value,
sidebarStatus: instance.layout.sidebarStatus,
epThemeColor: instance.layout.epThemeColor
};
if (theme === "default" || theme === "light") {
setEpThemeColor(getConfig().EpThemeColor);
} else {
const colors = find(themeColors.value, { themeColor: theme });
setEpThemeColor(colors.color);
}
}
/**
* @description hover和active颜色
* @see {@link https://element-plus.org/zh-CN/component/button.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A2%9C%E8%89%B2}
*/
const shadeBgColor = (color: string): string => {
return new TinyColor(color).shade(10).toString();
};
/** 设置ep主题色 */
const setEpThemeColor = (color: string) => {
useEpThemeStoreHook().setEpThemeColor(color);
body.style.setProperty("--el-color-primary-active", shadeBgColor(color));
document.documentElement.style.setProperty("--el-color-primary", color);
for (let i = 1; i <= 9; i++) {
document.documentElement.style.setProperty(
`--el-color-primary-light-${i}`,
lighten(color, i / 10)
);
}
for (let i = 1; i <= 2; i++) {
document.documentElement.style.setProperty(
`--el-color-primary-dark-${i}`,
darken(color, i / 10)
);
}
};
const dataTheme = ref<boolean>(instance?.layout?.darkMode);
/** 日间、夜间主题切换 */
function dataThemeChange() {
/* 如果当前是light夜间主题默认切换到default主题 */
if (useEpThemeStoreHook().epTheme === "light" && dataTheme.value) {
setLayoutThemeColor("default");
} else {
setLayoutThemeColor(useEpThemeStoreHook().epTheme);
}
if (dataTheme.value) {
instance.layout.darkMode = true;
document.documentElement.classList.add("dark");
} else {
instance.layout.darkMode = false;
document.documentElement.classList.remove("dark");
}
}
return {
body,
instance,
dataTheme,
layoutTheme,
themeColors,
dataThemeChange,
setEpThemeColor,
setLayoutThemeColor
};
}

View File

@ -0,0 +1,61 @@
import { computed, getCurrentInstance } from "vue";
import { useI18n } from "vue-i18n";
import { routerArrays } from "../types";
import { useMultiTagsStore } from "/@/store/modules/multiTags";
export default function useLayout() {
const instance = getCurrentInstance().appContext.app.config.globalProperties;
const initStorage = () => {
// 路由
if (
useMultiTagsStore().multiTagsCache &&
(!instance.$storage.tags || instance.$storage.tags.length === 0)
) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
instance.$storage.tags = routerArrays;
}
// 国际化
if (!instance.$storage.locale) {
// eslint-disable-next-line
instance.$storage.locale = { locale: instance.$config?.Locale ?? "zh" };
useI18n().locale.value = instance.$config?.Locale ?? "zh";
}
// 导航
if (!instance.$storage.layout) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
instance.$storage.layout = {
layout: instance.$config?.Layout ?? "vertical",
theme: instance.$config?.Theme ?? "default",
darkMode: instance.$config?.DarkMode ?? false,
sidebarStatus: instance.$config?.SidebarStatus ?? true,
epThemeColor: instance.$config?.EpThemeColor ?? "#409EFF"
};
}
// 灰色模式、色弱模式、隐藏标签页
if (!instance.$storage.configure) {
// eslint-disable-next-line
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
};
}
};
// 清空缓存后从serverConfig.json读取默认配置并赋值到storage中
const layout = computed(() => {
return instance.$storage?.layout.layout;
});
const layoutTheme = computed(() => {
return instance.$storage.layout;
});
return {
layout,
instance,
layoutTheme,
initStorage
};
}

View File

@ -0,0 +1,38 @@
import { useNav } from "./nav";
import { useI18n } from "vue-i18n";
import { useRoute } from "vue-router";
import { watch, getCurrentInstance } from "vue";
export default function useTranslationLang() {
const { changeTitle, changeWangeditorLanguage } = useNav();
const { locale, t } = useI18n();
const route = useRoute();
const instance =
getCurrentInstance().appContext.config.globalProperties.$storage;
function translationCh() {
instance.locale = { locale: "zh" };
locale.value = "zh";
}
function translationEn() {
instance.locale = { locale: "en" };
locale.value = "en";
}
watch(
() => locale.value,
() => {
changeTitle(route.meta);
locale.value === "en"
? changeWangeditorLanguage(locale.value)
: changeWangeditorLanguage("zh-CN");
}
);
return {
t,
locale,
translationCh,
translationEn
};
}

View File

@ -1,25 +1,16 @@
<script setup lang="ts">
import {
h,
reactive,
computed,
onMounted,
defineComponent,
getCurrentInstance
} from "vue";
import { setType } from "./types";
import { useI18n } from "vue-i18n";
import { routerArrays } from "./types";
import { emitter } from "/@/utils/mitt";
import { useAppStoreHook } from "/@/store/modules/app";
import { deviceDetection, useDark } from "@pureadmin/utils";
import { useMultiTagsStore } from "/@/store/modules/multiTags";
import { useSettingStoreHook } from "/@/store/modules/settings";
import { h, reactive, computed, onMounted, defineComponent } from "vue";
import backTop from "/@/assets/svg/back_top.svg?component";
import fullScreen from "/@/assets/svg/full_screen.svg?component";
import exitScreen from "/@/assets/svg/exit_screen.svg?component";
import useLayout from "./hooks/useLayout";
import navbar from "./components/navbar.vue";
import tag from "./components/tag/index.vue";
import appMain from "./components/appMain.vue";
@ -30,49 +21,8 @@ import Horizontal from "./components/sidebar/horizontal.vue";
const { isDark } = useDark();
const isMobile = deviceDetection();
const pureSetting = useSettingStoreHook();
const instance = getCurrentInstance().appContext.app.config.globalProperties;
// serverConfig.jsonstorage
const layout = computed(() => {
//
if (
useMultiTagsStore().multiTagsCache &&
(!instance.$storage.tags || instance.$storage.tags.length === 0)
) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
instance.$storage.tags = routerArrays;
}
//
if (!instance.$storage.locale) {
// eslint-disable-next-line
instance.$storage.locale = { locale: instance.$config?.Locale ?? "zh" };
useI18n().locale.value = instance.$config?.Locale ?? "zh";
}
//
if (!instance.$storage.layout) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
instance.$storage.layout = {
layout: instance.$config?.Layout ?? "vertical",
theme: instance.$config?.Theme ?? "default",
darkMode: instance.$config?.DarkMode ?? false,
sidebarStatus: instance.$config?.SidebarStatus ?? true,
epThemeColor: instance.$config?.EpThemeColor ?? "#409EFF"
};
}
//
if (!instance.$storage.configure) {
// eslint-disable-next-line
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
};
}
return instance.$storage?.layout.layout;
});
const { instance, layout } = useLayout();
const set: setType = reactive({
sidebar: computed(() => {

View File

@ -7,15 +7,23 @@ import qrCode from "./components/qrCode.vue";
import regist from "./components/regist.vue";
import update from "./components/update.vue";
import { initRouter } from "/@/router/utils";
import { useNav } from "/@/layout/hooks/nav";
import { message } from "@pureadmin/components";
import type { FormInstance } from "element-plus";
import useLayout from "/@/layout/hooks/useLayout";
import { storageSession } from "@pureadmin/utils";
import { ref, reactive, watch, computed, getCurrentInstance } from "vue";
import { operates, thirdParty } from "./utils/enums";
import { useUserStoreHook } from "/@/store/modules/user";
import { bg, avatar, currentWeek } from "./utils/static";
import { ReImageVerify } from "/@/components/ReImageVerify";
import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
import useDataThemeChange from "/@/layout/hooks/useDataThemeChange";
import useTranslationLang from "/@/layout/hooks/useTranslationLang";
import { ref, reactive, watch, computed, getCurrentInstance } from "vue";
import dayIcon from "/@/assets/svg/day.svg?component";
import darkIcon from "/@/assets/svg/dark.svg?component";
import globalization from "/@/assets/svg/globalization.svg?component";
defineOptions({
name: "Login"
@ -31,6 +39,13 @@ const currentPage = computed(() => {
return useUserStoreHook().currentPage;
});
const { initStorage } = useLayout();
initStorage();
const { dataTheme, dataThemeChange } = useDataThemeChange();
const { getDropdownItemStyle, getDropdownItemClass } = useNav();
const { locale, translationCh, translationEn } = useTranslationLang();
const ruleForm = reactive({
username: "admin",
password: "admin123",
@ -70,6 +85,46 @@ watch(imgCode, value => {
</script>
<template>
<div class="flex-c absolute right-5">
<!-- 主题 -->
<el-switch
v-model="dataTheme"
inline-prompt
:active-icon="dayIcon"
:inactive-icon="darkIcon"
@change="dataThemeChange"
/>
<!-- 国际化 -->
<el-dropdown trigger="click">
<globalization class="w-40px h-48px p-11px cursor-pointer outline-none" />
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['!dark:color-white', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<IconifyIconOffline
class="check-zh"
v-show="locale === 'zh'"
icon="check"
/>
简体中文
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['!dark:color-white', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span class="check-en" v-show="locale === 'en'">
<IconifyIconOffline icon="check" />
</span>
English
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<img :src="bg" class="wave" />
<div class="login-container">
<div class="img">