在這次博客中我們?yōu)橛脩?hù)增加頭像
實(shí)現(xiàn)功能
- 用戶(hù)頭像上傳
- 為每個(gè)用戶(hù)提供三個(gè)候選頭像岛请,分別是最近兩次的頭像和系統(tǒng)默認(rèn)頭像
依賴(lài)的第三方工具
- AngularJS前端框架
- Express后端框架
- Angular-File-upload插件
- connect-busboy插件
- then.js小工具
- mongoose數(shù)據(jù)庫(kù)插件
問(wèn)題分析
用一個(gè)長(zhǎng)度為3的棧來(lái)保存用戶(hù)的候選頭像凿菩,且棧的底部必定是系統(tǒng)默認(rèn)頭像太防,越新的頭像就越靠近棧頂
情況分類(lèi)
上傳新頭像
用戶(hù)上傳與之前上傳過(guò)的同名頭像怎么辦倒淫?
- 與當(dāng)前頭像名相同,什么都不做
- 與備用頭像名相同譬淳,當(dāng)前頭像入棧徘溢,刪除備用頭像名,當(dāng)前改為上傳頭像名
- 都不相同砂轻,當(dāng)前頭像入棧箕般,再看長(zhǎng)度有沒(méi)有超,超了刪第一號(hào)頭像(默認(rèn)后面的那個(gè))
在備用頭像里更換
- 用戶(hù)選擇默認(rèn)頭像舔清,當(dāng)前也是默認(rèn)丝里,不做任何事
- 用戶(hù)選備用頭像曲初,當(dāng)前是默認(rèn)頭像,當(dāng)前頭像不入棧杯聚,棧刪除對(duì)應(yīng)備用頭像
- 用戶(hù)選默認(rèn)頭像臼婆,當(dāng)前頭像非默認(rèn),當(dāng)前頭像入棧幌绍,若棧長(zhǎng)超過(guò)3颁褂,刪除1號(hào)頭像
- 當(dāng)前非默認(rèn)頭像,用戶(hù)選備用頭像傀广,當(dāng)前頭像入棧颁独,刪除相應(yīng)備用頭像
頁(yè)面代碼
由于在我的博客中前端實(shí)戰(zhàn)之用戶(hù)控制臺(tái)中有詳細(xì)的頁(yè)面代碼這里只出示一小部分,方便大家閱讀
<label class="control-label col-sm-2">
頭像
</label>
<div class="avatar col-sm-2">
<img alt="用戶(hù)頭像" class="img-circle" ng-src="{{profile.avatar}}">
</div>
<div class="btn-group change-avatar col-sm-2">
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
更換頭像
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li class="upload-button">
<div class="btn btn-lg btn-link upload-avatar" type="file" ng-file-select="fileSelect($files)" accept="image/*">
<span class="glyphicon glyphicon-pencil"></span>
上傳頭像
</div>
</li>
<li class="divider">
</li>
<li class="available-avatar">
<img ng-repeat="pic in picList" ng-src="{{pic}}" ng-click="changeAvatar(pic)">
</li>
</ul>
</div>
前端代碼
angular.module('settingAPP',['myApp.Services','angularFileUpload']).controller('profileCtrl',function($rootScope,$scope,$http,$upload){
$scope.count=0;
$scope.$on('userDone',function(){
$scope.profile=document.user.profile;
$scope.picList=$scope.profile.available_avatar;
});
$scope.fileSelect=function($files){
var file=$files[0];
$scope.upload=$upload.upload({
url:'/settings/newAvatar',
file:file
}).success(function(data, status, headers, config){
if(!data.success){
if(!data.err.message) data.err.message="未知錯(cuò)誤伪冰,稍后再試"
$rootScope.msg=data.err.message;
$rootScope.display=true;
}
else{
$scope.profile.avatar=data.avatar_path;
$scope.picList=data.list;
}
});
};
$scope.changeAvatar=function(pic){
var count,tmp;
for(var i=0;i<3;i++){
if($scope.picList[i]==pic){
count=i;
}
}
$http.post('/settings/changeAvatar',{pic:pic,num:count}).success(function(data){
if(!data.success){
if(!data.err.message) data.err.message="未知錯(cuò)誤誓酒,稍后再試"
$rootScope.msg=data.err.message;
$rootScope.display=true;
}
else{
$scope.picList=data.list;
$scope.profile.avatar=pic;
}
}).error(function(data){
$rootScope.msg='未知錯(cuò)誤,請(qǐng)重試';
$rootScope.display=true;
});
};
});
后端代碼
function newAvatar(req,res){//上傳新頭像
var img_path;
Then(function(cont){
req.pipe(req.busboy);
req.busboy.on('file',cont);
}).fin(function(cont,fieldname,file,filename){
img_path='/img/avatar/'+req.session.uname+'_'+filename;
var fileStream=fs.createWriteStream('public'+img_path);
file.pipe(fileStream);
fileStream.on('close',cont);
}).fin(function(cont){
User.findOne({username:req.session.uname},cont);
}).then(function(cont,doc){
if(!doc) return cont(new Err(msg.USER.userNone));
var tmp=doc.profile.available_avatar;
//與當(dāng)前頭像名相同贮聂,什么都不做
if(img_path==doc.profile.avatar) return cont(null,doc);
//與備用頭像名相同靠柑,當(dāng)前頭像入棧,刪除備用頭像名吓懈,當(dāng)前改為上傳頭像名
for(var i in tmp){
if(tmp[i]==img_path){
tmp.splice(i,1);
tmp.push(doc.profile.avatar);
doc.profile.avatar=img_path;
return doc.save(cont);
}
}
//都不相同歼冰,當(dāng)前入棧,再看長(zhǎng)度有沒(méi)有超耻警,超了刪1號(hào)
tmp.push(doc.profile.avatar);
doc.profile.avatar=img_path;
if(tmp.length>3) tmp.splice(1,1);
return doc.save(cont);
}).then(function(cont,doc){
res.json({
success:true,
err:null,
avatar_path:img_path,
list:doc.profile.available_avatar
});
}).fail(EndHandler);
}
function changeAvatar(req,res){//從候選頭像中選擇
var tmp=req.body;
Then(function(cont){
User.findOne({username:req.session.uname},cont);
}).then(function(cont,doc){
if(!doc) return cont(new Err(msg.USER.userNone));
//與當(dāng)前頭像名相同隔嫡,什么都不做
if(tmp.pic==doc.profile.avatar) return cont(null,doc);
//用戶(hù)選默認(rèn),當(dāng)前入棧甘穿,若棧長(zhǎng)超過(guò)3腮恩,刪除1號(hào)
if(tmp.num==0){
doc.profile.available_avatar.push(doc.profile.avatar);
if(doc.profile.available_avatar.length>3){
doc.profile.available_avatar.splice(1,1);
}
doc.profile.avatar=tmp.pic;
return doc.save(cont);
}
//用戶(hù)選備用,當(dāng)前默認(rèn)扒磁,不入棧庆揪,刪除對(duì)應(yīng)備用
if(doc.profile.avatar==doc.profile.available_avatar[0]){
doc.profile.avatar=tmp.pic;
doc.profile.available_avatar.splice(tmp.num,1);
return doc.save(cont);
}
//當(dāng)前非默認(rèn)式曲,用戶(hù)選備用妨托,當(dāng)前入棧,刪除相應(yīng)備用
doc.profile.available_avatar.push(doc.profile.avatar);
doc.profile.available_avatar.splice(tmp.num,1);
doc.profile.avatar=tmp.pic;
return doc.save(cont);
}).then(function(cont,doc){
res.json({
success:true,
err:null,
list:doc.profile.available_avatar
});
}).fail(EndHandler);
}