├── .gitattributes ├── .gitignore ├── README.md ├── app.js ├── articles └── test.md ├── doc ├── article.md ├── bookmark.md ├── comment.md ├── commonDAO.md ├── home.md └── user.md ├── package.json ├── public ├── 404 │ ├── 404.css │ ├── 404.html │ ├── boat.png │ ├── cloud.png │ ├── wave-back.png │ └── wave-front.png ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── gallary │ ├── 0750f1a8bb3bb36bc359cb9c6703f396.jpg │ ├── 1327390473_3dtj_4.jpg │ ├── 205cdf88d43f879491629c4bd21b0ef41ad53acb.jpg │ ├── 25c9c636afc37931e9ac3401e9c4b74542a9118f.jpg │ ├── 2fb27610b912c8fc769546e5fe039245d6882169.jpg │ ├── 304be9c3a55a1b416cb91ada4875f0cb.jpg │ ├── 347784364248d78f55c50f82fed7dd77.jpg │ ├── 36.jpg │ ├── 3622f6ee4bdcc69e40b2fd2a54562122.jpg │ ├── 472309f7905298227ea53ce9d5ca7bcb0a46d401.jpg │ ├── 57e853d9f2d3572c9c93a2f98813632762d0c35f.jpg │ ├── 70ccd1fe9925bc31a8c823b35cdf8db1cb137039.jpg │ ├── 83146ca0gw1e5uv98fxwcj20c80nfdhs.jpg │ ├── 97897383_2.jpg │ ├── a3d96e7c85580ec6aef37b242a9ed451.jpg │ ├── aa18972bd40735fab975fa929c510fb30f240817.jpg │ ├── ae8e9a18ab19d23f4bedbce2.jpg │ ├── bdc7a825bc315c60dd857dca8fb1cb13495477b8.jpg │ ├── d6ca7bcb0a46f21f78d01634f7246b600d33aef5.jpg │ ├── large_nKru_2391000169cf1260.jpg │ ├── m2w690hq92lt_large_LE4J_0156000035c81260.jpg │ ├── m2w690hq92lt_large_xlCV_77500001a647125f.jpg │ ├── m2w690hq92lt_original_sKaq_414f00003ce9118c.jpg │ ├── original_5fSW_59ff000093b9118c.jpg │ ├── original_DVSi_2346000169651260.jpg │ ├── u=553037556,1932829573&fm=9&gp=0.jpg │ ├── 无标题.jpg │ ├── 未来.JPG │ └── 科拉传奇.The.Legend.of.Korra.S01E12.Chi_Eng.WEB-HR.AAC.1024X576.x264-YYeTs&SLOMO[01-10-12].JPG ├── gallary_sm │ ├── 0750f1a8bb3bb36bc359cb9c6703f396.jpg │ ├── 1327390473_3dtj_4.jpg │ ├── 205cdf88d43f879491629c4bd21b0ef41ad53acb.jpg │ ├── 25c9c636afc37931e9ac3401e9c4b74542a9118f.jpg │ ├── 2fb27610b912c8fc769546e5fe039245d6882169.jpg │ ├── 304be9c3a55a1b416cb91ada4875f0cb.jpg │ ├── 347784364248d78f55c50f82fed7dd77.jpg │ ├── 36.jpg │ ├── 3622f6ee4bdcc69e40b2fd2a54562122.jpg │ ├── 472309f7905298227ea53ce9d5ca7bcb0a46d401.jpg │ ├── 57e853d9f2d3572c9c93a2f98813632762d0c35f.jpg │ ├── 70ccd1fe9925bc31a8c823b35cdf8db1cb137039.jpg │ ├── 83146ca0gw1e5uv98fxwcj20c80nfdhs.jpg │ ├── 97897383_2.jpg │ ├── a3d96e7c85580ec6aef37b242a9ed451.jpg │ ├── aa18972bd40735fab975fa929c510fb30f240817.jpg │ ├── ae8e9a18ab19d23f4bedbce2.jpg │ ├── bdc7a825bc315c60dd857dca8fb1cb13495477b8.jpg │ ├── d6ca7bcb0a46f21f78d01634f7246b600d33aef5.jpg │ ├── large_nKru_2391000169cf1260.jpg │ ├── m2w690hq92lt_large_LE4J_0156000035c81260.jpg │ ├── m2w690hq92lt_large_xlCV_77500001a647125f.jpg │ ├── m2w690hq92lt_original_sKaq_414f00003ce9118c.jpg │ ├── original_5fSW_59ff000093b9118c.jpg │ ├── original_DVSi_2346000169651260.jpg │ ├── u=553037556,1932829573&fm=9&gp=0.jpg │ ├── 无标题.jpg │ ├── 未来.JPG │ └── 科拉传奇.The.Legend.of.Korra.S01E12.Chi_Eng.WEB-HR.AAC.1024X576.x264-YYeTs&SLOMO[01-10-12].JPG ├── images │ ├── boat.png │ ├── cloud.png │ ├── default_avatar.jpg │ ├── favicon.ico │ ├── loading.gif │ ├── wave-back.png │ └── wave-front.png ├── javascripts │ ├── exp │ │ └── broadchat.js │ ├── page │ │ ├── articleDetail.js │ │ ├── editArticle.js │ │ ├── gallary.js │ │ ├── global.js │ │ ├── index.js │ │ ├── listArticle.js │ │ ├── listArticle_owner.js │ │ ├── login.js │ │ ├── regist.js │ │ ├── search.js │ │ ├── uploadPic.js │ │ ├── userCenter.js │ │ ├── userDetail.js │ │ └── writeArticle.js │ ├── pageTools │ │ ├── Admire.js │ │ ├── Article.js │ │ ├── Bookmark.js │ │ ├── Comment.js │ │ ├── Remind.js │ │ ├── Tag.js │ │ └── User.js │ └── tools │ │ ├── bootstrap.min.js │ │ ├── highlight.pack.js │ │ ├── jquery-1.10.2.min.js │ │ ├── jquery-mousewheel.js │ │ ├── markdown.js │ │ ├── showdown.js │ │ └── showdown_extensions │ │ ├── github.js │ │ ├── prettify.js │ │ ├── table.js │ │ └── twitter.js └── stylesheets │ ├── bootstrap-theme.min.css │ ├── bootstrap.min.css │ ├── github.css │ ├── monokai.css │ ├── page │ ├── admire.css │ ├── articleDetail.css │ ├── bookmark.css │ ├── comment.css │ ├── gallary.css │ ├── index.css │ ├── listArticle.css │ ├── remind.css │ ├── search.css │ ├── tag.css │ ├── uploadPic.css │ ├── user.css │ ├── userCenter.css │ ├── userDetail.css │ └── writeArticle.css │ ├── pageTools │ ├── admire.css │ ├── article.css │ ├── bookmark.css │ ├── comment.css │ ├── remind.css │ ├── tag.css │ └── user.css │ └── style.css ├── routes ├── Actions │ ├── AdmireAction.js │ ├── ArticleAction.js │ ├── BookmarkAction.js │ ├── CommentAction.js │ ├── ExpAction.js │ ├── GallaryAction.js │ ├── PictureAction.js │ ├── RemindAction.js │ ├── TagAction.js │ └── UserAction.js ├── Model │ ├── Admire.js │ ├── Article.js │ ├── Bookmark.js │ ├── Comment.js │ ├── CommonDAO.js │ ├── Remind.js │ ├── Tag.js │ └── User.js ├── index.js └── setting.js ├── upload_tmp └── 5792-oxlaq1.jpg └── views ├── advice.jade ├── articleDetail.jade ├── broadchat.jade ├── editArticle.jade ├── error.jade ├── gallary.jade ├── index.jade ├── layout.jade ├── listArticle.jade ├── login.jade ├── regist.jade ├── search.jade ├── userCenter.jade ├── userDetail.jade └── writeArticle.jade /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 天镶的博客 2 | ==== 3 | 一个基于Node.js开发的公共博客管理系统,使用express,mongodb进行开发 4 | 5 | 目前已部署到[nodejitsu](https://www.nodejitsu.com/)上,数据库使用[mongohq](http://www.mongohq.com/home),[单击访问主页](http://skyinlayer.nodejitsu.com/) 6 | 7 | ##目前的角色 8 | 9 | 1. 管理员 10 | 2. 来访用户 11 | 12 | ##目前的功能 13 | 14 | ###系统 15 | 16 | 1. 普通用户注册 17 | 2. 瀑布流查看博客图片 18 | 19 | ###所有用户 20 | 21 | 1. 查看/评论文章 22 | 2. 对评论点赞 23 | 3. 收藏文章 24 | 4. 查看用户中心 25 | 5. 修改基本的个人信息 26 | 27 | ###管理员额外功能 28 | 29 | 1. 添加/修改/删除 文章 30 | 2. 添加/删除 图片 31 | 32 | ##添加中的功能 33 | 34 | 1. 查看他人用户中心 35 | 2. 用户关注 36 | 3. 图片点赞 37 | 4. 文章访问量统计 38 | 5. ... 39 | 40 | -------------------------------------------------------------------------------- /articles/test.md: -------------------------------------------------------------------------------- 1 | ## ZOJ 1091 Knight Moves ## 2 | >**题意**:骑士遍历,给源点、目标点,求源点到目标点的最短步数 3 | > 4 | >**解法**:经典bfs 5 | > 6 | >**吐槽** :一直想用双向bfs写一次,不过这两天各种屁事。这题完全就是C++版本的翻译...熟悉了一下python的队列实现和矩阵,还是挺有收获的,发现我特别依赖字典,这样不好不好 7 | 8 | 9 | import sys 10 | des=[[2,1],[2,-1],[-2,1],[-2,-1],[1,2],[1,-2],[-1,2],[-1,-2]] 11 | def bfs(start,end): 12 | q=[] 13 | flag = [([0] * 11) for i in range(11)] 14 | q.append(start) 15 | flag[start['x']][start['y']]=1 16 | while len(q): 17 | cur=q[0] 18 | q=q[1:] 19 | if cur['x']==end['x'] and cur['y']==end['y']: 20 | return cur 21 | for i in range(len(des)): 22 | curx=des[i][0]+cur['x'] 23 | cury=des[i][1]+cur['y'] 24 | if curx<=8 and curx>=1 and cury<=8 and cury>=1 and flag[curx][cury]==0: 25 | flag[curx][cury]=1 26 | q.append({'x':curx,'y':cury,'t':cur['t']+1}) 27 | 28 | for line in sys.stdin: 29 | a=line.rstrip().split() 30 | start={'x':ord(a[0][0])-ord('a')+1,'y':ord(a[0][1])-ord('0'),'t':0} 31 | end={'x':ord(a[1][0])-ord('a')+1,'y':ord(a[1][1])-ord('0'),'t':0} 32 | ans=bfs(start,end) 33 | print 'To get from %s to %s takes %d knight moves.' %(a[0],a[1],ans['t']) -------------------------------------------------------------------------------- /doc/bookmark.md: -------------------------------------------------------------------------------- 1 | 书签 [Bookmark] 2 | === 3 | *** 4 | #构造函数 5 | ```js 6 | function Bookmark(bookmark) { 7 | this.username = bookmark.username; 8 | this.articleId = bookmark.articleId; 9 | this.time = bookmark.time; 10 | this.id = bookmark.id; 11 | } 12 | ``` 13 | #属性 14 | > **id** [string] : uuid v4生成的字符串 15 | 16 | > **username** [string] : 书签拥有者的用户名 17 | 18 | > **articleId** [string] : 书签所属文章的id 19 | 20 | > **time** [number] : 创建书签的时间,为毫秒数 21 | 22 | #原型上的方法 23 | *** 24 | ##save 25 | ###说明 26 | > 保存当前书签对象 27 | 28 | ###参数 29 | > **callback** [function] : 保存完成后的回调函数,两个参数 30 | 31 | >> **err** [object]: 若未发生错误,为null 32 | 33 | >> **result** [Bookmark] :持久化后的Bookmark对象 34 | 35 | ###实例 36 | ```js 37 | var bookmark = new Bookmark({ 38 | articleId: req.body.articleId, 39 | username: req.session.user.username 40 | }); 41 | bookmark.save(function(err, bookmark) { 42 | //TODO 43 | }); 44 | ``` 45 | 46 | ##remove 47 | ###说明 48 | > 移除当前书签对象 49 | 50 | ###参数 51 | > **callback** [function] : 移除完成后的回调函数,一个参数 52 | 53 | >> **err** [object]: 若未发生错误,为null 54 | 55 | ###实例 56 | ```js 57 | bookmark.remove(function(err) { 58 | if (err) return res.json(500, { 59 | message: err.message 60 | }); 61 | res.json({ 62 | success: true 63 | }); 64 | }); 65 | ``` 66 | 67 | #方法 68 | *** 69 | ##get 70 | ###说明 71 | > 根据书签id获取一个书签 72 | 73 | ###参数 74 | > **bookmarkId** [string] : 书签的id 75 | 76 | > **callback** [function] : 移除完成后的回调函数,两个参数 77 | 78 | >> **err** [object]: 若未发生错误,为null 79 | 80 | >> **bookmark** [Bookmark] : 获取到的书签对象,若失败,则为null 81 | 82 | ###实例 83 | ```js 84 | Bookmark.get(req.body.bookmarkId, function(err, bookmark) { 85 | if (err) return res.json(500); 86 | if (!bookmark) return res.status(404).send("not found"); 87 | bookmark.time = moment(bookmark.time).format("HH:mm MM月DD日 YYYY年"); 88 | res.json({ 89 | bookmark: bookmark 90 | }); 91 | }); 92 | ``` 93 | ##checkBooked 94 | ###说明 95 | > 判断一个用户是否收藏了某篇文章 96 | 97 | ###参数 98 | > **username** [string] : 用户的用户名 99 | 100 | > **articleId** [string] : 文章的id 101 | 102 | > **callback** [function] : 移除完成后的回调函数,两个参数 103 | 104 | >> **err** [object]: 若未发生错误,为null 105 | 106 | >> **booked** [boolean] : 若已经加入收藏,则为true,否则为false 107 | 108 | ###实例 109 | ```js 110 | Bookmark.checkBooked(req.session.user.username, req.body.articleId, function(err, booked) { 111 | if (err) return res.json(500, { 112 | message: err.message 113 | }); 114 | res.json({ 115 | booked: booked 116 | }); 117 | }); 118 | ``` 119 | 120 | ##countByArticle 121 | ###说明 122 | > 统计一篇文章的被收藏次数 123 | 124 | ###参数 125 | > **articleId** [string] : 文章的id 126 | 127 | > **callback** [function] : 移除完成后的回调函数,两个参数 128 | 129 | >> **err** [object]: 若未发生错误,为null 130 | 131 | >> **total** [number] : 文章被收藏次数 132 | 133 | ###实例 134 | ```js 135 | Bookmark.countByArticle(req.body.articleId, function(err, total) { 136 | if (err) return res.json(500, { 137 | message: err.message 138 | }); 139 | res.json({ 140 | total: total 141 | }); 142 | }); 143 | ``` 144 | 145 | ##countByUser 146 | ###说明 147 | > 统计一个用户的书签总个数 148 | 149 | ###参数 150 | > **username** [string] :用户的用户名 151 | 152 | > **callback** [function] : 移除完成后的回调函数,两个参数 153 | 154 | >> **err** [object]: 若未发生错误,为null 155 | 156 | >> **total** [number] : 用户的书签总个数 157 | 158 | ###实例 159 | ```js 160 | Bookmark.countByUser(req.body.username, function(err, total) { 161 | if (err) return res.json(500); 162 | res.json({ 163 | total: total 164 | }); 165 | }); 166 | ``` 167 | ##getByUser 168 | ###说明 169 | > 分页获取一个用户的所有书签 170 | 171 | ###参数 172 | > **username** [string] :用户的用户名 173 | 174 | > **curPage** [integer] : 当前页,从0开始 175 | 176 | > **perPage** [integer] : 每页的书签个数 177 | 178 | > **callback** [function] : 查询完成后的回调函数 179 | 180 | >> **err** [object]: 若未发生错误,为null 181 | 182 | >> **bookmarks** [array:Bookmark] : 获取到的书签对象的数组 183 | 184 | ###实例 185 | ```js 186 | Bookmark.getByUser(req.body.username, Number(req.body.curPage), Number(req.body.perPage), function(err, bookmarks) { 187 | if (err) return res.json(500); 188 | for (var i = bookmarks.length; i--;) { 189 | bookmarks[i].time = moment(bookmarks[i].time).format("HH:mm MM月DD日 YYYY年"); 190 | } 191 | res.json({ 192 | bookmarks: bookmarks 193 | }); 194 | }); 195 | ``` 196 | -------------------------------------------------------------------------------- /doc/comment.md: -------------------------------------------------------------------------------- 1 | 评论 [Comment] 2 | === 3 | *** 4 | #构造函数 5 | *** 6 | ```js 7 | function Comment(comment) { 8 | this.comment = comment.comment; 9 | this.username = comment.username; 10 | this.reply = comment.reply; 11 | this.articleId = comment.articleId; 12 | this.time = comment.time; 13 | this.id = comment.id; 14 | } 15 | ``` 16 | #属性 17 | *** 18 | > **id** [string] : 评论的id,uuid的v4生成 19 | 20 | > **articleId** [string] : 评论所属文章的id 21 | 22 | > **username** [string] : 创建这条评论的用户名 23 | 24 | > **comment** [string] : 评论的内容 25 | 26 | > **time** [number] : 评论的时间,为毫秒数 27 | 28 | > **reply** [string] : 若本评论回复了其他评论,则reply的值为被回复的评论的id,否则为null 29 | 30 | #原型上的方法 31 | *** 32 | ##save 33 | ### 说明 34 | > 保存当前评论对象 35 | 36 | ### 参数 37 | > **callback** [function] : 保存完成后的回调函数,两个参数 38 | 39 | >> **err** [object]: 若未发生错误,为null 40 | 41 | >> **result** [Comment] :持久化后的Comment对象 42 | 43 | 44 | ### 实例 45 | ```js 46 | var comment = new Comment({ 47 | articleId: req.body.articleId, 48 | username: req.session.user.username, 49 | comment: req.body.comment, 50 | reply: req.body.replyId 51 | }); 52 | comment.save(function(err, comment) { 53 | if (err) return callback(err); 54 | callback(err, comment); 55 | }); 56 | ``` 57 | 58 | ##remove 59 | ### 说明 60 | > 删除当前评论 61 | 62 | ### 参数 63 | > **callback** [function] : 删除完成后的回调函数,一个参数 64 | 65 | >> **err** [object]: 若未发生错误,为null 66 | 67 | 68 | ### 实例 69 | ```js 70 | comment.remove(function(err) { 71 | if (err) return res.json(500, { 72 | message: err.message 73 | }); 74 | res.json({ 75 | success: true 76 | }); 77 | }); 78 | ``` 79 | #方法 80 | *** 81 | ##get 82 | ### 说明 83 | > 根据评论id获取一个评论 84 | 85 | ### 参数 86 | > **commentId** [string] : 需要获取的评论的id 87 | 88 | > **callback** [function] : 获取完成后的回调函数,两个参数 89 | 90 | >> **err** [object]: 若未发生错误,为null 91 | 92 | >> **comment** [Comment]: 获取的评论对象,没有则为null 93 | 94 | 95 | ### 实例 96 | ```js 97 | Comment.get(req.body.commentId, function(err, comment) { 98 | //TODO 99 | }); 100 | ``` 101 | 102 | ##countByArticle 103 | ###说明 104 | > 统计一篇文章的评论个数 105 | 106 | ###参数 107 | > **articleId** [string]: 文章的id 108 | 109 | > **callback** [function] : 统计完成后的回调函数,两个参数 110 | 111 | >> **err** [object]: 若未发生错误,为null 112 | 113 | >> **total** [number]: 该文章的评论总数 114 | 115 | ###实例 116 | ```js 117 | Comment.countByArticle(req.body.articleId, function(err, total) { 118 | if (err) return res.json(500, { 119 | message: err.message 120 | }); 121 | res.json({ 122 | total: total 123 | }); 124 | }); 125 | ``` 126 | 127 | ##getByArticle 128 | ### 说明 129 | > 分页获取一篇文章的评论 130 | 131 | ### 参数 132 | > **articleId** [string] : 文章的id 133 | 134 | > **curPage** [integer] : 当前页,从0开始 135 | 136 | > **perPage** [integer] : 每页的文章个数 137 | 138 | > **callback** [function] : 获取完成后的回调函数,两个参数 139 | 140 | >> **err** [object]: 若未发生错误,为null 141 | 142 | >> **comments** [array:Comment]: 获取的评论对象列表 143 | 144 | ### 实例 145 | ```js 146 | Comment.getByArticle(req.body.articleId, Number(req.body.curPage), Number(req.body.perPage), function(err, comments) { 147 | var i; 148 | if (err) return res.json(500, { 149 | message: err.message 150 | }); 151 | for (i = comments.length; i--;) { 152 | comments[i].time = moment(comments[i].time).format("HH:mm MM月DD日 YYYY年"); 153 | } 154 | res.json({ 155 | comments: comments 156 | }); 157 | }); 158 | ``` 159 | 160 | ##countByUser 161 | ###说明 162 | > 统计一个用户的评论个数 163 | 164 | ###参数 165 | > **username** [string]: 用户的用户名 166 | 167 | > **callback** [function] : 统计完成后的回调函数,两个参数 168 | 169 | >> **err** [object]: 若未发生错误,为null 170 | 171 | >> **total** [number]: 该用户的评论总数 172 | 173 | ###实例 174 | ```js 175 | Comment.countByUser(req.body.username, function(err, total) { 176 | if (err) return res.json(500, { 177 | message: err.message 178 | }); 179 | res.json({ 180 | total: total 181 | }); 182 | }); 183 | ``` 184 | 185 | ##getByUser 186 | ### 说明 187 | > 分页获取一个用户的评论 188 | 189 | ### 参数 190 | > **username** [string]: 用户的用户名 191 | 192 | > **curPage** [integer] : 当前页,从0开始 193 | 194 | > **perPage** [integer] : 每页的文章个数 195 | 196 | > **callback** [function] : 获取完成后的回调函数,两个参数 197 | 198 | >> **err** [object]: 若未发生错误,为null 199 | 200 | >> **comments** [array:Comment]: 获取的评论对象列表 201 | 202 | ### 实例 203 | ```js 204 | Comment.getByUser(req.body.username, Number(req.body.curPage), Number(req.body.perPage), function(err, comments) { 205 | if (err) return res.json(500, { 206 | message: err.message 207 | }); 208 | for (var i = comments.length; i--;) { 209 | comments[i].time = moment(comments[i].time).format("HH:mm MM月DD日 YYYY年"); 210 | } 211 | res.json({ 212 | comments: comments 213 | }); 214 | }); 215 | ``` 216 | 217 | -------------------------------------------------------------------------------- /doc/commonDAO.md: -------------------------------------------------------------------------------- 1 | 公用数据库连接层 [CommonDAO.js] 2 | === 3 | *** 4 | 使用[node-mongodb-native](https://github.com/mongodb/node-mongodb-native)直接与mongodb数据库相连 5 | 6 | 提供以下方法: 7 | 8 | 1. [save](#save) 9 | 2. [findOne](#findone) 10 | 3. [find](#find) 11 | 4. [count](#count) 12 | 5. [update](#update) 13 | 6. [remove](#remove) 14 | 15 | ## save 16 | *** 17 | ### 说明 18 | > 用于将一个对象保存到mongodb数据库中 19 | 20 | ### 参数 21 | > **collectionName** [string]:mongodb的collection名称 22 | 23 | > **obj** [object] : 需要保存到collection中的对象 24 | 25 | > **callback** [function]:保存完毕后执行的回调函数 26 | 27 | >> **err** [object]: 若未发生错误,为null 28 | 29 | >> **result** [array:object] :result[0]为存入数据库的对象,若长度为0则保存失败 30 | 31 | ### 实例 32 | ```js 33 | commonDao.save("article", { 34 | id: uuid.v4, 35 | content: "hello world" 36 | }, function(err, result) { 37 | if (err) return callback(err); 38 | if (!result[0]) return callback(new Error("保存失败")); 39 | callback(err, new Article(result[0])); 40 | }); 41 | ``` 42 | 43 | ## findOne 44 | *** 45 | ### 说明 46 | > 根据特定条件在数据库中查找一个匹配的对象 47 | 48 | ### 参数 49 | > **collectionName** [string]: mongodb的collection名称 50 | 51 | > **oArgs** [object]: mongodb查询时的条件 52 | 53 | > **callback** [function]: 查询执行完后的回调函数,两个参数: 54 | 55 | >> **err** [object]: 若未发生错误,则为null 56 | 57 | >> **result** [object]: 查询结果 58 | 59 | ### 实例 60 | 根据文章id查找文章 61 | ```js 62 | commonDao.findOne("article", { 63 | id: id 64 | }, callback); 65 | ``` 66 | 67 | ## find 68 | *** 69 | ### 说明 70 | > 根据特定条件和配置在数据库中查找所有匹配的对象 71 | 72 | ### 参数 73 | > **collectionName** [string] : mongodb的collection名称 74 | 75 | > **oArgs** [object] : mongodb查询的条件及分页、排序设置 76 | 77 | >> **condition** [object] : mongodb查询的条件 78 | 79 | >> **page** [object] : 查询的分页设置 80 | > 81 | >>> **curPage** [integer] : 查询的页数,从0开始 82 | > 83 | >>> **perPage** [integer] : 查询每页的个数 84 | > 85 | >> **sort** [object] : 查询的排序方式,键为排序的字段名称,值为**1**表示**正序**,值为**-1**表示倒序 86 | > 87 | > **callback** [function] : 查询完成之后的回调函数,有两个参数: 88 | > 89 | >> **err** [object]: 若未发生错误,则为null 90 | > 91 | >> **results** [array:object]: 查询结果数组 92 | 93 | ### 实例 94 | 以创作时间为倒序,每页10个结果,查询第二页的所有文章 95 | ```js 96 | commonDao.find("article", { 97 | sort: { 98 | writeTime: -1 99 | }, 100 | page: { 101 | curPage: 1, 102 | perPage: 10 103 | } 104 | }, callback); 105 | ``` 106 | 107 | ## count 108 | *** 109 | ### 说明 110 | > 统计数据库中符合条件的对象个数 111 | 112 | ### 参数 113 | > **collectionName** [string] : mongodb的collection名称 114 | > 115 | > **oArgs** [object] : 统计的条件 116 | > 117 | > **callback** [function] : 统计完成后的回调函数,两个参数: 118 | > > **err** [object] : 若未发生错误,则为null 119 | > 120 | > > **total** [number] : 统计的结果 121 | 122 | ### 实例 123 | 通过作者用户名查询文章 124 | ```js 125 | commonDao.count("article", { 126 | writer: username 127 | }, callback); 128 | ``` 129 | ## update 130 | *** 131 | ### 说明 132 | > 更新所有符合条件的对象 133 | 134 | ### 参数 135 | > **collectionName** [string] : mongodb的collection名称 136 | 137 | > **oArgs** [object] : 查找需要被更新对象的条件 138 | 139 | > **change** [object] : 需要被更新的数据,键为更新的字段名称,值为需要被更新的值 140 | 141 | > **callback** [function] : 更新完成后的回调函数,一个参数: 142 | 143 | >> **err** [object] : 若未发生错误,则为null 144 | 145 | ### 实例 146 | 更新一个文章的主题,内容,修改时间,及标签 147 | ```js 148 | commonDao.update("article", { 149 | id: this.id 150 | }, { 151 | content: this.content, 152 | title: this.title, 153 | lastModifyTime: new Date().getTime(), 154 | tags: this.tags 155 | }, callback); 156 | ``` 157 | ## remove 158 | *** 159 | ### 说明 160 | > 移除所有符合条件的对象 161 | 162 | ### 参数 163 | > **collectionName** [string] : mongodb的collection名称 164 | 165 | > **oArgs** [object] : 查找需要被删除对象的条件 166 | 167 | > **callback** [function] : 删除完成后的回调函数,一个参数: 168 | 169 | >> **err** [object] : 若未发生错误,则为null 170 | 171 | ### 实例 172 | 根据文章id删除一篇文章 173 | ```js 174 | commonDao.remove("article", { 175 | id: articleId 176 | }, callback); 177 | ``` -------------------------------------------------------------------------------- /doc/home.md: -------------------------------------------------------------------------------- 1 | 项目简介 2 | === 3 | *** 4 | ##简介 5 | > 一个多人共同管理的博客模板 6 | > 7 | > 使用nodejs和mongodb进行开发 8 | > 9 | > 采用了express框架和jade模板引擎 10 | 11 | ##效果 12 | > [点我跳转](http://skyinlayer.jit.su/) 13 | 14 | ##依赖 15 | > [express: 3.4.2](http://expressjs.com/) 16 | > 17 | > [jade: *](http://jade-lang.com/) 18 | > 19 | > [node-uuid: 1.4.1](http://github.com/broofa/node-uuid) 20 | > 21 | > [mongodb: 1.3.19](https://github.com/mongodb/node-mongodb-native) 22 | > 23 | > [markdown: 0.5.0](https://github.com/evilstreak/markdown-js) 24 | > 25 | > [async: 0.2.9](https://github.com/caolan/async) 26 | > 27 | > [moment: 2.4.0](http://momentjs.com/) 28 | > 29 | > [gm: 1.13.3](https://github.com/aheckmann/gm) 30 | 31 | ##文档 32 | 33 | ### 模型层 34 | > [公用数据库连接层](https://github.com/LingyuCoder/Blog/wiki/%E5%85%AC%E7%94%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E8%BF%9E%E6%8E%A5%E5%B1%82-%5BCommonDAO.js%5D) 35 | 36 | > [文章](https://github.com/LingyuCoder/Blog/wiki/%E6%96%87%E7%AB%A0-%5BArticle%5D) 37 | 38 | > [用户](https://github.com/LingyuCoder/Blog/wiki/%E7%94%A8%E6%88%B7-%5BUser%5D) 39 | 40 | > [评论](https://github.com/LingyuCoder/Blog/wiki/%E8%AF%84%E8%AE%BA%5BComment%5D) 41 | 42 | > [书签](https://github.com/LingyuCoder/Blog/wiki/%E4%B9%A6%E7%AD%BE-%5BBookmark%5D) 43 | 44 | > [点赞(施工中)]() 45 | 46 | > [标签(施工中)]() 47 | 48 | ### 控制层(施工中) 49 | 50 | ### 表示层(施工中) -------------------------------------------------------------------------------- /doc/user.md: -------------------------------------------------------------------------------- 1 | 用户 [User] 2 | === 3 | *** 4 | #构造函数 5 | ```js 6 | function User(user) { 7 | this.username = user.username; 8 | this.nickname = user.nickname; 9 | this.password = user.password; 10 | this.owner = user.owner; 11 | this.avatar = user.avatar; 12 | this.tags = user.tags; 13 | } 14 | ``` 15 | # 属性 16 | *** 17 | > **username** [string] : 用户名,需手动保持唯一 18 | 19 | > **nickname** [string] : 用户昵称 20 | 21 | > **password** [string] : 用户密码 22 | 23 | > **owner** [boolean] : 用户是否为博客管理员 24 | 25 | > **avatar** [string] : 用户头像的url 26 | 27 | > **tags** [array:string] : 用户的标签列表,元素为标签的id 28 | 29 | # 原型上的方法 30 | *** 31 | ## save 32 | ### 说明 33 | > 保存当前用户 34 | 35 | ### 参数 36 | > **callback** [function] : 保存完成后的回调函数,两个参数 37 | 38 | >> **err** [object]: 若未发生错误,为null 39 | 40 | >> **result** [Article] :持久化后的User对象 41 | 42 | ### 实例 43 | ```js 44 | var user = new User({ 45 | username: req.body.username, 46 | password: req.body.password, 47 | nickname: req.body.nickname, 48 | avatar: "/images/default_avatar.jpg", 49 | owner: false, 50 | tags: [] 51 | }); 52 | user.save(function(err) { 53 | if (err) { 54 | return res.render("regist", { 55 | message: "发生错误,请稍后重试..." 56 | }); 57 | } else { 58 | req.session.user = user; 59 | res.redirect("/index"); 60 | } 61 | }); 62 | ``` 63 | ## update 64 | ### 说明 65 | > 更新当前用户 66 | 67 | ### 参数 68 | > **callback** [function] : 更新完成后的回调函数,一个参数 69 | 70 | >> **err** [object]: 若未发生错误,为null 71 | 72 | ### 实例 73 | ```js 74 | user.update(function(err) { 75 | req.session.user = user; 76 | res.render("userDetail", { 77 | user: req.session.user, 78 | success: true, 79 | message: "修改成功..." 80 | }); 81 | }); 82 | ``` 83 | ## remove 84 | ### 说明 85 | > 删除当前用户 86 | 87 | ### 参数 88 | > **callback** [function] : 删除完成后的回调函数,一个参数 89 | 90 | >> **err** [object]: 若未发生错误,为null 91 | 92 | 93 | ### 实例 94 | ```js 95 | user.remove(function(err) { 96 | if(err){ 97 | return res.render("error", { 98 | message: err.message 99 | }); 100 | } 101 | //do something after removing 102 | }); 103 | ``` 104 | # 方法 105 | *** 106 | ## get 107 | ### 说明 108 | > 根据用户的用户名,获取用户详细信息 109 | 110 | ### 参数 111 | > **username** [string] : 需要获取的用户的id 112 | 113 | > **callback** [function] : 获取完成后的回调函数,两个参数 114 | 115 | >> **err** [object]: 若未发生错误,为null 116 | 117 | >> **user** [User] : 该用户对象,没有则为null 118 | 119 | 120 | ### 实例 121 | ```js 122 | User.get(req.body.username, function(err, user) { 123 | if (err) return res.render("error", { 124 | message: err.message 125 | }); 126 | res.json({ 127 | username: user.username, 128 | nickname: user.nickname, 129 | owner: user.owner, 130 | tags: user.tags, 131 | avatar: user.avatar 132 | }); 133 | }); 134 | ``` 135 | 136 | ## countAll 137 | ### 说明 138 | > 统计系统中所有用户个数 139 | 140 | ### 参数 141 | > **callback** [function] : 删除完成后的回调函数,两个参数 142 | 143 | >> **err** [object]: 若未发生错误,为null 144 | 145 | >> **total** [number] : 系统中的用户总数 146 | 147 | 148 | ### 实例 149 | ```js 150 | User.count(function(err, total) { 151 | if(err) return res.json(500); 152 | return res.json({ 153 | total: total 154 | }); 155 | }); 156 | ``` 157 | ## getAll 158 | ### 说明 159 | > 分页获取系统中所有用户 160 | 161 | ### 参数 162 | > **curPage** [integer] : 当前页,从0开始 163 | 164 | > **perPage** [integer] : 每页用户个数 165 | 166 | > **callback** [function] : 删除完成后的回调函数,两个参数 167 | 168 | >> **err** [object]: 若未发生错误,为null 169 | 170 | >> **users** [array:User] : 获取的用户对象数组 171 | 172 | 173 | ### 实例 174 | ```js 175 | User.getAll(1, 10, function(err, useres) { 176 | if(err) return res.render("error"); 177 | return res.render("showUsers",{ 178 | useres: useres 179 | }); 180 | }); 181 | ``` 182 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "myblog", 3 | "version": "0.0.1-31", 4 | "private": true, 5 | "scripts": { 6 | "start": "node app.js" 7 | }, 8 | "dependencies": { 9 | "express": "3.4.2", 10 | "jade": "*", 11 | "node-uuid": "1.4.1", 12 | "mongodb": "1.3.19", 13 | "markdown": "0.5.0", 14 | "async": "0.2.9", 15 | "moment": "2.4.0", 16 | "gm": "1.13.3", 17 | "ws": "0.4.31" 18 | }, 19 | "subdomain": "skyinlayer", 20 | "engines": { 21 | "node": "0.10.x" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /public/404/404.css: -------------------------------------------------------------------------------- 1 | .main { 2 | position: absolute; 3 | width: 800px; 4 | height: 500px; 5 | margin-top:100px; 6 | left: 50%; 7 | margin-left: -400px; 8 | background-image: -webkit-linear-gradient(top, #5CC9FC, #FFFFFF); 9 | border-radius: 10px; 10 | overflow: hidden; 11 | box-shadow : 5px 5px 6px #525252; 12 | 13 | } 14 | 15 | .clouds { 16 | position: absolute; 17 | -webkit-animation: cloud_move 20s linear infinite; 18 | } 19 | 20 | .clouds .cloud { 21 | position: absolute; 22 | background-image: url("cloud.png"); 23 | background-position: center; 24 | background-repeat: no-repeat; 25 | } 26 | 27 | .clouds .cloud-sm{ 28 | width: 223px; 29 | height: 98px; 30 | background-size: 223px 78px; 31 | } 32 | 33 | .clouds .cloud-md{ 34 | width: 335px; 35 | height: 147px; 36 | background-size: 335px 147px; 37 | } 38 | 39 | .clouds .cloud-lg{ 40 | width: 670px; 41 | height: 294px; 42 | background-size: 670px 294px; 43 | } 44 | 45 | .boat { 46 | position: absolute; 47 | width: 100%; 48 | height: 100%; 49 | -webkit-animation: boat_shake 5s linear infinite; 50 | } 51 | 52 | .boat .boat-body{ 53 | position: absolute; 54 | bottom: 20px; 55 | background-position: center; 56 | background-repeat: no-repeat; 57 | background-image: url(boat.png); 58 | width: 384px; 59 | height: 354px; 60 | -webkit-transform: scaleX(-1); 61 | } 62 | 63 | .wave { 64 | position: absolute; 65 | width: 900px; 66 | bottom: -20px; 67 | left: -50px; 68 | } 69 | 70 | .wave-front { 71 | height: 120px; 72 | background-image: url(wave-front.png); 73 | -webkit-animation: wave_shake 6s linear infinite; 74 | } 75 | 76 | .wave-back { 77 | height: 125px; 78 | background-image: url(wave-back.png); 79 | -webkit-animation: wave_shake 6s linear 3s infinite; 80 | } 81 | 82 | .message { 83 | position: absolute; 84 | left: 450px; 85 | top: 100px; 86 | width: 300px; 87 | height: 200px; 88 | text-align: center; 89 | font-family: "Microsoft YaHei"; 90 | font-weight: bolder; 91 | color: rgb(109, 109, 109); 92 | text-shadow : 2px 2px 2px #ACACAC; 93 | } 94 | 95 | .message .code { 96 | font-size: 80px; 97 | } 98 | 99 | /* .message .code span:hover { 100 | display: block; 101 | -webkit-transform: rotate(90deg); 102 | -webkit-transform-origin: 20% 47%; 103 | -webkit-animation: error_code_down 2s ease-in-out 1; 104 | } */ 105 | 106 | .message .content { 107 | font-size: 40px; 108 | } 109 | @-webkit-keyframes error_code_down { 110 | from { 111 | -webkit-transform: rotate(0deg); 112 | } 113 | to { 114 | -webkit-transform: rotate(90deg); 115 | } 116 | } 117 | 118 | @-webkit-keyframes wave_shake { 119 | 0% { 120 | -webkit-transform: translate(0px, 0px); 121 | } 122 | 25% { 123 | -webkit-transform: translate(5px, 5px); 124 | } 125 | 75% { 126 | -webkit-transform: translate(0px, 5px); 127 | } 128 | 100% { 129 | -webkit-transform: translate(0px, 0px); 130 | } 131 | } 132 | 133 | @-webkit-keyframes cloud_move { 134 | from { 135 | left: -800px; 136 | } 137 | to { 138 | left: 0px; 139 | } 140 | } 141 | 142 | @-webkit-keyframes boat_shake { 143 | 0% { 144 | -webkit-transform: translate(0px, 0px); 145 | } 146 | 25% { 147 | -webkit-transform: translate(-10px, -10px); 148 | } 149 | 75% { 150 | -webkit-transform: translate(0px, -10px); 151 | } 152 | 100% { 153 | -webkit-transform: translate(0px, 0px); 154 | } 155 | } -------------------------------------------------------------------------------- /public/404/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 啊哦,好像有什么东西找不到了 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |

404

28 |

好像有什么东西找不到了

29 |
30 |
31 |
32 | 33 | -------------------------------------------------------------------------------- /public/404/boat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/404/boat.png -------------------------------------------------------------------------------- /public/404/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/404/cloud.png -------------------------------------------------------------------------------- /public/404/wave-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/404/wave-back.png -------------------------------------------------------------------------------- /public/404/wave-front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/404/wave-front.png -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/gallary/0750f1a8bb3bb36bc359cb9c6703f396.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/0750f1a8bb3bb36bc359cb9c6703f396.jpg -------------------------------------------------------------------------------- /public/gallary/1327390473_3dtj_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/1327390473_3dtj_4.jpg -------------------------------------------------------------------------------- /public/gallary/205cdf88d43f879491629c4bd21b0ef41ad53acb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/205cdf88d43f879491629c4bd21b0ef41ad53acb.jpg -------------------------------------------------------------------------------- /public/gallary/25c9c636afc37931e9ac3401e9c4b74542a9118f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/25c9c636afc37931e9ac3401e9c4b74542a9118f.jpg -------------------------------------------------------------------------------- /public/gallary/2fb27610b912c8fc769546e5fe039245d6882169.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/2fb27610b912c8fc769546e5fe039245d6882169.jpg -------------------------------------------------------------------------------- /public/gallary/304be9c3a55a1b416cb91ada4875f0cb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/304be9c3a55a1b416cb91ada4875f0cb.jpg -------------------------------------------------------------------------------- /public/gallary/347784364248d78f55c50f82fed7dd77.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/347784364248d78f55c50f82fed7dd77.jpg -------------------------------------------------------------------------------- /public/gallary/36.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/36.jpg -------------------------------------------------------------------------------- /public/gallary/3622f6ee4bdcc69e40b2fd2a54562122.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/3622f6ee4bdcc69e40b2fd2a54562122.jpg -------------------------------------------------------------------------------- /public/gallary/472309f7905298227ea53ce9d5ca7bcb0a46d401.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/472309f7905298227ea53ce9d5ca7bcb0a46d401.jpg -------------------------------------------------------------------------------- /public/gallary/57e853d9f2d3572c9c93a2f98813632762d0c35f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/57e853d9f2d3572c9c93a2f98813632762d0c35f.jpg -------------------------------------------------------------------------------- /public/gallary/70ccd1fe9925bc31a8c823b35cdf8db1cb137039.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/70ccd1fe9925bc31a8c823b35cdf8db1cb137039.jpg -------------------------------------------------------------------------------- /public/gallary/83146ca0gw1e5uv98fxwcj20c80nfdhs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/83146ca0gw1e5uv98fxwcj20c80nfdhs.jpg -------------------------------------------------------------------------------- /public/gallary/97897383_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/97897383_2.jpg -------------------------------------------------------------------------------- /public/gallary/a3d96e7c85580ec6aef37b242a9ed451.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/a3d96e7c85580ec6aef37b242a9ed451.jpg -------------------------------------------------------------------------------- /public/gallary/aa18972bd40735fab975fa929c510fb30f240817.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/aa18972bd40735fab975fa929c510fb30f240817.jpg -------------------------------------------------------------------------------- /public/gallary/ae8e9a18ab19d23f4bedbce2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/ae8e9a18ab19d23f4bedbce2.jpg -------------------------------------------------------------------------------- /public/gallary/bdc7a825bc315c60dd857dca8fb1cb13495477b8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/bdc7a825bc315c60dd857dca8fb1cb13495477b8.jpg -------------------------------------------------------------------------------- /public/gallary/d6ca7bcb0a46f21f78d01634f7246b600d33aef5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/d6ca7bcb0a46f21f78d01634f7246b600d33aef5.jpg -------------------------------------------------------------------------------- /public/gallary/large_nKru_2391000169cf1260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/large_nKru_2391000169cf1260.jpg -------------------------------------------------------------------------------- /public/gallary/m2w690hq92lt_large_LE4J_0156000035c81260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/m2w690hq92lt_large_LE4J_0156000035c81260.jpg -------------------------------------------------------------------------------- /public/gallary/m2w690hq92lt_large_xlCV_77500001a647125f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/m2w690hq92lt_large_xlCV_77500001a647125f.jpg -------------------------------------------------------------------------------- /public/gallary/m2w690hq92lt_original_sKaq_414f00003ce9118c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/m2w690hq92lt_original_sKaq_414f00003ce9118c.jpg -------------------------------------------------------------------------------- /public/gallary/original_5fSW_59ff000093b9118c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/original_5fSW_59ff000093b9118c.jpg -------------------------------------------------------------------------------- /public/gallary/original_DVSi_2346000169651260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/original_DVSi_2346000169651260.jpg -------------------------------------------------------------------------------- /public/gallary/u=553037556,1932829573&fm=9&gp=0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/u=553037556,1932829573&fm=9&gp=0.jpg -------------------------------------------------------------------------------- /public/gallary/无标题.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/无标题.jpg -------------------------------------------------------------------------------- /public/gallary/未来.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/未来.JPG -------------------------------------------------------------------------------- /public/gallary/科拉传奇.The.Legend.of.Korra.S01E12.Chi_Eng.WEB-HR.AAC.1024X576.x264-YYeTs&SLOMO[01-10-12].JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary/科拉传奇.The.Legend.of.Korra.S01E12.Chi_Eng.WEB-HR.AAC.1024X576.x264-YYeTs&SLOMO[01-10-12].JPG -------------------------------------------------------------------------------- /public/gallary_sm/0750f1a8bb3bb36bc359cb9c6703f396.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/0750f1a8bb3bb36bc359cb9c6703f396.jpg -------------------------------------------------------------------------------- /public/gallary_sm/1327390473_3dtj_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/1327390473_3dtj_4.jpg -------------------------------------------------------------------------------- /public/gallary_sm/205cdf88d43f879491629c4bd21b0ef41ad53acb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/205cdf88d43f879491629c4bd21b0ef41ad53acb.jpg -------------------------------------------------------------------------------- /public/gallary_sm/25c9c636afc37931e9ac3401e9c4b74542a9118f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/25c9c636afc37931e9ac3401e9c4b74542a9118f.jpg -------------------------------------------------------------------------------- /public/gallary_sm/2fb27610b912c8fc769546e5fe039245d6882169.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/2fb27610b912c8fc769546e5fe039245d6882169.jpg -------------------------------------------------------------------------------- /public/gallary_sm/304be9c3a55a1b416cb91ada4875f0cb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/304be9c3a55a1b416cb91ada4875f0cb.jpg -------------------------------------------------------------------------------- /public/gallary_sm/347784364248d78f55c50f82fed7dd77.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/347784364248d78f55c50f82fed7dd77.jpg -------------------------------------------------------------------------------- /public/gallary_sm/36.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/36.jpg -------------------------------------------------------------------------------- /public/gallary_sm/3622f6ee4bdcc69e40b2fd2a54562122.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/3622f6ee4bdcc69e40b2fd2a54562122.jpg -------------------------------------------------------------------------------- /public/gallary_sm/472309f7905298227ea53ce9d5ca7bcb0a46d401.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/472309f7905298227ea53ce9d5ca7bcb0a46d401.jpg -------------------------------------------------------------------------------- /public/gallary_sm/57e853d9f2d3572c9c93a2f98813632762d0c35f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/57e853d9f2d3572c9c93a2f98813632762d0c35f.jpg -------------------------------------------------------------------------------- /public/gallary_sm/70ccd1fe9925bc31a8c823b35cdf8db1cb137039.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/70ccd1fe9925bc31a8c823b35cdf8db1cb137039.jpg -------------------------------------------------------------------------------- /public/gallary_sm/83146ca0gw1e5uv98fxwcj20c80nfdhs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/83146ca0gw1e5uv98fxwcj20c80nfdhs.jpg -------------------------------------------------------------------------------- /public/gallary_sm/97897383_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/97897383_2.jpg -------------------------------------------------------------------------------- /public/gallary_sm/a3d96e7c85580ec6aef37b242a9ed451.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/a3d96e7c85580ec6aef37b242a9ed451.jpg -------------------------------------------------------------------------------- /public/gallary_sm/aa18972bd40735fab975fa929c510fb30f240817.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/aa18972bd40735fab975fa929c510fb30f240817.jpg -------------------------------------------------------------------------------- /public/gallary_sm/ae8e9a18ab19d23f4bedbce2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/ae8e9a18ab19d23f4bedbce2.jpg -------------------------------------------------------------------------------- /public/gallary_sm/bdc7a825bc315c60dd857dca8fb1cb13495477b8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/bdc7a825bc315c60dd857dca8fb1cb13495477b8.jpg -------------------------------------------------------------------------------- /public/gallary_sm/d6ca7bcb0a46f21f78d01634f7246b600d33aef5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/d6ca7bcb0a46f21f78d01634f7246b600d33aef5.jpg -------------------------------------------------------------------------------- /public/gallary_sm/large_nKru_2391000169cf1260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/large_nKru_2391000169cf1260.jpg -------------------------------------------------------------------------------- /public/gallary_sm/m2w690hq92lt_large_LE4J_0156000035c81260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/m2w690hq92lt_large_LE4J_0156000035c81260.jpg -------------------------------------------------------------------------------- /public/gallary_sm/m2w690hq92lt_large_xlCV_77500001a647125f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/m2w690hq92lt_large_xlCV_77500001a647125f.jpg -------------------------------------------------------------------------------- /public/gallary_sm/m2w690hq92lt_original_sKaq_414f00003ce9118c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/m2w690hq92lt_original_sKaq_414f00003ce9118c.jpg -------------------------------------------------------------------------------- /public/gallary_sm/original_5fSW_59ff000093b9118c.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/original_5fSW_59ff000093b9118c.jpg -------------------------------------------------------------------------------- /public/gallary_sm/original_DVSi_2346000169651260.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/original_DVSi_2346000169651260.jpg -------------------------------------------------------------------------------- /public/gallary_sm/u=553037556,1932829573&fm=9&gp=0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/u=553037556,1932829573&fm=9&gp=0.jpg -------------------------------------------------------------------------------- /public/gallary_sm/无标题.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/无标题.jpg -------------------------------------------------------------------------------- /public/gallary_sm/未来.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/未来.JPG -------------------------------------------------------------------------------- /public/gallary_sm/科拉传奇.The.Legend.of.Korra.S01E12.Chi_Eng.WEB-HR.AAC.1024X576.x264-YYeTs&SLOMO[01-10-12].JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/gallary_sm/科拉传奇.The.Legend.of.Korra.S01E12.Chi_Eng.WEB-HR.AAC.1024X576.x264-YYeTs&SLOMO[01-10-12].JPG -------------------------------------------------------------------------------- /public/images/boat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/images/boat.png -------------------------------------------------------------------------------- /public/images/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/images/cloud.png -------------------------------------------------------------------------------- /public/images/default_avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/images/default_avatar.jpg -------------------------------------------------------------------------------- /public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/images/favicon.ico -------------------------------------------------------------------------------- /public/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/images/loading.gif -------------------------------------------------------------------------------- /public/images/wave-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/images/wave-back.png -------------------------------------------------------------------------------- /public/images/wave-front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/images/wave-front.png -------------------------------------------------------------------------------- /public/javascripts/exp/broadchat.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var ws, 3 | $chat = $("#chat"), 4 | $users = $("#users"), 5 | $logs = $("#logs"), 6 | curUser = $chat.attr("nick"); 7 | if (window.WebSocket === undefined) { 8 | $chat.text("您的浏览器不支持WebSocket!"); 9 | } 10 | if (window.ws) { 11 | ws.close(); 12 | } 13 | ws = new WebSocket("ws://localhost:3001"); 14 | ws.onopen = function(event) { 15 | $("#nickname").val("游客"); 16 | $logs.append("
您已加入版聊
"); 17 | }; 18 | ws.onclose = function(event) { 19 | $logs.append("
您已断开版聊
"); 20 | }; 21 | ws.onmessage = function(event) { 22 | var data = JSON.parse(event.data); 23 | if (data.type === "message") { 24 | $chat.append("

" + data.nick + "(" + data.time + "): " + data.message + "

"); 25 | } else if (data.type === "join") { 26 | if ($("p[uid='" + data.uid + "']", $users).length === 0) { 27 | $users.append("

" + data.nick + "

"); 28 | $logs.append("
" + data.nick + "加入了版聊
"); 29 | } 30 | } else if (data.type === "exit") { 31 | $("p[uid='" + data.uid + "']", $users).remove(); 32 | $logs.append("
" + data.nick + "离开了版聊
"); 33 | } else if (data.type === "nickname") { 34 | $("#nickname").val(data.nick); 35 | $("p[uid='" + data.uid + "']", $users).text(data.nick); 36 | $logs.append("
" + data.oldnick + " 修改昵称为 " + data.nick + "
"); 37 | } 38 | }; 39 | $("#send").click(function(event) { 40 | var message = $("#message").val(); 41 | if (message.trim() !== "") { 42 | ws.send(JSON.stringify({ 43 | time: new Date().getTime(), 44 | message: message, 45 | type: "message" 46 | })); 47 | $("#message").val(""); 48 | } 49 | }); 50 | $("#changeNick").click(function(event) { 51 | var nick = $("#nickname").val(); 52 | if (nick.trim() !== "") { 53 | ws.send(JSON.stringify({ 54 | nick: nick, 55 | type: "nickname" 56 | })); 57 | } 58 | }); 59 | $("#message").bind("keypress", function(event) { 60 | if ((event.keyCode || event.which) == 13) { 61 | $("#send").click(); 62 | } 63 | }).focus(); 64 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/articleDetail.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var $replyComment = $("#replyComment"), 3 | $comments = $("#comments"), 4 | $bookmark = $("#bookmark"), 5 | curUser = $comments.attr("curUser"), 6 | __readMoreComments = function(event) { 7 | var articleId = $comments.attr("aid"), 8 | curPage = Number($comments.attr("cur")), 9 | perPage = 10, 10 | commentContainer = $comments.find(".g-container"); 11 | $comments.find(".u-more").text("正在努力加载中...").unbind("click", __readMoreComments); 12 | $(document).trigger("comment.getByArticle", [articleId, curPage, perPage, 13 | function(err, comments) { 14 | var i, m, container, 15 | __deleteFn = function(container) { 16 | return function(event) { 17 | var comment = $(this).data("comment"); 18 | $(document).trigger("comment.remove", [comment.id, 19 | function(err) { 20 | if (err) return; 21 | container.fadeOut(function() { 22 | container.remove(); 23 | }); 24 | } 25 | ]); 26 | }; 27 | }, 28 | __replyFn = function(container) { 29 | return function(event) { 30 | var comment = $(this).data("comment"); 31 | $("textarea", $replyComment).val(""); 32 | if ($("form input[name='replyId']", $replyComment).val() !== comment.id) { 33 | $replyComment.slideUp(function() { 34 | container.find(".g-comment-row:first").append($replyComment); 35 | $replyComment.slideDown(function() { 36 | $("textarea", $replyComment).focus(); 37 | }); 38 | $("form input[name='replyId']").val(comment.id); 39 | }); 40 | } else { 41 | if ($replyComment.css("display") === "none") { 42 | $replyComment.slideDown(function() { 43 | $("textarea", $replyComment).focus(); 44 | }); 45 | } else { 46 | $replyComment.slideUp(); 47 | } 48 | } 49 | }; 50 | }, 51 | __commentFn = function(err, $comment) { 52 | var comment = $comment.data("comment"); 53 | if (comment.username !== curUser) { 54 | $comment.find("span[type='remove']").parent().remove(); 55 | } 56 | if (!curUser) { 57 | $comment.find("span[type='reply']").parent().remove(); 58 | } 59 | $(document).trigger("admire.draw", [$comment.data("comment").id, $comment.find(".u-admire").parent()]); 60 | }; 61 | if (err) { 62 | $comments.find(".u-more").text("获取评论失败"); 63 | return; 64 | } 65 | for (i = 0, m = comments.length; i < m; i++) { 66 | container = $("
").appendTo(commentContainer); 67 | $(document).trigger("comment.drawOne", [comments[i], container, [{ 68 | html: "删除", 69 | click: __deleteFn(container) 70 | }, { 71 | html: "回复", 72 | click: __replyFn(container) 73 | }, { 74 | html: "" 75 | }], 76 | __commentFn 77 | ]); 78 | } 79 | $comments.attr("cur", curPage + 1); 80 | if (comments.length < perPage) { 81 | $comments.find(".u-more").text("没有更多评论了"); 82 | } else { 83 | $comments.find(".u-more").text("点击获取更多评论").bind("click", __readMoreComments); 84 | } 85 | 86 | } 87 | ]); 88 | }; 89 | $('pre code').each(function(i, e) { 90 | hljs.highlightBlock(e); 91 | }); 92 | 93 | $("#clearComment").click(function(event) { 94 | $("#newComments textarea").val(""); 95 | }); 96 | 97 | $(document).trigger("tag.drawArticleTags", [$("#tags").attr("aid"), $("#tags")]); 98 | 99 | $(".g-art-info .u-avatar").each(function() { 100 | $(document).trigger("user.draw", [$(this).attr("uid"), $(this), 101 | function(err, $user) { 102 | if (err) return; 103 | var user = $user.data("user"); 104 | $(".g-art-info .u-nick").text(user.nickname); 105 | } 106 | ]); 107 | }); 108 | 109 | $comments.find(".u-more").click(__readMoreComments).click(); 110 | 111 | $(document).trigger("bookmark.draw", [$bookmark.attr("aid"), $bookmark, $bookmark.attr("cur")]); 112 | 113 | $("#deleteArticle").click(function(event) { 114 | $(document).trigger("article.remove", [$(this).attr("aid"), function(err){ 115 | if(err) return; 116 | window.location.href = "/article_list"; 117 | }]); 118 | }); 119 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/editArticle.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var converter = new Showdown.converter(), 3 | formValidate = $("#formValidate"), 4 | $articleTags = $("#articleTags"), 5 | $allTags = $("#allTags"), 6 | getWindowHeight = function() { 7 | if (window.innerHeight) 8 | return window.innerHeight; 9 | else if (document.documentElement && document.documentElement.clientHeight) 10 | return document.documentElement.clientHeight; 11 | else if (document.body) 12 | return document.body.clientHeight; 13 | }, 14 | __addToArticleTags = function(event) { 15 | var tag = event.data, 16 | $div = $("
" + tag.name + "
"), 17 | $existTag = $articleTags.find("span[tid='" + tag.id + "']"); 18 | $div.click(__removeFromArticleTags); 19 | if ($existTag.length === 0) { 20 | $articleTags.append($div); 21 | } else { 22 | $existTag.parent().removeClass("a-label-strike"); 23 | setTimeout(function() { 24 | $existTag.parent().addClass("a-label-strike"); 25 | }, 0); 26 | } 27 | }, 28 | __removeFromArticleTags = function(event) { 29 | $(this).remove(); 30 | }; 31 | 32 | $("#inputArticle").bind("keyup", function(event) { 33 | $("#outputArticle").html(converter.makeHtml(this.value)); 34 | $('pre code').each(function(i, e) { 35 | hljs.highlightBlock(e); 36 | }); 37 | }).trigger("change"); 38 | 39 | $(window).bind("resize", function(event) { 40 | $("body").height(getWindowHeight() - 150); 41 | $(".panel").height(getWindowHeight() - 350); 42 | }).trigger("resize"); 43 | 44 | $("#saveArtBtn").click(function(event) { 45 | var that = $(this), 46 | articleTags = $articleTags.find("span"), 47 | tags = [], 48 | i, m; 49 | formValidate.hide(); 50 | if (!$("#inputTitle").val() || $("#inputTitle").val() === "") { 51 | formValidate.text("标题不能为空").slideDown(); 52 | return false; 53 | } 54 | for (i = articleTags.length; i--;) { 55 | tags.push($(articleTags[i]).attr("tid")); 56 | } 57 | $.ajax({ 58 | url: "/nor/conf/article_update", 59 | data: { 60 | articleId: that.attr("aid"), 61 | title: $("#inputTitle").val(), 62 | content: $("#inputArticle").val(), 63 | tags: JSON.stringify(tags) 64 | }, 65 | type: "POST", 66 | dataType: "json" 67 | }).done(function(data) { 68 | window.location.href = "/article_load?articleId=" + that.attr("aid"); 69 | }).error(function(data) { 70 | console.log(data); 71 | }); 72 | }); 73 | 74 | $(document).trigger("tag.drawAllTags", [$allTags, __addToArticleTags]); 75 | 76 | $(document).trigger("tag.drawArticleTags", [$articleTags.attr("aid"), $articleTags, __removeFromArticleTags]); 77 | 78 | $("#createTag").click(function(event) { 79 | var name = $("#newTagInput").val(), 80 | color = $("#newTagInput").attr("color"); 81 | if (!name) { 82 | $("#newTagInput").addClass("has-error"); 83 | return false; 84 | } 85 | 86 | $(document).trigger("tag.createTag", [name, color, $allTags, __addToArticleTags, 87 | function(event) { 88 | $("#newTagInput").val(""); 89 | } 90 | ]); 91 | }); 92 | 93 | $(".u-label-picker").click(function(event) { 94 | $("#newTag").attr("class", "label b-label-" + $(this).attr("value")).find("input").attr("color", $(this).attr("color")); 95 | }); 96 | 97 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/global.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | $("#hasRemind").each(function() { 3 | var that = $(this); 4 | $(document).trigger("remind.countAll", [ 5 | 6 | function(err, total) { 7 | if (err) { 8 | that.text("获取消息失败"); 9 | } 10 | var $reminds; 11 | if (total === 0) { 12 | that.text("没有新消息"); 13 | } else { 14 | that.append("" + total + "").append("新消息").append(""); 15 | $reminds = $("").insertAfter(that); 16 | $(document).trigger("remind.draw", [$reminds]); 17 | } 18 | } 19 | ]); 20 | }); 21 | $(document).scroll(function(event) { 22 | if ($(window).scrollTop() > 100) { 23 | $("#scrollToTop").fadeIn(); 24 | } else { 25 | $("#scrollToTop").fadeOut(); 26 | } 27 | }); 28 | $("#scrollToTop").click(function(event) { 29 | $('html,body').animate({ 30 | scrollTop: 0 31 | }, 'slow'); 32 | return false; 33 | }); 34 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/index.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | $('pre code').each(function(i, e) { 3 | hljs.highlightBlock(e); 4 | }); 5 | 6 | $(".m-tags").each(function() { 7 | var that = $(this), 8 | articleId = that.attr("aid"); 9 | $(document).trigger("tag.drawArticleTags", [articleId, that]); 10 | }); 11 | 12 | $(".u-avatar").each(function() { 13 | var that = $(this); 14 | $(document).trigger("user.draw", [that.attr("uid"), that]); 15 | }); 16 | 17 | $(".u-comment").each(function() { 18 | $(document).trigger("comment.drawCount", [$(this).attr("aid"), $(this)]); 19 | }); 20 | 21 | $(".u-book").each(function() { 22 | $(document).trigger("bookmark.draw", [$(this).attr("aid"), $(this), $(this).attr("cur")]); 23 | }); 24 | 25 | $(".g-art-body .u-panel").click(function(event){ 26 | window.location.href = "/article_load?articleId=" + $(this).attr("aid"); 27 | }); 28 | 29 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/listArticle.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var curPage = 0, 3 | MAX_PANELS = $(window).width() >= 992?3:2, 4 | __draw = function(article) { 5 | var $row = $(".g-row:last"), 6 | $arts = $(".g-arts"), 7 | $art; 8 | if ($(".g-art", $row).length === MAX_PANELS || $row.length === 0) { 9 | $row = $("
").addClass("g-row"); 10 | $arts.append($row); 11 | } 12 | 13 | $art = $("
").addClass("u-panel g-art"); 14 | $art.append("
" + article.writeTime + "
") 15 | .append("
") 16 | .append("
" + article.title + "
") 17 | .click(function(event) { 18 | window.location.href = "/article_load?articleId=" + article.id; 19 | }); 20 | $(document).trigger("user.getInfo", [article.writer, 21 | function(err, user) { 22 | if (err) return; 23 | $(".u-avatar", $art).append(""); 24 | } 25 | ]); 26 | $row.append($art); 27 | }, 28 | __readMore = function(event) { 29 | $(document).unbind("scroll", __readMore); 30 | $(".u-more").text("正在加载..."); 31 | var perPage = 10; 32 | if ($(window).height() + $(window).scrollTop() >= $('body').height()) { 33 | $(document).trigger("article.getAll", [curPage, perPage, 34 | function(err, articles) { 35 | if (err) { 36 | return; 37 | } 38 | var i, m; 39 | for (i = 0, m = articles.length; i < m; i++) { 40 | __draw(articles[i]); 41 | } 42 | curPage++; 43 | if (articles.length < perPage) { 44 | $(".u-more").text("已经没有更多文章了"); 45 | } else { 46 | $(document).bind("scroll", __readMore); 47 | $(".u-more").text("向下滚动加载更多"); 48 | $(document).scroll(); 49 | } 50 | } 51 | ]); 52 | } 53 | }; 54 | $("pre code").each(function(i, e) { 55 | hljs.highlightBlock(e); 56 | }); 57 | $("#articles tbody tr").click(function(event) { 58 | var that = $(this); 59 | window.location.href = "article_load?articleId=" + that.attr("aid"); 60 | }); 61 | $(document).scroll(__readMore); 62 | $(document).scroll(); 63 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/listArticle_owner.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | $(".u-delete").click(function(event) { 3 | var that = $(this); 4 | $.ajax({ 5 | url: "/nor/conf/article_remove", 6 | data: { 7 | articleId: that.attr("aid") 8 | }, 9 | dataType: "json", 10 | type: "get", 11 | }).done(function(data) { 12 | if(data.success){ 13 | that.parent().parent().remove(); 14 | } 15 | }).fail(function(err) { 16 | console.log(err.message); 17 | }); 18 | event.stopPropagation(); 19 | }); 20 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/login.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var formValidate = $("#formValidate"); 3 | $("#loginForm").submit(function(event){ 4 | formValidate.hide(); 5 | if (!this.username.value) { 6 | formValidate.text("请输入用户名").slideDown(); 7 | $(this.username).focus(); 8 | return false; 9 | } 10 | if (!this.password.value.match(/^[\w\-\u4e00-\u9fa5]{3,12}$/)) { 11 | formValidate.text("请输入密码").slideDown(); 12 | $(this.password).focus(); 13 | return false; 14 | } 15 | $(this).find("button[type='submit']").text("登陆中...").attr("disabled","disabled"); 16 | }); 17 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/regist.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var formValidate = $("#formValidate"); 3 | $("#registForm input:first").focus(); 4 | $("#registForm").submit(function(event) { 5 | formValidate.hide(); 6 | if (!this.username.value.match(/^[\w]{5,15}$/)) { 7 | formValidate.text("用户名必须为长度为5~15的字母、数字或下划线").slideDown(); 8 | $(this.username).focus(); 9 | return false; 10 | } 11 | if (!this.nickname.value.match(/^[\w\-\u4e00-\u9fa5]{3,12}$/)) { 12 | formValidate.text("昵称必须为长度为3~12的中文、字母、数字、下划线").slideDown(); 13 | $(this.nickname).focus(); 14 | return false; 15 | } 16 | if (!this.password.value.match(/^[a-zA-Z0-9]{5,15}$/)) { 17 | formValidate.text("密码必须为长度为5~15的字母或数字").slideDown(); 18 | $(this.password).focus(); 19 | return false; 20 | } 21 | if (this.password.value !== this.passAgain.value) { 22 | formValidate.text("两次输入密码不一致,请检查").slideDown(); 23 | $(this.password).focus(); 24 | return false; 25 | } 26 | $(this).find("button[type='submit']").text("注册中...").attr("disabled","disabled"); 27 | }); 28 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/search.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var $tags = $("#tags"), 3 | $chosenTags = $("#chosenTags"), 4 | $articles = $("#articles"), 5 | tags = [], 6 | curPage = 0, 7 | perPage = 10, 8 | title = "", 9 | searchType, 10 | __chooseTag = function(event) { 11 | var that = $(this); 12 | $chosenTags.append(that); 13 | that.unbind("click", __chooseTag).bind("click", __unChooseTag); 14 | }, 15 | __unChooseTag = function(event) { 16 | var that = $(this); 17 | $tags.append(that); 18 | that.unbind("click", __unChooseTag).bind("click", __chooseTag); 19 | }, 20 | __drawArticle = function(article) { 21 | var $row = $('
'), 22 | $avatar = $('
'), 23 | $time = $('
').text(article.writeTime), 24 | $title = $('
').text(article.title); 25 | $row.append($avatar).append($time).append($title).click(function(event) { 26 | window.location.href = "/article_load?articleId=" + article.id; 27 | }); 28 | $(document).trigger("user.getInfo", [article.writer, 29 | function(err, user) { 30 | if (err) return; 31 | if (user) { 32 | $avatar.append('头像无法显示'); 33 | } 34 | } 35 | ]); 36 | $articles.append($row); 37 | }, 38 | __getMore = function(event) { 39 | var that = $(this), 40 | __searchCallback = function(err, articles) { 41 | if (err) { 42 | that.text("搜索发生错误"); 43 | return; 44 | } 45 | for (var i = 0, m = articles.length; i < m; i++) { 46 | __drawArticle(articles[i]); 47 | } 48 | if (articles.length < perPage) { 49 | that.text("已经没有更多的结果了"); 50 | } else { 51 | that.text("点击搜索更多").bind("click", __getMore); 52 | curPage++; 53 | } 54 | }; 55 | if (searchType === "tags") { 56 | if (tags.length > 0) { 57 | that.text("搜索中,请稍后").unbind("click", __getMore); 58 | $(document).trigger("article.getByTags", [tags, curPage, perPage, __searchCallback]); 59 | } 60 | } else if (searchType === "title") { 61 | console.log(title); 62 | if (title.trim()) { 63 | that.text("搜索中,请稍后").unbind("click", __getMore); 64 | $(document).trigger("article.getByTitle", [title, curPage, perPage, __searchCallback]); 65 | } 66 | } 67 | }; 68 | $(document).trigger("tag.drawAllTags", [$tags, __chooseTag]); 69 | $("#more").click(__getMore); 70 | 71 | $("#tagSearchBtn").click(function(event) { 72 | $articles.html(""); 73 | tags = []; 74 | $chosenTags.find(".label").each(function() { 75 | tags.push($(this).attr("tid")); 76 | }); 77 | curPage = 0; 78 | searchType = "tags"; 79 | $("#more").unbind("click", __getMore).bind("click", __getMore).click(); 80 | }); 81 | 82 | $("#titleSearchBtn").click(function(event) { 83 | $articles.html(""); 84 | title = $("#titleSearchInput").val(); 85 | curPage = 0; 86 | searchType = "title"; 87 | $("#more").unbind("click", __getMore).bind("click", __getMore).click(); 88 | }); 89 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/uploadPic.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var $uploadZone = $("#uploadZone"), 3 | $uploadOutput = $("#uploadOutput"), 4 | $uploadResult = $("#uploadResult"), 5 | __uploadCancel = function(event) { 6 | var that = $(this).parent(), 7 | fileName = that.attr("fileName"); 8 | $.ajax({ 9 | url: "/nor/conf/picture_uploadCancel", 10 | data: { 11 | fileName: fileName 12 | }, 13 | dataType: "json", 14 | type: "post" 15 | }).done(function(data) { 16 | that.fadeOut(function() { 17 | $(this).remove(); 18 | }); 19 | }).fail(function(err) { 20 | console.log(err); 21 | }); 22 | }, 23 | __uploadFile = function(file) { 24 | var $div = $("
"), 25 | reader = new FileReader(), 26 | form = new FormData(), 27 | xhr = new XMLHttpRequest(); 28 | $uploadOutput.prepend($div); 29 | reader.onload = __parseCallback($div); 30 | reader.readAsDataURL(file); 31 | form.append("image", file); 32 | xhr.open("post", "/nor/conf/picture_upload", true); 33 | xhr.onreadystatechange = function(event) { 34 | if (4 == this.readyState) { 35 | var data = JSON.parse(event.target.response); 36 | $div.attr("fileName", data.fileName); 37 | $div.find(".u-remove").click(__uploadCancel); 38 | } 39 | }; 40 | xhr.upload.addEventListener("progress", function(event) { 41 | $div.find(".u-process").text(event.loaded / event.total * 100 + "%"); 42 | }, false); 43 | xhr.send(form); 44 | }, 45 | __parseCallback = function($div) { 46 | return function(event) { 47 | $div.find("img").attr("src", event.target.result); 48 | }; 49 | }; 50 | 51 | $.event.props.push("dataTransfer"); 52 | 53 | $uploadZone.bind("dragover", function(event) { 54 | event.stopPropagation(); 55 | event.preventDefault(); 56 | event.dataTransfer.dropEffect = 'copy'; 57 | }); 58 | 59 | $uploadZone.bind("drop", function(event) { 60 | event.stopPropagation(); 61 | event.preventDefault(); 62 | var files = event.dataTransfer.files; 63 | 64 | for (var i = files.length; i--;) { 65 | if (!files[i].type.match(/image*/)) { 66 | continue; 67 | } 68 | __uploadFile(files[i]); 69 | } 70 | }); 71 | 72 | $("#uploadBtn").bind("click", function(event) { 73 | var imgs = []; 74 | $uploadOutput.find("div").each(function() { 75 | if ($(this).attr("fileName")) { 76 | imgs.push($(this).attr("fileName")); 77 | } 78 | }); 79 | $uploadResult.removeClass("alert-success alert-danger").hide(); 80 | if (imgs.length > 0) { 81 | $.ajax({ 82 | url: "/nor/conf/picture_confirm", 83 | type: "post", 84 | dataType: "json", 85 | data: { 86 | images: imgs 87 | } 88 | }).done(function(data) { 89 | $uploadOutput.find(".g-preview").fadeOut(function() { 90 | $uploadOutput.find(".g-preview").remove(); 91 | }); 92 | $uploadResult.addClass("alert-success").text("上传" + imgs.length + "张图片成功!").slideDown(); 93 | }).fail(function(err) { 94 | $uploadResult.addClass("alert-danger").text("上传图片失败!").slideDown(); 95 | }); 96 | } else { 97 | $uploadResult.addClass("alert-danger").text("没有选择图片!").slideDown(); 98 | } 99 | }); 100 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/userDetail.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var formValidate = $("#formValidate"), 3 | $allTags = $("#allTags"), 4 | $myTags = $("#myTags"), 5 | __addToMyTags = function(event) { 6 | var tag = event.data, 7 | $div = $("
" + tag.name + "
"); 8 | $existTag = $myTags.find("span[tid='" + tag.id + "']"); 9 | $div.click(__removeFromMyTags); 10 | if ($existTag.length === 0) { 11 | $myTags.append($div); 12 | } else { 13 | $existTag.parent().removeClass("a-label-strike"); 14 | setTimeout(function() { 15 | $existTag.parent().addClass("a-label-strike"); 16 | }, 0); 17 | } 18 | }, 19 | __removeFromMyTags = function(event) { 20 | $(this).remove(); 21 | }; 22 | $("#inputAvatar").change(function(event) { 23 | $("#avatarPreview").attr("src", $(this).val()); 24 | }); 25 | $("#detail").submit(function(event) { 26 | var that = $(this), 27 | mytags = $myTags.find("span"), 28 | tags = [], 29 | i, m; 30 | formValidate.hide(); 31 | if (!this.nickname.value) { 32 | formValidate.text("昵称不能为空").slideDown(); 33 | return false; 34 | } 35 | 36 | if (!this.nickname.value.match(/^[\w\-\u4e00-\u9fa5]{3,12}$/)) { 37 | formValidate.text("昵称必须为长度为3~12的中文、字母、数字、下划线").slideDown(); 38 | $(this.nickname).focus(); 39 | return false; 40 | } 41 | if (!this.password.value && this.password.value !== "") { 42 | if (!this.password.value.match(/^[a-zA-Z0-9]{5,15}$/)) { 43 | formValidate.text("密码必须为长度为5~15的字母或数字").slideDown(); 44 | $(this.password).focus(); 45 | return false; 46 | } 47 | if (this.password.value != this.passwordAgain.value) { 48 | formValidate.text("密码验证不正确,请重新填写").slideDown(); 49 | return false; 50 | } 51 | } 52 | for (i = mytags.length; i--;) { 53 | tags.push($(mytags[i]).attr("tid")); 54 | } 55 | this.tags.value = JSON.stringify(tags); 56 | }); 57 | 58 | $("#newTagInput").change(function() { 59 | $(this).removeClass("has-error"); 60 | }); 61 | 62 | $("#createTag").click(function(event) { 63 | var name = $("#newTagInput").val(), 64 | color = $("#newTagInput").attr("color"); 65 | if (!name) { 66 | $("#newTagInput").addClass("has-error"); 67 | return false; 68 | } 69 | $(document).trigger("tag.createTag", [name, color, $allTags,__addToMyTags,function(event) { 70 | $("#newTagInput").val(""); 71 | }]); 72 | }); 73 | 74 | $(document).trigger("tag.drawAllTags", [$allTags,__addToMyTags]); 75 | 76 | $(document).trigger("tag.drawUserTags", [$("#inputUsername").val(), $myTags, __removeFromMyTags]); 77 | 78 | $(".u-label-picker").click(function(event) { 79 | $("#newTag").attr("class", "label b-label-" + $(this).attr("value")).find("input").attr("color", $(this).attr("color")); 80 | }); 81 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/page/writeArticle.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var formValidate = $("#formValidate"), 3 | converter = new Showdown.converter({ 4 | extensions: 'twitter' 5 | }), 6 | $articleTags = $("#articleTags"), 7 | $allTags = $("#allTags"), 8 | __addToArticleTags = function(event) { 9 | var tag = event.data, 10 | $div = $("
" + tag.name + "
"), 11 | $existTag = $articleTags.find("span[tid='" + tag.id + "']"); 12 | $div.click(__removeFromArticleTags); 13 | if ($existTag.length === 0) { 14 | $articleTags.append($div); 15 | } else { 16 | $existTag.parent().removeClass("a-label-strike"); 17 | setTimeout(function() { 18 | $existTag.parent().addClass("a-label-strike"); 19 | }, 0); 20 | } 21 | }, 22 | __removeFromArticleTags = function(event) { 23 | $(this).remove(); 24 | }; 25 | 26 | getWindowHeight = function() { 27 | if (window.innerHeight) 28 | return window.innerHeight; 29 | else if (document.documentElement && document.documentElement.clientHeight) 30 | return document.documentElement.clientHeight; 31 | else if (document.body) 32 | return document.body.clientHeight; 33 | }; 34 | 35 | $("#inputArticle").bind("keyup", function(event) { 36 | $("#outputArticle").html(converter.makeHtml(this.value)); 37 | $('pre code').each(function(i, e) { 38 | hljs.highlightBlock(e); 39 | }); 40 | }); 41 | 42 | $(window).bind("resize", function(event) { 43 | $("body").height(getWindowHeight() - 150); 44 | $(".panel").height(getWindowHeight() - 350); 45 | }).trigger("resize"); 46 | 47 | $(document).trigger("tag.drawAllTags", [$allTags, __addToArticleTags]); 48 | 49 | $("#createTag").click(function(event) { 50 | var name = $("#newTagInput").val(), 51 | color = $("#newTagInput").attr("color"); 52 | if (!name) { 53 | $("#newTagInput").addClass("has-error"); 54 | return false; 55 | } 56 | 57 | $(document).trigger("tag.createTag", [name, color, $allTags, __addToArticleTags, 58 | function(err, $tag) { 59 | if (err) { 60 | alert("创建标签失败"); 61 | return; 62 | } 63 | $("#newTagInput").val(""); 64 | } 65 | ]); 66 | }); 67 | 68 | $(".u-label-picker").click(function(event) { 69 | $("#newTag").attr("class", "label b-label-" + $(this).attr("value")).find("input").attr("color", $(this).attr("color")); 70 | }); 71 | 72 | $("#articleForm").submit(function(event) { 73 | var that = $(this), 74 | articleTags = $articleTags.find("span"), 75 | tags = [], 76 | i, m; 77 | formValidate.hide(); 78 | if (!this.title.value) { 79 | formValidate.text("标题不能为空").slideDown(); 80 | return false; 81 | } 82 | for (i = articleTags.length; i--;) { 83 | tags.push($(articleTags[i]).attr("tid")); 84 | } 85 | this.tags.value = JSON.stringify(tags); 86 | }); 87 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/pageTools/Remind.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var emitter = $(document); 3 | emitter.bind({ 4 | "remind.remove": function(event, remindId, fnCallback) { 5 | $.ajax({ 6 | url: "/nor/remind_remove", 7 | type: "post", 8 | dataType: "json", 9 | data: { 10 | remindId: remindId 11 | } 12 | }).done(function(data) { 13 | if (typeof fnCallback === "function") fnCallback(null); 14 | }).fail(function(err) { 15 | if (typeof fnCallback === "function") fnCallback(err); 16 | }); 17 | }, 18 | "remind.countAll": function(event, fnCallback) { 19 | $.ajax({ 20 | url: "/nor/remind_countAll", 21 | type: "post", 22 | dataType: "json" 23 | }).done(function(data) { 24 | if (typeof fnCallback === "function") fnCallback(null, data.total); 25 | }).fail(function(err) { 26 | if (typeof fnCallback === "function") fnCallback(err); 27 | }); 28 | }, 29 | "remind.countByType": function(event, type, fnCallback) { 30 | $.ajax({ 31 | url: "/nor/remind_countByType", 32 | type: "post", 33 | dataType: "json", 34 | data: { 35 | type: type 36 | } 37 | }).done(function(data) { 38 | if (typeof fnCallback === "function") fnCallback(null, data.total); 39 | }).fail(function(err) { 40 | if (typeof fnCallback === "function") fnCallback(err); 41 | }); 42 | }, 43 | "remind.getAll": function(event, curPage, perPage, fnCallback) { 44 | $.ajax({ 45 | url: "/nor/remind_getAll", 46 | type: "post", 47 | dataType: "json", 48 | data: { 49 | curPage: curPage, 50 | perPage: perPage 51 | } 52 | }).done(function(data) { 53 | if (typeof fnCallback === "function") fnCallback(null, data.reminds); 54 | }).fail(function(err) { 55 | if (typeof fnCallback === "function") fnCallback(err); 56 | }); 57 | }, 58 | "remind.getByType": function(event, type, curPage, perPage, fnCallback) { 59 | $.ajax({ 60 | url: "/nor/remind_getByType", 61 | type: "post", 62 | dataType: "json", 63 | data: { 64 | type: type, 65 | curPage: curPage, 66 | perPage: perPage 67 | } 68 | }).done(function(data) { 69 | if (typeof fnCallback === "function") fnCallback(null, data.reminds); 70 | }).fail(function(err) { 71 | if (typeof fnCallback === "function") fnCallback(err); 72 | }); 73 | }, 74 | "remind.setReaded": function(event, remindIds, fnCallback) { 75 | $.ajax({ 76 | url: "/nor/remind_setReaded", 77 | type: "post", 78 | dataType: "json", 79 | data: { 80 | remindIds: remindIds 81 | } 82 | }).done(function(data) { 83 | if (typeof fnCallback === "function") fnCallback(null); 84 | }).fail(function(err) { 85 | if (typeof fnCallback === "function") fnCallback(err); 86 | }); 87 | }, 88 | "remind.draw": function(event, container, fnCallback) { 89 | container.addClass("b-remind-loading"); 90 | var i, 91 | __countComment = function(err, total) { 92 | if (err) { 93 | if (typeof fnCallback === "function") fnCallback(err); 94 | return; 95 | } 96 | var $li = $("
  • "); 97 | if (total) { 98 | $li.append(" " + total + " 条新回复"); 99 | container.append($li); 100 | } 101 | container.data("commentTotal", total); 102 | emitter.trigger("remind.countByType", ["bookmark", __countBookmark]); 103 | }, 104 | __countBookmark = function(err, total) { 105 | if (err) { 106 | if (typeof fnCallback === "function") fnCallback(err); 107 | return; 108 | } 109 | var $li = $("
  • "); 110 | if (total) { 111 | $li.append(" " + total + " 条新收藏消息"); 112 | container.append($li); 113 | } 114 | container.data("bookmarkTotal", total); 115 | emitter.trigger("remind.countByType", ["admire", __countAdmire]); 116 | }, 117 | __countAdmire = function(err, total) { 118 | if (err) { 119 | if (typeof fnCallback === "function") fnCallback(err); 120 | return; 121 | } 122 | var $li = $("
  • "); 123 | if (total) { 124 | $li.append(" " + total + " 条赞"); 125 | container.append($li); 126 | } 127 | container.data("admireTotal", total); 128 | container.removeClass("b-remind-loading"); 129 | if (typeof fnCallback === "function") fnCallback(null, container); 130 | }; 131 | emitter.trigger("remind.countByType", ["comment", __countComment]); 132 | } 133 | }); 134 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/pageTools/User.js: -------------------------------------------------------------------------------- 1 | (function($, window) { 2 | var emitter = $(document); 3 | emitter.bind({ 4 | "user.draw": function(event, username, container, fnCallback) { 5 | container.addClass("b-user-loading"); 6 | emitter.trigger("user.getInfo", [username, 7 | function(err, user) { 8 | if (err) { 9 | if (typeof fnCallback === "function") fnCallback(err); 10 | return; 11 | } 12 | var $a, 13 | $img, 14 | $tags; 15 | container = container; 16 | $a = $(""); 17 | $img = $(""); 18 | $a.append($img); 19 | container.append($a); 20 | $tags = $("
    "); 21 | $img.popover({ 22 | title: user.nickname, 23 | placement: "bottom", 24 | html: true, 25 | content: $tags 26 | }).hover(function(event) { 27 | $img.popover("show"); 28 | }, function(event) { 29 | $img.popover("hide"); 30 | }).bind("show.bs.popover", function() { 31 | $tags.html(""); 32 | $(document).trigger("tag.drawUserTags", [user.username, $tags]); 33 | }); 34 | container.removeClass("b-user-loading").data("user", user); 35 | if (typeof fnCallback === "function") fnCallback(null, container); 36 | } 37 | ]); 38 | }, 39 | "user.getInfo": function(event, username, fnCallback) { 40 | $.ajax({ 41 | url: "/user_getDetail", 42 | data: { 43 | username: username 44 | }, 45 | type: "post", 46 | dataType: "json" 47 | }).done(function(data) { 48 | if (typeof fnCallback === "function") fnCallback(null, data); 49 | }).fail(function(err) { 50 | if (typeof fnCallback === "function") fnCallback(err); 51 | }); 52 | } 53 | }); 54 | }(jQuery, window)); -------------------------------------------------------------------------------- /public/javascripts/tools/showdown_extensions/github.js: -------------------------------------------------------------------------------- 1 | // 2 | // Github Extension (WIP) 3 | // ~~strike-through~~ -> strike-through 4 | // 5 | 6 | (function(){ 7 | var github = function(converter) { 8 | return [ 9 | { 10 | // strike-through 11 | // NOTE: showdown already replaced "~" with "~T", so we need to adjust accordingly. 12 | type : 'lang', 13 | regex : '(~T){2}([^~]+)(~T){2}', 14 | replace : function(match, prefix, content, suffix) { 15 | return '' + content + ''; 16 | } 17 | } 18 | ]; 19 | }; 20 | 21 | // Client-side export 22 | if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.github = github; } 23 | // Server-side export 24 | if (typeof module !== 'undefined') module.exports = github; 25 | }()); 26 | -------------------------------------------------------------------------------- /public/javascripts/tools/showdown_extensions/prettify.js: -------------------------------------------------------------------------------- 1 | // 2 | // Google Prettify 3 | // A showdown extension to add Google Prettify (http://code.google.com/p/google-code-prettify/) 4 | // hints to showdown's HTML output. 5 | // 6 | 7 | (function(){ 8 | 9 | var prettify = function(converter) { 10 | return [ 11 | { type: 'output', filter: function(source){ 12 | 13 | return source.replace(/(
    )?/gi, function(match, pre) {
    14 |                     if (pre) {
    15 |                         return '
    ';
    16 |                     } else {
    17 |                         return '';
    18 |                     }
    19 |                 });
    20 |             }}
    21 |         ];
    22 |     };
    23 | 
    24 |     // Client-side export
    25 |     if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.prettify = prettify; }
    26 |     // Server-side export
    27 |     if (typeof module !== 'undefined') module.exports = prettify;
    28 | 
    29 | }());
    30 | 
    
    
    --------------------------------------------------------------------------------
    /public/javascripts/tools/showdown_extensions/table.js:
    --------------------------------------------------------------------------------
      1 | /*global module:true*/
      2 | /*
      3 |  * Basic table support with re-entrant parsing, where cell content
      4 |  * can also specify markdown.
      5 |  *
      6 |  * Tables
      7 |  * ======
      8 |  *
      9 |  * | Col 1   | Col 2                                              |
     10 |  * |======== |====================================================|
     11 |  * |**bold** | ![Valid XHTML] (http://w3.org/Icons/valid-xhtml10) |
     12 |  * | Plain   | Value                                              |
     13 |  *
     14 |  */
     15 | 
     16 | (function(){
     17 |   var table = function(converter) {
     18 |     var tables = {}, style = 'text-align:left;', filter; 
     19 |     tables.th = function(header){
     20 |       if (header.trim() === "") { return "";}
     21 |       var id = header.trim().replace(/ /g, '_').toLowerCase();
     22 |       return '' + header + '';
     23 |     };
     24 |     tables.td = function(cell) {
     25 |       return '' + converter.makeHtml(cell) + '';
     26 |     };
     27 |     tables.ths = function(){
     28 |       var out = "", i = 0, hs = [].slice.apply(arguments);
     29 |       for (i;i');
     65 |           hs = line.substring(1, line.length -1).split('|');
     66 |           tbl.push(tables.thead.apply(this, hs));
     67 |           line = lines[++i];
     68 |           if (!line.trim().match(/^[|]{1}[-=| ]+[|]{1}$/)) {
     69 |             // not a table rolling back
     70 |             line = lines[--i];
     71 |           }
     72 |           else {
     73 |             line = lines[++i];
     74 |             tbl.push('');
     75 |             while (line.trim().match(/^[|]{1}.*[|]{1}$/)) {
     76 |               line = line.trim();
     77 |               tbl.push(tables.tr.apply(this, line.substring(1, line.length -1).split('|')));
     78 |               line = lines[++i];
     79 |             }
     80 |             tbl.push('');
     81 |             tbl.push('');
     82 |             // we are done with this table and we move along
     83 |             out.push(tbl.join('\n'));
     84 |             continue;
     85 |           }
     86 |         }
     87 |         out.push(line);
     88 |       }             
     89 |       return out.join('\n');
     90 |     };
     91 |     return [
     92 |     { 
     93 |       type: 'lang', 
     94 |       filter: filter
     95 |     }
     96 |     ];
     97 |   };
     98 | 
     99 |   // Client-side export
    100 |   if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.table = table; }
    101 |   // Server-side export
    102 |   if (typeof module !== 'undefined') {
    103 |     module.exports = table;
    104 |   }
    105 | }());
    106 | 
    
    
    --------------------------------------------------------------------------------
    /public/javascripts/tools/showdown_extensions/twitter.js:
    --------------------------------------------------------------------------------
     1 | //
     2 | //  Twitter Extension
     3 | //  @username   ->  @username
     4 | //  #hashtag    ->  #hashtag
     5 | //
     6 | 
     7 | (function(){
     8 | 
     9 |     var twitter = function(converter) {
    10 |         return [
    11 | 
    12 |             // @username syntax
    13 |             { type: 'lang', regex: '\\B(\\\\)?@([\\S]+)\\b', replace: function(match, leadingSlash, username) {
    14 |                 // Check if we matched the leading \ and return nothing changed if so
    15 |                 if (leadingSlash === '\\') {
    16 |                     return match;
    17 |                 } else {
    18 |                     return '@' + username + '';
    19 |                 }
    20 |             }},
    21 | 
    22 |             // #hashtag syntax
    23 |             { type: 'lang', regex: '\\B(\\\\)?#([\\S]+)\\b', replace: function(match, leadingSlash, tag) {
    24 |                 // Check if we matched the leading \ and return nothing changed if so
    25 |                 if (leadingSlash === '\\') {
    26 |                     return match;
    27 |                 } else {
    28 |                     return '#' + tag + '';
    29 |                 }
    30 |             }},
    31 | 
    32 |             // Escaped @'s
    33 |             { type: 'lang', regex: '\\\\@', replace: '@' }
    34 |         ];
    35 |     };
    36 | 
    37 |     // Client-side export
    38 |     if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.twitter = twitter; }
    39 |     // Server-side export
    40 |     if (typeof module !== 'undefined') module.exports = twitter;
    41 | 
    42 | }());
    43 | 
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/github.css:
    --------------------------------------------------------------------------------
      1 | /*
      2 | 
      3 | github.com style (c) Vasily Polovnyov 
      4 | 
      5 | */
      6 | 
      7 | pre code {
      8 |   display: block; padding: 0.5em;
      9 |   color: #333;
     10 |   background: #f8f8ff
     11 | }
     12 | 
     13 | pre .comment,
     14 | pre .template_comment,
     15 | pre .diff .header,
     16 | pre .javadoc {
     17 |   color: #998;
     18 |   font-style: italic
     19 | }
     20 | 
     21 | pre .keyword,
     22 | pre .css .rule .keyword,
     23 | pre .winutils,
     24 | pre .javascript .title,
     25 | pre .nginx .title,
     26 | pre .subst,
     27 | pre .request,
     28 | pre .status {
     29 |   color: #333;
     30 |   font-weight: bold
     31 | }
     32 | 
     33 | pre .number,
     34 | pre .hexcolor,
     35 | pre .ruby .constant {
     36 |   color: #099;
     37 | }
     38 | 
     39 | pre .string,
     40 | pre .tag .value,
     41 | pre .phpdoc,
     42 | pre .tex .formula {
     43 |   color: #d14
     44 | }
     45 | 
     46 | pre .title,
     47 | pre .id,
     48 | pre .coffeescript .params,
     49 | pre .scss .preprocessor {
     50 |   color: #900;
     51 |   font-weight: bold
     52 | }
     53 | 
     54 | pre .javascript .title,
     55 | pre .lisp .title,
     56 | pre .clojure .title,
     57 | pre .subst {
     58 |   font-weight: normal
     59 | }
     60 | 
     61 | pre .class .title,
     62 | pre .haskell .type,
     63 | pre .vhdl .literal,
     64 | pre .tex .command {
     65 |   color: #458;
     66 |   font-weight: bold
     67 | }
     68 | 
     69 | pre .tag,
     70 | pre .tag .title,
     71 | pre .rules .property,
     72 | pre .django .tag .keyword {
     73 |   color: #000080;
     74 |   font-weight: normal
     75 | }
     76 | 
     77 | pre .attribute,
     78 | pre .variable,
     79 | pre .lisp .body {
     80 |   color: #008080
     81 | }
     82 | 
     83 | pre .regexp {
     84 |   color: #009926
     85 | }
     86 | 
     87 | pre .class {
     88 |   color: #458;
     89 |   font-weight: bold
     90 | }
     91 | 
     92 | pre .symbol,
     93 | pre .ruby .symbol .string,
     94 | pre .lisp .keyword,
     95 | pre .tex .special,
     96 | pre .prompt {
     97 |   color: #990073
     98 | }
     99 | 
    100 | pre .built_in,
    101 | pre .lisp .title,
    102 | pre .clojure .built_in {
    103 |   color: #0086b3
    104 | }
    105 | 
    106 | pre .preprocessor,
    107 | pre .pi,
    108 | pre .doctype,
    109 | pre .shebang,
    110 | pre .cdata {
    111 |   color: #999;
    112 |   font-weight: bold
    113 | }
    114 | 
    115 | pre .deletion {
    116 |   background: #fdd
    117 | }
    118 | 
    119 | pre .addition {
    120 |   background: #dfd
    121 | }
    122 | 
    123 | pre .diff .change {
    124 |   background: #0086b3
    125 | }
    126 | 
    127 | pre .chunk {
    128 |   color: #aaa
    129 | }
    130 | 
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/monokai.css:
    --------------------------------------------------------------------------------
      1 | /*
      2 | Monokai style - ported by Luigi Maselli - http://grigio.org
      3 | */
      4 | 
      5 | pre code {
      6 |   display: block; padding: 0.5em;
      7 |   background: #272822;
      8 | }
      9 | 
     10 | pre .tag,
     11 | pre .tag .title,
     12 | pre .keyword,
     13 | pre .literal,
     14 | pre .strong,
     15 | pre .change,
     16 | pre .winutils,
     17 | pre .flow,
     18 | pre .lisp .title,
     19 | pre .clojure .built_in,
     20 | pre .nginx .title,
     21 | pre .tex .special {
     22 |   color: #F92672;
     23 | }
     24 | 
     25 | pre code {
     26 |   color: #DDD;
     27 | }
     28 | 
     29 | pre code .constant {
     30 | 	color: #66D9EF;
     31 | }
     32 | 
     33 | pre .code,
     34 | pre .class .title,
     35 | pre .header {
     36 | 	color: white;
     37 | }
     38 | 
     39 | pre .link_label,
     40 | pre .attribute,
     41 | pre .symbol,
     42 | pre .symbol .string,
     43 | pre .value,
     44 | pre .regexp {
     45 | 	color: #BF79DB;
     46 | }
     47 | 
     48 | pre .link_url,
     49 | pre .tag .value,
     50 | pre .string,
     51 | pre .bullet,
     52 | pre .subst,
     53 | pre .title,
     54 | pre .emphasis,
     55 | pre .haskell .type,
     56 | pre .preprocessor,
     57 | pre .ruby .class .parent,
     58 | pre .built_in,
     59 | pre .sql .aggregate,
     60 | pre .django .template_tag,
     61 | pre .django .variable,
     62 | pre .smalltalk .class,
     63 | pre .javadoc,
     64 | pre .django .filter .argument,
     65 | pre .smalltalk .localvars,
     66 | pre .smalltalk .array,
     67 | pre .attr_selector,
     68 | pre .pseudo,
     69 | pre .addition,
     70 | pre .stream,
     71 | pre .envvar,
     72 | pre .apache .tag,
     73 | pre .apache .cbracket,
     74 | pre .tex .command,
     75 | pre .prompt {
     76 |   color: #A6E22E;
     77 | }
     78 | 
     79 | pre .comment,
     80 | pre .java .annotation,
     81 | pre .blockquote,
     82 | pre .horizontal_rule,
     83 | pre .python .decorator,
     84 | pre .template_comment,
     85 | pre .pi,
     86 | pre .doctype,
     87 | pre .deletion,
     88 | pre .shebang,
     89 | pre .apache .sqbracket,
     90 | pre .tex .formula {
     91 |   color: #75715E;
     92 | }
     93 | 
     94 | pre .keyword,
     95 | pre .literal,
     96 | pre .css .id,
     97 | pre .phpdoc,
     98 | pre .title,
     99 | pre .header,
    100 | pre .haskell .type,
    101 | pre .vbscript .built_in,
    102 | pre .sql .aggregate,
    103 | pre .rsl .built_in,
    104 | pre .smalltalk .class,
    105 | pre .diff .header,
    106 | pre .chunk,
    107 | pre .winutils,
    108 | pre .bash .variable,
    109 | pre .apache .tag,
    110 | pre .tex .special,
    111 | pre .request,
    112 | pre .status {
    113 |   font-weight: bold;
    114 | }
    115 | 
    116 | pre .coffeescript .javascript,
    117 | pre .javascript .xml,
    118 | pre .tex .formula,
    119 | pre .xml .javascript,
    120 | pre .xml .vbscript,
    121 | pre .xml .css,
    122 | pre .xml .cdata {
    123 |   opacity: 0.5;
    124 | }
    125 | 
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/admire.css:
    --------------------------------------------------------------------------------
     1 | .admired{
     2 | 	background-color: #f0f0f0
     3 | }
     4 | 
     5 | .b-admire-loading {
     6 | 	background: url("/images/loading.gif") no-repeat;
     7 | 	background-position: center;
     8 | 	min-height: 32px;
     9 | 	min-width: 32px
    10 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/articleDetail.css:
    --------------------------------------------------------------------------------
      1 | @media (max-width: 992px) {
      2 | 	div.g-art .g-art-body {
      3 | 		width: 100%;
      4 | 	}
      5 | }
      6 | 
      7 | .u-flag {
      8 | 	position: relative;
      9 | 	left : -50px;
     10 | 	height: 60px;
     11 | 	margin-bottom: 30px;
     12 | }
     13 | 
     14 | .u-flag .u-flag-left {
     15 | 	min-width: 300px;
     16 | 	max-width: 1000px;
     17 | 	height: 60px;
     18 | 	position: absolute;
     19 | 	padding: 0 20px;
     20 | 	background-color: #d9534f;
     21 | 	text-align: center;
     22 | 	color: white;
     23 | }
     24 | 
     25 | .u-flag .u-flag-left h3{
     26 | 	text-overflow: ellipsis;
     27 | 	white-space : nowrap;
     28 | 	overflow: hidden;
     29 | }
     30 | 
     31 | .u-flag .u-flag-left:before {
     32 | 	position: absolute;
     33 | 	display: block;
     34 | 	content : "";
     35 | 	right: -30px;
     36 | 	border-bottom : 30px solid #d9534f;
     37 | 	border-top : 30px solid #d9534f;
     38 | 	border-right : 30px solid transparent;
     39 | }
     40 | 
     41 | .u-flag .u-flag-left:after {
     42 | 	position: absolute;
     43 | 	display: block;
     44 | 	content : "";
     45 | 	width : 60px;
     46 | 	height: 30px;
     47 | 	left : -15px;
     48 | 	top: 21px;
     49 | 	background-color: #ac2925;
     50 | 	-webkit-transform : rotate(90deg) skew(-20deg);
     51 | 	   -moz-transform : rotate(90deg) skew(-20deg);
     52 | 	        transform : rotate(90deg) skew(-20deg);
     53 | 	z-index: -1;
     54 | }
     55 | 
     56 | .g-art-footer .u-bookmark {
     57 | 	float:right;
     58 | }
     59 | 
     60 | .u-more {
     61 | 	width: 100%;
     62 | 	background-color: #f0f0f0;
     63 | 	text-align: center;
     64 | 	padding: 10px;
     65 | 	border-bottom-right-radius: 20px;
     66 | 	border-bottom-left-radius: 20px;
     67 | 	cursor: pointer;
     68 | }
     69 | 
     70 | .u-more:hover {
     71 | 	background-color: rgb(66, 139, 202);
     72 | 	color: white;
     73 | }
     74 | 
     75 | .g-reply-form {
     76 | 	display: none;
     77 | 	margin-left: 100px;
     78 | 	margin-top:30px;
     79 | }
     80 | 
     81 | .g-art {
     82 | 	width: 100%;
     83 | 	margin-top: 40px;
     84 | }
     85 | 
     86 | .g-art:after {
     87 | 	display: table;
     88 | 	clear: both;
     89 | 	content: "";
     90 | }
     91 | 
     92 | .g-art .g-art-body {
     93 | 	float: left;
     94 | 	width: 73%;
     95 | }
     96 | 
     97 | .g-art .g-art-info {
     98 | 	float: right;
     99 | 	width: 25%;
    100 | }
    101 | 
    102 | .g-art .g-art-info .g-user .u-avatar{
    103 | 	float: right;
    104 | 	width: 33%;
    105 | }
    106 | 
    107 | .g-art .g-art-info .g-user .u-nick{
    108 | 	float: left;
    109 | 	width: 66%;
    110 | 	margin-top: 20px;
    111 | 
    112 | 	text-align: center;
    113 | 	font-weight: bolder;
    114 | 	font-size: 150%;
    115 | }
    116 | 
    117 | .g-art .g-art-info .u-time {
    118 | 	margin-top: 20px;
    119 | 	text-align: center;
    120 | 	font-weight: bolder;
    121 | 	font-size: 120%;
    122 | }
    123 | 
    124 | .g-art .g-art-info .u-tags {
    125 | 	margin-top: 20px;
    126 | }
    127 | 
    128 | 
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/bookmark.css:
    --------------------------------------------------------------------------------
     1 | .b-bookmark-loading {
     2 | 	background: url("/images/loading.gif") no-repeat;
     3 | 	background-position: center;
     4 | 	min-height: 32px;
     5 | 	min-width: 32px
     6 | }
     7 | 
     8 | .u-bookmark {
     9 | 	padding : 5px 10px;
    10 | 	border-radius: 10px;
    11 | 	cursor: pointer;
    12 | }
    13 | 
    14 | .b-bookmark-booked {
    15 | 	background-color: #f0f0f0;
    16 | }
    17 | 
    18 | .b-bookmark-book:hover{
    19 | 	background-color: #f0f0f0;
    20 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/comment.css:
    --------------------------------------------------------------------------------
      1 | .b-comment-loading {
      2 | 	background: url("/images/loading.gif") no-repeat;
      3 | 	background-position: center;
      4 | 	min-height: 32px;
      5 | 	min-width: 32px;
      6 | }
      7 | 
      8 | .g-comment-row {
      9 | 	width : 100%;
     10 | }
     11 | 
     12 | .g-comment-row .g-info {
     13 | 	display: block;
     14 | 	height: 30px;
     15 | 	margin-left : 100px;
     16 | 	line-height: 30px;
     17 | }
     18 | 
     19 | .g-comment-row .g-info .u-nick{
     20 | 	margin-right: 20px;
     21 | 	font-weight : bolder;
     22 | 	font-size: large
     23 | }
     24 | 
     25 | .g-comment-row .g-info .u-time{
     26 | 	float:right;
     27 | }
     28 | 
     29 | .g-comment-row .u-content {
     30 | 	display: block;
     31 | 	margin-left : 100px;
     32 | 	margin-top : 10px;
     33 | 	font-size: large
     34 | }
     35 | 
     36 | .g-comment-row .u-avatar {
     37 | 	float: left;
     38 | }
     39 | 
     40 | .g-comment-row .g-operate {
     41 | 	margin-left: 100px;
     42 | }
     43 | 
     44 | .g-comment-row .g-operate:after {
     45 | 	display: table;
     46 | 	content: '';
     47 | 	clear: both;
     48 | }
     49 | 
     50 | .g-comment-row .u-opt {
     51 | 	float:right;
     52 | 	margin-left : 10px;
     53 | 	line-height: 14px;
     54 | 	padding : 4px 6px;
     55 | 	border-radius: 4px;
     56 | 	cursor : pointer;
     57 | }
     58 | 
     59 | .g-comment-row .u-opt:hover {
     60 | 	background-color: #f0f0f0;
     61 | }
     62 | 
     63 | .g-comment-row .admired {
     64 | 	background-color: #f0f0f0;
     65 | }
     66 | 
     67 | .g-comment-row .u-opt span{
     68 | 	margin-left : 5px;
     69 | }
     70 | 
     71 | .b-comment-reply {
     72 | 	background: #f4f4f4;
     73 | 	padding: 10px 20px;
     74 | 	border-radius: 20px;
     75 | 	margin-bottom: 20px;
     76 | 	border: 2px dashed #8F8F8F;
     77 | }
     78 | 
     79 | .u-comment-count {
     80 | 	cursor: pointer;
     81 | }
     82 | 
     83 | .u-comment-count a:hover {
     84 | 	color:#333;
     85 | }
     86 | 
     87 | .u-comment-count a {
     88 | 	color:#333;
     89 | 	text-decoration: none
     90 | }
     91 | 
     92 | .a-comment-reply:hover {
     93 | 	-webkit-animation: borderchange 1s infinite;
     94 | 	-moz-animation: borderchange 1s infinite;
     95 | 	animation: borderchange 1s infinite;
     96 | }
     97 | 
     98 | @-webkit-keyframes borderchange{
     99 | 	0% {
    100 | 		border: 2px dashed #8F8F8F;
    101 | 	}
    102 | 	25% {
    103 | 		border: 2px dashed orange;
    104 | 	}
    105 | 	50% {
    106 | 		border: 2px dashed red;
    107 | 	}
    108 | 	75% {
    109 | 		border: 2px dashed blue;
    110 | 	}
    111 | 	100%{
    112 | 		border: 2px dashed #8F8F8F;
    113 | 	}
    114 | }
    115 | 
    116 | @-moz-keyframes borderchange{
    117 | 	0% {
    118 | 		border: 2px dashed #8F8F8F;
    119 | 	}
    120 | 	25% {
    121 | 		border: 2px dashed orange;
    122 | 	}
    123 | 	50% {
    124 | 		border: 2px dashed red;
    125 | 	}
    126 | 	75% {
    127 | 		border: 2px dashed blue;
    128 | 	}
    129 | 	100%{
    130 | 		border: 2px dashed #8F8F8F;
    131 | 	}
    132 | }
    133 | 
    134 | @keyframes borderchange{
    135 | 	0% {
    136 | 		border: 2px dashed #8F8F8F;
    137 | 	}
    138 | 	25% {
    139 | 		border: 2px dashed orange;
    140 | 	}
    141 | 	50% {
    142 | 		border: 2px dashed red;
    143 | 	}
    144 | 	75% {
    145 | 		border: 2px dashed blue;
    146 | 	}
    147 | 	100%{
    148 | 		border: 2px dashed #8F8F8F;
    149 | 	}
    150 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/gallary.css:
    --------------------------------------------------------------------------------
      1 | .u-pic {
      2 | 	position: relative;
      3 | 	border: 1px solid #f0f0f0;
      4 | 	box-shadow: 0 0 6px #f0f0f0;
      5 | 	display: block;
      6 | 	cursor: pointer;
      7 | }
      8 | 
      9 | .u-pic img {
     10 | 	width: 100%;
     11 | }
     12 | 
     13 | .u-pic:hover {
     14 | 	position: relative;
     15 | 	z-index: 100;
     16 | 	-webkit-animation : bigger 1s 1;
     17 | 	-webkit-transform: scale(1.25);
     18 | 	-moz-animation : bigger 1s 1;
     19 | 	-moz-transform: scale(1.25);
     20 | 	animation : bigger 1s 1;
     21 | 	transform: scale(1.25);
     22 | }
     23 | 
     24 | @-moz-keyframes bigger { /* firefox */
     25 | 	from {
     26 | 		-moz-transform: scale(1);
     27 | 	}
     28 | 	to {
     29 | 		-moz-transform: scale(1.25);
     30 | 	}
     31 | }
     32 | 
     33 | @-webkit-keyframes bigger { /*chrome & safari*/
     34 | 	from {
     35 | 		-webkit-transform: scale(1);
     36 | 	}
     37 | 	to {
     38 | 		-webkit-transform: scale(1.25);
     39 | 	}
     40 | }
     41 | 
     42 | @keyframes bigger {
     43 | 	from {
     44 | 		transform: scale(1);
     45 | 	}
     46 | 	to {
     47 | 		transform: scale(1.25);
     48 | 	}
     49 | }
     50 | 
     51 | 
     52 | .scrollFooter {
     53 | 	width: 100%;
     54 | 	border-radius: 10px;
     55 | 	height: 40px;
     56 | 	line-height: 35px;
     57 | 	text-align: center;
     58 | 	background-color: #f0f0f0;
     59 | 	display: none
     60 | }
     61 | 
     62 | .g-gal-col {
     63 | 	padding: 0
     64 | }
     65 | 
     66 | .u-block {
     67 | 	position: fixed;
     68 | 	width: 100%;
     69 | 	height: 100%;
     70 | 	left : 0;
     71 | 	top : 0;
     72 | 	background-color: rgba(240, 240, 240, 0.7);
     73 | 	z-index: 101;
     74 | 	display: none;
     75 | 	overflow: auto;
     76 | }
     77 | 
     78 | .u-fillPic {
     79 | 	position: absolute;
     80 | 	margin-left: 50%;
     81 | 	border: 1px solid #818181;
     82 | 	box-shadow: 3px 3px 8px #818181;
     83 | 	z-index: 200;
     84 | 	display: none;
     85 | 	width: 70%;
     86 | 	left: -35%;
     87 | 	background-color: #f0f0f0;
     88 | 	margin-top : 50px;
     89 | }
     90 | 
     91 | .u-fillPic .u-opt {
     92 | 	position : absolute;
     93 | 	width: 36px;
     94 | 	height: 36px;
     95 | 	font-size: 20px;
     96 | 	line-height: 36px;
     97 | 	text-align: center;
     98 | 	background-color: #f5f5f5;
     99 | 	color : #818181;
    100 | 	border: 1px solid #818181;
    101 | 	border-radius: 18px;
    102 | 	box-shadow: 3px 3px 8px #818181;
    103 | }
    104 | 
    105 | .u-fillPic .u-opt:hover {
    106 | 	background-color: #818181;
    107 | 	color : white;
    108 | }
    109 | 
    110 | .u-close {
    111 | 	top : -16px;
    112 | 	right : -16px;
    113 | }
    114 | 
    115 | .u-bigger{
    116 | 	top : 24px;
    117 | 	right : -16px;
    118 | }
    119 | 
    120 | .u-smaller{
    121 | 	top : 64px;
    122 | 	right : -16px;
    123 | }
    124 | 
    125 | .u-fillPic img{
    126 | 	max-width: 100%;
    127 | 	min-width: 300px;
    128 | }
    129 | 
    130 | .u-conf-opt {
    131 | 	position: fixed;
    132 | 	width: 100px;
    133 | 	height: 100px;
    134 | 	text-align: center;
    135 | 	line-height: 85px;
    136 | 	font-size: 60px;
    137 | 	border: 4px dotted #333;
    138 | 	border-radius: 20px;
    139 | }
    140 | 
    141 | .u-trash {
    142 | 	right: 10px;
    143 | 	top : 100px;
    144 | }
    145 | 
    146 | .u-upload {
    147 | 	left: 10px;
    148 | 	top : 100px;
    149 | }
    150 | 
    151 | .b-removing {
    152 | 	width: 100%;
    153 | 	height: 100%;
    154 | 	position: absolute;
    155 | 	background-color: rgba(0,0,0,0.7);
    156 | 	left: 0;
    157 | 	top: 0;
    158 | 	text-align: center;
    159 | 	font-size: 50px;
    160 | 	color: #f0f0f0;
    161 | 	font-weight: bolder;
    162 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/index.css:
    --------------------------------------------------------------------------------
     1 | .u-flag .u-flag-left a{
     2 | 	color : white;
     3 | 	text-decoration: none;
     4 | }
     5 | 
     6 | .u-flag .u-flag-left a:hover{
     7 | 	color : #f0f0f0;
     8 | }
     9 | 
    10 | .u-flag .u-flag-left a:active{
    11 | 	color : gray;
    12 | }
    13 | 
    14 | .g-art-footer .m-tags {
    15 | 	float: left;
    16 | 	width: 60%;
    17 | }
    18 | 
    19 | .g-art-footer .u-item {
    20 | 	float:right;
    21 | 	padding : 5px 10px;
    22 | 	border-radius: 10px;
    23 | }
    24 | 
    25 | .g-art-footer .u-item span{
    26 | 	margin-left: 5px;
    27 | }
    28 | 
    29 | .g-art-footer .u-item:hover{
    30 | 	background-color: #f0f0f0
    31 | }
    32 | 
    33 | .g-art-footer .u-booked {
    34 | 	background-color: #f0f0f0
    35 | }
    36 | 
    37 | .g-art-info {
    38 | 	height:200px;
    39 | 	float:left;
    40 | 	width: 20%;position:relative
    41 | }
    42 | 
    43 | .g-art-info .u-avatar {
    44 | 	position: absolute;
    45 | 	right: 20px;
    46 | 	top: 45px;
    47 | }
    48 | 
    49 | .g-art-info  .u-time {
    50 | 	position: absolute;
    51 | 	width: 100px;
    52 | 	right: 20px;
    53 | 	top: 120px;
    54 | 	font-weight: bolder;
    55 | 	text-align: right;
    56 | }
    57 | 
    58 | .g-art-body {
    59 | 	float:left;
    60 | 	width: 80%;
    61 | 	position:relative;
    62 | 	border-left: 3px solid #757575;
    63 | }
    64 | 
    65 | .g-art-body .u-panel {
    66 | 	margin-top: 20px;
    67 | 	min-height:200px;
    68 | 	margin-left: 20px;
    69 | 	cursor: pointer;
    70 | }
    71 | 
    72 | .g-art-body .u-panel:before {
    73 | 	content: "";
    74 | 	width: 20px;
    75 | 	height: 20px;
    76 | 	border-top: 20px solid transparent;
    77 | 	border-right: 20px solid rgba(255,255,255,0.8);
    78 | 	border-bottom: 20px solid transparent;
    79 | 	position: absolute;
    80 | 	left: 0px;
    81 | 	top: 55px;
    82 | }
    83 | 
    84 | .g-art-body .u-dot {
    85 | 	position: absolute;
    86 | 	width: 12px;
    87 | 	height: 12px;
    88 | 	border-radius: 50%;
    89 | 	background-color: #757575;
    90 | 	left: -7px;
    91 | 	top: 70px;
    92 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/listArticle.css:
    --------------------------------------------------------------------------------
      1 | @media (max-width: 992px){
      2 | 	div.g-row .g-art {
      3 | 		width: 35%;
      4 | 		margin-left: 10%;
      5 | 	}
      6 | 	div.g-row:nth-child(odd) .g-art:nth-child(1) {
      7 | 		margin-left: 0;
      8 | 	}
      9 | 
     10 | 	div.g-row:nth-child(even) .g-art:nth-child(1) {
     11 | 		margin-left: 10%;
     12 | 	}
     13 | }
     14 | 
     15 | .g-arts {
     16 | 	width: 100%;
     17 | 	float: left;
     18 | 	margin-top: 40px;
     19 | }
     20 | 
     21 | .g-arts .g-row {
     22 | 	width: 100%;
     23 | 	padding: 40px 0 0 0;
     24 | }
     25 | 
     26 | .g-arts .g-row:after {
     27 | 	display: table;
     28 | 	content: "";
     29 | 	clear: both;
     30 | }
     31 | 
     32 | .g-row .g-art {
     33 | 	position: relative;
     34 | 	float: left;
     35 | 	width: 22%;
     36 | 
     37 | 	margin-left: 11%;
     38 | 
     39 | 	cursor: pointer;
     40 | }
     41 | 
     42 | .g-row:nth-child(odd) .g-art:nth-child(1) {
     43 | 	margin-left: 0;
     44 | }
     45 | 
     46 | .g-row:nth-child(even) .g-art:nth-child(1) {
     47 | 	margin-left: 11%;
     48 | }
     49 | 
     50 | .g-row .g-art .u-time{
     51 | 	position: absolute;
     52 | 	left: 10%;
     53 | 	top: -10px;
     54 | 	height: 20px;
     55 | 	width: 60%;
     56 | 	
     57 | 	border-radius: 10px;
     58 | 	box-shadow: 2px 2px 2px #8A8A8A;
     59 | 
     60 | 	font-weight: bolder;
     61 | 	background-color: rgba(255,255,255,0.8);
     62 | 	text-align: center;
     63 | }
     64 | 
     65 | .g-row .g-art .u-title{
     66 | 	width: 100%;
     67 | 	
     68 | 	word-wrap: break-word;
     69 | 	font-size: 150%;
     70 | 	font-weight: bolder;
     71 | 	text-align: center;
     72 | }
     73 | 
     74 | .g-row .g-art .u-avatar{
     75 | 	position: absolute;
     76 | 	right: 10px;
     77 | 	top: -15px;
     78 | 	width: 30px;
     79 | 	height: 30px;
     80 | 	
     81 | 	border-radius: 50%;
     82 | 
     83 | 	box-shadow: 2px 2px 2px #8A8A8A;
     84 | 	overflow: hidden;
     85 | }
     86 | 
     87 | .g-row .g-art .u-avatar img{
     88 | 	width: 100%;
     89 | }
     90 | 
     91 | .g-row .g-art:hover {
     92 | 	-webkit-animation: art_rotate 1s linear infinite;
     93 | 	-moz-animation: art_rotate 1s linear infinite;
     94 | 	animation: art_rotate 1s linear infinite;
     95 | }
     96 | 
     97 | @-webkit-keyframes art_rotate {
     98 | 	0% 100% {
     99 | 		-webkit-transform: scale(1);
    100 | 	}
    101 | 	50% {
    102 | 		-webkit-transform: scale(1.2);
    103 | 	}
    104 | }
    105 | 
    106 | @-moz-keyframes art_rotate {
    107 | 	0% 100% {
    108 | 		-moz-transform: scale(1);
    109 | 	}
    110 | 	50% {
    111 | 		-moz-transform: scale(1.2);
    112 | 	}
    113 | }
    114 | 
    115 | @keyframes art_rotate {
    116 | 	0% 100% {
    117 | 		transform: scale(1);
    118 | 	}
    119 | 	50% {
    120 | 		transform: scale(1.2);
    121 | 	}
    122 | }
    123 | 
    124 | .u-more {
    125 | 	margin-top:20px;
    126 | 	float: right;
    127 | 	font-weight: bolder;
    128 | 	padding: 10px;
    129 | }
    130 | 
    131 | .u-more:hover {
    132 | 	color: white;
    133 | 	background-color: rgb(63, 93, 255);
    134 | 	cursor: pointer;
    135 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/remind.css:
    --------------------------------------------------------------------------------
    https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/stylesheets/page/remind.css
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/search.css:
    --------------------------------------------------------------------------------
     1 | .u-more {
     2 | 	width: 100%;
     3 | 	background-color: #428bca;
     4 | 	color:#fff;
     5 | 	text-align: center;
     6 | 	padding: 10px;
     7 | 	border-radius: 20px;
     8 | 	cursor: pointer;
     9 | }
    10 | 
    11 | .u-more:hover {
    12 | 	background-color: #8f8f8f;
    13 | 	color: #f0f0f0;
    14 | }
    15 | 
    16 | .g-row {
    17 | 	margin: 10px 10px 20px 10px;
    18 | 	padding: 10px;
    19 | 	border: 2px dashed #333;
    20 | 	border-radius: 10px;
    21 | 	color: #333;
    22 | 	cursor: pointer;
    23 | }
    24 | 
    25 | .g-row:after {
    26 | 	display: table;
    27 | 	content: "";
    28 | 	clear: both;
    29 | }
    30 | 
    31 | .g-row:hover {
    32 | 	background: #f0f0f0
    33 | }
    34 | 
    35 | 
    36 | .g-row .u-avatar {
    37 | 	float: left;
    38 | 	width: 60px;
    39 | 	height: 60px;
    40 | }
    41 | 
    42 | .g-row .u-avatar img {
    43 | 	height: 100%;
    44 | 	width: 100%;
    45 | 	border-radius: 50%;
    46 | 	box-shadow: 2px 2px 2px #333
    47 | }
    48 | 
    49 | .g-row .u-time {
    50 | 	margin-left: 80px;
    51 | 	width: calc(100% - 80px);
    52 | 
    53 | 	text-align: right;
    54 | 	font-weight: bolder;
    55 | 	font-size: 120%;
    56 | }
    57 | 
    58 | .g-row .u-title {
    59 | 	margin-left: 80px;
    60 | 	margin-bottom: 24px;
    61 | 	width: calc(100% - 80px);
    62 | 
    63 | 	text-align: center;
    64 | 	font-weight: bolder;
    65 | 	font-size: 180%;
    66 | }
    67 | 
    68 | .u-panel {
    69 | 	margin-top: 20px;
    70 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/tag.css:
    --------------------------------------------------------------------------------
      1 | .b-label-1 {
      2 | 	background-color: #428bca
      3 | }
      4 | 
      5 | .b-label-2 {
      6 | 	background-color: #5cb85c
      7 | }
      8 | 
      9 | .b-label-3 {
     10 | 	background-color: #5cb0de
     11 | }
     12 | 
     13 | .b-label-4 {
     14 | 	background-color: #f0ad4e
     15 | }
     16 | 
     17 | .b-label-5 {
     18 | 	background-color: #d9543f
     19 | }
     20 | 
     21 | .u-label-picker {
     22 | 	cursor: pointer;
     23 | 	margin: 5px;
     24 | 	font-size: 14px
     25 | }
     26 | 
     27 | .u-label {
     28 | 	font-size: 15px;
     29 | 	cursor: pointer;
     30 | }
     31 | 
     32 | .a-label-rotateX{
     33 | 	margin: 5px;
     34 | 	display: inline-block;
     35 | }
     36 | 
     37 | .a-label-rotateX:hover{
     38 | 	-webkit-animation: labelrotatex 1s linear infinite;
     39 | 		 -moz-animation: labelrotatex 1s linear infinite;
     40 | 					animation: labelrotatex 1s linear infinite;
     41 | }
     42 | 
     43 | @-webkit-keyframes labelrotatex{
     44 | 	from {
     45 | 		-webkit-transform : rotateX(0deg);
     46 | 	}
     47 | 	to {
     48 | 		-webkit-transform : rotateX(360deg);
     49 | 	}
     50 | }
     51 | 
     52 | @-moz-keyframes labelrotatex{
     53 | 	from {
     54 | 		-moz-transform : rotateX(0deg);
     55 | 	}
     56 | 	to {
     57 | 		-moz-transform : rotateX(360deg);
     58 | 	}
     59 | }
     60 | 
     61 | @keyframes labelrotatex{
     62 | 	from {
     63 | 		transform : rotateX(0deg);
     64 | 	}
     65 | 	to {
     66 | 		transform : rotateX(360deg);
     67 | 	}
     68 | }
     69 | 
     70 | .a-label-strike {
     71 | 	-webkit-animation: labelstrike 1s linear 3;
     72 | 		 -moz-animation: labelstrike 1s linear 3;
     73 | 					animation: labelstrike 1s linear 3;
     74 | }
     75 | 
     76 | @-webkit-keyframes labelstrike{
     77 | 	0% {
     78 | 		-webkit-transform : scale(1);
     79 | 	}
     80 | 	50%{
     81 | 		-webkit-transform : scale(1.25);
     82 | 	}
     83 | 	100% {
     84 | 		-webkit-transform : scale(1);
     85 | 	}
     86 | }
     87 | 
     88 | @-moz-keyframes labelstrike{
     89 | 	0% {
     90 | 		-moz-transform : scale(1);
     91 | 	}
     92 | 	50%{
     93 | 		-moz-transform : scale(1.25);
     94 | 	}
     95 | 	100% {
     96 | 		-moz-transform : scale(1);
     97 | 	}
     98 | }
     99 | 
    100 | @keyframes labelstrike{
    101 | 	0% {
    102 | 		transform : scale(1);
    103 | 	}
    104 | 	50%{
    105 | 		transform : scale(1.25);
    106 | 	}
    107 | 	100% {
    108 | 		transform : scale(1);
    109 | 	}
    110 | }
    111 | 
    112 | .b-label-loading {
    113 | 	background: url("/images/loading.gif") no-repeat;
    114 | 	background-position: center;
    115 | 	min-height: 32px;
    116 | 	min-width: 32px;
    117 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/uploadPic.css:
    --------------------------------------------------------------------------------
     1 | .u-upload {
     2 | 	width: 100%;
     3 | 	border : 2px dashed #bbb;
     4 | 	color : #bbb;
     5 | 	-webkit-border-radius: 5px;
     6 | 	   -moz-border-radius: 5px;
     7 | 	padding : 25px;
     8 | 	margin : 50px 0;
     9 | 	text-align: center;
    10 | 	font: 20px bold 'Vollkorn';
    11 | }
    12 | 
    13 | .uploadResult {
    14 | 	width: 100%;
    15 | 	height: 50px;
    16 | 	display: none
    17 | }
    18 | 
    19 | .g-preview {
    20 | 	position: relative;
    21 | 	height: 300px;
    22 | 	float: left;
    23 | }
    24 | 
    25 | .g-preview .u-process {
    26 | 	position: absolute;
    27 | 	width: 100%;
    28 | 	height: 100%;
    29 | 	line-height: 300px;
    30 | 	text-align: center;
    31 | 	font-size: 50px;
    32 | 	text-overflow: clip;
    33 | 	opacity: 0.7;
    34 | 	text-shadow: 0 0 6px #f0f0f0;
    35 | }
    36 | 
    37 | .g-preview .u-image {
    38 | 	height: 100%
    39 | }
    40 | 
    41 | .g-preview .u-remove {
    42 | 	position: absolute;
    43 | 	right : 0px;
    44 | 	top : 0px;
    45 | 	width: 36px;
    46 | 	height: 36px;
    47 | 	font-size: 20px;
    48 | 	line-height: 36px;
    49 | 	text-align: center;
    50 | 	background-color: #f5f5f5;
    51 | 	color : #818181;
    52 | 	border: 1px solid #818181;
    53 | 	border-radius: 18px;
    54 | 	box-shadow: 3px 3px 8px #818181;
    55 | }
    56 | 
    57 | .g-preview .u-remove:hover {
    58 | 	background-color: #818181;
    59 | 	color : white;
    60 | }
    61 | 
    62 | .u-output {
    63 | 	width: 100%;
    64 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/user.css:
    --------------------------------------------------------------------------------
     1 | .b-user-loading {
     2 | 	background: url("/images/loading.gif") no-repeat;
     3 | 	background-position: center;
     4 | 	min-height: 32px;
     5 | 	min-width: 32px
     6 | }
     7 | 
     8 | .u-user-avatar img {
     9 |   height: 60px;
    10 |   width: 60px;
    11 |   border-radius: 30px;
    12 |   box-shadow: 0 0 6px #707070
    13 | }
    14 | 
    15 | .u-user-tags {
    16 | 	width: 272px;
    17 | 	padding-right: 20px;
    18 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/userCenter.css:
    --------------------------------------------------------------------------------
      1 | .g-hide {
      2 | 	display: none
      3 | }
      4 | 
      5 | .g-item {
      6 | 	padding: 5px 10px
      7 | }
      8 | 
      9 | .g-item .u-avatar {
     10 | 	float: left;
     11 | }
     12 | .g-item .g-info {
     13 | 	margin-left : 100px;
     14 | 	height: 30px
     15 | }
     16 | .g-item .g-info .u-time{
     17 | 	float:left;
     18 | }
     19 | 
     20 | .g-item .g-info .u-nick{
     21 | 	font-size: 120%;
     22 | 	font-weight: bolder;
     23 | }
     24 | 
     25 | .g-item .g-info .u-opt{
     26 | 	float:right;
     27 | 	padding : 5px 10px;
     28 | 	border-radius: 10px;
     29 | 	color: black;
     30 | 	cursor: pointer;
     31 | 	text-decoration: none
     32 | }
     33 | 
     34 | .g-item .g-info .u-opt:hover{
     35 | 	background-color: #f0f0f0
     36 | }
     37 | 
     38 | .g-item .u-title {
     39 | 	margin-left : 60px;
     40 | 	text-align: center
     41 | }
     42 | 
     43 | .g-item .u-title a{
     44 | 	text-decoration: none;
     45 | 	font-size: 150%
     46 | }
     47 | 
     48 | .g-item .u-time {
     49 | 	text-align: right
     50 | }
     51 | 
     52 | .g-item .u-content {
     53 | 	margin-left : 100px;
     54 | 	text-align: left;
     55 | }
     56 | 
     57 | .u-noitem {
     58 | 	text-align: center
     59 | }
     60 | 
     61 | .a-fliker {
     62 | 	display: inline-block;
     63 | 	-webkit-animation: labelfliker 2s infinite;
     64 | 	-moz-animation: labelfliker 2s infinite;
     65 | 	animation: labelfliker 2s infinite;
     66 | }
     67 | 
     68 | .u-more {
     69 | 	width: 100%;
     70 | 	background-color: #428bca;
     71 | 	color:#fff;
     72 | 	text-align: center;
     73 | 	padding: 10px;
     74 | 	border-radius: 20px;
     75 | 	cursor: pointer;
     76 | }
     77 | 
     78 | .u-more:hover {
     79 | 	background-color: #8f8f8f;
     80 | 	color: #f0f0f0;
     81 | }
     82 | 
     83 | @-moz-keyframes labelfliker {
     84 | 	0% {
     85 | 		-moz-transform : scale(1);
     86 | 	}
     87 | 	50% {
     88 | 		-moz-transform : scale(1.15);
     89 | 	}
     90 | 	100% {
     91 | 		-moz-transform : scale(1);
     92 | 	}
     93 | }
     94 | 
     95 | @-webkit-keyframes labelfliker {
     96 | 	0% {
     97 | 		-webkit-transform : scale(1);
     98 | 	}
     99 | 	50% {
    100 | 		-webkit-transform : scale(1.15);
    101 | 	}
    102 | 	100% {
    103 | 		-webkit-transform : scale(1);
    104 | 	}
    105 | }
    106 | 
    107 | @keyframes labelfliker {
    108 | 	0% {
    109 | 		transform : scale(1);
    110 | 	}
    111 | 	50% {
    112 | 		transform : scale(1.15);
    113 | 	}
    114 | 	100% {
    115 | 		transform : scale(1);
    116 | 	}
    117 | }
    118 | 
    119 | .g-row {
    120 | 	width: 100%;
    121 | }
    122 | 
    123 | .g-row:after {
    124 | 	display: table;
    125 | 	content: "";
    126 | 	clear: both;
    127 | }
    128 | 
    129 | .g-row .g-left {
    130 | 	float: left;
    131 | 	width: 25%;
    132 | }
    133 | 
    134 | .g-row .g-right {
    135 | 	float: right;
    136 | 	width: 73%;
    137 | }
    138 | 
    139 | .list-group .list-group-item {
    140 | 	background: transparent;
    141 | }
    142 | 
    143 | .list-group .list-group-item.active {
    144 | 	background: rgb(66, 139, 202)
    145 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/userDetail.css:
    --------------------------------------------------------------------------------
    https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/public/stylesheets/page/userDetail.css
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/page/writeArticle.css:
    --------------------------------------------------------------------------------
     1 | .u-panel-body {
     2 | 	margin: 0;
     3 | 	padding: 0;
     4 | 	position: relative;
     5 | 	width: 47.5%;
     6 | 	overflow: auto;
     7 | 	height: 100%;
     8 | }
     9 | 
    10 | #leftPanel {
    11 | 	float: left;
    12 | 	left : 1.5%;
    13 | }
    14 | 
    15 | #rightPanel {
    16 | 	float: right;
    17 | 	right : 1.5%;
    18 | 	padding: 2px;
    19 | }
    20 | 
    21 | #outputArticle {
    22 | 	overflow: auto;
    23 | }
    24 | 
    25 | .u-pane {
    26 | 	margin: 0;
    27 | 	padding: 0;
    28 | 	padding-left: 4px;
    29 | 	width: 100%;
    30 | 	border: none;
    31 | 	display: block;
    32 | 	border: 1px solid #888;
    33 | 	border-right: 1px solid #000;
    34 | 	border-bottom: 1px solid #000;
    35 | 	height: 100%;
    36 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/pageTools/admire.css:
    --------------------------------------------------------------------------------
     1 | .admired{
     2 | 	background-color: #f0f0f0
     3 | }
     4 | 
     5 | .b-admire-loading {
     6 | 	background: url("/images/loading.gif") no-repeat;
     7 | 	background-position: center;
     8 | 	min-height: 32px;
     9 | 	min-width: 32px
    10 | }
    11 | 
    12 | .g-admire-row {
    13 | 	width: 100%;
    14 | 	font-size: 14px;
    15 | }
    16 | 
    17 | .g-admire-row .g-info {
    18 | 	display: block;
    19 | 	height: 30px;
    20 | 	margin-left : 100px;
    21 | 	line-height: 30px;
    22 | }
    23 | 
    24 | .g-admire-row .g-info:after {
    25 | 	display: table;
    26 | 	clear: both;
    27 | 	content: "";
    28 | }
    29 | 
    30 | .g-admire-row .g-info .u-nick{
    31 | 	float: left;
    32 | 	width: 50%;
    33 | 	font-weight : bolder;
    34 | 	font-size: large
    35 | }
    36 | 
    37 | .g-admire-row .g-info .u-time{
    38 | 	float:right;
    39 | 	width: 50%;
    40 | 	text-align: right
    41 | }
    42 | 
    43 | .g-admire-row .u-comment {
    44 | 	display: block;
    45 | 	margin-left : 100px;
    46 | 	margin-top : 10px;
    47 | 	font-size: large;
    48 | 	border: 2px dashed #8F8F8F;
    49 | 	border-radius: 20px;
    50 | 	padding: 10px;
    51 | 	margin-bottom: 10px
    52 | }
    53 | 
    54 | .g-admire-row .u-avatar {
    55 | 	float: left;
    56 | }
    57 | 
    58 | .g-admire-row .g-operate {
    59 | 	margin-left: 100px;
    60 | 	height: 25px;
    61 | }
    62 | 
    63 | .g-admire-row .g-operate:after {
    64 | 	display: table;
    65 | 	content: '';
    66 | 	clear: both;
    67 | }
    68 | 
    69 | .g-admire-row .u-opt {
    70 | 	float:right;
    71 | 	margin-left : 10px;
    72 | 	line-height: 14px;
    73 | 	padding : 4px 6px;
    74 | 	border-radius: 4px;
    75 | 	cursor : pointer;
    76 | }
    77 | 
    78 | .g-admire-row .u-opt:hover {
    79 | 	background-color: #f0f0f0;
    80 | }
    81 | 
    82 | .g-admire-row .u-opt{
    83 | 	text-decoration: none;
    84 | 	color:#333;
    85 | }
    86 | 
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/pageTools/article.css:
    --------------------------------------------------------------------------------
     1 | .b-article-loading {
     2 | 	background: url("/images/loading.gif") no-repeat;
     3 | 	background-position: center;
     4 | 	min-height: 32px;
     5 | 	min-width: 32px
     6 | }
     7 | 
     8 | .g-article-row {
     9 | 	width: 100%;
    10 | 	font-size: 14px;
    11 | }
    12 | 
    13 | .g-article-row .g-info {
    14 | 	display: block;
    15 | 	height: 30px;
    16 | 	margin-left : 100px;
    17 | 	line-height: 30px;
    18 | }
    19 | 
    20 | .g-article-row .g-info .u-nick{
    21 | 	margin-right: 20px;
    22 | 	font-weight : bolder;
    23 | 	font-size: large
    24 | }
    25 | 
    26 | .g-article-row .g-info .u-time{
    27 | 	float:right;
    28 | }
    29 | 
    30 | .g-article-row .u-title {
    31 | 	display: block;
    32 | 	margin-left : 100px;
    33 | 	margin-top : 10px;
    34 | 	font-size: 150%;
    35 | 	font-weight: bolder;
    36 | 	text-align: center;
    37 | 	margin-bottom: 10px
    38 | }
    39 | 
    40 | .g-article-row .u-avatar {
    41 | 	float: left;
    42 | }
    43 | 
    44 | .g-article-row .g-operate {
    45 | 	margin-left: 100px;
    46 | 	height: 25px;
    47 | }
    48 | 
    49 | .g-article-row .g-operate:after {
    50 | 	display: table;
    51 | 	content: '';
    52 | 	clear: both;
    53 | }
    54 | 
    55 | .g-article-row .u-opt {
    56 | 	float:right;
    57 | 	margin-left : 10px;
    58 | 	line-height: 14px;
    59 | 	padding : 4px 6px;
    60 | 	border-radius: 4px;
    61 | 	cursor : pointer;
    62 | }
    63 | 
    64 | .g-article-row .u-opt:hover {
    65 | 	background-color: #f0f0f0;
    66 | }
    67 | 
    68 | .g-article-row .u-opt{
    69 | 	text-decoration: none;
    70 | 	color:#333;
    71 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/pageTools/bookmark.css:
    --------------------------------------------------------------------------------
     1 | .b-bookmark-loading {
     2 | 	background: url("/images/loading.gif") no-repeat;
     3 | 	background-position: center;
     4 | 	min-height: 32px;
     5 | 	min-width: 32px
     6 | }
     7 | 
     8 | .u-bookmark {
     9 | 	padding : 5px 10px;
    10 | 	border-radius: 10px;
    11 | 	cursor: pointer;
    12 | }
    13 | 
    14 | .b-bookmark-booked, .b-bookmark-book:hover {
    15 | 	background-color: rgba(66, 139, 202, 0.7);
    16 | 	color: white;
    17 | }
    18 | 
    19 | .g-bookmark-row {
    20 | 	width: 100%;
    21 | 	font-size: 14px;
    22 | }
    23 | 
    24 | .g-bookmark-row .g-info {
    25 | 	display: block;
    26 | 	height: 30px;
    27 | 	margin-left : 100px;
    28 | 	line-height: 30px;
    29 | }
    30 | 
    31 | .g-bookmark-row .g-info:after {
    32 | 	display: table;
    33 | 	clear: both;
    34 | 	content: "";
    35 | }
    36 | 
    37 | .g-bookmark-row .g-info .u-nick{
    38 | 	float: left;
    39 | 	width: 50%;
    40 | 	font-weight : bolder;
    41 | 	font-size: large
    42 | }
    43 | 
    44 | .g-bookmark-row .g-info .u-time{
    45 | 	float:right;
    46 | 	width: 50%;
    47 | 	text-align: right
    48 | }
    49 | 
    50 | .g-bookmark-row .u-comment {
    51 | 	display: block;
    52 | 	margin-left : 100px;
    53 | 	margin-top : 10px;
    54 | 	font-size: large;
    55 | 	border: 2px dashed #8F8F8F;
    56 | 	border-radius: 20px;
    57 | 	padding: 10px;
    58 | 	margin-bottom: 10px
    59 | }
    60 | 
    61 | .g-bookmark-row .u-avatar {
    62 | 	float: left;
    63 | }
    64 | 
    65 | .g-bookmark-row .g-operate {
    66 | 	margin-left: 100px;
    67 | 	height: 25px;
    68 | }
    69 | 
    70 | .g-bookmark-row .g-operate:after {
    71 | 	display: table;
    72 | 	content: '';
    73 | 	clear: both;
    74 | }
    75 | 
    76 | .g-bookmark-row .u-opt {
    77 | 	float:right;
    78 | 	margin-left : 10px;
    79 | 	line-height: 14px;
    80 | 	padding : 4px 6px;
    81 | 	border-radius: 4px;
    82 | 	cursor : pointer;
    83 | }
    84 | 
    85 | .g-bookmark-row .u-opt:hover {
    86 | 	background-color: #f0f0f0;
    87 | }
    88 | 
    89 | .g-bookmark-row .u-opt{
    90 | 	text-decoration: none;
    91 | 	color:#333;
    92 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/pageTools/comment.css:
    --------------------------------------------------------------------------------
      1 | @media (max-width: 992px) {
      2 | 	div.b-comment-reply {
      3 | 		padding: 5px 10px;
      4 | 	}
      5 | }
      6 | 
      7 | .b-comment-loading {
      8 | 	background: url("/images/loading.gif") no-repeat;
      9 | 	background-position: center;
     10 | 	min-height: 32px;
     11 | 	min-width: 32px;
     12 | }
     13 | 
     14 | .g-comment-row {
     15 | 	width : 100%;
     16 | 	font-size: 14px;
     17 | }
     18 | 
     19 | .g-comment-row .g-info {
     20 | 	display: block;
     21 | 	height: 30px;
     22 | 	margin-left : 100px;
     23 | 	line-height: 30px;
     24 | }
     25 | 
     26 | .g-comment-row .g-info:after{
     27 | 	display: table;
     28 | 	content: "";
     29 | 	clear: both;
     30 | }
     31 | 
     32 | 
     33 | .g-comment-row .g-info .u-nick{
     34 | 	float: left;
     35 | 	width: 50%;
     36 | 	font-weight : bolder;
     37 | 	font-size: large
     38 | }
     39 | 
     40 | .g-comment-row .g-info .u-time{
     41 | 	width: 50%;
     42 | 	float:right;
     43 | 	text-align: right;
     44 | }
     45 | 
     46 | .g-comment-row .u-content {
     47 | 	display: block;
     48 | 	margin-left : 100px;
     49 | 	margin-top : 10px;
     50 | 	font-size: large
     51 | }
     52 | 
     53 | .g-comment-row .u-avatar {
     54 | 	float: left;
     55 | }
     56 | 
     57 | .g-comment-row .g-operate {
     58 | 	margin-left: 100px;
     59 | 	height: 25px;
     60 | }
     61 | 
     62 | .g-comment-row .g-operate:after {
     63 | 	display: table;
     64 | 	content: '';
     65 | 	clear: both;
     66 | }
     67 | 
     68 | .g-comment-row .u-opt {
     69 | 	float:right;
     70 | 	margin-left : 10px;
     71 | 	line-height: 14px;
     72 | 	padding : 4px 6px;
     73 | 	border-radius: 4px;
     74 | 	cursor : pointer;
     75 | }
     76 | 
     77 | .g-comment-row .u-opt:hover, div.g-comment-row .admired{
     78 | 	background-color: rgba(66, 139, 202, 0.7);
     79 | 	color: white;
     80 | }
     81 | 
     82 | .g-comment-row .u-opt{
     83 | 	text-decoration: none;
     84 | 	color:#333;
     85 | }
     86 | 
     87 | .g-comment-row .u-opt span{
     88 | 	margin-left : 5px;
     89 | }
     90 | 
     91 | .b-comment-reply {
     92 | 	background: #f4f4f4;
     93 | 	padding: 10px 20px;
     94 | 	border-radius: 20px;
     95 | 	margin-bottom: 20px;
     96 | 	border: 2px dashed #8F8F8F;
     97 | }
     98 | 
     99 | .u-comment-count {
    100 | 	cursor: pointer;
    101 | }
    102 | 
    103 | .u-comment-count a:hover {
    104 | 	color:#333;
    105 | }
    106 | 
    107 | .u-comment-count a {
    108 | 	color:#333;
    109 | 	text-decoration: none
    110 | }
    111 | 
    112 | .a-comment-reply:hover {
    113 | 	-webkit-animation: borderchange 1s infinite;
    114 | 	-moz-animation: borderchange 1s infinite;
    115 | 	animation: borderchange 1s infinite;
    116 | }
    117 | 
    118 | @-webkit-keyframes borderchange{
    119 | 	0% {
    120 | 		border: 2px dashed #8F8F8F;
    121 | 	}
    122 | 	25% {
    123 | 		border: 2px dashed orange;
    124 | 	}
    125 | 	50% {
    126 | 		border: 2px dashed red;
    127 | 	}
    128 | 	75% {
    129 | 		border: 2px dashed blue;
    130 | 	}
    131 | 	100%{
    132 | 		border: 2px dashed #8F8F8F;
    133 | 	}
    134 | }
    135 | 
    136 | @-moz-keyframes borderchange{
    137 | 	0% {
    138 | 		border: 2px dashed #8F8F8F;
    139 | 	}
    140 | 	25% {
    141 | 		border: 2px dashed orange;
    142 | 	}
    143 | 	50% {
    144 | 		border: 2px dashed red;
    145 | 	}
    146 | 	75% {
    147 | 		border: 2px dashed blue;
    148 | 	}
    149 | 	100%{
    150 | 		border: 2px dashed #8F8F8F;
    151 | 	}
    152 | }
    153 | 
    154 | @keyframes borderchange{
    155 | 	0% {
    156 | 		border: 2px dashed #8F8F8F;
    157 | 	}
    158 | 	25% {
    159 | 		border: 2px dashed orange;
    160 | 	}
    161 | 	50% {
    162 | 		border: 2px dashed red;
    163 | 	}
    164 | 	75% {
    165 | 		border: 2px dashed blue;
    166 | 	}
    167 | 	100%{
    168 | 		border: 2px dashed #8F8F8F;
    169 | 	}
    170 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/pageTools/remind.css:
    --------------------------------------------------------------------------------
    1 | .b-remind-loading {
    2 | 	background: url("/images/loading.gif") no-repeat;
    3 | 	background-position: center;
    4 | 	min-height: 32px;
    5 | 	min-width: 32px
    6 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/pageTools/tag.css:
    --------------------------------------------------------------------------------
      1 | .b-label-1 {
      2 | 	background-color: #428bca
      3 | }
      4 | 
      5 | .b-label-2 {
      6 | 	background-color: #5cb85c
      7 | }
      8 | 
      9 | .b-label-3 {
     10 | 	background-color: #5cb0de
     11 | }
     12 | 
     13 | .b-label-4 {
     14 | 	background-color: #f0ad4e
     15 | }
     16 | 
     17 | .b-label-5 {
     18 | 	background-color: #d9543f
     19 | }
     20 | 
     21 | .u-label-picker {
     22 | 	cursor: pointer;
     23 | 	margin: 5px;
     24 | 	font-size: 14px;
     25 | 	display: inline-block;
     26 | }
     27 | 
     28 | .u-label {
     29 | 	font-size: 15px;
     30 | 	height: 23px;
     31 | 	cursor: pointer;
     32 | }
     33 | 
     34 | .a-label{
     35 | 	margin: 5px;
     36 | 	display: inline-block;
     37 | }
     38 | 
     39 | .a-label:hover{
     40 | 	-webkit-animation: a_label 1s linear infinite;
     41 | 		 -moz-animation: a_label 1s linear infinite;
     42 | 					animation: a_label 1s linear infinite;
     43 | }
     44 | 
     45 | @-webkit-keyframes a_label{
     46 | 	0% 100% {
     47 | 		-webkit-transform: scale(1);
     48 | 	}
     49 | 	50% {
     50 | 		-webkit-transform: scale(1.2);
     51 | 	}
     52 | }
     53 | 
     54 | @-moz-keyframes a_label{
     55 | 	0% 100% {
     56 | 		-moz-transform: scale(1);
     57 | 	}
     58 | 	50% {
     59 | 		-moz-transform: scale(1.2);
     60 | 	}
     61 | }
     62 | 
     63 | @keyframes a_label{
     64 | 	0% 100% {
     65 | 		transform: scale(1);
     66 | 	}
     67 | 	50% {
     68 | 		transform: scale(1.2);
     69 | 	}
     70 | }
     71 | 
     72 | .a-label-strike {
     73 | 	-webkit-animation: labelstrike 1s linear 3;
     74 | 		 -moz-animation: labelstrike 1s linear 3;
     75 | 					animation: labelstrike 1s linear 3;
     76 | }
     77 | 
     78 | @-webkit-keyframes labelstrike{
     79 | 	0% {
     80 | 		-webkit-transform : scale(1);
     81 | 	}
     82 | 	50%{
     83 | 		-webkit-transform : scale(1.25);
     84 | 	}
     85 | 	100% {
     86 | 		-webkit-transform : scale(1);
     87 | 	}
     88 | }
     89 | 
     90 | @-moz-keyframes labelstrike{
     91 | 	0% {
     92 | 		-moz-transform : scale(1);
     93 | 	}
     94 | 	50%{
     95 | 		-moz-transform : scale(1.25);
     96 | 	}
     97 | 	100% {
     98 | 		-moz-transform : scale(1);
     99 | 	}
    100 | }
    101 | 
    102 | @keyframes labelstrike{
    103 | 	0% {
    104 | 		transform : scale(1);
    105 | 	}
    106 | 	50%{
    107 | 		transform : scale(1.25);
    108 | 	}
    109 | 	100% {
    110 | 		transform : scale(1);
    111 | 	}
    112 | }
    113 | 
    114 | .b-label-loading {
    115 | 	background: url("/images/loading.gif") no-repeat;
    116 | 	background-position: center;
    117 | 	min-height: 32px;
    118 | 	min-width: 32px;
    119 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/pageTools/user.css:
    --------------------------------------------------------------------------------
     1 | .b-user-loading {
     2 | 	background: url("/images/loading.gif") no-repeat;
     3 | 	background-position: center;
     4 | 	min-height: 32px;
     5 | 	min-width: 32px
     6 | }
     7 | 
     8 | .u-user-avatar img {
     9 |   height: 60px;
    10 |   width: 60px;
    11 |   border-radius: 30px;
    12 |   box-shadow: 0 0 6px #707070
    13 | }
    14 | 
    15 | .u-user-tags {
    16 | 	width: 272px;
    17 | 	padding-right: 20px;
    18 | }
    
    
    --------------------------------------------------------------------------------
    /public/stylesheets/style.css:
    --------------------------------------------------------------------------------
      1 | body {
      2 |   font-size: 14px;
      3 |   padding-top: 50px;
      4 |   margin-top:-50px;
      5 |   font-family: ff-tisa-web-pro-1, ff-tisa-web-pro-2, 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, 'Hiragino Sans GB', 'Hiragino Sans GB W3', 'Microsoft YaHei UI', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif;
      6 | }
      7 | 
      8 | h1,h2,h3 {
      9 | 	font-family: ff-tisa-web-pro-1, ff-tisa-web-pro-2, 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, 'Hiragino Sans GB', 'Hiragino Sans GB W3', 'Microsoft YaHei UI', 'Microsoft YaHei', 'WenQuanYi Micro Hei', sans-serif;
     10 | }
     11 | 
     12 | .b-loading {
     13 | 	background: url("/images/loading.gif") no-repeat;
     14 | 	background-position: center;
     15 | 	min-height: 32px;
     16 | 	min-width: 32px;
     17 | }
     18 | 
     19 | 
     20 | .footer hr{
     21 | 	border-top: 1px solid #383838;
     22 | }
     23 | 
     24 | .footer p{
     25 |   text-align : center;
     26 |   font-style : italic;
     27 | }
     28 | 
     29 | .b-clouds {
     30 | 	z-index: -1;
     31 | 	position: fixed;
     32 | 	width: 100%;
     33 | 	height: 100%;
     34 | 	background-image: -webkit-linear-gradient(top, #5CC9FC, #FFFFFF);
     35 | 	background-image: -moz-linear-gradient(top, #5CC9FC, #FFFFFF);
     36 | 	background-image: -ms-linear-gradient(top, #5CC9FC, #FFFFFF);
     37 | 	overflow: hidden;
     38 | }
     39 | 
     40 | .b-clouds .block {
     41 | 	position: absolute;
     42 | 	background-image: -webkit-linear-gradient(left, #ffffff, transparent, #ffffff);
     43 | 	background-image: -moz-linear-gradient(to right, rgba(255,255,255,1), rgba(255,255,255,0), rgba(255,255,255,1));
     44 | 	background-image: linear-gradient(left, white, transparent, white);
     45 | 	background-image: -ms-linear-gradient(left, #ffffff00, transparent, #ffffff00);
     46 | 	overflow: hidden;
     47 | 	width: 100%;
     48 | 	height: 100%;
     49 | }
     50 | 
     51 | .b-clouds .clouds {
     52 | 	position: absolute;
     53 | 	width: 200%;
     54 | 	height: 400px;
     55 | 	/* -webkit-animation: cloud_move 60s linear infinite;
     56 | 	-moz-animation: cloud_move 60s linear infinite; */
     57 | }
     58 | 
     59 | .b-clouds .clouds .cloud {
     60 | 	position: absolute;
     61 | 	background-image: url("/images/cloud.png");
     62 | 	background-position: center;
     63 | 	background-repeat: no-repeat;
     64 | }
     65 | 
     66 | .b-clouds .clouds .cloud-sm{
     67 | 	width: 223px;
     68 | 	height: 98px;
     69 | 	background-size: 223px 78px;
     70 | }
     71 | 
     72 | .b-clouds .clouds .cloud-md{
     73 | 	width: 335px;
     74 | 	height: 147px;
     75 | 	background-size: 335px 147px;
     76 | }
     77 | 
     78 | .b-clouds .clouds .cloud-lg{
     79 | 	width: 670px;
     80 | 	height: 294px;
     81 | 	background-size: 670px 294px;
     82 | }
     83 | 
     84 | @-webkit-keyframes cloud_move {
     85 | 	from {
     86 | 		left: -100%;
     87 | 	}
     88 | 	to {
     89 | 		left: 0;
     90 | 	}
     91 | }
     92 | 
     93 | @-moz-keyframes cloud_move {
     94 | 	from {
     95 | 		left: -100%;
     96 | 	}
     97 | 	to {
     98 | 		left: 0;
     99 | 	}
    100 | }
    101 | 
    102 | @-ms-keyframes cloud_move {
    103 | 	from {
    104 | 		left: -100%;
    105 | 	}
    106 | 	to {
    107 | 		left: 0;
    108 | 	}
    109 | }
    110 | 
    111 | .scrollToTop {
    112 | 	width: 100px;
    113 | 	height: 100px;
    114 | 	border-radius: 20px;
    115 | 	font-size: 80px;
    116 | 	line-height: 100px;
    117 | 	background-color: #6D6D6D;
    118 | 	color: white;
    119 | 	opacity: 0.5;
    120 | 	text-align: center;
    121 | 	position: fixed;
    122 | 	right: 80px;
    123 | 	bottom: 80px;
    124 | 	padding-right: 5px;
    125 | 	cursor: pointer;
    126 | }
    127 | 
    128 | .scrollToTop:hover{
    129 | 	opacity: 1;
    130 | }
    131 | 
    132 | .g-main {
    133 | 	margin-top: 50px;
    134 | }
    135 | 
    136 | .u-panel {
    137 | 	padding: 20px;
    138 | 	border-radius: 20px;
    139 | 	box-shadow: 3px 3px 6px #8A8A8A;
    140 | 	background: rgba(255,255,255,0.8);
    141 | }
    142 | 
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/AdmireAction.js:
    --------------------------------------------------------------------------------
      1 | var Admire = require("../Model/Admire.js"),
      2 | 	Comment = require("../Model/Comment.js"),
      3 | 	Remind = require("../Model/Remind.js"),
      4 | 	moment = require("moment");
      5 | 
      6 | moment.lang("zh-cn");
      7 | 
      8 | exports.add = function(req, res) {
      9 | 	var admire = new Admire({
     10 | 		username: req.session.user.username,
     11 | 		commentId: req.body.commentId
     12 | 	});
     13 | 	admire.save(function(err, admire) {
     14 | 		if (err) return res.json(500, {
     15 | 			message: err.message
     16 | 		});
     17 | 		Comment.get(admire.commentId, function(err, comment) {
     18 | 			if (err) return res.json(500, {
     19 | 				message: err.message
     20 | 			});
     21 | 			new Remind({
     22 | 				type: "admire",
     23 | 				ref: admire.id,
     24 | 				user: comment.username
     25 | 			}).save(function(err) {
     26 | 				if (err) return res.json(500, {
     27 | 					message: err.message
     28 | 				});
     29 | 				res.json({
     30 | 					success: true
     31 | 				});
     32 | 			});
     33 | 		});
     34 | 	});
     35 | };
     36 | 
     37 | exports.remove = function(req, res) {
     38 | 	var admire = new Admire({
     39 | 		username: req.session.user.username,
     40 | 		commentId: req.body.commentId
     41 | 	});
     42 | 	admire.remove(function(err) {
     43 | 		if (err) return res.json(500, {
     44 | 			message: err.message
     45 | 		});
     46 | 		res.json({
     47 | 			success: true
     48 | 		});
     49 | 	});
     50 | };
     51 | 
     52 | exports.checkAdmired = function(req, res) {
     53 | 	var username = req.session.user.username,
     54 | 		commentId = req.body.commentId;
     55 | 	Admire.checkAdmired(username, commentId, function(err, admired) {
     56 | 		if (err) return res.json(500, {
     57 | 			message: err.message
     58 | 		});
     59 | 		res.json({
     60 | 			admired: admired
     61 | 		});
     62 | 	});
     63 | };
     64 | 
     65 | exports.countByComment = function(req, res) {
     66 | 	var commentId = req.body.commentId;
     67 | 	Admire.countByComment(commentId, function(err, total) {
     68 | 		if (err) return res.json(500, {
     69 | 			message: err.message
     70 | 		});
     71 | 		res.json({
     72 | 			total: total
     73 | 		});
     74 | 	});
     75 | };
     76 | 
     77 | exports.getOne = function(req, res) {
     78 | 	Admire.get(req.body.admireId, function(err, admire) {
     79 | 		if (err) return res.json(500);
     80 | 		if (!admire) return res.status(404).send("not fount");
     81 | 		admire.time = moment(admire.time).fromNow();
     82 | 		res.json({
     83 | 			admire: admire
     84 | 		});
     85 | 	});
     86 | };
     87 | 
     88 | exports.getByUser = function(req, res) {
     89 | 	Admire.getByUser(req.body.username, Number(req.body.curPage), Number(req.body.perPage), function(err, admires) {
     90 | 		if (err) return res.json(500);
     91 | 		for (var i = admires.length; i--;) {
     92 | 			admires[i].time = moment(admires[i].time).fromNow();
     93 | 		}
     94 | 		res.json({
     95 | 			admires: admires
     96 | 		});
     97 | 	});
     98 | };
     99 | 
    100 | exports.countByUser = function(req, res) {
    101 | 	Admire.countByUser(req.body.username, function(err, total) {
    102 | 		if (err) return res.json(500);
    103 | 		res.json({
    104 | 			total: total
    105 | 		});
    106 | 	});
    107 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/ArticleAction.js:
    --------------------------------------------------------------------------------
      1 | var Article = require("../Model/Article.js"),
      2 | 	User = require("../Model/User.js"),
      3 | 	Comment = require("../Model/Comment.js"),
      4 | 	Admire = require("../Model/Admire.js"),
      5 | 	Bookmark = require("../Model/Bookmark.js"),
      6 | 	Tag = require("../Model/Tag.js"),
      7 | 	async = require("async"),
      8 | 	markdown = require("markdown").markdown,
      9 | 	moment = require("moment");
     10 | 
     11 | moment.lang("zh-cn");
     12 | 
     13 | exports.writePage = function(req, res) {
     14 | 	res.render("writeArticle");
     15 | };
     16 | 
     17 | exports.editPage = function(req, res) {
     18 | 	Article.get(req.query.articleId, function(err, article) {
     19 | 		if (err) {
     20 | 			return res.render("error", {
     21 | 				message: err.message
     22 | 			});
     23 | 		}
     24 | 		if (article) {
     25 | 			return res.render("editArticle", {
     26 | 				article: article
     27 | 			});
     28 | 		}
     29 | 	});
     30 | };
     31 | 
     32 | exports.update = function(req, res) {
     33 | 	Article.get(req.body.articleId, function(err, article) {
     34 | 		if (err) return res.json(500, {
     35 | 			message: err.message
     36 | 		});
     37 | 		article.title = req.body.title;
     38 | 		article.content = req.body.content;
     39 | 		article.tags = JSON.parse(req.body.tags);
     40 | 		article.update(function(err) {
     41 | 			if (err) return res.json(500, {
     42 | 				message: err.message
     43 | 			});
     44 | 			res.json("editArticle", {
     45 | 				success: true
     46 | 			});
     47 | 		});
     48 | 	});
     49 | };
     50 | 
     51 | exports.save = function(req, res) {
     52 | 	console.log(req.body.tags);
     53 | 	var article = new Article({
     54 | 		writer: req.session.user.username,
     55 | 		content: req.body.content,
     56 | 		title: req.body.title,
     57 | 		tags: JSON.parse(req.body.tags)
     58 | 	});
     59 | 	article.save(function(err, art) {
     60 | 		if (err) return res.render("err", {
     61 | 			message: "保存文章失败"
     62 | 		});
     63 | 		res.redirect("/article_load?articleId=" + art.id);
     64 | 	});
     65 | };
     66 | 
     67 | exports.remove = function(req, res) {
     68 | 	Article.get(req.body.articleId, function(err, article) {
     69 | 		if (err) return res.json(500);
     70 | 		article.remove(function(err) {
     71 | 			if (err) return res.json(500);
     72 | 			res.json({});
     73 | 		});
     74 | 	});
     75 | };
     76 | 
     77 | exports.getOne = function(req, res) {
     78 | 	Article.get(req.body.articleId, function(err, article) {
     79 | 		if (err) return res.json(500);
     80 | 		if (!article) return res.status(404).send("not fount");
     81 | 		article.writeTime = moment(article.writeTime).fromNow();
     82 | 		return res.json({
     83 | 			article: article
     84 | 		});
     85 | 	});
     86 | };
     87 | 
     88 | 
     89 | exports.load = function(req, res) {
     90 | 	Article.get(req.query.articleId, function(err, article) {
     91 | 		if (err) return res.render("error", {
     92 | 			message: err.message
     93 | 		});
     94 | 		if (!article) return res.render("error", {
     95 | 			message: "没有找到该文章"
     96 | 		});
     97 | 		article.content = markdown.toHTML(article.content);
     98 | 		article.writeTime = moment(article.writeTime).fromNow();
     99 | 		res.render("articleDetail", {
    100 | 			article: article
    101 | 		});
    102 | 	});
    103 | };
    104 | 
    105 | exports.listAll = function(req, res) {
    106 | 	Article.getAll(Number(req.body.curPage), Number(req.body.perPage), function(err, articles) {
    107 | 		var i;
    108 | 		if (err) return res.json(500);
    109 | 		for (i = articles.length; i--;) {
    110 | 			articles[i].content = markdown.toHTML(articles[i].content);
    111 | 			articles[i].writeTime = moment(articles[i].writeTime).fromNow();
    112 | 		}
    113 | 		return res.json({
    114 | 			articles: articles
    115 | 		});
    116 | 	});
    117 | };
    118 | 
    119 | 
    120 | exports.getByUser = function(req, res) {
    121 | 	Article.getByUser(req.body.username, Number(req.body.curPage), Number(req.body.perPage), function(err, articles) {
    122 | 		if (err) return res.json(500);
    123 | 		for (var i = articles.length; i--;) {
    124 | 			articles[i].writeTime = moment(articles[i].writeTime).fromNow();
    125 | 		}
    126 | 		res.json({
    127 | 			articles: articles
    128 | 		});
    129 | 	});
    130 | };
    131 | 
    132 | exports.countByUser = function(req, res) {
    133 | 	Article.countByUser(req.body.username, function(err, total) {
    134 | 		if (err) return res.json(500);
    135 | 		res.json({
    136 | 			total: total
    137 | 		});
    138 | 	});
    139 | };
    140 | 
    141 | exports.getByTags = function(req, res) {
    142 | 	Article.getByTags(req.body.tags, Number(req.body.curPage), Number(req.body.perPage), function(err, articles) {
    143 | 		if (err) return res.json(500);
    144 | 		for (var i = articles.length; i--;) {
    145 | 			articles[i].writeTime = moment(articles[i].writeTime).fromNow();
    146 | 		}
    147 | 		res.json({
    148 | 			articles: articles
    149 | 		});
    150 | 	});
    151 | };
    152 | 
    153 | exports.getByTitle = function(req, res) {
    154 | 	Article.getByTitle(req.body.title, Number(req.body.curPage), Number(req.body.perPage), function(err, articles) {
    155 | 		if (err) return res.json(500);
    156 | 		for (var i = articles.length; i--;) {
    157 | 			articles[i].writeTime = moment(articles[i].writeTime).fromNow();
    158 | 		}
    159 | 		res.json({
    160 | 			articles: articles
    161 | 		});
    162 | 	});
    163 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/BookmarkAction.js:
    --------------------------------------------------------------------------------
      1 | var Bookmark = require("../Model/Bookmark.js"),
      2 | 	Article = require("../Model/Article.js"),
      3 | 	Remind = require("../Model/Remind.js"),
      4 | 	moment = require("moment");
      5 | 
      6 | moment.lang("zh-cn");
      7 | 
      8 | exports.save = function(req, res) {
      9 | 	var bookmark = new Bookmark({
     10 | 		articleId: req.body.articleId,
     11 | 		username: req.session.user.username
     12 | 	});
     13 | 	bookmark.save(function(err, bookmark) {
     14 | 		if (err) return res.json(500, {
     15 | 			message: err.message
     16 | 		});
     17 | 		Article.get(bookmark.articleId, function(err, article) {
     18 | 			if (err) return res.json(500, {
     19 | 				message: err.message
     20 | 			});
     21 | 			new Remind({
     22 | 				type: "bookmark",
     23 | 				ref: bookmark.id,
     24 | 				user: article.writer
     25 | 			}).save(function(err, remind) {
     26 | 				if (err) return res.json(500, {
     27 | 					message: err.message
     28 | 				});
     29 | 				res.json({
     30 | 					success: true
     31 | 				});
     32 | 			});
     33 | 		});
     34 | 		res.json({
     35 | 			success: true
     36 | 		});
     37 | 	});
     38 | };
     39 | 
     40 | exports.remove = function(req, res) {
     41 | 	var bookmark = new Bookmark({
     42 | 		articleId: req.body.articleId,
     43 | 		username: req.session.user.username
     44 | 	});
     45 | 	bookmark.remove(function(err) {
     46 | 		if (err) return res.json(500, {
     47 | 			message: err.message
     48 | 		});
     49 | 		res.json({
     50 | 			success: true
     51 | 		});
     52 | 	});
     53 | };
     54 | 
     55 | exports.countByArticle = function(req, res) {
     56 | 	Bookmark.countByArticle(req.body.articleId, function(err, total) {
     57 | 		if (err) return res.json(500, {
     58 | 			message: err.message
     59 | 		});
     60 | 		res.json({
     61 | 			total: total
     62 | 		});
     63 | 	});
     64 | };
     65 | 
     66 | exports.checkBooked = function(req, res) {
     67 | 	Bookmark.checkBooked(req.session.user.username, req.body.articleId, function(err, booked) {
     68 | 		if (err) return res.json(500, {
     69 | 			message: err.message
     70 | 		});
     71 | 		res.json({
     72 | 			booked: booked
     73 | 		});
     74 | 	});
     75 | };
     76 | 
     77 | exports.getOne = function(req, res) {
     78 | 	Bookmark.get(req.body.bookmarkId, function(err, bookmark) {
     79 | 		if (err) return res.json(500);
     80 | 		if (!bookmark) return res.status(404).send("not found");
     81 | 		bookmark.time = moment(bookmark.time).fromNow();
     82 | 		res.json({
     83 | 			bookmark: bookmark
     84 | 		});
     85 | 	});
     86 | };
     87 | 
     88 | exports.getByUser = function(req, res) {
     89 | 	Bookmark.getByUser(req.body.username, Number(req.body.curPage), Number(req.body.perPage), function(err, bookmarks) {
     90 | 		if (err) return res.json(500);
     91 | 		for (var i = bookmarks.length; i--;) {
     92 | 			bookmarks[i].time = moment(bookmarks[i].time).fromNow();
     93 | 		}
     94 | 		res.json({
     95 | 			bookmarks: bookmarks
     96 | 		});
     97 | 	});
     98 | };
     99 | 
    100 | exports.countByUser = function(req, res) {
    101 | 	Bookmark.countByUser(req.body.username, function(err, total) {
    102 | 		if (err) return res.json(500);
    103 | 		res.json({
    104 | 			total: total
    105 | 		});
    106 | 	});
    107 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/CommentAction.js:
    --------------------------------------------------------------------------------
      1 | var Comment = require("../Model/Comment.js"),
      2 | 	Remind = require("../Model/Remind.js"),
      3 | 	moment = require("moment"),
      4 | 	async = require("async");
      5 | 
      6 | moment.lang("zh-cn");
      7 | 
      8 | exports.save = function(req, res) {
      9 | 	var remind,
     10 | 		comment = new Comment({
     11 | 			articleId: req.body.articleId,
     12 | 			username: req.session.user.username,
     13 | 			comment: req.body.comment,
     14 | 			reply: req.body.replyId
     15 | 		});
     16 | 
     17 | 	async.waterfall([
     18 | 
     19 | 		function(callback) {
     20 | 			comment.save(function(err, comment) {
     21 | 				if (err) return callback(err);
     22 | 				callback(err, comment);
     23 | 			});
     24 | 		},
     25 | 		function(comment, callback) {
     26 | 			if (comment.reply) {
     27 | 				Comment.get(comment.reply, function(err, com) {
     28 | 					if (err) return callback(err);
     29 | 					var remind = new Remind({
     30 | 						type: "comment",
     31 | 						ref: comment.id,
     32 | 						user: com.username
     33 | 					});
     34 | 					remind.save(function(err) {
     35 | 						if (err) return callback(err);
     36 | 						callback(comment);
     37 | 					});
     38 | 				});
     39 | 			} else {
     40 | 				callback(comment);
     41 | 			}
     42 | 		},
     43 | 		function(comment, callback) {
     44 | 			Article.get(comment.articleId, function(err, com) {
     45 | 				if (err) return callback(err);
     46 | 				var remind = new Remind({
     47 | 					type: "comment",
     48 | 					ref: comment.id,
     49 | 					user: com.username
     50 | 				});
     51 | 				remind.save(function(err) {
     52 | 					if (err) return callback(err);
     53 | 					callback(comment);
     54 | 				});
     55 | 			});
     56 | 		}
     57 | 	], function(err) {
     58 | 		if (err) res.render("error", {
     59 | 			message: err.message
     60 | 		});
     61 | 		res.redirect("/article_load?articleId=" + comment.articleId + "#comments");
     62 | 	});
     63 | };
     64 | 
     65 | exports.remove = function(req, res) {
     66 | 	Comment.get(req.body.commentId, function(err, comment) {
     67 | 		if (err) return res.json(500, {
     68 | 			message: err.message
     69 | 		});
     70 | 		if (req.session.user.username === comment.username) {
     71 | 			comment.remove(function(err) {
     72 | 				if (err) return res.json(500, {
     73 | 					message: err.message
     74 | 				});
     75 | 				res.json({
     76 | 					success: true
     77 | 				});
     78 | 			});
     79 | 		} else {
     80 | 			return res.json(500, {
     81 | 				message: "不能删除他人的评论"
     82 | 			});
     83 | 		}
     84 | 	});
     85 | };
     86 | 
     87 | exports.getByArticle = function(req, res) {
     88 | 	Comment.getByArticle(req.body.articleId, Number(req.body.curPage), Number(req.body.perPage), function(err, comments) {
     89 | 		var i;
     90 | 		if (err) return res.json(500, {
     91 | 			message: err.message
     92 | 		});
     93 | 		for (i = comments.length; i--;) {
     94 | 			comments[i].time = moment(comments[i].time).fromNow();
     95 | 		}
     96 | 		res.json({
     97 | 			comments: comments
     98 | 		});
     99 | 	});
    100 | };
    101 | 
    102 | exports.countByArticle = function(req, res) {
    103 | 	Comment.countByArticle(req.body.articleId, function(err, total) {
    104 | 		if (err) return res.json(500, {
    105 | 			message: err.message
    106 | 		});
    107 | 		res.json({
    108 | 			total: total
    109 | 		});
    110 | 	});
    111 | };
    112 | 
    113 | exports.countByUser = function(req, res) {
    114 | 	Comment.countByUser(req.body.username, function(err, total) {
    115 | 		if (err) return res.json(500, {
    116 | 			message: err.message
    117 | 		});
    118 | 		res.json({
    119 | 			total: total
    120 | 		});
    121 | 	});
    122 | };
    123 | 
    124 | exports.getByUser = function(req, res) {
    125 | 	Comment.getByUser(req.body.username, Number(req.body.curPage), Number(req.body.perPage), function(err, comments) {
    126 | 		if (err) return res.json(500, {
    127 | 			message: err.message
    128 | 		});
    129 | 		for (var i = comments.length; i--;) {
    130 | 			comments[i].time = moment(comments[i].time).fromNow();
    131 | 		}
    132 | 		res.json({
    133 | 			comments: comments
    134 | 		});
    135 | 	});
    136 | };
    137 | 
    138 | 
    139 | exports.getOne = function(req, res) {
    140 | 	Comment.get(req.body.commentId, function(err, comment) {
    141 | 		if (err) return res.json(500);
    142 | 		if (!comment) return res.status(404).send("not fount");
    143 | 		comment.time = moment(comment.time).fromNow();
    144 | 		res.json({
    145 | 			comment: comment
    146 | 		});
    147 | 	});
    148 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/ExpAction.js:
    --------------------------------------------------------------------------------
    1 | exports.broadchat = function(req, res) {
    2 | 	res.render("broadchat");
    3 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/GallaryAction.js:
    --------------------------------------------------------------------------------
     1 | var fs = require("fs"),
     2 | 	gallary = require("../setting.js").gallary;
     3 | 
     4 | exports.gallaryPage = function(req, res) {
     5 | 	res.render("gallary");
     6 | };
     7 | 
     8 | exports.listByPage = function(req, res) {
     9 | 	var curPage = req.query.curPage || 0,
    10 | 		perPage = Number(req.query.perPage) || 10;
    11 | 	path = "public/" + gallary.name;
    12 | 	fs.readdir(path, function(err, files) {
    13 | 		var i,
    14 | 			start = curPage * perPage,
    15 | 			end,
    16 | 			total;
    17 | 		if (err) return res.json(500, {
    18 | 			message: err.message
    19 | 		});
    20 | 		if (start > files.length) {
    21 | 			res.json({
    22 | 				files: [],
    23 | 				total: files.length,
    24 | 				gallary: gallary.name,
    25 | 				gallary_small: gallary.small
    26 | 			});
    27 | 		} else {
    28 | 			end = start + perPage > files.length ? files.length : start + perPage;
    29 | 			res.json({
    30 | 				files: files.slice(start, end),
    31 | 				total: files.length,
    32 | 				start: start,
    33 | 				end: end,
    34 | 				gallary_small: gallary.small,
    35 | 				gallary: gallary.name
    36 | 			});
    37 | 		}
    38 | 	});
    39 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/PictureAction.js:
    --------------------------------------------------------------------------------
      1 | var setting = require("../setting.js"),
      2 | 	fs = require("fs"),
      3 | 	async = require("async"),
      4 | 	gm = require("gm"),
      5 | 	path = require("path"),
      6 | 	imageMagick = gm.subClass({
      7 | 		imageMagick: true
      8 | 	}),
      9 | 	uuid = require("node-uuid"),
     10 | 	util = require("util"),
     11 | 	__copyFile = function copyFile(file, toDir, callback) {
     12 | 		var reads = fs.createReadStream(file);
     13 | 		var writes = fs.createWriteStream(path.join(path.dirname(toDir), path.basename(file)));
     14 | 		reads.pipe(writes);
     15 | 		//don't forget close the  when  all the data are read  
     16 | 		reads.on("end", function() {
     17 | 			writes.end();
     18 | 			callback(null);
     19 | 		});
     20 | 		reads.on("error", function(err) {
     21 | 			console.log("error occur in reads");
     22 | 			callback(true, err);
     23 | 		});
     24 | 	};
     25 | 
     26 | exports.remove = function(req, res) {
     27 | 	var fileName = req.body.fileName,
     28 | 		smallFile = "public/" + setting.gallary.small + "/" + fileName,
     29 | 		orignFile = "public/" + setting.gallary.name + "/" + fileName;
     30 | 	try {
     31 | 		fs.unlinkSync(smallFile);
     32 | 		fs.unlinkSync(orignFile);
     33 | 	} catch (e) {
     34 | 		return res.json(500, {
     35 | 			message: e.message
     36 | 		});
     37 | 	}
     38 | 	res.json({
     39 | 		success: true
     40 | 	});
     41 | 
     42 | };
     43 | 
     44 | exports.uploadDirect = function(req, res) {
     45 | 	var inputFile = req.files.image.path,
     46 | 		fileName = new RegExp('^' + setting.uploadDir + '\\\\([\\w-\\.]+)$').exec(inputFile)[1],
     47 | 		resizeFile = "public/" + setting.gallary.small + "/" + fileName,
     48 | 		outputFile = "public/" + setting.gallary.name + "/" + fileName;
     49 | 	async.waterfall([
     50 | 
     51 | 		function(callback) {
     52 | 			imageMagick(inputFile).write(outputFile, function(err) {
     53 | 				if (err) return callback(err);
     54 | 				callback(null);
     55 | 			});
     56 | 		},
     57 | 		function(callback) {
     58 | 			imageMagick(inputFile).resize(400).write(resizeFile, function(err) {
     59 | 				if (err) return callback(err);
     60 | 				callback(null);
     61 | 			});
     62 | 		},
     63 | 		function(callback) {
     64 | 			if (fs.existsSync(inputFile)) {
     65 | 				fs.unlink(inputFile, function(err) {
     66 | 					if (err) return callback(err);
     67 | 					callback(null);
     68 | 				});
     69 | 			} else {
     70 | 				callback(new Error("未找到文件"));
     71 | 			}
     72 | 		}
     73 | 	], function(err) {
     74 | 		if (err) return res.json(500, {
     75 | 			message: err.message
     76 | 		});
     77 | 		res.json({
     78 | 			success: true,
     79 | 			fileName: fileName,
     80 | 			gallary: setting.gallary.name,
     81 | 			gallary_small: setting.gallary.small
     82 | 		});
     83 | 	});
     84 | };
     85 | 
     86 | exports.uploadDirectNoCompress = function(req, res) {
     87 | 	var inputFile = req.files.image.path,
     88 | 		fileName = (/^upload_tmp\/([\w\-\.]+)$/.exec(inputFile) || /^upload_tmp\\([\w\-\.]+)$/.exec(inputFile))[1],
     89 | 		resizeFile = "public/" + setting.gallary.small + "/" + fileName,
     90 | 		outputFile = "public/" + setting.gallary.name + "/" + fileName;
     91 | 	async.waterfall([
     92 | 
     93 | 		function(callback) {
     94 | 			__copyFile(inputFile, resizeFile, callback);
     95 | 		},
     96 | 		function(callback) {
     97 | 			__copyFile(inputFile, outputFile, callback);
     98 | 		},
     99 | 		function(callback) {
    100 | 			if (fs.existsSync(inputFile)) {
    101 | 				fs.unlink(inputFile, function(err) {
    102 | 					if (err) return callback(err);
    103 | 					callback(null);
    104 | 				});
    105 | 			} else {
    106 | 				callback(new Error("未找到文件"));
    107 | 			}
    108 | 		}
    109 | 	], function(err) {
    110 | 		if (err) return res.json(500, {
    111 | 			message: err.message
    112 | 		});
    113 | 		res.json({
    114 | 			success: true,
    115 | 			fileName: fileName,
    116 | 			gallary: setting.gallary.name,
    117 | 			gallary_small: setting.gallary.small
    118 | 		});
    119 | 	});
    120 | };
    121 | 
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/RemindAction.js:
    --------------------------------------------------------------------------------
     1 | var Remind = require("../Model/Remind.js"),
     2 | 	moment = require("moment"),
     3 | 	async = require("async");
     4 | 
     5 | exports.getAll = function(req, res) {
     6 | 	Remind.getByUser(req.session.user.username, Number(req.body.curPage), Number(req.body.perPage), function(err, reminds) {
     7 | 		if (err) res.json(500, {
     8 | 			message: err.message
     9 | 		});
    10 | 		res.json({
    11 | 			reminds: reminds
    12 | 		});
    13 | 	});
    14 | };
    15 | 
    16 | exports.getByType = function(req, res) {
    17 | 	Remind.getByUserAndType(req.session.user.username, req.body.type, Number(req.body.curPage), Number(req.body.perPage), function(err, reminds) {
    18 | 		if (err) res.json(500, {
    19 | 			message: err.message
    20 | 		});
    21 | 		res.json({
    22 | 			reminds: reminds
    23 | 		});
    24 | 	});
    25 | };
    26 | 
    27 | exports.countUnreadAll = function(req, res) {
    28 | 	Remind.countUnreadByUser(req.session.user.username, function(err, total) {
    29 | 		if (err) res.json(500, {
    30 | 			message: err.message
    31 | 		});
    32 | 		res.json({
    33 | 			total: total
    34 | 		});
    35 | 	});
    36 | };
    37 | 
    38 | exports.countUnreadByType = function(req, res) {
    39 | 	Remind.countUnreadByUserAndType(req.session.user.username, req.body.type, function(err, total) {
    40 | 		if (err) res.json(500, {
    41 | 			message: err.message
    42 | 		});
    43 | 		res.json({
    44 | 			total: total
    45 | 		});
    46 | 	});
    47 | };
    48 | 
    49 | exports.remove = function(req, res) {
    50 | 	var remindId = req.body.remindId;
    51 | 	Remind.getOne(remindId, function(err, remind) {
    52 | 		if (err) return callback(err);
    53 | 		remind.remove(function(err) {
    54 | 			if (err) return res.json(500);
    55 | 			res.json(null);
    56 | 		});
    57 | 	});
    58 | };
    59 | 
    60 | exports.setReaded = function(req, res) {
    61 | 	var remindIds = req.body.remindIds;
    62 | 	async.each(remindIds, function(remindId, callback) {
    63 | 		Remind.getOne(remindId, function(err, remind) {
    64 | 			if (err) return callback(err);
    65 | 			remind.readed = true;
    66 | 			remind.update(function(err) {
    67 | 				if (err) return callback(err);
    68 | 				callback(null);
    69 | 			});
    70 | 		});
    71 | 	}, function(err) {
    72 | 		if (err) return res.json(500);
    73 | 		res.json(null);
    74 | 	});
    75 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/TagAction.js:
    --------------------------------------------------------------------------------
     1 | var Tag = require("../Model/Tag.js"),
     2 | 	User = require("../Model/User.js"),
     3 | 	Article = require("../Model/Article.js"),
     4 | 	async = require("async");
     5 | 
     6 | exports.create = function(req, res) {
     7 | 	var tag = new Tag({
     8 | 		name: req.body.name,
     9 | 		color: req.body.color
    10 | 	});
    11 | 	tag.save(function(err, newTag) {
    12 | 		if (err) return res.json(500, {
    13 | 			message: err.message
    14 | 		});
    15 | 		res.json({
    16 | 			tag: newTag
    17 | 		});
    18 | 	});
    19 | };
    20 | 
    21 | exports.listAll = function(req, res) {
    22 | 	var name = req.query.name;
    23 | 	Tag.getAll(function(err, tags) {
    24 | 		if (err) return res.json(500, {
    25 | 			message: err.message
    26 | 		});
    27 | 		res.json({
    28 | 			tags: tags
    29 | 		});
    30 | 	});
    31 | };
    32 | 
    33 | exports.listUserTags = function(req, res) {
    34 | 	User.get(req.body.username, function(err, user) {
    35 | 		if (err) return req.json(500, {
    36 | 			message: err.message
    37 | 		});
    38 | 		async.map(user.tags, function(tagId, callback) {
    39 | 			Tag.get(tagId, function(err, tag) {
    40 | 				if (err) return callback(tag);
    41 | 				callback(null, tag);
    42 | 			});
    43 | 		}, function(err, tags) {
    44 | 			if (err) return req.json(500, {
    45 | 				message: err.message
    46 | 			});
    47 | 			res.json({
    48 | 				tags: tags
    49 | 			});
    50 | 		});
    51 | 	});
    52 | };
    53 | 
    54 | exports.listArticleTags = function(req, res) {
    55 | 	Article.get(req.body.articleId, function(err, article) {
    56 | 		if (err) return req.json(500, {
    57 | 			message: err.message
    58 | 		});
    59 | 		async.map(article.tags, function(tagId, callback) {
    60 | 			Tag.get(tagId, function(err, tag) {
    61 | 				if (err) return callback(tag);
    62 | 				callback(null, tag);
    63 | 			});
    64 | 		}, function(err, tags) {
    65 | 			if (err) return req.json(500, {
    66 | 				message: err.message
    67 | 			});
    68 | 			res.json({
    69 | 				tags: tags
    70 | 			});
    71 | 		});
    72 | 	});
    73 | };
    74 | 
    75 | exports.listFuzzy = function(req, res) {
    76 | 	var name = req.query.name;
    77 | 	Tag.getByFuzzyName(name, function(err, tags) {
    78 | 		if (err) return res.json(500, {
    79 | 			message: err.message
    80 | 		});
    81 | 		res.json({
    82 | 			tags: tags
    83 | 		});
    84 | 	});
    85 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Actions/UserAction.js:
    --------------------------------------------------------------------------------
      1 | var User = require("../Model/User.js"),
      2 |   async = require("async"),
      3 |   Bookmark = require("../Model/Bookmark.js"),
      4 |   Admire = require("../Model/Admire.js"),
      5 |   Article = require("../Model/Article.js"),
      6 |   Comment = require("../Model/Comment.js"),
      7 |   moment = require("moment");
      8 | exports.loginPage = function(req, res) {
      9 |   res.render('login');
     10 | };
     11 | 
     12 | exports.registPage = function(req, res) {
     13 |   res.render('regist');
     14 | };
     15 | 
     16 | exports.login = function(req, res) {
     17 |   User.get(req.body.username, function(err, user) {
     18 |     if (err) return req.render("error", {
     19 |       message: "发生错误,请稍后重试..."
     20 |     });
     21 |     if (user && user.password === req.body.password) {
     22 |       req.session.user = user;
     23 |       res.redirect("/index");
     24 |     } else {
     25 |       res.render("login", {
     26 |         message: "用户名或密码错误..."
     27 |       });
     28 |     }
     29 |   });
     30 | };
     31 | 
     32 | exports.logout = function(req, res) {
     33 |   if (typeof req.session.user !== "undefined") {
     34 |     delete req.session.user;
     35 |   }
     36 |   res.redirect("index");
     37 | };
     38 | 
     39 | exports.loadDetail = function(req, res) {
     40 |   res.render("userDetail", {
     41 |     user: req.session.user
     42 |   });
     43 | };
     44 | 
     45 | exports.getDetail = function(req, res) {
     46 |   User.get(req.body.username, function(err, user) {
     47 |     if (err) return res.render("error", {
     48 |       message: err.message
     49 |     });
     50 |     res.json({
     51 |       username: user.username,
     52 |       nickname: user.nickname,
     53 |       owner: user.owner,
     54 |       tags: user.tags,
     55 |       avatar: user.avatar
     56 |     });
     57 |   });
     58 | };
     59 | 
     60 | exports.modify = function(req, res) {
     61 |   var tags = JSON.parse(req.body.tags);
     62 |   User.get(req.session.user.username, function(err, user) {
     63 |     if (err) return res.render("error", {
     64 |       message: err.message
     65 |     });
     66 |     if (user) {
     67 |       user.nickname = req.body.nickname;
     68 |       user.tags = tags;
     69 |       if (req.body.password) {
     70 |         user.password = req.body.password;
     71 |       }
     72 |       user.avatar = req.body.avatar || "/images/default_avatar.jpg";
     73 |       user.update(function(err) {
     74 |         req.session.user = user;
     75 |         res.render("userDetail", {
     76 |           user: req.session.user,
     77 |           success: true,
     78 |           message: "修改成功..."
     79 |         });
     80 |       });
     81 |     } else {
     82 |       res.render("userDetail", {
     83 |         user: req.session.user,
     84 |         success: false,
     85 |         message: "修改失败,用户不存在..."
     86 |       });
     87 |     }
     88 |   });
     89 | };
     90 | 
     91 | exports.regist = function(req, res) {
     92 |   User.get(req.body.username, function(err, user) {
     93 |     if (err) return res.render("error", {
     94 |       message: err.message
     95 |     });
     96 |     if (user) {
     97 |       return res.render("regist", {
     98 |         message: "用户名已被注册..."
     99 |       });
    100 |     } else {
    101 |       user = new User({
    102 |         username: req.body.username,
    103 |         password: req.body.password,
    104 |         nickname: req.body.nickname,
    105 |         avatar: "/images/default_avatar.jpg",
    106 |         owner: false,
    107 |         tags: []
    108 |       });
    109 |       user.save(function(err) {
    110 |         if (err) {
    111 |           return res.render("regist", {
    112 |             message: "发生错误,请稍后重试..."
    113 |           });
    114 |         } else {
    115 |           req.session.user = user;
    116 |           res.redirect("/index");
    117 |         }
    118 |       });
    119 |     }
    120 |   });
    121 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/Admire.js:
    --------------------------------------------------------------------------------
     1 | var commonDao = require("./CommonDAO.js"),
     2 | 	collectionName = "admire",
     3 | 	uuid = require("node-uuid"),
     4 | 	__resultToListFn = function(callback) {
     5 | 		return function(err, results) {
     6 | 			var i;
     7 | 			if (err) return callback(err);
     8 | 			for (i = results.length; i--;) {
     9 | 				results[i] = new Admire(results[i]);
    10 | 			}
    11 | 			callback(err, results);
    12 | 
    13 | 		};
    14 | 	};
    15 | 
    16 | function Admire(admire) {
    17 | 	this.username = admire.username;
    18 | 	this.commentId = admire.commentId;
    19 | 	this.time = admire.time;
    20 | 	this.id = admire.id;
    21 | }
    22 | 
    23 | module.exports = Admire;
    24 | 
    25 | Admire.prototype.save = function(callback) {
    26 | 	commonDao.save(collectionName, {
    27 | 		username: this.username,
    28 | 		commentId: this.commentId,
    29 | 		time: new Date().getTime(),
    30 | 		id: uuid.v4()
    31 | 	}, function(err, result) {
    32 | 		if (err) return callback(err);
    33 | 		if (!result[0]) return callback(new Error("保存失败"));
    34 | 		callback(err, new Admire(result[0]));
    35 | 	});
    36 | };
    37 | 
    38 | Admire.get = function(admireId, callback) {
    39 | 	commonDao.findOne(collectionName, {
    40 | 		id: admireId
    41 | 	}, function(err, result) {
    42 | 		if (err) return callback(err);
    43 | 		callback(err, result ? new Admire(result) : result);
    44 | 	});
    45 | };
    46 | 
    47 | Admire.removeByComment = function(commentId, callback) {
    48 | 	commonDao.remove(collectionName, {
    49 | 		commentId: commentId
    50 | 	}, callback);
    51 | };
    52 | 
    53 | Admire.getByUser = function(username, curPage, perPage, callback) {
    54 | 	commonDao.find(collectionName, {
    55 | 		condition: {
    56 | 			username: username
    57 | 		},
    58 | 		sort: {
    59 | 			time: -1
    60 | 		},
    61 | 		page: {
    62 | 			curPage: curPage,
    63 | 			perPage: perPage
    64 | 		}
    65 | 	}, __resultToListFn(callback));
    66 | };
    67 | 
    68 | Admire.countByUser = function(username, callback) {
    69 | 	commonDao.count(collectionName, {
    70 | 		username: username
    71 | 	}, callback);
    72 | };
    73 | 
    74 | Admire.prototype.remove = function(callback) {
    75 | 	commonDao.remove(collectionName, {
    76 | 		username: this.username,
    77 | 		commentId: this.commentId
    78 | 	}, callback);
    79 | };
    80 | 
    81 | Admire.countByComment = function(commentId, callback) {
    82 | 	commonDao.count(collectionName, {
    83 | 		commentId: commentId
    84 | 	}, callback);
    85 | };
    86 | 
    87 | Admire.checkAdmired = function(username, commentId, callback) {
    88 | 	commonDao.findOne(collectionName, {
    89 | 		username: username,
    90 | 		commentId: commentId
    91 | 	}, function(err, result) {
    92 | 		if (err) return callback(err);
    93 | 		if (!result) return callback(err, false);
    94 | 		return callback(err, true);
    95 | 	});
    96 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/Article.js:
    --------------------------------------------------------------------------------
      1 | var commonDao = require("./CommonDAO.js"),
      2 | 	collectionName = "article",
      3 | 	uuid = require("node-uuid"),
      4 | 	async = require("async"),
      5 | 	Bookmark = require("./Bookmark.js"),
      6 | 	Comment = require("./Comment.js"),
      7 | 	__resultToListFn = function(callback) {
      8 | 		return function(err, results) {
      9 | 			var i;
     10 | 			if (err) return callback(err);
     11 | 			for (i = results.length; i--;) {
     12 | 				results[i] = new Article(results[i]);
     13 | 			}
     14 | 			callback(err, results);
     15 | 		};
     16 | 	};
     17 | 
     18 | function Article(article) {
     19 | 	this.content = article.content;
     20 | 	this.title = article.title;
     21 | 	this.writer = article.writer;
     22 | 	this.id = article.id;
     23 | 	this.writeTime = article.writeTime;
     24 | 	this.lastModifyTime = article.lastModifyTime;
     25 | 	this.tags = article.tags;
     26 | }
     27 | 
     28 | module.exports = Article;
     29 | 
     30 | Article.prototype.save = function(callback) {
     31 | 	var article = {
     32 | 		content: this.content,
     33 | 		title: this.title,
     34 | 		writer: this.writer,
     35 | 		writeTime: new Date().getTime(),
     36 | 		lastModifyTime: new Date().getTime(),
     37 | 		tags: this.tags,
     38 | 		id: uuid.v4()
     39 | 	};
     40 | 	commonDao.save(collectionName, article, function(err, result) {
     41 | 		if (err) return callback(err);
     42 | 		if (!result[0]) return callback(new Error("保存失败"));
     43 | 		callback(err, new Article(result[0]));
     44 | 	});
     45 | };
     46 | 
     47 | Article.prototype.update = function(callback) {
     48 | 	commonDao.update(collectionName, {
     49 | 		id: this.id
     50 | 	}, {
     51 | 		content: this.content,
     52 | 		title: this.title,
     53 | 		lastModifyTime: new Date().getTime(),
     54 | 		tags: this.tags
     55 | 	}, callback);
     56 | };
     57 | 
     58 | Article.prototype.remove = function(callback) {
     59 | 	var articleId = this.id;
     60 | 	commonDao.remove(collectionName, {
     61 | 		id: articleId
     62 | 	}, callback);
     63 | };
     64 | 
     65 | Article.get = function(id, callback) {
     66 | 	commonDao.findOne(collectionName, {
     67 | 		id: id
     68 | 	}, function(err, result) {
     69 | 		if (err) return callback(err);
     70 | 		callback(err, result ? new Article(result) : result);
     71 | 	});
     72 | };
     73 | 
     74 | Article.countAll = function(callback) {
     75 | 	commonDao.count(collectionName, {}, callback);
     76 | };
     77 | 
     78 | Article.getAll = function(curPage, perPage, callback) {
     79 | 	commonDao.find(collectionName, {
     80 | 		sort: {
     81 | 			writeTime: -1
     82 | 		},
     83 | 		page: {
     84 | 			curPage: curPage,
     85 | 			perPage: perPage
     86 | 		}
     87 | 	}, __resultToListFn(callback));
     88 | };
     89 | 
     90 | Article.getByUser = function(username, curPage, perPage, callback) {
     91 | 	commonDao.find(collectionName, {
     92 | 		condition: {
     93 | 			writer: username
     94 | 		},
     95 | 		sort: {
     96 | 			writeTime: -1
     97 | 		},
     98 | 		page: {
     99 | 			curPage: curPage,
    100 | 			perPage: perPage
    101 | 		}
    102 | 	}, __resultToListFn(callback));
    103 | };
    104 | 
    105 | Article.countByUser = function(username, callback) {
    106 | 	commonDao.count(collectionName, {
    107 | 		writer: username
    108 | 	}, callback);
    109 | };
    110 | 
    111 | Article.getByTags = function(tags, curPage, perPage, callback) {
    112 | 	commonDao.find(collectionName, {
    113 | 		condition: {
    114 | 			tags: {
    115 | 				$all: tags
    116 | 			}
    117 | 		},
    118 | 		sort: {
    119 | 			writeTime: -1
    120 | 		},
    121 | 		page: {
    122 | 			curPage: curPage,
    123 | 			perPage: perPage
    124 | 		}
    125 | 	}, __resultToListFn(callback));
    126 | };
    127 | 
    128 | Article.getByTitle = function(title, curPage, perPage, callback) {
    129 | 	console.log(title);
    130 | 	commonDao.find(collectionName, {
    131 | 		condition: {
    132 | 			title: new RegExp(title, "i")
    133 | 		},
    134 | 		sort: {
    135 | 			writeTime: -1
    136 | 		},
    137 | 		page: {
    138 | 			curPage: curPage,
    139 | 			perPage: perPage
    140 | 		}
    141 | 	}, __resultToListFn(callback));
    142 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/Bookmark.js:
    --------------------------------------------------------------------------------
      1 | var commonDao = require("./CommonDAO.js"),
      2 | 	collectionName = "bookmark",
      3 | 	uuid = require("node-uuid"),
      4 | 	__resultToListFn = function(callback) {
      5 | 		return function(err, results) {
      6 | 			var i;
      7 | 			if (err) return callback(err);
      8 | 			for (i = results.length; i--;) {
      9 | 				results[i] = new Bookmark(results[i]);
     10 | 			}
     11 | 			callback(err, results);
     12 | 		};
     13 | 	};
     14 | 
     15 | function Bookmark(bookmark) {
     16 | 	this.username = bookmark.username;
     17 | 	this.articleId = bookmark.articleId;
     18 | 	this.time = bookmark.time;
     19 | 	this.id = bookmark.id;
     20 | }
     21 | 
     22 | module.exports = Bookmark;
     23 | 
     24 | Bookmark.prototype.save = function(callback) {
     25 | 	commonDao.save(collectionName, {
     26 | 		username: this.username,
     27 | 		articleId: this.articleId,
     28 | 		time: new Date().getTime(),
     29 | 		id: uuid.v4()
     30 | 	}, function(err, result) {
     31 | 		if (err) return callback(err);
     32 | 		if (!result[0]) return callback(new Error("保存失败"));
     33 | 		callback(err, new Bookmark(result[0]));
     34 | 	});
     35 | };
     36 | 
     37 | Bookmark.prototype.remove = function(callback) {
     38 | 	commonDao.remove(collectionName, {
     39 | 		username: this.username,
     40 | 		articleId: this.articleId
     41 | 	}, callback);
     42 | };
     43 | 
     44 | 
     45 | Bookmark.get = function(bookmarkId, callback) {
     46 | 	commonDao.findOne(collectionName, {
     47 | 		id: bookmarkId
     48 | 	}, function(err, result) {
     49 | 		if (err) return callback(err);
     50 | 		callback(err, result ? new Bookmark(result) : result);
     51 | 	});
     52 | };
     53 | 
     54 | Bookmark.checkBooked = function(username, articleId, callback) {
     55 | 	commonDao.findOne(collectionName, {
     56 | 		username: username,
     57 | 		articleId: articleId
     58 | 	}, function(err, result) {
     59 | 		if (err) return callback(err);
     60 | 		if (!result) return callback(err, false);
     61 | 		return callback(err, true);
     62 | 	});
     63 | };
     64 | 
     65 | Bookmark.getByUser = function(username, curPage, perPage, callback) {
     66 | 	commonDao.find(collectionName, {
     67 | 		condition: {
     68 | 			username: username
     69 | 		},
     70 | 		sort: {
     71 | 			time: -1
     72 | 		},
     73 | 		page: {
     74 | 			curPage: curPage,
     75 | 			perPage: perPage
     76 | 		}
     77 | 	}, __resultToListFn(callback));
     78 | };
     79 | 
     80 | Bookmark.countByUser = function(username, callback) {
     81 | 	commonDao.count(collectionName, {
     82 | 		username: username
     83 | 	}, callback);
     84 | };
     85 | 
     86 | Bookmark.getByArticle = function(articleId, callback) {
     87 | 	commonDao.find(collectionName, {
     88 | 		condition: {
     89 | 			articleId: articleId
     90 | 		},
     91 | 		sort: {
     92 | 			time: -1
     93 | 		}
     94 | 	}, __resultToListFn(callback));
     95 | };
     96 | 
     97 | Bookmark.countByArticle = function(articleId, callback) {
     98 | 	commonDao.count(collectionName, {
     99 | 		articleId: articleId
    100 | 	}, function(err, total) {
    101 | 		if (err) return callback(err);
    102 | 		callback(err, total);
    103 | 	});
    104 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/Comment.js:
    --------------------------------------------------------------------------------
      1 | var commonDao = require("./CommonDAO.js"),
      2 | 	collectionName = "comment",
      3 | 	uuid = require("node-uuid"),
      4 | 	Admire = require("./Admire.js"),
      5 | 	async = require("async"),
      6 | 	__resultToListFn = function(callback) {
      7 | 		return function(err, results) {
      8 | 			var i;
      9 | 			if (err) {
     10 | 				return callback(err);
     11 | 			}
     12 | 			for (i = results.length; i--;) {
     13 | 				results[i] = new Comment(results[i]);
     14 | 			}
     15 | 			callback(err, results);
     16 | 		};
     17 | 	};
     18 | 
     19 | function Comment(comment) {
     20 | 	this.comment = comment.comment;
     21 | 	this.username = comment.username;
     22 | 	this.reply = comment.reply;
     23 | 	this.articleId = comment.articleId;
     24 | 	this.time = comment.time;
     25 | 	this.id = comment.id;
     26 | }
     27 | 
     28 | module.exports = Comment;
     29 | 
     30 | Comment.prototype.save = function(callback) {
     31 | 	commonDao.save(collectionName, {
     32 | 		comment: this.comment,
     33 | 		username: this.username,
     34 | 		articleId: this.articleId,
     35 | 		time: new Date().getTime(),
     36 | 		reply: this.reply,
     37 | 		id: uuid.v4()
     38 | 	}, function(err, result) {
     39 | 		if (err) return callback(err);
     40 | 		if (!result[0]) return new Error("保存评论失败");
     41 | 		return callback(err, new Comment(result[0]));
     42 | 	});
     43 | };
     44 | 
     45 | Comment.prototype.remove = function(callback) {
     46 | 	var commentId = this.id;
     47 | 	commonDao.remove(collectionName, {
     48 | 		id: commentId
     49 | 	}, callback);
     50 | };
     51 | 
     52 | Comment.get = function(commentId, callback) {
     53 | 	commonDao.findOne(collectionName, {
     54 | 		id: commentId
     55 | 	}, function(err, result) {
     56 | 		if (err) return callback(err);
     57 | 		callback(err, result ? new Comment(result) : result);
     58 | 	});
     59 | };
     60 | 
     61 | Comment.getByArticle = function(articleId, curPage, perPage, callback) {
     62 | 	commonDao.find(collectionName, {
     63 | 		condition: {
     64 | 			articleId: articleId
     65 | 		},
     66 | 		sort: {
     67 | 			time: -1
     68 | 		},
     69 | 		page: {
     70 | 			curPage: curPage,
     71 | 			perPage: perPage
     72 | 		}
     73 | 	}, __resultToListFn(callback));
     74 | };
     75 | 
     76 | Comment.getByUser = function(username, curPage, perPage, callback) {
     77 | 	commonDao.find(collectionName, {
     78 | 		condition: {
     79 | 			username: username
     80 | 		},
     81 | 		sort: {
     82 | 			time: -1
     83 | 		},
     84 | 		page: {
     85 | 			curPage: curPage,
     86 | 			perPage: perPage
     87 | 		}
     88 | 	}, __resultToListFn(callback));
     89 | };
     90 | 
     91 | Comment.countByUser = function(username, callback) {
     92 | 	commonDao.count(collectionName, {
     93 | 		username: username
     94 | 	}, callback);
     95 | };
     96 | 
     97 | Comment.countByArticle = function(articleId, callback) {
     98 | 	commonDao.count(collectionName, {
     99 | 		articleId: articleId
    100 | 	}, callback);
    101 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/CommonDAO.js:
    --------------------------------------------------------------------------------
     1 | var MongoClient = require('mongodb').MongoClient,
     2 | 	setting = require("../setting.js"),
     3 | 	client;
     4 | console.log("MongoDB connecting...");
     5 | exports.save = function(collectionName, obj, callback) {
     6 | 	MongoClient.connect(setting.host, function(err, client) {
     7 | 		client.collection(collectionName, function(err, collection) {
     8 | 			if (err) return callback(err);
     9 | 			collection.insert(obj, {
    10 | 				safe: true
    11 | 			}, function(err, result) {
    12 | 				callback(err, result);
    13 | 				client.close();
    14 | 			});
    15 | 		});
    16 | 	});
    17 | };
    18 | 
    19 | exports.findOne = function(collectionName, oArgs, callback) {
    20 | 	MongoClient.connect(setting.host, function(err, client) {
    21 | 		client.collection(collectionName, function(err, collection) {
    22 | 			if (err) return callback(err);
    23 | 			collection.findOne(oArgs, function(err, result) {
    24 | 				callback(err, result);
    25 | 				client.close();
    26 | 			});
    27 | 		});
    28 | 	});
    29 | };
    30 | 
    31 | exports.update = function(collectionName, oArgs, newObj, callback) {
    32 | 	if (newObj._id) delete newObj._id;
    33 | 	MongoClient.connect(setting.host, function(err, client) {
    34 | 		client.collection(collectionName, function(err, collection) {
    35 | 			if (err) return callback(err);
    36 | 			collection.update(oArgs, {
    37 | 					$set: newObj
    38 | 				}, {
    39 | 					safe: true,
    40 | 					upsert: false,
    41 | 					multi: true
    42 | 				},
    43 | 				function(err, result) {
    44 | 					callback(err, result);
    45 | 					client.close();
    46 | 				});
    47 | 		});
    48 | 	});
    49 | 
    50 | };
    51 | 
    52 | exports.remove = function(collectionName, oArgs, callback) {
    53 | 	MongoClient.connect(setting.host, function(err, client) {
    54 | 		client.collection(collectionName, function(err, collection) {
    55 | 			if (err) return callback(err);
    56 | 			collection.remove(oArgs, function(err, result) {
    57 | 				callback(err, result);
    58 | 				client.close();
    59 | 			});
    60 | 		});
    61 | 	});
    62 | };
    63 | 
    64 | exports.count = function(collectionName, oArgs, callback) {
    65 | 	MongoClient.connect(setting.host, function(err, client) {
    66 | 		client.collection(collectionName, function(err, collection) {
    67 | 			if (err) return callback(err);
    68 | 			collection.count(oArgs, function(err, result) {
    69 | 				callback(err, result);
    70 | 				client.close();
    71 | 			});
    72 | 		});
    73 | 	});
    74 | };
    75 | 
    76 | exports.find = function(collectionName, oArgs, callback) {
    77 | 	MongoClient.connect(setting.host, function(err, client) {
    78 | 		client.collection(collectionName, function(err, collection) {
    79 | 			var tmp,
    80 | 				skip;
    81 | 			if (err) return callback(err);
    82 | 			tmp = collection.find(oArgs.condition);
    83 | 			if (oArgs.sort) tmp.sort(oArgs.sort);
    84 | 			if (oArgs.page) {
    85 | 				skip = oArgs.page.curPage * oArgs.page.perPage;
    86 | 				tmp.limit(oArgs.page.perPage).skip(skip);
    87 | 			}
    88 | 			tmp.toArray(function(err, result) {
    89 | 				callback(err, result);
    90 | 				client.close();
    91 | 			});
    92 | 		});
    93 | 	});
    94 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/Remind.js:
    --------------------------------------------------------------------------------
      1 | var commonDao = require("./CommonDAO.js"),
      2 | 	collectionName = "remind",
      3 | 	uuid = require("node-uuid"),
      4 | 	async = require("async"),
      5 | 	__resultToListFn = function(callback) {
      6 | 		return function(err, results) {
      7 | 			var i;
      8 | 			if (err) return callback(err);
      9 | 			for (i = results.length; i--;) {
     10 | 				results[i] = new Remind(results[i]);
     11 | 			}
     12 | 			callback(err, results);
     13 | 		};
     14 | 	};
     15 | 
     16 | function Remind(remind) {
     17 | 	this.id = remind.id;
     18 | 	this.time = remind.time;
     19 | 	this.type = remind.type;
     20 | 	this.ref = remind.ref;
     21 | 	this.readed = remind.readed;
     22 | 	this.user = remind.user;
     23 | }
     24 | 
     25 | module.exports = Remind;
     26 | 
     27 | Remind.prototype.save = function(callback) {
     28 | 	commonDao.save(collectionName, {
     29 | 		time: new Date().getTime(),
     30 | 		type: this.type,
     31 | 		ref: this.ref,
     32 | 		user: this.user,
     33 | 		readed: false,
     34 | 		id: uuid.v4()
     35 | 	}, function(err, result) {
     36 | 		if (err) return callback(err);
     37 | 		if (!result[0]) return callback(new Error("保存失败"));
     38 | 		callback(err, new Remind(result[0]));
     39 | 	});
     40 | };
     41 | 
     42 | Remind.getOne = function(remindId, callback) {
     43 | 	commonDao.findOne(collectionName, {
     44 | 		id: remindId
     45 | 	}, function(err, result) {
     46 | 		if (err) return callback(err);
     47 | 		callback(err, result ? new Remind(result) : null);
     48 | 	});
     49 | };
     50 | 
     51 | Remind.prototype.remove = function(callback) {
     52 | 	commonDao.remove(collectionName, {
     53 | 		id: this.id
     54 | 	}, callback);
     55 | };
     56 | 
     57 | Remind.prototype.update = function(callback) {
     58 | 	commonDao.update(collectionName, {
     59 | 		id: this.id
     60 | 	}, {
     61 | 		readed: this.readed
     62 | 	}, callback);
     63 | };
     64 | 
     65 | Remind.getByUser = function(username, curPage, perPage, callback) {
     66 | 	commonDao.find(collectionName, {
     67 | 		condition: {
     68 | 			user: username
     69 | 		},
     70 | 		sort: {
     71 | 			time: -1
     72 | 		},
     73 | 		page: {
     74 | 			curPage: curPage,
     75 | 			perPage: perPage
     76 | 		},
     77 | 	}, __resultToListFn(callback));
     78 | };
     79 | 
     80 | Remind.getByUserAndType = function(username, type, curPage, perPage, callback) {
     81 | 	commonDao.find(collectionName, {
     82 | 		condition: {
     83 | 			user: username,
     84 | 			type: type
     85 | 		},
     86 | 		page: {
     87 | 			curPage: curPage,
     88 | 			perPage: perPage
     89 | 		},
     90 | 		sort: {
     91 | 			time: -1
     92 | 		}
     93 | 	}, __resultToListFn(callback));
     94 | };
     95 | 
     96 | Remind.countByUser = function(username, callback) {
     97 | 	commonDao.count(collectionName, {
     98 | 		user: username
     99 | 	}, callback);
    100 | };
    101 | 
    102 | Remind.countByUserAndType = function(username, type, callback) {
    103 | 	commonDao.count(collectionName, {
    104 | 		user: username,
    105 | 		type: type
    106 | 	}, callback);
    107 | };
    108 | 
    109 | Remind.countUnreadByUser = function(username, callback) {
    110 | 	commonDao.count(collectionName, {
    111 | 		user: username,
    112 | 		readed: false
    113 | 	}, callback);
    114 | };
    115 | 
    116 | Remind.countUnreadByUserAndType = function(username, type, callback) {
    117 | 	commonDao.count(collectionName, {
    118 | 		user: username,
    119 | 		type: type,
    120 | 		readed: false
    121 | 	}, callback);
    122 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/Tag.js:
    --------------------------------------------------------------------------------
     1 | var commonDao = require("./CommonDAO.js"),
     2 | 	collectionName = "tag",
     3 | 	uuid = require("node-uuid"),
     4 | 	__resultToListFn = function(callback) {
     5 | 		return function(err, results) {
     6 | 			var i;
     7 | 			if (err) return callback(err);
     8 | 			for (i = results.length; i--;) {
     9 | 				results[i] = new Tag(results[i]);
    10 | 			}
    11 | 			callback(err, results);
    12 | 
    13 | 		};
    14 | 	};
    15 | 
    16 | function Tag(tag) {
    17 | 	this.name = tag.name;
    18 | 	this.createTime = tag.createTime;
    19 | 	this.id = tag.id;
    20 | 	this.color = tag.color;
    21 | }
    22 | 
    23 | module.exports = Tag;
    24 | 
    25 | Tag.prototype.save = function(callback) {
    26 | 	commonDao.save(collectionName, {
    27 | 		name: this.name,
    28 | 		color: this.color,
    29 | 		createTime: new Date().getTime(),
    30 | 		id: uuid.v4()
    31 | 	}, function(err, result) {
    32 | 		if (err) return callback(err);
    33 | 		if (!result[0]) return new Error("保存标签失败");
    34 | 		return callback(err, new Tag(result[0]));
    35 | 	});
    36 | };
    37 | 
    38 | Tag.get = function(id, callback) {
    39 | 	commonDao.findOne(collectionName, {
    40 | 		id: id
    41 | 	}, function(err, result) {
    42 | 		if (err) return callback(err);
    43 | 		callback(err, result ? new Tag(result) : result);
    44 | 	});
    45 | };
    46 | 
    47 | Tag.getAll = function(callback) {
    48 | 	commonDao.find(collectionName, {
    49 | 		sort: {
    50 | 			createTime: -1
    51 | 		}
    52 | 	}, __resultToListFn(callback));
    53 | };
    54 | 
    55 | Tag.getByFuzzyName = function(name, callback) {
    56 | 	commonDao.find(collectionName, {
    57 | 		condition: {
    58 | 			name: new RegExp(name)
    59 | 		},
    60 | 		sort: {
    61 | 			createTime: -1
    62 | 		}
    63 | 	}, __resultToListFn(callback));
    64 | };
    
    
    --------------------------------------------------------------------------------
    /routes/Model/User.js:
    --------------------------------------------------------------------------------
     1 | var commonDao = require("./CommonDAO.js"),
     2 | 	collectionName = "user",
     3 | 	__resultToListFn = function(callback) {
     4 | 		return function(err, results) {
     5 | 			var i;
     6 | 			if (err) {
     7 | 				return callback(err);
     8 | 			}
     9 | 			for (i = results.length; i--;) {
    10 | 				results[i] = new User(results[i]);
    11 | 			}
    12 | 			callback(err, results);
    13 | 
    14 | 		};
    15 | 	};
    16 | 
    17 | function User(user) {
    18 | 	this.username = user.username;
    19 | 	this.nickname = user.nickname;
    20 | 	this.password = user.password;
    21 | 	this.owner = user.owner;
    22 | 	this.avatar = user.avatar;
    23 | 	this.tags = user.tags;
    24 | }
    25 | 
    26 | module.exports = User;
    27 | 
    28 | User.prototype.save = function(callback) {
    29 | 	commonDao.save(collectionName, {
    30 | 		username: this.username,
    31 | 		password: this.password,
    32 | 		nickname: this.nickname,
    33 | 		owner: this.owner,
    34 | 		avatar: this.avatar,
    35 | 		tags: this.tags
    36 | 	}, function(err, result) {
    37 | 		if (err) return callback(err);
    38 | 		if (!result[0]) return new Error("保存评论失败");
    39 | 		return callback(err, new User(result[0]));
    40 | 	});
    41 | };
    42 | 
    43 | User.prototype.remove = function(callback) {
    44 | 	commonDao.remove(collectionName, {
    45 | 		username: this.username
    46 | 	}, callback);
    47 | };
    48 | 
    49 | User.prototype.update = function(callback) {
    50 | 	commonDao.update(collectionName, {
    51 | 		username: this.username
    52 | 	}, {
    53 | 		username: this.username,
    54 | 		password: this.password,
    55 | 		nickname: this.nickname,
    56 | 		owner: this.owner,
    57 | 		avatar: this.avatar,
    58 | 		tags: this.tags
    59 | 	}, callback);
    60 | };
    61 | 
    62 | User.get = function(username, callback) {
    63 | 	commonDao.findOne(collectionName, {
    64 | 		username: username
    65 | 	}, function(err, result) {
    66 | 		if (err) return callback(err);
    67 | 		callback(err, result ? new User(result) : result);
    68 | 	});
    69 | };
    70 | 
    71 | User.getAll = function(curPage, perPage, callback) {
    72 | 	commonDao.find(collectionName, {
    73 | 		page: {
    74 | 			curPage: curPage,
    75 | 			perPage: perPage
    76 | 		},
    77 | 		sort: {
    78 | 			username: 1
    79 | 		}
    80 | 	}, __resultToListFn(callback));
    81 | };
    82 | 
    83 | User.countAll = function(callback) {
    84 | 	commonDao.count(collectionName, {}, callback);
    85 | };
    
    
    --------------------------------------------------------------------------------
    /routes/index.js:
    --------------------------------------------------------------------------------
     1 | var Article = require("./Model/Article.js"),
     2 | 	User = require("./Model/User.js"),
     3 | 	Comment = require("./Model/Comment.js"),
     4 | 	Admire = require("./Model/Admire.js"),
     5 | 	Bookmark = require("./Model/Bookmark.js"),
     6 | 	markdown = require("markdown").markdown,
     7 | 	async = require("async"),
     8 | 	moment = require("moment");
     9 | 
    10 | exports.index = function(req, res) {
    11 | 	var page = (req.query.page || 1) - 1,
    12 | 		artPerPage = req.query.artPerPage || 5;
    13 | 	async.waterfall([
    14 | 
    15 | 		function(callback) {
    16 | 			Article.getAll(page, artPerPage, function(err, articles) {
    17 | 				if (err) return callback(err);
    18 | 				callback(err, articles);
    19 | 			});
    20 | 		},
    21 | 		function(articles, callback) {
    22 | 			Article.countAll(function(err, total) {
    23 | 				if (err) return callback(err);
    24 | 				callback(err, articles, total);
    25 | 			});
    26 | 		}
    27 | 	], function(err, articles, total) {
    28 | 		var i,
    29 | 			totalPage,
    30 | 			curPage,
    31 | 			startPage,
    32 | 			endPage;
    33 | 		if (err) return res.render("error", {
    34 | 			message: "获取文章列表时发生错误..."
    35 | 		});
    36 | 		for (i = articles.length; i--;) {
    37 | 			articles[i].content = markdown.toHTML(articles[i].content);
    38 | 			articles[i].writeTime = moment(articles[i].writeTime).fromNow();
    39 | 		}
    40 | 		totalPage = Math.ceil(total / artPerPage);
    41 | 		curPage = page + 1;
    42 | 
    43 | 		if (curPage <= 2) {
    44 | 			startPage = 1;
    45 | 			endPage = totalPage >= 5 ? 5 : totalPage;
    46 | 		} else if (curPage >= totalPage - 2) {
    47 | 			endPage = totalPage;
    48 | 			startPage = totalPage >= 5 ? totalPage - 4 : 1;
    49 | 		} else {
    50 | 			startPage = curPage - 2;
    51 | 			endPage = curPage + 2;
    52 | 		}
    53 | 		res.render("index", {
    54 | 			articles: articles,
    55 | 			curPage: page + 1,
    56 | 			artPerPage: artPerPage,
    57 | 			totalPage: totalPage,
    58 | 			startPage: startPage,
    59 | 			endPage: endPage
    60 | 		});
    61 | 	});
    62 | };
    63 | 
    64 | exports.userCenter = function(req, res) {
    65 | 	var username = req.query.username || req.session.user.username;
    66 | 	User.get(username, function(err, user) {
    67 | 		if (err) return res.render("error", {
    68 | 			message: err.message
    69 | 		});
    70 | 		res.render("userCenter", {
    71 | 			curUser: user
    72 | 		});
    73 | 	});
    74 | };
    75 | 
    76 | exports.advicePage = function(req, res) {
    77 | 	res.render("advice");
    78 | };
    79 | 
    80 | exports.searchPage = function(req, res) {
    81 | 	res.render("search");
    82 | };
    83 | 
    84 | exports.articleListPage = function(req, res){
    85 | 	res.render("listArticle");
    86 | };
    
    
    --------------------------------------------------------------------------------
    /routes/setting.js:
    --------------------------------------------------------------------------------
     1 | var fs = require('fs');
     2 | if(!fs.existsSync("upload_tmp")){
     3 | 	fs.mkdirSync("upload_tmp");
     4 | }
     5 | 
     6 | if(!fs.existsSync("public/gallary_sm")){
     7 | 	fs.mkdirSync("public/gallary_sm");
     8 | }
     9 | 
    10 | if(!fs.existsSync("public/gallary")){
    11 | 	fs.mkdirSync("public/gallary");
    12 | }
    13 | 
    14 | module.exports = {
    15 | 	//本地数据库测试
    16 | 	host : process.env.DB || "mongodb://127.0.0.1:27017/myblog",
    17 | 	gallary : {
    18 | 		small : "gallary_sm",
    19 | 		name : "gallary"
    20 | 	},
    21 | 	uploadDir : "upload_tmp"
    22 | };
    
    
    --------------------------------------------------------------------------------
    /upload_tmp/5792-oxlaq1.jpg:
    --------------------------------------------------------------------------------
    https://raw.githubusercontent.com/LingyuCoder/NodeBlog/80e5fba805415f2110a13bb3c1705258b079f744/upload_tmp/5792-oxlaq1.jpg
    
    
    --------------------------------------------------------------------------------
    /views/advice.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 | 
     5 | block content
     6 | 	div(class="container")
     7 | 		div(class="jumbotron u-panel", style="margin-top:50px")
     8 | 			h1 感谢您提供宝贵的意见
     9 | 			p 如果您对这个博客有任何意见和建议,或者遇到了任何bug,均可在此进行提交
    10 | 			p 如果您喜欢这个博客,请分享给你的好友:
    11 | 				div(class="jiathis_style_32x32")
    12 | 					a(class="jiathis_button_qzone")
    13 | 					a(class="jiathis_button_tsina")
    14 | 					a(class="jiathis_button_tqq")
    15 | 					a(class="jiathis_button_renren")
    16 | 					a(class="jiathis_button_kaixin001")
    17 | 					a(href="http://www.jiathis.com/share", class="jiathis jiathis_txt jtico jtico_jiathis", target="_blank")
    18 | 					a(class="jiathis_counter_style")
    19 | 				div(class="clearfix")
    20 | 		div(class = "ds-thread")
    21 | 
    22 | block javascript
    23 | 	script(type="text/javascript",src="http://v3.jiathis.com/code/jia.js",charset="utf-8")
    24 | 	script(type = 'text/javascript')
    25 | 		var duoshuoQuery = {
    26 | 			short_name: "skyinlayer"
    27 | 		};
    28 | 		(function() {
    29 | 			var ds = document.createElement('script');
    30 | 			ds.type = 'text/javascript';
    31 | 			ds.async = true;
    32 | 			ds.src = 'http://static.duoshuo.com/embed.js';
    33 | 			ds.charset = 'UTF-8';
    34 | 			(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ds);
    35 | 		})();
    36 | 
    37 | 
    
    
    --------------------------------------------------------------------------------
    /views/articleDetail.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 |   link(rel='stylesheet', href='/stylesheets/github.css')
     5 |   link(rel='stylesheet', href='/stylesheets/pageTools/tag.css')
     6 |   link(rel='stylesheet', href='/stylesheets/pageTools/admire.css')
     7 |   link(rel='stylesheet', href='/stylesheets/pageTools/comment.css')
     8 |   link(rel='stylesheet', href='/stylesheets/pageTools/user.css')
     9 |   link(rel='stylesheet', href='/stylesheets/pageTools/bookmark.css') 
    10 |   link(rel='stylesheet', href='/stylesheets/page/articleDetail.css')
    11 |   //- script(src="http://tjs.sjs.sinajs.cn/open/api/js/wb.js", type="text/javascript", charset="utf-8")
    12 | block content
    13 |   div(class="container")
    14 |     div(class="g-art", id="artBody")
    15 |       div(class="u-panel g-art-body")
    16 |         div(class="u-flag")
    17 |           div(class="u-flag-left")
    18 |             h3
    19 |               !=article.title
    20 |         section
    21 |           !=article.content
    22 |         div(class="g-art-footer")
    23 |           div(id="bookmark", aid="#{article.id}", cur=user?"#{user.username}":"")
    24 |           div(style="float:right;padding:5px 10px")
    25 |             //- wb:share-button(appkey="1yj5nG", addition="number", type="button", default_text="#{article.title} 来自 天镶的博客", ralateUid="1162383197")
    26 |           div(class="clearfix")
    27 |         hr
    28 |         div(id="comments", aid="#{article.id}", cur="0", curUser=user?"#{user.username}":"")
    29 |           div(class="g-container")
    30 |           div(class="u-more") 点击获取更多
    31 | 
    32 |         div(id="replyComment", class="g-reply-form")
    33 |           form(action="/nor/comment_addComment", method="post")
    34 |             input(type="hidden", name="articleId", value="#{article.id}")
    35 |             input(type="hidden", name="replyId")
    36 |             div(class="form-group")
    37 |                 textarea(class="form-control", name="comment", id="inputComment", style="resize: none", rows=2)
    38 |             div(class="form-group")
    39 |                 button(class="btn btn-success", type="submit", style="float:right") 发送
    40 |           div(class="clearfix")
    41 | 
    42 |         div(id="newComments") 
    43 |           if user
    44 |             h3 新评论:
    45 |             form(action="/nor/comment_addComment", method="post")
    46 |               input(type="hidden", name="articleId", value="#{article.id}")
    47 |               div(class="form-group")
    48 |                 textarea(class="form-control", name="comment", id="inputComment", style="resize: none", rows=4)
    49 |               div(class="form-group")
    50 |                 button(class="btn btn-success", id="sendComment", type="submit", style="float:left") 发送
    51 |                 button(class="btn btn-danger", type="button" ,id="clearComment", style="float:right") 清空
    52 |           else
    53 |             h3(style="text-align:center") 请登录后评论
    54 |       div(class="g-art-info hidden-sm")
    55 |         div(class="u-panel")
    56 |           div(class="g-user")
    57 |             div(class="u-avatar", uid="#{article.writer}")
    58 |             div(class="u-nick")
    59 |             div(class="clearfix")
    60 |           div(class="u-time") #{"作于: " + article.writeTime}
    61 |           if user&&user.owner
    62 |             div(class="g-opt")
    63 |               a(class="btn btn-primary", style="width:100%;margin-top:10px", href="/nor/conf/article_edit?articleId=#{article.id}") 修改
    64 |               button(class="btn btn-danger", aid="#{article.id}",style="width:100%;margin-top:10px", id="deleteArticle") 删除
    65 |         div(class="u-panel", style="margin-top: 20px") 文章标签:
    66 |           div(class="u-tags", id="tags", aid="#{article.id}")
    67 | 
    68 | block javascript
    69 |   script(type='text/javascript', src='/javascripts/tools/highlight.pack.js')
    70 |   script(type='text/javascript', src='/javascripts/pageTools/Tag.js')
    71 |   script(type='text/javascript', src='/javascripts/pageTools/Admire.js')
    72 |   script(type='text/javascript', src='/javascripts/pageTools/Comment.js')
    73 |   script(type='text/javascript', src='/javascripts/pageTools/Article.js')
    74 |   script(type='text/javascript', src='/javascripts/pageTools/User.js')
    75 |   script(type='text/javascript', src='/javascripts/pageTools/Bookmark.js')
    76 |   script(type='text/javascript', src='/javascripts/page/articleDetail.js')
    
    
    --------------------------------------------------------------------------------
    /views/broadchat.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 | 	style(type="text/stylesheet")
     5 | 		.g-row {
     6 | 			width: 100%;
     7 | 			margin-top:40px;
     8 | 		}
     9 | 		.g-row:after{
    10 | 			content:"";
    11 | 			display: table;
    12 | 			clear:both;
    13 | 		}
    14 | block content
    15 | 	div(class="container")
    16 | 		h2
    17 | 			strong 版聊
    18 | 		div(class="g-row", style="font-size:120%;font-weight: bolder")
    19 | 			div(class="", style="width: 32%;float:right") 
    20 | 				div(class="u-panel", id="users") 版上的用户:
    21 | 					hr
    22 | 				div(class="u-panel", style="margin-top:20px", id="logs")
    23 | 			div(class="u-panel", style="width: 66%;float:left")
    24 | 				div(class="panel-body",nick=user?"#{user.nickname}":"游客", id="chat")
    25 | 				div(class="form-group", style="padding: 20px 0;")
    26 | 					input(type="text",class="form-control", style="width: 83%;float:left", id="message")
    27 | 					button(class="btn btn-success", style="width: 15%;float:right", id="send") 发送 
    28 | 				div(class="form-group", style="padding: 20px 0;")
    29 | 					input(type="text",class="form-control", style="width: 83%;float:left", id="nickname")
    30 | 					button(class="btn btn-success", style="width: 15%;float:right", id="changeNick") 修改昵称 
    31 | 
    32 | 
    33 | block javascript
    34 | 	script(type='text/javascript', src="/javascripts/exp/broadchat.js")
    35 | 
    36 | 
    
    
    --------------------------------------------------------------------------------
    /views/editArticle.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 |   link(rel='stylesheet', href='/stylesheets/github.css')
     5 |   link(rel='stylesheet', href='/stylesheets/pageTools/tag.css')
     6 |   link(rel='stylesheet', href='/stylesheets/page/writeArticle.css')
     7 | block content
     8 |   div(class="container")
     9 |     h2
    10 |       strong 修改文章
    11 |     div(class="u-panel")
    12 |       div(class="alert alert-danger", id="formValidate", style="display:none")
    13 |       div(class="form-group")
    14 |         label(for="inputTitle") 
    15 |           h3 标题:
    16 |         input(class="form-control", type="text", id="inputTitle", placeholder="文章标题", value="#{article.title}")
    17 |       div(class="panel", style="padding:10px;height:80%;background:transparent")
    18 |         div(class="u-panel-body" id="leftPanel")
    19 |           textarea(class="u-pane", id="inputArticle", style="resize: none;")
    20 |             =article.content
    21 |         div(class="u-panel-body" id="rightPanel")
    22 |           div(class="u-pane", id="outputArticle")
    23 |         div(style="clear:both")
    24 |       div(class="row")
    25 |         input(type="hidden", name="tags")
    26 |         div(class="col-md-6")
    27 |           h2 本文标签
    28 |           hr
    29 |           div(id="articleTags", aid="#{article.id}")
    30 |         div(class="col-md-6")
    31 |           h2 所有标签
    32 |           hr
    33 |           div(id="allTags")
    34 |           hr
    35 |           span(class="label b-label-1", style="padding:8px 5px", id="newTag")
    36 |             input(id="newTagInput",type="text", placeholder="标签名", color="#428bca")
    37 |             span(class="glyphicon glyphicon-plus u-tag-create", style="margin-left:5px;cursor:pointer", id="createTag")
    38 |           span(class="label b-label-1 u-label-picker", value=1, color="#428bca") 深蓝
    39 |           span(class="label b-label-2 u-label-picker", value=2, color="#5cb85c") 绿色
    40 |           span(class="label b-label-3 u-label-picker", value=3, color="#5cb0de") 淡蓝
    41 |           span(class="label b-label-4 u-label-picker", value=4, color="#f0ad4e") 黄色
    42 |           span(class="label b-label-5 u-label-picker", value=5, color="#d9543f") 红色
    43 |       div(class="form-group", style="margin-top:20px")
    44 |         button(class="btn btn-primary", style="width:100%", id="saveArtBtn", aid="#{article.id}") 保存文章
    45 | 
    46 | block javascript
    47 |   script(type='text/javascript', src='/javascripts/tools/showdown.js')
    48 |   script(type='text/javascript', src='/javascripts/tools/highlight.pack.js')
    49 |   script(type='text/javascript', src='/javascripts/pageTools/Tag.js')
    50 |   script(type='text/javascript', src='/javascripts/page/editArticle.js')
    51 | 
    
    
    --------------------------------------------------------------------------------
    /views/error.jade:
    --------------------------------------------------------------------------------
    1 | #{message}
    
    
    --------------------------------------------------------------------------------
    /views/gallary.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 | 	link(rel='stylesheet', href='/stylesheets/page/gallary.css')
     5 | block content
     6 | 	div(class="u-block", id="blocker")
     7 | 		div(class="u-loading") 加载中,请等待
     8 | 	div(class="u-fillPic", id="filler")
     9 | 		div(class="u-opt u-close")
    10 | 			span(class="glyphicon glyphicon-remove")
    11 | 		center
    12 | 			img
    13 | 	div(class="container")
    14 | 		div(id="gallary", class="row")
    15 | 			div(class="col-sm-3 g-gal-col", index=0, id="col-0")
    16 | 			div(class="col-sm-3 g-gal-col", index=1, id="col-1")
    17 | 			div(class="col-sm-3 g-gal-col", index=2, id="col-2")
    18 | 			div(class="col-sm-3 g-gal-col", index=3, id="col-3")
    19 | 		div(class="clearfix")
    20 | 		div(class="scrollFooter" ) 加载中,请稍后
    21 | 	if user&&user.owner
    22 | 		div(class="glyphicon glyphicon-trash u-conf-opt u-trash", id="trash")
    23 | 		div(class="glyphicon glyphicon-upload u-conf-opt u-upload", id="upload")
    24 | block javascript
    25 | 	script(type='text/javascript', src='/javascripts/tools/jquery-mousewheel.js')
    26 | 	script(type='text/javascript', src='/javascripts/page/gallary.js')
    
    
    --------------------------------------------------------------------------------
    /views/index.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 | 	link(rel='stylesheet', href='/stylesheets/github.css')
     5 | 	link(rel='stylesheet', href='/stylesheets/pageTools/tag.css')
     6 | 	link(rel='stylesheet', href='/stylesheets/pageTools/user.css')
     7 | 	link(rel='stylesheet', href='/stylesheets/pageTools/comment.css')
     8 | 	link(rel='stylesheet', href='/stylesheets/pageTools/bookmark.css')
     9 | 	link(rel='stylesheet', href='/stylesheets/page/index.css')
    10 | block content
    11 | 	div(class='container', style="padding-top: 20px")
    12 | 		each article in articles
    13 | 			div(class="row" style="")
    14 | 				div(class='g-art-info')
    15 | 					div(class="u-avatar", uid="#{article.writer}")
    16 | 					div(class="u-time") #{article.writeTime}
    17 | 
    18 | 				div(class='g-art-body')
    19 | 					div(class="u-dot")
    20 | 					div(class="u-panel", aid="#{article.id}")
    21 | 						div(class="u-title")
    22 | 							h3 #{article.title}
    23 | 						hr
    24 | 						div
    25 | 							!=article.content
    26 | 						hr
    27 | 						div(class="g-art-footer")
    28 | 							div(class="m-tags", aid="#{article.id}")
    29 | 							div(class="u-item u-book", aid="#{article.id}", cur=user?"#{user.username}":"") 
    30 | 							div(class="u-item u-comment", aid="#{article.id}")
    31 | 							div(class="clearfix")
    32 | 		ul(class="pager")
    33 | 			li(class=curPage===1?"previous disabled" : "previous") 
    34 | 				a(href=curPage===1?"javascript:void(0)":"/index?page=#{curPage-1}")
    35 | 					←上一页
    36 | 			li(class=curPage===totalPage?"next disabled" : "next") 
    37 | 				a(href=curPage===totalPage?"javascript:void(0)":"/index?page=#{curPage+1}")
    38 | 					→下一页
    39 | 
    40 | block javascript
    41 | 	script(type='text/javascript', src='/javascripts/tools/highlight.pack.js')
    42 | 	script(type='text/javascript', src='/javascripts/pageTools/Tag.js')
    43 | 	script(type='text/javascript', src='/javascripts/pageTools/User.js')
    44 | 	script(type='text/javascript', src='/javascripts/pageTools/Comment.js')
    45 | 	script(type='text/javascript', src='/javascripts/pageTools/Bookmark.js')
    46 | 	script(type='text/javascript', src='/javascripts/page/index.js')
    
    
    --------------------------------------------------------------------------------
    /views/layout.jade:
    --------------------------------------------------------------------------------
     1 | doctype 5
     2 | html(xmlns:wb="http://open.weibo.com/wb")
     3 |   head
     4 |     meta(property="wb:webmaster", content="8984d0c69a7d9445")
     5 |     meta(name="description", content="天镶的博客,使用nodejs+mongodb搭建")
     6 |     meta(name="keywords", content="天镶,博客,skyinlayer,nodejs,mongodb,前端,html,css,javascript")
     7 |     title 天镶的博客
     8 |     link(rel="shortcut icon", href="/favicon.ico", type="image/x-icon")
     9 |     link(rel='stylesheet', href='/stylesheets/bootstrap.min.css')
    10 |     link(rel='stylesheet', href='/stylesheets/pageTools/remind.css')
    11 |     link(rel='stylesheet', href='/stylesheets/style.css')
    12 |     block style
    13 | 
    14 |   body
    15 |     div(class="b-clouds")
    16 |       div(class="clouds")
    17 |         div(class="cloud cloud-lg", style="left: 10%;top: 20%")
    18 |         div(class="cloud cloud-sm", style="top: 30%")
    19 |         div(class="cloud cloud-md", style="left: 20%;top: 50%")
    20 |         div(class="cloud cloud-lg", style="left: 60%;top: 20%")
    21 |         div(class="cloud cloud-sm", style="left: 50%;top: 30%")
    22 |         div(class="cloud cloud-md", style="left: 70%;top: 40%")
    23 |       div(class="block")
    24 |     div(class="scrollToTop", style="display:none", id="scrollToTop")
    25 |       span(class="glyphicon glyphicon-arrow-up")
    26 |     div(class='navbar navbar-inverse navbar-fixed-top')
    27 |       div(class="container")
    28 |         div(class='navbar-header')
    29 |           button(type='button', class='navbar-toggle', data-toggle='collapse', data-target='.navbar-collapse')
    30 |             span(class='icon-bar')
    31 |             span(class='icon-bar')
    32 |             span(class='icon-bar')
    33 |           a(class='navbar-brand', href='/index') 天镶的博客
    34 |         
    35 |         div(class='collapse navbar-collapse')
    36 |           ul(class='nav navbar-nav')
    37 |             li
    38 |               a(href='/index') 首页
    39 |             li
    40 |               a(href='/articleList') 文章列表
    41 |             li
    42 |               a(href='/search') 搜索
    43 |             li
    44 |               a(href='/gallary') 图片墙
    45 |             li(class="dropdown")
    46 |               a(href="#", class="dropdown-toggle", data-toggle="dropdown") 小玩意
    47 |                 b(class="caret")
    48 |               ul(class="dropdown-menu")
    49 |                 li
    50 |                   a(href="/broadchat") 版聊
    51 |             li
    52 |               a(href="/advicePage") 建议
    53 |             if user
    54 |               li
    55 |                 a(href="/userCenter") 个人中心
    56 |           ul(class='nav navbar-nav navbar-right')
    57 |             if user
    58 |               li(class="dropdown")
    59 |                 a(href="#", class="dropdown-toggle", data-toggle="dropdown", id="hasRemind") 
    60 |               li(class="dropdown")
    61 |                 a(href="#", class="dropdown-toggle", data-toggle="dropdown") #{user.nickname} 
    62 |                   b(class="caret")
    63 |                 ul(class="dropdown-menu")
    64 |                   if user.owner
    65 |                     li
    66 |                       a(href="/nor/conf/article_write") 写新文章
    67 |                     li
    68 |                       a(href="/article_list") 管理文章
    69 |                   li
    70 |                     a(href="/nor/user_detail") 修改个人信息
    71 |                   li
    72 |                     a(href="/user_logout") 登出
    73 |             else
    74 |               li
    75 |                 a(href='/user_loginPage') 登录
    76 |     div(class="g-main")
    77 |       block content
    78 |     div(class="footer") 
    79 |       hr
    80 |       p LingyuCoder 2013
    81 | 
    82 |     script(type='text/javascript', src='/javascripts/tools/jquery-1.10.2.min.js')
    83 |     script(type='text/javascript', src='/javascripts/tools/bootstrap.min.js')
    84 |     script(type='text/javascript', src='/javascripts/pageTools/Remind.js') 
    85 |     script(type='text/javascript', src='/javascripts/page/global.js') 
    86 | 
    87 |     block javascript
    88 | 
    
    
    --------------------------------------------------------------------------------
    /views/listArticle.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 |   link(rel='stylesheet', href='/stylesheets/github.css')
     5 |   link(rel='stylesheet', href='/stylesheets/page/listArticle.css')
     6 | block content
     7 |   div(class="container")
     8 |     div(class="g-arts")
     9 |     div(class="u-panel u-more") 向下滚动加载更多
    10 | 
    11 | block javascript
    12 |   script(type='text/javascript', src='/javascripts/tools/highlight.pack.js')
    13 |   script(type='text/javascript', src='/javascripts/pageTools/User.js')
    14 |   script(type='text/javascript', src='/javascripts/pageTools/Article.js')
    15 |   script(type='text/javascript', src='/javascripts/page/listArticle.js')
    16 |   if user && user.owner
    17 |     script(type='text/javascript', src='/javascripts/page/listArticle_owner.js')
    
    
    --------------------------------------------------------------------------------
    /views/login.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block content
     4 |   div(class='container')
     5 |     h1
     6 |       strong 登录
     7 |     if message
     8 |       div(class='alert alert-danger') #{message}
     9 |     div(class="alert alert-danger", id="formValidate", style="display:none")
    10 |     div(class="u-panel")
    11 |       div(class="panel-body")
    12 |         form(class="form-horizontal", method="post", action="/user_login", id="loginForm")
    13 |           div(class="form-group")
    14 |             label(for="inputUsername", class="col-sm-2 col-sm-offset-2 control-label") 用户名
    15 |             div(class="col-sm-5")
    16 |               input(type="text", name="username", class="form-control", id="inputUsername", placeholder="用户名")
    17 |           div(class="form-group")
    18 |             label(for="inputPassword", class="col-sm-2 col-sm-offset-2 control-label") 密码
    19 |             div(class="col-sm-5")
    20 |               input(type="password", name="password", class="form-control", id="inputPassword", placeholder="填写密码")
    21 |           div(class="form-group")
    22 |             button(type='submit', id='loginBtn', class='btn btn-success col-sm-1 col-sm-offset-4') 登录
    23 |             a(href="user_registPage", class="btn btn-primary col-sm-1 col-sm-offset-2") 注册
    24 |     
    25 | block javascript
    26 |   script(type='text/javascript', src='/javascripts/page/login.js')
    
    
    --------------------------------------------------------------------------------
    /views/regist.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block content
     4 |   div(class='container')
     5 |     h1
     6 |       strong 注册
     7 |     if message
     8 |       div(class="alert alert-danger") #{message}
     9 |     div(class="alert alert-danger", id="formValidate", style="display:none")
    10 |     div(class="u-panel")
    11 |       div(class="panel-body")
    12 |         form(class="form-horizontal", method="post", action="/user_regist", id="registForm")
    13 |           div(class="form-group")
    14 |             label(for="inputUsername", class="col-sm-2 col-sm-offset-2 control-label") 用户名
    15 |             div(class="col-sm-5")
    16 |               input(type="text", name="username", class="form-control", id="inputUsername", placeholder="用户名")
    17 |           div(class="form-group")
    18 |             label(for="inputNickname", class="col-sm-2 col-sm-offset-2 control-label") 昵称
    19 |             div(class="col-sm-5")
    20 |               input(type="text", name="nickname", class="form-control", id="inputNickname", placeholder="昵称")
    21 |           div(class="form-group")
    22 |             label(for="inputPassword", class="col-sm-2 col-sm-offset-2 control-label") 密码
    23 |             div(class="col-sm-5")
    24 |               input(type="password", name="password", class="form-control", id="inputPassword", placeholder="填写密码")
    25 |           div(class="form-group")
    26 |             label(for="inputPassAgain", class="col-sm-2 col-sm-offset-2 control-label") 密码重复
    27 |             div(class="col-sm-5")
    28 |               input(type="password", name="passAgain", class="form-control", id="inputPassAgain", placeholder="再次填写密码")
    29 |           div(class="form-group")
    30 |             button(type="submit" class="col-sm-1 col-sm-offset-4 btn btn-success") 注册
    31 |             a(class="col-sm-offset-2 col-sm-1 btn btn-primary", href="user_loginPage") 登录
    32 | 
    33 | block javascript
    34 |   script(type='text/javascript', src='/javascripts/page/regist.js')
    35 |             
    36 |             
    
    
    --------------------------------------------------------------------------------
    /views/search.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 | 	link(rel='stylesheet', href='/stylesheets/pageTools/tag.css')
     5 | 	link(rel='stylesheet', href='/stylesheets/page/search.css')
     6 | 
     7 | block content
     8 | 	div(class="container")
     9 | 		div(class="row", style="margin-top:40px")
    10 | 			div(class="col-sm-8")
    11 | 				div(class="g-arts u-panel")
    12 | 					div(id="articles", curPage=0)
    13 | 					div(class="u-more", id="more") 请根据条件进行搜索
    14 | 			div(class="col-sm-4")
    15 | 				div(class="g-tags u-panel")
    16 | 					h3 标签搜索:
    17 | 					hr
    18 | 					div(id="tags")
    19 | 					hr
    20 | 					p 已选择标签: 
    21 | 					div(id="chosenTags")
    22 | 					hr
    23 | 					button(class="btn btn-success", id="tagSearchBtn") 给我搜
    24 | 				div(class="g-tags u-panel")
    25 | 					h3 标题搜索:
    26 | 					hr
    27 | 					input(class="form-control", type="text", id="titleSearchInput", placeholder="请输入部分标题")	
    28 | 					hr
    29 | 					button(class="btn btn-success", id="titleSearchBtn") 给我搜
    30 | 
    31 | block javascript
    32 | 	script(type='text/javascript', src="/javascripts/pageTools/Tag.js")
    33 | 	script(type='text/javascript', src="/javascripts/pageTools/Article.js")
    34 | 	script(type='text/javascript', src="/javascripts/pageTools/User.js")
    35 | 	script(type='text/javascript', src="/javascripts/page/search.js")
    36 | 
    37 | 
    
    
    --------------------------------------------------------------------------------
    /views/userCenter.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 |   link(rel='stylesheet', href='/stylesheets/pageTools/comment.css')
     5 |   link(rel='stylesheet', href='/stylesheets/pageTools/tag.css')
     6 |   link(rel='stylesheet', href='/stylesheets/pageTools/admire.css')
     7 |   link(rel='stylesheet', href='/stylesheets/pageTools/user.css')
     8 |   link(rel='stylesheet', href='/stylesheets/pageTools/bookmark.css')
     9 |   link(rel='stylesheet', href='/stylesheets/pageTools/admire.css')
    10 |   link(rel='stylesheet', href='/stylesheets/pageTools/article.css')
    11 |   link(rel='stylesheet', href='/stylesheets/page/userCenter.css')
    12 | 
    13 | block content
    14 |   input(type="hidden", id="user", uid=user?"#{user.username}":"")
    15 |   input(type="hidden", id="curUser", uid="#{curUser.username}")
    16 |   div(class='container')
    17 |     h1
    18 |       div(style="float:left")
    19 |         strong #{curUser.nickname}的用户中心
    20 |       div(class="u-avatar", style="float:right", id="user")
    21 |       div(class="clearfix")
    22 |     
    23 |     div(class="g-row")
    24 |       div(class="g-left")
    25 |         div(class="list-group u-panel", id="chosePanel", style="padding:0;border-radius:20px;overflow:hidden")
    26 |           if user&&curUser.username === user.username
    27 |             a(href="#", class="list-group-item", ref="getComments") 收到的评论
    28 |               span(class="badge pull-right remind-count", type="comment")
    29 |             a(href="#", class="list-group-item", ref="getAdmires") 收到的贊
    30 |               span(class="badge pull-right remind-count", type="admire")
    31 |             a(href="#", class="list-group-item", ref="getBookmarks") 收到的收藏
    32 |               span(class="badge pull-right remind-count", type="bookmark")
    33 |           if curUser.owner
    34 |             a(href="#", class="list-group-item", ref="articles") 
    35 |               if user&&curUser.username === user.username
    36 |                 != "我的文章"
    37 |               else
    38 |                 != "ta的文章"
    39 |               span(class="badge pull-right article-count")
    40 |           a(href="#", class=curUser.owner?"list-group-item" : "list-group-item active", ref="bookmarks")
    41 |             if user&&curUser.username === user.username
    42 |               != "我的收藏"
    43 |             else
    44 |               != "ta的收藏"
    45 |             span(class="badge pull-right bookmark-count")
    46 |           a(href="#", class="list-group-item", ref="comments")
    47 |             if user&&curUser.username === user.username
    48 |               != "我的评论"
    49 |             else
    50 |               != "ta的评论"
    51 |             span(class="badge pull-right comment-count")
    52 |           a(href="#", class="list-group-item", ref="admires")
    53 |             if user&&curUser.username === user.username
    54 |               != "我赞过的评论"
    55 |             else
    56 |               != "ta赞过的评论"
    57 |             span(class="badge pull-right admire-count")
    58 |         div(class="u-panel", style="margin-top:20px")
    59 |           if user&&curUser.username === user.username
    60 |             != "我的标签:"
    61 |           else
    62 |             != "ta的标签:"
    63 |           div(id="tags")
    64 |       div(class="g-right")
    65 |         div(class="u-panel")
    66 |           if user&&curUser.username === user.username
    67 |             div(class="panel-body g-hide", id="getComments", cur="0")
    68 |               div(class="g-container")
    69 |               div(class="u-more") 点击加载更多
    70 |             div(class="panel-body g-hide", id="getAdmires", cur="0")
    71 |               div(class="g-container")
    72 |               div(class="u-more") 点击加载更多
    73 |             div(class="panel-body g-hide", id="getBookmarks", cur="0")
    74 |               div(class="g-container")
    75 |               div(class="u-more") 点击加载更多
    76 |           if curUser.owner
    77 |             div(class="panel-body g-hide", id="articles", cur="0")
    78 |               div(class="g-container")
    79 |               div(class="u-more") 点击加载更多
    80 | 
    81 |           div(class="panel-body g-hide", id="comments", cur="0")
    82 |             div(class="g-container")
    83 |             div(class="u-more") 点击加载更多
    84 |           div(class="panel-body g-hide", id="bookmarks", cur="0")
    85 |             div(class="g-container")
    86 |             div(class="u-more") 点击加载更多
    87 |           div(class="panel-body g-hide", id="admires", cur="0")
    88 |             div(class="g-container")
    89 |             div(class="u-more") 点击加载更多
    90 |        
    91 | block javascript
    92 |   script(type='text/javascript', src='/javascripts/pageTools/User.js')
    93 |   script(type='text/javascript', src='/javascripts/pageTools/Tag.js')
    94 |   script(type='text/javascript', src='/javascripts/pageTools/Article.js')
    95 |   script(type='text/javascript', src='/javascripts/pageTools/Bookmark.js')
    96 |   script(type='text/javascript', src='/javascripts/pageTools/Admire.js')
    97 |   script(type='text/javascript', src='/javascripts/pageTools/Comment.js')
    98 |   script(type='text/javascript', src='/javascripts/page/userCenter.js')
    
    
    --------------------------------------------------------------------------------
    /views/userDetail.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 |   link(rel='stylesheet', href='/stylesheets/pageTools/tag.css')
     5 |   link(rel='stylesheet', href='/stylesheets/pageTools/user.css')
     6 | 
     7 | block content
     8 |   div(class='container')
     9 |     h1
    10 |       strong 个人信息
    11 |     form(class="form-horizontal", method="post", action="/nor/user_modify", id="detail")
    12 |       div(class="u-panel")
    13 |         if message
    14 |           if success
    15 |             div(class="alert alert-success") #{message}
    16 |           else 
    17 |             div(class="alert alert-danger") #{message}
    18 |           div(class="alert alert-danger", id="formValidate", style="display:none")
    19 |         div(class="form-group")
    20 |           label(for="inputUsername", class="col-sm-2 col-sm-offset-2 control-label") 用户名
    21 |           div(class="col-sm-4")
    22 |             input(type="text", name="username", readonly="readonly", class="form-control", id="inputUsername", value="#{user.username}")
    23 |         div(class="form-group")
    24 |           label(for="inputNickname", class="col-sm-2 col-sm-offset-2 control-label") 昵称
    25 |           div(class="col-sm-4")
    26 |             input(type="text", name="nickname", class="form-control", id="inputNickname", value="#{user.nickname}")
    27 |         div(class="form-group")
    28 |           label(for="inputAvatar", class="col-sm-2 col-sm-offset-2 control-label") 头像地址
    29 |           div(class="col-sm-4")
    30 |             input(type="text", name="avatar", class="form-control", id="inputAvatar", value="#{user.avatar}")
    31 |         div(class="form-group")
    32 |           label(class="col-sm-2 col-sm-offset-2 control-label") 头像预览
    33 |           div(class="col-sm-4")
    34 |             div(class="u-user-avatar")
    35 |               img(src="#{user.avatar}",id="avatarPreview")
    36 |         div(class="form-group")
    37 |           label(for="inputPassword", class="col-sm-2 col-sm-offset-2 control-label") 密码
    38 |           div(class="col-sm-4")
    39 |             input(type="password", name="password", class="form-control", id="inputPassword", placeholder="填写密码,为空则不修改")
    40 |         div(class="form-group")
    41 |           label(for="inputPassAgain", class="col-sm-2 col-sm-offset-2 control-label") 密码重复
    42 |           div(class="col-sm-4")
    43 |             input(type="password", name="passwordAgain", class="form-control", id="inputPassAgain", placeholder="再次填写密码")
    44 |       div(class="form-group", style="margin-top:20px")
    45 |         input(type="hidden", name="tags")
    46 |         div(class="col-sm-6") 
    47 |           div(class="u-panel")
    48 |             h3 您的标签
    49 |             hr
    50 |             div(id="myTags", class="m-myTags")
    51 |         div(class="col-sm-6")
    52 |           div(class="u-panel")
    53 |             h3 所有标签
    54 |             hr
    55 |             div(id="allTags", class="m-allTags")
    56 |             hr
    57 |             span(class="label b-label-1", style="padding:8px 5px", id="newTag")
    58 |               input(id="newTagInput", type="text", placeholder="标签名", color="#428bca")
    59 |               span(class="glyphicon glyphicon-plus u-tag-create", style="margin-left:5px;cursor:pointer", id="createTag")
    60 |             span(class="label b-label-1 u-label-picker", value=1, color="#428bca") 深蓝
    61 |             span(class="label b-label-2 u-label-picker", value=2, color="#5cb85c") 绿色
    62 |             span(class="label b-label-3 u-label-picker", value=3, color="#5cb0de") 淡蓝
    63 |             span(class="label b-label-4 u-label-picker", value=4, color="#f0ad4e") 黄色
    64 |             span(class="label b-label-5 u-label-picker", value=5, color="#d9543f") 红色
    65 |       div(class="form-group")
    66 |         button(type="submit" class="col-sm-offset-3 col-sm-2 btn btn-primary") 提交修改
    67 |         a(class="btn btn-default col-sm-offset-2 col-sm-2", href="user_detail") 恢复
    68 |   
    69 | block javascript
    70 |   script(type='text/javascript', src='/javascripts/pageTools/Tag.js')
    71 |   script(type='text/javascript', src='/javascripts/page/userDetail.js')
    72 | 
    73 | 
    
    
    --------------------------------------------------------------------------------
    /views/writeArticle.jade:
    --------------------------------------------------------------------------------
     1 | extends layout
     2 | 
     3 | block style
     4 |   link(rel='stylesheet', href='/stylesheets/github.css')
     5 |   link(rel='stylesheet', href='/stylesheets/pageTools/tag.css')
     6 |   link(rel='stylesheet', href='/stylesheets/page/writeArticle.css')
     7 | 
     8 | block content
     9 |   div(class="container")
    10 |     form(action="/nor/conf/article_save", method="post", id="articleForm")
    11 |       h2
    12 |         strong 写新文章
    13 |       div(class="u-panel")
    14 |         div(class="alert alert-danger", id="formValidate", style="display:none")
    15 |       
    16 |         div(class="form-group")
    17 |           label(for="inputTitle") 
    18 |             h3 标题:
    19 |           input(class="form-control", type="text", name="title",id="inputTitle", placeholder="文章标题")
    20 |         div(class="panel panel-default", style="padding:10px;height:80%")
    21 |           div(class="u-panel-body" id="leftPanel")
    22 |             textarea(class="u-pane", id="inputArticle", name="content",style="resize: none;")
    23 |           div(class="u-panel-body" id="rightPanel")
    24 |             div(class="u-pane", id="outputArticle")
    25 |           div(style="clear:both")
    26 |         div(class="row")
    27 |           input(type="hidden", name="tags")
    28 |           div(class="col-sm-6")
    29 |             h2 本文标签
    30 |             hr
    31 |             div(id="articleTags")
    32 |           div(class="col-sm-6")
    33 |             h2 所有标签
    34 |             hr
    35 |             div(id="allTags")
    36 |             hr
    37 |             span(class="label b-label-1", style="padding:8px 5px", id="newTag")
    38 |               input(id="newTagInput",type="text", placeholder="标签名", color="#428bca")
    39 |               span(class="glyphicon glyphicon-plus u-tag-create", style="margin-left:5px;cursor:pointer", id="createTag")
    40 |             span(class="label b-label-1 u-label-picker", value=1, color="#428bca") 深蓝
    41 |             span(class="label b-label-2 u-label-picker", value=2, color="#5cb85c") 绿色
    42 |             span(class="label b-label-3 u-label-picker", value=3, color="#5cb0de") 淡蓝
    43 |             span(class="label b-label-4 u-label-picker", value=4, color="#f0ad4e") 黄色
    44 |             span(class="label b-label-5 u-label-picker", value=5, color="#d9543f") 红色
    45 |         div(class="form-group", style="margin-top:20px")
    46 |           button(class="btn btn-primary", style="width:100%", id="saveArtBtn", type="submit") 保存文章
    47 | 
    48 | block javascript
    49 |   script(type='text/javascript', src='/javascripts/tools/showdown.js')
    50 |   script(type='text/javascript', src='/javascripts/tools/showdown_extensions/twitter.js')
    51 |   script(type='text/javascript', src='/javascripts/tools/highlight.pack.js')
    52 |   script(type='text/javascript', src='/javascripts/pageTools/Tag.js')
    53 |   script(type='text/javascript', src='/javascripts/page/writeArticle.js')
    
    
    --------------------------------------------------------------------------------