feat(update): 添加软件更新检查功能

- 在应用启动时检查 GitHub 上的最新版本
- 如果发现新版本,通过通知提示用户更新
- 新增 GitHubReleaseVersion模型用于解析版本信息
- 在前端添加更新通知的展示逻辑
This commit is contained in:
spark 2025-02-06 16:19:11 +08:00
parent 322e87efbd
commit e55506705e
3 changed files with 137 additions and 11 deletions

27
app.go
View File

@ -16,6 +16,7 @@ import (
"go-stock/backend/data" "go-stock/backend/data"
"go-stock/backend/db" "go-stock/backend/db"
"go-stock/backend/logger" "go-stock/backend/logger"
"go-stock/backend/models"
"strings" "strings"
"time" "time"
) )
@ -48,18 +49,21 @@ func (a *App) startup(ctx context.Context) {
go onExit(a) go onExit(a)
}) })
//检查新版本
go func() {
config := data.NewSettingsApi(&data.Settings{}).GetConfig()
if config.CheckUpdate {
checkUpdate(a)
}
}()
} }
func checkUpdate(a *App) { func checkUpdate(a *App) {
releaseVersion := &models.GitHubReleaseVersion{}
_, err := resty.New().R().
SetResult(releaseVersion).
Get("https://api.github.com/repos/ArvinLovegood/go-stock/releases/latest")
if err != nil {
logger.SugaredLogger.Errorf("get github release version error:%s", err.Error())
return
}
logger.SugaredLogger.Infof("releaseVersion:%+v", releaseVersion.TagName)
if releaseVersion.TagName != Version {
go runtime.EventsEmit(a.ctx, "updateVersion", releaseVersion)
}
} }
// domReady is called after front-end resources have been loaded // domReady is called after front-end resources have been loaded
@ -94,6 +98,11 @@ func (a *App) domReady(ctx context.Context) {
}() }()
go runtime.EventsEmit(a.ctx, "telegraph", refreshTelegraphList()) go runtime.EventsEmit(a.ctx, "telegraph", refreshTelegraphList())
go MonitorStockPrices(a) go MonitorStockPrices(a)
//检查新版本
go func() {
checkUpdate(a)
}()
} }
func refreshTelegraphList() *[]string { func refreshTelegraphList() *[]string {

83
backend/models/models.go Normal file
View File

@ -0,0 +1,83 @@
package models
import "time"
// @Author spark
// @Date 2025/2/6 15:25
// @Desc
//-----------------------------------------------------------------------------------
type GitHubReleaseVersion struct {
Url string `json:"url"`
AssetsUrl string `json:"assets_url"`
UploadUrl string `json:"upload_url"`
HtmlUrl string `json:"html_url"`
Id int `json:"id"`
Author struct {
Login string `json:"login"`
Id int `json:"id"`
NodeId string `json:"node_id"`
AvatarUrl string `json:"avatar_url"`
GravatarId string `json:"gravatar_id"`
Url string `json:"url"`
HtmlUrl string `json:"html_url"`
FollowersUrl string `json:"followers_url"`
FollowingUrl string `json:"following_url"`
GistsUrl string `json:"gists_url"`
StarredUrl string `json:"starred_url"`
SubscriptionsUrl string `json:"subscriptions_url"`
OrganizationsUrl string `json:"organizations_url"`
ReposUrl string `json:"repos_url"`
EventsUrl string `json:"events_url"`
ReceivedEventsUrl string `json:"received_events_url"`
Type string `json:"type"`
UserViewType string `json:"user_view_type"`
SiteAdmin bool `json:"site_admin"`
} `json:"author"`
NodeId string `json:"node_id"`
TagName string `json:"tag_name"`
TargetCommitish string `json:"target_commitish"`
Name string `json:"name"`
Draft bool `json:"draft"`
Prerelease bool `json:"prerelease"`
CreatedAt time.Time `json:"created_at"`
PublishedAt time.Time `json:"published_at"`
Assets []struct {
Url string `json:"url"`
Id int `json:"id"`
NodeId string `json:"node_id"`
Name string `json:"name"`
Label string `json:"label"`
Uploader struct {
Login string `json:"login"`
Id int `json:"id"`
NodeId string `json:"node_id"`
AvatarUrl string `json:"avatar_url"`
GravatarId string `json:"gravatar_id"`
Url string `json:"url"`
HtmlUrl string `json:"html_url"`
FollowersUrl string `json:"followers_url"`
FollowingUrl string `json:"following_url"`
GistsUrl string `json:"gists_url"`
StarredUrl string `json:"starred_url"`
SubscriptionsUrl string `json:"subscriptions_url"`
OrganizationsUrl string `json:"organizations_url"`
ReposUrl string `json:"repos_url"`
EventsUrl string `json:"events_url"`
ReceivedEventsUrl string `json:"received_events_url"`
Type string `json:"type"`
UserViewType string `json:"user_view_type"`
SiteAdmin bool `json:"site_admin"`
} `json:"uploader"`
ContentType string `json:"content_type"`
State string `json:"state"`
Size int `json:"size"`
DownloadCount int `json:"download_count"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
BrowserDownloadUrl string `json:"browser_download_url"`
} `json:"assets"`
TarballUrl string `json:"tarball_url"`
ZipballUrl string `json:"zipball_url"`
Body string `json:"body"`
}

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import {computed, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue' import {computed, h, onBeforeMount, onBeforeUnmount, onMounted, reactive, ref} from 'vue'
import { import {
Follow, GetConfig, Follow, GetConfig,
GetFollowList, GetFollowList,
@ -10,7 +10,18 @@ import {
SetCostPriceAndVolume, SetStockSort, SetCostPriceAndVolume, SetStockSort,
UnFollow UnFollow
} from '../../wailsjs/go/main/App' } from '../../wailsjs/go/main/App'
import {NButton, NFlex, NForm, NFormItem, NInputNumber, NText, useMessage, useModal,useNotification} from 'naive-ui' import {
NAvatar,
NButton,
NFlex,
NForm,
NFormItem,
NInputNumber,
NText,
useMessage,
useModal,
useNotification
} from 'naive-ui'
import {EventsOn, WindowFullscreen, WindowReload, WindowUnfullscreen} from '../../wailsjs/runtime' import {EventsOn, WindowFullscreen, WindowReload, WindowUnfullscreen} from '../../wailsjs/runtime'
import {Add, Search,StarOutline} from '@vicons/ionicons5' import {Add, Search,StarOutline} from '@vicons/ionicons5'
import { MdPreview } from 'md-editor-v3'; import { MdPreview } from 'md-editor-v3';
@ -148,6 +159,29 @@ EventsOn("newChatStream",async (msg) => {
} }
}) })
EventsOn("updateVersion",async (msg) => {
notify.info({
avatar: () =>
h(NAvatar, {
size: 'small',
round: false,
src: 'https://github.com/ArvinLovegood/go-stock/raw/master/build/appicon.png'
}),
title: '发现新版本',
content: '请前往发布页下载更新',
duration: 0,
meta: msg.name,
action: () => {
return h(NButton, {
type: 'primary',
size: 'small',
onClick: () => {
window.open(msg.html_url)
}
}, { default: () => '查看' })
}
})
})
//A //A