feat: 添加炫彩更新提示~

This commit is contained in:
2025-09-09 21:10:41 +08:00
parent fb4dc7fa83
commit 64fb077d65
4 changed files with 158 additions and 19 deletions

View File

@@ -1,7 +1,7 @@
{ {
"name": "frontend", "name": "frontend",
"private": true, "private": true,
"version": "0.0.1", "version": "1.0.1",
"main": "dist-electron/main.js", "main": "dist-electron/main.js",
"scripts": { "scripts": {
"dev": "concurrently \"vite\" \"yarn watch:main\" \"yarn electron-dev\"", "dev": "concurrently \"vite\" \"yarn watch:main\" \"yarn electron-dev\"",

View File

@@ -7,6 +7,12 @@
<span class="logo-glow" aria-hidden="true"></span> <span class="logo-glow" aria-hidden="true"></span>
<img src="@/assets/AUTO-MAS.ico" alt="AUTO-MAS" class="title-logo" /> <img src="@/assets/AUTO-MAS.ico" alt="AUTO-MAS" class="title-logo" />
<span class="title-text">AUTO-MAS</span> <span class="title-text">AUTO-MAS</span>
<span class="version-text">
v{{ version }}
<span v-if="updateInfo?.if_need_update" class="update-hint" :title="getUpdateTooltip()">
检测到更新 {{ updateInfo.latest_version }} 请尽快更新
</span>
</span>
</div> </div>
</div> </div>
@@ -16,26 +22,18 @@
<!-- 右侧窗口控制按钮 --> <!-- 右侧窗口控制按钮 -->
<div class="title-bar-right"> <div class="title-bar-right">
<div class="window-controls"> <div class="window-controls">
<button <button class="control-button minimize-button" @click="minimizeWindow" title="最小化">
class="control-button minimize-button"
@click="minimizeWindow"
title="最小化"
>
<MinusOutlined /> <MinusOutlined />
</button> </button>
<button <button
class="control-button maximize-button" class="control-button maximize-button"
@click="toggleMaximize" @click="toggleMaximize"
:title="isMaximized ? '还原' : '最大化'" :title="isMaximized ? '还原' : '最大化'"
> >
<BorderOutlined v-if="!isMaximized" /> <BorderOutlined v-if="!isMaximized" />
<CopyOutlined v-else /> <CopyOutlined v-else />
</button> </button>
<button <button class="control-button close-button" @click="closeWindow" title="关闭">
class="control-button close-button"
@click="closeWindow"
title="关闭"
>
<CloseOutlined /> <CloseOutlined />
</button> </button>
</div> </div>
@@ -47,10 +45,47 @@
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { MinusOutlined, BorderOutlined, CopyOutlined, CloseOutlined } from '@ant-design/icons-vue' import { MinusOutlined, BorderOutlined, CopyOutlined, CloseOutlined } from '@ant-design/icons-vue'
import { useTheme } from '@/composables/useTheme' import { useTheme } from '@/composables/useTheme'
import { Service } from '@/api'
import type { UpdateCheckOut } from '@/api'
const { isDark } = useTheme() const { isDark } = useTheme()
const isMaximized = ref(false) const isMaximized = ref(false)
// 使用 import.meta.env 或直接定义版本号,确保打包后可用
const version = import.meta.env.VITE_APP_VERSION || '获取版本失败!'
const updateInfo = ref<UpdateCheckOut | null>(null)
// 获取是否有更新
const getAppVersion = async () => {
try {
const ver = await Service.checkUpdateApiUpdateCheckPost({
current_version: version,
})
updateInfo.value = ver
return ver || '获取版本失败!'
} catch (error) {
console.error('Failed to get app version:', error)
return '获取版本失败!'
}
}
// 生成更新提示的详细信息
const getUpdateTooltip = () => {
if (!updateInfo.value?.update_info) return ''
const updateDetails = []
for (const [category, items] of Object.entries(updateInfo.value.update_info)) {
if (items && items.length > 0) {
updateDetails.push(`${category}:`)
items.forEach(item => {
updateDetails.push(`${item}`)
})
updateDetails.push('')
}
}
return updateDetails.join('\n')
}
const minimizeWindow = async () => { const minimizeWindow = async () => {
try { try {
await window.electronAPI?.windowMinimize() await window.electronAPI?.windowMinimize()
@@ -62,7 +97,7 @@ const minimizeWindow = async () => {
const toggleMaximize = async () => { const toggleMaximize = async () => {
try { try {
await window.electronAPI?.windowMaximize() await window.electronAPI?.windowMaximize()
isMaximized.value = await window.electronAPI?.windowIsMaximized() || false isMaximized.value = (await window.electronAPI?.windowIsMaximized()) || false
} catch (error) { } catch (error) {
console.error('Failed to toggle maximize:', error) console.error('Failed to toggle maximize:', error)
} }
@@ -78,10 +113,11 @@ const closeWindow = async () => {
onMounted(async () => { onMounted(async () => {
try { try {
isMaximized.value = await window.electronAPI?.windowIsMaximized() || false isMaximized.value = (await window.electronAPI?.windowIsMaximized()) || false
} catch (error) { } catch (error) {
console.error('Failed to get window state:', error) console.error('Failed to get window state:', error)
} }
await getAppVersion()
}) })
</script> </script>
@@ -124,11 +160,11 @@ onMounted(async () => {
left: 55px; /* 调整:更贴近图标 */ left: 55px; /* 调整:更贴近图标 */
top: 50%; top: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
width: 200px; /* 缩小尺寸以适配 32px 高度 */ width: 200px; /* 缩小尺寸以适配 32px 高度 */
height: 100px; height: 100px;
pointer-events: none; pointer-events: none;
border-radius: 50%; border-radius: 50%;
background: radial-gradient(circle at 50% 50%, var(--ant-color-primary) 0%, rgba(0,0,0,0) 70%); background: radial-gradient(circle at 50% 50%, var(--ant-color-primary) 0%, rgba(0, 0, 0, 0) 70%);
filter: blur(24px); /* 降低模糊避免越界过多 */ filter: blur(24px); /* 降低模糊避免越界过多 */
opacity: 0.4; opacity: 0.4;
z-index: 0; z-index: 0;
@@ -153,10 +189,23 @@ onMounted(async () => {
z-index: 1; z-index: 1;
} }
.version-text {
font-size: 13px;
font-weight: 400;
opacity: 0.8;
position: relative;
z-index: 1;
margin-left: 4px;
}
.title-bar-dark .title-text { .title-bar-dark .title-text {
color: #fff; color: #fff;
} }
.title-bar-dark .version-text {
color: #ffffff;
}
.title-bar-center { .title-bar-center {
flex: 1; flex: 1;
height: 100%; height: 100%;
@@ -218,4 +267,79 @@ onMounted(async () => {
.title-bar-dark .maximize-button:hover { .title-bar-dark .maximize-button:hover {
background: rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.15);
} }
</style>
.update-hint {
font-weight: 500;
margin-left: 4px;
cursor: help;
background: linear-gradient(45deg, #ff0000, #ff7f00, #ffff00, #00ff00, #8b00ff, #ff0000);
background-size: 400% 400%;
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
animation:
rainbow-flow 3s ease-in-out infinite,
glow-pulse 2s ease-in-out infinite;
position: relative;
}
.update-hint::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(45deg, #ff0000, #ff7f00, #ffff00, #00ff00, #8b00ff, #ff0000);
background-size: 400% 400%;
border-radius: 4px;
z-index: -1;
opacity: 0.3;
filter: blur(8px);
animation: rainbow-flow 3s ease-in-out infinite;
}
.title-bar-dark .update-hint::before {
opacity: 0.5;
filter: blur(10px);
}
@keyframes rainbow-flow {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
@keyframes glow-pulse {
0% {
filter: brightness(1) saturate(1);
transform: scale(1);
}
50% {
filter: brightness(1.2) saturate(1.3);
transform: scale(1.02);
}
100% {
filter: brightness(1) saturate(1);
transform: scale(1);
}
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.7;
}
100% {
opacity: 1;
}
}
</style>

View File

@@ -5,9 +5,18 @@ export interface ElectronAPI {
selectFolder: () => Promise<string | null> selectFolder: () => Promise<string | null>
selectFile: (filters?: Array<{ name: string; extensions: string[] }>) => Promise<string | null> selectFile: (filters?: Array<{ name: string; extensions: string[] }>) => Promise<string | null>
// 窗口控制
windowMinimize: () => Promise<void>
windowMaximize: () => Promise<void>
windowClose: () => Promise<void>
windowIsMaximized: () => Promise<boolean>
// 管理员权限检查 // 管理员权限检查
checkAdmin: () => Promise<boolean> checkAdmin: () => Promise<boolean>
// 重启为管理员
restartAsAdmin: () => Promise<void>
// 环境检查 // 环境检查
checkEnvironment: () => Promise<{ checkEnvironment: () => Promise<{
pythonExists: boolean pythonExists: boolean
@@ -53,7 +62,6 @@ export interface ElectronAPI {
callback: (progress: { progress: number; status: string; message: string }) => void callback: (progress: { progress: number; status: string; message: string }) => void
) => void ) => void
removeDownloadProgressListener: () => void removeDownloadProgressListener: () => void
restartAsAdmin: () => Promise<void>
} }
declare global { declare global {

View File

@@ -2,6 +2,9 @@ import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import path from 'path' import path from 'path'
// 读取package.json中的版本号
const packageJson = require('./package.json')
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
@@ -12,4 +15,8 @@ export default defineConfig({
'@': path.resolve(__dirname, './src'), '@': path.resolve(__dirname, './src'),
}, },
}, },
define: {
// 在编译时将版本号注入到环境变量中
'import.meta.env.VITE_APP_VERSION': JSON.stringify(packageJson.version)
}
}) })