├── .bowerrc ├── .gitignore ├── views ├── includes │ ├── footer.jade │ ├── head.jade │ └── header.jade ├── layout.jade └── pages │ ├── index.jade │ ├── detail.jade │ ├── userlist.jade │ ├── list.jade │ └── admin.jade ├── models ├── user.js └── movie.js ├── public └── js │ └── admin.js ├── bower.json ├── README.md ├── package.json ├── schemas ├── movie.js └── user.js ├── .project ├── Gruntfile.js ├── LICENSE ├── app.js └── config └── routes.js /.bowerrc: -------------------------------------------------------------------------------- 1 | {"directory" : "public/libs"} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | bower_components/ 3 | public/libs/ 4 | *.log 5 | 6 | build/ 7 | dist/ 8 | -------------------------------------------------------------------------------- /views/includes/footer.jade: -------------------------------------------------------------------------------- 1 | .container 2 | .row 3 | .col-md-12 4 | p.text-center(style="line-height:25px") Copyright 2001-2014 【#{movie.title}】 By Kvkens -------------------------------------------------------------------------------- /models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var UserSchema = require("../schemas/user"); 3 | var User = mongoose.model("User", UserSchema); 4 | 5 | module.exports = User; -------------------------------------------------------------------------------- /models/movie.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var MovieSchema = require("../schemas/movie"); 3 | var Movie = mongoose.model("Movie", MovieSchema); 4 | 5 | module.exports = Movie; -------------------------------------------------------------------------------- /views/includes/head.jade: -------------------------------------------------------------------------------- 1 | link(href="/libs/bootstrap/dist/css/bootstrap.min.css",rel="stylesheet") 2 | script(src="/libs/jquery/dist/jquery.min.js") 3 | script(src="/libs/bootstrap/dist/js/bootstrap.min.js") -------------------------------------------------------------------------------- /views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype 2 | html 3 | head 4 | meta(charset="utf-8") 5 | meta(name="viewport",content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no") 6 | title #{title} 7 | include ./includes/head 8 | body 9 | include ./includes/header 10 | block content -------------------------------------------------------------------------------- /public/js/admin.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | $(".del").click(function(event){ 3 | if(!confirm("是否删除?")){ 4 | return; 5 | } 6 | var target = $(event.target); 7 | var id = target.data("id"); 8 | var tr = $(".item-id-" + id); 9 | 10 | $.ajax({ 11 | type : "DELETE", 12 | url : "/admin/list?id=" + id 13 | }).done(function(result){ 14 | if(result.success === 1){ 15 | if(tr.length > 0){ 16 | tr.remove(); 17 | } 18 | } 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Imooc", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Kvkens " 6 | ], 7 | "description": "node.js+express+jade+mongodb", 8 | "main": "app.js", 9 | "keywords": [ 10 | "node.js" 11 | ], 12 | "license": "MIT", 13 | "homepage": "www.imyy.org", 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "public/libs", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "bootstrap": "~3.2.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /views/pages/index.jade: -------------------------------------------------------------------------------- 1 | extends ../layout 2 | 3 | block content 4 | .container 5 | .row(style="margin-bottom:70px") 6 | each item in movies 7 | .col-md-2 8 | .thumbnail 9 | a(href="/movie/#{item._id}",target="_blank") 10 | img(src="#{item.poster}",alt="#{item.title}",title="#{item.title}") 11 | .caption 12 | h3 #{item.title} 13 | p: a.btn.btn-primary(href="/movie/#{item._id}",role="button",target="_blank") 14 | span.glyphicon.glyphicon-zoom-in 观看预告片 -------------------------------------------------------------------------------- /views/pages/detail.jade: -------------------------------------------------------------------------------- 1 | extends ../layout 2 | 3 | block content 4 | .container 5 | .row(style="margin-bottom:70px") 6 | .col-md-7 7 | embed(src="#{movie.flash}",allowFullScreen="true",quality="high",width="720",height="600",align="middle",type="application/x-shockwave-flash") 8 | .col-md-5 9 | dl.dl-horizontal 10 | dt 电影名字 11 | dd= movie.title 12 | dt 导演 13 | dd= movie.doctor 14 | dt 国家 15 | dd= movie.country 16 | dt 语言 17 | dd= movie.language 18 | dt 上映年份 19 | dd= movie.year 20 | dt 简介 21 | dd= movie.summary -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 后续有时间更新一下吧~ 2 | 3 | ===== 4 | 5 | ####慕课网bootstrap+node.js+express+jade+mongodb打造下一代web应用程序。 6 | 7 | ===== 8 | ###架构 9 | - 自动化流程:grunt、grunt-concurrent、grunt-contrib-watch、grunt-nodemon 10 | - 前端:Bootstrap、jQuery `后面会采用angular做为前端MVC` 11 | - 后端:node.js、express、jade、moment、underscore、mongoose、bcrypt、cookie-parser、express-session 12 | - 数据库:MongoDB 13 | 14 | 15 | -------------------------- 16 | ### 本地开发和运行 17 | 18 | 1. 安装 [nodejs](http://nodejs.org) 环境和 [npm](https://www.npmjs.org),具体方法请自行参考其官网文档。 19 | 2. 在项目根目录依次执行 `npm install` 和 `bower install`安装依赖项,然后执行 `grunt` 即可启动开发服务器并调用系统浏览器打开 。 20 | 3. 默认数使用的 MongoDB 服务器地址为 `mongodb://localhost/imooc` 21 | 22 | ### 功能模块 23 | 24 | - `首页电影展示` 25 | - `电影查看 ` 26 | - `用户的注册与登录` 27 | - `后台电影录入` 28 | - `后台电影管理列表` 29 | - `后台注册用户列表` 30 | 31 | -------------------------- 32 | -------------------------------------------------------------------------------- /views/pages/userlist.jade: -------------------------------------------------------------------------------- 1 | extends ../layout 2 | 3 | block content 4 | .container 5 | .row(style="margin-bottom:70px") 6 | .panel.panel-default 7 | .panel-heading 注册用户信息 8 | 9 | table.table.table-hover.table-bordered 10 | thead 11 | tr 12 | th 登录名 13 | th 注册时间 14 | th 查看 15 | th 更新 16 | th 删除 17 | tbody 18 | each item in users 19 | tr(class="item-id-#{item._id}") 20 | td #{item.name} 21 | td #{moment(item.meta.updateAt).format('YYYY-MM-DD HH:mm:ss')} 22 | td: a.btn.btn-info.btn-xs(target="_blank",href="../movie/#{item._id}") 查看 23 | td: a.btn.btn-success.btn-xs(target="_blank",href="../admin/update/#{item._id}") 修改 24 | td 25 | button.btn.btn-danger.del.btn-xs(type="button",data-id="#{item._id}") 删除 26 | script(src="/js/admin.js") -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Imooc", 3 | "version": "0.0.1", 4 | "description": "node.js+express+jade+mongodb", 5 | "main": "app.js", 6 | "dependencies": { 7 | "bcrypt": "^0.8.0", 8 | "body-parser": "^1.9.0", 9 | "connect-mongo": "^0.4.1", 10 | "cookie-parser": "^1.3.3", 11 | "express": "^4.9.5", 12 | "express-session": "^1.8.2", 13 | "grunt": "^0.4.5", 14 | "grunt-concurrent": "^1.0.0", 15 | "grunt-contrib-watch": "^0.6.1", 16 | "grunt-nodemon": "^0.3.0", 17 | "jade": "^1.7.0", 18 | "moment": "^2.8.3", 19 | "mongoose": "^3.8.17", 20 | "morgan": "^1.4.1", 21 | "underscore": "^1.7.0" 22 | }, 23 | "devDependencies": {}, 24 | "scripts": { 25 | "test": "echo \"Error: no test specified\" && exit 1" 26 | }, 27 | "keywords": [ 28 | "node.js" 29 | ], 30 | "author": "Kvkens", 31 | "license": "ISC" 32 | } 33 | -------------------------------------------------------------------------------- /schemas/movie.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | 3 | var MovieSchema = new mongoose.Schema({ 4 | doctor: String, 5 | title: String, 6 | language: String, 7 | country: String, 8 | summary: String, 9 | flash: String, 10 | poster: String, 11 | year: String, 12 | meta: { 13 | createAt: { 14 | type: Date, 15 | default: Date.now() 16 | }, 17 | updateAt: { 18 | type: Date, 19 | default: Date.now() 20 | } 21 | } 22 | }); 23 | 24 | MovieSchema.pre("save", function(next) { 25 | if (this.isNew) { 26 | this.meta.createAt = this.meta.updateAt = Date.now(); 27 | } else { 28 | this.meta.updateAt = Date.now(); 29 | } 30 | next() 31 | }); 32 | 33 | MovieSchema.statics = { 34 | fetch: function(cb) { 35 | return this 36 | .find({}) 37 | .sort("meta.updateAt") 38 | .exec(cb); 39 | }, 40 | findById: function(id, cb) { 41 | return this 42 | .findOne({ 43 | _id: id 44 | }) 45 | .exec(cb); 46 | } 47 | } 48 | 49 | module.exports = MovieSchema; -------------------------------------------------------------------------------- /views/pages/list.jade: -------------------------------------------------------------------------------- 1 | extends ../layout 2 | 3 | block content 4 | .container 5 | .row(style="margin-bottom:70px") 6 | .panel.panel-default 7 | .panel-heading 电影详情信息 8 | 9 | table.table.table-hover.table-bordered 10 | thead 11 | tr 12 | th 电影名字 13 | th 导演 14 | th 国家 15 | th 上映年份 16 | th 录入时间 17 | th 查看 18 | th 更新 19 | th 删除 20 | tbody 21 | each item in movies 22 | tr(class="item-id-#{item._id}") 23 | td #{item.title} 24 | td #{item.doctor} 25 | td #{item.country} 26 | td #{item.year} 27 | td #{moment(item.meta.updateAt).format('YYYY-MM-DD HH:mm:ss')} 28 | td: a.btn.btn-info.btn-xs(target="_blank",href="../movie/#{item._id}") 查看 29 | td: a.btn.btn-success.btn-xs(target="_blank",href="../admin/update/#{item._id}") 修改 30 | td 31 | button.btn.btn-danger.del.btn-xs(type="button",data-id="#{item._id}") 删除 32 | script(src="/js/admin.js") -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Imooc 4 | Create By HBuilder 5 | 6 | 7 | 8 | 9 | com.aptana.ide.core.unifiedBuilder 10 | 11 | 12 | 13 | 14 | 15 | com.aptana.projects.webnature 16 | 17 | 18 | 19 | 1412301388247 20 | 21 | 10 22 | 23 | org.eclipse.ui.ide.orFilterMatcher 24 | 25 | 26 | org.eclipse.ui.ide.multiFilter 27 | 1.0-projectRelativePath-matches-false-false-bin 28 | 29 | 30 | org.eclipse.ui.ide.multiFilter 31 | 1.0-projectRelativePath-matches-false-false-setting 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | watch: { 5 | jade: { 6 | files: ['views/**'], 7 | options: { 8 | livereload: true 9 | } 10 | }, 11 | js: { 12 | files: ['public/js/**', 'models/**/*.js', 'schemas/**/*.js'], 13 | //tasks: ['jshint'], 14 | options: { 15 | livereload: true 16 | } 17 | } 18 | }, 19 | 20 | nodemon: { 21 | dev: { 22 | script: 'app.js', 23 | options: { 24 | args: [], 25 | ignore: ['README.md', 'node_modules/**', 'DS_Store'], 26 | ext: 'js', 27 | watch: ['./'], 28 | nodeArgs: ['--debug'], 29 | delay: 1000, 30 | env: { 31 | PORT: 3000 32 | }, 33 | cwd: __dirname 34 | } 35 | } 36 | }, 37 | 38 | concurrent: { 39 | tasks: ['nodemon', 'watch'], 40 | options: { 41 | logConcurrentOutput: true 42 | } 43 | } 44 | }); 45 | 46 | grunt.loadNpmTasks("grunt-contrib-watch"); 47 | grunt.loadNpmTasks("grunt-nodemon"); 48 | grunt.loadNpmTasks("grunt-concurrent"); 49 | grunt.option("force", true); 50 | grunt.registerTask("default", ["concurrent"]); 51 | 52 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Kvkens 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 | -------------------------------------------------------------------------------- /schemas/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var bcrypt = require("bcrypt"); 3 | var SALT_WORK_FACTOR = 10; 4 | 5 | var UserSchema = new mongoose.Schema({ 6 | name: { 7 | type: String, 8 | unique: true 9 | }, 10 | password: String, 11 | meta: { 12 | createAt: { 13 | type: Date, 14 | default: Date.now() 15 | }, 16 | updateAt: { 17 | type: Date, 18 | default: Date.now() 19 | } 20 | } 21 | }); 22 | 23 | UserSchema.pre("save", function(next) { 24 | var user = this; 25 | if (this.isNew) { 26 | this.meta.createAt = this.meta.updateAt = Date.now(); 27 | } else { 28 | this.meta.updateAt = Date.now(); 29 | } 30 | bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) { 31 | if (err) return next(err); 32 | 33 | bcrypt.hash(user.password, salt, function(err, hash) { 34 | if (err) return next(err); 35 | 36 | user.password = hash; 37 | next(); 38 | }); 39 | }); 40 | //next(); 41 | }); 42 | 43 | UserSchema.methods = { 44 | comparePassword: function(_password, cb) { 45 | bcrypt.compare(_password, this.password, function(err, isMatch) { 46 | if (err) { 47 | return cb(err); 48 | } 49 | cb(null, isMatch); 50 | }); 51 | } 52 | } 53 | 54 | UserSchema.statics = { 55 | fetch: function(cb) { 56 | return this 57 | .find({}) 58 | .sort("meta.updateAt") 59 | .exec(cb); 60 | }, 61 | findById: function(id, cb) { 62 | return this 63 | .findOne({ 64 | _id: id 65 | }) 66 | .exec(cb); 67 | } 68 | } 69 | 70 | module.exports = UserSchema; -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | /*(c) Copyright 2014 Kvkens. All Rights Reserved. */ 2 | var express = require("express"); 3 | var path = require("path"); 4 | var mongoose = require("mongoose"); 5 | var port = process.env.PORT || 3000; 6 | var app = express(); 7 | var dbUrl = "mongodb://localhost/imooc"; 8 | mongoose.connect(dbUrl); 9 | 10 | app.set("views", "./views/pages"); 11 | app.set("view engine", "jade"); 12 | var bodyParser = require('body-parser'); 13 | var session = require('express-session'); //如果要使用session,需要单独包含这个模块 14 | var cookieParser = require('cookie-parser'); //如果要使用cookie,需要显式包含这个模块 15 | var bcrypt = require("bcrypt"); //bcrypt加密引用 16 | var mongoStore = require("connect-mongo")(session); //express4 的写法详见参考connect-mongo API 17 | var logger = require('morgan'); 18 | app.use(bodyParser.urlencoded({ 19 | extended: true 20 | })); 21 | app.use(cookieParser()); 22 | app.use(session({ 23 | name: "kvkens", 24 | secret: "imooc", 25 | resave: false, 26 | saveUninitialized: false, 27 | store: new mongoStore({ 28 | url: dbUrl, 29 | auto_reconnect: true,//issue 推荐解决方法 30 | collection: "sessions" 31 | }) 32 | })); 33 | 34 | if("development" === app.get("env")){ 35 | app.set("showStackError",true); 36 | app.use(logger(":method :url :status")); 37 | app.locals.pretty = true; 38 | mongoose.set("debug",true); 39 | } 40 | 41 | require("./config/routes")(app); 42 | app.use(express.static(path.join(__dirname, "./public"))); 43 | app.locals.moment = require("moment"); 44 | app.listen(port); 45 | 46 | console.log("imooc started on port " + port); -------------------------------------------------------------------------------- /views/pages/admin.jade: -------------------------------------------------------------------------------- 1 | extends ../layout 2 | 3 | block content 4 | .container 5 | .row(style="margin-bottom:70px") 6 | form.form-horizontal(method="post",action="/admin/movie/new") 7 | input(type="hidden",name="movie[_id]",value="#{movie._id}") 8 | .form-group 9 | label.col-sm-2.control-label(for="inputTitle") 电影名字 10 | .col-sm-10 11 | input#inputTitle.form-control(type="text",name="movie[title]",value="#{movie.title}") 12 | .form-group 13 | label.col-sm-2.control-label(for="inputDoctor") 导演 14 | .col-sm-10 15 | input#inputDoctor.form-control(type="text",name="movie[doctor]",value="#{movie.doctor}") 16 | .form-group 17 | label.col-sm-2.control-label(for="inputCountry") 国家 18 | .col-sm-10 19 | input#inputCountry.form-control(type="text",name="movie[country]",value="#{movie.country}") 20 | .form-group 21 | label.col-sm-2.control-label(for="inputLanguage") 语言 22 | .col-sm-10 23 | input#inputLanguage.form-control(type="text",name="movie[language]",value="#{movie.language}") 24 | .form-group 25 | label.col-sm-2.control-label(for="inputYear") 上映年份 26 | .col-sm-10 27 | input#inputYear.form-control(type="text",name="movie[year]",value="#{movie.year}") 28 | .form-group 29 | label.col-sm-2.control-label(for="inputPoster") 海报地址 30 | .col-sm-10 31 | input#inputPoster.form-control(type="text",name="movie[poster]",value="#{movie.poster}") 32 | .form-group 33 | label.col-sm-2.control-label(for="inputFlash") 片源地址 34 | .col-sm-10 35 | input#inputFlash.form-control(type="text",name="movie[flash]",value="#{movie.flash}") 36 | .form-group 37 | label.col-sm-2.control-label(for="inputSummary") 简介 38 | .col-sm-10 39 | textarea#inputSummary.form-control(name="movie[summary]") #{movie.summary} 40 | .form-group 41 | .col-sm-offset-2.col-sm-10 42 | button.btn.btn-default(type="submit") 录入 -------------------------------------------------------------------------------- /views/includes/header.jade: -------------------------------------------------------------------------------- 1 | .container 2 | .row 3 | .page-header 4 | h1.alert.alert-info= title 5 | small.label.label-success 慕课网电影天堂  - www.imyy.org 6 | .navbar.navbar-default.navbar-fixed-bottom 7 | .container 8 | .navbar-header 9 | a.navbar-brand(href="/") 重度科幻迷 10 | if user 11 | p.navbar-text.navbar-right 12 | span 欢迎您:[#{user.name}] 13 | span  |  14 | a.navbar-link(href="/logout") 登出 15 | else 16 | p.navbar-text.navbar-right 17 | a.navbar-link(href="#",data-toggle="modal",data-target="#signupModal") 注册 18 | span  |  19 | a.navbar-link(href="#",data-toggle="modal",data-target="#signinModal") 登录 20 | #signupModal.modal.fade 21 | .modal-dialog 22 | .modal-content 23 | form(method="POST",action="/user/signup") 24 | .modal-header 注册 25 | .modal-body 26 | .form-group 27 | label(for="signupName") 用户名 28 | input#signupName.form-control(name="user[name]",type="text") 29 | .form-group 30 | label(for="signupPassword") 密码 31 | input#Password.form-control(name="user[password]",type="password") 32 | .modal-footer 33 | button.btn.btn-danger(type="button",data-dismiss="modal") 关闭 34 | button.btn.btn-success(type="submit") 提交 35 | 36 | #signinModal.modal.fade 37 | .modal-dialog 38 | .modal-content 39 | form(method="POST",action="/user/signin") 40 | .modal-header 登录 41 | .modal-body 42 | .form-group 43 | label(for="signinName") 用户名 44 | input#signinName.form-control(name="user[name]",type="text") 45 | .form-group 46 | label(for="signinPassword") 密码 47 | input#signinPassword.form-control(name="user[password]",type="password") 48 | .modal-footer 49 | button.btn.btn-danger(type="button",data-dismiss="modal") 关闭 50 | button.btn.btn-success(type="submit") 登录 -------------------------------------------------------------------------------- /config/routes.js: -------------------------------------------------------------------------------- 1 | /*(c) Copyright 2014 Kvkens. All Rights Reserved. */ 2 | var Movie = require("../models/movie"); 3 | var User = require("../models/user"); 4 | var _ = require("underscore"); 5 | module.exports = function(app) { 6 | app.use(function(req, res, next) { 7 | var _user = req.session.user; 8 | if (_user) { 9 | app.locals.user = _user; 10 | } 11 | return next(); 12 | }); 13 | // index page 14 | app.get("/", function(req, res) { 15 | console.log(req.session.user); 16 | Movie.fetch(function(err, movies) { 17 | if (err) { 18 | console.log(err); 19 | } 20 | res.render("index", { 21 | title: "imooc 首页", 22 | movies: movies 23 | }); 24 | }); 25 | 26 | }); 27 | 28 | // detail page 29 | app.get("/movie/:id", function(req, res) { 30 | var id = req.params.id; 31 | Movie.findById(id, function(err, movie) { 32 | res.render("detail", { 33 | title: "imooc:" + movie.title, 34 | movie: movie 35 | }); 36 | }); 37 | }); 38 | 39 | // admin page 40 | app.get("/admin/movie", function(req, res) { 41 | res.render("admin", { 42 | title: "imooc 后台录入页", 43 | movie: { 44 | doctor: '', 45 | country: '', 46 | title: '', 47 | year: '', 48 | poster: '', 49 | language: '', 50 | flash: '', 51 | summary: '' 52 | } 53 | }); 54 | }); 55 | app.get('/admin/update/:id', function(req, res) { 56 | var id = req.params.id; 57 | 58 | if (id) { 59 | Movie.findById(id, function(err, movie) { 60 | res.render('admin', { 61 | title: 'imooc 后台更新页面 --- ' + movie.title, 62 | movie: movie 63 | }); 64 | }); 65 | } 66 | }); 67 | // admin post movie 68 | app.post("/admin/movie/new", function(req, res) { 69 | var id = req.body.movie._id; 70 | console.log(id); 71 | var movieObj = req.body.movie; 72 | var _movie; 73 | if (id !== "undefined") { 74 | Movie.findById(id, function(err, movie) { 75 | if (err) { 76 | console.log(err); 77 | } 78 | 79 | _movie = _.extend(movie, movieObj); 80 | _movie.save(function(err, movie) { 81 | if (err) { 82 | console.log(err); 83 | } 84 | res.redirect("/movie/" + movie._id); 85 | }); 86 | }); 87 | } else { 88 | _movie = new Movie({ 89 | doctor: movieObj.doctor, 90 | title: movieObj.title, 91 | country: movieObj.country, 92 | language: movieObj.language, 93 | year: movieObj.year, 94 | poster: movieObj.poster, 95 | summary: movieObj.summary, 96 | flash: movieObj.flash 97 | }); 98 | 99 | _movie.save(function(err, movie) { 100 | if (err) { 101 | console.log(err); 102 | } 103 | res.redirect("/movie/" + movie._id); 104 | }); 105 | } 106 | }); 107 | 108 | // list page 109 | app.get("/admin/list", function(req, res) { 110 | Movie.fetch(function(err, movies) { 111 | if (err) { 112 | console.log(err) 113 | } 114 | res.render('list', { 115 | title: 'imooc 列表页', 116 | movies: movies 117 | }) 118 | }) 119 | }); 120 | // user list page 121 | app.get("/admin/userlist", function(req, res) { 122 | User.fetch(function(err, users) { 123 | if (err) { 124 | console.log(err) 125 | } 126 | res.render('userlist', { 127 | title: 'imooc 管理员列表', 128 | users: users 129 | }) 130 | }) 131 | }); 132 | //list delete movie 133 | app.delete("/admin/list", function(req, res) { 134 | var id = req.query.id; 135 | if (id) { 136 | Movie.remove({ 137 | _id: id 138 | }, function(err, movie) { 139 | if (err) { 140 | console.log(err); 141 | } else { 142 | res.json({ 143 | success: 1 144 | }); 145 | } 146 | }); 147 | } 148 | }); 149 | 150 | //signup 151 | app.post("/user/signup", function(req, res) { 152 | var _user = req.body.user; 153 | //var _user = req.params.user; 154 | //var _user = req.query.user; 155 | User.findOne({ 156 | name: _user.name 157 | }, function(err, user) { 158 | console.log(user); 159 | if (err) { 160 | console.log(err); 161 | } 162 | if (user) { 163 | return res.redirect("/"); 164 | } else { 165 | var user = new User(_user); 166 | user.save(function(err, user) { 167 | if (err) { 168 | console.log(err); 169 | } 170 | res.redirect("/admin/userlist"); 171 | }); 172 | } 173 | }); 174 | }); 175 | 176 | //signin 177 | app.post("/user/signin", function(req, res) { 178 | var _user = req.body.user; 179 | var name = _user.name; 180 | var password = _user.password; 181 | User.findOne({ 182 | name: name 183 | }, function(err, user) { 184 | if (err) { 185 | console.log(err); 186 | } 187 | if (!user) { 188 | return res.redirect("/"); 189 | } 190 | 191 | user.comparePassword(password, function(err, isMatch) { 192 | if (err) { 193 | console.log(err); 194 | } 195 | if (isMatch) { 196 | req.session.user = user; 197 | return res.redirect("/"); 198 | } else { 199 | return res.redirect("/"); 200 | } 201 | }); 202 | }); 203 | }); 204 | 205 | //logout 206 | app.get("/logout", function(req, res) { 207 | delete req.session.user; 208 | delete app.locals.user; 209 | res.redirect("/"); 210 | }); 211 | } --------------------------------------------------------------------------------