mirror of https://gitee.com/godoos/godoos.git
33 changed files with 1041 additions and 291 deletions
@ -0,0 +1 @@ |
|||||
|
## 变更记录 |
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,108 @@ |
|||||
|
<template> |
||||
|
<div class="ad-container" v-show="state.ad.isShow" @click="onSponsorsClick"> |
||||
|
<el-carousel height="240px" 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> |
||||
|
</el-carousel-item> |
||||
|
</el-carousel> |
||||
|
<div class="ad-close"> |
||||
|
<el-icon :size="20" @click.stop="onCloseSponsors"> |
||||
|
<CircleCloseFilled /> |
||||
|
</el-icon> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup lang="ts" name="layoutSponsors"> |
||||
|
import { reactive, computed, onMounted } from 'vue'; |
||||
|
import { useUpgradeStore } from '@/stores/upgrade'; |
||||
|
const upgradeStore = useUpgradeStore(); |
||||
|
|
||||
|
// 定义变量内容 |
||||
|
const state = reactive({ |
||||
|
ad: { |
||||
|
isShow: false, |
||||
|
index: 0, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
// 设置轮播图箭头显示 |
||||
|
const setCarouselShow = computed(() => { |
||||
|
return upgradeStore.adList.length <= 1 ? 'never' : 'hover'; |
||||
|
}); |
||||
|
// 关闭赞助商 |
||||
|
const onCloseSponsors = () => { |
||||
|
state.ad.isShow = false; |
||||
|
}; |
||||
|
// 轮播图改变时 |
||||
|
const onCarouselChange = (e: number) => { |
||||
|
state.ad.index = e; |
||||
|
}; |
||||
|
// 当前项内容点击 |
||||
|
const onSponsorsClick = () => { |
||||
|
const link = upgradeStore.adList[state.ad.index]?.link |
||||
|
if(link){ |
||||
|
window.open(link) |
||||
|
} |
||||
|
}; |
||||
|
// 延迟显示,防止影响其它界面加载 |
||||
|
const delayShow = () => { |
||||
|
setTimeout(() => { |
||||
|
state.ad.isShow = true; |
||||
|
}, 3000); |
||||
|
}; |
||||
|
// 页面加载时 |
||||
|
onMounted(() => { |
||||
|
delayShow(); |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.ad-container { |
||||
|
position: fixed; |
||||
|
top: calc(50vh - 175px); |
||||
|
left: calc(50vw - 175px); |
||||
|
z-index: 3; |
||||
|
width: 350px; |
||||
|
height: 350px; |
||||
|
background-color: #ffffff; |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
border-radius: 5px; |
||||
|
overflow: hidden; |
||||
|
cursor: pointer; |
||||
|
.ad-img { |
||||
|
width: 100%; |
||||
|
height: 80px; |
||||
|
} |
||||
|
.ad-text { |
||||
|
padding: 10px; |
||||
|
color: #303133; |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
.ad-close { |
||||
|
width: 60px; |
||||
|
height: 60px; |
||||
|
border-radius: 100%; |
||||
|
position: absolute; |
||||
|
background: rgba(0, 0, 0, 0.05); |
||||
|
transition: all 0.3s ease; |
||||
|
right: -30px; |
||||
|
top: -30px; |
||||
|
:deep(i) { |
||||
|
position: absolute; |
||||
|
left: 9px; |
||||
|
bottom: 9px; |
||||
|
color: #afafaf; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
&:hover { |
||||
|
transition: all 0.3s ease; |
||||
|
:deep(i) { |
||||
|
color: #409EFF; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,114 @@ |
|||||
|
<template> |
||||
|
<div class="sponsors-container" v-show="state.sponsors.isShow" @click="onSponsorsClick"> |
||||
|
<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> |
||||
|
</el-carousel-item> |
||||
|
</el-carousel> |
||||
|
<div class="sponsors-close"> |
||||
|
<el-icon :size="20" @click.stop="onCloseSponsors"> |
||||
|
<CircleCloseFilled /> |
||||
|
</el-icon> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup lang="ts" name="layoutSponsors"> |
||||
|
import { reactive, computed, onMounted } from 'vue'; |
||||
|
import { useUpgradeStore } from '@/stores/upgrade'; |
||||
|
const upgradeStore = useUpgradeStore(); |
||||
|
|
||||
|
// 定义变量内容 |
||||
|
const state = reactive({ |
||||
|
sponsors: { |
||||
|
// list: [ |
||||
|
// { |
||||
|
// url: "", |
||||
|
// text: "", |
||||
|
// link: '', |
||||
|
// }, |
||||
|
// ], |
||||
|
isShow: false, |
||||
|
index: 0, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
// 设置轮播图箭头显示 |
||||
|
const setCarouselShow = computed(() => { |
||||
|
return upgradeStore.noticeList.length <= 1 ? 'never' : 'hover'; |
||||
|
}); |
||||
|
// 关闭赞助商 |
||||
|
const onCloseSponsors = () => { |
||||
|
state.sponsors.isShow = false; |
||||
|
}; |
||||
|
// 轮播图改变时 |
||||
|
const onCarouselChange = (e: number) => { |
||||
|
state.sponsors.index = e; |
||||
|
}; |
||||
|
// 当前项内容点击 |
||||
|
const onSponsorsClick = () => { |
||||
|
const link = upgradeStore.noticeList[state.sponsors.index]?.link |
||||
|
if(link){ |
||||
|
window.open(link) |
||||
|
} |
||||
|
}; |
||||
|
// 延迟显示,防止影响其它界面加载 |
||||
|
const delayShow = () => { |
||||
|
setTimeout(() => { |
||||
|
state.sponsors.isShow = true; |
||||
|
}, 3000); |
||||
|
}; |
||||
|
// 页面加载时 |
||||
|
onMounted(() => { |
||||
|
delayShow(); |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.sponsors-container { |
||||
|
position: fixed; |
||||
|
right: 6px; |
||||
|
bottom: 48px; |
||||
|
z-index: 3; |
||||
|
width: 200px; |
||||
|
background-color: #ffffff; |
||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
||||
|
border-radius: 5px; |
||||
|
overflow: hidden; |
||||
|
cursor: pointer; |
||||
|
.sponsors-img { |
||||
|
width: 100%; |
||||
|
height: 80px; |
||||
|
} |
||||
|
.sponsors-text { |
||||
|
padding: 10px; |
||||
|
color: #303133; |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
.sponsors-close { |
||||
|
width: 60px; |
||||
|
height: 60px; |
||||
|
border-radius: 100%; |
||||
|
position: absolute; |
||||
|
background: rgba(0, 0, 0, 0.05); |
||||
|
transition: all 0.3s ease; |
||||
|
right: -30px; |
||||
|
bottom: -30px; |
||||
|
:deep(i) { |
||||
|
position: absolute; |
||||
|
left: 9px; |
||||
|
top: 9px; |
||||
|
color: #afafaf; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
&:hover { |
||||
|
transition: all 0.3s ease; |
||||
|
:deep(i) { |
||||
|
color: #409EFF; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,143 @@ |
|||||
|
<template> |
||||
|
<div class="upgrade-dialog"> |
||||
|
<el-dialog |
||||
|
v-model="state.isUpgrade" |
||||
|
width="300px" |
||||
|
destroy-on-close |
||||
|
:show-close="false" |
||||
|
:close-on-click-modal="false" |
||||
|
:close-on-press-escape="false" |
||||
|
> |
||||
|
<div class="upgrade-title"> |
||||
|
<div class="upgrade-title-warp"> |
||||
|
<span class="upgrade-title-warp-txt">{{ $t('upgrade.title') }}</span> |
||||
|
<span class="upgrade-title-warp-version">v{{ upgradeStore.versionTag }}</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="upgrade-content"> |
||||
|
GodoOS {{ $t('upgrade.msg') }} |
||||
|
<div class="mt5"> |
||||
|
<el-link type="primary" class="font12" href="https://gitee.com/lyt-top/vue-next-admin/blob/master/CHANGELOG.md" target="_black"> |
||||
|
CHANGELOG.md |
||||
|
</el-link> |
||||
|
</div> |
||||
|
<div class="upgrade-content-desc mt5">{{ $t('upgrade.desc') }}</div> |
||||
|
<div class="upgrade-content-desc" v-if="upgradeStore.progress > 0"> |
||||
|
<el-progress :text-inside="true" :stroke-width="20" :percentage="upgradeStore.progress" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="upgrade-btn"> |
||||
|
<el-button round size="default" type="info" text @click="onCancel">{{ $t('upgrade.btnOne') }}</el-button> |
||||
|
<el-button type="primary" round size="default" @click="onUpgrade" :loading="state.isLoading">{{ state.btnTxt }}</el-button> |
||||
|
</div> |
||||
|
</el-dialog> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup lang="ts" name="layoutUpgrade"> |
||||
|
import { reactive, onMounted } from 'vue'; |
||||
|
import { t } from '@/i18n'; |
||||
|
import { useUpgradeStore } from '@/stores/upgrade'; |
||||
|
const upgradeStore = useUpgradeStore(); |
||||
|
const state = reactive({ |
||||
|
isUpgrade: false, |
||||
|
isLoading: false, |
||||
|
btnTxt: '', |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
// 残忍拒绝 |
||||
|
const onCancel = () => { |
||||
|
state.isUpgrade = false; |
||||
|
}; |
||||
|
// 马上更新 |
||||
|
const onUpgrade = () => { |
||||
|
state.isLoading = true; |
||||
|
state.btnTxt = t('upgrade.btnTwoLoading'); |
||||
|
setTimeout(async () => { |
||||
|
await upgradeStore.update(); |
||||
|
state.isLoading = false; |
||||
|
}, 2000); |
||||
|
}; |
||||
|
// 延迟显示,防止刷新时界面显示太快 |
||||
|
const delayShow = () => { |
||||
|
setTimeout(() => { |
||||
|
state.isUpgrade = true; |
||||
|
}, 2000); |
||||
|
}; |
||||
|
// 页面加载时 |
||||
|
onMounted(() => { |
||||
|
delayShow(); |
||||
|
setTimeout(() => { |
||||
|
state.btnTxt = t('upgrade.btnTwo'); |
||||
|
}, 200); |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.upgrade-dialog { |
||||
|
:deep(.el-dialog) { |
||||
|
padding: 0 !important; |
||||
|
.el-dialog__body { |
||||
|
padding: 0 !important; |
||||
|
} |
||||
|
.el-dialog__header { |
||||
|
display: none !important; |
||||
|
} |
||||
|
.upgrade-title { |
||||
|
text-align: center; |
||||
|
height: 100px; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
position: relative; |
||||
|
&::after { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
background-color: #2882dc; |
||||
|
width: 100%; |
||||
|
height: 100px; |
||||
|
border-bottom-left-radius: 100%; |
||||
|
border-bottom-right-radius: 100%; |
||||
|
} |
||||
|
.upgrade-title-warp { |
||||
|
z-index: 1; |
||||
|
position: relative; |
||||
|
.upgrade-title-warp-txt { |
||||
|
color: #ffffff; |
||||
|
font-size: 22px; |
||||
|
letter-spacing: 3px; |
||||
|
} |
||||
|
.upgrade-title-warp-version { |
||||
|
color: #ffffff; |
||||
|
background-color: #2882dc; |
||||
|
font-size: 12px; |
||||
|
position: absolute; |
||||
|
display: flex; |
||||
|
top: -2px; |
||||
|
right: -50px; |
||||
|
padding: 2px 4px; |
||||
|
border-radius: 2px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.upgrade-content { |
||||
|
padding: 20px; |
||||
|
line-height: 22px; |
||||
|
.upgrade-content-desc { |
||||
|
color: rgba(255, 255, 255, 0.7); |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
} |
||||
|
.upgrade-btn { |
||||
|
border-top: 1px solid #ebeef5; |
||||
|
display: flex; |
||||
|
justify-content: space-around; |
||||
|
padding: 15px 20px; |
||||
|
.el-button { |
||||
|
width: 100%; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,58 @@ |
|||||
|
<script setup lang="ts"> |
||||
|
import { ref, onMounted, inject } from 'vue'; |
||||
|
import { getSystemKey } from "@/system/config"; |
||||
|
import {t} from "@/i18n"; |
||||
|
import { BrowserWindow } from '@/system/window/BrowserWindow'; |
||||
|
const win = inject<BrowserWindow>('browserWindow'); |
||||
|
const processList = ref([]); |
||||
|
const apiUrl = getSystemKey("apiUrl"); |
||||
|
let timerId: ReturnType<typeof setTimeout>; // 用于保存定时器ID |
||||
|
|
||||
|
onMounted(() => { |
||||
|
fetchProcesses(); |
||||
|
}); |
||||
|
win?.on("close", () => { |
||||
|
//console.log(timerId) |
||||
|
clearTimeout(timerId); |
||||
|
}) |
||||
|
const fetchProcesses = async () => { |
||||
|
try { |
||||
|
const response = await fetch(apiUrl + '/store/listport'); |
||||
|
if (!response.ok) { |
||||
|
throw new Error('Network response was not ok'); |
||||
|
} |
||||
|
const data = await response.json(); |
||||
|
processList.value = data.processes; |
||||
|
timerId = setTimeout(() => { |
||||
|
fetchProcesses() |
||||
|
}, 3000); |
||||
|
} catch (error) { |
||||
|
console.error('Error fetching processes:', error); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const killProcess = async (name: string) => { |
||||
|
try { |
||||
|
const response = await fetch(apiUrl + '/store/killport?name=' + name); |
||||
|
if (!response.ok) { |
||||
|
throw new Error('Network response was not ok'); |
||||
|
} |
||||
|
fetchProcesses(); // 刷新列表 |
||||
|
} catch (error) { |
||||
|
console.error('Error killing process:', error); |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
<template> |
||||
|
<el-table :data="processList" stripe style="width: 96%;margin:auto;border:none" max-height="550"> |
||||
|
<el-table-column prop="port" :label="t('process.port')" sortable /> |
||||
|
<el-table-column prop="pid" :label="t('process.pid')" sortable /> |
||||
|
<el-table-column prop="name" :label="t('process.name')" /> |
||||
|
<el-table-column prop="proto" :label="t('process.proto')" /> |
||||
|
<el-table-column :label="t('process.action')"> |
||||
|
<template #default="{ row }"> |
||||
|
<el-button circle icon="Remove" @click="killProcess(row.name)" style="width: 35px;height: 35px;" /> |
||||
|
</template> |
||||
|
</el-table-column> |
||||
|
</el-table> |
||||
|
</template> |
@ -0,0 +1,108 @@ |
|||||
|
import { defineStore } from 'pinia' |
||||
|
import { ref } from "vue"; |
||||
|
import { t } from "@/i18n"; |
||||
|
// import storeInitList from "@/assets/store.json";
|
||||
|
import { getSystemKey } from "@/system/config"; |
||||
|
export const useStoreStore = defineStore('storeStore', () => { |
||||
|
const currentCateId = ref(0) |
||||
|
const currentTitle = ref(t("store.hots")) |
||||
|
const currentCate = ref('hots') |
||||
|
const categoryList = ['hots', 'work', 'development', 'games', 'education', 'news', 'shopping', 'social', 'utilities', 'others', 'add'] |
||||
|
const categoryIcon = ['HomeFilled', 'Odometer', 'Postcard', 'TrendCharts', 'School', 'HelpFilled', 'ShoppingCart', 'ChatLineRound', 'MessageBox', 'Ticket', 'CirclePlusFilled'] |
||||
|
const isready = ref(false); |
||||
|
const installed = getSystemKey("intstalledPlugins"); |
||||
|
const apiUrl = getSystemKey("apiUrl"); |
||||
|
const installedList: any = ref(installed); |
||||
|
const storeList: any = ref([]) |
||||
|
const outList: any = ref([]) |
||||
|
async function getList() { |
||||
|
if (currentCate.value == 'add') return; |
||||
|
//storeList.value = storeInitList
|
||||
|
const storeUrl = apiUrl + '/store/storelist?cate=' + currentCate.value |
||||
|
const res = await fetch(storeUrl) |
||||
|
if (!res.ok) { |
||||
|
return [] |
||||
|
} |
||||
|
let list:any = await res.json() |
||||
|
//console.log(data)
|
||||
|
if (outList.value.length > 0 && currentCate.value == 'hots') { |
||||
|
const names = list.value.map((item : any) => item.name) |
||||
|
const adds:any = [] |
||||
|
outList.value.forEach((item : any) => { |
||||
|
if (!names.includes(item.name)) { |
||||
|
adds.push(item) |
||||
|
} |
||||
|
}) |
||||
|
list = adds.concat(list) |
||||
|
} |
||||
|
storeList.value = list |
||||
|
await checkProgress() |
||||
|
isready.value = true; |
||||
|
} |
||||
|
async function addOutList(item:any) { |
||||
|
const has = outList.value.find((i:any) => i.name === item.name) |
||||
|
if(!has) { |
||||
|
item.isOut = true |
||||
|
outList.value.push(item) |
||||
|
await getList() |
||||
|
return true |
||||
|
}else{ |
||||
|
return false |
||||
|
} |
||||
|
} |
||||
|
async function changeCate(index: number, item: string) { |
||||
|
currentCateId.value = index |
||||
|
currentCate.value = item |
||||
|
currentTitle.value = t("store." + item) |
||||
|
await getList() |
||||
|
} |
||||
|
async function checkProgress() { |
||||
|
const completion: any = await fetch(apiUrl + '/store/listporgress') |
||||
|
if (!completion.ok) { |
||||
|
return |
||||
|
} |
||||
|
let res: any = await completion.json() |
||||
|
if (!res || res.length < 1) { |
||||
|
res = [] |
||||
|
} |
||||
|
storeList.value.forEach((item: any, index: number) => { |
||||
|
const pitem: any = res.find((i: any) => i.name == item.name) |
||||
|
//console.log(pitem)
|
||||
|
if (pitem) { |
||||
|
storeList.value[index].isRuning = pitem.running |
||||
|
} else { |
||||
|
storeList.value[index].isRuning = false |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
return { |
||||
|
currentCateId, |
||||
|
categoryIcon, |
||||
|
currentTitle, |
||||
|
currentCate, |
||||
|
categoryList, |
||||
|
isready, |
||||
|
installedList, |
||||
|
storeList, |
||||
|
outList, |
||||
|
apiUrl, |
||||
|
changeCate, |
||||
|
getList, |
||||
|
addOutList, |
||||
|
checkProgress |
||||
|
} |
||||
|
}, { |
||||
|
persist: { |
||||
|
enabled: true, |
||||
|
strategies: [ |
||||
|
{ |
||||
|
storage: localStorage, |
||||
|
paths: [ |
||||
|
"outList" |
||||
|
] |
||||
|
}, // name 字段用localstorage存储
|
||||
|
], |
||||
|
} |
||||
|
}) |
@ -0,0 +1,88 @@ |
|||||
|
import { defineStore } from "pinia"; |
||||
|
import { ref } from "vue"; |
||||
|
import { getSystemKey, setSystemKey, parseJson, getSystemConfig } from '@/system/config' |
||||
|
import { RestartApp } from '@/util/goutil'; |
||||
|
import { ElMessage } from 'element-plus' |
||||
|
export const useUpgradeStore = defineStore('upgradeStore', () => { |
||||
|
const hasUpgrade = ref(false); |
||||
|
const hasNotice = ref(false); |
||||
|
const hasAd = ref(false); |
||||
|
const updateUrl = ref(''); |
||||
|
const versionTag = ref(0) |
||||
|
const currentVersion = ref(0) |
||||
|
const progress = ref(0) |
||||
|
const noticeList:any = ref([]) |
||||
|
const adList:any = ref([]) |
||||
|
async function checkUpdate() { |
||||
|
const config = getSystemConfig(); |
||||
|
currentVersion.value = config.version; |
||||
|
const releaseRes = await fetch(`${config.apiUrl}/system/updateInfo`) |
||||
|
if (!releaseRes.ok) return; |
||||
|
const releaseData = await releaseRes.json() |
||||
|
versionTag.value = releaseData.version |
||||
|
if(versionTag.value > config.version){ |
||||
|
hasUpgrade.value = true |
||||
|
updateUrl.value = releaseData.url |
||||
|
} |
||||
|
if (releaseData.noticeList && releaseData.noticeList.length > 0) { |
||||
|
hasNotice.value = true |
||||
|
noticeList.value = releaseData.noticeList |
||||
|
} |
||||
|
if (!hasUpgrade.value && releaseData.adList && releaseData.adList.length > 0) { |
||||
|
hasAd.value = true |
||||
|
adList.value = releaseData.adList |
||||
|
} |
||||
|
} |
||||
|
async function update() { |
||||
|
const apiUrl = getSystemKey('apiUrl') |
||||
|
const upUrl = `${apiUrl}/system/update?url=${updateUrl.value}` |
||||
|
const upRes = await fetch(upUrl) |
||||
|
if (!upRes.ok) return; |
||||
|
const reader: any = upRes.body?.getReader(); |
||||
|
if (!reader) { |
||||
|
ElMessage({ |
||||
|
type: 'error', |
||||
|
message: "the system has not stream!" |
||||
|
}) |
||||
|
} |
||||
|
while (true) { |
||||
|
const { done, value } = await reader.read(); |
||||
|
if (done) { |
||||
|
reader.releaseLock(); |
||||
|
break; |
||||
|
} |
||||
|
const rawjson = new TextDecoder().decode(value); |
||||
|
const json = parseJson(rawjson); |
||||
|
//console.log(json)
|
||||
|
if (json) { |
||||
|
if (json.progress) { |
||||
|
progress.value = json.progress |
||||
|
} |
||||
|
if (json.updateCompleted) { |
||||
|
hasUpgrade.value = false |
||||
|
progress.value = 0 |
||||
|
ElMessage({ |
||||
|
type: 'success', |
||||
|
message: "update completed!" |
||||
|
}) |
||||
|
setSystemKey('version', versionTag.value) |
||||
|
currentVersion.value = versionTag.value |
||||
|
RestartApp() |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return { |
||||
|
hasUpgrade, |
||||
|
hasNotice, |
||||
|
hasAd, |
||||
|
versionTag, |
||||
|
updateUrl, |
||||
|
noticeList, |
||||
|
adList, |
||||
|
progress, |
||||
|
checkUpdate, |
||||
|
update |
||||
|
} |
||||
|
}) |
@ -1,62 +0,0 @@ |
|||||
import { getSystemConfig,setSystemKey,parseJson } from '@/system/config' |
|
||||
import { RestartApp } from './goutil'; |
|
||||
import { Dialog } from '@/system'; |
|
||||
import { ElMessage } from 'element-plus' |
|
||||
export async function checkUpdate() { |
|
||||
const config = getSystemConfig(); |
|
||||
const updateGiteeUrl = `${config.apiUrl}/system/updateInfo` |
|
||||
const releaseRes = await fetch(updateGiteeUrl) |
|
||||
if (!releaseRes.ok) return; |
|
||||
const releaseData = await releaseRes.json() |
|
||||
const versionTag = releaseData.version; |
|
||||
if (!versionTag) return; |
|
||||
if (versionTag <= config.version) return; |
|
||||
const updateUrl = releaseData.url |
|
||||
if (!updateUrl || updateUrl == '') return; |
|
||||
const dialogRes: any = await Dialog.showMessageBox({ |
|
||||
title: '更新提示', |
|
||||
message: `发现新版本:${versionTag},是否更新?` |
|
||||
}) |
|
||||
//console.log(dialogRes)
|
|
||||
if (dialogRes.response !== -1) { |
|
||||
return; |
|
||||
} |
|
||||
const { setProgress,dialogwin } = Dialog.showProcessDialog({ |
|
||||
message: '正在更新', |
|
||||
}); |
|
||||
const upUrl = `${config.apiUrl}/system/update?url=${updateUrl}` |
|
||||
const upRes = await fetch(upUrl) |
|
||||
if (!upRes.ok) return; |
|
||||
const reader: any = upRes.body?.getReader(); |
|
||||
if (!reader) { |
|
||||
ElMessage({ |
|
||||
type: 'error', |
|
||||
message: "the system has not stream!" |
|
||||
}) |
|
||||
} |
|
||||
while (true) { |
|
||||
const { done, value } = await reader.read(); |
|
||||
if (done) { |
|
||||
reader.releaseLock(); |
|
||||
break; |
|
||||
} |
|
||||
const rawjson = new TextDecoder().decode(value); |
|
||||
const json = parseJson(rawjson); |
|
||||
console.log(json) |
|
||||
if(json){ |
|
||||
if(json.progress){ |
|
||||
setProgress(json.progress) |
|
||||
} |
|
||||
if(json.updateCompleted){ |
|
||||
dialogwin.close() |
|
||||
ElMessage({ |
|
||||
type: 'success', |
|
||||
message: "update completed!" |
|
||||
}) |
|
||||
setSystemKey('version',versionTag) |
|
||||
RestartApp() |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,66 @@ |
|||||
|
package store |
||||
|
|
||||
|
import ( |
||||
|
"godo/files" |
||||
|
"godo/libs" |
||||
|
"io" |
||||
|
"log" |
||||
|
"net/http" |
||||
|
"os" |
||||
|
"path/filepath" |
||||
|
"strings" |
||||
|
) |
||||
|
|
||||
|
// UploadHandler 处理上传的HTTP请求
|
||||
|
func UploadHandler(w http.ResponseWriter, r *http.Request) { |
||||
|
|
||||
|
// 解析上传的文件
|
||||
|
err := r.ParseMultipartForm(10000 << 20) // 限制最大上传大小为1000MB
|
||||
|
if err != nil { |
||||
|
http.Error(w, "上传文件过大"+err.Error(), http.StatusBadRequest) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
file, header, err := r.FormFile("files") // 表单字段名为"files"
|
||||
|
if err != nil { |
||||
|
http.Error(w, "没有找到文件", http.StatusBadRequest) |
||||
|
return |
||||
|
} |
||||
|
defer file.Close() |
||||
|
|
||||
|
// 读取文件内容
|
||||
|
fileBytes, err := io.ReadAll(file) |
||||
|
if err != nil { |
||||
|
log.Printf("读取文件内容出错: %v", err) |
||||
|
http.Error(w, "读取文件内容出错", http.StatusInternalServerError) |
||||
|
return |
||||
|
} |
||||
|
cachePath := libs.GetCacheDir() |
||||
|
baseName := filepath.Base(header.Filename) |
||||
|
filenameNoExt := strings.TrimSuffix(baseName, filepath.Ext(baseName)) |
||||
|
|
||||
|
savePath := filepath.Join(cachePath, baseName) |
||||
|
|
||||
|
out, err := os.Create(savePath) |
||||
|
if err != nil { |
||||
|
log.Printf("创建文件出错: %v", err) |
||||
|
http.Error(w, "保存文件出错", http.StatusInternalServerError) |
||||
|
return |
||||
|
} |
||||
|
defer out.Close() |
||||
|
|
||||
|
// 将文件内容写入到服务器上的文件
|
||||
|
_, err = out.Write(fileBytes) |
||||
|
if err != nil { |
||||
|
log.Printf("写入文件出错: %v", err) |
||||
|
http.Error(w, "写入文件出错", http.StatusInternalServerError) |
||||
|
return |
||||
|
} |
||||
|
runDir := libs.GetRunDir() |
||||
|
err = files.HandlerFile(savePath, runDir) |
||||
|
if err != nil { |
||||
|
log.Printf("Error moving file: %v", err) |
||||
|
} |
||||
|
|
||||
|
libs.SuccessMsg(w, filenameNoExt, "File already exists and is of correct size") |
||||
|
} |
Loading…
Reference in new issue