Browse Source

change upgrade

master
godo 9 months ago
parent
commit
f77ebc4621
  1. 1
      frontend/components.d.ts
  2. 27
      frontend/src/components/desktop/Ad.vue
  3. 2
      frontend/src/components/desktop/Desktop.vue
  4. 61
      frontend/src/components/desktop/Notice.vue
  5. 66
      frontend/src/stores/upgrade.ts
  6. 56
      frontend/src/system/event/SystemEvent.ts
  7. 20
      frontend/src/system/index.ts
  8. 1
      frontend/vite.config.ts
  9. 2
      godo/cmd/main.go
  10. 90
      godo/sys/msg.go
  11. 60
      godo/sys/update.go

1
frontend/components.d.ts

@ -92,6 +92,7 @@ declare module 'vue' {
NetWork: typeof import('./src/components/taskbar/NetWork.vue')['default'] NetWork: typeof import('./src/components/taskbar/NetWork.vue')['default']
NetworkPop: typeof import('./src/components/taskbar/NetworkPop.vue')['default'] NetworkPop: typeof import('./src/components/taskbar/NetworkPop.vue')['default']
NotFound: typeof import('./src/components/window/NotFound.vue')['default'] NotFound: typeof import('./src/components/window/NotFound.vue')['default']
Notice: typeof import('./src/components/desktop/Notice.vue')['default']
NotifyGroup: typeof import('./src/components/builtin/NotifyGroup.vue')['default'] NotifyGroup: typeof import('./src/components/builtin/NotifyGroup.vue')['default']
OpeningDesktop: typeof import('./src/components/desktop/OpeningDesktop.vue')['default'] OpeningDesktop: typeof import('./src/components/desktop/OpeningDesktop.vue')['default']
OpenWiteDialog: typeof import('./src/components/builtin/OpenWiteDialog.vue')['default'] OpenWiteDialog: typeof import('./src/components/builtin/OpenWiteDialog.vue')['default']

27
frontend/src/components/desktop/Ad.vue

@ -1,9 +1,9 @@
<template> <template>
<div class="ad-container" v-show="state.ad.isShow" @click="onSponsorsClick"> <div class="ad-container" v-if="upgradeStore.hasAd" @click="onSponsorsClick">
<el-carousel height="240px" indicator-position="none" :arrow="setCarouselShow" @change="onCarouselChange"> <el-carousel height="350px" indicator-position="none" :arrow="setCarouselShow" @change="onCarouselChange">
<el-carousel-item v-for="(v, k) in upgradeStore.adList" :key="k"> <el-carousel-item v-for="(v, k) in upgradeStore.adList" :key="k">
<img :src="v.url" v-if="v.url" class="ad-img" /> <img :src="v.img" v-if="v.img && v.img != ''" class="ad-img" />
<div class="ad-text" v-html="v.text"></div> <div class="ad-text" v-html="v.desc"></div>
</el-carousel-item> </el-carousel-item>
</el-carousel> </el-carousel>
<div class="ad-close"> <div class="ad-close">
@ -15,7 +15,7 @@
</template> </template>
<script setup lang="ts" name="layoutSponsors"> <script setup lang="ts" name="layoutSponsors">
import { reactive, computed, onMounted } from 'vue'; import { reactive, computed } from 'vue';
import { useUpgradeStore } from '@/stores/upgrade'; import { useUpgradeStore } from '@/stores/upgrade';
const upgradeStore = useUpgradeStore(); const upgradeStore = useUpgradeStore();
@ -31,9 +31,9 @@ const state = reactive({
const setCarouselShow = computed(() => { const setCarouselShow = computed(() => {
return upgradeStore.adList.length <= 1 ? 'never' : 'hover'; return upgradeStore.adList.length <= 1 ? 'never' : 'hover';
}); });
// //
const onCloseSponsors = () => { const onCloseSponsors = () => {
state.ad.isShow = false; upgradeStore.hasAd = false;
}; };
// //
const onCarouselChange = (e: number) => { const onCarouselChange = (e: number) => {
@ -46,16 +46,6 @@ const onSponsorsClick = () => {
window.open(link) window.open(link)
} }
}; };
//
const delayShow = () => {
setTimeout(() => {
state.ad.isShow = true;
}, 3000);
};
//
onMounted(() => {
delayShow();
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@ -73,12 +63,13 @@ onMounted(() => {
cursor: pointer; cursor: pointer;
.ad-img { .ad-img {
width: 100%; width: 100%;
height: 80px; height: 100px;
} }
.ad-text { .ad-text {
padding: 10px; padding: 10px;
color: #303133; color: #303133;
font-size: 14px; font-size: 14px;
text-align: left;
} }
.ad-close { .ad-close {
width: 60px; width: 60px;

2
frontend/src/components/desktop/Desktop.vue

@ -17,7 +17,7 @@
<NotifyGroup></NotifyGroup> <NotifyGroup></NotifyGroup>
<MessageCenterPop></MessageCenterPop> <MessageCenterPop></MessageCenterPop>
<Chosen></Chosen> <Chosen></Chosen>
<Sponsors v-if="upgradeStore.hasNotice"></Sponsors> <Notice v-if="upgradeStore.hasNotice"></Notice>
<Upgrade v-if="upgradeStore.hasUpgrade"></Upgrade> <Upgrade v-if="upgradeStore.hasUpgrade"></Upgrade>
<Ad v-if="upgradeStore.hasAd"></Ad> <Ad v-if="upgradeStore.hasAd"></Ad>
</div> </div>

61
frontend/src/components/desktop/Sponsors.vue → frontend/src/components/desktop/Notice.vue

@ -1,35 +1,27 @@
<template> <template>
<div class="sponsors-container" v-show="state.sponsors.isShow" @click="onSponsorsClick"> <div class="notice-container" v-if="upgradeStore.hasNotice" @click="onnoticeClick">
<el-carousel height="240px" indicator-position="none" :arrow="setCarouselShow" @change="onCarouselChange"> <el-carousel height="240px" indicator-position="none" :arrow="setCarouselShow" @change="onCarouselChange">
<el-carousel-item v-for="(v, k) in upgradeStore.noticeList" :key="k"> <el-carousel-item v-for="(v, k) in upgradeStore.noticeList" :key="k">
<img :src="v.url" v-if="v.url" class="sponsors-img" /> <img :src="v.img" v-if="v.img && v.img != ''" class="notice-img" />
<div class="sponsors-text" v-html="v.text"></div> <div class="notice-text" v-html="v.desc"></div>
</el-carousel-item> </el-carousel-item>
</el-carousel> </el-carousel>
<div class="sponsors-close"> <div class="notice-close">
<el-icon :size="20" @click.stop="onCloseSponsors"> <el-icon :size="20" @click.stop="onClosenotice">
<CircleCloseFilled /> <CircleCloseFilled />
</el-icon> </el-icon>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts" name="layoutSponsors"> <script setup lang="ts" name="layoutnotice">
import { reactive, computed, onMounted } from 'vue'; import { reactive, computed } from 'vue';
import { useUpgradeStore } from '@/stores/upgrade'; import { useUpgradeStore } from '@/stores/upgrade';
const upgradeStore = useUpgradeStore(); const upgradeStore = useUpgradeStore();
// //
const state = reactive({ const state = reactive({
sponsors: { notice: {
// list: [
// {
// url: "",
// text: "",
// link: '',
// },
// ],
isShow: false,
index: 0, index: 0,
}, },
}); });
@ -38,38 +30,28 @@ const state = reactive({
const setCarouselShow = computed(() => { const setCarouselShow = computed(() => {
return upgradeStore.noticeList.length <= 1 ? 'never' : 'hover'; return upgradeStore.noticeList.length <= 1 ? 'never' : 'hover';
}); });
// //
const onCloseSponsors = () => { const onClosenotice = () => {
state.sponsors.isShow = false; upgradeStore.hasNotice = false;
}; };
// //
const onCarouselChange = (e: number) => { const onCarouselChange = (e: number) => {
state.sponsors.index = e; state.notice.index = e;
}; };
// //
const onSponsorsClick = () => { const onnoticeClick = () => {
const link = upgradeStore.noticeList[state.sponsors.index]?.link const link = upgradeStore.noticeList[state.notice.index]?.link
if(link){ if(link){
window.open(link) window.open(link)
} }
}; };
//
const delayShow = () => {
setTimeout(() => {
state.sponsors.isShow = true;
}, 3000);
};
//
onMounted(() => {
delayShow();
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.sponsors-container { .notice-container {
position: fixed; position: fixed;
right: 6px; right: 5px;
bottom: 48px; bottom: 50px;
z-index: 3; z-index: 3;
width: 200px; width: 200px;
background-color: #ffffff; background-color: #ffffff;
@ -77,16 +59,17 @@ onMounted(() => {
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
cursor: pointer; cursor: pointer;
.sponsors-img { .notice-img {
width: 100%; width: 100%;
height: 80px; height: 80px;
} }
.sponsors-text { .notice-text {
padding: 10px; padding: 10px;
color: #303133; color: #303133;
font-size: 14px; font-size: 12px;
text-align: left;
} }
.sponsors-close { .notice-close {
width: 60px; width: 60px;
height: 60px; height: 60px;
border-radius: 100%; border-radius: 100%;

66
frontend/src/stores/upgrade.ts

@ -34,16 +34,50 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
// 如果所有部分都相等,则返回0 // 如果所有部分都相等,则返回0
return 0; return 0;
} }
async function checkUpdate() { function systemMessage(){
const config = getSystemConfig();
const source = new EventSource(`${config.apiUrl}/system/message`);
source.onmessage = function(event) {
const data = JSON.parse(event.data);
//console.log(data)
handleMessage(data);
};
source.onerror = function(event) {
console.error('EventSource error:', event);
};
}
async function handleMessage(message:any) {
switch (message.type) {
case 'update':
checkUpdate(message.data.data)
break;
default:
console.warn('Unknown message type:', message.type);
}
}
async function checkUpdate(res:any) {
console.log(res)
const config = getSystemConfig(); const config = getSystemConfig();
currentVersion.value = config.version; currentVersion.value = config.version;
const releaseRes = await fetch(`${config.apiUrl}/system/updateInfo`) let bottomList:any = []
if (!releaseRes.ok) return; let centerList:any = []
const releaseData = await releaseRes.json() if (res.adlist && res.adlist.length > 0) {
if(releaseData.code !== 200){ bottomList = res.adlist[0]['bottom']
return centerList = res.adlist[0]['center']
} }
const res = releaseData.data if(bottomList && bottomList.length > 0){
hasNotice.value = true
noticeList.value = changeUrl(bottomList)
}
console.log(noticeList)
console.log(centerList)
if(centerList && centerList.length > 0){
hasAd.value = true
adList.value = changeUrl(centerList)
}
console.log(adList.value)
if(!res.version || res.version == ""){ if(!res.version || res.version == ""){
return return
} }
@ -53,17 +87,14 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
hasUpgrade.value = true hasUpgrade.value = true
updateUrl.value = res.url updateUrl.value = res.url
} }
if (res.adList) { }
if(res.adList.center && res.adList.center.length > 0){ function changeUrl(list : any){
hasNotice.value = true list.forEach((item:any) => {
noticeList.value = res.adList.center if(item.img && item.img.indexOf('http') == -1){
} item.img = `https://godoos.com${item.img}`
if(res.adList.bottom && res.adList.bottom.length > 0){
hasAd.value = true
adList.value = res.adList.bottom
} }
});
} return list
} }
async function update() { async function update() {
const apiUrl = getSystemKey('apiUrl') const apiUrl = getSystemKey('apiUrl')
@ -116,6 +147,7 @@ export const useUpgradeStore = defineStore('upgradeStore', () => {
adList, adList,
progress, progress,
checkUpdate, checkUpdate,
systemMessage,
update update
} }
}) })

56
frontend/src/system/event/SystemEvent.ts

@ -2,7 +2,7 @@ import { mountEvent, emitEvent } from './EventHook';
import { RootState } from '../root'; import { RootState } from '../root';
import { useSystem } from '../index'; import { useSystem } from '../index';
import { join } from '../core/Path'; //import { join } from '../core/Path';
function initSizeEvent() { function initSizeEvent() {
const rootState = useSystem()._rootState; const rootState = useSystem()._rootState;
@ -54,36 +54,36 @@ function initNetworkEvent() {
rootState.info.connection = connection; rootState.info.connection = connection;
}); });
} }
function setAlertTask(time: number, callback: any) { // function setAlertTask(time: number, callback: any) {
const date = new Date(); //现在时刻 // const date = new Date(); //现在时刻
const dateIntegralPoint = new Date(time); // const dateIntegralPoint = new Date(time);
setTimeout(() => { // setTimeout(() => {
callback(); // callback();
}, dateIntegralPoint.getTime() - date.getTime()); //用户登录后的下一个整点执行。 // }, dateIntegralPoint.getTime() - date.getTime()); //用户登录后的下一个整点执行。
} // }
async function initAlertEvent() { async function initAlertEvent() {
const sys = useSystem(); // const sys = useSystem();
const chosenDay = new Date(); // const chosenDay = new Date();
const fileName = `${chosenDay.getFullYear()}-${chosenDay.getMonth() + 1}-${chosenDay.getDate()}.json`; // const fileName = `${chosenDay.getFullYear()}-${chosenDay.getMonth() + 1}-${chosenDay.getDate()}.json`;
const filePath = join(sys._rootState.options.userLocation || '', '/Schedule', fileName) // const filePath = join(sys._rootState.options.userLocation || '', '/Schedule', fileName)
const isExits = await sys.fs.exists(filePath); // const isExits = await sys.fs.exists(filePath);
if (isExits) { // if (isExits) {
const alredyNotes = await sys.fs.readFile(filePath); // const alredyNotes = await sys.fs.readFile(filePath);
const alertList = JSON.parse(alredyNotes); // const alertList = JSON.parse(alredyNotes);
alertList.forEach((item: any) => { // alertList.forEach((item: any) => {
if (item.time < Date.now()) return; // if (item.time < Date.now()) return;
setAlertTask(item.time, () => { // setAlertTask(item.time, () => {
sys.createNotify({ // sys.createNotify({
title: '日程提醒', // title: '日程提醒',
content: `今日${new Date(item.time).getHours()}${new Date(item.time).getMinutes()}分 的提醒: ${ // content: `今日${new Date(item.time).getHours()}时${new Date(item.time).getMinutes()}分 的提醒: ${
item.text // item.text
}`, // }`,
}); // });
}); // });
}); // });
} // }
} }
export { initSizeEvent, initBatteryEvent, initNetworkEvent, initAlertEvent }; export { initSizeEvent, initBatteryEvent, initNetworkEvent, initAlertEvent };

20
frontend/src/system/index.ts

@ -106,7 +106,7 @@ export class System {
setTimeout(() => { setTimeout(() => {
const upgradeStore = useUpgradeStore(); const upgradeStore = useUpgradeStore();
upgradeStore.checkUpdate() upgradeStore.systemMessage()
}, 6000); }, 6000);
this.emit('start'); this.emit('start');
this._ready && this._ready(this); this._ready && this._ready(this);
@ -180,15 +180,15 @@ export class System {
} }
// initAppList() { initAppList() {
// this.isReadyUpdateAppList = true; this.isReadyUpdateAppList = true;
// nextTick(() => { nextTick(() => {
// if (this.isReadyUpdateAppList) { if (this.isReadyUpdateAppList) {
// this.isReadyUpdateAppList = false; this.isReadyUpdateAppList = false;
// this.refershAppList(); this.refershAppList();
// } }
// }); });
// } }

1
frontend/vite.config.ts

@ -33,6 +33,7 @@ export default defineConfig(async () => ({
}, },
}, },
build:{ build:{
sourcemap: true,
// 打包环境移除console.log,debugger // 打包环境移除console.log,debugger
terserOptions: { terserOptions: {
compress: { compress: {

2
godo/cmd/main.go

@ -55,7 +55,7 @@ func OsStart() {
progressRouter.HandleFunc("/setting", store.StoreSettingHandler).Methods(http.MethodPost) progressRouter.HandleFunc("/setting", store.StoreSettingHandler).Methods(http.MethodPost)
progressRouter.HandleFunc("/upload", store.UploadHandler).Methods(http.MethodPost) progressRouter.HandleFunc("/upload", store.UploadHandler).Methods(http.MethodPost)
router.HandleFunc("/system/updateInfo", sys.GetUpdateUrlHandler).Methods(http.MethodGet) router.HandleFunc("/system/message", sys.HandleSystemEvents).Methods(http.MethodGet)
router.HandleFunc("/system/update", sys.UpdateAppHandler).Methods(http.MethodGet) router.HandleFunc("/system/update", sys.UpdateAppHandler).Methods(http.MethodGet)
router.HandleFunc("/system/setting", sys.ConfigHandler).Methods(http.MethodPost) router.HandleFunc("/system/setting", sys.ConfigHandler).Methods(http.MethodPost)
fileRouter := router.PathPrefix("/file").Subrouter() fileRouter := router.PathPrefix("/file").Subrouter()

90
godo/sys/msg.go

@ -0,0 +1,90 @@
package sys
import (
"encoding/json"
"fmt"
"net/http"
"sync"
"time"
)
// 定义消息结构体
type Message struct {
Type string `json:"type"`
Data interface{} `json:"data"`
}
// 定义一个结构体来保存客户端连接
type client struct {
conn http.ResponseWriter
}
var clients = make(map[*client]bool)
var mutex sync.Mutex
// 处理客户端连接
func HandleSystemEvents(w http.ResponseWriter, r *http.Request) {
// 设置响应头
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
// 创建客户端连接对象
c := &client{conn: w}
// 添加客户端到列表
mutex.Lock()
clients[c] = true
mutex.Unlock()
// 发送初始消息
updateInfo, err := GetUpdateInfo()
if err == nil {
SendToClient(c, Message{
Type: "update",
Data: updateInfo,
})
}
// 监听客户端关闭
defer func() {
mutex.Lock()
delete(clients, c)
mutex.Unlock()
}()
// 读取客户端请求直到关闭
for {
select {
case <-r.Context().Done():
return
}
}
}
// 向客户端发送消息
func SendToClient(c *client, msg Message) {
jsonMsg, err := json.Marshal(msg)
if err != nil {
fmt.Println("Error marshaling JSON:", err)
return
}
fmt.Fprintf(c.conn, "data: %s\n\n", jsonMsg)
c.conn.(http.Flusher).Flush()
}
// 广播消息给所有客户端
func Broadcast(msg Message) {
mutex.Lock()
defer mutex.Unlock()
for c := range clients {
SendToClient(c, msg)
}
}
// 每隔一段时间广播一条消息
func SendMessagePeriodically(msg Message) {
ticker := time.NewTicker(1 * time.Second)
for range ticker.C {
Broadcast(msg)
}
}

60
godo/sys/update.go

@ -51,11 +51,17 @@ type UpdateAdReq struct {
Desc string `json:"desc"` Desc string `json:"desc"`
} }
type UpdateVersionReq struct { type UpdateVersionReq struct {
Version string `json:"version"` Version string `json:"version"`
Url string `json:"url"` Url string `json:"url"`
Name string `json:"name"` Name string `json:"name"`
Desc string `json:"desc"` Desc string `json:"desc"`
AdList []UpdateAdReq `json:"adList"` AdList []map[string][]UpdateAdReq `json:"adlist"`
}
type ServerRes struct {
Sucess bool `json:"sucess"`
Message string `json:"message"`
Data UpdateVersionReq `json:"data"`
Time int64 `json:"time"`
} }
func (pr *ProgressReader) Read(p []byte) (n int, err error) { func (pr *ProgressReader) Read(p []byte) (n int, err error) {
@ -127,31 +133,39 @@ func UpdateAppHandler(w http.ResponseWriter, r *http.Request) {
// 更新完成后发送响应给前端 // 更新完成后发送响应给前端
json.NewEncoder(w).Encode(map[string]bool{"updateCompleted": true}) json.NewEncoder(w).Encode(map[string]bool{"updateCompleted": true})
} }
func GetUpdateInfo() (ServerRes, error) {
func GetUpdateUrlHandler(w http.ResponseWriter, r *http.Request) { var updateInfo ServerRes
info, err := libs.GetSystemInfo() info, err := libs.GetSystemInfo()
if err != nil { if err != nil {
http.Error(w, "update error:"+err.Error(), http.StatusInternalServerError) return updateInfo, fmt.Errorf("update error get info:" + err.Error())
return
} }
updateUrl := "https://godoos.com/version?info=" + info updateUrl := "https://godoos.com/version?info=" + info
log.Printf("updateUrl:%v", updateUrl)
res, err := http.Get(updateUrl) res, err := http.Get(updateUrl)
if err != nil { if err != nil {
libs.ErrorMsg(w, err.Error()) return updateInfo, fmt.Errorf("update error get url:" + err.Error())
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode == 200 { if res.StatusCode != 200 {
body, err := io.ReadAll(res.Body) return updateInfo, fmt.Errorf("update error get url")
if err != nil { }
libs.ErrorMsg(w, err.Error()) body, err := io.ReadAll(res.Body)
return if err != nil {
} return updateInfo, fmt.Errorf("update error read body:" + err.Error())
var updateInfo UpdateVersionReq }
err = json.Unmarshal(body, &updateInfo) err = json.Unmarshal(body, &updateInfo)
if err != nil { log.Printf("updateInfo:%v", updateInfo)
fmt.Println("Error unmarshalling JSON:", err) if err != nil {
return fmt.Println("Error unmarshalling JSON:", err)
} return updateInfo, fmt.Errorf("update error unmarshal:" + err.Error())
json.NewEncoder(w).Encode(updateInfo) }
return updateInfo, nil
}
func GetUpdateUrlHandler(w http.ResponseWriter, r *http.Request) {
updateInfo, err := GetUpdateInfo()
if err != nil {
libs.ErrorMsg(w, err.Error())
return
} }
json.NewEncoder(w).Encode(updateInfo)
} }

Loading…
Cancel
Save