• uniapp 实现在线签合同/签名/信息认证(无插件依赖)


    最近项目接到一个新的需求,需要对接一个可以在线签合同的的功能,知道需要后马上开干,经过一番斗争,终于终于下班啦
    开个玩笑,废话不多说,直接上代码,因为代码是直接项目中搬出来的,没有依赖其他插件纯手工,小伙伴们要看清除那些是自己需要的,不需要的就删掉啦。

    目前只测试小程序 , 其他端需要自己去适配

    效果图:
    在这里插入图片描述
    页面有两个,一个表单提交也需要上传身份证正反面,第二个页面有合同展示,签字面板是以弹窗形式

    第一个页面(表单也不需要的可以删除):

    
    <template>
    	<view>
    		<form @submit="formSubmit">
    			<view class="Rboy-box">
    				<view class="Rboy-obverse">
    					<image class="obverseimg" :src="ALMain_drawing" @click="obverse_btn" mode="aspectFill">image>
    					<input style="display: none;" name="ALMain_drawing" />
    					<view class="bottom">
    						<text>身份证正面照text>
    					view>
    				view>
    				<view class="Rboy-reverse">
    					<image class="reverseimg" :src="ALPicture" @click="reverse_btn" mode="aspectFill">image>
    					<input style="display: none;" name="ALPicture" />
    					<view class="bottom">
    						<text>身份证反面照text>
    					view>
    				view>
    			view>
    			<view class="Rboy-form">
    				<view class="Rboy-form-row">
    					<label>姓名label>
    					<view class="form-rowDom"><input placeholder="请输入姓名" disabled name="name"
    							:value="RealName.username" />view>
    				view>
    				<view class="Rboy-form-row">
    					<label>身份证号码label>
    					<view class="form-rowDom"><input placeholder="请输入身份证" disabled name="certificates"
    							:value="RealName.id_card" />view>
    				view>
    				<view class="Rboy-form-row">
    					<label>电话号码label>
    					<view class="form-rowDom"><input placeholder="请输入电话" disabled name="phone"
    							:value="RealName.phone" />view>
    				view>
    				<view class="Rboy-form-row">
    					<label>支付宝账号label>
    					<view class="form-rowDom"><input placeholder="请输入电话" disabled name="phone"
    							:value="RealName.alipay" />view>
    				view>
    			view>
    			<view class="agreement">
    				<view class="agreement-row" @click="JumpSee">
    					<view class="agreement-name">《自由职业合作服务协议》view>
    					<view class="agreement-row-label">
    						<text
    							:style="{ color: signStatus === false?'#f97777':'#666' }">{{ signStatus === false ? '去签字':'已签署' }}text>
    						<tui-icon name="arrowright" size="18">tui-icon>
    					view>
    				view>
    			view>
    			<view class="application">
    				<view class="application-tips" @click="readValve">
    					<tui-icon :color=" prevent === 'circle' ?'#999':'#fea12e' " size="14" :name="prevent">tui-icon>
    					<text style="margin-left: 10upx;">我已同意并签署《自由职业合作服务协议》text>
    				view>
    				<button form-type="submit">提交认证button>
    				
    			view>
    		form>
    	view>
    template>
    <script>
    	export default {
    		data() {
    			return {
    
    				identity: 0, //实名状态  ban:禁止实名 true:成功实名
    				ALMain_drawing: 'https://777777.com/mapp/img/comm/identity_topside.png', //身份默认证正面
    				ALPicture: 'https://777777.com/mapp/img/comm/identity_backside.png', //身份默认证反面		
    				RealName: {
    					Main_drawing: '', //身份证正面
    					Picture: '', //身份证反面	
    					username: '', //姓名
    					id_card: '', //身份证号
    					phone: '', //手机号
    					alipay: '', //支付宝
    					agreement: '' //协议
    				},
    		 	signStatus: false, //签署状态
    				prevent: 'circle',
    				// InformationRealName:true
    			}
    		},
    		async onLoad() {
    			const t = this;
    			const result = await t.$req('/user/getIdentityInfo', {})
    			let rd = result.data;
    			if (rd.code == 0) {
    				let data = rd.data;
    				t.RealName.username = data.username;
    				t.RealName.id_card = data.id_card;
    				t.RealName.phone = data.phone;
    				t.RealName.alipay = data.alipay;
    			}
    		},
    
    		onShow() {
    			const t = this;
    			uni.getStorage({
    				key: 'autograph_key',
    				success: function(res) {
    					if (res.data !== '') {
    						t.signStatus = true
    						t.RealName.agreement = res.data
    					}
    				}
    			});
    		},
    		methods: {
    			async obverse_btn() {
    				const t = this;
    				uni.chooseImage({
    					count: 1, //默认9
    					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
    					sourceType: ['album'], //从相册选择
    					success: function(res) {
    						let ImgType = res.tempFilePaths[0].split(".")
    						uni.getFileSystemManager().readFile({
    							filePath: res.tempFilePaths[0],
    							encoding: 'base64',
    						 success: async (res) => {
    								t.RealName.Main_drawing = 'data:image/png;base64,' + res.data;
    								// t.ALMain_drawing = t.RealName.Main_drawing;
    								uni.showLoading({
    									title: '加载中'
    								});
    								// console.log(res.data)
    								const result = await t.$req("/user/upload/img", {
    									uid: t.user.uid,
    									type: ImgType[1],
    									img: res.data,
    									place: 'identity'
    								})
    								let rd = result.data
    								// console.log(rd)
    								if (rd.code == 0) {
    									let data = rd.data
    									t.ALMain_drawing = data.url;
    									uni.hideLoading();
    									t.RealName.Main_drawing = data.url;
    								}
    							}
    						})
    					}
    				});
    			},
    			async reverse_btn() {
    				const t = this;
    				uni.chooseImage({
    					count: 1, //默认9
    					sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
    					sourceType: ['album'], //从相册选择
    					success: function(res) {
    						let ImgType = res.tempFilePaths[0].split(".")
    						uni.getFileSystemManager().readFile({
    							filePath: res.tempFilePaths[0],
    							encoding: 'base64',
    							success: async (res) => {
    								t.RealName.Picture = 'data:image/png;base64,' + res.data;
    								uni.showLoading({
    									title: '加载中'
    								});
    								// console.log(res.data)
    								const result = await t.$req("/user/upload/img", {
    									uid: t.user.uid,
    									type: ImgType[1],
    									img: res.data,
    									place: 'identity'
    								})
    								// https://ganqiao-dev.oss-cn-hangzhou.aliyuncs.com 测试环境路径
    								let rd = result.data
    								// console.log(rd)
    								if (rd.code == 0) {
    									let data = rd.data
    									t.ALPicture = data.url;
    									uni.hideLoading();
    									t.RealName.Picture = data.url;
    								}
    							}
    						})
    					}
    				});
    			},
    			readValve() {
    				const t = this;
    				if (t.prevent == "circle") {
    					t.prevent = "circle-fill"
    				} else {
    					t.prevent = "circle"
    				}
    			},
    			JumpSee() {
    				const t = this;
    				uni.navigateTo({
    					url: '/pages/login/seeagreement'
    				})
    			},
    			async formSubmit(e) {
    				const t = this;
    				var formdata = e.detail.value
    				if (t.RealName.Main_drawing == '') {
    					uni.showToast({
    						title: '请上传身份证正面照',
    						icon: "none",
    						duration: 2000
    					});
    					return false
    				}
    				if (t.RealName.Picture == '') {
    					uni.showToast({
    						title: '请上传身份证反面照',
    						icon: "none",
    						duration: 2000
    					});
    					return false
    				}
    				if (t.RealName.agreement == '') {
    					uni.showToast({
    						title: '请签署《自由职业合作服务协议》',
    						icon: "none",
    						duration: 2000
    					});
    					return false
    				}
    				if (t.prevent == 'circle') {
    					uni.showToast({
    						title: '请同意勾选《自由职业合作服务协议》',
    						icon: "none",
    						duration: 2000
    					});
    					return false
    				}
    				let RealName = t.RealName;
    				const result = await t.$req('/user/ysUpdateIdentity', {
    					topside: RealName.Main_drawing,
    					backside: RealName.Picture,
    					agree: 1,
    					user_sign: RealName.agreement
    				})
    				let rd = result.data
    				if (rd.code == 0) {
    
    					let data = rd.data;
    					uni.showToast({
    						title: '提交成功',
    						icon: 'none',
    						default: 200
    					})
    				}
    			}
    		}
    	}
    script>
    <style scoped lang="less">
    page{background:#fff!important}.Rboy-box{width:100%;display:flex;flex-direction:row;padding:30upx 3%;align-items:center;justify-content:space-between}.Rboy-box,.Rboy-obverse{height:auto;box-sizing:border-box}.Rboy-obverse{width:48%;margin-bottom:0upx;position:relative;box-shadow:0 3px 13px rgba(0,0,0,.05);padding:0}.Rboy-reverse{width:80%;padding:20px 3%}.obverseimg{width:100%;height:240rpx}.bottom{text-align:center;margin:auto}.bottom,.bottom text{width:100%;height:80upx;line-height:80upx}.bottom text{display:block;background:#fff;font-size:14px;color:#777}.Rboy-reverse{width:48%;height:auto;box-sizing:border-box;margin-bottom:0upx;position:relative;box-shadow:0 3px 13px rgba(0,0,0,.05);padding:0}.reverseimg{width:100%;height:240rpx}.application{width:100%;height:auto;display:flex;flex-direction:column;justify-content:center;position:fixed;bottom:20upx;left:0;right:0;padding-bottom:20upx}.application button,.application label{width:90%;height:90upx;line-height:90upx;display:block;margin:auto;text-align:center;background:linear-gradient(180deg,#efc480,#f8dca5 25%,#ffd5a2 98%);border-radius:50px;font-weight:700;font-size:15px;color:#fd972e;box-shadow:0 5px 3px #fdb964}.application button:after{border:none}.Rboy-form{width:94%;height:auto;background:#fff;margin:auto;box-shadow:0 3px 13px rgba(0,0,0,.05;);box-sizing:border-box;padding:0upx 3%}.Rboy-form-row{width:100%;display:flex;flex-direction:row;justify-content:space-between;align-items:center;border-bottom:1px solid #f5f3f3;height:100upx;line-height:100upx}.Rboy-form-row label{width:25%;font-size:14px}.form-rowDom{width:75%}.form-rowDom input{width:100%;font-size:12px}.agreement{width:94%;height:auto;background:#fff;margin:30upx auto;box-shadow:0 3px 13px rgba(0,0,0,.05);box-sizing:border-box;padding:0 3%}.agreement-row{width:100%;height:auto;display:flex;flex-direction:row;justify-content:space-between;align-items:center}.agreement-name{width:70%;height:100upx;line-height:100upx;text-align:left;font-size:14px;color:#2ebbfe}.agreement-row-label{width:30%;height:100upx;line-height:100upx;display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.agreement-row-label text{font-size:12px}.application-tips{width:90%;height:auto;margin:0 auto;line-height:80upx}.application-tips text{color:#999}
    style>
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261

    第二个页面:(签名页-请把接口改成自己的 不然容易报错)

    
    <template>
    	<view class="content">
    
    		<view class="authentication_top">
    			<image v-if="PreviewContract" :src="contractImg" mode="widthFix">image>
    			
    			<view class="bgCoverBox" v-if="publish"><canvas :style="{width:height +'px',height:width +'px'}" canvas-id="mycontract" class="canvsborder2">canvas>view>
    			
    		view>
    		<view class="authentication_bottom" v-if="NavAutograph" style="background:#ffe9e9" @click="agreeSign">
    			<button style="color:#f00">我已阅读上述内容,同意签字>>button>
    		view>
    	
    		<view class="authentication_fun" v-if="Navpreservation" style="background:#fff; ">
    			
    			<button style="color:#fd972e;"  @click="SigningCompleted">签署完成,去提交>>button>
    		view>
    	
    		
    		<view class="signMask" v-if="autographStatus">
    			<view class="sigh-btns">
    				<button class="btn" @tap="handleCancel">取消button>
    				<button class="btn" @tap="handleReset">重写button>
    				<button class="btn" @tap="handleConfirm">确认button>
    			view>
    			<view class="sign-box">
    				<canvas class="mycanvas" :style="{width:width +'px',height:height +'px'}" canvas-id="mycanvas"
    					@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">canvas>
    				<canvas canvas-id="camCacnvs" :style="{width:height +'px',height:width +'px'}"
    					class="canvsborder">canvas>
    			view>
    		view>
    
    		
    
    	view>
    template>
    <script>
    	var x = 20;
    	var y = 20;
    	var tempPoint = []; //用来存放当前画纸上的轨迹点
    	var id = 0;
    	var type = '';
    	let that;
    	let canvasw;
    	let canvash;
    	export default {
    		data() {
    			return {
    				
    				contractImg: '../../static/motu.jpg', //合同路径
    				ctx: '', //绘图图像
    				points: [], //路径点集合,
    				width: 0,
    				height: 0,
    				autographStatus: false,
    				publish: false,
    				PreviewContract:true,
    				NavAutograph: true,
    				Navpreservation:false
    			}
    		},
    		onLoad(option) {
    			that = this;
    			id = option.id;
    			type = option.type;
    			this.ctx = uni.createCanvasContext('mycanvas', this); //创建绘图对象
    			//设置画笔样式
    			this.ctx.lineWidth = 4;
    			this.ctx.lineCap = 'round';
    			this.ctx.lineJoin = 'round';
    			uni.getSystemInfo({
    				success: function(res) {
    					that.width = res.windowWidth * 0.8;
    					that.height = res.windowHeight * 0.85;
    				}
    			});
    		},
    		onShow() {
    			const t = this;
    			uni.getStorage({
    				key: 'autograph_key',
    				success: function (res) {
    					if( res.data !== '' ){
    						t.contractImg = res.data
    						t.PreviewContract = true;
    						t.publish = false;
    						t.NavAutograph = false
    					}
    				}
    			});				
    		},		
    		
    		methods: {
    			agreeSign() {
    				this.autographStatus = true;
    			},
    
    			//触摸开始,获取到起点
    			touchstart: function(e) {
    				let startX = e.changedTouches[0].x;
    				let startY = e.changedTouches[0].y;
    				let startPoint = {
    					X: startX,
    					Y: startY
    				};
    				/* **************************************************
    				#由于uni对canvas的实现有所不同,这里需要把起点存起来
    			 * **************************************************/
    				this.points.push(startPoint);
    
    				//每次触摸开始,开启新的路径
    				this.ctx.beginPath();
    			},
    			//触摸移动,获取到路径点
    			touchmove: function(e) {
    				let moveX = e.changedTouches[0].x;
    				let moveY = e.changedTouches[0].y;
    				let movePoint = {
    					X: moveX,
    					Y: moveY
    				};
    				this.points.push(movePoint); //存点
    				let len = this.points.length;
    		 	if (len >= 2) {
    					this.draw(); //绘制路径
    				}
    				tempPoint.push(movePoint);
    			},
    			// 触摸结束,将未绘制的点清空防止对后续路径产生干扰
    			touchend: function() {
    				this.points = [];
    			},
    			/* ***********************************************	
    					#   绘制笔迹
    					#   1.为保证笔迹实时显示,必须在移动的同时绘制笔迹
    					#   2.为保证笔迹连续,每次从路径集合中区两个点作为起点(moveTo)和终点(lineTo)
    					#   3.将上一次的终点作为下一次绘制的起点(即清除第一个点)
    					************************************************ */
    			draw: function() {
    				let point1 = this.points[0];
    				let point2 = this.points[1];
    				this.points.shift();
    				this.ctx.moveTo(point1.X, point1.Y);
    				this.ctx.lineTo(point2.X, point2.Y);
    				this.ctx.stroke();
    				this.ctx.draw(true);
    			},
    			handleCancel() {
    				uni.navigateBack({
    					delta: 1
    				});
    			},
    			//清空画布
    			handleReset: function() {
    				console.log('handleReset');
    				that.ctx.clearRect(0, 0, that.width, that.height);
    				that.ctx.draw(true);
    				tempPoint = [];
    			},
    			//将签名笔迹上传到服务器,并将返回来的地址存到本地
    			handleConfirm: function() {
    				const t = this;
    				if (tempPoint.length == 0) {
    					uni.showToast({
    						title: '请先签名',
    						icon: 'none',
    						duration: 2000
    					});
    					return;
    				}
    				uni.showLoading({
    					title: '生成中'
    				});
    				uni.canvasToTempFilePath({
    					canvasId: 'mycanvas',
    					success: function(res) {
    						let tempPath = res.tempFilePath;
    						const ctx = uni.createCanvasContext('camCacnvs', that);
    						ctx.translate(0, that.width);
    						ctx.rotate((-90 * Math.PI) / 180);
    						ctx.drawImage(tempPath, 0, 0, that.width, that.height);
    						ctx.draw();
    						setTimeout(() => {
    							//保存签名图片到本地
    							uni.canvasToTempFilePath({
    									canvasId: 'camCacnvs',
    									success: function(res) {
    										//这是签名图片文件的本地临时地址
    										let path = res.tempFilePath;
    										console.log(path, "保存签名图片到本地")
    										t.autographStatus = false
    										// 开始合成
    										var _this = this;
    										t.publish = true;
    										t.PreviewContract = false;
    										t.NavAutograph = false;
    										t.Navpreservation = true;
    										const loy = uni.createCanvasContext('mycontract', this);
    										// loy.clearRect(0, 0, that.width, that.height);
    										// loy.translate(0, 0);
    										// loy.rotate((0 * Math.PI) / 180);
    										let imgGao = ''
    										uni.getSystemInfo({
    											success:function(res){
    												imgGao = res.screenWidth 
    											}
    										})
    										loy.drawImage(t.contractImg, 0, 0, 375 , 600);
    										loy.drawImage(path, 260, 500, 100, 50);
    										loy.draw();
    										setTimeout(() =>{
    											uni.canvasToTempFilePath({
    												canvasId: 'mycontract',
    												success: function(res) {
    													uni.hideLoading();
    													t.contractImg = res.tempFilePath;
    													// console.log("合同图片",res.tempFilePath)
    												}	
    											})
    										} ,200)
    										// 合成完毕
    									},
    									fail: err => {
    										// console.log('fail', err);
    									}
    								},
    								this
    							);
    						}, 200);
    					}
    				});
    			},
    			preservationImg(){
    				const t = this;
    				uni.downloadFile({
    					url: t.contractImg,
    					success: res => {
    						if (res.statusCode === 200) {
    							uni.saveImageToPhotosAlbum({
    								filePath: res.tempFilePath,
    								success: function() {
    									uni.showToast({
    										title: '保存成功',
    										icon: 'none',
    										duration: 2000
    									});
    								},
    								fail: function() {
    									uni.showToast({
    										title: '保存失败',
    										icon: 'none',
    										duration: 2000
    									});
    								}
    							});
    						} else {
    							uni.showToast({
    								title: '第三方网络错误',
    								icon: 'none',
    								duration: 2000
    							});
    						}
    					}
    				});
    			},
    			SigningCompleted(){
    				const t = this;
    				let ImgType = t.contractImg.split(".")
    				uni.getFileSystemManager().readFile({
    					  filePath: t.contractImg,
    					  encoding: 'base64',
    					  success: async(res) =>{
    						  t.contractImg = 'data:image/png;base64,' + res.data;
    						  uni.showLoading({
    							  title: '提交中'
    						  });
    						  // console.log(res.data)
    						   const result = await t.$req("/user/upload/img",{ 
    							   uid: t.user.uid,
    							   type: ImgType[1],
    							   img: res.data,
    							   place: 'sign'	
    							})
    							let rd = result.data
    							// console.log(rd)
    							if(rd.code == 0){
    								let data = rd.data
    								t.contractImg = data.url;								
    								uni.hideLoading();
    								uni.setStorage({
    									key: 'autograph_key',
    									data: t.contractImg,
    									success: function () {
    										console.log("签字",'success');
    									}
    								});
    								uni.navigateBack({ delta: 1 });    // 返回上一页								
    							}
    					  }
    				})				
    			},
    			ReSign:function(){
    				// console.log(this.ctx)
    				this.autographStatus = true
    			}
    		}
    	}
    script>
    <style>
    .authentication_top{width:100%;height:90%;position:fixed;top:0;left:0;right:0;margin:auto;overflow-y:scroll;padding-bottom:40rpx}.authentication_top image{width:100%;display:inline-block}.authentication_bottom{width:100%;height:10%;position:fixed;bottom:0;left:0;right:0;margin:auto;display:flex;flex-direction:column;justify-content:center;align-items:center;background:#ffe9e9}.authentication_bottom button{background:0 0;border:none;font-size:15px;color:red;width:100%;text-align:center}.authentication_bottom button:after{display:none}.authentication_fun{width:100%;height:10%;position:fixed;bottom:30rpx;left:0;right:0;margin:auto;display:flex;flex-direction:row;justify-content:center;align-items:center;background:#ffe9e9;padding:0 3%;width:90%;border-radius:50px;box-shadow:0 3px 13px rgba(0,0,0,.2);border:4px solid #fd972e;box-sizing:border-box}.authentication_fun button{border:none;font-size:15px;background:0 0;width:100%;text-align:center}.authentication_fun button:after{display:none}.signMask{width:100%;height:100%;background:#fff;position:fixed;top:0;bottom:0;left:0;right:0;flex-direction:row}.sign-box,.signMask{margin:auto;display:flex}.sign-box{width:80%;height:90%;flex-direction:column;text-align:center}.sigh-btns,.sign-view{height:100%}.sigh-btns{margin:auto;display:flex;flex-direction:column;justify-content:space-around}.btn{margin:auto;padding:8rpx 40rpx;font-size:14px;transform:rotate(90deg);border:1rpx solid grey}.mycanvas{margin:auto 0rpx;background-color:#ececec}.canvsborder{border:1rpx solid #333;position:fixed;top:0;left:10000rpx}.bgCoverBox{width:100%;height:auto}.canvsborder2{height:700px!important}
    	
    style>
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
  • 相关阅读:
    SENET和GateNet(推荐系统(embedding))
    刷题2个月,终于挺进梦寐以求的大厂,数据结构和算法太TM重要了
    Redis数据库
    Android开发中Button背景颜色不能修改问题及解决方法
    2022.8.22面试
    电影产业的数据洞察:爬虫技术在票房分析中的应用
    【LeetCode: 207.课程表:拓扑排序+图】
    MODBUS-RTU从站通信(SMART PLC作为MODBUS-RTU从站)
    初识Scrapy和使用
    独立站定制开发,如何做Google广告引流
  • 原文地址:https://blog.csdn.net/changshataofan/article/details/128183848