作业要求个人完成一个电子商城的基本功能。使用NodeJS和mongoDB实现。
1、登录注册
我把登录注册的重心放在了正则约束、上传头像和“记住我”功能上。
正则约束在前天写过,有待补充。
上传头像的 ajax 的传值方式和其他的传值不同,所以单独提出来。
上传头像的 ajax 请求:
var formData = new FormData();
formData.append("test", $("#upImg")[0].files[0]);
console.log(formData);
$.ajax({
type: "POST",
url: "http://192.168.1.2:5000/uploadImg",
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(res) {
if(res.err == 0) {
console.log(res.doc)
$("#profile").attr("src", "http://192.168.1.2:5000/" + res.doc);
$("#profile").css("width", "300px");
$("#profile").css("height", "300px")
alert(res.msg);
imgSrc = "http://192.168.1.2:5000/" + res.doc;
}
},
error: function(res) {}
});
上传头像的后端接收处理:
//静态目录
app.use("/static", express.static(path.join(__dirname, "../static")));
//上传头像
app.post("/uploadImg", multer({
dest: "/tmp/"
}).single("test"), (req, res) => {
//为图片定义一个“时间+随机数”的名字
let filename = new Date().getTime() + parseInt(Math.random() * 10000) + "." + req.file.mimetype.split("/")[1];
//目标文件目录的转移,文件转移到静态目录下
fs.readFile(req.file.path, (err, data) => {
fs.writeFile(path.join(__dirname, "../static/profile", filename), data, (err) => {
if(err) {
return res.send({
err: -1
});
}
imgSchema.insertMany({
i_Src: "static/profile/" + filename,
i_Type: 1
}, (err, result) => {
if(err) {
return res.send({
err: -2,
msg: "上传失败"
});
}
if(result.length == 1) {
console.log(result)
res.send({
err: 0,
msg: "上传成功",
doc: result[0].i_Src
})
}
})
})
})
})
注册的 ajax 请求:
$.ajax({
type: "POST",
url: "http://192.168.1.2:5000/user/register",
data: {
u_nickname: $("#account").val(), //昵称
u_password: $("#password").val(), //密码
u_gender: $("input[name='gender']:checked").val(), //性别
u_profile: imgSrc, //头像
u_phone: $("#phone").val(), //联系方式
u_address: $("#address").val() //地址
},
success: function(res) {
alert(res.msg);
window.location.href = "login.html"; //注册成功直接跳至登录界面
},
error: function(res) {
console.log(res.msg);
}
});
接下来是“记住我”,“记住我”是指保存登录状态,我将用户名和密码保存在 localStorage 下,cookie 也可以实现,而且 cookie 可以设置过期时间。两种方案各有利弊,且真正的项目中,为保证账号安全也会有更多考虑的处理。
localStorage 方法的封装:
var storage = {
obj: window.localStorage ? window.localStorage : null,
set: function(key, value) { //setItem()
if(typeof(value) == "object") {
value = JSON.stringify(value); //对象类型转为字符串
}
return this.obj.setItem(key, value);
},
get: function(key) { //getItem()
var result = this.obj.getItem(key);
try {
//JSON.parse(result)
result = JSON.parse(result);
} catch(err) {
//alert(err)
}
return result;
},
clear: function(key) { //removeItem() 和 clear()
if(key) {
this.obj.removeItem(key);
} else {
this.obj.clear();
}
},
getAllKey: function() {
var keys = [];
for(var i = 0; i < this.obj.length; i++) {
keys.push(this.obj.key(i));
}
return keys;
}
}
第一次登录时保存用户名:
var setUser = storage.set("user","value");
点击退出删除 localStorage 中的用户名 :
var delUser = storage.clear("user");
之后登录时查询 localStorage 中是否有用户名,有则处于登录状态,无则重新登录:
var getUser = storage.get("user");
2、浏览商品
页面所有商品的显示是在页面加载时就发生的,不依附于click等事件。
页面加载时发起的显示所有商品的 ajax 请求:
function ajax(iAjax) {
$.ajax({
type: "POST",
url: "http://192.168.1.2:5000/user/showGoods",
data: {
g_type: iAjax
},
success: function(res) {
if(res.err == 0) {
dataUse = res.data;
$(".vegetables").find("figure").remove();
init(res.data);
}
},
error: function() {}
});
}
以上的 g_type ,在点击类别的时候,click 事件上的页面链接如下:
onclick="window.location.href='shop.html?data=vegetales'"
对链接的处理:
var classWho = String(location.search.split("=")[1]);
switch(classWho) {
case "all":
break;
case "vegetables":
showVege();
break;
case "fruit":
showFruit();
break;
case "meat":
showMeat();
break;
}
不同的链接不同的跳转:
function showVege() {
ajax(2);
}
function showFruit() {
ajax(1);
}
function showMeat() {
ajax(3);
}
3、添加购物车
添加购物车时需要注意是在之前的基础上添加还是添加了新的。
添加时需要将要添加购物车的商品和购物车里已有的商品进行比对,查看购物车内是否存在这个商品,存在的话此商品数量加一,不存在则添加此商品至购物车。我这里的数据比较简单,主要是比对商品名称、商品价格、商品图片进行比较,一致的则是购物车里有的。
添加购物车 ajax 请求:
$.ajax({
type: "POST",
url: "http://192.168.1.2:5000/user/addCart",
data: {
_id: $(obj).attr("value"), //商品id
c_user:user //用户名
},
success: function(res) {
if(res.err == 0) {
alert(res.msg);
}
},
error: function(res) {}
});
添加购物车的后端处理:
router.post("/addCart", (req, res) => {
goodsSchema.find({
_id: req.body._id
}, (err, result) => {
cartSchema.find({
c_user: req.body.c_user,
c_name: result[0].g_name
}, (err, result1) => {
//console.log(result1)
if(result1.length == 0) {
cartSchema.insertMany({
c_user: req.body.c_user,
c_name: result[0].g_name,
c_img: result[0].g_img,
c_price: result[0].g_price,
c_num: 1,
c_total: result[0].g_price
}, (err, result3) => {
if(result3.length == 1) {
res.send({
err: 0,
msg: "成功添加购物车"
})
}
})
} else {
cartSchema.update({
c_user: req.body.c_user,
c_name: result[0].g_name
}, {
$set: {
c_num: result1[0].c_num + 1,
c_total: (result1[0].c_num + 1) * result[0].g_price
}
}, (err, result4) => {
console.log("result4" + result4)
res.send({
err: 0,
msg: "bingo"
})
})
}
})
})
})
promise 用起来更为简洁明了,改进之后可以用 promise 写。而且我这里验证购物车是否存在某商品太过复杂,可以更简单的查询,正在改进。
还有更新购物车,清空购物车都相对简单,就不写了。时间不早了,好好休息,晚安。