请关注我的小站:http://oideas.herokuapp.com/
不好意思,说明一下,本来的话今天应该能够把前两天段更的blog写完,但是,恩,周五的下班之前,老大直接给我来一句“你还是装linux系统吧”,我,好吧,昨晚搞了一晚上,结果无线总是连不上,今天出去买了跟线,插上,装好各种环境,不知不觉已经到现在了,我去,想着blog还没跟,赶紧的。。。不多说了,总之就是告诉大家,我在用linux,而且还是个菜鸟,无言以对了。。。。
1.各功能实现说明
最新,毋庸置疑,应该就是我们的网站首页,那么,上一章已经实现的差不多了,下面打开views下的headere.ejs文件,将:
<li><a href="#" title="8小时内最新">最新</a></li>
修改为:
<li><a href="/" title="8小时内最新">最新</a></li>
ok这个功能暂时这样。
精华,这个功能应该是显示评论最多,赞最多,并且最新的,所以这个跟【最新】这个共能是差不多的,只不过是排序不一样
投稿,已经实现。
关于,属于扯淡的东西,自己想。
博客,可以链接到你自己的博客,或者实现它,项目最后,如果我还有精力,会带着大家实现。
搜索,这个其实就是最新或精华的另一种显示而已。
然后就是今天的登录和注册了。
2.布局登录界面和注册界面
为什么我对界面看如此重要,就好比人的脸一样,有些人让你看一样之后就想吐,而有些人让你看了还想看,这就是我想说的。
本来是想做成弹出窗口的形式,但是浏览了不下于30多个国外的网站,都没找到我想要的,国内几个比较知名的我是知道的,都没有看,无奈之下拿个以前做的修修,真不是想敷衍大家,而是自己想要的样子很模糊,自己做出来又要浪费很长时间,所以直接开始把。
登录界面:
上一章加了投稿功能,但是是是用户未登录模式的,我们肯定也是需要用户登录的,好,打开style.css文件,追加css:
.form-login {
background: #fff;
right: 0px;
margin: 0px auto;
margin-top:40px;
width: 400px;
}
.header {
background: #e84c3d;
text-align:center;
font-size:18px;
padding:20px 25px;
color:#4d4d4d;
}
.inputs {
margin-top:10px;
color:#4d4d4d;
}
.inputs input[type="text"], .inputs [type="password"], .inputs [type="email"] {
width:340px;
height:45px;
background:url(../images/bgnoise_lg.png) repeat left top;
color:#4d4d4d;
font-size:16px;
margin-top:15px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
border:0;
margin-left:20px;
padding:0px 10px;
}
.inputs input[type="text"]:hover, .inputs input[type="text"]:focus,.inputs [type="password"]:hover, .inputs [type="password"]:focus,.inputs [type="email"] :hover,.inputs [type="email"] :focus{
outline:none;
}
.link-2 {
float:right;
margin-top:15px;
margin-right:20px;
}
.link-2 a, .link-2 a:hover {
color:#4d4d4d;
}
.link-2 a:hover {
text-decoration:none;
}
.button-login input[type="submit"] {
width:360px;
height:55px;
margin-left:20px;
margin-top:25px;
margin-bottom:40px;
font-size:18px;
font-weight:bold;
text-transform:uppercase;
outline: none;
position: relative;
cursor: pointer;
border-radius: 5px;
color: #fff;
border:0;
background: #e84c3d;
}
.button-login input[type="submit"]:hover { opacity:0.9; }
.button-login input[type="submit"]:active {
top: 3px;
background: #e84c3d;
box-shadow: inset 0 1px 2px #ba3c30;
}
在views 下新建ologin.ejs和oregist.ejs, 其中ologin.ejs如下:
<%- include header%>
<form action="/dologin" class="form-login" method="post" id="login_form">
<div class="header">
OMinds-登录
</div>
<div class="inputs">
<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>
<input id="email" name="email" type="text" required="" placeholder="邮箱">
<input id="passw" name="passw" type="password" required="" placeholder="密码">
<div class="link-2">
<a href="/forget">忘记密码?</a>
</div>
<div class="clear">
</div>
<div class="button-login">
<input type="button" value="登 录" id="login_btn">
</div>
</div>
</form>
<%- include footer%>
oregist.ejs内容:
<%- include header%>
<form action="/doregist" class="form-login" method="post" id="regist_form">
<div class="header">
OMinds-注册
</div>
<div class="inputs">
<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>
<input id="reg_nickname" name="reg_nickname" type="text" required="" placeholder="昵称">
<input id="reg_email" name="reg_email" type="text" required="" placeholder="邮箱">
<input id="reg_passw" name="reg_passw" type="password" required="" placeholder="密码">
<input id="reg_repassw" name="reg_repassw" type="password" required="" placeholder="密码确认">
<div class="link-2">
<a href="/login">已有帐号?</a>
</div>
<div class="clear">
</div>
<div class="button-login">
<input type="button" value="注 册" id="regist_btn">
</div>
</div>
</form>
<%- include footer%>
内容没有多大区别,就是regist中比login多了几个框而已。
ok,修改header.ejs文件,将:
<li><a href="#" >登录</a></li>
<li><a href="#">注册</a></li>
<li><a href="/login" >LOG</a></li>
<li><a href="/regist">REG</a></li>
我装b了,你可以不用把登录和注册换成英文,我是自己玩的happy了~~~
接下来在routes/index.js中,添加:
app.get('/login', function (req, res) {
res.render('ologin', {
title : 'OMinds - 登录' });
});
app.get('/regist', function (req, res) {
res.render('oregist', {
title : 'OMinds - 注册' });
});
好了,打开浏览其看一下效果把,登录效果:
注册效果:
好,我们先来实现注册的代码,首先注册的表单,一般要做个验证,或者你也可以把它交给后台验证,当然了,一般这种简单的验证还是放在前端的,好了,我们需要使用jquery,到官网下载
http://jquery.com/download/ 下载相关的版本,我的是1.7(下载的时候,有时候发现浏览器把js的内容打开了,不要紧,比可以复制下来保存,或者点击链接的时候选择连接另存为),
ok,把它放到,js文件夹下,在header.ejs中加入<script language="javascript" type="text/javascript" src="/js/jquery-1.7.1.min.js"></script>
同时在js文件夹下新建common.js 内容如下:
$(document).ready(function(){
var flag = false;
$("#searckBtn").click(function(){
if(!flag){
$("#headbar").append("<li id=searchinput><from action=# ><input type=tex name=searchkey class=searck_input></form></li>");
}else{
$("#searchinput").remove();
}
flag = !flag;
});
$("#login_btn").click(function(){
var email = $("#email").val();
var passw = $("#passw").val();
if(email==null||email.trim()==''||passw==null||passw.trim()==''){
$("#error").text('邮箱或密码不能为空!');
return;
}else if(passw!=null&&(passw.length<6||passw.length>40)){
$("#error").text('您输入的密码不符合要求,密码长度为6-40!');
return;
}
$("#login_form").submit();
});
$("#regist_btn").click(function(){
var nickname = $("#reg_nickname").val();
var email = $("#reg_email").val();
var passw = $("#reg_passw").val();
var repassw = $("#reg_repassw").val();
if(nickname==null||nickname.trim()==''){
$("#error").text('昵称不能为空!');
return;
}else if(email==null||email.trim()==''){
$("#error").text('邮箱不能为空!');
return;
}else if(passw==null||passw.trim()==''){
$("#error").text('密码不能为空!');
return;
}else if(repassw==null||repassw.trim()==''){
$("#error").text('请确认密码!');
return;
}else if(passw!=null&&(passw.length<6||passw.length>40)){
$("#error").text('您输入的密码不符合要求,密码长度为6-40!');
return;
}
$("#regist_form").submit();
});
});
在header.ejs中加入<script language="javascript" type="text/javascript" src="/js/common.js"></script>
common.js中主要是监控登录和注册按钮的方法,细心的同学可能已经注意到还有一个searchbar的click方法,这个后面会说到。
前端的验证js中,输出错误怎么办呢?我也没法看到啊,对,那么需要我们再在ologin.ejs和oregist.ejs中添加一个标签,他们看起来应该是这样子的:
<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>
放在哪里呢?当然是:
<div class="inputs">
代码之后了,以ologin.ejs为例,看最终代码:
<%- include header%>
<form action="/dologin" class="form-login" method="post" id="login_form">
<div class="header">
OMinds-登录
</div>
<div class="inputs">
<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>
<input id="email" name="email" type="text" required="" placeholder="邮箱">
<input id="passw" name="passw" type="password" required="" placeholder="密码">
<div class="link-2">
<a href="/forgot-password">忘记密码?</a>
</div>
<div class="clear">
</div>
<div class="button-login">
<input type="button" value="登 录" id="login_btn">
</div>
</div>
</form>
<%- include footer%>
好,前端已经ok了,现在是后台,那么,我们要先建立user的表。在models文件夹下,新建user.js,内容:
var mongodb = require('./db');
var ObjectID = require('mongodb').ObjectID;
function User(user) {
this.email = user.email;
this.password = user.password;
this.nickname = user.nickname;
this.photo = user.photo;
this.cdate = user.cdate;
this._id = user._id;
};
module.exports = User;
// C(增)
User.prototype.save = function(callback) {
var date = new Date();
var time = date.getFullYear()+ "-"+ (date.getMonth() + 1)+ "-"+ date.getDate()+ " "+ date.getHours()+ ":"+ (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())+ ":"+ (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
var user = {
email : this.email,
password : this.password,
nickname : this.nickname,
photo : this.photo,
cdate : time
};
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
db.collection('users', function(err, collection) {
if (err) {
db.close();
return callback(err);
}
collection.insert(user, {
safe : true
}, function(err, user) {
db.close();
if (err) {
return callback(err);
}
callback(null, user[0]);
});
});
});
};
// R(查)
User.get = function(email, callback) {
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
db.collection('users', function(err, collection) {
if (err) {
db.close();
return callback(err);
}
collection.findOne({
email : email
}, function(err, user) {
db.close();
if (err) {
return callback(err);
}
callback(null, user);
});
});
});
};
// R(查,通过ID)
User.getById = function(id, callback) {
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
db.collection('users', function(err, collection) {
if (err) {
db.close();
return callback(err);
}
collection.findOne({
_id : new ObjectID(id)
}, function(err, user) {
if (err) {
return callback(err);
}
callback(null, user);
});
});
});
};
// U (改)
User.update = function(user, callback) {
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
db.collection('users', function(err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
collection.update({
"email" : user.email}, {
$set : {
nickname : user.nickname,
password : user.password,
photo : user.photo
}
}, function(err) {
mongodb.close();
if (err) {
return callback(err);
}
callback(null);
});
});
});
};
没错,只有三类方法,为什么没有删除呢?为了增加用户,我们为什么还要删除方法?
好,下面开始做逻辑处理了,代开routes下的index.js 添加注册的方法:
app.post('/doregist',function (req, res){
var email = req.body.reg_email;
var nickname = req.body.reg_nickname;
var md5 = crypto.createHash('md5'), password = md5.update(req.body.reg_passw).digest('hex');
var mde = crypto.createHash('md5'), email_MD5 = mde.update(email.toLowerCase()).digest('hex');
var newUser = new User({
email : email,
nickname : nickname,
password : password,
photo : "http://www.gravatar.com/avatar/" + email_MD5 + "?s=48"
});
User.get(newUser.email, function(err, user) {
if (user) {
req.flash('error', '该邮箱已注册,请登录或找回密码。');
req.flash('email', email);
req.flash('nickname', nickname);
req.flash('password', password);
req.flash('repassword', repassword);
return res.redirect('/regist');
}
// 如果不存在则新增用户
newUser.save(function(err, user) {
if (err) {
req.flash('error', err);
req.flash('email', email);
req.flash('nickname', nickname);
req.flash('password', password);
req.flash('repassword', repassword);
return res.redirect('/regist');
}
req.session.user = user;
res.redirect('/');
});
});
});
其中密码做了md5加密,这没什么好说的(不可逆,别想着解密),头像功能,如果我说我想自己做一个有人觉得我能成功吗?恩,暂时用的是gravatar这个东西,s=48表示取得48*48大小的图片。注册成功了吗?恩,理论上是成功了,但是我们看不到结果,虽然已经将user写进session中了,但是我们却没有用,好,打开header.ejs文件将:
<ul style="margin-left:50px;float:right;">
<li><a href="/login" >LOG</a></li>
<li><a href="/regist">REG</a></li>
</ul>
改为:
<ul style="margin-left:50px;float:right;">
<%if(user) {%>
<a href="#" class="user_icon" style="clear:both;padding: 0;"><img src="<%=user.photo%>" title="<%=user.nickname%>"></a>
<%}else{%>
<li><a href="/login" >LOG</a></li>
<li><a href="/regist">REG</a></li>
<%}%>
</ul>
看起来是没问题了,但是用浏览器刷一下会发现找不到user,那是因为,我们在app.get('/')这个方法中没有传入啊,好把,在routes/index.js文件中的所有res.render中都加入代码:
user : req.session.user
最后index.js应该是这样的:
var crypto = require('crypto');
var Mind = require('../models/mind.js');
var User = require('../models/user.js');
//trim方法
function trimStr(str){
if(str){
return str.replace(/(^\s*)|(\s*$)/g,"");
}
}
module.exports = function(app) {
app.get('/', function (req, res) {
Mind.getAll(function(err, minds) {
if(err){
minds = [];
}
res.render('index', {
title : 'OMinds - 最新',
user : req.session.user,
minds : minds });
});
});
app.get('/login', function (req, res) {
var use = req.session.user;
if(use){
return res.redirect('/');
}
res.render('ologin', {
title : 'OMinds - 登录' ,
user : req.session.user,
error : req.flash('error').toString()});
});
app.get('/regist', function (req, res) {
res.render('oregist', {
title : 'OMinds - 注册',
user : req.session.user,
error : req.flash('error').toString()});
});
app.get('/logout', function (req, res) {
delete req.session.user;
return res.redirect('/');
});
app.get('/upminds', function (req, res) {
res.render('upminds', { title: 'OMinds - 投稿' ,
user : req.session.user,
error : req.flash('error').toString(),
ocontent:req.flash('ocontent').toString()
});
});
app.post('/doregist',function (req, res){
var email = req.body.reg_email;
var nickname = req.body.reg_nickname;
var md5 = crypto.createHash('md5'), password = md5.update(req.body.reg_passw).digest('hex');
var mde = crypto.createHash('md5'), email_MD5 = mde.update(email.toLowerCase()).digest('hex');
var newUser = new User({
email : email,
nickname : nickname,
password : password,
photo : "http://www.gravatar.com/avatar/" + email_MD5 + "?s=48"
});
User.get(newUser.email, function(err, user) {
if (user) {
req.flash('error', '该邮箱已注册,请登录或找回密码。');
req.flash('email', email);
req.flash('nickname', nickname);
req.flash('password', password);
req.flash('repassword', repassword);
return res.redirect('/regist');
}
// 如果不存在则新增用户
newUser.save(function(err, user) {
if (err) {
req.flash('error', err);
req.flash('email', email);
req.flash('nickname', nickname);
req.flash('password', password);
req.flash('repassword', repassword);
return res.redirect('/regist');
}
req.session.user = user;
res.redirect('/');
});
});
});
app.post('/dologin', function(req, res) {
var email = req.body.email;
var md5 = crypto.createHash('md5');
var password = md5.update(req.body.passw).digest('hex');
User.get(email, function(err, user) {
req.flash('email', email);
console.log(user);
if (!user) {
req.flash('error', '邮箱或密码错误!');
return res.redirect('/login');// 用户不存在则跳转到登录页
}
// 检查密码是否一致
if (user.password != password) {
req.flash('error', '邮箱或密码错误!');
return res.redirect('/login');// 密码错误则跳转到登录页
}
// 用户名密码都匹配后,将用户信息存入 session
req.session.user = user;
res.redirect('/');// 登陆成功后跳转到主页
});
});
app.post('/putup',function (req, res) {
var user = req.session.user;
var cont = trimStr(req.body.mind_text);
if(cont==null||cont.length<40||cont.length>700){
req.flash('error', "您的投稿不符合条件,请修改后提交。");
req.flash('ocontent', cont);
return res.redirect('/upminds');
}
var mind;
var flag = true;
//no login
if (!user) {
mind = new Mind({
content : cont,
user : null,
flag : flag
});
mind.save(function(err, mind) {
if (err) {
req.flash('error', err);
return res.redirect('/upminds');
}
res.redirect('/');
});
}
// login
else {
//暂时不做处理
}
});
};
其中app.post('/dologin')为我们的登录方法,app.get('/logout')是退出方法。
以上我们已经实现了登录和注册,让我们看看效果:
看到右上角的头像了吗?对,我们没有退出按钮,为什么需要呢?其实在我写完app.get('/logout')方法的时候,突然想到不应个给退出,当然你可一自己手动退出,通过 /lougout去访问。
最后,前面提到的searchbar的click方法,既然js是显示的效果,那么,其他也没多少东西,打开header.ejs。将搜索的链接代码变为:
<li><a href="javascript:void(0);" id="searckBtn">搜索</a></li>
在style.css中加入:
.searck_input{
padding: 7px 9px;
border-radius: 0 100px 100px 0;
}
input.searck_input:focus{
outline:none;
}
ok,效果:
看到红色画线框中的地方了吗?对 那就是我们做的效果。
以上,本章的登录和注册。。
ideas-ominds交流群:
158325682,有想要一起做的,或者有什么不懂的都可以找我哦。