文件位置:1.Node.js零基础入门教程\node.js—资料\day8\素材\大事件项目
在assets/js/baseAPI.js中修改统一请求根路径
纯粹是因为之前本人手贱,故意修改名称与端口所致的。

在assets/js/login.js中修改注册的post接口

先在VSCode的扩展中加上express插件先

接着启动之前的api_server后端项目
nodemon app.js
然后再回到前端项目,按住ctrl+shift+p调出Express: Host Current Workspace and Open in Browser

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

打开assets/js/article/art_cate.js,找到删除文章类别的异步处理函数,通过console.log控制台打印命令发现,之所以不能删除是因为没有返回status,没返回它则是因为找不到id,因为它返回为空。

而造成这个问题的原因则是因为前端找不到这个属性名ID,但我们数据库写的是id。
aricle/art_cate.html

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

更改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-edit和form-edit经过的接口有两个,第一个是根据id获取文章分类,绑定点击事件click的异步操作,看到之前把$value.Id改为了$value.id,控制台显示的data数据没有问题。


可是当点击修改弹窗的修改表单时,即到第二个接口updatacate,控制台打印的信息却是:

这就很令人困惑了,明明都通过接口测试了,控制台却说没把第一个接口的data.id值传给了第二个接口?也许真的没有传到,查看修改类别的this对象,可以看到控制台输出的data值没有id,而是Id。

这也正好说明了之前Id必须为Number的怪相。
后面在aricle/art_cate.html的form表单修改隐藏域的Id为id即可:

后面拿个alter也可以看到数据没问题了

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

方案二:改Id为id。
在art_pub.html。

art_list.html

router_handler/article.js
//文章列表显示处理函数
exports.getArticle = (req, res) => {
// const sql = 'select * from ev_articles where is_delete=0 order by id asc'
const sql = `select aleft.Id as 'Id',
aleft.title as 'title',
aleft.content as 'content',
aleft.pub_date as 'pub_date',
aleft.state as 'state',
aleft.is_delete as 'is_delete',
aright.name as 'cate_name'
from ev_articles as aleft left join ev_article_cate as aright on aleft.cate_id=aright.id
where aleft.is_delete=0 order by aleft.Id asc`
db.query(sql, (err, results) => {
if (err) return res.cc(err)
res.send({
status: 0,
message: '获取文章列表成功!',
data: results,
})
})
}


拿来博客:注册密码/修改密码之密码强度判断
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)
}

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="" />
</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)
}

基本上就是直接拿别人写好的随便改
参考博客:项目中遇到的bug、问题总结
拿了别人的代码没认真看,出现了问题,挺尴尬的。
app.js添加session包(这个不用添加,这是个天坑,不用 VUE 你会很痛苦)
//为了验证码能通过,则需要导入session组件
const session = require('express-session')
app.use(
session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
})
)
参考博客:
下面这个是用session的,在后端判断是没有问题,但是如果搞到前端就要面临不同接口的不同session问题,网上有大量关于Vue的处理,但是没有layui的,我也找不到,所以一定要慎重考虑:
案例分享--NodeJs制作随机验证码
下面的这个则是用通过id选择器通过点击事件替换,只用考虑前端而不用管后端怎么样,非常方便。
使用node生成验证码图片,并进行验证
router/user.js:定义获取校验码与验证码验证路由
// 定义获取验证码路由
router.get('/getCaptcha', userHandler.getCaptcha)
//定义验证码验证路由
//router.get('/verifyCaptcha', userHandler.verifyCaptcha)
router_handler/user.js:实现获取校验码与验证码验证的处理函数
const captcha = require('svg-captcha') //1.引入的模块
//获取验证码处理函数
exports.getCaptcha = (req, res) => {
const cap = captcha.create({
size: 4, //长度
ignoreChars: '0o1il', //排除字符
noise: 3, //干扰线条数
width: 120, // 宽度
height: 36, // 高度
color: true, // 验证码字符是否有颜色,默认是没有,如果设置了背景颜色,那么默认就是有字符颜色
background: '#fff', // 背景色 可以自己改
})
// req.session.captcha = cap.text
// console.log(req.session)
// res.type('svg') //响应类型
res.send(cap)
}

如果要搞session后台判断的话,则需要弄个验证码验证接口(但是我搞不成)。
login.html
<!-- 验证码区域 -->
<div class="layui-inline input-group">
<div class="layui-input-inline" style="width: 135px">
<input
type="text"
class="layui-input"
placeholder="输入验证码"
id="codeInput"
/>
</div>
<!-- 该方案弃用 -->
<!-- <img
src=""
alt="点击获取验证码"
current_port="http://127.0.0.1:8080"
id="codeImg"
/> -->
<span id="codeImg">点击获取验证码</span>
</div>
assets/js/login.js:
先判断完验证码,再接上登录的ajax操作
$(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()
})
})
let validation = ''
//点击更换验证码
$('#codeImg').on('click', function () {
/*在请求获得验证码那块:(该方案弃用,狗都不用,还是Vue方便)
src在启动layui模板后,它认为的端口号是80端口,但是后端开的是8080,如果两个改成一样的,
就会端口占用,所以就需要在baseAPI.js设置ajax能跨域的端口,
因此需要通过attr修改成我们最终的请求接口,再通过prob设置验证码点击更换。
*/
// var cp = $(this).attr('current_port')
// $(this).prop('src', cp + '/api/getCaptcha?=t' + Date.now())
$.get('/api/getCaptcha', (res) => {
// console.log(res)
validation = res.text
codeImg.innerHTML = res.data
})
})
//验证验证码,这个后端相应的接口应该要写入到login里面去
$('#codeInput').on('blur', function () {
if (
$(this).val().length == 4 &&
$(this).val().toLowerCase() == validation.toLowerCase()
) {
// layer.msg('验证码正确')
// 监听登录表单的提交事件
$('#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'
},
})
})
} else {
layer.msg('验证码输入错误')
}
})
})
//密码强度判断
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)
}
1、重置密码、注册页面:密码强度显示(完成)
2、登录页面有校验码,虽然有点丑(完成)
当然不是什么程序员之间的革命情谊啦,何况黑马程序员也没给我钱。
主观原因: 想整属于我自己的个人项目,我希望可以在前端这块有我的痕迹,所以我选择魔改这个项目,没想到吧,
以后如果要告我侵权,请黑马程序员手下留情,当然我也不太可能商用的,我也不会选择贩卖它,
如果未来有一天我这个项目受欢迎,然后又像套娃一样,被人魔改然后贩卖。
请提醒我,让我们伟大的开源精神、名气与汗水卷死他们。
客观原因:被老师质疑我的能力,在综合实训那天被骂得狗血淋头
我的指导老师谈大事件本身就是个铭感词(也怪我选词想都没想就拿这个项目进行综合实训的答辩),
并且也谈到这个项目是不完善的,没有网站基本改有的功能,并且还问到我这个项目的研究目的是什么?
我当时非常的摆烂,直接说是整着来玩的,结果把老师气得。
他们直接把这个项目能找的缺点、我个人操作的问题能说的都说了。
我全程低头红豆泥私密马赛,你说的对,我改。。。,
其实挺好笑的,大三实习要写论文,队伍对我组长的任务分配也是基本不愿执行,非得等到最后答辩几天才肯帮忙,
结果还怪我最后对他们不理不问,挺搞笑的,简直是把我当保姆。
其余答辩的队伍,则是都选择了曾经华为的比赛项目——本质就是数据报表高级版。
图弄得花里胡哨,把我给秀到了,看到我这个大反面教材,老师也是都看不下去了。
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).
我是ruby的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp
我想用这两种语言中的任何一种(最好是ruby)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生
这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什
例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果
我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源
我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几