【nodejs】大事件后台管理系统(四)——layui前端布局与改进

  • 【nodejs】大事件后台管理系统(四)——layui前端布局与改进已关闭评论
  • 23 次浏览
  • A+
所属分类:Web前端
摘要

文件位置:1.Node.js零基础入门教程node.js—资料day8素材大事件项目
在assets/js/baseAPI.js中修改统一请求根路径


6. layui大事件项目

文件位置:1.Node.js零基础入门教程node.js—资料day8素材大事件项目
assets/js/baseAPI.js中修改统一请求根路径

6.1 调整接口名称

纯粹是因为之前本人手贱,故意修改名称与端口所致的。
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

assets/js/login.js中修改注册的post接口
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

6.2 express启动

先在VSCode的扩展中加上express插件先
【nodejs】大事件后台管理系统(四)——layui前端布局与改进
接着启动之前的api_server后端项目

nodemon app.js 

然后再回到前端项目,按住ctrl+shift+p调出Express: Host Current Workspace and Open in Browser
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

6.3 最终效果

输入我的数据库信息(因人而异):

  • 账号:ks
  • 密码:123456
    【nodejs】大事件后台管理系统(四)——layui前端布局与改进

6.4 Layui布局问题

6.4.1 文章类别列表删除失效问题

打开assets/js/article/art_cate.js,找到删除文章类别的异步处理函数,通过console.log控制台打印命令发现,之所以不能删除是因为没有返回status,没返回它则是因为找不到id,因为它返回为空。
【nodejs】大事件后台管理系统(四)——layui前端布局与改进
而造成这个问题的原因则是因为前端找不到这个属性名ID,但我们数据库写的是id。
aricle/art_cate.html
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

6.4.2 文章类别列表的编辑失效问题

因为上一节的更新文章类别的校验规则对象body参数里面定义了我们数据库的id为Id,但是我们的前端只能找数据库的存在的信息,而不是跑去后端验证,所以出现跟上面一样的问题。

【nodejs】大事件后台管理系统(四)——layui前端布局与改进

更改schema/artcate.js的更新分类校验对象。

// 校验规则对象 - 更新分类 exports.update_cate_schema = { 	body: { 		id, 		name, 		alias, 	}, } 

更改router_handler/artcate.js里面的更新文章处理分类对象的body校验对象的Id为id。

// 更新文章分类的处理函数 exports.updateCateById = (req, res) => { 	// const sql = `select * from ev_article_cate where name=? or alias=?` 	const sql = `select * from ev_article_cate where id != ? and (name=? or alias=?)`  	// 执行查重操作 	db.query( 		sql, 		[req.body.id, req.body.name, req.body.alias], 		(err, results) => { 			// 执行 SQL 语句失败 			if (err) return res.cc(err)  			// 判断 分类名称 和 分类别名 是否被占用 			if (results.length === 2) 				return res.cc('分类名称与别名被占用,请更换后重试!') 			if ( 				results.length === 1 && 				results[0].name === req.body.name && 				results[0].alias === req.body.alias 			) 				return res.cc('分类名称与别名被占用,请更换后重试!') 			if (results.length === 1 && results[0].name === req.body.name) 				return res.cc('分类名称被占用,请更换后重试!') 			if (results.length === 1 && results[0].alias === req.body.alias) 				return res.cc('分类别名被占用,请更换后重试!')  			// 更新文章分类 			const sql = `update ev_article_cate set ? where id=?`  			db.query(sql, [req.body, req.body.id], (err, results) => { 				// 执行 SQL 语句失败 				if (err) return res.cc(err) 				// console.log(results) 				// SQL 语句执行成功,但是影响行数不等于 1 				if (results.affectedRows !== 1) 					return res.cc('更新文章分类失败!')  				// 更新文章分类成功 				res.cc('更新文章分类成功!', 0) 			}) 		} 	) 	// res.send('ok') } 

之后通过测试软件进行接口测试是没问题,这里就懒得展示了。

但是即便这点击编辑后,弹出修改表单窗口也没多大的关系,它会提示Id必须为Number,这就很奇怪了。

回到我们前端的编辑问题上,编辑要依靠id绑定了btn-editform-edit经过的接口有两个,第一个是根据id获取文章分类,绑定点击事件click的异步操作,看到之前把$value.Id改为了$value.id,控制台显示的data数据没有问题。
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

【nodejs】大事件后台管理系统(四)——layui前端布局与改进

可是当点击修改弹窗的修改表单时,即到第二个接口updatacate,控制台打印的信息却是:
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

这就很令人困惑了,明明都通过接口测试了,控制台却说没把第一个接口的data.id值传给了第二个接口?也许真的没有传到,查看修改类别的this对象,可以看到控制台输出的data值没有id,而是Id。
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

这也正好说明了之前Id必须为Number的怪相。

后面在aricle/art_cate.html的form表单修改隐藏域的Id为id即可:
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

后面拿个alter也可以看到数据没问题了
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

6.4.3 文章发布的类别下拉框问题

方案一:改用input(垃圾的方案)
在文章发布那块,使用layui的select组件后,尽管能够方便下拉显示数据库中文章分类的内容,但是无论怎么填写都会提示这里是必填项,要么选择去掉select,要么改成input项,完全不清楚发生了什么bug?
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

方案二:改Id为id。
art_pub.html
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

6.4.4 文章列表不能显示分类的内容

原因:因为数据库本身的数据都没有分类名,只有分类id而已。
art_list.html
【nodejs】大事件后台管理系统(四)——layui前端布局与改进

6.5 改进页面

6.5.1 注册、重置密码页面添加密码强度

1) 重置密码页面

效果

【nodejs】大事件后台管理系统(四)——layui前端布局与改进

代码

拿来博客:注册密码/修改密码之密码强度判断
user/user_pwd.html

点击查看代码
<!DOCTYPE html> <html lang="en"> 	<head> 		<meta charset="UTF-8" /> 		<meta name="viewport" content="width=device-width, initial-scale=1.0" /> 		<title>Document</title> 		<link rel="stylesheet" href="/assets/lib/layui/css/layui.css" /> 		<link rel="stylesheet" href="/assets/css/user/user_pwd.css" /> 	</head> 	<body> 		<!-- 卡片区域 --> 		<div class="layui-card"> 			<div class="layui-card-header">修改密码</div> 			<div class="layui-card-body"> 				<form class="layui-form"> 					<div class="layui-form-item"> 						<label class="layui-form-label">原密码</label> 						<div class="layui-input-block"> 							<input 								type="password" 								name="oldPwd" 								required 								lay-verify="required|pwd" 								placeholder="请输入原密码" 								autocomplete="off" 								class="layui-input" 							/> 						</div> 					</div>  					<div class="layui-form-item"> 						<label class="layui-form-label" for="psd">新密码</label> 						<div class="layui-input-block"> 							<input 								onKeyUp="javascript:passwordChangeStatuss(this.value);" 								onBlur="javascript:passwordChangeStatuss(this.value);" 								type="password" 								name="newPwd" 								required 								lay-verify="required|pwd|samePwd" 								placeholder="请输入新密码" 								autocomplete="off" 								class="layui-input" 							/> 							<span class="psdInfo"></span> 						</div> 						<!-- <div class="strong"> 							<p class="fl"> 								<span class="hover">弱</span> 								<span class="">中</span> 								<span class="">强</span> 							</p> 						</div> --> 					</div> 					<div class="layui-form-item"> 						<label class="layui-form-label">密码强度</label> 						<div class="layui-btn-group pwd-item"> 							<label id="l" class="layui-btn layui-btn-primary" 								>低</label 							> 							<label id="m" class="layui-btn layui-btn-primary" 								>中</label 							> 							<label id="h" class="layui-btn layui-btn-primary" 								>高</label 							> 						</div> 					</div> 					<div class="layui-form-item"> 						<label class="layui-form-label">确认新密码</label> 						<div class="layui-input-block"> 							<input 								type="password" 								name="rePwd" 								required 								lay-verify="required|pwd|rePwd" 								placeholder="请再次确认密码" 								autocomplete="off" 								class="layui-input" 							/> 							<span class="psd1Info"></span> 						</div> 					</div> 					<div class="layui-form-item"> 						<div class="layui-input-block"> 							<button 								class="layui-btn" 								lay-submit 								lay-filter="formDemo" 							> 								修改密码 							</button> 							<button 								type="reset" 								class="layui-btn layui-btn-primary" 							> 								重置 							</button> 						</div> 					</div> 				</form> 			</div> 		</div>  		<!-- 导入 layui 的 js --> 		<script src="/assets/lib/layui/layui.all.js"></script> 		<!-- 导入 jQuery --> 		<script src="/assets/lib/jquery.js"></script> 		<!-- 导入 baseAPI --> 		<script src="/assets/js/baseAPI.js"></script> 		<!-- 导入自己的 js --> 		<script src="/assets/js/user/user_pwd.js"></script> 	</body> </html>  

user_pwd.js:

点击查看代码
$(function () { 	var form = layui.form  	form.verify({ 		pwd: [/^[S]{6,12}$/, '密码必须6到12位,且不能出现空格'], 		samePwd: function (value) { 			if (value === $('[name=oldPwd]').val()) { 				return '新旧密码不能相同!' 			} 		}, 		rePwd: function (value) { 			if (value !== $('[name=newPwd]').val()) { 				return '两次密码不一致!' 			} 		}, 	})  	$('.layui-form').on('submit', function (e) { 		e.preventDefault() 		$.ajax({ 			method: 'POST', 			url: '/my/updatepwd', 			data: $(this).serialize(), 			success: function (res) { 				if (res.status !== 0) { 					return layui.layer.msg('更新密码失败!') 				} 				layui.layer.msg('更新密码成功!') 				// 重置表单 				$('.layui-form')[0].reset() 			}, 		}) 	}) }) //密码强度判断 function passwordChangeStatuss(pwd) { 	if (pwd == '' || pwd == null) { 		$('.pwd-item label').attr('class', 'layui-btn layui-btn-primary') 	} else { 		S_level = checkStrong(pwd) 		switch (S_level) { 			case 0: 				$('.pwd-item label').attr( 					'class', 					'layui-btn layui-btn-primary' 				) 			case 1: 				$('#l').attr('class', 'layui-btn layui-btn-danger') 				$('#m').attr('class', 'layui-btn layui-btn-primary') 				$('#h').attr('class', 'layui-btn layui-btn-primary') 				break 			case 2: 				$('#l').attr('class', 'layui-btn layui-btn-danger') 				$('#m').attr('class', 'layui-btn layui-btn-warm') 				$('#h').attr('class', 'layui-btn layui-btn-primary') 				break 			default: 				$('#l').attr('class', 'layui-btn layui-btn-danger') 				$('#m').attr('class', 'layui-btn layui-btn-warm') 				$('#h').attr('class', 'layui-btn') 		} 	} } //判断输入密码的类型 function CharMode(iN) { 	if (iN >= 48 && iN <= 57) 		//数字 		return 1 	if (iN >= 65 && iN <= 90) 		//大写 		return 2 	if (iN >= 97 && iN <= 122) 		//小写 		return 4 	else return 8 } //bitTotal函数 //计算密码模式 function bitTotal(num) { 	modes = 0 	for (i = 0; i < 4; i++) { 		if (num & 1) modes++ 		num >>>= 1 	} 	return modes } //返回强度级别 function checkStrong(sPW) { 	if (sPW.length <= 8) return 0 //密码太短 	Modes = 0 	for (i = 0; i < sPW.length; i++) { 		//密码模式 		Modes |= CharMode(sPW.charCodeAt(i)) 	} 	return bitTotal(Modes) }  

2) 注册页面

效果

【nodejs】大事件后台管理系统(四)——layui前端布局与改进

代码

assets/login.css

点击查看代码
html, body {   margin: 0;   padding: 0;   height: 100%;   width: 100%;   background: url('/assets/images/login_bg.jpg') no-repeat center;   background-size: cover; }  .loginAndRegBox {   width: 400px;   height: 350px;   background-color: #fff;   position: absolute;   left: 50%;   top: 50%;   transform: translate(-50%, -50%); }  .title-box {   height: 60px;   background: url('/assets/images/login_title.png') no-repeat center; }  .reg-box {   display: none; }  .layui-form {   padding: 0 30px; }  .links {   display: flex;   justify-content: flex-end; }  .links a {   font-size: 12px; }  .layui-form-item {   position: relative; }  .layui-icon {   position: absolute;   left: 10px;   top: 10px; }  .layui-input {   padding-left: 32px; }  .warn{     display: inline-block;     width:22px;     height:22px;     background: url("../images/paywarn.png");     background-repeat: no-repeat;     background-size:22px 22px;     vertical-align: top; } 

login.html

点击查看代码
<!DOCTYPE html> <html lang="en"> 	<head> 		<meta charset="UTF-8" /> 		<meta name="viewport" content="width=device-width, initial-scale=1.0" /> 		<title>LinFeng后台-登录/注册</title> 		<!-- 导入 LayUI 的样式 --> 		<link rel="stylesheet" href="/assets/lib/layui/css/layui.css" /> 		<!-- 导入自己的样式表 --> 		<link rel="stylesheet" href="/assets/css/login.css" /> 	</head> 	<body> 		<!-- 头部的 Logo 区域 --> 		<div class="layui-main"> 			<img src="/assets/images/logo.png" alt="【nodejs】大事件后台管理系统(四)——layui前端布局与改进" alt="" /> 		</div>  		<!-- 登录注册区域 --> 		<div class="loginAndRegBox"> 			<div class="title-box"></div> 			<!-- 登录的div --> 			<div class="login-box"> 				<!-- 登录的表单 --> 				<form class="layui-form" id="form_login"> 					<!-- 用户名 --> 					<div class="layui-form-item"> 						<i class="layui-icon layui-icon-username"></i> 						<input 							type="text" 							name="username" 							required 							lay-verify="required" 							placeholder="请输入用户名" 							autocomplete="off" 							class="layui-input" 						/> 					</div> 					<!-- 密码 --> 					<div class="layui-form-item"> 						<i class="layui-icon layui-icon-password"></i> 						<input 							type="password" 							name="password" 							required 							lay-verify="required|pwd" 							placeholder="请输入密码" 							autocomplete="off" 							class="layui-input" 						/> 					</div> 					<!-- 登录按钮 --> 					<div class="layui-form-item"> 						<!-- 注意:表单提交按钮和普通按钮的区别,就是 lay-submit 属性 --> 						<button 							class="layui-btn layui-btn-fluid layui-btn-normal" 							lay-submit 						> 							登录 						</button> 					</div> 					<div class="layui-form-item links"> 						<a href="javascript:;" id="link_reg">去注册账号</a> 					</div> 				</form> 			</div> 			<!-- 注册的div --> 			<div class="reg-box"> 				<!-- 注册的表单 --> 				<form class="layui-form" id="form_reg"> 					<!-- 用户名 --> 					<div class="layui-form-item"> 						<i class="layui-icon layui-icon-username"></i> 						<input 							type="text" 							name="username" 							required 							lay-verify="required" 							placeholder="请输入用户名" 							autocomplete="off" 							class="layui-input" 						/> 					</div> 					<!-- 密码 --> 					<div class="layui-form-item"> 						<i class="layui-icon layui-icon-password"></i> 						<input 							onKeyUp="javascript:passwordChangeStatuss(this.value);" 							onBlur="javascript:passwordChangeStatuss(this.value);" 							type="password" 							name="password" 							required 							lay-verify="required|pwd" 							placeholder="请输入密码" 							autocomplete="off" 							class="layui-input" 						/> 					</div> 					<div class="layui-form-item"> 						<label class="layui-form-label" 							><i class="warn"></i>密码强度</label 						> 						<div class="layui-btn-group pwd-item"> 							<label id="l" class="layui-btn layui-btn-primary" 								>低</label 							> 							<label id="m" class="layui-btn layui-btn-primary" 								>中</label 							> 							<label id="h" class="layui-btn layui-btn-primary" 								>高</label 							> 						</div> 					</div> 					<!-- 密码确认框 --> 					<div class="layui-form-item"> 						<i class="layui-icon layui-icon-password"></i> 						<input 							type="password" 							name="repassword" 							required 							lay-verify="required|pwd|repwd" 							placeholder="再次确认密码" 							autocomplete="off" 							class="layui-input" 						/> 					</div> 					<!-- 注册按钮 --> 					<div class="layui-form-item"> 						<!-- 注意:表单提交按钮和普通按钮的区别,就是 lay-submit 属性 --> 						<button 							class="layui-btn layui-btn-fluid layui-btn-normal" 							lay-submit 						> 							注册 						</button> 					</div> 					<div class="layui-form-item links"> 						<a href="javascript:;" id="link_login">去登录</a> 					</div> 				</form> 			</div> 		</div>  		<!-- 导入 Layui 的JS文件 --> 		<script src="/assets/lib/layui/layui.all.js"></script> 		<!-- 导入 JQuery --> 		<script src="/assets/lib/jquery.js"></script> 		<!-- 导入自己封装的 baseAPI.js --> 		<script src="/assets/js/baseAPI.js"></script> 		<!-- 导入自己的 JavaScript 脚本 --> 		<script src="/assets/js/login.js"></script> 	</body> </html>  

assets/js/login.js:

点击查看代码
$(function () { 	// 点击“去注册账号”的链接 	$('#link_reg').on('click', function () { 		$('.login-box').hide() 		$('.reg-box').show() 	})  	// 点击“去登录”的链接 	$('#link_login').on('click', function () { 		$('.login-box').show() 		$('.reg-box').hide() 	})  	// 从 layui 中获取 form 对象 	var form = layui.form 	var layer = layui.layer 	// 通过 form.verify() 函数自定义校验规则 	form.verify({ 		// 自定义了一个叫做 pwd 校验规则 		pwd: [/^[S]{6,12}$/, '密码必须6到12位,且不能出现空格'], 		// 校验两次密码是否一致的规则 		repwd: function (value) { 			// 通过形参拿到的是确认密码框中的内容 			// 还需要拿到密码框中的内容 			// 然后进行一次等于的判断 			// 如果判断失败,则return一个提示消息即可 			var pwd = $('.reg-box [name=password]').val() 			if (pwd !== value) { 				return '两次密码不一致!' 			} 		}, 	})  	// 监听注册表单的提交事件 	$('#form_reg').on('submit', function (e) { 		// 1. 阻止默认的提交行为 		e.preventDefault() 		// 2. 发起Ajax的POST请求 		var data = { 			username: $('#form_reg [name=username]').val(), 			password: $('#form_reg [name=password]').val(), 		} 		$.post('/api/register', data, function (res) { 			if (res.status !== 0) { 				return layer.msg(res.message) 			} 			layer.msg('注册成功,请登录!') 			// 模拟人的点击行为 			$('#link_login').click() 		}) 	})  	// 监听登录表单的提交事件 	$('#form_login').submit(function (e) { 		// 阻止默认提交行为 		e.preventDefault() 		$.ajax({ 			url: '/api/login', 			method: 'POST', 			// 快速获取表单中的数据 			data: $(this).serialize(), 			success: function (res) { 				if (res.status !== 0) { 					return layer.msg('登录失败!') 				} 				layer.msg('登录成功!') 				// 将登录成功得到的 token 字符串,保存到 localStorage 中 				localStorage.setItem('token', res.token) 				// 跳转到后台主页 				location.href = '/index.html' 			}, 		}) 	}) })  //密码强度判断 function passwordChangeStatuss(pwd) { 	if (pwd == '' || pwd == null) { 		$('.pwd-item label').attr('class', 'layui-btn layui-btn-primary') 	} else { 		S_level = checkStrong(pwd) 		switch (S_level) { 			case 0: 				$('.pwd-item label').attr( 					'class', 					'layui-btn layui-btn-primary' 				) 			case 1: 				$('#l').attr('class', 'layui-btn layui-btn-danger') 				$('#m').attr('class', 'layui-btn layui-btn-primary') 				$('#h').attr('class', 'layui-btn layui-btn-primary') 				break 			case 2: 				$('#l').attr('class', 'layui-btn layui-btn-danger') 				$('#m').attr('class', 'layui-btn layui-btn-warm') 				$('#h').attr('class', 'layui-btn layui-btn-primary') 				break 			default: 				$('#l').attr('class', 'layui-btn layui-btn-danger') 				$('#m').attr('class', 'layui-btn layui-btn-warm') 				$('#h').attr('class', 'layui-btn') 		} 	} } //判断输入密码的类型 function CharMode(iN) { 	if (iN >= 48 && iN <= 57) 		//数字 		return 1 	if (iN >= 65 && iN <= 90) 		//大写 		return 2 	if (iN >= 97 && iN <= 122) 		//小写 		return 4 	else return 8 } //bitTotal函数 //计算密码模式 function bitTotal(num) { 	modes = 0 	for (i = 0; i < 4; i++) { 		if (num & 1) modes++ 		num >>>= 1 	} 	return modes } //返回强度级别 function checkStrong(sPW) { 	if (sPW.length <= 8) return 0 //密码太短 	Modes = 0 	for (i = 0; i < sPW.length; i++) { 		//密码模式 		Modes |= CharMode(sPW.charCodeAt(i)) 	} 	return bitTotal(Modes) }