feat: 将整体logo视觉替换为ai生成的logo

master
LCJ-MinYa 2 months ago
parent 6825193266
commit 6559b3eff2

@ -1,42 +1,42 @@
// 根据角色动态生成路由 // 根据角色动态生成路由
import { defineFakeRoute } from "vite-plugin-fake-server/client"; import { defineFakeRoute } from 'vite-plugin-fake-server/client';
export default defineFakeRoute([ export default defineFakeRoute([
{ {
url: "/login", url: '/login',
method: "post", method: 'post',
response: ({ body }) => { response: ({ body }) => {
if (body.username === "admin") { if (body.username === 'admin') {
return { return {
success: true, success: true,
data: { data: {
avatar: "https://avatars.githubusercontent.com/u/44761321", avatar: '/user_small.png',
username: "admin", username: 'admin',
nickname: "小铭", nickname: 'Levi',
// 一个用户可能有多个角色 // 一个用户可能有多个角色
roles: ["admin"], roles: ['admin'],
// 按钮级别权限 // 按钮级别权限
permissions: ["*:*:*"], permissions: ['*:*:*'],
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin", accessToken: 'eyJhbGciOiJIUzUxMiJ9.admin',
refreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh", refreshToken: 'eyJhbGciOiJIUzUxMiJ9.adminRefresh',
expires: "2030/10/30 00:00:00" expires: '2030/10/30 00:00:00',
} },
}; };
} else { } else {
return { return {
success: true, success: true,
data: { data: {
avatar: "https://avatars.githubusercontent.com/u/52823142", avatar: 'https://avatars.githubusercontent.com/u/52823142',
username: "common", username: 'common',
nickname: "小林", nickname: '小林',
roles: ["common"], roles: ['common'],
permissions: ["permission:btn:add", "permission:btn:edit"], permissions: ['permission:btn:add', 'permission:btn:edit'],
accessToken: "eyJhbGciOiJIUzUxMiJ9.common", accessToken: 'eyJhbGciOiJIUzUxMiJ9.common',
refreshToken: "eyJhbGciOiJIUzUxMiJ9.commonRefresh", refreshToken: 'eyJhbGciOiJIUzUxMiJ9.commonRefresh',
expires: "2030/10/30 00:00:00" expires: '2030/10/30 00:00:00',
} },
}; };
} }
} },
} },
]); ]);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 96 KiB

@ -1,32 +1,29 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from "vue"; import { ref, computed } from 'vue';
import { noticesData } from "./data"; import { noticesData } from './data';
import NoticeList from "./components/NoticeList.vue"; import NoticeList from './components/NoticeList.vue';
import BellIcon from "@iconify-icons/ep/bell"; import BellIcon from '@iconify-icons/ep/bell';
const noticesNum = ref(0); const noticesNum = ref(0);
const notices = ref(noticesData); const notices = ref([]);
// const notices = ref(noticesData);
const activeKey = ref(noticesData[0]?.key); const activeKey = ref(noticesData[0]?.key);
notices.value.map(v => (noticesNum.value += v.list.length)); notices.value.map((v) => (noticesNum.value += v.list.length));
const getLabel = computed( const getLabel = computed(() => (item) => item.name + (item.list.length > 0 ? `(${item.list.length})` : ''));
() => item =>
item.name + (item.list.length > 0 ? `(${item.list.length})` : "")
);
</script> </script>
<template> <template>
<el-dropdown trigger="click" placement="bottom-end"> <el-dropdown
<span trigger="click"
:class="[ placement="bottom-end"
'dropdown-badge', >
'navbar-bg-hover', <span :class="['dropdown-badge', 'navbar-bg-hover', 'select-none', Number(noticesNum) !== 0 && 'mr-[10px]']">
'select-none', <el-badge
Number(noticesNum) !== 0 && 'mr-[10px]' :value="Number(noticesNum) === 0 ? '' : noticesNum"
]" :max="99"
> >
<el-badge :value="Number(noticesNum) === 0 ? '' : noticesNum" :max="99">
<span class="header-notice-icon"> <span class="header-notice-icon">
<IconifyIconOffline :icon="BellIcon" /> <IconifyIconOffline :icon="BellIcon" />
</span> </span>
@ -46,11 +43,20 @@ const getLabel = computed(
:image-size="60" :image-size="60"
/> />
<span v-else> <span v-else>
<template v-for="item in notices" :key="item.key"> <template
<el-tab-pane :label="getLabel(item)" :name="`${item.key}`"> v-for="item in notices"
:key="item.key"
>
<el-tab-pane
:label="getLabel(item)"
:name="`${item.key}`"
>
<el-scrollbar max-height="330px"> <el-scrollbar max-height="330px">
<div class="noticeList-container"> <div class="noticeList-container">
<NoticeList :list="item.list" :emptyText="item.emptyText" /> <NoticeList
:list="item.list"
:emptyText="item.emptyText"
/>
</div> </div>
</el-scrollbar> </el-scrollbar>
</el-tab-pane> </el-tab-pane>

@ -1,22 +1,21 @@
import { storeToRefs } from "pinia"; import { storeToRefs } from 'pinia';
import { getConfig } from "@/config"; import { getConfig } from '@/config';
import { emitter } from "@/utils/mitt"; import { emitter } from '@/utils/mitt';
import Avatar from "@/assets/user.jpg"; import Avatar from '@/assets/user.jpg';
import { getTopMenu } from "@/router/utils"; import { getTopMenu } from '@/router/utils';
import { useFullscreen } from "@vueuse/core"; import { useFullscreen } from '@vueuse/core';
import type { routeMetaType } from "../types"; import type { routeMetaType } from '../types';
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from 'vue-router';
import { router, remainingPaths } from "@/router"; import { router, remainingPaths } from '@/router';
import { computed, type CSSProperties } from "vue"; import { computed, type CSSProperties } from 'vue';
import { useAppStoreHook } from "@/store/modules/app"; import { useAppStoreHook } from '@/store/modules/app';
import { useUserStoreHook } from "@/store/modules/user"; import { useUserStoreHook } from '@/store/modules/user';
import { useGlobal, isAllEmpty } from "@pureadmin/utils"; import { useGlobal, isAllEmpty } from '@pureadmin/utils';
import { usePermissionStoreHook } from "@/store/modules/permission"; import { usePermissionStoreHook } from '@/store/modules/permission';
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill"; import ExitFullscreen from '@iconify-icons/ri/fullscreen-exit-fill';
import Fullscreen from "@iconify-icons/ri/fullscreen-fill"; import Fullscreen from '@iconify-icons/ri/fullscreen-fill';
const errorInfo = const errorInfo = 'The current routing configuration is incorrect, please check the configuration';
"The current routing configuration is incorrect, please check the configuration";
export function useNav() { export function useNav() {
const route = useRoute(); const route = useRoute();
@ -25,34 +24,30 @@ export function useNav() {
const { isFullscreen, toggle } = useFullscreen(); const { isFullscreen, toggle } = useFullscreen();
const { wholeMenus } = storeToRefs(usePermissionStoreHook()); const { wholeMenus } = storeToRefs(usePermissionStoreHook());
/** 平台`layout`中所有`el-tooltip`的`effect`配置,默认`light` */ /** 平台`layout`中所有`el-tooltip`的`effect`配置,默认`light` */
const tooltipEffect = getConfig()?.TooltipEffect ?? "light"; const tooltipEffect = getConfig()?.TooltipEffect ?? 'light';
const getDivStyle = computed((): CSSProperties => { const getDivStyle = computed((): CSSProperties => {
return { return {
width: "100%", width: '100%',
display: "flex", display: 'flex',
alignItems: "center", alignItems: 'center',
justifyContent: "space-between", justifyContent: 'space-between',
overflow: "hidden" overflow: 'hidden',
}; };
}); });
/** 头像(如果头像为空则使用 src/assets/user.jpg */ /** 头像(如果头像为空则使用 src/assets/user.jpg */
const userAvatar = computed(() => { const userAvatar = computed(() => {
return isAllEmpty(useUserStoreHook()?.avatar) return isAllEmpty(useUserStoreHook()?.avatar) ? Avatar : useUserStoreHook()?.avatar;
? Avatar
: useUserStoreHook()?.avatar;
}); });
/** 昵称(如果昵称为空则显示用户名) */ /** 昵称(如果昵称为空则显示用户名) */
const username = computed(() => { const username = computed(() => {
return isAllEmpty(useUserStoreHook()?.nickname) return isAllEmpty(useUserStoreHook()?.nickname) ? useUserStoreHook()?.username : useUserStoreHook()?.nickname;
? useUserStoreHook()?.username
: useUserStoreHook()?.nickname;
}); });
const avatarsStyle = computed(() => { const avatarsStyle = computed(() => {
return username.value ? { marginRight: "10px" } : ""; return username.value ? { marginRight: '10px' } : '';
}); });
const isCollapse = computed(() => { const isCollapse = computed(() => {
@ -89,7 +84,7 @@ export function useNav() {
} }
function onPanel() { function onPanel() {
emitter.emit("openPanel"); emitter.emit('openPanel');
} }
function toggleSideBar() { function toggleSideBar() {
@ -105,7 +100,7 @@ export function useNav() {
const httpReg = /^http(s?):\/\//; const httpReg = /^http(s?):\/\//;
const routeChildPath = route.children[0]?.path; const routeChildPath = route.children[0]?.path;
if (httpReg.test(routeChildPath)) { if (httpReg.test(routeChildPath)) {
return route.path + "/" + routeChildPath; return route.path + '/' + routeChildPath;
} else { } else {
return routeChildPath; return routeChildPath;
} }
@ -113,7 +108,7 @@ export function useNav() {
function menuSelect(indexPath: string) { function menuSelect(indexPath: string) {
if (wholeMenus.value.length === 0 || isRemaining(indexPath)) return; if (wholeMenus.value.length === 0 || isRemaining(indexPath)) return;
emitter.emit("changLayoutRoute", indexPath); emitter.emit('changLayoutRoute', indexPath);
} }
/** 判断路径是否参与菜单 */ /** 判断路径是否参与菜单 */
@ -123,7 +118,7 @@ export function useNav() {
/** 获取`logo` */ /** 获取`logo` */
function getLogo() { function getLogo() {
return new URL("/logo.svg", import.meta.url).href; return new URL('/user_small.png', import.meta.url).href;
} }
return { return {
@ -152,6 +147,6 @@ export function useNav() {
username, username,
userAvatar, userAvatar,
avatarsStyle, avatarsStyle,
tooltipEffect tooltipEffect,
}; };
} }

@ -1,25 +1,25 @@
<script setup lang="ts"> <script setup lang="ts">
import Motion from "./utils/motion"; import Motion from './utils/motion';
import { useRouter } from "vue-router"; import { useRouter } from 'vue-router';
import { message } from "@/utils/message"; import { message } from '@/utils/message';
import { loginRules } from "./utils/rule"; import { loginRules } from './utils/rule';
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from '@/layout/hooks/useNav';
import type { FormInstance } from "element-plus"; import type { FormInstance } from 'element-plus';
import { useLayout } from "@/layout/hooks/useLayout"; import { useLayout } from '@/layout/hooks/useLayout';
import { useUserStoreHook } from "@/store/modules/user"; import { useUserStoreHook } from '@/store/modules/user';
import { initRouter, getTopMenu } from "@/router/utils"; import { initRouter, getTopMenu } from '@/router/utils';
import { bg, avatar, illustration } from "./utils/static"; import { bg, avatar, illustration } from './utils/static';
import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { useRenderIcon } from '@/components/ReIcon/src/hooks';
import { ref, reactive, toRaw, onMounted, onBeforeUnmount } from "vue"; import { ref, reactive, toRaw, onMounted, onBeforeUnmount } from 'vue';
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange"; import { useDataThemeChange } from '@/layout/hooks/useDataThemeChange';
import dayIcon from "@/assets/svg/day.svg?component"; import dayIcon from '@/assets/svg/day.svg?component';
import darkIcon from "@/assets/svg/dark.svg?component"; import darkIcon from '@/assets/svg/dark.svg?component';
import Lock from "@iconify-icons/ri/lock-fill"; import Lock from '@iconify-icons/ri/lock-fill';
import User from "@iconify-icons/ri/user-3-fill"; import User from '@iconify-icons/ri/user-3-fill';
defineOptions({ defineOptions({
name: "Login" name: 'Login',
}); });
const router = useRouter(); const router = useRouter();
const loading = ref(false); const loading = ref(false);
@ -33,8 +33,8 @@ dataThemeChange(overallStyle.value);
const { title } = useNav(); const { title } = useNav();
const ruleForm = reactive({ const ruleForm = reactive({
username: "admin", username: 'admin',
password: "admin123" password: 'admin123',
}); });
const onLogin = async (formEl: FormInstance | undefined) => { const onLogin = async (formEl: FormInstance | undefined) => {
@ -43,17 +43,17 @@ const onLogin = async (formEl: FormInstance | undefined) => {
if (valid) { if (valid) {
loading.value = true; loading.value = true;
useUserStoreHook() useUserStoreHook()
.loginByUsername({ username: ruleForm.username, password: "admin123" }) .loginByUsername({ username: ruleForm.username, password: 'admin123' })
.then(res => { .then((res) => {
if (res.success) { if (res.success) {
// //
return initRouter().then(() => { return initRouter().then(() => {
router.push(getTopMenu(true).path).then(() => { router.push(getTopMenu(true).path).then(() => {
message("登录成功", { type: "success" }); message('登录成功', { type: 'success' });
}); });
}); });
} else { } else {
message("登录失败", { type: "error" }); message('登录失败', { type: 'error' });
} }
}) })
.finally(() => (loading.value = false)); .finally(() => (loading.value = false));
@ -63,23 +63,26 @@ const onLogin = async (formEl: FormInstance | undefined) => {
/** 使用公共函数,避免`removeEventListener`失效 */ /** 使用公共函数,避免`removeEventListener`失效 */
function onkeypress({ code }: KeyboardEvent) { function onkeypress({ code }: KeyboardEvent) {
if (["Enter", "NumpadEnter"].includes(code)) { if (['Enter', 'NumpadEnter'].includes(code)) {
onLogin(ruleFormRef.value); onLogin(ruleFormRef.value);
} }
} }
onMounted(() => { onMounted(() => {
window.document.addEventListener("keypress", onkeypress); window.document.addEventListener('keypress', onkeypress);
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.document.removeEventListener("keypress", onkeypress); window.document.removeEventListener('keypress', onkeypress);
}); });
</script> </script>
<template> <template>
<div class="select-none"> <div class="select-none">
<img :src="bg" class="wave" /> <img
:src="bg"
class="wave"
/>
<div class="flex-c absolute right-5 top-3"> <div class="flex-c absolute right-5 top-3">
<!-- 主题 --> <!-- 主题 -->
<el-switch <el-switch
@ -96,7 +99,7 @@ onBeforeUnmount(() => {
</div> </div>
<div class="login-box"> <div class="login-box">
<div class="login-form"> <div class="login-form">
<avatar class="avatar" /> <!-- <avatar class="avatar" /> -->
<Motion> <Motion>
<h2 class="outline-none">{{ title }}</h2> <h2 class="outline-none">{{ title }}</h2>
</Motion> </Motion>
@ -113,8 +116,8 @@ onBeforeUnmount(() => {
{ {
required: true, required: true,
message: '请输入账号', message: '请输入账号',
trigger: 'blur' trigger: 'blur',
} },
]" ]"
prop="username" prop="username"
> >
@ -158,7 +161,7 @@ onBeforeUnmount(() => {
</template> </template>
<style scoped> <style scoped>
@import url("@/style/login.css"); @import url('@/style/login.css');
</style> </style>
<style lang="scss" scoped> <style lang="scss" scoped>

Loading…
Cancel
Save