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