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']
NetworkPop: typeof import('./src/components/taskbar/NetworkPop.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']
OpeningDesktop: typeof import('./src/components/desktop/OpeningDesktop.vue')['default']
OpenWiteDialog: typeof import('./src/components/builtin/OpenWiteDialog.vue')['default']

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

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

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

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

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

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

66
frontend/src/stores/upgrade.ts

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

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

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

20
frontend/src/system/index.ts

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

1
frontend/vite.config.ts

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

2
godo/cmd/main.go

@ -55,7 +55,7 @@ func OsStart() {
progressRouter.HandleFunc("/setting", store.StoreSettingHandler).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/setting", sys.ConfigHandler).Methods(http.MethodPost)
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"`
}
type UpdateVersionReq struct {
Version string `json:"version"`
Url string `json:"url"`
Name string `json:"name"`
Desc string `json:"desc"`
AdList []UpdateAdReq `json:"adList"`
Version string `json:"version"`
Url string `json:"url"`
Name string `json:"name"`
Desc string `json:"desc"`
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) {
@ -127,31 +133,39 @@ func UpdateAppHandler(w http.ResponseWriter, r *http.Request) {
// 更新完成后发送响应给前端
json.NewEncoder(w).Encode(map[string]bool{"updateCompleted": true})
}
func GetUpdateUrlHandler(w http.ResponseWriter, r *http.Request) {
func GetUpdateInfo() (ServerRes, error) {
var updateInfo ServerRes
info, err := libs.GetSystemInfo()
if err != nil {
http.Error(w, "update error:"+err.Error(), http.StatusInternalServerError)
return
return updateInfo, fmt.Errorf("update error get info:" + err.Error())
}
updateUrl := "https://godoos.com/version?info=" + info
log.Printf("updateUrl:%v", updateUrl)
res, err := http.Get(updateUrl)
if err != nil {
libs.ErrorMsg(w, err.Error())
return updateInfo, fmt.Errorf("update error get url:" + err.Error())
}
defer res.Body.Close()
if res.StatusCode == 200 {
body, err := io.ReadAll(res.Body)
if err != nil {
libs.ErrorMsg(w, err.Error())
return
}
var updateInfo UpdateVersionReq
err = json.Unmarshal(body, &updateInfo)
if err != nil {
fmt.Println("Error unmarshalling JSON:", err)
return
}
json.NewEncoder(w).Encode(updateInfo)
if res.StatusCode != 200 {
return updateInfo, fmt.Errorf("update error get url")
}
body, err := io.ReadAll(res.Body)
if err != nil {
return updateInfo, fmt.Errorf("update error read body:" + err.Error())
}
err = json.Unmarshal(body, &updateInfo)
log.Printf("updateInfo:%v", updateInfo)
if err != nil {
fmt.Println("Error unmarshalling JSON:", err)
return updateInfo, fmt.Errorf("update error unmarshal:" + err.Error())
}
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