hwasmart-yanfaleixiangmu-es.../src/render/components/ProgramBurnForm.vue

445 lines
9.7 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

<template>
<h1 class="text-center text-3xl title">ESP32程序批量烧录</h1>
<div class="home">
<div class="operatebox">
<div class="flexbox">
<div class="p-4 nop">
<div class="textport">待烧录串口</div>
<textarea disabled class="commsg resize-none border-2" :value="ports">
</textarea>
</div>
<div class="p-4 nop">
<div class="textport"> </div>
<button
class="seleanni px-4 border-2 rounded text-white"
:class="loading ? 'bg-gray-500' : 'bg-blue-500'"
:disabled="loading"
@click="selectFile"
>
   
</button>
</div>
<div class="p-4 truncate nop">
<input
disabled
type="text"
class="filebox border-2"
:value="selectedFilePath"
/>
</div>
</div>
<div class="col-span-2 nopd">
<button
class="anni px-4 border-2 rounded text-white"
:class="loading ? 'bg-gray-500' : 'bg-blue-500'"
:disabled="loading"
@click="burn_start"
>
<svg
v-if="loadings"
class="svgbox animate-spin h-5 w-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
<div class="fontset" v-else>烧   录</div>
</button>
</div>
<div class="tips">
<h6 class="tipstitle">操 作 方 法</h6>
<textarea disabled class="tipsmsg resize-none border-2">
1. 待烧录或烧录失败的串口会自动显示。
2. 点击按钮选择需要烧录的程序。
3. 点击烧录按钮,等待烧录完成。
**右侧为烧录输出**
#若烧录失败可以通过烧录输出判断错误原因#
</textarea
>
</div>
</div>
<div class="msgbox">
<textarea
ref="container"
disabled
class="textbox resize-none border-2 w-full"
:value="msg"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, inject, watch, onMounted } from "vue";
function alert(data) {
loading.value = true;
var a = document.createElement("div"),
p = document.createElement("p"),
btn = document.createElement("div"),
textNode = document.createTextNode(data ? data : ""),
btnText = document.createTextNode("确定");
// 控制样式
css(a, {
"padding-top": "60px",
position: "fixed",
left: "0",
right: "0",
top: "40%",
width: "300px",
height: "180px",
margin: "0 auto",
"background-color": "#fff",
border: "2px solid #ccc",
"font-size": "100%",
"text-align": "center",
"z-index": "3",
});
css(btn, {
margin: "10%",
"margin-bottom": "5%",
width: "80%",
position: "absolute",
bottom: "0",
background: "#2222ff",
opacity: "0.8",
"border-radius": "24px",
color: "#fff",
});
// 内部结构套入
p.appendChild(textNode);
btn.appendChild(btnText);
a.appendChild(p);
a.appendChild(btn);
// 整体显示到页面内
document.getElementsByTagName("body")[0].appendChild(a);
// 确定绑定点击事件删除标签
btn.onclick = function () {
a.parentNode?.removeChild(a);
loading.value = false;
};
}
function css(targetObj, cssObj) {
var str = targetObj.getAttribute("style") ? targetObj.getAttribute("style") : "";
for (var i in cssObj) {
str += i + ":" + cssObj[i] + ";";
}
targetObj.style.cssText = str;
}
window.alert = alert;
const IPCRENDERER_API_SUPPORTED = inject("IPCRENDERER_API_SUPPORTED", false);
const loading = ref(false);
const loadings = ref(false);
const msg = ref("烧录结果输出:\n");
const container = ref(null);
const selectedPort = ref("");
const ports = ref([]);
const errsum = ref(0);
const sucsum = ref(0);
const succom = ref([]);
const failedcom = ref([]);
const comlength = ref(0);
const setPorts = (value: Object[]) => {
let compath = [];
value.forEach((element) => {
compath.push(element.path);
});
if (loading.value == false) {
ports.value = compath;
}
comlength.value = ports.value.length;
};
const selectedFilePath = ref("");
const setSelectedFilePath = (value: string) => (selectedFilePath.value = value);
const selectFile = () => {
if (!IPCRENDERER_API_SUPPORTED) {
alert("The ipcRenderer API is not supported.");
return;
}
ipcRenderer.send("SELECT_FILE");
};
const alert_msg = (value: string) => {
if (!value) {
return;
}
alert(value);
};
const errlog = (value: number) => {
if (!value) {
return;
}
errsum.value = value;
};
const suclog = (value: number) => {
if (!value) {
return;
}
sucsum.value = value;
};
const append_msg = (value: string) => {
if (!value) {
return;
}
msg.value += value + "\n";
};
const suc_result = (value: Array<string>) => {
if (!value) {
return;
}
succom.value.push(value);
};
const failed_result = (value: Array<string>) => {
if (!value) {
return;
}
failedcom.value.push(value);
};
const scroll = () => {
setTimeout(() => (container.value.scrollTop = container.value.scrollHeight), 5);
};
const burn = () => {
selectedPort.value = ports.value.shift();
const param = {
selectedPort: selectedPort.value,
selectedFilePath: selectedFilePath.value,
errsum: errsum.value,
sucsum: sucsum.value,
};
ipcRenderer.send("BURN", param);
loading.value = true;
loadings.value = true;
};
const burn_start = () => {
if (ports.value.length == 0) {
alert("未发现串口");
return;
}
if (!selectedFilePath.value) {
alert("请选择程序文件");
return;
}
succom.value = [];
failedcom.value = [];
errsum.value = 0;
sucsum.value = 0;
msg.value = "烧录结果输出:\n";
burn();
};
watch(msg, () => {
scroll();
});
onMounted(() => {
if (!IPCRENDERER_API_SUPPORTED) {
alert("The ipcRenderer API is not supported.");
return;
}
ipcRenderer.receive("SELECT_FILE", setSelectedFilePath);
ipcRenderer.receive("LIST_PORTS", setPorts);
ipcRenderer.receive("BURN_END", () => {
if (ports.value.length == 0) {
loadings.value = false;
loading.value = false;
if (errsum.value == 0) {
alert("串口已全部烧录成功!");
return;
} else if (sucsum.value == 0) {
alert("串口已全部烧录失败!");
ports.value = failedcom.value;
return;
} else {
alert(`烧录结束,成功:${sucsum.value}个,失败:${errsum.value}`);
ports.value = failedcom.value;
return;
}
}
burn();
});
ipcRenderer.receive("ALERT_MSG", alert_msg);
ipcRenderer.receive("ERR_SUM", errlog);
ipcRenderer.receive("SUC_SUM", suclog);
ipcRenderer.receive("APPEND_MSG", append_msg);
ipcRenderer.receive("FAILED_RESULT", failed_result);
ipcRenderer.receive("SUC_RESULT", suc_result);
// ipcRenderer.receive('CLEAN_MSG' , () => msg.value = '')
});
</script>
<style scoped>
.title {
min-width: 220px;
height: 14vh;
line-height: 14vh;
}
.textport {
width: 45%;
font-size: clamp(0.8rem, 0.5rem + 1vw, 2rem);
display: flex;
align-items: center;
}
.anni {
width: 40%;
min-width: 60px;
height: 80%;
margin-top: 1%;
border-radius: 48px;
position: relative;
z-index: 2;
}
.fontset {
margin: auto;
width: 100%;
text-align: center;
display: flex;
font-size: clamp(0.8rem, 0.5rem + 1vw, 2rem);
justify-content: space-around;
align-items: center;
}
.seleanni {
width: 45%;
border-radius: 24px;
height: 100%;
font-size: clamp(0.8rem, 0.5rem + 1vw, 2rem);
}
.selebox {
width: 45%;
border-radius: 24px;
height: 100%;
box-shadow: inset 4px 4px 4px rgba(0, 0, 0, 0.3),
inset -4px -4px 4px rgba(255, 255, 255, 0.7);
}
.filebox {
min-width: 90px;
width: 90%;
background-color: #fff;
height: 100%;
border-radius: 24px;
white-space: nowrap;
overflow: hidden;
box-shadow: inset 4px 4px 4px rgba(0, 0, 0, 0.3),
inset -4px -4px 4px rgba(255, 255, 255, 0.7);
}
.flexbox {
margin: 0;
width: 100%;
height: 40%;
background-color: #eeffff;
display: flex;
justify-content: center;
align-content: space-evenly;
flex-wrap: wrap;
overflow: hidden;
}
.svgbox {
margin: auto;
}
.nop {
padding: 0;
padding-left: 10%;
flex: 1;
min-width: 100%;
max-width: 200%;
height: 16%;
min-height: 28px;
overflow: hidden;
display: flex;
justify-content: start;
}
.nopd {
padding: 0;
flex: 1;
display: flex;
width: 100%;
height: 10%;
justify-content: center;
align-content: center;
}
.msgbox {
padding: 0;
width: 48%;
height: 100%;
overflow: hidden;
}
.textbox {
height: 100%;
background-color: #ffe;
}
.home {
height: 80vh;
display: flex;
justify-content: center;
margin: auto;
}
.operatebox {
margin: 0;
width: 48%;
margin-right: 1%;
height: 100%;
background-color: #ccffff;
}
.tips {
width: 100%;
height: 50%;
background-color: #99ffff;
padding-left: 9%;
}
.tipstitle {
width: 90%;
min-width: 120px;
min-height: 10%;
text-align: center;
padding-top: 1.5%;
font-size: clamp(0.6rem, 0.5rem + 1vw, 1.2rem);
}
.tipsmsg {
width: 90%;
height: 80%;
background-color: #efe;
}
.commsg {
width: 45%;
height: 100%;
background-color: #efe;
}
</style>