来访人员登记系统(十二)动态增减html页面表格表单并获取表单值传递给C#后台
前置模块
来访人员登记系统(十)网页端使用websocket向C#服务端传送图片和文字
本文在上文的基础上增加了动态增减表格表单的功能,实现通过单击按钮增加或删除一列表格和其中的表单,用递增的id区分开每一个表单项,并获取其中的提交值传递给后台进行文字和图片处理。
HTML
HTML中增加了两个按钮,用于控制表格的增减,另外还增加了对每个需要提交的表单项的编号,方便后台进行处理。
<!DOCTYPE html>
<html lang="zh-cn" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html" charset="utf-8" />
<title>XXXX股份有限公司主机房人员出入申请单</title>
<link rel="stylesheet" href="style.css" />
<script type="text/javascript" src="script.js" charset="utf-8"></script>
</head>
<body>
<div id="caption">
<h1>XXXX股份有限公司</h1>
<h1>主机房人员出入申请单</h1>
</div>
<div>
<input id="delcol" class="button leftbutton" type="button" value="减少列" />
<input id="addcol" class="button rightbutton" type="button" value="增加列" />
</div>
<div id="maincontent">
<form id="sendForm">
<table id="formtable">
<tr>
<td><input id="staff1" class="text" type="text" placeholder="弘业对接人员" required /></td>
</tr>
<tr>
<td><input id="name1" class="text" type="text" placeholder="外单位人员" required /></td>
</tr>
<tr>
<td><input id="company1" class="text" type="text" placeholder="单位名称" required /></td>
</tr>
<tr>
<td><input id="idcard1" class="text" type="text" placeholder="身份证号" required pattern="/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/" /></td>
</tr>
<tr>
<td><span class="imgtext">身份证国徽面照片:</span></td>
</tr>
<tr>
<td><img id="previewa_1" class="preview" /></td>
</tr>
<tr>
<td><input id="imga_1" class="file" type="file" accept="image/*" required /></td>
</tr>
<tr>
<td><span class="imgtext">身份证人像面照片:</span></td>
</tr>
<tr>
<td><img id="previewb_1" class="preview" /></td>
</tr>
<tr>
<td><input id="imgb_1" class="file" type="file" accept="image/*" required /></td>
</tr>
<tr>
<td><input id="phone1" class="text" type="text" placeholder="电话" required /></td>
</tr>
<tr>
<td><span>预约日期:</span><input id="date1" class="date" type="date" required /></td>
</tr>
<tr>
<td><input id="ETA1" class="text" type="text" placeholder="预期到达时间(hh:mm)" required pattern="^(?:(?:[0-2][0-3])|(?:[0-1][0-9])):[0-5][0-9]$" /></td>
</tr>
<tr>
<td><textarea id="intention1" placeholder="进出事由" required></textarea></td>
</tr>
<tr>
<td><textarea id="relevants1" placeholder="涉及设备/系统" required></textarea></td>
</tr>
</table>
<div>
<input class="button leftbutton" type="submit" value="提交" />
<input class="button rightbutton" type="reset" value="重置" />
</div>
</form>
</div>
</body>
</html>
CSS
css中在上文的基础上加入了一些优化,改了几个类的名字。
body {
font-family: 'Microsoft YaHei';
text-align: center;
}
#caption {
margin-top: 60px;
margin-bottom: 40px;
}
#maincontent {
margin-bottom: 60px;
}
table {
margin: 0 auto;
margin-top: 5px;
margin-bottom: 30px;
text-align: center;
font-size: 18px;
}
td {
padding: 20px 20px 20px 20px;
}
input {
font-size: 18px;
font-family: 'Microsoft YaHei';
}
.text {
width: 300px;
height: 40px;
}
.imgtext {
display: block;
text-align: left;
}
.preview {
width: 300px;
height: 200px;
overflow: hidden;
}
.file {
font-size: 15px;
}
.date {
width: 210px;
height: 35px;
}
textarea {
font-size: 18px;
font-family: 'Microsoft YaHei';
width: 300px;
height: 100px;
resize: none;
}
.button {
width: 80px;
height: 40px;
}
.leftbutton {
margin-right: 30px;
}
.rightbutton {
margin-left: 30px;
}
Javascript
js中增加了将图片预览事件的绑定封装成函数进行调用,增加了动态增减表单项的功能,每次增加时自动绑定图片的change事件。在与服务端通信时采用循环的方式,一次循环提交一组文字+图片,文字图片分离提交,图片对应的身份证号附在图片的base64码的末尾。
// javascript
var start = function () {
// 上传并预览图片
var previewimg = function (imga, prea, imgb, preb) {
var fileDom1 = document.getElementById(imga);
var previewDom1 = document.getElementById(prea);
var fileDom2 = document.getElementById(imgb);
var previewDom2 = document.getElementById(preb);
fileDom1.addEventListener("change", e => {
var file = fileDom1.files[0];
// 检查上传的文件是否为图片格式
if (!file || file.type.indexOf("image/") < 0) {
fileDom1.value = "";
previewDom1.src = "";
return;
}
var fileReader = new FileReader();
fileReader.onload = e => {
previewDom1.src = e.target.result;
};
fileReader.readAsDataURL(file);
});
fileDom2.addEventListener("change", e => {
var file = fileDom2.files[0];
if (!file || file.type.indexOf("image/") < 0) {
fileDom2.value = "";
previewDom2.src = "";
return;
}
var fileReader = new FileReader();
fileReader.onload = e => {
previewDom2.src = e.target.result;
};
fileReader.readAsDataURL(file);
});
};
// 绑定初始列的图片预览事件
previewimg("imga_1", "previewa_1", "imgb_1", "previewb_1");
// 动态增减表格的列
var addcolumnbtn = document.getElementById("addcol");
var delcolumnbtn = document.getElementById("delcol");
var column_num = 1; // 记录当前列的个数,提交时需要用此参数遍历
addcolumnbtn.addEventListener('click', function (e) {
var table = document.getElementById('formtable');
var length_row = table.rows.length;
var row0 = table.rows[0].cells;
var length_col = row0.length;
column_num += 1;
// 填充表格内容并修改input的id
for (var i = 0; i < length_row; i++) {
var x = table.rows[i].insertCell(length_col);
x.innerHTML = table.rows[i].cells[length_col - 1].innerHTML.replace(column_num - 1, column_num);
}
// 清空图片上传和图片预览绑定的资源
document.getElementById("imga_" + column_num).value = "";
document.getElementById("previewa_" + column_num).src = "";
document.getElementById("imgb_" + column_num).value = "";
document.getElementById("previewb_" + column_num).src = "";
// 绑定图片上传事件
previewimg("imga_" + column_num, "previewa_" + column_num, "imgb_" + column_num, "previewb_" + column_num);
});
delcolumnbtn.addEventListener('click', function (e) {
var table = document.getElementById('formtable');
var length_row = table.rows.length;
var row0 = table.rows[0].cells;
var length_col = row0.length - 1;
if (length_col) {
column_num -= 1;
for (var i = 0; i < length_row; i++) {
table.rows[i].deleteCell(length_col);
}
}
else {
alert("至少需要一个预约人,无法减少。");
}
});
// 建立websocket通信
var wsImpl = window.WebSocket || window.MozWebSocket;
window.ws = new wsImpl('ws://192.168.204.43:7181/');
var form = document.getElementById('sendForm');
// 以base64格式发送图片文件,并把身份证号附在最后
function sendFile(fileDom, idcard) {
var file = fileDom.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (e) {
var base64Code = reader.result;
ws.send(base64Code + "," + idcard);
};
}
// 覆写提交事件
form.addEventListener('submit', function (e) {
e.preventDefault();
for (var i = 1; i <= column_num; i++) {
var staff = document.getElementById('staff' + i);
var name = document.getElementById('name' + i);
var company = document.getElementById('company' + i);
var idcard = document.getElementById('idcard' + i);
var phone = document.getElementById('phone' + i);
var date = document.getElementById('date' + i);
var ETA = document.getElementById('ETA' + i);
var intention = document.getElementById('intention' + i);
var relevants = document.getElementById('relevants' + i);
var fileDom1 = document.getElementById('imga_' + i);
var fileDom2 = document.getElementById('imgb_' + i);
var msg = staff.value + ',' + name.value + ',' + company.value + ',' + idcard.value + ',' + phone.value + ',' + date.value + ',' +
ETA.value + ',' + intention.value + ',' + relevants.value;
ws.send(msg);
sendFile(fileDom1, idcard.value);
sendFile(fileDom2, idcard.value);
}
alert("您的申请已提交。");
form.reset();
for (var i = 1; i <= column_num; i++) {
document.getElementById('previewa_' + i).src = "";
document.getElementById('previewb_' + i).src = "";
}
});
};
window.onload = start;
C#服务端
C#中取消了采用static变量current_idcard确定图片对应身份证号信息的方式,换用为将身份证号信息写入图片末尾的方式,用逗号分隔。
// 将客户端发来的身份证照片的base64码复原成图片,并存储到本地文件夹
private void saveidcardImage(string msg)
{
// base64码预处理
string hz = msg.Split(',')[0].Split(';')[0].Split('/')[1];
string[] str = msg.Split(',');
byte[] imageBytes = Convert.FromBase64String(str[1]);
string idcard = str[2];
//读入MemoryStream对象
MemoryStream memoryStream = new MemoryStream(imageBytes, 0, imageBytes.Length);
memoryStream.Write(imageBytes, 0, imageBytes.Length);
// 保存图片
Image image = Image.FromStream(memoryStream);
string filename = image_directory + idcard + "_a." + hz;
if (!File.Exists(filename))
{
image.Save(filename);
}
else
{
filename = image_directory + idcard + "_b." + hz;
image.Save(filename);
}
}
总结
将事件的操作封装为函数以方便调用,比直接写事件逻辑性更好;
对id进行编号后,用循环可以很方便地控制多组数据的分别发送。