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

<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>