600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > HTML5+jSignature插件手写签名生成图片并转换成文件流实现服务器上传功能

HTML5+jSignature插件手写签名生成图片并转换成文件流实现服务器上传功能

时间:2022-05-02 10:11:06

相关推荐

HTML5+jSignature插件手写签名生成图片并转换成文件流实现服务器上传功能

简介

项目结构:html+vue+springboot

html引入VUE项目vue.min.js、jQuery的jquery-3.4.1.min.js,签名:modernizr.js、jSignature.min.js、jSignature.min.noconflict.js,手机端mui.min.js,弹窗样式:mustache.js、zeroModal.js

所用的js在这里

HTML

<!DOCTYPE html><html><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="renderer" content="webkit"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"><meta name="apple-mobile-web-app-capable" content="yes"><link rel="stylesheet" href="css/mui.min.css"/><link rel="stylesheet" href="css/zeroModal.css"/><title>签到</title><style>body {font-family: 'Helvetica Neue', Helvetica, sans-serif;font-size: 17px;line-height: 21px;color: #000;}html,body,#app {height: 100%;margin: 0px;padding: 0px;/* background-color: #F5F5F5 !important; */}.content{margin: 0.9375rem;}.title{height: 2.5rem;background-color: #fef6e1;color: #dc8e35;padding: 0.9375rem;font-size: 0.9375rem;display: flex;align-items: center;border-radius: 0.5rem;margin-bottom: 0.9375rem;}.title img{width: 0.9375rem;height:0.9375rem; margin-right: 0.9375rem;}.flex{display: flex;color: #333333;border-bottom: 0.0625rem solid #efefef;}.left_label{height: 1.25rem;display: inline-block;line-height: 1.25rem;color: #999;padding-top: 0.625rem;}.center_label{flex: 1;line-height: 1.25rem;text-align: left;}.center_input{flex: 1;line-height: 1.25rem;text-align: center;}.flex input{border: 0;margin-bottom: 0.5rem;}.table-view{border-radius: 0.5rem;border-top: 0;border-bottom: 0;margin-top: 0;margin-bottom: 1rem;padding-left: 0;list-style: none;background-color: #fff;}.table-view-cell{padding: 0.6875rem 0.9375rem 0 0.9375rem;overflow: hidden;}.qm{padding: 0.6875rem 0.9375rem;}.table-view::before{position: absolute;right: 0;left: 0;height: 1px;content: '';-webkit-transform: scaleY(.5);transform: scaleY(.5);background-color: #c8c7cc;top: -1px;}.table-view:after {position: absolute;right: 0;bottom: 0;left: 0;height: 1px;content: '';-webkit-transform: scaleY(.5);transform: scaleY(.5);background-color: #c8c7cc;}.memo{line-height: 1.25rem;text-indent: 1.875rem;}#signature{border: 1px solid #CCCCCC;}.qmcenter{margin-top: 1rem;}#image{border: 1px solid #CCCCCC;}</style></head><body><div id="app"><div class="content"><div class="title"><img src="image/notice.png" /><span>签到</span></div><form><ul class="table-view"><li class="table-view-cell mui-collapse-content flex"><div class="left_label" ><font style="color: red;">*</font>手机号:</div><div class="center_input"><input type="text" placeholder="请输入手机号" v-model="form.userMobile" oninvalid="userMobile" oninput="value=value.replace(/[^\d]/g,'')"></div></li><li class="table-view-cell mui-collapse-content flex"><div class="left_label" ><font style="color: red;">*</font>验证码:</div><div class="center_input"><input type="text" placeholder="请输入验证码" v-model="form.verificationCode" style="width: 55%;" id="verificationCode"><span v-show="isViewCode" style="color: #1c6fcd;" @click="sendOutVerificationCode" >获取验证码</span><span v-show="!isViewCode" style="color: #1c6fcd;">剩余时间{{count}}s</span></div></li></ul><ul class="table-view"><li class="table-view-cell mui-collapse-content qm"><div class="left_label" ><font style="color: red;">*</font>签名:</div><button type="button" class="mui-btn mui-btn-success"style="border-radius: 5px;float: right;" @click="signatureCreate">预览签名</button><button type="button" class="mui-btn mui-btn-success"style="border-radius: 5px;float: right;margin-right: 7px;" @click="signatureReset">重置签名</button><div class="center_input qmcenter"><div id="signatureparent"><div id="signature"></div></div></div></li></ul><button type="button" class="mui-btn mui-btn-primary mui-btn-block" style="border-radius: 8px;" @click="submitData">提交签到</button></form><div id="image" style="margin:20px;display: none;"></div></div></div><script type="text/javascript" src="js/jquery-3.4.1.min.js"></script><script type="text/javascript" src="js/modernizr.js"></script><script type="text/javascript" src="js/jSignature.min.js"></script><script type="text/javascript" src="js/jSignature.min.noconflict.js"></script><script type="text/javascript" src="js/mui.min.js"></script><script type="text/javascript" src="js/vue.min.js" charset="utf-8"></script><script type="text/javascript" src="js/app.js" charset="utf-8"></script><script type="text/javascript" src="js/mustache.js"></script><script type="text/javascript" src="js/zeroModal.js"></script><script type="text/javascript">$(function(){//初始化签名插件var param= {width: '100%',//签名区域的宽height: '300px',//签名区域的高signatureLine: false,//去除默认画布上那条横线lineWidth: '2' //画笔的大小};$("#signature").jSignature(param);})var app = new Vue({el: '#app',data:{form:{userMobile:undefined,verificationCode:undefined},verificationCode:undefined,isViewCode: true,count: '',timer: null,ggxxrecid:undefined,recid:undefined,detail:{},},mounted: function() {},created() {//业务代码初始化var queryStr=this.GetStrQuery();if(queryStr!=null){var whereStr=queryStr.wherestr;if(whereStr!=null && whereStr!="" && whereStr!=undefined){var whereJson = JSON.parse(whereStr);console.log(whereJson.recid);this.ggxxrecid = whereJson.recid;setTimeout(function() {app.getPxggDetail(whereJson.recid);}, 200);}}},methods: {//html弹窗modaleAlert(content,contentDetail){zeroModal.alert({content: content,contentDetail: contentDetail,width: '60%',height: '40%',okFn: function() {}});},//是否获取允许验证码sendOutVerificationCode(){if(this.form.userMobile != null){mui.ajax(serverUrl + "/getPxggTrainDetail", {data: {tel:this.form.userMobile,recid:this.ggxxrecid},dataType: "json",type: 'POST', //HTTP请求类型timeout: 20000, //超时时间设置为10秒;success: function(data) {console.log(data);if (data.code==200) {app.recid = data.msg;app.getCode();} else {mui.toast("您的报名信息不存在,请确认是否用此手机号报名!");}},error: function(xhr, type, errorThrown) {mui.toast('手机号检测异常');}});}else {mui.toast('请先输入手机号!');}},//获取验证码getCode:function(){const userMobile = this.form.userMobile;const TIME_COUNT = 120;if (!this.timer) {this.count = TIME_COUNT;this.isViewCode = false;this.timer = setInterval(() => {if (this.count > 0 && this.count <= TIME_COUNT) {this.count--;} else {this.isViewCode = true;clearInterval(this.timer);this.timer = null;}}, 1000)}mui.ajax(serverUrl + "/getMobileCode", {data: {tel:this.form.userMobile},dataType: "json",type: 'POST', //HTTP请求类型timeout: 20000, //超时时间设置为10秒;success: function(data) {if (data.code==200) {app.verificationCode = data.data;} else {mui.toast(data.msg);}},error: function(xhr, type, errorThrown) {mui.toast('获取验证码失败');}});},//初始化获取浏览器url传参GetStrQuery:function () {var params = location.search.substr(1);//这一条语句获取了包括问号开始到参数的最后,不包括前面的路径,去掉问号var pa = params.split("&");var queryStr = new Object();for(var i = 0; i < pa.length; i ++){queryStr[pa[i].split("=")[0]] = unescape(pa[i].split("=")[1]);}if(queryStr != null) return queryStr;return null;},//提交saveData:function() {app.imageSave();app.submitData();},//提交form表单submitData:function(){if (this.form.userMobile == null || this.form.userMobile == undefined || this.form.userMobile == '') {mui.toast("请填写手机号!");return;}if (this.verificationCode!=this.form.verificationCode) {mui.toast("验证码输入错误!");return;}if( $("#signature").jSignature('getData', 'native').length == 0){mui.toast("请先进行签名"); return; }this.form.recid = this.detail.recid;mui.ajax(serverUrl + "/editPxggTrain", {data: {data:JSON.stringify(this.form)},dataType: "json",type: 'POST', //HTTP请求类型timeout: 20000, //超时时间设置为10秒;success: function(data) {// console.log(data);if (data.code==200) {if (data.data) {mui.toast("保存成功!");app.reset();app.signatureReset();}} else {mui.toast(data.msg);}},error: function(xhr, type, errorThrown) {mui.toast('保存失败');}});},//重置表单数据reset:function(){app.form.userMobile=undefined;app.form.verificationCode=undefined;app.verificationCode=undefined;app.isViewCode= true;app.count= '';app.timer= null;},//重置签名画板signatureReset:function(){$("#signature").jSignature('reset');$("#image").attr('src','');document.getElementById("image").style.display="none";},//生成预览签名signatureCreate:function(){if( $("#signature").jSignature('getData', 'native').length == 0){mui.toast("请先进行签名"); return; }document.getElementById("image").style.display="";var datapair = $("#signature").jSignature("getData", "image")console.log(datapair);var img = new Image();img.src = "data:" + datapair[0] + "," + datapair[1]$(img).appendTo($("#image"))},//上传签名图片imageSave:function(){var datapair = $("#signature").jSignature("getData","image"); //将canvas里面的数据转换成base64数组var imgBase64='data:' + datapair[0] + "," + datapair[1]; //封装成正确的base64var file= this.base64toFile(imgBase64,'file');//base64转换成流文件,可以打印出来看下console.log("file====>",file);let formData = new FormData(); //封装成formData格式formData.append('file', file);formData.append('businessid', app.recid);mui.ajax(serverUrl + "/upLoadItemImage", {contentType: false, //不可少processData: false, //不可少dataType: "json",type: 'POST', //HTTP请求类型timeout: 20000, //超时时间设置为10秒;data : formData,async : false,success: function(data) {if (data.code==200) {if (data.data) {mui.toast("签名图片保存成功!");// app.reset();}} else {mui.toast(data.msg);}},error: function(xhr, type, errorThrown) {mui.toast('保存失败');}});},//重点来了,该方法将Base64格式转换成流格式base64toFile:function(dataurl, filename) {let arr = dataurl.split(',')let mime = arr[0].match(/:(.*?);/)[1]let suffix = mime.split('/')[1]let bstr = atob(arr[1])let n = bstr.lengthlet u8arr = new Uint8Array(n)while (n--) {u8arr[n] = bstr.charCodeAt(n)}return new File([u8arr], `${filename}.${suffix}`, {type: mime})},//业务代码获取详情getPxggDetail(recid){mui.ajax(serverUrl + "/getPxggDetail", {data: {recid:recid},dataType: "json",type: 'POST', //HTTP请求类型timeout: 20000, //超时时间设置为10秒;success: function(data) {console.log(data);if (data.code==200) {app.detail = data.data;this.detail = data.data;var newtime = this.parseTime(new Date(),'{y}-{m}-{d} {h}:{i}:{s}');console.log(this.detail);console.log(this.detail.signInStartTime);console.log(this.detail.signInEndTime);//当前时间大于报名开始时间if (pareDate(newtime,this.detail.signInStartTime)) {//在时间段内} else {//报名尚未开始app.modaleAlert('签到尚未开始','');$("input[type=text]").prop('disabled','disabled');$("span").prop('disabled','disabled');$(".mui-btn").prop('disabled','disabled');}//当前时间大于报名结束时间if (pareDate(newtime,this.detail.signInEndTime)) {//报名已结束app.modaleAlert('签到已结束','');$("input[type=text]").prop('disabled','disabled');$("span").prop('disabled','disabled');$(".mui-btn").prop('disabled','disabled');} else {//在时间段内}} else {mui.toast(data.msg);}}});},},});</script></body></html>

java服务端

@ApiOperation("手机端保存签名图片")@RequestMapping(value = "/upLoadItemImage", method = {RequestMethod.POST }, produces = "application/json;charset=UTF-8")public @ResponseBody AjaxResult upLoadItemImage(HttpServletRequest request, HttpServletResponse response){try {//这个是图片保存表的外键idString businessid=request.getParameter("businessid");if (StringUtils.isEmpty(businessid)){return AjaxResult.error("缺少必要参数");}String userName = "";Date now = Date.from(Instant.now());boolean istrue=false;//附件表SysAttachment attachment = new SysAttachment();// 判断 request 是否有文件上传,即多部分请求if (multipartResolver.isMultipart(request)) {// 转换成多部分requestMultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) multipartResolver.resolveMultipart(request);// 取得request中的所有文件名Iterator<String> iter = multiRequest.getFileNames();while (iter.hasNext()) {// 记录上传过程起始时的时间,用来计算上传时间int pre = (int) System.currentTimeMillis();// 取得上传文件MultipartFile file = multiRequest.getFile(iter.next());if (file != null) {// 取得当前上传文件的文件名称String fileName = file.getOriginalFilename();// 如果名称不为“”,说明该文件存在,否则说明该文件不存在if (fileName.trim() != "") {//获取原始文件名、后缀和文件大小long size = file.getSize()/ 1024;String extension = FileUploadUtils.getExtension(file);// 上传并返回新文件路径名称 YaWeiConfig.getUploadPath()是上传的路径比如D:/ruoyi/xxxString pathFileName = FileUploadUtils.upload(YaWeiConfig.getUploadPath(), file);attachment.setFileName(fileName);//附件类型attachment.setModule(WhythConstants.TRAIN.HANDWRITE_SIGN_IN_MUDOLE);attachment.setBusinessid(businessid);attachment.setPath(pathFileName);attachment.setAttachmentSize(size);attachment.setSuffix(extension);attachment.setCreateBy(userName);attachment.setCreateTime(now);attachment.setUpdateBy(userName);attachment.setUpdateTime(now);istrue=iSysAttachmentService.save(attachment);}}}}if(istrue){return AjaxResult.success(attachment);}else{return AjaxResult.error("上传失败!");}} catch (Exception e) {e.printStackTrace();logger.error("上传失败:", e);return AjaxResult.error("签名图片保存失败!失败信息:"+e.getMessage());}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。