Skip to content

Commit 2e224a8

Browse files
authored
优化 Logo 相关内容 (#2099)
* chore: 更新.gitignore,添加对本地配置文件的忽略 * feat(logo): 新增Logo组件并在多个页面中替换原有logo实现 * fix: 修复菜单 Logo 部分删除文本后显示异常的问题
2 parents 8a9b088 + ec7c57e commit 2e224a8

File tree

6 files changed

+124
-64
lines changed

6 files changed

+124
-64
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ rm_file/
2727
/server/server
2828
/server/latest_log
2929
/server/__debug_bin*
30+
/server/*.local.yaml
3031
server/uploads/
3132

3233
*.iml

web/src/components/logo/index.vue

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<script setup>
2+
import { ref, watchEffect } from 'vue';
3+
import { useAppStore } from '@/pinia/modules/app.js';
4+
import { storeToRefs } from 'pinia';
5+
6+
const props = defineProps({
7+
// logo 尺寸,单位为:rem
8+
size: {
9+
type: Number,
10+
default: 2
11+
}
12+
})
13+
14+
const darkLogoPath = '/logo-dark.png';
15+
const lightLogoPath = '/logo.png';
16+
17+
const appStore = useAppStore();
18+
const { isDark } = storeToRefs(appStore);
19+
20+
const logoSrc = ref('');
21+
const showTextPlaceholder = ref(false);
22+
23+
// 检查图片是否存在
24+
function checkImageExists(url) {
25+
return new Promise((resolve) => {
26+
const tryToLoad = new Image();
27+
tryToLoad.onload = () => resolve(true);
28+
tryToLoad.onerror = () => resolve(false);
29+
tryToLoad.src = url;
30+
});
31+
}
32+
33+
watchEffect(async () => {
34+
showTextPlaceholder.value = false; // 重置占位符状态
35+
36+
// 暗色模式直接 load,可以省一次亮色的 load
37+
if (isDark.value && await checkImageExists(darkLogoPath)) {
38+
logoSrc.value = darkLogoPath;
39+
return;
40+
}
41+
42+
if (await checkImageExists(lightLogoPath)) {
43+
logoSrc.value = lightLogoPath;
44+
return
45+
}
46+
47+
// 到这里就包没有提供两种 logo 了
48+
showTextPlaceholder.value = true;
49+
console.error(
50+
'错误: 在公共目录中找不到logo.png(或logo-dark.png)。'
51+
);
52+
console.warn(
53+
'解决方案: 请在您的公共目录(/public)中放置logo.png和/或logo-dark.png文件,或确保路径正确。'
54+
);
55+
});
56+
57+
// 直接用 16px 作为默认的基准大小
58+
const SPACING = 16
59+
function getSize() {
60+
return {
61+
width: `${props.size * SPACING}px`,
62+
height: `${props.size * SPACING}px`,
63+
}
64+
}
65+
</script>
66+
67+
<template>
68+
<img v-if="!showTextPlaceholder && logoSrc" :src="logoSrc" :alt="$GIN_VUE_ADMIN.appName" class="object-contain"
69+
:style="{
70+
...getSize()
71+
}" :class="{
72+
'filter invert-[90%] hue-rotate-180 brightness-110':
73+
isDark && logoSrc === '/logo.png',
74+
}" />
75+
<div v-else-if="showTextPlaceholder"
76+
class="rounded-full bg-gray-300 dark:bg-gray-600 flex items-center justify-center text-gray-700 dark:text-gray-200 font-bold text-xs"
77+
:style="{
78+
...getSize()
79+
}">
80+
GVA
81+
</div>
82+
</template>

web/src/core/config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ const greenText = (text) => `\x1b[32m${text}\x1b[0m`
77

88
const config = {
99
appName: 'Gin-Vue-Admin',
10-
appLogo: 'logo.png',
1110
showViteLogo: true,
1211
logs: []
1312
}

web/src/view/layout/header/index.vue

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,11 @@
99
>
1010
<div class="flex items-center cursor-pointer flex-1">
1111
<div
12-
class="flex items-center cursor-pointer"
12+
class="flex items-center justify-center cursor-pointer"
1313
:class="isMobile ? '' : 'min-w-48'"
1414
@click="router.push({ path: '/' })"
1515
>
16-
<img
17-
alt
18-
class="h-12 bg-white rounded-full"
19-
:src="$GIN_VUE_ADMIN.appLogo"
20-
/>
16+
<Logo />
2117
<div
2218
v-if="!isMobile"
2319
class="inline-flex font-bold text-2xl ml-2"
@@ -112,6 +108,8 @@
112108
import { setUserAuthority } from '@/api/user'
113109
import { fmtTitle } from '@/utils/fmtRouterTitle'
114110
import gvaAside from '@/view/layout/aside/index.vue'
111+
import Logo from '@/components/logo/index.vue'
112+
115113
const userStore = useUserStore()
116114
const router = useRouter()
117115
const route = useRoute()

web/src/view/layout/setting/modules/general/index.vue

Lines changed: 35 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -49,69 +49,61 @@
4949
<div class="section-content">
5050
<div class="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl p-6 shadow-sm">
5151
<div class="space-y-5">
52-
<div class="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-5 flex items-center justify-between hover:shadow-md transition-all duration-150 ease-in-out hover:-translate-y-0.5">
52+
<div
53+
class="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-5 flex items-center justify-between hover:shadow-md transition-all duration-150 ease-in-out hover:-translate-y-0.5">
5354
<div class="flex items-center gap-4">
54-
<div class="w-12 h-12 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl flex items-center justify-center text-red-600 dark:text-red-400 text-xl">
55+
<div
56+
class="w-12 h-12 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl flex items-center justify-center text-red-600 dark:text-red-400 text-xl">
5557
🔄
5658
</div>
5759
<div>
5860
<h4 class="text-sm font-semibold text-gray-900 dark:text-white">重置配置</h4>
5961
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">将所有设置恢复为默认值</p>
6062
</div>
6163
</div>
62-
<el-button
63-
type="danger"
64-
size="small"
64+
<el-button type="danger" size="small"
6565
class="rounded-lg font-medium transition-all duration-150 ease-in-out hover:-translate-y-0.5"
66-
@click="handleResetConfig"
67-
>
66+
@click="handleResetConfig">
6867
重置配置
6968
</el-button>
7069
</div>
7170

72-
<div class="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-5 flex items-center justify-between hover:shadow-md transition-all duration-150 ease-in-out hover:-translate-y-0.5">
71+
<div
72+
class="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-5 flex items-center justify-between hover:shadow-md transition-all duration-150 ease-in-out hover:-translate-y-0.5">
7373
<div class="flex items-center gap-4">
74-
<div class="w-12 h-12 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-xl flex items-center justify-center text-blue-600 dark:text-blue-400 text-xl">
74+
<div
75+
class="w-12 h-12 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-xl flex items-center justify-center text-blue-600 dark:text-blue-400 text-xl">
7576
📤
7677
</div>
7778
<div>
7879
<h4 class="text-sm font-semibold text-gray-900 dark:text-white">导出配置</h4>
7980
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">导出当前配置为 JSON 文件</p>
8081
</div>
8182
</div>
82-
<el-button
83-
type="primary"
84-
size="small"
83+
<el-button type="primary" size="small"
8584
class="rounded-lg font-medium transition-all duration-150 ease-in-out hover:-translate-y-0.5"
8685
:style="{ backgroundColor: config.primaryColor, borderColor: config.primaryColor }"
87-
@click="handleExportConfig"
88-
>
86+
@click="handleExportConfig">
8987
导出配置
9088
</el-button>
9189
</div>
9290

93-
<div class="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-5 flex items-center justify-between hover:shadow-md transition-all duration-150 ease-in-out hover:-translate-y-0.5">
91+
<div
92+
class="bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg p-5 flex items-center justify-between hover:shadow-md transition-all duration-150 ease-in-out hover:-translate-y-0.5">
9493
<div class="flex items-center gap-4">
95-
<div class="w-12 h-12 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-xl flex items-center justify-center text-green-600 dark:text-green-400 text-xl">
94+
<div
95+
class="w-12 h-12 bg-green-50 dark:bg-green-900/20 border border-green-200 dark:border-green-800 rounded-xl flex items-center justify-center text-green-600 dark:text-green-400 text-xl">
9696
📥
9797
</div>
9898
<div>
9999
<h4 class="text-sm font-semibold text-gray-900 dark:text-white">导入配置</h4>
100100
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">从 JSON 文件导入配置</p>
101101
</div>
102102
</div>
103-
<el-upload
104-
ref="uploadRef"
105-
:auto-upload="false"
106-
:show-file-list="false"
107-
accept=".json"
108-
@change="handleImportConfig"
109-
>
110-
<el-button
111-
type="success"
112-
size="small"
113-
class="rounded-lg font-medium transition-all duration-150 ease-in-out hover:-translate-y-0.5"
114-
>
103+
<el-upload ref="uploadRef" :auto-upload="false" :show-file-list="false" accept=".json"
104+
@change="handleImportConfig">
105+
<el-button type="success" size="small"
106+
class="rounded-lg font-medium transition-all duration-150 ease-in-out hover:-translate-y-0.5">
115107
导入配置
116108
</el-button>
117109
</el-upload>
@@ -131,35 +123,25 @@
131123
<div class="section-content">
132124
<div class="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-xl p-6 shadow-sm">
133125
<div class="flex items-start gap-5">
134-
<div class="w-16 h-16 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-xl flex items-center justify-center flex-shrink-0 shadow-sm">
135-
<img
136-
src="/logo.png"
137-
alt="Gin-Vue-Admin Logo"
138-
class="w-10 h-10 object-contain"
139-
@error="handleLogoError"
140-
/>
126+
<div
127+
class="w-16 h-16 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-xl flex items-center justify-center flex-shrink-0 shadow-sm">
128+
<Logo />
141129
</div>
142130
<div class="flex-1">
143131
<h4 class="text-xl font-semibold text-gray-900 dark:text-white mb-3">Gin-Vue-Admin</h4>
144132
<p class="text-sm text-gray-600 dark:text-gray-400 mb-5 leading-relaxed">
145133
基于 Vue3 + Gin 的全栈开发基础平台,提供完整的后台管理解决方案
146134
</p>
147135
<div class="flex items-center gap-3 text-sm">
148-
<a
149-
href="https://github.com/flipped-aurora/gin-vue-admin"
150-
target="_blank"
136+
<a href="https://github.com/flipped-aurora/gin-vue-admin" target="_blank"
151137
class="font-medium transition-colors duration-150 hover:underline"
152-
:style="{ color: config.primaryColor }"
153-
>
138+
:style="{ color: config.primaryColor }">
154139
GitHub 仓库
155140
</a>
156141
<span class="text-gray-400 dark:text-gray-500">·</span>
157-
<a
158-
href="https://www.gin-vue-admin.com/"
159-
target="_blank"
142+
<a href="https://www.gin-vue-admin.com/" target="_blank"
160143
class="font-medium transition-colors duration-150 hover:underline"
161-
:style="{ color: config.primaryColor }"
162-
>
144+
:style="{ color: config.primaryColor }">
163145
官方文档
164146
</a>
165147
</div>
@@ -172,10 +154,11 @@
172154
</template>
173155

174156
<script setup>
175-
import { ref, computed, onMounted } from 'vue'
157+
import { ref, onMounted } from 'vue'
176158
import { ElMessage, ElMessageBox } from 'element-plus'
177159
import { storeToRefs } from 'pinia'
178160
import { useAppStore } from '@/pinia'
161+
import Logo from '@/components/logo/index.vue'
179162
180163
defineOptions({
181164
name: 'GeneralSettings'
@@ -187,7 +170,6 @@ const uploadRef = ref()
187170
188171
const browserInfo = ref('')
189172
const screenResolution = ref('')
190-
const logoUrl = ref('')
191173
192174
onMounted(() => {
193175
const userAgent = navigator.userAgent
@@ -206,10 +188,6 @@ onMounted(() => {
206188
screenResolution.value = `${screen.width}×${screen.height}`
207189
})
208190
209-
const handleLogoError = () => {
210-
logoUrl.value = ''
211-
}
212-
213191
const handleResetConfig = async () => {
214192
try {
215193
await ElMessageBox.confirm(
@@ -221,7 +199,7 @@ const handleResetConfig = async () => {
221199
type: 'warning'
222200
}
223201
)
224-
202+
225203
appStore.resetConfig()
226204
ElMessage.success('配置已重置')
227205
} catch {
@@ -233,15 +211,15 @@ const handleExportConfig = () => {
233211
const configData = JSON.stringify(config.value, null, 2)
234212
const blob = new Blob([configData], { type: 'application/json' })
235213
const url = URL.createObjectURL(blob)
236-
214+
237215
const link = document.createElement('a')
238216
link.href = url
239217
link.download = `gin-vue-admin-config-${new Date().toISOString().split('T')[0]}.json`
240218
document.body.appendChild(link)
241219
link.click()
242220
document.body.removeChild(link)
243221
URL.revokeObjectURL(url)
244-
222+
245223
ElMessage.success('配置已导出')
246224
}
247225
@@ -250,13 +228,13 @@ const handleImportConfig = (file) => {
250228
reader.onload = (e) => {
251229
try {
252230
const importedConfig = JSON.parse(e.target.result)
253-
231+
254232
Object.keys(importedConfig).forEach(key => {
255233
if (key in config.value) {
256234
config.value[key] = importedConfig[key]
257235
}
258236
})
259-
237+
260238
ElMessage.success('配置已导入')
261239
} catch (error) {
262240
ElMessage.error('配置文件格式错误')
@@ -280,6 +258,7 @@ const handleImportConfig = (file) => {
280258
opacity: 0;
281259
transform: translateY(12px);
282260
}
261+
283262
to {
284263
opacity: 1;
285264
transform: translateY(0);

web/src/view/login/index.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
>
1414
<div>
1515
<div class="flex items-center justify-center">
16-
<img class="w-24" :src="$GIN_VUE_ADMIN.appLogo" alt />
16+
<Logo :size="6" />
1717
</div>
1818
<div class="mb-9">
1919
<p class="text-center text-4xl font-bold">
@@ -131,6 +131,7 @@
131131
import { ElMessage } from 'element-plus'
132132
import { useRouter } from 'vue-router'
133133
import { useUserStore } from '@/pinia/modules/user'
134+
import Logo from '@/components/logo/index.vue'
134135
135136
defineOptions({
136137
name: 'Login'

0 commit comments

Comments
 (0)