You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
496 lines
13 KiB
496 lines
13 KiB
<script setup> |
|
import {onBeforeMount, ref, computed} from "vue"; |
|
import {useStore} from "vuex"; |
|
import {get_git_ver, get_update_alter, get_update_option, handle_update} from "@/apis/update.js" |
|
import Tips from "@/components/update/Tips.vue" |
|
import config from "@/request/config.js" |
|
import ProcessIcon from "@/components/update/ProcessIcon.vue"; |
|
import {ElMessageBox} from "element-plus"; |
|
|
|
|
|
// 注册store |
|
const store = useStore() |
|
|
|
// 注册props |
|
const props = defineProps({ |
|
ip: { |
|
type: String, |
|
default: '' |
|
}, |
|
ver_id: { |
|
type: Number, |
|
default: 0 |
|
} |
|
}) |
|
|
|
// 配置状态 |
|
const updateStatus = ref({}) |
|
let showStatusTips = ref(false) |
|
|
|
// |
|
const handleShowStatusTips = () => { |
|
if (store.state.updateModule.update_status[props.ip]) { |
|
showStatusTips.value = true |
|
} |
|
} |
|
|
|
// 配置websocket |
|
let ws = null |
|
let wsGetStatusInterval = null |
|
|
|
const createWs = () => { |
|
console.log(ws) |
|
if (!ws) { |
|
console.log("建立ws连接") |
|
ws = new WebSocket(config.baseWS + "/ws/update/") |
|
ws.onopen = wsOpen |
|
ws.onmessage = wsMessage |
|
ws.onerror = wsError |
|
ws.onclose = wsClose |
|
} |
|
} |
|
|
|
const wsOpen = () => { |
|
wsSend(JSON.stringify({"msg": "ping"})) |
|
} |
|
|
|
const wsError = () => { |
|
ws.close() |
|
console.log("重新连接") |
|
if (ws.readyState !== 3) { |
|
ws = null |
|
createWs() |
|
} |
|
} |
|
|
|
const wsMessage = (event) => { |
|
handleWsMessage(event.data) |
|
} |
|
|
|
const wsClose = () => { |
|
console.log("关闭ws") |
|
ws = null |
|
} |
|
|
|
const wsSend = (msg) => { |
|
console.log(ws) |
|
if (ws === null) { |
|
createWs() |
|
} |
|
console.log(ws) |
|
if (ws.readyState === 1) { |
|
ws.send(msg) |
|
} |
|
} |
|
|
|
const handleWsMessage = function (msg) { |
|
if (msg === "你已经连接成功") { |
|
return |
|
} |
|
if (JSON.parse(msg).hasOwnProperty('msg')) { |
|
if (JSON.parse(msg)['msg'] === "ping") { |
|
wsSend(JSON.stringify({"msg": "pong"})) |
|
} |
|
} |
|
if (JSON.parse(msg).hasOwnProperty('status')) { |
|
console.log(JSON.parse(msg)) |
|
updateStatus.value = JSON.parse(msg)['status']['result'] |
|
} |
|
} |
|
|
|
const wsGetStatus = function () { |
|
if (ws === null || ws.readyState === 3) { |
|
createWs() |
|
wsGetStatusInterval = setInterval(() => { |
|
wsSend(JSON.stringify({'ip': props.ip})) |
|
}, 1000) |
|
} else { |
|
wsGetStatusInterval = setInterval(() => { |
|
wsSend(JSON.stringify({'ip': props.ip})) |
|
}, 1000) |
|
} |
|
} |
|
|
|
const stopWsGetStatus = function () { |
|
setTimeout(() => { |
|
clearInterval(wsGetStatusInterval) |
|
}, 1000) |
|
|
|
} |
|
|
|
const handleWsOpen = () => { |
|
if (store.state.updateModule.update_status[props.ip] === true) { |
|
createWs() |
|
wsGetStatus() |
|
} else { |
|
createWs() |
|
} |
|
} |
|
// const handleWsClose = () => { |
|
// if (store.state.updateModule.update_status[props.ip] === false) { |
|
// ws.send(JSON.stringify({"msg": "finish"})) |
|
// wsClose() |
|
// } |
|
// } |
|
|
|
const handleWsClear = (ip) => { |
|
if (store.state.updateModule.update_status[ip] === false) { |
|
wsSend(JSON.stringify({"finish": ip})) |
|
updateStatus.value = {} |
|
} |
|
} |
|
// const clearUpdateStatus = () => { |
|
// if () |
|
// updateStatus.value = {} |
|
// } |
|
|
|
|
|
// region 获取git版本 |
|
const git_ver = ref([]) |
|
const selectedVersion = ref('') |
|
|
|
onBeforeMount(async () => { |
|
await get_git_ver().then(res => { |
|
if (Array.isArray(res)) { |
|
git_ver.value = [...res] |
|
} |
|
}).catch() |
|
}) |
|
// endregion |
|
|
|
// region 获取升级警告 |
|
const updateAlter = ref([]) |
|
onBeforeMount( |
|
async () => { |
|
await get_update_alter().then( |
|
res => { |
|
if (Array.isArray(res)) { |
|
updateAlter.value = [...res] |
|
console.log(updateAlter.value) |
|
} |
|
} |
|
).catch(err => { |
|
console.log(err) |
|
}) |
|
} |
|
) |
|
|
|
// region 获取升级命令的功能 |
|
const updateCmd = ref({setup: [], teardown: [], sql: [], config: [], client: []}) |
|
|
|
onBeforeMount( |
|
async () => { |
|
await get_update_option().then(res => { |
|
|
|
// 返回值处理逻辑 |
|
if (Array.isArray(res)) { |
|
console.log(res) |
|
res.forEach( |
|
(value, index) => { |
|
if (value.process === "setup") { |
|
updateCmd.value.setup.push(value) |
|
} |
|
if (value.process === "teardown") { |
|
updateCmd.value.teardown.push(value) |
|
} |
|
if (value.process === "sql") { |
|
updateCmd.value.sql.push(value) |
|
} |
|
if (value.process === "config") { |
|
updateCmd.value.config.push(value) |
|
} |
|
if (value.process === "client") { |
|
updateCmd.value.client.push(value) |
|
} |
|
} |
|
) |
|
} |
|
}).catch() |
|
} |
|
) |
|
//endregion |
|
|
|
// region 处理版本依赖 |
|
let selectedVerId = ref('9999') |
|
|
|
const handleChangeVersion = () => { |
|
git_ver.value.forEach( |
|
(item, index) => { |
|
if (item.short_release === selectedVersion.value) { |
|
selectedVerId.value = item.ver_id |
|
} |
|
} |
|
) |
|
} |
|
// endregion |
|
|
|
// 切换版本事件 |
|
const changeVersion = () => { |
|
handleChangeVersion() |
|
handleUpdateAlter() |
|
} |
|
// endregion |
|
|
|
// region 处理版本警告 |
|
const showAlterMsg = ref('') |
|
const handleUpdateAlter = () => { |
|
updateAlter.value.forEach( |
|
(item, index) => { |
|
if (selectedVerId.value < item.ver_id && props.ver_id >= item.ver_id) { |
|
showAlterMsg.value = "当前版本为" + props.ver_id + ":" + item.alter |
|
ElMessageBox( |
|
{ |
|
title: "降级提示", |
|
message: showAlterMsg.value, |
|
confirmButtonText: "知道了", |
|
closeOnClickModal: false, |
|
type: "warning", |
|
center: true, |
|
'show-close': false |
|
} |
|
).then().catch() |
|
} |
|
} |
|
) |
|
} |
|
|
|
// region 处理按键文案 |
|
let updateBtn = ref("更新") |
|
const handleBtnName = (ip) => { |
|
if (store.state.updateModule.update_status[ip] === false) { |
|
updateBtn.value = "更新" |
|
} |
|
if (store.state.updateModule.update_status[ip] === true) { |
|
updateBtn.value = "更新中" |
|
} |
|
} |
|
// endregion |
|
|
|
// region 更新时禁用全部选项 |
|
const disableAll = ref(false) |
|
|
|
const handleDisable = (ip) => { |
|
disableAll.value = store.state.updateModule.update_status[ip] === true; |
|
} |
|
// endregion |
|
|
|
// region 更新状态 |
|
const changUpdateStatus = (ip) => { |
|
store.commit("updateModule/change_update_status", ip) |
|
} |
|
// endregion |
|
|
|
// region opened事件对应的功能 |
|
// 定义方法用于在加载过程中将ip对应的状态存入全局store中 |
|
const addUpdateStatus = () => { |
|
if (!store.state.updateModule.update_status.hasOwnProperty(props.ip)) { |
|
let data = { |
|
"ip": props.ip, |
|
"status": false // 更新中是true 更新是false |
|
} |
|
store.commit("updateModule/add_update_status", data) |
|
} |
|
} |
|
|
|
const getCurrentConfig = () => { |
|
if (store.state.updateModule.update_config.hasOwnProperty(props.ip)) { |
|
selectedVersion.value = store.state.updateModule.update_config[props.ip].version |
|
checkedCmd.value = store.state.updateModule.update_config[props.ip].selected |
|
} else { |
|
selectedVersion.value = '' |
|
} |
|
} |
|
|
|
const handleOpened = () => { |
|
getCurrentConfig() |
|
addUpdateStatus() |
|
handleBtnName(props.ip) |
|
handleDisable(props.ip) |
|
handleWsOpen() |
|
handleShowStatusTips() |
|
} |
|
// endregion |
|
|
|
// region close时间对应功能 |
|
const handleClose = () => { |
|
stopWsGetStatus() |
|
handleWsClear(props.ip) |
|
// handleWsClose() |
|
showStatusTips.value = false |
|
store.state.updateModule.update_dialog_show = false |
|
} |
|
// endregion |
|
|
|
// region 提交升级相关逻辑 |
|
const updateForm = ref() |
|
const checkedCmd = ref([]) |
|
|
|
// 处理点击事件 |
|
const handleRep = (ip) => { |
|
console.log(store.state.updateModule.update_status[ip]) |
|
changUpdateStatus(ip) // 更新状态 |
|
handleBtnName(props.ip) // 变更按键文案 |
|
handleDisable(props.ip) // 启用全部状态 |
|
handleShowStatusTips() |
|
console.log(store.state.updateModule.update_status[ip]) |
|
} |
|
|
|
const handleUpdate = async () => { |
|
if (props.ip === "" || selectedVersion.value === "") { |
|
alert("请先选择影院和目标版本!") |
|
return |
|
} |
|
|
|
updateStatus.value = {} |
|
|
|
handleRep(props.ip) |
|
|
|
// 处理ws |
|
wsGetStatus() |
|
|
|
// 添加store全局数据 |
|
let data = {} |
|
data = { |
|
"ip": props.ip, |
|
"config": {'version': selectedVersion.value, 'selected': checkedCmd.value} |
|
} |
|
store.commit("updateModule/add_update_cine", data) |
|
|
|
// 处理提交数据的结构 |
|
let cmd_array = [] |
|
checkedCmd.value.forEach((value, index) => { |
|
cmd_array.push(value) |
|
}) |
|
let params = { |
|
ip: props.ip, |
|
version: selectedVersion.value, |
|
cmd: JSON.stringify(cmd_array) |
|
} |
|
|
|
await handle_update(params).then(res => { |
|
const res_data = JSON.parse(JSON.stringify(res)) |
|
const res_ip = res_data["ip"] |
|
// 处理成功逻辑 |
|
if (res_data["result"] === "success") { |
|
handleRep(res_ip) |
|
store.commit("updateModule/clear_update_status", res_ip) // 清除临时状态 |
|
} |
|
if (res_data["result"] === "fail") { |
|
alert(res_ip + ' 升级失败:' + res_data["msg"]) |
|
handleRep(res_ip) |
|
store.commit("updateModule/clear_update_status", res_ip) // 清除临时状态 |
|
} |
|
stopWsGetStatus() // 停止获取ws更新状态 |
|
}).catch(err => { |
|
const ip = err.config.params.ip |
|
handleRep(ip) |
|
store.commit("updateModule/clear_update_status", ip) // 清除临时状态 |
|
stopWsGetStatus() // 停止获取ws更新状态 |
|
alert(ip + " 升级失败,请重试!") |
|
}) |
|
} |
|
|
|
// endregion |
|
</script> |
|
|
|
|
|
<template> |
|
<el-dialog v-model="store.state.updateModule.update_dialog_show" title="更新影院" :modal="true" width="720px" |
|
:close-on-click-modal="false" @opened="handleOpened" @close="handleClose"> |
|
<div><span class="update">更新单机:</span><span class="ip">{{ ip }}</span><span>目标版本:</span> |
|
|
|
<el-select v-model="selectedVersion" :disabled="disableAll" @change="changeVersion"> |
|
<el-option v-for="ver in git_ver" :label="ver.short_release" :value="ver.short_release" |
|
:key="ver.id"></el-option> |
|
</el-select> |
|
</div> |
|
<el-form ref="updateForm"> |
|
<el-form-item> |
|
<el-checkbox-group v-model="checkedCmd" :disabled="disableAll"> |
|
<el-divider content-position="left"> |
|
<span class="cmd_label">执行脚本</span> |
|
<ProcessIcon v-if="showStatusTips" class="process_icon" |
|
:exec-status="updateStatus.setup"/> |
|
</el-divider> |
|
<el-checkbox v-for="cmd in updateCmd.setup" v-if="true" :label="cmd.id" :key="cmd.id" |
|
:checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }} |
|
<tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips> |
|
</el-checkbox> |
|
|
|
<el-divider content-position="left"> |
|
<span class="cmd_label">数据库</span> |
|
<ProcessIcon v-if="showStatusTips" class="process_icon" |
|
:exec-status="updateStatus.sql"/> |
|
</el-divider> |
|
<el-checkbox v-for="cmd in updateCmd.sql" :label="cmd.id" :key="cmd.id" |
|
:checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }} |
|
<tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips> |
|
</el-checkbox> |
|
<el-divider content-position="left"> |
|
<span class="cmd_label">执行升级</span> |
|
<ProcessIcon v-if="showStatusTips" class="process_icon" |
|
:exec-status="updateStatus.teardown"/> |
|
</el-divider> |
|
<el-checkbox v-for="cmd in updateCmd.teardown" :label="cmd.id" :key="cmd.id" |
|
:checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }} |
|
<tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips> |
|
</el-checkbox> |
|
<el-divider content-position="left"> |
|
<span class="cmd_label">修改设置</span> |
|
<ProcessIcon v-if="showStatusTips" class="process_icon" |
|
:exec-status="updateStatus.config"/> |
|
</el-divider> |
|
<template v-for="cmd in updateCmd.config"> |
|
<el-checkbox v-if="selectedVerId >= cmd.ver_id" :label="cmd.id" :key="cmd.id" |
|
:checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }} |
|
<tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips> |
|
</el-checkbox> |
|
</template> |
|
<el-divider content-position="left"> |
|
<span class="cmd_label">客户端</span> |
|
<ProcessIcon v-if="showStatusTips" class="process_icon" |
|
:exec-status="updateStatus.client"/> |
|
</el-divider> |
|
<el-checkbox v-for="cmd in updateCmd.client" :label="cmd.id" :key="cmd.id" |
|
:checked="cmd.is_checked" :disabled="cmd.is_force">{{ cmd.desc }} |
|
<tips v-if="cmd.comment !==''" title="设置说明" :width="400" :content="cmd.comment"></tips> |
|
</el-checkbox> |
|
</el-checkbox-group> |
|
</el-form-item> |
|
</el-form> |
|
<el-button type="primary" @click="handleUpdate" :disabled="disableAll">{{ updateBtn }}</el-button> |
|
</el-dialog> |
|
</template> |
|
|
|
<style scoped> |
|
.el-checkbox-group { |
|
text-align: left; |
|
width: 640px; |
|
padding-left: 25px; |
|
} |
|
|
|
.el-checkbox { |
|
margin-left: 0; |
|
margin-right: 25px; |
|
width: 180px; |
|
padding-left: 0; |
|
text-align: left; |
|
} |
|
|
|
.el-divider--horizontal { |
|
line-height: 1; |
|
} |
|
|
|
.update { |
|
padding-left: 0; |
|
} |
|
|
|
.ip { |
|
margin-right: 100px; |
|
} |
|
|
|
:deep(.el-divider--horizontal .el-icon) { |
|
margin-left: 10px; |
|
} |
|
|
|
</style>
|
|
|