├── static ├── scss │ ├── _var.scss │ ├── style.scss │ ├── _override.scss │ ├── _avatar.scss │ ├── _icon.scss │ └── _util.scss ├── lib │ ├── moment │ │ ├── ender.js │ │ ├── package.js │ │ ├── LICENSE │ │ ├── locale │ │ │ ├── ar-tn.js │ │ │ ├── ja.js │ │ │ ├── km.js │ │ │ ├── fr-ca.js │ │ │ ├── uz.js │ │ │ ├── ko.js │ │ │ ├── tzm.js │ │ │ ├── da.js │ │ │ ├── ar-ma.js │ │ │ ├── nn.js │ │ │ ├── fo.js │ │ │ ├── tzm-latn.js │ │ │ ├── tl-ph.js │ │ │ ├── nb.js │ │ │ ├── fr.js │ │ │ ├── pt-br.js │ │ │ ├── en-ca.js │ │ │ ├── si.js │ │ │ ├── pt.js │ │ │ ├── vi.js │ │ │ ├── sv.js │ │ │ ├── cv.js │ │ │ ├── eu.js │ │ │ ├── en-au.js │ │ │ ├── th.js │ │ │ ├── en-gb.js │ │ │ ├── sq.js │ │ │ ├── it.js │ │ │ ├── ml.js │ │ │ ├── nl.js │ │ │ ├── fy.js │ │ │ ├── ro.js │ │ │ ├── af.js │ │ │ ├── eo.js │ │ │ ├── gl.js │ │ │ ├── he.js │ │ │ ├── my.js │ │ │ ├── de.js │ │ │ ├── ms.js │ │ │ ├── ms-my.js │ │ │ ├── cy.js │ │ │ ├── de-at.js │ │ │ ├── ca.js │ │ │ ├── es.js │ │ │ └── tr.js │ │ └── README.md │ └── angular │ │ └── angular-messages.min.js ├── images │ ├── favicon.ico │ └── default-avatar.jpg ├── css │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── MaterialIcons-Regular.eot │ │ ├── MaterialIcons-Regular.ttf │ │ ├── fontawesome-webfont.woff │ │ ├── fontawesome-webfont.woff2 │ │ ├── MaterialIcons-Regular.woff │ │ └── MaterialIcons-Regular.woff2 │ └── style.css ├── js │ ├── app.filters.js │ ├── modules │ │ ├── topic │ │ │ └── topicCtrl.js │ │ ├── signin │ │ │ └── signin.js │ │ └── signup │ │ │ └── signup.js │ ├── component │ │ ├── main-menu.js │ │ ├── leftMenu.js │ │ ├── topic-list.js │ │ ├── register-form.js │ │ ├── login-form.js │ │ └── common-toolbar.js │ ├── app.core.js │ ├── service │ │ ├── user.js │ │ ├── topic.js │ │ ├── app.services.js │ │ └── baiduweather.js │ ├── app.starter.js │ ├── app.config.js │ └── directives │ │ └── app.directives.js ├── templates │ ├── avatar.html │ ├── topic-list.html │ ├── dialog.html │ ├── main-menu.html │ ├── left-menu.html │ ├── login-form.html │ ├── common-toolbar.html │ └── register-form.html ├── package.json └── .jscsrc ├── views ├── common │ ├── footer.ejs │ ├── scripts.ejs │ └── header.ejs ├── error.ejs ├── mail │ └── mail-active.ejs ├── signup │ └── signup.ejs ├── signin │ └── signin.ejs └── index.ejs ├── jsconfig.json ├── tingyun.json ├── services ├── index.js ├── message.js ├── github.oauth.js ├── mail.js └── qq.oauth.js ├── models ├── index.js ├── message.model.js ├── comment.model.js ├── topic.model.js └── user.model.js ├── .eslintrc ├── routes ├── user.route.js ├── comment.route.js ├── index.js └── topic.route.js ├── .gitignore ├── LICENSE ├── package.json ├── README.md ├── .jscsrc ├── controllers ├── index.js ├── user.controller.js └── comment.controller.js ├── middlewares └── index.js ├── server.js ├── util └── index.js └── config.js /static/scss/_var.scss: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /views/common/footer.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/lib/moment/ender.js: -------------------------------------------------------------------------------- 1 | $.ender({ moment: require('moment') }) 2 | -------------------------------------------------------------------------------- /static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/images/favicon.ico -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs" 5 | } 6 | } -------------------------------------------------------------------------------- /static/css/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /static/images/default-avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/images/default-avatar.jpg -------------------------------------------------------------------------------- /static/css/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /static/css/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /static/js/app.filters.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | "use strict"; 3 | angular 4 | .module('app.filters',[]) 5 | .filter('') 6 | })(); -------------------------------------------------------------------------------- /static/css/fonts/MaterialIcons-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/MaterialIcons-Regular.eot -------------------------------------------------------------------------------- /static/css/fonts/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /static/css/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /static/css/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /static/css/fonts/MaterialIcons-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/MaterialIcons-Regular.woff -------------------------------------------------------------------------------- /static/css/fonts/MaterialIcons-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/parox2014/angular2club/HEAD/static/css/fonts/MaterialIcons-Regular.woff2 -------------------------------------------------------------------------------- /tingyun.json: -------------------------------------------------------------------------------- 1 | { 2 | "agent_log_level": "info", 3 | "app_name": [ 4 | "angular2club" 5 | ], 6 | "licenseKey": "6dc7580b1ba0e2533fe16c5541175777" 7 | } -------------------------------------------------------------------------------- /static/templates/avatar.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | -------------------------------------------------------------------------------- /views/error.ejs: -------------------------------------------------------------------------------- 1 | <%include ./common/header.ejs%> 2 | 3 | 4 | 5 |

<%=message%>

6 |

<%=JSON.stringify(error)%>

7 | 8 | <%include ./common/scripts.ejs%> 9 | 10 | <%include ./common/footer.ejs%> 11 | -------------------------------------------------------------------------------- /views/mail/mail-active.ejs: -------------------------------------------------------------------------------- 1 |

<%=user.profile.nickName%>,您好!

2 |

3 | 这是来自<%=config.SITE_NAME%>的激活邮件,如果是您自己注册的,请点下面的链接,对帐号进行激活: 4 |

5 |

6 | <%=link%> 7 |

8 |

如果不是您自己注册的,请忽略邮件!

-------------------------------------------------------------------------------- /static/js/modules/topic/topicCtrl.js: -------------------------------------------------------------------------------- 1 | (function(ng){ 2 | "use strict"; 3 | ng.module('app.topic',['app.core']) 4 | .controller('TopicController',function($scope,$stateParams){ 5 | $scope.vm=$stateParams; 6 | }); 7 | })(window.angular); -------------------------------------------------------------------------------- /static/scss/style.scss: -------------------------------------------------------------------------------- 1 | 2 | body{ 3 | font-family:"Microsoft Yahei","Helvetica Neue", Arial, sans-serif !important; 4 | } 5 | 6 | @import "var.scss"; 7 | @import "util.scss"; 8 | @import "icon.scss"; 9 | @import "override.scss"; 10 | @import "avatar.scss" 11 | -------------------------------------------------------------------------------- /static/scss/_override.scss: -------------------------------------------------------------------------------- 1 | //覆盖输入框样式 2 | .mdl-textfield{ 3 | width: 100%; 4 | } 5 | .mdl-layout-title{ 6 | font-family: 'Microsoft Yahei'; 7 | } 8 | 9 | .mdl-button-block{ 10 | width: 100%; 11 | } 12 | .md-fab-bottom-right{ 13 | position: fixed; 14 | bottom: 20px; 15 | right:0; 16 | } 17 | -------------------------------------------------------------------------------- /services/index.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | 4 | module.exports = { 5 | QQOAuth2: require('./qq.oauth'), 6 | GithubOAuth2: require('./github.oauth'), 7 | Topic:require('./topic'), 8 | Mail: require('./mail'), 9 | User: require('./user'), 10 | Comment:require('./comment'), 11 | Message:require('./message') 12 | }; 13 | -------------------------------------------------------------------------------- /static/lib/moment/package.js: -------------------------------------------------------------------------------- 1 | var profile = { 2 | resourceTags: { 3 | ignore: function(filename, mid){ 4 | // only include moment/moment 5 | return mid != "moment/moment"; 6 | }, 7 | amd: function(filename, mid){ 8 | return /\.js$/.test(filename); 9 | } 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /static/js/component/main-menu.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | angular.module('app.component') 3 | .directive('mainMenu', mainMenuDirective); 4 | 5 | function mainMenuDirective(user) { 6 | return { 7 | restrict: 'EA', 8 | replace: true, 9 | templateUrl: '../templates/main-menu.html', 10 | link: function(scope, element) { 11 | 12 | } 13 | }; 14 | } 15 | })(); 16 | -------------------------------------------------------------------------------- /static/scss/_avatar.scss: -------------------------------------------------------------------------------- 1 | .mdl-avatar{ 2 | display: inline-block; 3 | width:40px; 4 | height: 40px; 5 | border-radius: 50%; 6 | overflow: hidden; 7 | position: relative; 8 | 9 | img{ 10 | width: 100%; 11 | height: 100%; 12 | } 13 | h4{ 14 | width: 100%; 15 | height: 100%; 16 | text-align: center; 17 | padding: 0; 18 | margin: 0; 19 | line-height: 2.5; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /static/js/app.core.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | angular.module('app.core',[ 3 | 'ngAria', 4 | 'ngAnimate', 5 | 'ngMaterial', 6 | 'ngResource', 7 | 'ngMessages', 8 | 'ngSanitize', 9 | 'ngTouch', 10 | 'pascalprecht.translate', 11 | 'ui.router', 12 | 'app.directives', 13 | 'app.component', 14 | 'app.services' 15 | ]); 16 | })(); 17 | -------------------------------------------------------------------------------- /static/js/component/leftMenu.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | angular.module('app.component') 3 | .directive('leftMenu',function () { 4 | return { 5 | replace:true, 6 | templateUrl:'../templates/left-menu.html', 7 | link:function (scope) { 8 | scope.currentUser = window.__currentUser; 9 | } 10 | }; 11 | }); 12 | })(window.angular); 13 | -------------------------------------------------------------------------------- /models/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const mongoose = require('mongoose'); 3 | const config = require('../config'); 4 | 5 | mongoose.Promise = global.Promise; 6 | 7 | mongoose.connect(config.DATABASE, { 8 | poolSize: 20 9 | }, function(err) { 10 | if (!err) { 11 | logger.info('database connect success'); 12 | } else { 13 | logger.error(err.message); 14 | } 15 | }); 16 | 17 | exports.User = require('./user.model'); 18 | exports.Topic = require('./topic.model'); 19 | exports.Comment = require('./comment.model'); 20 | exports.Message = require('./message.model'); 21 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "arrowFunctions": true, 4 | "jsx": true, 5 | "generators": true, 6 | "es6": true, 7 | "destructuring": true, 8 | "classes": true, 9 | "defaultParams": true, 10 | "blockBindings": true, 11 | "modules": true, 12 | "node": true, 13 | "objectLiteralComputedProperties": true, 14 | "objectLiteralShorthandMethods": true, 15 | "objectLiteralShorthandProperties": true, 16 | "restParams": true, 17 | "spread": true, 18 | "templateStrings": true 19 | }, 20 | "env": { 21 | "node": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /views/common/scripts.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 16 | -------------------------------------------------------------------------------- /views/common/header.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <%=title%> 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /routes/user.route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var express = require('express'); 4 | var userRouter = express.Router(); 5 | var userCtrl = require('../controllers').userCtrl; 6 | var auth = require('../middlewares'); 7 | 8 | //激活帐号 9 | //GET /users/:id/active 10 | userRouter.get('/:id/active', userCtrl.active); 11 | 12 | //验证帐号的唯一性 13 | //GET /users/unique 14 | userRouter.get('/unique', userCtrl.unique); 15 | 16 | //更新用户资料 17 | //PUT /users/:id 18 | userRouter.put('/:id', auth.signinRequired, userCtrl.update); 19 | 20 | //获取用户资料 21 | //GET /users/:id 22 | userRouter.get('/:id', auth.signinRequired, userCtrl.getUserProfile); 23 | 24 | module.exports = userRouter; 25 | -------------------------------------------------------------------------------- /views/signup/signup.ejs: -------------------------------------------------------------------------------- 1 | <%include ../common/header.ejs%> 2 | 3 | 4 | 6 |
7 |
8 |
9 | 10 | 11 | <%include ../common/scripts.ejs%> 12 | 17 | 18 | <%include ../common/footer.ejs%> 19 | -------------------------------------------------------------------------------- /routes/comment.route.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const CommentCtrl = require('../controllers').CommentCtrl; 3 | const commentRouter = express.Router(); 4 | const auth = require('../middlewares'); 5 | 6 | //查询评论列表 7 | //GET /comments 8 | commentRouter.get('/',CommentCtrl.getCommentList); 9 | 10 | //添加评论 11 | //POST /comments 12 | commentRouter.post('/',auth.signinRequired,CommentCtrl.createComment); 13 | 14 | //删除评论 15 | //DELETE /comments/:id 16 | commentRouter.delete('/:id',auth.signinRequired,CommentCtrl.removeComment); 17 | 18 | //更新评论 19 | //PUT /comments/:id 20 | commentRouter.put('/:id',auth.signinRequired,CommentCtrl.updateComment); 21 | module.exports = commentRouter; 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | 29 | # webstorm 30 | .idea 31 | 32 | #VS code 33 | .vscode 34 | 35 | #upload folder 36 | uploads 37 | -------------------------------------------------------------------------------- /static/js/modules/signin/signin.js: -------------------------------------------------------------------------------- 1 | angular 2 | .module('app.login',[ 3 | 'app.core', 4 | 'app.config' 5 | ]) 6 | .controller('LoginController',function ($scope,$timeout,$dialog,$filter,$mdToast) { 7 | $scope.onSuccess=function (user) { 8 | $mdToast.showSimple('登录成功'); 9 | 10 | $timeout(function () { 11 | location.href='/'; 12 | },2000); 13 | 14 | }; 15 | 16 | $scope.onError=function (error) { 17 | var msg=$filter('translate')(error.msg); 18 | $dialog.alert(msg,function () { 19 | console.log('fuck'); 20 | }); 21 | }; 22 | }) 23 | .run(function () { 24 | // body... 25 | }); 26 | -------------------------------------------------------------------------------- /static/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2club", 3 | "version": "0.0.1", 4 | "author": "William Du", 5 | "dependencies": { 6 | "angular": "^1.4.6", 7 | "angular-animate": "^1.4.6", 8 | "angular-aria": "^1.4.6", 9 | "angular-material": "^0.11.1", 10 | "bootstrap": "^3.3.5", 11 | "font-awesome": "^4.4.0", 12 | "gulp": "^3.9.0", 13 | "gulp-autoprefixer": "^2.3.1", 14 | "gulp-concat": "^2.6.0", 15 | "gulp-cssmin": "*", 16 | "gulp-jshint": "*", 17 | "gulp-minify-css": "^1.2.1", 18 | "gulp-ng-annotate": "*", 19 | "gulp-ng-html2js": "*", 20 | "gulp-rename": "^1.2.2", 21 | "gulp-sass": "*", 22 | "gulp-uglify": "^1.4.0", 23 | "gulp-util": "^3.0.6", 24 | "gulp-watch": "^4.3.5", 25 | "moment": "^2.10.6" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /views/signin/signin.ejs: -------------------------------------------------------------------------------- 1 | <%include ../common/header.ejs%> 2 | 3 | 4 | 7 |
8 | 12 | 13 |
14 |
15 | 16 | 17 | <%include ../common/scripts.ejs%> 18 | 23 | 24 | <%include ../common/footer.ejs%> 25 | -------------------------------------------------------------------------------- /static/js/component/topic-list.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | "use strict"; 3 | angular 4 | .module('app.component') 5 | .directive('topicList',topicListDirective); 6 | 7 | function TopicListController($scope,$attrs,$element,Topic,$parse){ 8 | var that=this; 9 | var params=$parse($attrs.option)($scope); 10 | 11 | that.init=init; 12 | that.getList=getList; 13 | 14 | function init(){ 15 | $scope.topics=this.getList(params); 16 | } 17 | 18 | function getList(params){ 19 | return Topic.query(params); 20 | } 21 | } 22 | 23 | function topicListDirective(){ 24 | return { 25 | restrict:'EA', 26 | templateUrl:'../templates/topic-list.html', 27 | replace:true, 28 | controller:TopicListController, 29 | link:function(scope,element,attrs,topicCtrl){ 30 | topicCtrl.init(); 31 | } 32 | } 33 | } 34 | })(); -------------------------------------------------------------------------------- /models/message.model.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var mongoose = require('mongoose'); 4 | var Schema = mongoose.Schema; 5 | var ObjectId = Schema.Types.ObjectId; 6 | var MessageSchema = new Schema({ 7 | //消息类型 8 | type: { 9 | type: Number, //消息类型,1:回复您的贴子,2:回复评论,3:@ at您 10 | required: true 11 | }, 12 | 13 | //消息发送者 14 | from: { 15 | type: ObjectId, 16 | required: true, 17 | ref:'User' 18 | }, 19 | 20 | //消息接收者 21 | to: [ { 22 | type: ObjectId, 23 | required: true, 24 | ref:'User' 25 | } ], 26 | 27 | //贴子ID 28 | topicId: { 29 | type: ObjectId, 30 | required: true, 31 | ref: 'Topic' 32 | }, 33 | //是否已读 34 | isReaded: { 35 | type: Boolean, 36 | default: false 37 | } 38 | }, { 39 | versionKey: false, 40 | timestamps: { 41 | createdAt: 'createdAt', 42 | updatedAt: 'updatedAt' 43 | } 44 | }); 45 | 46 | MessageSchema.index({ 47 | createAt: -1 48 | }); 49 | 50 | module.exports = mongoose.model('Message', MessageSchema); 51 | -------------------------------------------------------------------------------- /static/templates/topic-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | avatar 4 |
5 |

6 | {{ topic.title }} 7 |

8 |

9 | thumb_up 10 | {{ topic.meta.votes }} 11 | 12 | favorite 13 | {{ topic.meta.favs }} 14 | 15 | access_time 16 | {{ topic.updatedAt|date:'yyyy年M月d日 hh:mm' }} 17 |

18 |
19 | 20 |
21 |
-------------------------------------------------------------------------------- /models/comment.model.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var mongoose = require('mongoose'); 4 | var Schema = mongoose.Schema; 5 | var ObjectId = Schema.Types.ObjectId; 6 | var CommentSchema = new Schema({ 7 | content: { 8 | type: String, 9 | required: true 10 | }, 11 | topicId: { 12 | type: ObjectId, 13 | required: true 14 | }, 15 | 16 | //回复 17 | replyTo: { 18 | type:ObjectId, 19 | ref:'User' 20 | }, 21 | mentions:[ { type:ObjectId,ref:'User' } ], 22 | //创建者 23 | creator: { 24 | type: ObjectId, 25 | ref:'User', 26 | required: true 27 | }, 28 | 29 | //赞成 30 | votes: { 31 | type: Number, 32 | default: 0 33 | } 34 | }, { 35 | versionKey: false, 36 | timestamps: { 37 | createdAt: 'createdAt', 38 | updatedAt: 'updatedAt' 39 | } 40 | }); 41 | 42 | CommentSchema.index({ 43 | _id: 1 44 | }); 45 | CommentSchema.index({ 46 | creator: 1, 47 | createdAt: -1 48 | }); 49 | CommentSchema.index({ 50 | votes: 1 51 | }); 52 | 53 | module.exports = mongoose.model('Comment', CommentSchema); 54 | -------------------------------------------------------------------------------- /static/js/service/user.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | angular 4 | .module('app.services') 5 | .factory('user', userService); 6 | 7 | function userService($http, api) { 8 | var currentUser = null; 9 | return { 10 | signup: function() { 11 | return $http.post(api.user.SIGN_UP, this.toJson()); 12 | }, 13 | signin: function() { 14 | return $http.post(api.user.SIGN_IN, this.toJson()); 15 | }, 16 | unique: function(value) { 17 | var params = { 18 | account: value 19 | }; 20 | return $http.get(api.user.UNIQUE, { 21 | params: params 22 | }); 23 | }, 24 | toJson: function() { 25 | return { 26 | account: this.account, 27 | nickName: this.nickName, 28 | password: this.password 29 | }; 30 | }, 31 | currentUser: function(user) { 32 | if (user) { 33 | currentUser = user; 34 | } else { 35 | return currentUser; 36 | } 37 | } 38 | }; 39 | } 40 | })(); 41 | -------------------------------------------------------------------------------- /static/js/service/topic.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | "use strict"; 3 | angular 4 | .module('app.services') 5 | .factory('Topic',function($resource,api,$http,$q){ 6 | var Topic=$resource(api.topic.BASE+'/:id',{ 7 | id:'@_id' 8 | }); 9 | 10 | 11 | Topic.prototype.toggleGood=toggleGood; 12 | Topic.prototype.toggleVote=toggleVote; 13 | 14 | return Topic; 15 | 16 | function toggleGood(){ 17 | this.isGood=!this.isGood; 18 | } 19 | 20 | function toggleVote(cuid){ 21 | var deffered=$q.defer(); 22 | var uri=(api.topic.BASE+api.topic.VOTE).replace(':id',this._id); 23 | var vote=this.voters.indexOf(cuid)>-1?-1:1; 24 | var self=this; 25 | uri+='?vote='+vote; 26 | 27 | $http.put(uri) 28 | .then(function(resp){ 29 | angular.extend(self,resp.data); 30 | deffered.resolve(resp); 31 | },function(err){ 32 | deffered.reject(err); 33 | }); 34 | 35 | return deffered.promise; 36 | } 37 | }); 38 | })(); -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var ctrls = require('../controllers'); 4 | var SignCtrl = ctrls.SignCtrl; 5 | var userRouter = require('./user.route'); 6 | var topicRouter = require('./topic.route'); 7 | const commentRouter = require('./comment.route'); 8 | 9 | module.exports = function(server) { 10 | //渲染主页页 11 | server.get('/', ctrls.MainCtrl.getSessionUserAndAllTopics); 12 | 13 | //渲染登录页面 14 | server.get('/signin', SignCtrl.showSignin); 15 | 16 | //渲染注册页面 17 | server.get('/signup', SignCtrl.showSignup); 18 | 19 | //注册 20 | server.post('/signup', SignCtrl.signup); 21 | 22 | //登录 23 | server.post('/signin', SignCtrl.signin); 24 | 25 | server.post('/mail', SignCtrl.sendMail); 26 | 27 | //退出 28 | server.get('/signout', SignCtrl.signout); 29 | 30 | //QQ授权登录 31 | server.get('/oauth/qq/callback', SignCtrl.qqOAuth); 32 | 33 | //github授权登录 34 | server.get('/oauth/github/callback', SignCtrl.githubOAuth); 35 | 36 | server.use('/users', userRouter); 37 | 38 | server.use('/topics', topicRouter); 39 | 40 | server.use('/comments',commentRouter); 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /services/message.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const models = require('../models'); 4 | const Message = models.Message; 5 | 6 | class MessageService { 7 | /** 8 | * 发送消息 9 | * @method send 10 | * @param {ObjectId} from 发送者 11 | * @param {ObjectId} to 接收者 12 | * @param {Object} option 其它选项 13 | * @return {Promise} [description] 14 | */ 15 | static send(from,to,option) { 16 | if (!Array.isArray(to)){ 17 | to = [ to ]; 18 | } 19 | let obj = { 20 | from:from, 21 | to:to 22 | }; 23 | Object.assign(obj,option); 24 | return Message.create(obj); 25 | } 26 | /** 27 | * 标记消息为已读 28 | * @method markAsReaded 29 | * @param {ObjectId} id [description] 30 | * @param {ObjectId} sessionUser 31 | * @return {Promise} [description] 32 | */ 33 | static markAsReaded(id,sessionUser) { 34 | return Message.findOneAndUpdate({ _id:id,to:sessionUser },{ isReaded:true }); 35 | } 36 | 37 | static removeReaded(sessionUser) { 38 | return Message.findAndRemove({ isReaded:true,to:sessionUser }); 39 | } 40 | } 41 | 42 | module.exports = MessageService; 43 | -------------------------------------------------------------------------------- /static/templates/dialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | 6 | 7 | close 8 | 9 |
10 |
11 | 12 |

13 |

14 |
15 |
16 | 20 | 21 | 26 | 27 |
28 |
29 | -------------------------------------------------------------------------------- /static/js/component/register-form.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | angular.module('app.component') 3 | .directive('registerForm', registerFormDirective); 4 | 5 | function registerFormDirective(user) { 6 | return { 7 | restrict: 'EA', 8 | replace: true, 9 | templateUrl: '../templates/register-form.html', 10 | scope: { 11 | formTitle: '@', 12 | onSuccess: '&', 13 | onError: '&' 14 | }, 15 | link: function(scope, element) { 16 | 17 | var viewModel = scope.vm = { 18 | isSubmiting: false 19 | }; 20 | 21 | scope.user = user; 22 | 23 | scope.onSubmit = function() { 24 | viewModel.isSubmiting = true; 25 | user.signup() 26 | .success(function(resp) { 27 | scope.onSuccess({ 28 | user: resp 29 | }); 30 | }) 31 | .error(function(resp) { 32 | viewModel.isSubmiting = false; 33 | scope.onError({ 34 | error: resp 35 | }); 36 | }); 37 | }; 38 | 39 | } 40 | }; 41 | } 42 | })(); 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Keyboard Man 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /static/js/app.starter.js: -------------------------------------------------------------------------------- 1 | 2 | angular.module('app.starter',[ 3 | 'app.core', 4 | 'app.config', 5 | 'app.routes', 6 | 'app.baiduWeather' 7 | ]) 8 | .controller('MainController',function ($scope,BaiduWeather,baiduWeatherApiKey) { 9 | var baiduWeather = new BaiduWeather(baiduWeatherApiKey); 10 | var cityId; 11 | 12 | $scope.getData = function () { 13 | baiduWeather 14 | .getCityListByName('杭州') 15 | .then(function (resp) { 16 | cityId = resp[0].area_id; 17 | return baiduWeather.getRecentWeatherByCityId(cityId); 18 | }) 19 | .then(function(data) { 20 | console.log('recent',data); 21 | return baiduWeather.getTodayWeatherByCityId(cityId); 22 | }) 23 | .then(function(data) { 24 | console.log('today',data); 25 | }) 26 | .catch(function(err) { 27 | console.error(err); 28 | }); 29 | 30 | }; 31 | }) 32 | .run(function (user) { 33 | user.currentUser(window.__currentUser); 34 | }); 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular2club", 3 | "version": "1.0.0", 4 | "description": "'an angular2 club of china'", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/WilliamDu1981/angular2club.git" 12 | }, 13 | "keywords": [ 14 | "angular2", 15 | "club", 16 | "nodejs" 17 | ], 18 | "author": "'William Du'", 19 | "license": "MIT", 20 | "dependencies": { 21 | "body-parser": "^1.13.3", 22 | "connect-mongo": "^0.8.2", 23 | "cookie-parser": "^1.3.5", 24 | "ejs": "^2.3.3", 25 | "eventproxy": "^0.3.4", 26 | "express": "^4.13.3", 27 | "express-session": "^1.11.3", 28 | "express-validator": "^2.17.1", 29 | "favicon": "0.0.2", 30 | "log4js": "^0.6.28", 31 | "moment": "*", 32 | "mongoose": "^4.1.5", 33 | "multer": "^1.1.0", 34 | "nodemailer": "^1.5.0", 35 | "redis": "^2.2.1", 36 | "serve-favicon": "^2.3.0", 37 | "underscore": "^1.8.3" 38 | }, 39 | "devDependencies": { 40 | "mocha": "^2.3.3", 41 | "morgan": "^1.6.1", 42 | "should": "^7.1.0", 43 | "supertest": "^1.1.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /static/lib/moment/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2015 Tim Wood, Iskren Chernev, Moment.js contributors 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /static/templates/main-menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | add 4 | 5 | 6 | 9 | share 10 | 11 | 技术分享 12 | 13 | 14 | 15 | 18 | help 19 | 20 | 技术问答 21 | 22 | 23 | 24 | 27 | work 28 | 29 | 招聘 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /static/scss/_icon.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Material Icons'; 3 | font-style: normal; 4 | font-weight: 400; 5 | src: url(./fonts/MaterialIcons-Regular.eot); /* For IE6-8 */ 6 | src: local('Material Icons'), 7 | local('MaterialIcons-Regular'), 8 | url(./fonts/MaterialIcons-Regular.woff2) format('woff2'), 9 | url(./fonts/MaterialIcons-Regular.woff) format('woff'), 10 | url(./fonts/MaterialIcons-Regular.ttf) format('truetype'); 11 | } 12 | 13 | .material-icons { 14 | font-family: 'Material Icons'; 15 | font-weight: normal; 16 | font-style: normal; 17 | font-size: 24px; /* Preferred icon size */ 18 | display: inline-block; 19 | width: 1em; 20 | height: 1em; 21 | line-height: 1; 22 | text-transform: none; 23 | letter-spacing: normal; 24 | word-wrap: normal; 25 | white-space: nowrap; 26 | direction: ltr; 27 | 28 | /* Support for all WebKit browsers. */ 29 | -webkit-font-smoothing: antialiased; 30 | /* Support for Safari and Chrome. */ 31 | text-rendering: optimizeLegibility; 32 | 33 | /* Support for Firefox. */ 34 | -moz-osx-font-smoothing: grayscale; 35 | 36 | /* Support for IE. */ 37 | font-feature-settings: 'liga'; 38 | } 39 | -------------------------------------------------------------------------------- /static/js/modules/signup/signup.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | angular 3 | .module('app.register', [ 4 | 'app.core', 5 | 'app.config', 6 | 'ngMessages' 7 | ]) 8 | .controller('RegisterStep1Controller', function($scope, $state, $mdToast) { 9 | $scope.nextStep = nextStep; 10 | 11 | function nextStep(user) { 12 | $mdToast.showSimple('注册成功'); 13 | $state.go('step2', { 14 | userId: user._id 15 | }); 16 | } 17 | }) 18 | .controller('RegisterStep2Controller', function($scope, $stateParams, 19 | $state) { 20 | var uid = $stateParams.userId; 21 | if (!uid) { 22 | return $state.go('step1'); 23 | } 24 | $scope.vm = { 25 | userId: uid 26 | }; 27 | }) 28 | .config(function($stateProvider, $urlRouterProvider) { 29 | $stateProvider 30 | .state('step1', { 31 | url: '/step1', 32 | template: '', 33 | controller: 'RegisterStep1Controller' 34 | }) 35 | .state('step2', { 36 | url: '/step2/:userId', 37 | template: '

注册成功,请前往你的邮箱激活帐号!

', 38 | controller: 'RegisterStep2Controller' 39 | }); 40 | 41 | $urlRouterProvider.otherwise('/step1'); 42 | }); 43 | 44 | })(); 45 | -------------------------------------------------------------------------------- /static/js/component/login-form.js: -------------------------------------------------------------------------------- 1 | angular.module('app.component') 2 | .directive('loginForm',function (user,$rootScope) { 3 | return { 4 | restrict:'EA', 5 | scope:{ 6 | onSuccess:'&', 7 | onError:'&', 8 | formTitle:'@' 9 | }, 10 | replace:true, 11 | templateUrl:'../templates/login-form.html', 12 | link:function ($scope,element) { 13 | var viewModel = $scope.vm = { 14 | isSubmiting:false, 15 | qqUri:document.querySelector('[name="qq"]').value, 16 | gitHubUri:document.querySelector('[name="github"]').value 17 | }; 18 | 19 | $scope.user = user; 20 | 21 | $scope.onSubmit = function () { 22 | viewModel.isSubmiting = true; 23 | user.signin() 24 | .success(function (resp) { 25 | $scope.onSuccess({ user:user }); 26 | }) 27 | .error(function (err) { 28 | $scope.onError({ error:err }); 29 | viewModel.isSubmiting = false; 30 | }); 31 | }; 32 | 33 | $scope.onClick=function(e){ 34 | "use strict"; 35 | $rootScope.$broadcast('$requestStart',e); 36 | }; 37 | } 38 | }; 39 | }); 40 | -------------------------------------------------------------------------------- /static/scss/_util.scss: -------------------------------------------------------------------------------- 1 | 2 | //常用内边距 3 | .mdl-pd-1x{ 4 | padding: 10px; 5 | } 6 | 7 | .mdl-pd-2x{ 8 | padding: 20px 9 | } 10 | 11 | .mdl-pd-3x{ 12 | padding: 30px; 13 | } 14 | 15 | .mdl-pd-ver-1x{ 16 | padding-top:10px; 17 | padding-bottom: 10px; 18 | } 19 | 20 | .mdl-pd-ver-2x{ 21 | padding-top: 20px; 22 | padding-bottom: 20px; 23 | } 24 | 25 | .mdl-pd-ver-3x{ 26 | padding-top: 30px; 27 | padding-bottom: 30px; 28 | } 29 | 30 | .mdl-pd-hor-1x{ 31 | padding-left: 10px; 32 | padding-right: 10px; 33 | } 34 | 35 | .mdl-pd-hor-2x{ 36 | padding-left: 20px; 37 | padding-right: 20px; 38 | } 39 | 40 | //常用外边距 41 | .mdl-mg-1x{ 42 | margin: 10px; 43 | } 44 | 45 | .mdl-mg-2x{ 46 | margin: 20px 47 | } 48 | 49 | .mdl-mg-3x{ 50 | margin: 30px; 51 | } 52 | 53 | .mdl-mg-ver-1x{ 54 | margin-top:10px; 55 | margin-bottom: 10px; 56 | } 57 | 58 | .mdl-mg-ver-2x{ 59 | margin-top: 20px; 60 | margin-bottom: 20px; 61 | } 62 | 63 | .mdl-mg-ver-3x{ 64 | margin-top: 30px; 65 | margin-bottom: 30px; 66 | } 67 | 68 | .mdl-mg-hor-1x{ 69 | margin-left: 10px; 70 | margin-right: 10px; 71 | } 72 | 73 | .mdl-mg-hor-2x{ 74 | margin-left: 20px; 75 | margin-right: 20px; 76 | } 77 | 78 | //文字对齐 79 | .mdl-text-center{ 80 | text-align: center; 81 | } 82 | .mdl-text-right{ 83 | text-align: right; 84 | } 85 | -------------------------------------------------------------------------------- /static/js/component/common-toolbar.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | angular 3 | .module('app.component', ['app.services', 'ngMessages']) 4 | .directive('commonToolbar', function($mdSidenav, user, $timeout) { 5 | return { 6 | templateUrl: '../templates/common-toolbar.html', 7 | scope: { 8 | showMenuButton: '@' 9 | }, 10 | replace: true, 11 | link: function(scope, element) { 12 | scope.toggleSideMenu = function() { 13 | $mdSidenav('leftMenu').toggle(); 14 | }; 15 | 16 | scope.currentUser = user.currentUser(); 17 | 18 | scope.vm = { 19 | isShowLoading: false 20 | }; 21 | 22 | scope.$on('$requestStart', function(argument) { 23 | toggleLoading(true); 24 | }); 25 | 26 | scope.$on('$requestSuccess', function() { 27 | toggleLoading(false); 28 | }); 29 | 30 | scope.$on('$responseError', function() { 31 | toggleLoading(false); 32 | }); 33 | 34 | function toggleLoading(isShow) { 35 | if (isShow) { 36 | return (scope.vm.isShowLoading = isShow); 37 | } 38 | $timeout(function() { 39 | scope.vm.isShowLoading = isShow; 40 | }, 500); 41 | } 42 | } 43 | }; 44 | }); 45 | })(); 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular2club 2 | 3 | 本地部署方法: 4 | 5 | 一、部署mongodb: 6 | 7 | 1.选择一个盘创建一个文件夹:/data/db; 8 | 9 | 2.创建一个批处理文件:mongodb.bat,复制下面的内容: 10 | 11 | 12 | @echo off 13 | title mongo数据库 14 | echo 启动mongodb 15 | pause 16 | echo 进入根目录 17 | cd\ 18 | echo 切换到e盘//此处换成你自己mongodb的安装盘 19 | e: 20 | echo 进入mongo文件夹 21 | cd \mongo\bin 22 | echo 执行mongo程序 23 | mongod.exe --dbpath e:\data\db 24 | pause 25 | 26 | 保存,然后执行此批处理文件 27 | 28 | 3.创建一个数据库: 29 | 30 | 打开cmd命令窗口,执行下列命令 31 | $ cd x:\yourpath\mongo\bin 32 | $ mongo.exe//执行mongo客户端命令 33 | $ use admin //切换到admin库 34 | //创建的一个root用户 35 | $ db.createUser({ 36 | user:'root', 37 | pwd:'your password',//填你自己的密码 38 | roles:['root','dbAdminAnyDatabase'] 39 | }) 40 | 41 | //创建数据库angular2club 42 | $ use angular2club 43 | $ db.createUser({ 44 | user:'angular2club', 45 | pwd:'parox606', 46 | roles:['dbAdmin','readWrite'] 47 | }) 48 | 49 | 完成后,关闭刚才的批处理文件窗口,再用文本编辑器打开,在启动mongodb的地方加上下面的参数: 50 | 51 | mongod.exe --dbpath e:\data\db --auth 52 | 53 | 保存后,再次双击启动,现在操作数据库,就需要用权限了; 54 | 55 | 56 | 二、部署web服务器: 57 | 58 | 1.安装依赖,打开一个cmd窗口,执行下面命令 59 | 60 | $ cd x:\yourpath\angular2club 61 | $ npm install 62 | 63 | 2.启动服务器 64 | 65 | $ node server.js 66 | 67 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles":[ "node_modules/**",".idea",".git","static"], 3 | "disallowArrowFunctions":false, 4 | "disallowMultipleLineBreaks": false, 5 | "disallowTrailingComma":true, 6 | "disallowEmptyBlocks": true, 7 | "disallowSpaceAfterObjectKeys": true, 8 | "disallowCommaBeforeLineBreak": false, 9 | "disallowTrailingWhitespace": true, 10 | "disallowSpaceAfterPrefixUnaryOperators": [ "++", "--", "+", "-", "~", "!" ], "disallowSpaceBeforePostfixUnaryOperators": [ "++", "--" ], 11 | "disallowKeywordsOnNewLine": [ "else" ], 12 | "requireLineFeedAtFileEnd": true, 13 | "requireMultipleVarDecl": false, 14 | "requireCapitalizedConstructors": true, 15 | "requireSpacesInsideObjectBrackets": "all", "requireSpacesInsideArrayBrackets": "all", 16 | "requireSemicolons":true, 17 | "requireSpaceBeforeBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 18 | "requireSpaceAfterBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 19 | "requireSpaceAfterKeywords": [ "if", "else", "for", "while", "do", "switch", "try", "catch" ], 20 | "requireSpaceBeforeBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 21 | "requireSpaceAfterBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 22 | "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, 23 | "fix":true, 24 | "esnext":true, 25 | "extract": ["*.htm", "*.html","*.ejs"], 26 | "validateLineBreaks": "LF", 27 | } 28 | -------------------------------------------------------------------------------- /static/.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles":[ "node_modules/**",".idea",".git","static"], 3 | "disallowArrowFunctions":false, 4 | "disallowMultipleLineBreaks": false, 5 | "disallowTrailingComma":true, 6 | "disallowEmptyBlocks": true, 7 | "disallowSpaceAfterObjectKeys": true, 8 | "disallowCommaBeforeLineBreak": false, 9 | "disallowTrailingWhitespace": true, 10 | "disallowSpaceAfterPrefixUnaryOperators": [ "++", "--", "+", "-", "~", "!" ], "disallowSpaceBeforePostfixUnaryOperators": [ "++", "--" ], 11 | "disallowKeywordsOnNewLine": [ "else" ], 12 | "requireLineFeedAtFileEnd": true, 13 | "requireMultipleVarDecl": false, 14 | "requireCapitalizedConstructors": true, 15 | "requireSpacesInsideObjectBrackets": "all", "requireSpacesInsideArrayBrackets": "all", 16 | "requireSemicolons":true, 17 | "requireSpaceBeforeBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 18 | "requireSpaceAfterBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 19 | "requireSpaceAfterKeywords": [ "if", "else", "for", "while", "do", "switch", "try", "catch" ], 20 | "requireSpaceBeforeBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 21 | "requireSpaceAfterBinaryOperators": [ "+", "-", "/", "*", "=", "==", "===", "!=", "!==" ], 22 | "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, 23 | "fix":true, 24 | "esnext":true, 25 | "extract": ["*.htm", "*.html","*.ejs"], 26 | "validateLineBreaks": "LF", 27 | } 28 | -------------------------------------------------------------------------------- /controllers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var User = require('../models').User; 4 | var Topic = require('../models').Topic; 5 | var EventProxy = require('eventproxy'); 6 | var config = require('../config'); 7 | 8 | class MainController { 9 | static getSessionUserAndAllTopics(req, res) { 10 | var evtProxy = new EventProxy(); 11 | var findSessionUser = 'findSessionUserSuccess'; 12 | var findTopics = 'findTopicsSuccess'; 13 | 14 | evtProxy.all([ findSessionUser, findTopics ], function(user, topics) { 15 | res.render('index', { 16 | title: config.SITE_NAME, 17 | user: user, 18 | topics: topics || [] 19 | }); 20 | }); 21 | 22 | if (req.session.user) { 23 | User.findOne({ 24 | _id: req.session.user 25 | }, function(err, user) { 26 | evtProxy.emit(findSessionUser, user); 27 | }); 28 | 29 | Topic.find() 30 | .where('creator').equals(req.session.user) 31 | .exec(function(err, topics) { 32 | evtProxy.emit(findTopics, topics); 33 | }); 34 | 35 | } else { 36 | res.render('index', { 37 | title: config.SITE_NAME, 38 | user: null, 39 | topics: [] 40 | }); 41 | } 42 | } 43 | } 44 | 45 | module.exports = { 46 | MainCtrl: MainController, 47 | SignCtrl: require('./sign.controller'), 48 | topicCtrl: require('./topic.controller'), 49 | userCtrl: require('./user.controller'), 50 | CommentCtrl:require('./comment.controller') 51 | }; 52 | -------------------------------------------------------------------------------- /views/index.ejs: -------------------------------------------------------------------------------- 1 | <%include ./common/header.ejs%> 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 |
10 |
11 | 12 | 15 | <%include ./common/scripts.ejs%> 16 | 17 | 37 | 38 | <%include ./common/footer.ejs%> 39 | -------------------------------------------------------------------------------- /routes/topic.route.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const express = require('express'); 4 | const topicCtrl = require('../controllers').topicCtrl; 5 | const topicRouter = express.Router(); 6 | const auth = require('../middlewares'); 7 | 8 | //获取topic列表 9 | topicRouter.get('/', topicCtrl.getTopicList); 10 | 11 | //获取topic详情 12 | topicRouter.get('/:topicId', topicCtrl.getTopicDetail); 13 | 14 | //创建topic 15 | topicRouter.post('/', auth.signinRequired, topicCtrl.createTopic); 16 | 17 | //更新topic 18 | topicRouter.put('/:topicId', auth.signinRequired, topicCtrl.updateTopic); 19 | 20 | //删除topic 21 | topicRouter.delete('/:topicId', auth.signinRequired, topicCtrl.removeTopic); 22 | 23 | //置顶 24 | //PUT /topics/:id/top 25 | topicRouter.put( 26 | '/:topicId/top', 27 | auth.signinRequired, 28 | auth.adminRequired, 29 | topicCtrl.toggleIsTop 30 | ); 31 | 32 | //设为精华文章 33 | ////PUT /topics/:id/good 34 | topicRouter.put( 35 | '/:topicId/good', 36 | auth.signinRequired, 37 | auth.adminRequired, 38 | topicCtrl.toggleIsGood 39 | ); 40 | 41 | //点赞 42 | //PUT /topics/:id/vote 43 | topicRouter.put( 44 | '/:topicId/vote', 45 | auth.signinRequired, 46 | topicCtrl.toggleVote 47 | ); 48 | 49 | //收藏 50 | topicRouter.put( 51 | '/:topicId/fav', 52 | auth.signinRequired, 53 | topicCtrl.toggleFavorite 54 | ); 55 | 56 | //获取收藏的topic 57 | topicRouter.get( 58 | '/favs/:id', 59 | auth.signinRequired, 60 | topicCtrl.getFavoriteTopics 61 | ); 62 | 63 | //获取点赞的topic 64 | topicRouter.get( 65 | '/votes/:id', 66 | auth.signinRequired, 67 | topicCtrl.getVoteTopics 68 | ); 69 | 70 | module.exports = topicRouter; 71 | -------------------------------------------------------------------------------- /static/templates/left-menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | select_all 7 | 全部 8 | 9 | 10 | 11 | 12 | share 13 | 分享 14 | 15 | 16 | 17 | 18 | stars 19 | 精华 20 | 21 | 22 | 23 | 24 | question_answer 25 | 问答 26 | 27 | 28 | 29 | 30 | work 31 | 招聘 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | add_circle 40 | 新建 41 | 42 | 43 | 44 |
45 | -------------------------------------------------------------------------------- /static/templates/login-form.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | 5 | email 6 | 12 | 13 | 14 | 15 | lock 16 | 24 | 25 | 26 | 27 | 登录 31 | 32 | 33 | 34 | 35 | 还没有帐号?注册 36 | 37 | 38 | 39 | QQ登录 40 | 41 | 42 | 43 | 44 | github登录 45 | 46 | 47 | 48 |
49 | -------------------------------------------------------------------------------- /services/github.oauth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const https = require('https'); 4 | const querystring = require('querystring'); 5 | const Util = require('../util'); 6 | const OAuth2 = require('./oauth2'); 7 | 8 | class GitHubOAuth2 extends OAuth2 { 9 | 10 | /** 11 | * class GitHubOAuth2 12 | * @method constructor 13 | * @param {[String]} appId [appId] 14 | * @param {[String]} appKey [appKey] 15 | * @param {[String]} redirectUrl [redirectUrl] 16 | * @return {[Object]} [instant] 17 | */ 18 | constructor(appId, appKey, redirectUrl) { 19 | 20 | super(appId, appKey, redirectUrl); 21 | 22 | this._config = { 23 | OAUTH_URI: 'https://github.com/login/oauth/authorize?', 24 | HOST_NAME: 'github.com', 25 | PATH_ACCESS_TOKEN: '/login/oauth/access_token?', 26 | SCOPE: ['user'], 27 | }; 28 | 29 | this._requestOptions.hostname = this._config.HOST_NAME; 30 | 31 | this._state = Util.createHash('github_oauth_angular2_club'); 32 | } 33 | 34 | /** 35 | * @description get user's info by access token 36 | * @param token {String} access token 37 | */ 38 | getUserInfo(token) { 39 | let params = { 40 | access_token: token, 41 | }; 42 | 43 | let options = { 44 | hostname: 'api.github.com', 45 | path: '/user?' + querystring.stringify(params), 46 | headers: { 47 | Accept: 'application/json', 48 | 'User-Agent': 'angular2 club', 49 | }, 50 | }; 51 | 52 | return new Promise((resolve, reject) => { 53 | let req = https.request(options, resp => { 54 | this._handleResponse(resp, resolve, reject); 55 | }); 56 | 57 | req.on('error', function(err) { 58 | reject(err); 59 | }); 60 | 61 | req.end(); 62 | }); 63 | } 64 | } 65 | 66 | module.exports = GitHubOAuth2; 67 | -------------------------------------------------------------------------------- /static/js/app.config.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | angular.module('app.config', []) 3 | .factory('api', api) 4 | .constant('baiduWeatherApiKey', '6aa7516564286a7fed27f1b7745a3b6c') 5 | .factory('httpInterceptor', interceptor) 6 | .config(appConfig); 7 | 8 | function api() { 9 | return { 10 | user: { 11 | SIGN_UP: '/signup', 12 | SIGN_IN: '/signin', 13 | SIGN_OUT: '/signout', 14 | UNIQUE: '/users/unique' 15 | }, 16 | topic:{ 17 | BASE:'/topics', 18 | GOOD:'/:id/good', 19 | VOTE:'/:id/vote' 20 | } 21 | }; 22 | } 23 | 24 | function appConfig($translateProvider, $mdThemingProvider, $httpProvider) { 25 | 26 | $mdThemingProvider 27 | .theme('default') 28 | .primaryPalette('indigo') 29 | .accentPalette('red'); 30 | 31 | $httpProvider.defaults.headers.common['X-Requested-With'] = 32 | 'XMLHttpRequest'; 33 | 34 | $httpProvider.interceptors.push('httpInterceptor'); 35 | } 36 | 37 | //拦截器 38 | function interceptor($q, $rootScope) { 39 | return { 40 | // optional method 41 | 'request': function(config) { 42 | $rootScope.$broadcast('$requestStart', config); 43 | return config; 44 | }, 45 | 46 | // optional method 47 | 'requestError': function(rejection) { 48 | $rootScope.$broadcast('$requestError', rejection); 49 | return $q.reject(rejection); 50 | }, 51 | 52 | 53 | 54 | // optional method 55 | 'response': function(response) { 56 | $rootScope.$broadcast('$requestSuccess', response); 57 | return response; 58 | }, 59 | 60 | // optional method 61 | 'responseError': function(rejection) { 62 | $rootScope.$broadcast('$responseError', rejection); 63 | return $q.reject(rejection); 64 | } 65 | }; 66 | } 67 | })(); 68 | -------------------------------------------------------------------------------- /services/mail.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const config = require('../config'); 4 | const mailer = require('nodemailer'); 5 | const transporter = mailer.createTransport({ 6 | host: config.mail.HOST, 7 | port: config.mail.PORT, 8 | auth: { 9 | user: config.mail.USER, 10 | pass: config.mail.PASS, 11 | }, 12 | }); 13 | const fs = require('fs'); 14 | 15 | const ejs = require('ejs'); 16 | 17 | class Mail { 18 | /** 19 | *@description class mailservice 20 | *@params tplPath {String} template path 21 | *@params options {Object} 22 | *@params options.from {String} mail address 23 | *@params options.to {String} mail receiver 24 | *@params options.subject {String} mail title 25 | *@params options.html {String} mail content 26 | * */ 27 | constructor(tplPath, options) { 28 | let defaults = { 29 | from: `${config.SITE_NAME}<${config.mail.USER}>`, 30 | to: '', 31 | subject: `${config.SITE_NAME}帐号激活`, 32 | html: '', 33 | }; 34 | 35 | this._options = Object.assign(defaults, options); 36 | 37 | fs.readFile(tplPath, 'utf-8', (err, data)=> { 38 | this._template = data; 39 | }); 40 | 41 | } 42 | 43 | /** 44 | * 发送邮件 45 | * @method sendMail 46 | * @param {[Object]} data [description] 47 | * @param {[Object]} options [description] 48 | * @return {[Promise]} [description] 49 | */ 50 | sendMail(data, options) { 51 | options = Object.assign(this._options, options); 52 | 53 | data = data || {}; 54 | 55 | options.html = ejs.render(this._template, data); 56 | 57 | return new Promise(function(resolve, reject) { 58 | transporter.sendMail(options, function(err, info) { 59 | if (err) { 60 | reject(err); 61 | } else { 62 | resolve(info); 63 | } 64 | }); 65 | }); 66 | } 67 | } 68 | 69 | module.exports = Mail; 70 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | body{font-family:"Microsoft Yahei","Helvetica Neue",Arial,sans-serif!important}.mdl-pd-1x{padding:10px}.mdl-pd-2x{padding:20px}.mdl-pd-3x{padding:30px}.mdl-pd-ver-1x{padding-top:10px;padding-bottom:10px}.mdl-pd-ver-2x{padding-top:20px;padding-bottom:20px}.mdl-pd-ver-3x{padding-top:30px;padding-bottom:30px}.mdl-pd-hor-1x{padding-left:10px;padding-right:10px}.mdl-pd-hor-2x{padding-left:20px;padding-right:20px}.mdl-mg-1x{margin:10px}.mdl-mg-2x{margin:20px}.mdl-mg-3x{margin:30px}.mdl-mg-ver-1x{margin-top:10px;margin-bottom:10px}.mdl-mg-ver-2x{margin-top:20px;margin-bottom:20px}.mdl-mg-ver-3x{margin-top:30px;margin-bottom:30px}.mdl-mg-hor-1x{margin-left:10px;margin-right:10px}.mdl-mg-hor-2x{margin-left:20px;margin-right:20px}.mdl-text-center{text-align:center}.mdl-text-right{text-align:right}@font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(./fonts/MaterialIcons-Regular.eot);src:local("Material Icons"),local("MaterialIcons-Regular"),url(./fonts/MaterialIcons-Regular.woff2) format("woff2"),url(./fonts/MaterialIcons-Regular.woff) format("woff"),url(./fonts/MaterialIcons-Regular.ttf) format("truetype")}.material-icons{font-family:'Material Icons';font-weight:400;font-style:normal;font-size:24px;display:inline-block;width:1em;height:1em;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;-webkit-font-feature-settings:'liga';-moz-font-feature-settings:'liga';font-feature-settings:'liga'}.mdl-button-block,.mdl-textfield{width:100%}.mdl-layout-title{font-family:'Microsoft Yahei'}.md-fab-bottom-right{position:fixed;bottom:20px;right:0}.mdl-avatar{display:inline-block;width:40px;height:40px;-webkit-border-radius:50%;border-radius:50%;overflow:hidden;position:relative}.mdl-avatar h4,.mdl-avatar img{width:100%;height:100%}.mdl-avatar h4{text-align:center;padding:0;margin:0;line-height:2.5} -------------------------------------------------------------------------------- /models/topic.model.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mongoose = require('mongoose'); 4 | const Schema = mongoose.Schema; 5 | const ObjectId = Schema.Types.ObjectId; 6 | const TopicSchema = new Schema({ 7 | title: { 8 | type: String, 9 | required: true 10 | }, 11 | content: { 12 | type: String, 13 | required: true 14 | }, 15 | type: { 16 | type: Number, 17 | required: true 18 | }, 19 | isTop: { 20 | type: Boolean, 21 | default: false 22 | }, // 置顶帖 23 | isGood: { 24 | type: Boolean, 25 | default: false 26 | }, // 精华帖 27 | isLock: { 28 | type: Boolean, 29 | default: false 30 | }, // 被锁定主题 31 | deleted: { 32 | type: Boolean, 33 | default: false 34 | }, 35 | creator: { 36 | type: ObjectId, 37 | ref: 'User', 38 | required: true 39 | }, 40 | lastComment: { 41 | type: ObjectId, 42 | ref: 'Comment' 43 | }, 44 | lastCommentAt: { 45 | type: Date 46 | }, 47 | //点赞的人 48 | voters: [ { 49 | type: ObjectId, 50 | ref: 'User' 51 | } ], 52 | 53 | //收藏的人 54 | favers: [ { 55 | type: ObjectId, 56 | ref: 'User' 57 | } ], 58 | meta: { 59 | //点赞数 60 | votes: { 61 | type: Number, 62 | default: 0 63 | }, 64 | 65 | //收藏数 66 | favs: { 67 | type: Number, 68 | default: 0 69 | }, 70 | 71 | //访问数 72 | visits: { 73 | type: Number, 74 | default: 0 75 | }, 76 | 77 | //评论数 78 | comments: { 79 | type: Number, 80 | default: 0 81 | } 82 | } 83 | }, { 84 | versionKey: false, 85 | timestamps: { 86 | createdAt: 'createdAt', 87 | updatedAt: 'updatedAt' 88 | } 89 | }); 90 | 91 | TopicSchema.index({ 92 | isTop: -1, 93 | lastCommentAt: -1 94 | }); 95 | TopicSchema.index({ 96 | creator: 1, 97 | createdAt: -1 98 | }); 99 | 100 | module.exports = mongoose.model('Topic', TopicSchema); 101 | -------------------------------------------------------------------------------- /static/templates/common-toolbar.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 9 | 10 |

11 | Angular 2 中文社区 12 |

13 | 14 | 登录 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 |
23 |
24 | {{currentUser.profile.nickName}} 25 |
26 |
27 | {{currentUser.account}} 28 |
29 |
30 |
31 | 32 | 33 | 34 | account_circle 35 | 个人资料 36 | 37 | 38 | 39 | 40 | 41 | power_settings_new 42 | 退出登录 43 | 44 | 45 |
46 |
47 |
48 | 49 |
50 | -------------------------------------------------------------------------------- /controllers/user.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const util = require('../util'); 4 | const User = require('../services').User; 5 | 6 | const config = require('../config'); 7 | 8 | class UserController { 9 | 10 | /** 11 | * 验证帐户是否已经存在 12 | * @param req 13 | * @param res 14 | */ 15 | static unique(req, res) { 16 | User.unique(req.query.account) 17 | .then(function(isExist) { 18 | if (isExist) { 19 | res.responseError({ 20 | code: 403, 21 | msg: 'account is exist' 22 | }); 23 | } else { 24 | res.json({ 25 | result: true, 26 | msg: 'account is not exist' 27 | }); 28 | } 29 | }, function(err) { 30 | 31 | res.responseError({ 32 | code: 403, 33 | msg: err 34 | }); 35 | }); 36 | } 37 | 38 | /** 39 | * 激活用户帐号 40 | * @param req 41 | * @param res 42 | */ 43 | static active(req, res) { 44 | let userid = req.params.id; 45 | 46 | User.active(userid, function(err, user) { 47 | if (err) { 48 | return res.responseError(err); 49 | } 50 | 51 | res.json(user); 52 | }); 53 | } 54 | 55 | /** 56 | * 更新用户资料 57 | * @param req 58 | * @param res 59 | */ 60 | static update(req, res) { 61 | var reqBody = req.body; 62 | 63 | var update = Object.assign({}, reqBody); 64 | 65 | User.updateProfile(req.session.user, update) 66 | .then(doc => { 67 | res.json(doc); 68 | }) 69 | .catch(err => { 70 | res.responseError(err); 71 | }); 72 | } 73 | 74 | /** 75 | * 获取用户资料 76 | * @param req 77 | * @param res 78 | */ 79 | static getUserProfile(req, res) { 80 | var uid = req.params.id; 81 | 82 | User.getById(uid) 83 | .then(doc => { 84 | res.json(doc); 85 | }) 86 | .catch(err => { 87 | res.responseError(err); 88 | }); 89 | } 90 | } 91 | 92 | module.exports = UserController; 93 | -------------------------------------------------------------------------------- /controllers/comment.controller.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const services = require('../services'); 4 | const Comment = services.Comment; 5 | const Util = require('../util'); 6 | class CommentController { 7 | 8 | static createComment(req,res) { 9 | 10 | req.checkBody('content','评论内容不能为空').notEmpty(); 11 | req.checkBody('topicId','评论的主题不能为空').notEmpty(); 12 | 13 | let mapErrors = req.validationErrors(true); 14 | 15 | //如果存在错误,则向客户端返回错误 16 | if (mapErrors) { 17 | return res.responseError({ 18 | code:403, 19 | msg: mapErrors 20 | }); 21 | } 22 | 23 | let user = req.session.user; 24 | 25 | Comment.create(user,req.body) 26 | .then(result=>{ 27 | res.json(result); 28 | }) 29 | .catch(err=>{ 30 | logger.error(err); 31 | res.responseError(err); 32 | }); 33 | } 34 | 35 | static getCommentList(req,res) { 36 | let query = req.query||{}; 37 | Comment.getCommentList(query) 38 | .then(docs=>{ 39 | res.json(docs); 40 | }) 41 | .catch(err=>{ 42 | res.responseError(err); 43 | }); 44 | } 45 | 46 | static removeComment(req,res) { 47 | let commentId = req.params.id; 48 | let creator = req.session.user; 49 | Comment.removeById(commentId,creator) 50 | .then(result=>{ 51 | res.status(204).send(result); 52 | }) 53 | .catch(err=>{ 54 | res.responseError(err); 55 | }); 56 | } 57 | static updateComment(req,res) { 58 | req.checkBody('content','评论内容不能为空').notEmpty(); 59 | let mapErrors = req.validationErrors(true); 60 | 61 | //如果存在错误,则向客户端返回错误 62 | if (mapErrors) { 63 | return res.responseError({ 64 | code:403, 65 | msg: mapErrors 66 | }); 67 | } 68 | 69 | let creator = req.session.user; 70 | let update = Util.pick(req.body,[ 'content','mentions' ]); 71 | let id = req.params.id; 72 | 73 | 74 | Comment.update(id,creator,update) 75 | .then(doc=>{ 76 | res.status(201).json(doc); 77 | }) 78 | .catch(err=>{ 79 | res.responseError(err); 80 | }); 81 | } 82 | } 83 | module.exports = CommentController; 84 | -------------------------------------------------------------------------------- /middlewares/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const express = require('express'); 3 | 4 | express.response.__proto__.responseError = function(err) { 5 | let code = err.code || 500; 6 | 7 | this.status(code); 8 | 9 | //如果是异步请求,发送错误 10 | if (this.xhr) { 11 | return this.send(err); 12 | } 13 | 14 | //如果不是异步请求,渲染错误页面 15 | this.render('error', { 16 | title: err.msg, 17 | message: err.msg, 18 | error: err 19 | }); 20 | }; 21 | 22 | express.request.__proto__.generateSession = function(user, callback) { 23 | 24 | let req = this; 25 | 26 | callback = callback || noop; 27 | return new Promise((resolve, reject) => { 28 | 29 | req.session.regenerate(function() { 30 | req.session.user = user._id; 31 | req.session.account = user.account; 32 | req.session.nickName = user.profile.nickName; 33 | req.session.siteAdmin = user.siteAdmin; 34 | req.session.msg = 'Authenticated as ' + user.profile.nickName; 35 | 36 | user.set('lastOnline', Date.now()); 37 | logger.debug(user); 38 | user.save(function(err,doc) { 39 | if (err) { 40 | reject(err); 41 | callback(err, undefined); 42 | return; 43 | } 44 | 45 | resolve(doc); 46 | callback(undefined, doc); 47 | }); 48 | 49 | }); 50 | }); 51 | }; 52 | 53 | exports.signinRequired = function(req, res, next) { 54 | if (req.session.user) { 55 | next(); 56 | } else { 57 | if (req.xhr) { 58 | res.responseError({ 59 | code:401, 60 | msg: 'signin required' 61 | }); 62 | } else { 63 | res.redirect('/signin'); 64 | } 65 | } 66 | }; 67 | 68 | exports.adminRequired = function(req, res, next) { 69 | logger.debug(req.session); 70 | if (req.session.siteAdmin) { 71 | next(); 72 | } else { 73 | logger.warn('需要管理员权限'); 74 | if (req.xhr) { 75 | res.responseError({ 76 | code:401, 77 | msg: 'admin required' 78 | }); 79 | } else { 80 | res.redirect('/'); 81 | } 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /static/lib/moment/locale/ar-tn.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Tunisian Arabic (ar-tn) 3 | 4 | (function (global, factory) { 5 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 6 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 7 | factory(global.moment) 8 | }(this, function (moment) { 'use strict'; 9 | 10 | 11 | var ar_tn = moment.defineLocale('ar-tn', { 12 | months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), 13 | monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), 14 | weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), 15 | weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), 16 | weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), 17 | longDateFormat: { 18 | LT: 'HH:mm', 19 | LTS: 'HH:mm:ss', 20 | L: 'DD/MM/YYYY', 21 | LL: 'D MMMM YYYY', 22 | LLL: 'D MMMM YYYY HH:mm', 23 | LLLL: 'dddd D MMMM YYYY HH:mm' 24 | }, 25 | calendar: { 26 | sameDay: '[اليوم على الساعة] LT', 27 | nextDay: '[غدا على الساعة] LT', 28 | nextWeek: 'dddd [على الساعة] LT', 29 | lastDay: '[أمس على الساعة] LT', 30 | lastWeek: 'dddd [على الساعة] LT', 31 | sameElse: 'L' 32 | }, 33 | relativeTime: { 34 | future: 'في %s', 35 | past: 'منذ %s', 36 | s: 'ثوان', 37 | m: 'دقيقة', 38 | mm: '%d دقائق', 39 | h: 'ساعة', 40 | hh: '%d ساعات', 41 | d: 'يوم', 42 | dd: '%d أيام', 43 | M: 'شهر', 44 | MM: '%d أشهر', 45 | y: 'سنة', 46 | yy: '%d سنوات' 47 | }, 48 | week: { 49 | dow: 1, // Monday is the first day of the week. 50 | doy: 4 // The week that contains Jan 4th is the first week of the year. 51 | } 52 | }); 53 | 54 | return ar_tn; 55 | 56 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/ja.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : japanese (ja) 3 | //! author : LI Long : https://github.com/baryon 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var ja = moment.defineLocale('ja', { 13 | months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), 14 | monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'), 15 | weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'), 16 | weekdaysShort : '日_月_火_水_木_金_土'.split('_'), 17 | weekdaysMin : '日_月_火_水_木_金_土'.split('_'), 18 | longDateFormat : { 19 | LT : 'Ah時m分', 20 | LTS : 'Ah時m分s秒', 21 | L : 'YYYY/MM/DD', 22 | LL : 'YYYY年M月D日', 23 | LLL : 'YYYY年M月D日Ah時m分', 24 | LLLL : 'YYYY年M月D日Ah時m分 dddd' 25 | }, 26 | meridiemParse: /午前|午後/i, 27 | isPM : function (input) { 28 | return input === '午後'; 29 | }, 30 | meridiem : function (hour, minute, isLower) { 31 | if (hour < 12) { 32 | return '午前'; 33 | } else { 34 | return '午後'; 35 | } 36 | }, 37 | calendar : { 38 | sameDay : '[今日] LT', 39 | nextDay : '[明日] LT', 40 | nextWeek : '[来週]dddd LT', 41 | lastDay : '[昨日] LT', 42 | lastWeek : '[前週]dddd LT', 43 | sameElse : 'L' 44 | }, 45 | relativeTime : { 46 | future : '%s後', 47 | past : '%s前', 48 | s : '数秒', 49 | m : '1分', 50 | mm : '%d分', 51 | h : '1時間', 52 | hh : '%d時間', 53 | d : '1日', 54 | dd : '%d日', 55 | M : '1ヶ月', 56 | MM : '%dヶ月', 57 | y : '1年', 58 | yy : '%d年' 59 | } 60 | }); 61 | 62 | return ja; 63 | 64 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/km.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : khmer (km) 3 | //! author : Kruy Vanna : https://github.com/kruyvanna 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var km = moment.defineLocale('km', { 13 | months: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), 14 | monthsShort: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), 15 | weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), 16 | weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), 17 | weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), 18 | longDateFormat: { 19 | LT: 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L: 'DD/MM/YYYY', 22 | LL: 'D MMMM YYYY', 23 | LLL: 'D MMMM YYYY HH:mm', 24 | LLLL: 'dddd, D MMMM YYYY HH:mm' 25 | }, 26 | calendar: { 27 | sameDay: '[ថ្ងៃនៈ ម៉ោង] LT', 28 | nextDay: '[ស្អែក ម៉ោង] LT', 29 | nextWeek: 'dddd [ម៉ោង] LT', 30 | lastDay: '[ម្សិលមិញ ម៉ោង] LT', 31 | lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime: { 35 | future: '%sទៀត', 36 | past: '%sមុន', 37 | s: 'ប៉ុន្មានវិនាទី', 38 | m: 'មួយនាទី', 39 | mm: '%d នាទី', 40 | h: 'មួយម៉ោង', 41 | hh: '%d ម៉ោង', 42 | d: 'មួយថ្ងៃ', 43 | dd: '%d ថ្ងៃ', 44 | M: 'មួយខែ', 45 | MM: '%d ខែ', 46 | y: 'មួយឆ្នាំ', 47 | yy: '%d ឆ្នាំ' 48 | }, 49 | week: { 50 | dow: 1, // Monday is the first day of the week. 51 | doy: 4 // The week that contains Jan 4th is the first week of the year. 52 | } 53 | }); 54 | 55 | return km; 56 | 57 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/fr-ca.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : canadian french (fr-ca) 3 | //! author : Jonathan Abourbih : https://github.com/jonbca 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var fr_ca = moment.defineLocale('fr-ca', { 13 | months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), 14 | monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), 15 | weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), 16 | weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), 17 | weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'YYYY-MM-DD', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd D MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[Aujourd\'hui à] LT', 28 | nextDay: '[Demain à] LT', 29 | nextWeek: 'dddd [à] LT', 30 | lastDay: '[Hier à] LT', 31 | lastWeek: 'dddd [dernier à] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : 'dans %s', 36 | past : 'il y a %s', 37 | s : 'quelques secondes', 38 | m : 'une minute', 39 | mm : '%d minutes', 40 | h : 'une heure', 41 | hh : '%d heures', 42 | d : 'un jour', 43 | dd : '%d jours', 44 | M : 'un mois', 45 | MM : '%d mois', 46 | y : 'un an', 47 | yy : '%d ans' 48 | }, 49 | ordinalParse: /\d{1,2}(er|e)/, 50 | ordinal : function (number) { 51 | return number + (number === 1 ? 'er' : 'e'); 52 | } 53 | }); 54 | 55 | return fr_ca; 56 | 57 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/uz.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : uzbek (uz) 3 | //! author : Sardor Muminov : https://github.com/muminoff 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var uz = moment.defineLocale('uz', { 13 | months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), 14 | monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), 15 | weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), 16 | weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), 17 | weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'D MMMM YYYY, dddd HH:mm' 25 | }, 26 | calendar : { 27 | sameDay : '[Бугун соат] LT [да]', 28 | nextDay : '[Эртага] LT [да]', 29 | nextWeek : 'dddd [куни соат] LT [да]', 30 | lastDay : '[Кеча соат] LT [да]', 31 | lastWeek : '[Утган] dddd [куни соат] LT [да]', 32 | sameElse : 'L' 33 | }, 34 | relativeTime : { 35 | future : 'Якин %s ичида', 36 | past : 'Бир неча %s олдин', 37 | s : 'фурсат', 38 | m : 'бир дакика', 39 | mm : '%d дакика', 40 | h : 'бир соат', 41 | hh : '%d соат', 42 | d : 'бир кун', 43 | dd : '%d кун', 44 | M : 'бир ой', 45 | MM : '%d ой', 46 | y : 'бир йил', 47 | yy : '%d йил' 48 | }, 49 | week : { 50 | dow : 1, // Monday is the first day of the week. 51 | doy : 7 // The week that contains Jan 4th is the first week of the year. 52 | } 53 | }); 54 | 55 | return uz; 56 | 57 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/ko.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : korean (ko) 3 | //! 4 | //! authors 5 | //! 6 | //! - Kyungwook, Park : https://github.com/kyungw00k 7 | //! - Jeeeyul Lee 8 | 9 | (function (global, factory) { 10 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 11 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 12 | factory(global.moment) 13 | }(this, function (moment) { 'use strict'; 14 | 15 | 16 | var ko = moment.defineLocale('ko', { 17 | months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), 18 | monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'), 19 | weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'), 20 | weekdaysShort : '일_월_화_수_목_금_토'.split('_'), 21 | weekdaysMin : '일_월_화_수_목_금_토'.split('_'), 22 | longDateFormat : { 23 | LT : 'A h시 m분', 24 | LTS : 'A h시 m분 s초', 25 | L : 'YYYY.MM.DD', 26 | LL : 'YYYY년 MMMM D일', 27 | LLL : 'YYYY년 MMMM D일 A h시 m분', 28 | LLLL : 'YYYY년 MMMM D일 dddd A h시 m분' 29 | }, 30 | calendar : { 31 | sameDay : '오늘 LT', 32 | nextDay : '내일 LT', 33 | nextWeek : 'dddd LT', 34 | lastDay : '어제 LT', 35 | lastWeek : '지난주 dddd LT', 36 | sameElse : 'L' 37 | }, 38 | relativeTime : { 39 | future : '%s 후', 40 | past : '%s 전', 41 | s : '몇초', 42 | ss : '%d초', 43 | m : '일분', 44 | mm : '%d분', 45 | h : '한시간', 46 | hh : '%d시간', 47 | d : '하루', 48 | dd : '%d일', 49 | M : '한달', 50 | MM : '%d달', 51 | y : '일년', 52 | yy : '%d년' 53 | }, 54 | ordinalParse : /\d{1,2}일/, 55 | ordinal : '%d일', 56 | meridiemParse : /오전|오후/, 57 | isPM : function (token) { 58 | return token === '오후'; 59 | }, 60 | meridiem : function (hour, minute, isUpper) { 61 | return hour < 12 ? '오전' : '오후'; 62 | } 63 | }); 64 | 65 | return ko; 66 | 67 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/tzm.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Morocco Central Atlas Tamaziɣt (tzm) 3 | //! author : Abdel Said : https://github.com/abdelsaid 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var tzm = moment.defineLocale('tzm', { 13 | months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), 14 | monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), 15 | weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), 16 | weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), 17 | weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS: 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd D MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[ⴰⵙⴷⵅ ⴴ] LT', 28 | nextDay: '[ⴰⵙⴽⴰ ⴴ] LT', 29 | nextWeek: 'dddd [ⴴ] LT', 30 | lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT', 31 | lastWeek: 'dddd [ⴴ] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s', 36 | past : 'ⵢⴰⵏ %s', 37 | s : 'ⵉⵎⵉⴽ', 38 | m : 'ⵎⵉⵏⵓⴺ', 39 | mm : '%d ⵎⵉⵏⵓⴺ', 40 | h : 'ⵙⴰⵄⴰ', 41 | hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ', 42 | d : 'ⴰⵙⵙ', 43 | dd : '%d oⵙⵙⴰⵏ', 44 | M : 'ⴰⵢoⵓⵔ', 45 | MM : '%d ⵉⵢⵢⵉⵔⵏ', 46 | y : 'ⴰⵙⴳⴰⵙ', 47 | yy : '%d ⵉⵙⴳⴰⵙⵏ' 48 | }, 49 | week : { 50 | dow : 6, // Saturday is the first day of the week. 51 | doy : 12 // The week that contains Jan 1st is the first week of the year. 52 | } 53 | }); 54 | 55 | return tzm; 56 | 57 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/da.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : danish (da) 3 | //! author : Ulrik Nielsen : https://github.com/mrbase 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var da = moment.defineLocale('da', { 13 | months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'), 14 | monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), 15 | weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), 16 | weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'), 17 | weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D. MMMM YYYY', 23 | LLL : 'D. MMMM YYYY HH:mm', 24 | LLLL : 'dddd [d.] D. MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay : '[I dag kl.] LT', 28 | nextDay : '[I morgen kl.] LT', 29 | nextWeek : 'dddd [kl.] LT', 30 | lastDay : '[I går kl.] LT', 31 | lastWeek : '[sidste] dddd [kl] LT', 32 | sameElse : 'L' 33 | }, 34 | relativeTime : { 35 | future : 'om %s', 36 | past : '%s siden', 37 | s : 'få sekunder', 38 | m : 'et minut', 39 | mm : '%d minutter', 40 | h : 'en time', 41 | hh : '%d timer', 42 | d : 'en dag', 43 | dd : '%d dage', 44 | M : 'en måned', 45 | MM : '%d måneder', 46 | y : 'et år', 47 | yy : '%d år' 48 | }, 49 | ordinalParse: /\d{1,2}\./, 50 | ordinal : '%d.', 51 | week : { 52 | dow : 1, // Monday is the first day of the week. 53 | doy : 4 // The week that contains Jan 4th is the first week of the year. 54 | } 55 | }); 56 | 57 | return da; 58 | 59 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/ar-ma.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Moroccan Arabic (ar-ma) 3 | //! author : ElFadili Yassine : https://github.com/ElFadiliY 4 | //! author : Abdel Said : https://github.com/abdelsaid 5 | 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 8 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 9 | factory(global.moment) 10 | }(this, function (moment) { 'use strict'; 11 | 12 | 13 | var ar_ma = moment.defineLocale('ar-ma', { 14 | months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), 15 | monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), 16 | weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), 17 | weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), 18 | weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), 19 | longDateFormat : { 20 | LT : 'HH:mm', 21 | LTS : 'HH:mm:ss', 22 | L : 'DD/MM/YYYY', 23 | LL : 'D MMMM YYYY', 24 | LLL : 'D MMMM YYYY HH:mm', 25 | LLLL : 'dddd D MMMM YYYY HH:mm' 26 | }, 27 | calendar : { 28 | sameDay: '[اليوم على الساعة] LT', 29 | nextDay: '[غدا على الساعة] LT', 30 | nextWeek: 'dddd [على الساعة] LT', 31 | lastDay: '[أمس على الساعة] LT', 32 | lastWeek: 'dddd [على الساعة] LT', 33 | sameElse: 'L' 34 | }, 35 | relativeTime : { 36 | future : 'في %s', 37 | past : 'منذ %s', 38 | s : 'ثوان', 39 | m : 'دقيقة', 40 | mm : '%d دقائق', 41 | h : 'ساعة', 42 | hh : '%d ساعات', 43 | d : 'يوم', 44 | dd : '%d أيام', 45 | M : 'شهر', 46 | MM : '%d أشهر', 47 | y : 'سنة', 48 | yy : '%d سنوات' 49 | }, 50 | week : { 51 | dow : 6, // Saturday is the first day of the week. 52 | doy : 12 // The week that contains Jan 1st is the first week of the year. 53 | } 54 | }); 55 | 56 | return ar_ma; 57 | 58 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/nn.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : norwegian nynorsk (nn) 3 | //! author : https://github.com/mechuwind 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var nn = moment.defineLocale('nn', { 13 | months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), 14 | monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), 15 | weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'), 16 | weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'), 17 | weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD.MM.YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd D MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[I dag klokka] LT', 28 | nextDay: '[I morgon klokka] LT', 29 | nextWeek: 'dddd [klokka] LT', 30 | lastDay: '[I går klokka] LT', 31 | lastWeek: '[Føregåande] dddd [klokka] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : 'om %s', 36 | past : 'for %s sidan', 37 | s : 'nokre sekund', 38 | m : 'eit minutt', 39 | mm : '%d minutt', 40 | h : 'ein time', 41 | hh : '%d timar', 42 | d : 'ein dag', 43 | dd : '%d dagar', 44 | M : 'ein månad', 45 | MM : '%d månader', 46 | y : 'eit år', 47 | yy : '%d år' 48 | }, 49 | ordinalParse: /\d{1,2}\./, 50 | ordinal : '%d.', 51 | week : { 52 | dow : 1, // Monday is the first day of the week. 53 | doy : 4 // The week that contains Jan 4th is the first week of the year. 54 | } 55 | }); 56 | 57 | return nn; 58 | 59 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/fo.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : faroese (fo) 3 | //! author : Ragnar Johannesen : https://github.com/ragnar123 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var fo = moment.defineLocale('fo', { 13 | months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), 14 | monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), 15 | weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), 16 | weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), 17 | weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd D. MMMM, YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay : '[Í dag kl.] LT', 28 | nextDay : '[Í morgin kl.] LT', 29 | nextWeek : 'dddd [kl.] LT', 30 | lastDay : '[Í gjár kl.] LT', 31 | lastWeek : '[síðstu] dddd [kl] LT', 32 | sameElse : 'L' 33 | }, 34 | relativeTime : { 35 | future : 'um %s', 36 | past : '%s síðani', 37 | s : 'fá sekund', 38 | m : 'ein minutt', 39 | mm : '%d minuttir', 40 | h : 'ein tími', 41 | hh : '%d tímar', 42 | d : 'ein dagur', 43 | dd : '%d dagar', 44 | M : 'ein mánaði', 45 | MM : '%d mánaðir', 46 | y : 'eitt ár', 47 | yy : '%d ár' 48 | }, 49 | ordinalParse: /\d{1,2}\./, 50 | ordinal : '%d.', 51 | week : { 52 | dow : 1, // Monday is the first day of the week. 53 | doy : 4 // The week that contains Jan 4th is the first week of the year. 54 | } 55 | }); 56 | 57 | return fo; 58 | 59 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/tzm-latn.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn) 3 | //! author : Abdel Said : https://github.com/abdelsaid 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var tzm_latn = moment.defineLocale('tzm-latn', { 13 | months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), 14 | monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'), 15 | weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), 16 | weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), 17 | weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd D MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[asdkh g] LT', 28 | nextDay: '[aska g] LT', 29 | nextWeek: 'dddd [g] LT', 30 | lastDay: '[assant g] LT', 31 | lastWeek: 'dddd [g] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : 'dadkh s yan %s', 36 | past : 'yan %s', 37 | s : 'imik', 38 | m : 'minuḍ', 39 | mm : '%d minuḍ', 40 | h : 'saɛa', 41 | hh : '%d tassaɛin', 42 | d : 'ass', 43 | dd : '%d ossan', 44 | M : 'ayowr', 45 | MM : '%d iyyirn', 46 | y : 'asgas', 47 | yy : '%d isgasn' 48 | }, 49 | week : { 50 | dow : 6, // Saturday is the first day of the week. 51 | doy : 12 // The week that contains Jan 1st is the first week of the year. 52 | } 53 | }); 54 | 55 | return tzm_latn; 56 | 57 | })); -------------------------------------------------------------------------------- /static/js/directives/app.directives.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var directives = angular.module('app.directives', []); 3 | 4 | directives.directive('unique', uniqueDirecitve); 5 | 6 | function uniqueDirecitve($parse, user) { 7 | return { 8 | require: '?^ngModel', 9 | link: function(scope, element, attr, ngModel) { 10 | var isUnique = false; 11 | var getNgModel = $parse(attr.ngModel); 12 | 13 | element.bind('blur', function() { 14 | var value = getNgModel(scope); 15 | 16 | if (isUnique || !value) { 17 | return; 18 | } 19 | 20 | user.unique(value) 21 | .success(function(resp) { 22 | console.log(resp); 23 | ngModel.$setValidity('unique', true); 24 | isUnique = true; 25 | }) 26 | .error(function(err) { 27 | console.log(err); 28 | ngModel.$setValidity('unique', false); 29 | isUnique = true; 30 | }); 31 | }); 32 | 33 | element.bind('input', function() { 34 | isUnique = false; 35 | }); 36 | } 37 | }; 38 | } 39 | 40 | directives.directive('languageMenu', languageMenuDirective); 41 | 42 | function languageMenuDirective($translate) { 43 | return { 44 | link: function(scope, element) { 45 | var langs = [{ 46 | text: '中文', 47 | value: 'zh_CN', 48 | isChecked: true 49 | }, { 50 | text: 'English', 51 | value: 'en', 52 | isChecked: false 53 | } ]; 54 | 55 | scope.openMenu = function($mdOpenMenu, ev) { 56 | $mdOpenMenu(ev); 57 | }; 58 | 59 | scope.changeLang = function(lang) { 60 | $translate.use(lang.value); 61 | angular.forEach(langs, function(item) { 62 | item.isChecked = false; 63 | }); 64 | 65 | lang.isChecked = true; 66 | }; 67 | 68 | scope.langs = langs; 69 | } 70 | }; 71 | } 72 | 73 | directives.directive('mdAvatar', avatarDirective); 74 | 75 | function avatarDirective() { 76 | return { 77 | restrict: 'EA', 78 | replace: true, 79 | templateUrl: '../templates/avatar.html', 80 | scope: { 81 | profile: '=' 82 | } 83 | }; 84 | } 85 | 86 | })(); 87 | -------------------------------------------------------------------------------- /static/lib/moment/locale/tl-ph.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Tagalog/Filipino (tl-ph) 3 | //! author : Dan Hagman 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var tl_ph = moment.defineLocale('tl-ph', { 13 | months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), 14 | monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), 15 | weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), 16 | weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), 17 | weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'MM/D/YYYY', 22 | LL : 'MMMM D, YYYY', 23 | LLL : 'MMMM D, YYYY HH:mm', 24 | LLLL : 'dddd, MMMM DD, YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[Ngayon sa] LT', 28 | nextDay: '[Bukas sa] LT', 29 | nextWeek: 'dddd [sa] LT', 30 | lastDay: '[Kahapon sa] LT', 31 | lastWeek: 'dddd [huling linggo] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : 'sa loob ng %s', 36 | past : '%s ang nakalipas', 37 | s : 'ilang segundo', 38 | m : 'isang minuto', 39 | mm : '%d minuto', 40 | h : 'isang oras', 41 | hh : '%d oras', 42 | d : 'isang araw', 43 | dd : '%d araw', 44 | M : 'isang buwan', 45 | MM : '%d buwan', 46 | y : 'isang taon', 47 | yy : '%d taon' 48 | }, 49 | ordinalParse: /\d{1,2}/, 50 | ordinal : function (number) { 51 | return number; 52 | }, 53 | week : { 54 | dow : 1, // Monday is the first day of the week. 55 | doy : 4 // The week that contains Jan 4th is the first week of the year. 56 | } 57 | }); 58 | 59 | return tl_ph; 60 | 61 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/nb.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : norwegian bokmål (nb) 3 | //! authors : Espen Hovlandsdal : https://github.com/rexxars 4 | //! Sigurd Gartmann : https://github.com/sigurdga 5 | 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 8 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 9 | factory(global.moment) 10 | }(this, function (moment) { 'use strict'; 11 | 12 | 13 | var nb = moment.defineLocale('nb', { 14 | months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'), 15 | monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), 16 | weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'), 17 | weekdaysShort : 'søn_man_tirs_ons_tors_fre_lør'.split('_'), 18 | weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), 19 | longDateFormat : { 20 | LT : 'H.mm', 21 | LTS : 'H.mm.ss', 22 | L : 'DD.MM.YYYY', 23 | LL : 'D. MMMM YYYY', 24 | LLL : 'D. MMMM YYYY [kl.] H.mm', 25 | LLLL : 'dddd D. MMMM YYYY [kl.] H.mm' 26 | }, 27 | calendar : { 28 | sameDay: '[i dag kl.] LT', 29 | nextDay: '[i morgen kl.] LT', 30 | nextWeek: 'dddd [kl.] LT', 31 | lastDay: '[i går kl.] LT', 32 | lastWeek: '[forrige] dddd [kl.] LT', 33 | sameElse: 'L' 34 | }, 35 | relativeTime : { 36 | future : 'om %s', 37 | past : 'for %s siden', 38 | s : 'noen sekunder', 39 | m : 'ett minutt', 40 | mm : '%d minutter', 41 | h : 'en time', 42 | hh : '%d timer', 43 | d : 'en dag', 44 | dd : '%d dager', 45 | M : 'en måned', 46 | MM : '%d måneder', 47 | y : 'ett år', 48 | yy : '%d år' 49 | }, 50 | ordinalParse: /\d{1,2}\./, 51 | ordinal : '%d.', 52 | week : { 53 | dow : 1, // Monday is the first day of the week. 54 | doy : 4 // The week that contains Jan 4th is the first week of the year. 55 | } 56 | }); 57 | 58 | return nb; 59 | 60 | })); -------------------------------------------------------------------------------- /models/user.model.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var mongoose = require('mongoose'); 4 | var Schema = mongoose.Schema; 5 | var ObjectId = Schema.Types.ObjectId; 6 | 7 | var UserSchema = new Schema({ 8 | account: { 9 | type: String, 10 | required: true, 11 | unique: true 12 | }, 13 | hashedPassword: { 14 | type: String 15 | }, 16 | openId: String, //第三方帐号登录的用户ID 17 | 18 | type: { 19 | required: true, 20 | type: Number, //1:注册用户,2:QQ用户,3:微博用户:4:github用户,5:微信 21 | default: 1 22 | }, 23 | isActive: { 24 | type: Boolean, 25 | default: false //帐号是否激活,默认未激活 26 | }, 27 | meta: { 28 | //用户积分 29 | score: { 30 | type: Number, 31 | default: 0 32 | }, 33 | 34 | //发贴数 35 | topicCount: { 36 | type: Number, 37 | default: 0 38 | }, 39 | 40 | //评论数 41 | commentCount: { 42 | type: Number, 43 | default: 0 44 | }, 45 | 46 | //精华文章数 47 | goodTopicCount: { 48 | type: Number, 49 | default: 0 50 | } 51 | }, 52 | profile: { 53 | nickName: { 54 | type: String, 55 | required: true 56 | }, 57 | realName: String, 58 | mobile: String, 59 | email: String, 60 | qq: String, 61 | weibo: String, 62 | weixin: String, 63 | github: String, 64 | googlePlus: String, 65 | facebook: String, 66 | twitter: String, 67 | avatar: String, 68 | gender: Number, //1为男性,0为女性 69 | province: String, 70 | city: String, 71 | address: String, 72 | website: String, 73 | birthday: Date, 74 | description: String 75 | }, 76 | 77 | siteAdmin: { 78 | type: Boolean, 79 | default: false 80 | }, 81 | lastOnline: { 82 | type: Date, 83 | default: Date.now 84 | } 85 | }, { 86 | versionKey: false, 87 | timestamps: { 88 | createdAt: 'createdAt', 89 | updatedAt: 'updatedAt' 90 | } 91 | }); 92 | 93 | UserSchema.statics.unique = function(query) { 94 | return new Promise((resolve, reject) => { 95 | this.findOne(query, function(err, doc) { 96 | if (err) { 97 | reject(err); 98 | } else { 99 | let isExist = !!doc; 100 | resolve(isExist, doc); 101 | } 102 | }); 103 | }); 104 | }; 105 | 106 | module.exports = mongoose.model('User', UserSchema); 107 | -------------------------------------------------------------------------------- /static/lib/moment/locale/fr.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : french (fr) 3 | //! author : John Fischer : https://github.com/jfroffice 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var fr = moment.defineLocale('fr', { 13 | months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'), 14 | monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'), 15 | weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'), 16 | weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'), 17 | weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd D MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[Aujourd\'hui à] LT', 28 | nextDay: '[Demain à] LT', 29 | nextWeek: 'dddd [à] LT', 30 | lastDay: '[Hier à] LT', 31 | lastWeek: 'dddd [dernier à] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : 'dans %s', 36 | past : 'il y a %s', 37 | s : 'quelques secondes', 38 | m : 'une minute', 39 | mm : '%d minutes', 40 | h : 'une heure', 41 | hh : '%d heures', 42 | d : 'un jour', 43 | dd : '%d jours', 44 | M : 'un mois', 45 | MM : '%d mois', 46 | y : 'un an', 47 | yy : '%d ans' 48 | }, 49 | ordinalParse: /\d{1,2}(er|)/, 50 | ordinal : function (number) { 51 | return number + (number === 1 ? 'er' : ''); 52 | }, 53 | week : { 54 | dow : 1, // Monday is the first day of the week. 55 | doy : 4 // The week that contains Jan 4th is the first week of the year. 56 | } 57 | }); 58 | 59 | return fr; 60 | 61 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/pt-br.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : brazilian portuguese (pt-br) 3 | //! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var pt_br = moment.defineLocale('pt-br', { 13 | months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), 14 | monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), 15 | weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'), 16 | weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), 17 | weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D [de] MMMM [de] YYYY', 23 | LLL : 'D [de] MMMM [de] YYYY [às] HH:mm', 24 | LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[Hoje às] LT', 28 | nextDay: '[Amanhã às] LT', 29 | nextWeek: 'dddd [às] LT', 30 | lastDay: '[Ontem às] LT', 31 | lastWeek: function () { 32 | return (this.day() === 0 || this.day() === 6) ? 33 | '[Último] dddd [às] LT' : // Saturday + Sunday 34 | '[Última] dddd [às] LT'; // Monday - Friday 35 | }, 36 | sameElse: 'L' 37 | }, 38 | relativeTime : { 39 | future : 'em %s', 40 | past : '%s atrás', 41 | s : 'poucos segundos', 42 | m : 'um minuto', 43 | mm : '%d minutos', 44 | h : 'uma hora', 45 | hh : '%d horas', 46 | d : 'um dia', 47 | dd : '%d dias', 48 | M : 'um mês', 49 | MM : '%d meses', 50 | y : 'um ano', 51 | yy : '%d anos' 52 | }, 53 | ordinalParse: /\d{1,2}º/, 54 | ordinal : '%dº' 55 | }); 56 | 57 | return pt_br; 58 | 59 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/en-ca.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : canadian english (en-ca) 3 | //! author : Jonathan Abourbih : https://github.com/jonbca 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var en_ca = moment.defineLocale('en-ca', { 13 | months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), 14 | monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), 15 | weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), 16 | weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), 17 | weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), 18 | longDateFormat : { 19 | LT : 'h:mm A', 20 | LTS : 'h:mm:ss A', 21 | L : 'YYYY-MM-DD', 22 | LL : 'D MMMM, YYYY', 23 | LLL : 'D MMMM, YYYY h:mm A', 24 | LLLL : 'dddd, D MMMM, YYYY h:mm A' 25 | }, 26 | calendar : { 27 | sameDay : '[Today at] LT', 28 | nextDay : '[Tomorrow at] LT', 29 | nextWeek : 'dddd [at] LT', 30 | lastDay : '[Yesterday at] LT', 31 | lastWeek : '[Last] dddd [at] LT', 32 | sameElse : 'L' 33 | }, 34 | relativeTime : { 35 | future : 'in %s', 36 | past : '%s ago', 37 | s : 'a few seconds', 38 | m : 'a minute', 39 | mm : '%d minutes', 40 | h : 'an hour', 41 | hh : '%d hours', 42 | d : 'a day', 43 | dd : '%d days', 44 | M : 'a month', 45 | MM : '%d months', 46 | y : 'a year', 47 | yy : '%d years' 48 | }, 49 | ordinalParse: /\d{1,2}(st|nd|rd|th)/, 50 | ordinal : function (number) { 51 | var b = number % 10, 52 | output = (~~(number % 100 / 10) === 1) ? 'th' : 53 | (b === 1) ? 'st' : 54 | (b === 2) ? 'nd' : 55 | (b === 3) ? 'rd' : 'th'; 56 | return number + output; 57 | } 58 | }); 59 | 60 | return en_ca; 61 | 62 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/si.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Sinhalese (si) 3 | //! author : Sampath Sitinamaluwa : https://github.com/sampathsris 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var si = moment.defineLocale('si', { 13 | months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), 14 | monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), 15 | weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), 16 | weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන'.split('_'), 17 | weekdaysMin : 'ඉ_ස_අ_බ_බ්‍ර_සි_සෙ'.split('_'), 18 | longDateFormat : { 19 | LT : 'a h:mm', 20 | LTS : 'a h:mm:ss', 21 | L : 'YYYY/MM/DD', 22 | LL : 'YYYY MMMM D', 23 | LLL : 'YYYY MMMM D, a h:mm', 24 | LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss' 25 | }, 26 | calendar : { 27 | sameDay : '[අද] LT[ට]', 28 | nextDay : '[හෙට] LT[ට]', 29 | nextWeek : 'dddd LT[ට]', 30 | lastDay : '[ඊයේ] LT[ට]', 31 | lastWeek : '[පසුගිය] dddd LT[ට]', 32 | sameElse : 'L' 33 | }, 34 | relativeTime : { 35 | future : '%sකින්', 36 | past : '%sකට පෙර', 37 | s : 'තත්පර කිහිපය', 38 | m : 'මිනිත්තුව', 39 | mm : 'මිනිත්තු %d', 40 | h : 'පැය', 41 | hh : 'පැය %d', 42 | d : 'දිනය', 43 | dd : 'දින %d', 44 | M : 'මාසය', 45 | MM : 'මාස %d', 46 | y : 'වසර', 47 | yy : 'වසර %d' 48 | }, 49 | ordinalParse: /\d{1,2} වැනි/, 50 | ordinal : function (number) { 51 | return number + ' වැනි'; 52 | }, 53 | meridiem : function (hours, minutes, isLower) { 54 | if (hours > 11) { 55 | return isLower ? 'ප.ව.' : 'පස් වරු'; 56 | } else { 57 | return isLower ? 'පෙ.ව.' : 'පෙර වරු'; 58 | } 59 | } 60 | }); 61 | 62 | return si; 63 | 64 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/pt.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : portuguese (pt) 3 | //! author : Jefferson : https://github.com/jalex79 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var pt = moment.defineLocale('pt', { 13 | months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'), 14 | monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'), 15 | weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'), 16 | weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'), 17 | weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D [de] MMMM [de] YYYY', 23 | LLL : 'D [de] MMMM [de] YYYY HH:mm', 24 | LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[Hoje às] LT', 28 | nextDay: '[Amanhã às] LT', 29 | nextWeek: 'dddd [às] LT', 30 | lastDay: '[Ontem às] LT', 31 | lastWeek: function () { 32 | return (this.day() === 0 || this.day() === 6) ? 33 | '[Último] dddd [às] LT' : // Saturday + Sunday 34 | '[Última] dddd [às] LT'; // Monday - Friday 35 | }, 36 | sameElse: 'L' 37 | }, 38 | relativeTime : { 39 | future : 'em %s', 40 | past : 'há %s', 41 | s : 'segundos', 42 | m : 'um minuto', 43 | mm : '%d minutos', 44 | h : 'uma hora', 45 | hh : '%d horas', 46 | d : 'um dia', 47 | dd : '%d dias', 48 | M : 'um mês', 49 | MM : '%d meses', 50 | y : 'um ano', 51 | yy : '%d anos' 52 | }, 53 | ordinalParse: /\d{1,2}º/, 54 | ordinal : '%dº', 55 | week : { 56 | dow : 1, // Monday is the first day of the week. 57 | doy : 4 // The week that contains Jan 4th is the first week of the year. 58 | } 59 | }); 60 | 61 | return pt; 62 | 63 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/vi.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : vietnamese (vi) 3 | //! author : Bang Nguyen : https://github.com/bangnk 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var vi = moment.defineLocale('vi', { 13 | months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), 14 | monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), 15 | weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), 16 | weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), 17 | weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM [năm] YYYY', 23 | LLL : 'D MMMM [năm] YYYY HH:mm', 24 | LLLL : 'dddd, D MMMM [năm] YYYY HH:mm', 25 | l : 'DD/M/YYYY', 26 | ll : 'D MMM YYYY', 27 | lll : 'D MMM YYYY HH:mm', 28 | llll : 'ddd, D MMM YYYY HH:mm' 29 | }, 30 | calendar : { 31 | sameDay: '[Hôm nay lúc] LT', 32 | nextDay: '[Ngày mai lúc] LT', 33 | nextWeek: 'dddd [tuần tới lúc] LT', 34 | lastDay: '[Hôm qua lúc] LT', 35 | lastWeek: 'dddd [tuần rồi lúc] LT', 36 | sameElse: 'L' 37 | }, 38 | relativeTime : { 39 | future : '%s tới', 40 | past : '%s trước', 41 | s : 'vài giây', 42 | m : 'một phút', 43 | mm : '%d phút', 44 | h : 'một giờ', 45 | hh : '%d giờ', 46 | d : 'một ngày', 47 | dd : '%d ngày', 48 | M : 'một tháng', 49 | MM : '%d tháng', 50 | y : 'một năm', 51 | yy : '%d năm' 52 | }, 53 | ordinalParse: /\d{1,2}/, 54 | ordinal : function (number) { 55 | return number; 56 | }, 57 | week : { 58 | dow : 1, // Monday is the first day of the week. 59 | doy : 4 // The week that contains Jan 4th is the first week of the year. 60 | } 61 | }); 62 | 63 | return vi; 64 | 65 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/sv.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : swedish (sv) 3 | //! author : Jens Alm : https://github.com/ulmus 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var sv = moment.defineLocale('sv', { 13 | months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'), 14 | monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'), 15 | weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'), 16 | weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'), 17 | weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'YYYY-MM-DD', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd D MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[Idag] LT', 28 | nextDay: '[Imorgon] LT', 29 | lastDay: '[Igår] LT', 30 | nextWeek: '[På] dddd LT', 31 | lastWeek: '[I] dddd[s] LT', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : 'om %s', 36 | past : 'för %s sedan', 37 | s : 'några sekunder', 38 | m : 'en minut', 39 | mm : '%d minuter', 40 | h : 'en timme', 41 | hh : '%d timmar', 42 | d : 'en dag', 43 | dd : '%d dagar', 44 | M : 'en månad', 45 | MM : '%d månader', 46 | y : 'ett år', 47 | yy : '%d år' 48 | }, 49 | ordinalParse: /\d{1,2}(e|a)/, 50 | ordinal : function (number) { 51 | var b = number % 10, 52 | output = (~~(number % 100 / 10) === 1) ? 'e' : 53 | (b === 1) ? 'a' : 54 | (b === 2) ? 'a' : 55 | (b === 3) ? 'e' : 'e'; 56 | return number + output; 57 | }, 58 | week : { 59 | dow : 1, // Monday is the first day of the week. 60 | doy : 4 // The week that contains Jan 4th is the first week of the year. 61 | } 62 | }); 63 | 64 | return sv; 65 | 66 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/cv.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : chuvash (cv) 3 | //! author : Anatoly Mironov : https://github.com/mirontoli 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var cv = moment.defineLocale('cv', { 13 | months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), 14 | monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), 15 | weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), 16 | weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), 17 | weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD-MM-YYYY', 22 | LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]', 23 | LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm', 24 | LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm' 25 | }, 26 | calendar : { 27 | sameDay: '[Паян] LT [сехетре]', 28 | nextDay: '[Ыран] LT [сехетре]', 29 | lastDay: '[Ӗнер] LT [сехетре]', 30 | nextWeek: '[Ҫитес] dddd LT [сехетре]', 31 | lastWeek: '[Иртнӗ] dddd LT [сехетре]', 32 | sameElse: 'L' 33 | }, 34 | relativeTime : { 35 | future : function (output) { 36 | var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран'; 37 | return output + affix; 38 | }, 39 | past : '%s каялла', 40 | s : 'пӗр-ик ҫеккунт', 41 | m : 'пӗр минут', 42 | mm : '%d минут', 43 | h : 'пӗр сехет', 44 | hh : '%d сехет', 45 | d : 'пӗр кун', 46 | dd : '%d кун', 47 | M : 'пӗр уйӑх', 48 | MM : '%d уйӑх', 49 | y : 'пӗр ҫул', 50 | yy : '%d ҫул' 51 | }, 52 | ordinalParse: /\d{1,2}-мӗш/, 53 | ordinal : '%d-мӗш', 54 | week : { 55 | dow : 1, // Monday is the first day of the week. 56 | doy : 7 // The week that contains Jan 1st is the first week of the year. 57 | } 58 | }); 59 | 60 | return cv; 61 | 62 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/eu.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : euskara (eu) 3 | //! author : Eneko Illarramendi : https://github.com/eillarra 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var eu = moment.defineLocale('eu', { 13 | months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'), 14 | monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'), 15 | weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'), 16 | weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'), 17 | weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'YYYY-MM-DD', 22 | LL : 'YYYY[ko] MMMM[ren] D[a]', 23 | LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm', 24 | LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm', 25 | l : 'YYYY-M-D', 26 | ll : 'YYYY[ko] MMM D[a]', 27 | lll : 'YYYY[ko] MMM D[a] HH:mm', 28 | llll : 'ddd, YYYY[ko] MMM D[a] HH:mm' 29 | }, 30 | calendar : { 31 | sameDay : '[gaur] LT[etan]', 32 | nextDay : '[bihar] LT[etan]', 33 | nextWeek : 'dddd LT[etan]', 34 | lastDay : '[atzo] LT[etan]', 35 | lastWeek : '[aurreko] dddd LT[etan]', 36 | sameElse : 'L' 37 | }, 38 | relativeTime : { 39 | future : '%s barru', 40 | past : 'duela %s', 41 | s : 'segundo batzuk', 42 | m : 'minutu bat', 43 | mm : '%d minutu', 44 | h : 'ordu bat', 45 | hh : '%d ordu', 46 | d : 'egun bat', 47 | dd : '%d egun', 48 | M : 'hilabete bat', 49 | MM : '%d hilabete', 50 | y : 'urte bat', 51 | yy : '%d urte' 52 | }, 53 | ordinalParse: /\d{1,2}\./, 54 | ordinal : '%d.', 55 | week : { 56 | dow : 1, // Monday is the first day of the week. 57 | doy : 7 // The week that contains Jan 1st is the first week of the year. 58 | } 59 | }); 60 | 61 | return eu; 62 | 63 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/en-au.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : australian english (en-au) 3 | 4 | (function (global, factory) { 5 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 6 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 7 | factory(global.moment) 8 | }(this, function (moment) { 'use strict'; 9 | 10 | 11 | var en_au = moment.defineLocale('en-au', { 12 | months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), 13 | monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), 14 | weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), 15 | weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), 16 | weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), 17 | longDateFormat : { 18 | LT : 'h:mm A', 19 | LTS : 'h:mm:ss A', 20 | L : 'DD/MM/YYYY', 21 | LL : 'D MMMM YYYY', 22 | LLL : 'D MMMM YYYY h:mm A', 23 | LLLL : 'dddd, D MMMM YYYY h:mm A' 24 | }, 25 | calendar : { 26 | sameDay : '[Today at] LT', 27 | nextDay : '[Tomorrow at] LT', 28 | nextWeek : 'dddd [at] LT', 29 | lastDay : '[Yesterday at] LT', 30 | lastWeek : '[Last] dddd [at] LT', 31 | sameElse : 'L' 32 | }, 33 | relativeTime : { 34 | future : 'in %s', 35 | past : '%s ago', 36 | s : 'a few seconds', 37 | m : 'a minute', 38 | mm : '%d minutes', 39 | h : 'an hour', 40 | hh : '%d hours', 41 | d : 'a day', 42 | dd : '%d days', 43 | M : 'a month', 44 | MM : '%d months', 45 | y : 'a year', 46 | yy : '%d years' 47 | }, 48 | ordinalParse: /\d{1,2}(st|nd|rd|th)/, 49 | ordinal : function (number) { 50 | var b = number % 10, 51 | output = (~~(number % 100 / 10) === 1) ? 'th' : 52 | (b === 1) ? 'st' : 53 | (b === 2) ? 'nd' : 54 | (b === 3) ? 'rd' : 'th'; 55 | return number + output; 56 | }, 57 | week : { 58 | dow : 1, // Monday is the first day of the week. 59 | doy : 4 // The week that contains Jan 4th is the first week of the year. 60 | } 61 | }); 62 | 63 | return en_au; 64 | 65 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/th.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : thai (th) 3 | //! author : Kridsada Thanabulpong : https://github.com/sirn 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var th = moment.defineLocale('th', { 13 | months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), 14 | monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'), 15 | weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), 16 | weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference 17 | weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), 18 | longDateFormat : { 19 | LT : 'H นาฬิกา m นาที', 20 | LTS : 'H นาฬิกา m นาที s วินาที', 21 | L : 'YYYY/MM/DD', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY เวลา H นาฬิกา m นาที', 24 | LLLL : 'วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที' 25 | }, 26 | meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, 27 | isPM: function (input) { 28 | return input === 'หลังเที่ยง'; 29 | }, 30 | meridiem : function (hour, minute, isLower) { 31 | if (hour < 12) { 32 | return 'ก่อนเที่ยง'; 33 | } else { 34 | return 'หลังเที่ยง'; 35 | } 36 | }, 37 | calendar : { 38 | sameDay : '[วันนี้ เวลา] LT', 39 | nextDay : '[พรุ่งนี้ เวลา] LT', 40 | nextWeek : 'dddd[หน้า เวลา] LT', 41 | lastDay : '[เมื่อวานนี้ เวลา] LT', 42 | lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT', 43 | sameElse : 'L' 44 | }, 45 | relativeTime : { 46 | future : 'อีก %s', 47 | past : '%sที่แล้ว', 48 | s : 'ไม่กี่วินาที', 49 | m : '1 นาที', 50 | mm : '%d นาที', 51 | h : '1 ชั่วโมง', 52 | hh : '%d ชั่วโมง', 53 | d : '1 วัน', 54 | dd : '%d วัน', 55 | M : '1 เดือน', 56 | MM : '%d เดือน', 57 | y : '1 ปี', 58 | yy : '%d ปี' 59 | } 60 | }); 61 | 62 | return th; 63 | 64 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/en-gb.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : great britain english (en-gb) 3 | //! author : Chris Gedrim : https://github.com/chrisgedrim 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var en_gb = moment.defineLocale('en-gb', { 13 | months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'), 14 | monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'), 15 | weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'), 16 | weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'), 17 | weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH:mm', 20 | LTS : 'HH:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY HH:mm', 24 | LLLL : 'dddd, D MMMM YYYY HH:mm' 25 | }, 26 | calendar : { 27 | sameDay : '[Today at] LT', 28 | nextDay : '[Tomorrow at] LT', 29 | nextWeek : 'dddd [at] LT', 30 | lastDay : '[Yesterday at] LT', 31 | lastWeek : '[Last] dddd [at] LT', 32 | sameElse : 'L' 33 | }, 34 | relativeTime : { 35 | future : 'in %s', 36 | past : '%s ago', 37 | s : 'a few seconds', 38 | m : 'a minute', 39 | mm : '%d minutes', 40 | h : 'an hour', 41 | hh : '%d hours', 42 | d : 'a day', 43 | dd : '%d days', 44 | M : 'a month', 45 | MM : '%d months', 46 | y : 'a year', 47 | yy : '%d years' 48 | }, 49 | ordinalParse: /\d{1,2}(st|nd|rd|th)/, 50 | ordinal : function (number) { 51 | var b = number % 10, 52 | output = (~~(number % 100 / 10) === 1) ? 'th' : 53 | (b === 1) ? 'st' : 54 | (b === 2) ? 'nd' : 55 | (b === 3) ? 'rd' : 'th'; 56 | return number + output; 57 | }, 58 | week : { 59 | dow : 1, // Monday is the first day of the week. 60 | doy : 4 // The week that contains Jan 4th is the first week of the year. 61 | } 62 | }); 63 | 64 | return en_gb; 65 | 66 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/sq.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Albanian (sq) 3 | //! author : Flakërim Ismani : https://github.com/flakerimi 4 | //! author: Menelion Elensúle: https://github.com/Oire (tests) 5 | //! author : Oerd Cukalla : https://github.com/oerd (fixes) 6 | 7 | (function (global, factory) { 8 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 9 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 10 | factory(global.moment) 11 | }(this, function (moment) { 'use strict'; 12 | 13 | 14 | var sq = moment.defineLocale('sq', { 15 | months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'), 16 | monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'), 17 | weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'), 18 | weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'), 19 | weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'), 20 | meridiemParse: /PD|MD/, 21 | isPM: function (input) { 22 | return input.charAt(0) === 'M'; 23 | }, 24 | meridiem : function (hours, minutes, isLower) { 25 | return hours < 12 ? 'PD' : 'MD'; 26 | }, 27 | longDateFormat : { 28 | LT : 'HH:mm', 29 | LTS : 'HH:mm:ss', 30 | L : 'DD/MM/YYYY', 31 | LL : 'D MMMM YYYY', 32 | LLL : 'D MMMM YYYY HH:mm', 33 | LLLL : 'dddd, D MMMM YYYY HH:mm' 34 | }, 35 | calendar : { 36 | sameDay : '[Sot në] LT', 37 | nextDay : '[Nesër në] LT', 38 | nextWeek : 'dddd [në] LT', 39 | lastDay : '[Dje në] LT', 40 | lastWeek : 'dddd [e kaluar në] LT', 41 | sameElse : 'L' 42 | }, 43 | relativeTime : { 44 | future : 'në %s', 45 | past : '%s më parë', 46 | s : 'disa sekonda', 47 | m : 'një minutë', 48 | mm : '%d minuta', 49 | h : 'një orë', 50 | hh : '%d orë', 51 | d : 'një ditë', 52 | dd : '%d ditë', 53 | M : 'një muaj', 54 | MM : '%d muaj', 55 | y : 'një vit', 56 | yy : '%d vite' 57 | }, 58 | ordinalParse: /\d{1,2}\./, 59 | ordinal : '%d.', 60 | week : { 61 | dow : 1, // Monday is the first day of the week. 62 | doy : 4 // The week that contains Jan 4th is the first week of the year. 63 | } 64 | }); 65 | 66 | return sq; 67 | 68 | })); -------------------------------------------------------------------------------- /services/qq.oauth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const https = require('https'); 4 | const querystring = require('querystring'); 5 | const Util = require('../util'); 6 | const OAuth2 = require('./oauth2'); 7 | 8 | class QQOAuth2 extends OAuth2 { 9 | 10 | /** 11 | * [constructor description] 12 | * @method constructor 13 | * @param {[type]} appId [description] 14 | * @param {[type]} appKey [description] 15 | * @param {[type]} redirectUrl [description] 16 | * @return {[type]} [description] 17 | */ 18 | constructor(appId, appKey, redirectUrl) { 19 | 20 | super(appId, appKey, redirectUrl); 21 | 22 | this._config = { 23 | HOST_NAME: 'graph.qq.com', 24 | PATH_ACCESS_TOKEN: '/oauth2.0/token?', 25 | PATH_OPEN_ID: '/oauth2.0/me?', 26 | PATH_GET_USER_INFO: '/user/get_user_info?', 27 | OAUTH_URI: 'https://graph.qq.com/oauth2.0/authorize?' 28 | }; 29 | 30 | this._requestOptions.hostname = this._config.HOST_NAME; 31 | 32 | this._state = Util.createHash('qq_oauth_angular2_club'); 33 | } 34 | 35 | /** 36 | * @description get user's openId by access token 37 | * @param token {String} access token 38 | */ 39 | getOpenId(token) { 40 | let params = { 41 | access_token: token 42 | }; 43 | 44 | let options = Object.assign({ 45 | path: this._config.PATH_OPEN_ID + querystring.stringify(params) 46 | }, this._requestOptions); 47 | 48 | return new Promise((resolve, reject) => { 49 | https 50 | .request(options, resp => { 51 | this._handleResponse(resp, resolve, reject); 52 | }) 53 | .on('error', function(err) { 54 | reject(err); 55 | }) 56 | .end(); 57 | }); 58 | } 59 | /** 60 | * @description get user's info by access token and openId 61 | * @param token {String} access token 62 | * @param openId {String} openId 63 | */ 64 | getUserInfo(token, openId) { 65 | let params = { 66 | access_token: token, 67 | openid: openId, 68 | oauth_consumer_key: this._appId 69 | }; 70 | 71 | let options = Object.assign({ 72 | path: this._config.PATH_GET_USER_INFO + querystring.stringify( 73 | params) 74 | }, this._requestOptions); 75 | 76 | return new Promise((resolve, reject) => { 77 | https 78 | .request(options, resp => { 79 | this._handleResponse(resp, resolve, reject); 80 | }) 81 | .on('error', function(err) { 82 | reject(err); 83 | }) 84 | .end(); 85 | }); 86 | } 87 | } 88 | 89 | module.exports = QQOAuth2; 90 | -------------------------------------------------------------------------------- /static/lib/moment/locale/it.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : italian (it) 3 | //! author : Lorenzo : https://github.com/aliem 4 | //! author: Mattia Larentis: https://github.com/nostalgiaz 5 | 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 8 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 9 | factory(global.moment) 10 | }(this, function (moment) { 'use strict'; 11 | 12 | 13 | var it = moment.defineLocale('it', { 14 | months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'), 15 | monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'), 16 | weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'), 17 | weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'), 18 | weekdaysMin : 'D_L_Ma_Me_G_V_S'.split('_'), 19 | longDateFormat : { 20 | LT : 'HH:mm', 21 | LTS : 'HH:mm:ss', 22 | L : 'DD/MM/YYYY', 23 | LL : 'D MMMM YYYY', 24 | LLL : 'D MMMM YYYY HH:mm', 25 | LLLL : 'dddd, D MMMM YYYY HH:mm' 26 | }, 27 | calendar : { 28 | sameDay: '[Oggi alle] LT', 29 | nextDay: '[Domani alle] LT', 30 | nextWeek: 'dddd [alle] LT', 31 | lastDay: '[Ieri alle] LT', 32 | lastWeek: function () { 33 | switch (this.day()) { 34 | case 0: 35 | return '[la scorsa] dddd [alle] LT'; 36 | default: 37 | return '[lo scorso] dddd [alle] LT'; 38 | } 39 | }, 40 | sameElse: 'L' 41 | }, 42 | relativeTime : { 43 | future : function (s) { 44 | return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; 45 | }, 46 | past : '%s fa', 47 | s : 'alcuni secondi', 48 | m : 'un minuto', 49 | mm : '%d minuti', 50 | h : 'un\'ora', 51 | hh : '%d ore', 52 | d : 'un giorno', 53 | dd : '%d giorni', 54 | M : 'un mese', 55 | MM : '%d mesi', 56 | y : 'un anno', 57 | yy : '%d anni' 58 | }, 59 | ordinalParse : /\d{1,2}º/, 60 | ordinal: '%dº', 61 | week : { 62 | dow : 1, // Monday is the first day of the week. 63 | doy : 4 // The week that contains Jan 4th is the first week of the year. 64 | } 65 | }); 66 | 67 | return it; 68 | 69 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/ml.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : malayalam (ml) 3 | //! author : Floyd Pink : https://github.com/floydpink 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var ml = moment.defineLocale('ml', { 13 | months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), 14 | monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), 15 | weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), 16 | weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), 17 | weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), 18 | longDateFormat : { 19 | LT : 'A h:mm -നു', 20 | LTS : 'A h:mm:ss -നു', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY, A h:mm -നു', 24 | LLLL : 'dddd, D MMMM YYYY, A h:mm -നു' 25 | }, 26 | calendar : { 27 | sameDay : '[ഇന്ന്] LT', 28 | nextDay : '[നാളെ] LT', 29 | nextWeek : 'dddd, LT', 30 | lastDay : '[ഇന്നലെ] LT', 31 | lastWeek : '[കഴിഞ്ഞ] dddd, LT', 32 | sameElse : 'L' 33 | }, 34 | relativeTime : { 35 | future : '%s കഴിഞ്ഞ്', 36 | past : '%s മുൻപ്', 37 | s : 'അൽപ നിമിഷങ്ങൾ', 38 | m : 'ഒരു മിനിറ്റ്', 39 | mm : '%d മിനിറ്റ്', 40 | h : 'ഒരു മണിക്കൂർ', 41 | hh : '%d മണിക്കൂർ', 42 | d : 'ഒരു ദിവസം', 43 | dd : '%d ദിവസം', 44 | M : 'ഒരു മാസം', 45 | MM : '%d മാസം', 46 | y : 'ഒരു വർഷം', 47 | yy : '%d വർഷം' 48 | }, 49 | meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, 50 | isPM : function (input) { 51 | return /^(ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി)$/.test(input); 52 | }, 53 | meridiem : function (hour, minute, isLower) { 54 | if (hour < 4) { 55 | return 'രാത്രി'; 56 | } else if (hour < 12) { 57 | return 'രാവിലെ'; 58 | } else if (hour < 17) { 59 | return 'ഉച്ച കഴിഞ്ഞ്'; 60 | } else if (hour < 20) { 61 | return 'വൈകുന്നേരം'; 62 | } else { 63 | return 'രാത്രി'; 64 | } 65 | } 66 | }); 67 | 68 | return ml; 69 | 70 | })); -------------------------------------------------------------------------------- /static/lib/angular/angular-messages.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.4.7 3 | (c) 2010-2015 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(z,h,A){'use strict';function m(h){return["$animate",function(r){return{restrict:"AE",transclude:"element",terminal:!0,require:"^^ngMessages",link:function(n,f,a,g,l){var c=f[0],p,h=a.ngMessage||a.when;a=a.ngMessageExp||a.whenExp;var k=function(b){p=b?v(b)?b:b.split(/[\s,]+/):null;g.reRender()};a?(k(n.$eval(a)),n.$watchCollection(a,k)):k(h);var e,q;g.register(c,q={test:function(b){var a=p;b=a?v(a)?0<=a.indexOf(b):a.hasOwnProperty(b):void 0;return b},attach:function(){e||l(n,function(b){r.enter(b, 7 | null,f);e=b;var a=e.$$attachId=g.getAttachId();e.on("$destroy",function(){e&&e.$$attachId===a&&(g.deregister(c),q.detach())})})},detach:function(){if(e){var b=e;e=null;r.leave(b)}}})}}}]}var v=h.isArray,w=h.forEach,x=h.isString,y=h.element;h.module("ngMessages",[]).directive("ngMessages",["$animate",function(h){function r(f,a){return x(a)&&0===a.length||n(f.$eval(a))}function n(f){return x(f)?f.length:!!f}return{require:"ngMessages",restrict:"AE",controller:["$element","$scope","$attrs",function(f, 8 | a,g){function l(b,a){for(var d=a,f=[];d&&d!==b;){var c=d.$$ngMessageNode;if(c&&c.length)return k[c];d.childNodes.length&&-1==f.indexOf(d)?(f.push(d),d=d.childNodes[d.childNodes.length-1]):d=d.previousSibling||d.parentNode}}var c=this,p=0,m=0;this.getAttachId=function(){return m++};var k=this.messages={},e,q;this.render=function(b){b=b||{};e=!1;q=b;for(var p=r(a,g.ngMessagesMultiple)||r(a,g.multiple),d=[],k={},s=c.head,l=!1,m=0;null!=s;){m++;var t=s.message,u=!1;l||w(b,function(a,b){!u&&n(a)&&t.test(b)&& 9 | !k[b]&&(u=k[b]=!0,t.attach())});u?l=!p:d.push(t);s=s.next}w(d,function(b){b.detach()});d.length!==m?h.setClass(f,"ng-active","ng-inactive"):h.setClass(f,"ng-inactive","ng-active")};a.$watchCollection(g.ngMessages||g["for"],c.render);this.reRender=function(){e||(e=!0,a.$evalAsync(function(){e&&q&&c.render(q)}))};this.register=function(b,a){var d=p.toString();k[d]={message:a};var e=f[0],g=k[d];c.head?(e=l(e,b))?(g.next=e.next,e.next=g):(g.next=c.head,c.head=g):c.head=g;b.$$ngMessageNode=d;p++;c.reRender()}; 10 | this.deregister=function(b){var a=b.$$ngMessageNode;delete b.$$ngMessageNode;var d=k[a];(b=l(f[0],b))?b.next=d.next:c.head=d.next;delete k[a];c.reRender()}}]}}]).directive("ngMessagesInclude",["$templateRequest","$document","$compile",function(h,m,n){return{restrict:"AE",require:"^^ngMessages",link:function(f,a,g){var l=g.ngMessagesInclude||g.src;h(l).then(function(c){n(c)(f,function(c){a.after(c);c=y(m[0].createComment(" ngMessagesInclude: "+l+" "));a.after(c);a.remove()})})}}}]).directive("ngMessage", 11 | m("AE")).directive("ngMessageExp",m("A"))})(window,window.angular); 12 | //# sourceMappingURL=angular-messages.min.js.map 13 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | //require('tingyun'); 3 | const log4js = require('log4js'); 4 | global.logger = log4js.getLogger(); 5 | global.noop = function() {}; 6 | 7 | const express = require('express'); 8 | const bodyParser = require('body-parser'); 9 | const cookieParser = require('cookie-parser'); 10 | const session = require('express-session'); 11 | const expressValidator = require('express-validator'); 12 | const MongoStore = require('connect-mongo')(session); 13 | const mongoose = require('mongoose'); 14 | const path = require('path'); 15 | const config = require('./config'); 16 | const routes = require('./routes'); 17 | const morgan = require('morgan'); 18 | const favicon = require('serve-favicon'); 19 | const middleware = require('./middlewares'); 20 | 21 | const server = express(); 22 | 23 | server.set('view engine', config.VIEW_ENGINE); 24 | 25 | server.use(bodyParser.json()); 26 | server.use(bodyParser.urlencoded({ 27 | extended: false 28 | })); 29 | 30 | server.use(expressValidator()); 31 | 32 | server.use(express.static(path.join(__dirname, 'static'))); 33 | 34 | server.use(cookieParser()); 35 | 36 | server.use(favicon(__dirname + '/static/images/favicon.ico')); 37 | 38 | server.use(session({ 39 | secret: config.SESSION_SECRET, 40 | resave: false, 41 | saveUninitialized: true, 42 | cookie: { 43 | maxAge: config.COOKIE_MAX_AGE 44 | }, 45 | store: new MongoStore({ 46 | mongooseConnection: mongoose.connection 47 | }) 48 | })); 49 | 50 | /*server.use(middleware.handleError); 51 | 52 | server.use(middleware.handleSession);*/ 53 | 54 | server.use(function(req, res, next) { 55 | res.xhr = req.xhr; 56 | logger.debug(`request type is XMLHttpRequest:${res.xhr}`); 57 | next(); 58 | }); 59 | 60 | routes(server); 61 | 62 | server.use(morgan('dev')); 63 | 64 | // catch 404 and forward to error handler 65 | server.use(function(req, res, next) { 66 | var err = new Error('Page Not Found'); 67 | err.status = 404; 68 | next(err); 69 | }); 70 | 71 | // 错误处理 72 | // 开发环镜 73 | if (server.get('env') === 'development') { 74 | server.use(function(err, req, res, next) { 75 | res.status(err.status || 500); 76 | res.render('error', { 77 | title: err.message, 78 | message: err.message, 79 | error: err 80 | }); 81 | }); 82 | 83 | } 84 | 85 | // 生产环境错误处理 86 | server.use(function(err, req, res, next) { 87 | res.status(err.status || 500); 88 | res.render('error', { 89 | message: err.message, 90 | error: {} 91 | }); 92 | }); 93 | 94 | server.locals.config = config; 95 | 96 | server.listen(config.PORT, function() { 97 | logger.info('server start success at port:' + config.PORT); 98 | }); 99 | 100 | module.exports = server; 101 | -------------------------------------------------------------------------------- /static/lib/moment/locale/nl.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : dutch (nl) 3 | //! author : Joris Röling : https://github.com/jjupiter 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), 13 | monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); 14 | 15 | var nl = moment.defineLocale('nl', { 16 | months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), 17 | monthsShort : function (m, format) { 18 | if (/-MMM-/.test(format)) { 19 | return monthsShortWithoutDots[m.month()]; 20 | } else { 21 | return monthsShortWithDots[m.month()]; 22 | } 23 | }, 24 | weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'), 25 | weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'), 26 | weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'), 27 | longDateFormat : { 28 | LT : 'HH:mm', 29 | LTS : 'HH:mm:ss', 30 | L : 'DD-MM-YYYY', 31 | LL : 'D MMMM YYYY', 32 | LLL : 'D MMMM YYYY HH:mm', 33 | LLLL : 'dddd D MMMM YYYY HH:mm' 34 | }, 35 | calendar : { 36 | sameDay: '[vandaag om] LT', 37 | nextDay: '[morgen om] LT', 38 | nextWeek: 'dddd [om] LT', 39 | lastDay: '[gisteren om] LT', 40 | lastWeek: '[afgelopen] dddd [om] LT', 41 | sameElse: 'L' 42 | }, 43 | relativeTime : { 44 | future : 'over %s', 45 | past : '%s geleden', 46 | s : 'een paar seconden', 47 | m : 'één minuut', 48 | mm : '%d minuten', 49 | h : 'één uur', 50 | hh : '%d uur', 51 | d : 'één dag', 52 | dd : '%d dagen', 53 | M : 'één maand', 54 | MM : '%d maanden', 55 | y : 'één jaar', 56 | yy : '%d jaar' 57 | }, 58 | ordinalParse: /\d{1,2}(ste|de)/, 59 | ordinal : function (number) { 60 | return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); 61 | }, 62 | week : { 63 | dow : 1, // Monday is the first day of the week. 64 | doy : 4 // The week that contains Jan 4th is the first week of the year. 65 | } 66 | }); 67 | 68 | return nl; 69 | 70 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/fy.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : frisian (fy) 3 | //! author : Robin van der Vliet : https://github.com/robin0van0der0v 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), 13 | monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); 14 | 15 | var fy = moment.defineLocale('fy', { 16 | months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), 17 | monthsShort : function (m, format) { 18 | if (/-MMM-/.test(format)) { 19 | return monthsShortWithoutDots[m.month()]; 20 | } else { 21 | return monthsShortWithDots[m.month()]; 22 | } 23 | }, 24 | weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), 25 | weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), 26 | weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), 27 | longDateFormat : { 28 | LT : 'HH:mm', 29 | LTS : 'HH:mm:ss', 30 | L : 'DD-MM-YYYY', 31 | LL : 'D MMMM YYYY', 32 | LLL : 'D MMMM YYYY HH:mm', 33 | LLLL : 'dddd D MMMM YYYY HH:mm' 34 | }, 35 | calendar : { 36 | sameDay: '[hjoed om] LT', 37 | nextDay: '[moarn om] LT', 38 | nextWeek: 'dddd [om] LT', 39 | lastDay: '[juster om] LT', 40 | lastWeek: '[ôfrûne] dddd [om] LT', 41 | sameElse: 'L' 42 | }, 43 | relativeTime : { 44 | future : 'oer %s', 45 | past : '%s lyn', 46 | s : 'in pear sekonden', 47 | m : 'ien minút', 48 | mm : '%d minuten', 49 | h : 'ien oere', 50 | hh : '%d oeren', 51 | d : 'ien dei', 52 | dd : '%d dagen', 53 | M : 'ien moanne', 54 | MM : '%d moannen', 55 | y : 'ien jier', 56 | yy : '%d jierren' 57 | }, 58 | ordinalParse: /\d{1,2}(ste|de)/, 59 | ordinal : function (number) { 60 | return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); 61 | }, 62 | week : { 63 | dow : 1, // Monday is the first day of the week. 64 | doy : 4 // The week that contains Jan 4th is the first week of the year. 65 | } 66 | }); 67 | 68 | return fy; 69 | 70 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/ro.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : romanian (ro) 3 | //! author : Vlad Gurdiga : https://github.com/gurdiga 4 | //! author : Valentin Agachi : https://github.com/avaly 5 | 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 8 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 9 | factory(global.moment) 10 | }(this, function (moment) { 'use strict'; 11 | 12 | 13 | function relativeTimeWithPlural(number, withoutSuffix, key) { 14 | var format = { 15 | 'mm': 'minute', 16 | 'hh': 'ore', 17 | 'dd': 'zile', 18 | 'MM': 'luni', 19 | 'yy': 'ani' 20 | }, 21 | separator = ' '; 22 | if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { 23 | separator = ' de '; 24 | } 25 | return number + separator + format[key]; 26 | } 27 | 28 | var ro = moment.defineLocale('ro', { 29 | months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), 30 | monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'), 31 | weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'), 32 | weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'), 33 | weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'), 34 | longDateFormat : { 35 | LT : 'H:mm', 36 | LTS : 'H:mm:ss', 37 | L : 'DD.MM.YYYY', 38 | LL : 'D MMMM YYYY', 39 | LLL : 'D MMMM YYYY H:mm', 40 | LLLL : 'dddd, D MMMM YYYY H:mm' 41 | }, 42 | calendar : { 43 | sameDay: '[azi la] LT', 44 | nextDay: '[mâine la] LT', 45 | nextWeek: 'dddd [la] LT', 46 | lastDay: '[ieri la] LT', 47 | lastWeek: '[fosta] dddd [la] LT', 48 | sameElse: 'L' 49 | }, 50 | relativeTime : { 51 | future : 'peste %s', 52 | past : '%s în urmă', 53 | s : 'câteva secunde', 54 | m : 'un minut', 55 | mm : relativeTimeWithPlural, 56 | h : 'o oră', 57 | hh : relativeTimeWithPlural, 58 | d : 'o zi', 59 | dd : relativeTimeWithPlural, 60 | M : 'o lună', 61 | MM : relativeTimeWithPlural, 62 | y : 'un an', 63 | yy : relativeTimeWithPlural 64 | }, 65 | week : { 66 | dow : 1, // Monday is the first day of the week. 67 | doy : 7 // The week that contains Jan 1st is the first week of the year. 68 | } 69 | }); 70 | 71 | return ro; 72 | 73 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/af.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : afrikaans (af) 3 | //! author : Werner Mollentze : https://github.com/wernerm 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var af = moment.defineLocale('af', { 13 | months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), 14 | monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), 15 | weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), 16 | weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), 17 | weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), 18 | meridiemParse: /vm|nm/i, 19 | isPM : function (input) { 20 | return /^nm$/i.test(input); 21 | }, 22 | meridiem : function (hours, minutes, isLower) { 23 | if (hours < 12) { 24 | return isLower ? 'vm' : 'VM'; 25 | } else { 26 | return isLower ? 'nm' : 'NM'; 27 | } 28 | }, 29 | longDateFormat : { 30 | LT : 'HH:mm', 31 | LTS : 'HH:mm:ss', 32 | L : 'DD/MM/YYYY', 33 | LL : 'D MMMM YYYY', 34 | LLL : 'D MMMM YYYY HH:mm', 35 | LLLL : 'dddd, D MMMM YYYY HH:mm' 36 | }, 37 | calendar : { 38 | sameDay : '[Vandag om] LT', 39 | nextDay : '[Môre om] LT', 40 | nextWeek : 'dddd [om] LT', 41 | lastDay : '[Gister om] LT', 42 | lastWeek : '[Laas] dddd [om] LT', 43 | sameElse : 'L' 44 | }, 45 | relativeTime : { 46 | future : 'oor %s', 47 | past : '%s gelede', 48 | s : '\'n paar sekondes', 49 | m : '\'n minuut', 50 | mm : '%d minute', 51 | h : '\'n uur', 52 | hh : '%d ure', 53 | d : '\'n dag', 54 | dd : '%d dae', 55 | M : '\'n maand', 56 | MM : '%d maande', 57 | y : '\'n jaar', 58 | yy : '%d jaar' 59 | }, 60 | ordinalParse: /\d{1,2}(ste|de)/, 61 | ordinal : function (number) { 62 | return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter 63 | }, 64 | week : { 65 | dow : 1, // Maandag is die eerste dag van die week. 66 | doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. 67 | } 68 | }); 69 | 70 | return af; 71 | 72 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/eo.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : esperanto (eo) 3 | //! author : Colin Dean : https://github.com/colindean 4 | //! komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko. 5 | //! Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni! 6 | 7 | (function (global, factory) { 8 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 9 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 10 | factory(global.moment) 11 | }(this, function (moment) { 'use strict'; 12 | 13 | 14 | var eo = moment.defineLocale('eo', { 15 | months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'), 16 | monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'), 17 | weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'), 18 | weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'), 19 | weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'), 20 | longDateFormat : { 21 | LT : 'HH:mm', 22 | LTS : 'HH:mm:ss', 23 | L : 'YYYY-MM-DD', 24 | LL : 'D[-an de] MMMM, YYYY', 25 | LLL : 'D[-an de] MMMM, YYYY HH:mm', 26 | LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm' 27 | }, 28 | meridiemParse: /[ap]\.t\.m/i, 29 | isPM: function (input) { 30 | return input.charAt(0).toLowerCase() === 'p'; 31 | }, 32 | meridiem : function (hours, minutes, isLower) { 33 | if (hours > 11) { 34 | return isLower ? 'p.t.m.' : 'P.T.M.'; 35 | } else { 36 | return isLower ? 'a.t.m.' : 'A.T.M.'; 37 | } 38 | }, 39 | calendar : { 40 | sameDay : '[Hodiaŭ je] LT', 41 | nextDay : '[Morgaŭ je] LT', 42 | nextWeek : 'dddd [je] LT', 43 | lastDay : '[Hieraŭ je] LT', 44 | lastWeek : '[pasinta] dddd [je] LT', 45 | sameElse : 'L' 46 | }, 47 | relativeTime : { 48 | future : 'je %s', 49 | past : 'antaŭ %s', 50 | s : 'sekundoj', 51 | m : 'minuto', 52 | mm : '%d minutoj', 53 | h : 'horo', 54 | hh : '%d horoj', 55 | d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo 56 | dd : '%d tagoj', 57 | M : 'monato', 58 | MM : '%d monatoj', 59 | y : 'jaro', 60 | yy : '%d jaroj' 61 | }, 62 | ordinalParse: /\d{1,2}a/, 63 | ordinal : '%da', 64 | week : { 65 | dow : 1, // Monday is the first day of the week. 66 | doy : 7 // The week that contains Jan 1st is the first week of the year. 67 | } 68 | }); 69 | 70 | return eo; 71 | 72 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/gl.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : galician (gl) 3 | //! author : Juan G. Hurtado : https://github.com/juanghurtado 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var gl = moment.defineLocale('gl', { 13 | months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'), 14 | monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'), 15 | weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'), 16 | weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'), 17 | weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'), 18 | longDateFormat : { 19 | LT : 'H:mm', 20 | LTS : 'H:mm:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY H:mm', 24 | LLLL : 'dddd D MMMM YYYY H:mm' 25 | }, 26 | calendar : { 27 | sameDay : function () { 28 | return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; 29 | }, 30 | nextDay : function () { 31 | return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT'; 32 | }, 33 | nextWeek : function () { 34 | return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; 35 | }, 36 | lastDay : function () { 37 | return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT'; 38 | }, 39 | lastWeek : function () { 40 | return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT'; 41 | }, 42 | sameElse : 'L' 43 | }, 44 | relativeTime : { 45 | future : function (str) { 46 | if (str === 'uns segundos') { 47 | return 'nuns segundos'; 48 | } 49 | return 'en ' + str; 50 | }, 51 | past : 'hai %s', 52 | s : 'uns segundos', 53 | m : 'un minuto', 54 | mm : '%d minutos', 55 | h : 'unha hora', 56 | hh : '%d horas', 57 | d : 'un día', 58 | dd : '%d días', 59 | M : 'un mes', 60 | MM : '%d meses', 61 | y : 'un ano', 62 | yy : '%d anos' 63 | }, 64 | ordinalParse : /\d{1,2}º/, 65 | ordinal : '%dº', 66 | week : { 67 | dow : 1, // Monday is the first day of the week. 68 | doy : 7 // The week that contains Jan 1st is the first week of the year. 69 | } 70 | }); 71 | 72 | return gl; 73 | 74 | })); -------------------------------------------------------------------------------- /static/templates/register-form.html: -------------------------------------------------------------------------------- 1 |
4 | 5 |

6 |
7 | 8 | email 9 | 16 |
17 |
邮箱必填
18 |
邮箱格式不正确
19 |
此邮箱已经注册
20 |
21 |
22 | 23 | 24 | person 25 | 33 |
34 |
昵称必填
35 |
昵称不能少于两个字
36 |
昵称不能多于20个字
37 |
38 | 39 |
40 | 41 | 42 | lock 43 | 51 |
52 |
密码必填
53 |
密码不能少于6个字符
54 |
密码不能多于20个字符
55 |
56 |
57 | 58 | 59 | 62 | 注册 63 | 64 | 65 | 66 | 67 | 68 | 已有帐号?登录 69 | 70 | 71 | 72 | QQ登录 73 | 74 | 75 | 76 | 77 | github登录 78 | 79 | 80 |
81 | -------------------------------------------------------------------------------- /util/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const crypto=require('crypto'); 4 | 5 | class Util{ 6 | 7 | /** 8 | * 生成hash字符 9 | * @param str {String} 10 | */ 11 | static createHash (str){ 12 | crypto.createHash('sha256').update(str).digest('base64').toString(); 13 | } 14 | 15 | /** 16 | * 去除结果里的callback 17 | * @param jsonpStr {String} 18 | * @returns {JSON|string} 19 | */ 20 | static transformJSONPData(jsonpStr){ 21 | jsonpStr=jsonpStr.replace(/^callback\(/,''); 22 | return jsonpStr.replace(');',''); 23 | } 24 | 25 | /** 26 | * 根据用户信息生成session,并保存最后上线时间 27 | * @param req {Object} 28 | * @param user {Object} 29 | * @param [callback] {function} 30 | * @returns {Promise} 31 | */ 32 | static generateSession(req,user,callback){ 33 | callback=callback||noop; 34 | 35 | return new Promise(function(resolve,reject){ 36 | req.session.regenerate(function(){ 37 | req.session.user=user._id; 38 | req.session.account=user.account; 39 | req.session.nickName=user.nickName; 40 | req.session.siteAdmin=user.siteAdmin; 41 | req.session.msg='Authenticated as '+user.nickName; 42 | 43 | user.set('lastOnline',Date.now()); 44 | 45 | user.save(function(err){ 46 | if(err){ 47 | reject(err); 48 | callback(err,undefined); 49 | }else{ 50 | resolve(user); 51 | callback(undefined,user); 52 | } 53 | }); 54 | 55 | }); 56 | }); 57 | } 58 | 59 | /** 60 | * 从model上拾取指定的属性 61 | * @param model {Object} 62 | * @param props {Array} 63 | * @returns {Object} 64 | */ 65 | static pick(model,props){ 66 | let result={}; 67 | 68 | props.forEach(function(prop){ 69 | let value=model[prop]; 70 | if(value){ 71 | result[prop]=value; 72 | } 73 | }); 74 | 75 | return result; 76 | } 77 | 78 | /** 79 | * 处理响应错误 80 | * @param {[Object]} req [description] 81 | * @param {[Object]} res [description] 82 | * @param {[Object]} err [错误信息] 83 | * @return {[undefined]} [description] 84 | */ 85 | static handleError(req,res,err){ 86 | logger.error('catch error',err); 87 | let code=err.code||500; 88 | 89 | res.status(code); 90 | 91 | if(req.xhr){ 92 | res.send(err); 93 | }else{ 94 | res.render('error', { 95 | title:err.msg, 96 | message: err.msg, 97 | error: err 98 | }); 99 | } 100 | } 101 | } 102 | 103 | module.exports=Util; 104 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | const DB_NAME = 'angular2club';//数据库名 6 | const DB_USER = 'angular2club';//数据库用户名 7 | const DB_PWD = 'parox606';//数据库密码 8 | const DB_URL = 'localhost/';//数据库地址 9 | 10 | const config = { 11 | HOST:'test.angular2.club', 12 | PORT:80, 13 | VIEW_ENGINE:'ejs', 14 | DATABASE:`mongodb://${DB_USER}:${DB_PWD}@${DB_URL}${DB_NAME}`, 15 | CDN:'', 16 | SITE_ICON:'', 17 | SITE_LOG:'', 18 | SITE_NAME:'Angular2 Club', 19 | SITE_DESC:'', 20 | SESSION_SECRET:'angular2club', 21 | COOKIE_MAX_AGE:60 * 60 * 1000, 22 | ONEAPM_KEY:'UFYEBAIDBQleb32RFVxFWlRKWx0270AOXx4CAgYFSd920QkLHQQLSgdU68f5UwYfAAoaA1Q=', 23 | TINGYUN_KEY:'6dc7580b1ba0e2533fe16c5541175777', 24 | mail:{ 25 | HOST: 'smtp.163.com', 26 | PORT: 25, 27 | USER:'angular2_club@163.com', 28 | PASS:'pygrhmztmopdyefz' 29 | }, 30 | upload:{ 31 | PATH:path.join('/upload/'), 32 | URL:'/upload/' 33 | }, 34 | oAuth:{ 35 | qq:{ 36 | APP_ID:101268680, 37 | APP_KEY:'0bd1ac2e7948d03f0f75128239d71910', 38 | CALLBACK_URI:'http://test.angular2.club/oauth/qq/callback', 39 | HOST_NAME:'graph.qq.com', 40 | PATH_ACCESS_TOKEN:'/oauth2.0/token?', 41 | PATH_OPEN_ID:'/oauth2.0/me?', 42 | PATH_GET_USER_INFO:'/user/get_user_info?' 43 | }, 44 | weChat:{ 45 | 46 | }, 47 | github:{ 48 | APP_ID:'48796150f263a025b74b', 49 | APP_KEY:'d6744a1216fa4d097842b7c97967a22646794742', 50 | CALLBACK_URI:'http://test.angular2.club/oauth/github/callback', 51 | HOST_NAME:'github.com', 52 | PATH_ACCESS_TOKEN:'/login/oauth/access_token?', 53 | PATH_OPEN_ID:'/oauth2.0/me?', 54 | PATH_GET_USER_INFO:'/user/get_user_info?', 55 | SCOPE:[ 'user' ] 56 | }, 57 | microBlog:{ 58 | APP_ID:4126929706, 59 | APP_KEY:'568324052c2ce439e5b7b7c4126d77e8' 60 | } 61 | }, 62 | //注册用户类型 63 | userType:{ 64 | REG_BY_SELF:1,//自己注册 65 | QQ:2,//qq登录 66 | MICRO_BLOG:3,//微博登录 67 | GITHUB:4,//github登录 68 | WE_CHAT:5//微信登录 69 | }, 70 | //贴子类型 71 | //1,分享,2,问题,3:招聘 72 | topicType:{ 73 | SHARE:1, 74 | QUESTION:2, 75 | RECRUIT:3 76 | }, 77 | //用户加分项目 78 | score:{ 79 | TOPIC:10,//发贴加分 80 | COMMENT:2,//评论加分 81 | GOOD:10,//精华加分 82 | VOTE:1//被赞,无论是topic还是comment被赞,都加分 83 | }, 84 | //消息类型,1:回复您的贴子,2:回复评论,3:@ at您 85 | messageType:{ 86 | REPLY_TOPIC:1, 87 | REPLY_COMMENT:2, 88 | AT:3 89 | }, 90 | genderType:{ 91 | male:1, 92 | femaile:0, 93 | '男':1, 94 | '女':0 95 | } 96 | }; 97 | Object.freeze(config); 98 | 99 | module.exports = config; 100 | -------------------------------------------------------------------------------- /static/lib/moment/locale/he.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Hebrew (he) 3 | //! author : Tomer Cohen : https://github.com/tomer 4 | //! author : Moshe Simantov : https://github.com/DevelopmentIL 5 | //! author : Tal Ater : https://github.com/TalAter 6 | 7 | (function (global, factory) { 8 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 9 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 10 | factory(global.moment) 11 | }(this, function (moment) { 'use strict'; 12 | 13 | 14 | var he = moment.defineLocale('he', { 15 | months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), 16 | monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), 17 | weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), 18 | weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), 19 | weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), 20 | longDateFormat : { 21 | LT : 'HH:mm', 22 | LTS : 'HH:mm:ss', 23 | L : 'DD/MM/YYYY', 24 | LL : 'D [ב]MMMM YYYY', 25 | LLL : 'D [ב]MMMM YYYY HH:mm', 26 | LLLL : 'dddd, D [ב]MMMM YYYY HH:mm', 27 | l : 'D/M/YYYY', 28 | ll : 'D MMM YYYY', 29 | lll : 'D MMM YYYY HH:mm', 30 | llll : 'ddd, D MMM YYYY HH:mm' 31 | }, 32 | calendar : { 33 | sameDay : '[היום ב־]LT', 34 | nextDay : '[מחר ב־]LT', 35 | nextWeek : 'dddd [בשעה] LT', 36 | lastDay : '[אתמול ב־]LT', 37 | lastWeek : '[ביום] dddd [האחרון בשעה] LT', 38 | sameElse : 'L' 39 | }, 40 | relativeTime : { 41 | future : 'בעוד %s', 42 | past : 'לפני %s', 43 | s : 'מספר שניות', 44 | m : 'דקה', 45 | mm : '%d דקות', 46 | h : 'שעה', 47 | hh : function (number) { 48 | if (number === 2) { 49 | return 'שעתיים'; 50 | } 51 | return number + ' שעות'; 52 | }, 53 | d : 'יום', 54 | dd : function (number) { 55 | if (number === 2) { 56 | return 'יומיים'; 57 | } 58 | return number + ' ימים'; 59 | }, 60 | M : 'חודש', 61 | MM : function (number) { 62 | if (number === 2) { 63 | return 'חודשיים'; 64 | } 65 | return number + ' חודשים'; 66 | }, 67 | y : 'שנה', 68 | yy : function (number) { 69 | if (number === 2) { 70 | return 'שנתיים'; 71 | } else if (number % 10 === 0 && number !== 10) { 72 | return number + ' שנה'; 73 | } 74 | return number + ' שנים'; 75 | } 76 | } 77 | }); 78 | 79 | return he; 80 | 81 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/my.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Burmese (my) 3 | //! author : Squar team, mysquar.com 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var symbolMap = { 13 | '1': '၁', 14 | '2': '၂', 15 | '3': '၃', 16 | '4': '၄', 17 | '5': '၅', 18 | '6': '၆', 19 | '7': '၇', 20 | '8': '၈', 21 | '9': '၉', 22 | '0': '၀' 23 | }, numberMap = { 24 | '၁': '1', 25 | '၂': '2', 26 | '၃': '3', 27 | '၄': '4', 28 | '၅': '5', 29 | '၆': '6', 30 | '၇': '7', 31 | '၈': '8', 32 | '၉': '9', 33 | '၀': '0' 34 | }; 35 | 36 | var my = moment.defineLocale('my', { 37 | months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), 38 | monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), 39 | weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), 40 | weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), 41 | weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), 42 | 43 | longDateFormat: { 44 | LT: 'HH:mm', 45 | LTS: 'HH:mm:ss', 46 | L: 'DD/MM/YYYY', 47 | LL: 'D MMMM YYYY', 48 | LLL: 'D MMMM YYYY HH:mm', 49 | LLLL: 'dddd D MMMM YYYY HH:mm' 50 | }, 51 | calendar: { 52 | sameDay: '[ယနေ.] LT [မှာ]', 53 | nextDay: '[မနက်ဖြန်] LT [မှာ]', 54 | nextWeek: 'dddd LT [မှာ]', 55 | lastDay: '[မနေ.က] LT [မှာ]', 56 | lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]', 57 | sameElse: 'L' 58 | }, 59 | relativeTime: { 60 | future: 'လာမည့် %s မှာ', 61 | past: 'လွန်ခဲ့သော %s က', 62 | s: 'စက္ကန်.အနည်းငယ်', 63 | m: 'တစ်မိနစ်', 64 | mm: '%d မိနစ်', 65 | h: 'တစ်နာရီ', 66 | hh: '%d နာရီ', 67 | d: 'တစ်ရက်', 68 | dd: '%d ရက်', 69 | M: 'တစ်လ', 70 | MM: '%d လ', 71 | y: 'တစ်နှစ်', 72 | yy: '%d နှစ်' 73 | }, 74 | preparse: function (string) { 75 | return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) { 76 | return numberMap[match]; 77 | }); 78 | }, 79 | postformat: function (string) { 80 | return string.replace(/\d/g, function (match) { 81 | return symbolMap[match]; 82 | }); 83 | }, 84 | week: { 85 | dow: 1, // Monday is the first day of the week. 86 | doy: 4 // The week that contains Jan 1st is the first week of the year. 87 | } 88 | }); 89 | 90 | return my; 91 | 92 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/de.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : german (de) 3 | //! author : lluchs : https://github.com/lluchs 4 | //! author: Menelion Elensúle: https://github.com/Oire 5 | 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 8 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 9 | factory(global.moment) 10 | }(this, function (moment) { 'use strict'; 11 | 12 | 13 | function processRelativeTime(number, withoutSuffix, key, isFuture) { 14 | var format = { 15 | 'm': ['eine Minute', 'einer Minute'], 16 | 'h': ['eine Stunde', 'einer Stunde'], 17 | 'd': ['ein Tag', 'einem Tag'], 18 | 'dd': [number + ' Tage', number + ' Tagen'], 19 | 'M': ['ein Monat', 'einem Monat'], 20 | 'MM': [number + ' Monate', number + ' Monaten'], 21 | 'y': ['ein Jahr', 'einem Jahr'], 22 | 'yy': [number + ' Jahre', number + ' Jahren'] 23 | }; 24 | return withoutSuffix ? format[key][0] : format[key][1]; 25 | } 26 | 27 | var de = moment.defineLocale('de', { 28 | months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), 29 | monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), 30 | weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), 31 | weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), 32 | weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), 33 | longDateFormat : { 34 | LT: 'HH:mm', 35 | LTS: 'HH:mm:ss', 36 | L : 'DD.MM.YYYY', 37 | LL : 'D. MMMM YYYY', 38 | LLL : 'D. MMMM YYYY HH:mm', 39 | LLLL : 'dddd, D. MMMM YYYY HH:mm' 40 | }, 41 | calendar : { 42 | sameDay: '[Heute um] LT [Uhr]', 43 | sameElse: 'L', 44 | nextDay: '[Morgen um] LT [Uhr]', 45 | nextWeek: 'dddd [um] LT [Uhr]', 46 | lastDay: '[Gestern um] LT [Uhr]', 47 | lastWeek: '[letzten] dddd [um] LT [Uhr]' 48 | }, 49 | relativeTime : { 50 | future : 'in %s', 51 | past : 'vor %s', 52 | s : 'ein paar Sekunden', 53 | m : processRelativeTime, 54 | mm : '%d Minuten', 55 | h : processRelativeTime, 56 | hh : '%d Stunden', 57 | d : processRelativeTime, 58 | dd : processRelativeTime, 59 | M : processRelativeTime, 60 | MM : processRelativeTime, 61 | y : processRelativeTime, 62 | yy : processRelativeTime 63 | }, 64 | ordinalParse: /\d{1,2}\./, 65 | ordinal : '%d.', 66 | week : { 67 | dow : 1, // Monday is the first day of the week. 68 | doy : 4 // The week that contains Jan 4th is the first week of the year. 69 | } 70 | }); 71 | 72 | return de; 73 | 74 | })); -------------------------------------------------------------------------------- /static/js/service/app.services.js: -------------------------------------------------------------------------------- 1 | (function (angular) { 2 | angular.module('app.services', ['ngMaterial','app.config']) 3 | .factory('$dialog', function($mdDialog,$filter) { 4 | var translateFilter=$filter('translate'); 5 | return { 6 | confirm:_confirm, 7 | alert:_alert 8 | }; 9 | 10 | function _confirm(template,callback) { 11 | var options; 12 | if(angular.isObject(template)){ 13 | options=template; 14 | }else { 15 | options={ 16 | template:template, 17 | onConfirm:callback 18 | }; 19 | } 20 | showDialog(options); 21 | } 22 | 23 | function _alert(template,callbakc) { 24 | var options; 25 | if(angular.isObject(template)){ 26 | options=template; 27 | }else{ 28 | options={ 29 | template:template, 30 | type:'warn', 31 | showOkButton:false, 32 | cancelText:translateFilter('CLOSE'), 33 | onCancel:callbakc 34 | }; 35 | } 36 | 37 | showDialog(options); 38 | } 39 | 40 | function showDialog(config) { 41 | var parentEl = angular.element(document.body); 42 | 43 | var defaults={ 44 | title:translateFilter('HINT'), 45 | okText:translateFilter('CONFIRM'), 46 | cancelText:translateFilter('CANCEL'), 47 | showOkButton:true, 48 | showCancelButton:true, 49 | showToolbar:true, 50 | template:'您确定要这样做吗?', 51 | type:'primary', 52 | clickOutsideToClose :true, 53 | escapeToClose :true, 54 | onConfirm:angular.noop, 55 | onCancel:angular.noop 56 | }; 57 | 58 | angular.extend(defaults,config); 59 | 60 | $mdDialog.show({ 61 | parent: defaults.parentEl||parentEl, 62 | 63 | templateUrl:'../templates/dialog.html', 64 | locals: { 65 | config: defaults 66 | }, 67 | controller: DialogController 68 | }); 69 | function DialogController($scope, $mdDialog, config) { 70 | $scope.config = config; 71 | $scope.onConfirm=function () { 72 | config.onConfirm(); 73 | $mdDialog.hide(); 74 | }; 75 | $scope.closeDialog = function() { 76 | config.onCancel(); 77 | $mdDialog.hide(); 78 | }; 79 | } 80 | } 81 | }); 82 | })(angular); 83 | -------------------------------------------------------------------------------- /static/lib/moment/README.md: -------------------------------------------------------------------------------- 1 | [![Join the chat at https://gitter.im/moment/moment](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/moment/moment?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 2 | 3 | [![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url] [![Build Status][travis-image]][travis-url] 4 | [![Coverage Status](https://coveralls.io/repos/moment/moment/badge.svg?branch=master)](https://coveralls.io/r/moment/moment?branch=master) 5 | 6 | A lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates. 7 | 8 | ## [Documentation](http://momentjs.com/docs/) 9 | 10 | ## Port to ES6 (version 2.10.0) 11 | 12 | Moment 2.10.0 does not bring any new features, but the code is now written in 13 | es6 modules and placed inside `src/`. Previously `moment.js`, `locale/*.js` and 14 | `test/moment/*.js`, `test/locale/*.js` contained the source of the project. Now 15 | the source is in `src/`, temporary build (es5) files are placed under 16 | `build/umd/` (for running tests during development), and the `moment.js` and 17 | `locale/*.js` files are updated only on release. 18 | 19 | If you want to use a particular revision of the code, make sure to run 20 | `grunt transpile update-index`, so `moment.js` and `locales/*.js` are synced 21 | with `src/*`. We might place that in a commit hook in the future. 22 | 23 | ## Upgrading to 2.0.0 24 | 25 | There are a number of small backwards incompatible changes with version 2.0.0. [See the full descriptions here](https://gist.github.com/timrwood/e72f2eef320ed9e37c51#backwards-incompatible-changes) 26 | 27 | * Changed language ordinal method to return the number + ordinal instead of just the ordinal. 28 | 29 | * Changed two digit year parsing cutoff to match strptime. 30 | 31 | * Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`. 32 | 33 | * Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`. 34 | 35 | * Removed the lang data objects from the top level namespace. 36 | 37 | * Duplicate `Date` passed to `moment()` instead of referencing it. 38 | 39 | ## [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) 40 | 41 | ## [Contributing](https://github.com/moment/moment/blob/develop/CONTRIBUTING.md) 42 | 43 | We're looking for co-maintainers! If you want to become a master of time please 44 | write to [ichernev](https://github.com/ichernev). 45 | 46 | ## License 47 | 48 | Moment.js is freely distributable under the terms of the [MIT license](https://github.com/moment/moment/blob/develop/LICENSE). 49 | 50 | [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat 51 | [license-url]: LICENSE 52 | 53 | [npm-url]: https://npmjs.org/package/moment 54 | [npm-version-image]: http://img.shields.io/npm/v/moment.svg?style=flat 55 | [npm-downloads-image]: http://img.shields.io/npm/dm/moment.svg?style=flat 56 | 57 | [travis-url]: http://travis-ci.org/moment/moment 58 | [travis-image]: http://img.shields.io/travis/moment/moment/develop.svg?style=flat 59 | -------------------------------------------------------------------------------- /static/lib/moment/locale/ms.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Bahasa Malaysia (ms-MY) 3 | //! author : Weldan Jamili : https://github.com/weldan 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var ms = moment.defineLocale('ms', { 13 | months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), 14 | monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), 15 | weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), 16 | weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), 17 | weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH.mm', 20 | LTS : 'HH.mm.ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY [pukul] HH.mm', 24 | LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' 25 | }, 26 | meridiemParse: /pagi|tengahari|petang|malam/, 27 | meridiemHour: function (hour, meridiem) { 28 | if (hour === 12) { 29 | hour = 0; 30 | } 31 | if (meridiem === 'pagi') { 32 | return hour; 33 | } else if (meridiem === 'tengahari') { 34 | return hour >= 11 ? hour : hour + 12; 35 | } else if (meridiem === 'petang' || meridiem === 'malam') { 36 | return hour + 12; 37 | } 38 | }, 39 | meridiem : function (hours, minutes, isLower) { 40 | if (hours < 11) { 41 | return 'pagi'; 42 | } else if (hours < 15) { 43 | return 'tengahari'; 44 | } else if (hours < 19) { 45 | return 'petang'; 46 | } else { 47 | return 'malam'; 48 | } 49 | }, 50 | calendar : { 51 | sameDay : '[Hari ini pukul] LT', 52 | nextDay : '[Esok pukul] LT', 53 | nextWeek : 'dddd [pukul] LT', 54 | lastDay : '[Kelmarin pukul] LT', 55 | lastWeek : 'dddd [lepas pukul] LT', 56 | sameElse : 'L' 57 | }, 58 | relativeTime : { 59 | future : 'dalam %s', 60 | past : '%s yang lepas', 61 | s : 'beberapa saat', 62 | m : 'seminit', 63 | mm : '%d minit', 64 | h : 'sejam', 65 | hh : '%d jam', 66 | d : 'sehari', 67 | dd : '%d hari', 68 | M : 'sebulan', 69 | MM : '%d bulan', 70 | y : 'setahun', 71 | yy : '%d tahun' 72 | }, 73 | week : { 74 | dow : 1, // Monday is the first day of the week. 75 | doy : 7 // The week that contains Jan 1st is the first week of the year. 76 | } 77 | }); 78 | 79 | return ms; 80 | 81 | })); -------------------------------------------------------------------------------- /static/js/service/baiduweather.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | angular 3 | .module('app.baiduWeather',[]) 4 | //百度天气服务 5 | .factory('BaiduWeather',function ($http,$q) { 6 | var cityListUri = 'http://apis.baidu.com/apistore/weatherservice/citylist'; 7 | var recentWeatherUri = 'http://apis.baidu.com/apistore/weatherservice/recentweathers'; 8 | var todayWeatherUri = 'http://apis.baidu.com/apistore/weatherservice/cityid'; 9 | 10 | function BaiduWeather(apiKey) { 11 | this.API_KEY = apiKey; 12 | } 13 | 14 | BaiduWeather.prototype = { 15 | /** 16 | * 判断请求是否成功 17 | * @method _isReqSuccess 18 | * @param {String} msg [description] 19 | * @return {Boolean} [description] 20 | * @private 21 | */ 22 | _isReqSuccess:function (msg) { 23 | return msg === 'success'; 24 | }, 25 | /** 26 | * 共用请求 27 | * @param {String} url 请求地址 28 | * @param {Object} param 请求参数 29 | * @returns {*|d.promise|promise} 30 | * @private 31 | */ 32 | _request:function(url,param){ 33 | var deferred = $q.defer(); 34 | var that = this; 35 | 36 | $http({ 37 | url:url, 38 | method:'GET', 39 | params:param, 40 | headers:{ 41 | apiKey:this.API_KEY 42 | } 43 | }) 44 | .success(function (resp) { 45 | if (that._isReqSuccess(resp.errMsg)){ 46 | return deferred.resolve(resp.retData); 47 | } 48 | deferred.reject(resp); 49 | }) 50 | .error(function (err) { 51 | deferred.reject(err); 52 | }); 53 | 54 | return deferred.promise; 55 | }, 56 | /** 57 | * 获取城市列表 58 | * @method getCityListByName 59 | * @param {String} cityName 城市名称 60 | * @return {[type]} [description] 61 | */ 62 | getCityListByName:function (cityName) { 63 | return this._request(cityListUri, { 64 | cityname:cityName 65 | }); 66 | }, 67 | /** 68 | * 获取最近天气,过去七天与未来四天 69 | * @method getRencentWeatherByCityId 70 | * @param {String} cityId 城市Id 71 | * @return {Promise} [description] 72 | */ 73 | getRecentWeatherByCityId:function (cityId) { 74 | return this._request(recentWeatherUri,{ 75 | cityid:cityId 76 | }); 77 | }, 78 | /** 79 | * 获取今天的天气 80 | * @param cityId 81 | * @returns {*|d.promise|promise} 82 | */ 83 | getTodayWeatherByCityId:function(cityId){ 84 | return this._request(todayWeatherUri,{ 85 | cityid:cityId 86 | }); 87 | } 88 | }; 89 | return BaiduWeather; 90 | }); 91 | })(); 92 | -------------------------------------------------------------------------------- /static/lib/moment/locale/ms-my.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Bahasa Malaysia (ms-MY) 3 | //! author : Weldan Jamili : https://github.com/weldan 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var ms_my = moment.defineLocale('ms-my', { 13 | months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'), 14 | monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'), 15 | weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'), 16 | weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'), 17 | weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'), 18 | longDateFormat : { 19 | LT : 'HH.mm', 20 | LTS : 'HH.mm.ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY [pukul] HH.mm', 24 | LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm' 25 | }, 26 | meridiemParse: /pagi|tengahari|petang|malam/, 27 | meridiemHour: function (hour, meridiem) { 28 | if (hour === 12) { 29 | hour = 0; 30 | } 31 | if (meridiem === 'pagi') { 32 | return hour; 33 | } else if (meridiem === 'tengahari') { 34 | return hour >= 11 ? hour : hour + 12; 35 | } else if (meridiem === 'petang' || meridiem === 'malam') { 36 | return hour + 12; 37 | } 38 | }, 39 | meridiem : function (hours, minutes, isLower) { 40 | if (hours < 11) { 41 | return 'pagi'; 42 | } else if (hours < 15) { 43 | return 'tengahari'; 44 | } else if (hours < 19) { 45 | return 'petang'; 46 | } else { 47 | return 'malam'; 48 | } 49 | }, 50 | calendar : { 51 | sameDay : '[Hari ini pukul] LT', 52 | nextDay : '[Esok pukul] LT', 53 | nextWeek : 'dddd [pukul] LT', 54 | lastDay : '[Kelmarin pukul] LT', 55 | lastWeek : 'dddd [lepas pukul] LT', 56 | sameElse : 'L' 57 | }, 58 | relativeTime : { 59 | future : 'dalam %s', 60 | past : '%s yang lepas', 61 | s : 'beberapa saat', 62 | m : 'seminit', 63 | mm : '%d minit', 64 | h : 'sejam', 65 | hh : '%d jam', 66 | d : 'sehari', 67 | dd : '%d hari', 68 | M : 'sebulan', 69 | MM : '%d bulan', 70 | y : 'setahun', 71 | yy : '%d tahun' 72 | }, 73 | week : { 74 | dow : 1, // Monday is the first day of the week. 75 | doy : 7 // The week that contains Jan 1st is the first week of the year. 76 | } 77 | }); 78 | 79 | return ms_my; 80 | 81 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/cy.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : Welsh (cy) 3 | //! author : Robert Allen 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var cy = moment.defineLocale('cy', { 13 | months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), 14 | monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), 15 | weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), 16 | weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), 17 | weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), 18 | // time formats are the same as en-gb 19 | longDateFormat: { 20 | LT: 'HH:mm', 21 | LTS : 'HH:mm:ss', 22 | L: 'DD/MM/YYYY', 23 | LL: 'D MMMM YYYY', 24 | LLL: 'D MMMM YYYY HH:mm', 25 | LLLL: 'dddd, D MMMM YYYY HH:mm' 26 | }, 27 | calendar: { 28 | sameDay: '[Heddiw am] LT', 29 | nextDay: '[Yfory am] LT', 30 | nextWeek: 'dddd [am] LT', 31 | lastDay: '[Ddoe am] LT', 32 | lastWeek: 'dddd [diwethaf am] LT', 33 | sameElse: 'L' 34 | }, 35 | relativeTime: { 36 | future: 'mewn %s', 37 | past: '%s yn ôl', 38 | s: 'ychydig eiliadau', 39 | m: 'munud', 40 | mm: '%d munud', 41 | h: 'awr', 42 | hh: '%d awr', 43 | d: 'diwrnod', 44 | dd: '%d diwrnod', 45 | M: 'mis', 46 | MM: '%d mis', 47 | y: 'blwyddyn', 48 | yy: '%d flynedd' 49 | }, 50 | ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, 51 | // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh 52 | ordinal: function (number) { 53 | var b = number, 54 | output = '', 55 | lookup = [ 56 | '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed 57 | 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed 58 | ]; 59 | if (b > 20) { 60 | if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { 61 | output = 'fed'; // not 30ain, 70ain or 90ain 62 | } else { 63 | output = 'ain'; 64 | } 65 | } else if (b > 0) { 66 | output = lookup[b]; 67 | } 68 | return number + output; 69 | }, 70 | week : { 71 | dow : 1, // Monday is the first day of the week. 72 | doy : 4 // The week that contains Jan 4th is the first week of the year. 73 | } 74 | }); 75 | 76 | return cy; 77 | 78 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/de-at.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : austrian german (de-at) 3 | //! author : lluchs : https://github.com/lluchs 4 | //! author: Menelion Elensúle: https://github.com/Oire 5 | //! author : Martin Groller : https://github.com/MadMG 6 | 7 | (function (global, factory) { 8 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 9 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 10 | factory(global.moment) 11 | }(this, function (moment) { 'use strict'; 12 | 13 | 14 | function processRelativeTime(number, withoutSuffix, key, isFuture) { 15 | var format = { 16 | 'm': ['eine Minute', 'einer Minute'], 17 | 'h': ['eine Stunde', 'einer Stunde'], 18 | 'd': ['ein Tag', 'einem Tag'], 19 | 'dd': [number + ' Tage', number + ' Tagen'], 20 | 'M': ['ein Monat', 'einem Monat'], 21 | 'MM': [number + ' Monate', number + ' Monaten'], 22 | 'y': ['ein Jahr', 'einem Jahr'], 23 | 'yy': [number + ' Jahre', number + ' Jahren'] 24 | }; 25 | return withoutSuffix ? format[key][0] : format[key][1]; 26 | } 27 | 28 | var de_at = moment.defineLocale('de-at', { 29 | months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), 30 | monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), 31 | weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'), 32 | weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'), 33 | weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'), 34 | longDateFormat : { 35 | LT: 'HH:mm', 36 | LTS: 'HH:mm:ss', 37 | L : 'DD.MM.YYYY', 38 | LL : 'D. MMMM YYYY', 39 | LLL : 'D. MMMM YYYY HH:mm', 40 | LLLL : 'dddd, D. MMMM YYYY HH:mm' 41 | }, 42 | calendar : { 43 | sameDay: '[Heute um] LT [Uhr]', 44 | sameElse: 'L', 45 | nextDay: '[Morgen um] LT [Uhr]', 46 | nextWeek: 'dddd [um] LT [Uhr]', 47 | lastDay: '[Gestern um] LT [Uhr]', 48 | lastWeek: '[letzten] dddd [um] LT [Uhr]' 49 | }, 50 | relativeTime : { 51 | future : 'in %s', 52 | past : 'vor %s', 53 | s : 'ein paar Sekunden', 54 | m : processRelativeTime, 55 | mm : '%d Minuten', 56 | h : processRelativeTime, 57 | hh : '%d Stunden', 58 | d : processRelativeTime, 59 | dd : processRelativeTime, 60 | M : processRelativeTime, 61 | MM : processRelativeTime, 62 | y : processRelativeTime, 63 | yy : processRelativeTime 64 | }, 65 | ordinalParse: /\d{1,2}\./, 66 | ordinal : '%d.', 67 | week : { 68 | dow : 1, // Monday is the first day of the week. 69 | doy : 4 // The week that contains Jan 4th is the first week of the year. 70 | } 71 | }); 72 | 73 | return de_at; 74 | 75 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/ca.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : catalan (ca) 3 | //! author : Juan G. Hurtado : https://github.com/juanghurtado 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var ca = moment.defineLocale('ca', { 13 | months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'), 14 | monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'), 15 | weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'), 16 | weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'), 17 | weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'), 18 | longDateFormat : { 19 | LT : 'H:mm', 20 | LTS : 'LT:ss', 21 | L : 'DD/MM/YYYY', 22 | LL : 'D MMMM YYYY', 23 | LLL : 'D MMMM YYYY H:mm', 24 | LLLL : 'dddd D MMMM YYYY H:mm' 25 | }, 26 | calendar : { 27 | sameDay : function () { 28 | return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; 29 | }, 30 | nextDay : function () { 31 | return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; 32 | }, 33 | nextWeek : function () { 34 | return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; 35 | }, 36 | lastDay : function () { 37 | return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; 38 | }, 39 | lastWeek : function () { 40 | return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT'; 41 | }, 42 | sameElse : 'L' 43 | }, 44 | relativeTime : { 45 | future : 'en %s', 46 | past : 'fa %s', 47 | s : 'uns segons', 48 | m : 'un minut', 49 | mm : '%d minuts', 50 | h : 'una hora', 51 | hh : '%d hores', 52 | d : 'un dia', 53 | dd : '%d dies', 54 | M : 'un mes', 55 | MM : '%d mesos', 56 | y : 'un any', 57 | yy : '%d anys' 58 | }, 59 | ordinalParse: /\d{1,2}(r|n|t|è|a)/, 60 | ordinal : function (number, period) { 61 | var output = (number === 1) ? 'r' : 62 | (number === 2) ? 'n' : 63 | (number === 3) ? 'r' : 64 | (number === 4) ? 't' : 'è'; 65 | if (period === 'w' || period === 'W') { 66 | output = 'a'; 67 | } 68 | return number + output; 69 | }, 70 | week : { 71 | dow : 1, // Monday is the first day of the week. 72 | doy : 4 // The week that contains Jan 4th is the first week of the year. 73 | } 74 | }); 75 | 76 | return ca; 77 | 78 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/es.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : spanish (es) 3 | //! author : Julio Napurí : https://github.com/julionc 4 | 5 | (function (global, factory) { 6 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 7 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 8 | factory(global.moment) 9 | }(this, function (moment) { 'use strict'; 10 | 11 | 12 | var monthsShortDot = 'Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.'.split('_'), 13 | monthsShort = 'Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Sep_Oct_Nov_Dic'.split('_'); 14 | 15 | var es = moment.defineLocale('es', { 16 | months : 'Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre'.split('_'), 17 | monthsShort : function (m, format) { 18 | if (/-MMM-/.test(format)) { 19 | return monthsShort[m.month()]; 20 | } else { 21 | return monthsShortDot[m.month()]; 22 | } 23 | }, 24 | weekdays : 'Domingo_Lunes_Martes_Miércoles_Jueves_Viernes_Sábado'.split('_'), 25 | weekdaysShort : 'Dom._Lun._Mar._Mié._Jue._Vie._Sáb.'.split('_'), 26 | weekdaysMin : 'Do_Lu_Ma_Mi_Ju_Vi_Sá'.split('_'), 27 | longDateFormat : { 28 | LT : 'H:mm', 29 | LTS : 'H:mm:ss', 30 | L : 'DD/MM/YYYY', 31 | LL : 'D [de] MMMM [de] YYYY', 32 | LLL : 'D [de] MMMM [de] YYYY H:mm', 33 | LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm' 34 | }, 35 | calendar : { 36 | sameDay : function () { 37 | return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; 38 | }, 39 | nextDay : function () { 40 | return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; 41 | }, 42 | nextWeek : function () { 43 | return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; 44 | }, 45 | lastDay : function () { 46 | return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; 47 | }, 48 | lastWeek : function () { 49 | return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT'; 50 | }, 51 | sameElse : 'L' 52 | }, 53 | relativeTime : { 54 | future : 'en %s', 55 | past : 'hace %s', 56 | s : 'unos segundos', 57 | m : 'un minuto', 58 | mm : '%d minutos', 59 | h : 'una hora', 60 | hh : '%d horas', 61 | d : 'un día', 62 | dd : '%d días', 63 | M : 'un mes', 64 | MM : '%d meses', 65 | y : 'un año', 66 | yy : '%d años' 67 | }, 68 | ordinalParse : /\d{1,2}º/, 69 | ordinal : '%dº', 70 | week : { 71 | dow : 1, // Monday is the first day of the week. 72 | doy : 4 // The week that contains Jan 4th is the first week of the year. 73 | } 74 | }); 75 | 76 | return es; 77 | 78 | })); -------------------------------------------------------------------------------- /static/lib/moment/locale/tr.js: -------------------------------------------------------------------------------- 1 | //! moment.js locale configuration 2 | //! locale : turkish (tr) 3 | //! authors : Erhan Gundogan : https://github.com/erhangundogan, 4 | //! Burak Yiğit Kaya: https://github.com/BYK 5 | 6 | (function (global, factory) { 7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : 8 | typeof define === 'function' && define.amd ? define(['moment'], factory) : 9 | factory(global.moment) 10 | }(this, function (moment) { 'use strict'; 11 | 12 | 13 | var suffixes = { 14 | 1: '\'inci', 15 | 5: '\'inci', 16 | 8: '\'inci', 17 | 70: '\'inci', 18 | 80: '\'inci', 19 | 2: '\'nci', 20 | 7: '\'nci', 21 | 20: '\'nci', 22 | 50: '\'nci', 23 | 3: '\'üncü', 24 | 4: '\'üncü', 25 | 100: '\'üncü', 26 | 6: '\'ncı', 27 | 9: '\'uncu', 28 | 10: '\'uncu', 29 | 30: '\'uncu', 30 | 60: '\'ıncı', 31 | 90: '\'ıncı' 32 | }; 33 | 34 | var tr = moment.defineLocale('tr', { 35 | months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'), 36 | monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'), 37 | weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'), 38 | weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'), 39 | weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'), 40 | longDateFormat : { 41 | LT : 'HH:mm', 42 | LTS : 'HH:mm:ss', 43 | L : 'DD.MM.YYYY', 44 | LL : 'D MMMM YYYY', 45 | LLL : 'D MMMM YYYY HH:mm', 46 | LLLL : 'dddd, D MMMM YYYY HH:mm' 47 | }, 48 | calendar : { 49 | sameDay : '[bugün saat] LT', 50 | nextDay : '[yarın saat] LT', 51 | nextWeek : '[haftaya] dddd [saat] LT', 52 | lastDay : '[dün] LT', 53 | lastWeek : '[geçen hafta] dddd [saat] LT', 54 | sameElse : 'L' 55 | }, 56 | relativeTime : { 57 | future : '%s sonra', 58 | past : '%s önce', 59 | s : 'birkaç saniye', 60 | m : 'bir dakika', 61 | mm : '%d dakika', 62 | h : 'bir saat', 63 | hh : '%d saat', 64 | d : 'bir gün', 65 | dd : '%d gün', 66 | M : 'bir ay', 67 | MM : '%d ay', 68 | y : 'bir yıl', 69 | yy : '%d yıl' 70 | }, 71 | ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, 72 | ordinal : function (number) { 73 | if (number === 0) { // special case for zero 74 | return number + '\'ıncı'; 75 | } 76 | var a = number % 10, 77 | b = number % 100 - a, 78 | c = number >= 100 ? 100 : null; 79 | return number + (suffixes[a] || suffixes[b] || suffixes[c]); 80 | }, 81 | week : { 82 | dow : 1, // Monday is the first day of the week. 83 | doy : 7 // The week that contains Jan 1st is the first week of the year. 84 | } 85 | }); 86 | 87 | return tr; 88 | 89 | })); --------------------------------------------------------------------------------