提交 36decf64 作者: 方治民

feat: 添加版本更新相关实现

上级 d746409c
......@@ -73,8 +73,9 @@
"@stomp/stompjs": "^7.0.0",
"@vue/runtime-core": "^3.2.47",
"@vue/shared": "^3.2.47",
"@vueuse/core": "^9.13.0",
"@vueuse/shared": "^9.13.0",
"@vueuse/core": "^10.1.0",
"@vueuse/electron": "^10.1.0",
"@vueuse/shared": "^10.1.0",
"@zxcvbn-ts/core": "^2.2.1",
"ant-design-vue": "^3.2.19",
"axios": "^0.26.1",
......@@ -84,6 +85,8 @@
"dayjs": "^1.11.7",
"default-passive-events": "^2.0.0",
"echarts": "^5.4.2",
"electron-log": "^4.4.8",
"electron-updater": "^5.3.0",
"intro.js": "^7.0.1",
"js-file-download": "^0.4.12",
"lodash-es": "^4.17.21",
......@@ -150,7 +153,7 @@
"dotenv": "^16.0.3",
"electron": "^23.2.4",
"electron-builder": "^23.6.0",
"electron-vite": "1.0.21",
"electron-vite": "^1.0.22",
"eslint": "^8.39.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
......
......@@ -35,11 +35,14 @@ dependencies:
specifier: ^3.2.47
version: 3.2.47
'@vueuse/core':
specifier: ^9.13.0
version: 9.13.0(vue@3.2.47)
specifier: ^10.1.0
version: 10.1.0(vue@3.2.47)
'@vueuse/electron':
specifier: ^10.1.0
version: 10.1.0(electron@23.2.4)(vue@3.2.47)
'@vueuse/shared':
specifier: ^9.13.0
version: 9.13.0(vue@3.2.47)
specifier: ^10.1.0
version: 10.1.0(vue@3.2.47)
'@zxcvbn-ts/core':
specifier: ^2.2.1
version: 2.2.1
......@@ -67,6 +70,12 @@ dependencies:
echarts:
specifier: ^5.4.2
version: 5.4.2
electron-log:
specifier: ^4.4.8
version: 4.4.8
electron-updater:
specifier: ^5.3.0
version: 5.3.0
intro.js:
specifier: ^7.0.1
version: 7.0.1
......@@ -262,8 +271,8 @@ devDependencies:
specifier: ^23.6.0
version: 23.6.0
electron-vite:
specifier: 1.0.21
version: 1.0.21(vite@4.3.2)
specifier: ^1.0.22
version: 1.0.22(vite@4.3.2)
eslint:
specifier: ^8.39.0
version: 8.39.0
......@@ -356,7 +365,7 @@ devDependencies:
version: 5.0.4
unplugin-auto-import:
specifier: ^0.15.3
version: 0.15.3(@vueuse/core@9.13.0)(rollup@3.21.0)
version: 0.15.3(@vueuse/core@10.1.0)(rollup@3.21.0)
vite:
specifier: ^4.3.2
version: 4.3.2(@types/node@18.16.1)(less@4.1.3)(terser@5.17.1)
......@@ -2940,7 +2949,6 @@ packages:
/@types/semver@7.3.13:
resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==}
dev: true
/@types/showdown@2.0.0:
resolution: {integrity: sha512-70xBJoLv+oXjB5PhtA8vo7erjLDp9/qqI63SRHm4REKrwuPOLs8HhXwlZJBJaB4kC18cCZ1UUZ6Fb/PLFW4TCA==}
......@@ -3348,22 +3356,35 @@ packages:
'@vue/server-renderer': 3.2.47(vue@3.2.47)
dev: true
/@vueuse/core@9.13.0(vue@3.2.47):
resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
/@vueuse/core@10.1.0(vue@3.2.47):
resolution: {integrity: sha512-3Znoa5m5RO+z4/C9w6DRaKTR3wCVJvD5rav8HTDGsr+7rOZRHtcgFJ8NcCs0ZvIpmev2kExTa311ns5j2RbzDQ==}
dependencies:
'@types/web-bluetooth': 0.0.16
'@vueuse/metadata': 9.13.0
'@vueuse/shared': 9.13.0(vue@3.2.47)
'@vueuse/metadata': 10.1.0
'@vueuse/shared': 10.1.0(vue@3.2.47)
vue-demi: 0.14.0(vue@3.2.47)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
/@vueuse/metadata@9.13.0:
resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
/@vueuse/electron@10.1.0(electron@23.2.4)(vue@3.2.47):
resolution: {integrity: sha512-Y8PlZISpS+Wj3uM5eHW2WtSh3T9BZysnTKuCGxr2JcnyNfsl7K9QtSNSkZkrXEYX2NsBz6WK6VzXpOocDo0NEg==}
peerDependencies:
electron: '>=9.0.0'
dependencies:
'@vueuse/shared': 10.1.0(vue@3.2.47)
electron: 23.2.4
vue-demi: 0.14.0(vue@3.2.47)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
dev: false
/@vueuse/shared@9.13.0(vue@3.2.47):
resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
/@vueuse/metadata@10.1.0:
resolution: {integrity: sha512-cM28HjDEw5FIrPE9rgSPFZvQ0ZYnOLAOr8hl1XM6tFl80U3WAR5ROdnAqiYybniwP5gt9MKKAJAqd/ab2aHkqg==}
/@vueuse/shared@10.1.0(vue@3.2.47):
resolution: {integrity: sha512-2X52ogu12i9DkKOQ01yeb/BKg9UO87RNnpm5sXkQvyORlbq8ONS5l39MYkjkeVWWjdT0teJru7a2S41dmHmqjQ==}
dependencies:
vue-demi: 0.14.0(vue@3.2.47)
transitivePeerDependencies:
......@@ -3612,7 +3633,6 @@ packages:
/argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
dev: true
/arr-diff@4.0.0:
resolution: {integrity: sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==}
......@@ -4006,7 +4026,6 @@ packages:
sax: 1.2.4
transitivePeerDependencies:
- supports-color
dev: true
/builder-util@23.6.0:
resolution: {integrity: sha512-QiQHweYsh8o+U/KNCZFSvISRnvRctb8m/2rB2I1JdByzvNKxPeFLlHFRPQRXab6aYeXc18j9LpsDLJ3sGQmWTQ==}
......@@ -5335,6 +5354,10 @@ packages:
- supports-color
dev: true
/electron-log@4.4.8:
resolution: {integrity: sha512-QQ4GvrXO+HkgqqEOYbi+DHL7hj5JM+nHi/j+qrN9zeeXVKy8ZABgbu4CnG+BBqDZ2+tbeq9tUC4DZfIWFU5AZA==}
dev: false
/electron-osx-sign@0.6.0:
resolution: {integrity: sha512-+hiIEb2Xxk6eDKJ2FFlpofCnemCbjbT5jz+BKGpVBrRNT3kWTGs4DfNX6IzGwgi33hUcXF+kFs9JW+r6Wc1LRg==}
engines: {node: '>=4.0.0'}
......@@ -5369,8 +5392,24 @@ packages:
resolution: {integrity: sha512-MrlFq/j+TYHOjeWsWGYfzevc25HNeJdsF6qaLFrqBTRWZQtWkb1myq/Q2veLWezVaa5OcSZ99CFwTT4aF4Mung==}
dev: true
/electron-vite@1.0.21(vite@4.3.2):
resolution: {integrity: sha512-Ur6AMc6Eej7YK5hGK5hVQGJLZotz0msWhvelVRf/oreWMYd0mmc94CIj9traHScYvBRsO2uqdkwD59/E7j0q2Q==}
/electron-updater@5.3.0:
resolution: {integrity: sha512-iKEr7yQBcvnQUPnSDYGSWC9t0eF2YbZWeYYYZzYxdl+HiRejXFENjYMnYjoOm2zxyD6Cr2JTHZhp9pqxiXuCOw==}
dependencies:
'@types/semver': 7.3.13
builder-util-runtime: 9.1.1
fs-extra: 10.1.0
js-yaml: 4.1.0
lazy-val: 1.0.5
lodash.escaperegexp: 4.1.2
lodash.isequal: 4.5.0
semver: 7.5.0
typed-emitter: 2.1.0
transitivePeerDependencies:
- supports-color
dev: false
/electron-vite@1.0.22(vite@4.3.2):
resolution: {integrity: sha512-RMzMIkOhjk7Lq7NuMk6kMTYta8Zy8mg8AxApgpL3kUJxfCQGJH4oODcNUuAAn49kuD+Zy4W2lQbpn5aDHsGfLg==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
peerDependencies:
......@@ -6619,7 +6658,6 @@ packages:
graceful-fs: 4.2.11
jsonfile: 6.1.0
universalify: 2.0.0
dev: true
/fs-extra@11.1.1:
resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==}
......@@ -7800,7 +7838,6 @@ packages:
hasBin: true
dependencies:
argparse: 2.0.1
dev: true
/jsesc@0.5.0:
resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==}
......@@ -7887,7 +7924,6 @@ packages:
universalify: 2.0.0
optionalDependencies:
graceful-fs: 4.2.11
dev: true
/jsonparse@1.3.1:
resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
......@@ -7947,7 +7983,6 @@ packages:
/lazy-val@1.0.5:
resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==}
dev: true
/less@4.1.3:
resolution: {integrity: sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==}
......@@ -8096,6 +8131,14 @@ packages:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
dev: true
/lodash.escaperegexp@4.1.2:
resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==}
dev: false
/lodash.isequal@4.5.0:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
dev: false
/lodash.isfunction@3.0.9:
resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==}
dev: true
......@@ -9854,7 +9897,6 @@ packages:
resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==}
dependencies:
tslib: 2.5.0
dev: true
/safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
......@@ -9894,7 +9936,6 @@ packages:
/sax@1.2.4:
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
dev: true
/scroll-into-view-if-needed@2.2.31:
resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
......@@ -10887,7 +10928,6 @@ packages:
/tslib@2.5.0:
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
dev: true
/tsutils@3.21.0(typescript@5.0.4):
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
......@@ -10975,6 +11015,12 @@ packages:
is-typed-array: 1.1.10
dev: true
/typed-emitter@2.1.0:
resolution: {integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==}
optionalDependencies:
rxjs: 7.8.0
dev: false
/typedarray-to-buffer@3.1.5:
resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==}
dependencies:
......@@ -11089,14 +11135,13 @@ packages:
/universalify@2.0.0:
resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
engines: {node: '>= 10.0.0'}
dev: true
/unpipe@1.0.0:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
dev: true
/unplugin-auto-import@0.15.3(@vueuse/core@9.13.0)(rollup@3.21.0):
/unplugin-auto-import@0.15.3(@vueuse/core@10.1.0)(rollup@3.21.0):
resolution: {integrity: sha512-RLT8SqbPn4bT7yBshZId0uPSofKWnwr66RyDaxWaFb/+f7OTDOWAsVNz+hOQLBWSjvbekr2xZY9ccS8TDHJbCQ==}
engines: {node: '>=14'}
peerDependencies:
......@@ -11110,7 +11155,7 @@ packages:
dependencies:
'@antfu/utils': 0.7.2
'@rollup/pluginutils': 5.0.2(rollup@3.21.0)
'@vueuse/core': 9.13.0(vue@3.2.47)
'@vueuse/core': 10.1.0(vue@3.2.47)
local-pkg: 0.4.3
magic-string: 0.30.0
minimatch: 9.0.0
......
import log from 'electron-log'
import { autoUpdater } from 'electron-updater'
import type { BrowserWindow } from 'electron'
import { ipcMain } from 'electron'
autoUpdater.logger = log
log.info('App starting...')
type MessageType =
| 'checking-for-update'
| 'error'
| 'update-available'
| 'update-not-available'
| 'download-progress'
| 'update-downloaded'
export async function useUpdater(win: BrowserWindow) {
function checkForUpdate() {
autoUpdater.checkForUpdates()
}
function sendUpdateMessageToWindow(body: { type: MessageType; text: string }) {
log.info(`${body.type}: ${body.text}`)
win.webContents.send('updater-message', body)
}
autoUpdater.on('checking-for-update', () => {
sendUpdateMessageToWindow({ type: 'checking-for-update', text: '正在检查更新...' })
})
autoUpdater.on('update-available', (info) => {
sendUpdateMessageToWindow({ type: 'update-available', text: `发现新版本 v${info.version}` })
})
autoUpdater.on('update-not-available', () => {
sendUpdateMessageToWindow({ type: 'update-not-available', text: '当前已是最新版本!' })
})
autoUpdater.on('error', (err) => {
sendUpdateMessageToWindow({ type: 'error', text: err.message })
})
autoUpdater.on('download-progress', (progress) => {
sendUpdateMessageToWindow({
type: 'download-progress',
text: `正在下载新版本 ${Number(progress.percent).toFixed(2)}%`,
})
})
autoUpdater.on('update-downloaded', () => {
sendUpdateMessageToWindow({ type: 'update-downloaded', text: '下载完成' })
setTimeout(() => {
// 退出并安装更新包
autoUpdater.quitAndInstall(false, true)
win.destroy()
}, 1500)
})
// 监听界面发送的检查更新事件
ipcMain.on('checkForUpdate', () => {
checkForUpdate()
})
// 检查更新
checkForUpdate()
}
import type { IpcRenderer, IpcRendererEvent } from 'electron'
import type { UseIpcRendererReturn } from '@vueuse/electron'
import { useIpcRenderer } from '@vueuse/electron'
const ipc = useIpcRenderer()
export type IpcRendererListener = (event: IpcRendererEvent, ...args: any[]) => void
export interface UserIpcRendererRetrun extends UseIpcRendererReturn {
invokeAsync<T>(channel: string, ...args: any[]): Promise<T | null>
}
export interface UseElectronReturn {
ipcRenderer: UserIpcRendererRetrun
}
export function useElectron(ipcRenderer?: IpcRenderer): UseElectronReturn {
if (!ipcRenderer) ipcRenderer = window?.require('electron').ipcRenderer
if (!ipcRenderer) throw new Error('provide IpcRenderer module or enable nodeIntegration')
return {
ipcRenderer: {
on: ipc.on,
once: ipc.once,
removeListener: ipc.removeListener,
removeAllListeners: ipc.removeAllListeners,
send: ipc.send,
sendSync: ipc.sendSync,
sendTo: ipc.sendTo,
sendToHost: ipc.sendToHost,
postMessage: ipc.postMessage,
invoke: ipc.invoke,
invokeAsync: <T>(channel: string, ...args: any[]): Promise<T> => ipcRenderer.invoke(channel, ...args),
},
}
}
<script setup lang="tsx">
import dayjs from 'dayjs'
import { BasicModal } from '/@/components/Modal'
import { Icon } from '/@/components/Icon'
import { useElectron } from '@/hooks/electron/useElectron'
import { useMessage } from '@/hooks/web/useMessage'
import { getEnvText } from '/@/utils/env'
type MessageType =
| 'checking-for-update'
| 'error'
| 'update-available'
| 'update-not-available'
| 'download-progress'
| 'update-downloaded'
const { ipcRenderer: ipc } = useElectron()
const { createMessage } = useMessage()
const startYear = 2021
const currentYear = dayjs().year()
const yearText = ref<string>(currentYear === startYear ? `${currentYear}` : `${startYear} - ${currentYear}`)
const loading = ref<boolean>(false)
// 监听检查更新事件
let hide = null
ipc.on('updater-message', (_e, body: { type: MessageType; text: string }) => {
console.log('updater-message', body)
const { type, text } = body
if (type === 'checking-for-update' || type === 'download-progress') {
loading.value = true
hide = createMessage.loading({
key: 'updating',
content: text,
duration: 0,
})
} else if (type === 'update-available' || type === 'update-not-available' || type === 'update-downloaded') {
createMessage.success(text)
} else if (type === 'error') {
createMessage.error(text)
}
if (type === 'error' || type === 'update-downloaded' || type === 'update-not-available') {
loading.value = false
hide?.()
}
})
</script>
<template>
<BasicModal v-bind="$attrs" centered :footer="null" :canFullscreen="false">
<!-- 关于信息 -->
<template #title>
<a-space>
<Icon icon="ant-design:info-circle-outlined" :size="22" />
<div class="title-text">关于</div>
</a-space>
</template>
<div class="about-wrap">
<!-- 公司 + 版权信息 -->
<div class="about-app-info-wrap">
<div class="app-icon">
<img src="logo.png" />
</div>
<!-- <div class="app-name">{{ $app.name }}</div> -->
<div class="app-description">{{ $app.description }}</div>
<div class="app-version">
<a-tooltip>
<template #title>
<div class="flex flex-col items-center justify-center">
<div class="version-mode">{{ getEnvText() }}</div>
<div class="update-time">发布时间: {{ $app.lastBuildTime }}</div>
</div>
</template>
<a-button type="text">
<span class="version-text">{{ $app.version }}</span>
</a-button>
</a-tooltip>
</div>
<!-- 检查版本更新按钮 -->
<div class="app-check-update-action">
<a-button type="dashed" :loading="loading" @click="ipc.send('checkForUpdate')">
<Icon icon="ant-design:bulb-outlined" v-show="!loading" />
检查更新
</a-button>
</div>
</div>
<!-- 版本信息 -->
<div class="about-footer">
<div class="company">长沙壹润信息科技发展有限公司</div>
<div class="copyright">
<span>Copyright © {{ yearText }}</span>
<span class="link">
<a target="_blank" href="https://yiring.com">YiRing.com</a>
</span>
</div>
</div>
</div>
</BasicModal>
</template>
<style lang="less" scoped>
.about-wrap {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}
.about-app-info-wrap {
display: flex;
flex-direction: column;
align-items: center;
> div {
margin-top: 10px;
}
.app-icon {
width: 50px;
}
.app-description {
font-weight: bold;
}
.app-version {
display: flex;
flex-direction: column;
align-items: center;
.version-text::before {
content: 'V';
margin-right: 2px;
}
}
}
.about-footer {
height: 60px;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
color: #898989;
font-size: 13px;
user-select: none;
letter-spacing: 1px;
.company {
letter-spacing: 2px;
}
.link {
margin-left: 5px;
&:hover {
text-decoration: underline;
cursor: pointer;
}
a {
color: #898989;
margin-left: 3px;
}
}
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论