├── .gitignore ├── README.md ├── app.js ├── config.coffee ├── config.js ├── controlers ├── adminCtr.coffee ├── adminCtr.js ├── departmentCtr.coffee ├── departmentCtr.js ├── installCtr.coffee ├── installCtr.js ├── reportCtr.coffee ├── reportCtr.js ├── userCtr.coffee └── userCtr.js ├── models ├── departmentsModel.coffee ├── departmentsModel.js ├── reportModel.coffee ├── reportModel.js ├── usersModel.coffee └── usersModel.js ├── other&this └── db-info.md ├── package.json ├── public ├── css │ ├── adminDepartment.css │ ├── adminDepartment.less │ ├── adminGroup.css │ ├── adminGroup.less │ ├── adminStyle.css │ ├── adminStyle.less │ ├── adminUser.css │ ├── adminUser.less │ ├── bootstrap.min.css │ ├── header.css │ ├── header.less │ ├── pepper-grinder │ │ ├── images │ │ │ ├── animated-overlay.gif │ │ │ ├── ui-bg_diagonal-maze_20_6e4f1c_10x10.png │ │ │ ├── ui-bg_diagonal-maze_40_000000_10x10.png │ │ │ ├── ui-bg_fine-grain_10_eceadf_60x60.png │ │ │ ├── ui-bg_fine-grain_10_f8f7f6_60x60.png │ │ │ ├── ui-bg_fine-grain_15_eceadf_60x60.png │ │ │ ├── ui-bg_fine-grain_15_f7f3de_60x60.png │ │ │ ├── ui-bg_fine-grain_15_ffffff_60x60.png │ │ │ ├── ui-bg_fine-grain_65_654b24_60x60.png │ │ │ ├── ui-bg_fine-grain_68_b83400_60x60.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_3572ac_256x240.png │ │ │ ├── ui-icons_8c291d_256x240.png │ │ │ ├── ui-icons_b83400_256x240.png │ │ │ ├── ui-icons_fbdb93_256x240.png │ │ │ └── ui-icons_ffffff_256x240.png │ │ ├── jquery-ui-1.10.3.custom.css │ │ └── jquery-ui-1.10.3.custom.min.css │ ├── reportStyle.css │ ├── reportStyle.less │ ├── style.css │ ├── style.less │ ├── treeList.css │ └── treeList.less ├── img │ ├── glyphicons-halflings-white.png │ └── glyphicons-halflings.png ├── js │ ├── ReportModel.coffee │ ├── ReportModel.js │ ├── TreeList.coffee │ ├── TreeList.js │ ├── admin │ │ ├── DepartmentUserMode.coffee │ │ ├── DepartmentUserMode.js │ │ ├── admingroup.coffee │ │ ├── admingroup.js │ │ ├── department.coffee │ │ ├── department.js │ │ ├── users.coffee │ │ └── users.js │ ├── bootstrap.min.js │ ├── cs.js │ ├── jquery-1.9.1.min.js │ ├── jquery-ui-1.10.3.custom.min.js │ ├── jquery.mobile-1.3.1.min.js │ ├── knockout-2.2.1.js │ ├── login.coffee │ ├── login.js │ ├── password.coffee │ ├── password.js │ ├── reportBase.coffee │ ├── reportBase.js │ ├── require.js │ ├── showReports.coffee │ ├── showReports.js │ ├── subordinateReports.coffee │ ├── subordinateReports.js │ ├── validator-min.js │ ├── validator.js │ ├── writeReport.coffee │ └── writeReport.js ├── mobile │ ├── css │ │ ├── images │ │ │ ├── ajax-loader.gif │ │ │ ├── icons-18-black.png │ │ │ ├── icons-18-white.png │ │ │ ├── icons-36-black.png │ │ │ └── icons-36-white.png │ │ ├── jquery.mobile-1.3.1.min.css │ │ ├── reportStyle.css │ │ └── reportStyle.less │ └── js │ │ ├── Model.coffee │ │ ├── Model.js │ │ ├── main.coffee │ │ └── main.js └── ueditor │ ├── dialogs │ ├── highlightcode │ │ └── highlightcode.html │ ├── internal.js │ ├── link │ │ └── link.html │ ├── spechars │ │ ├── spechars.html │ │ └── spechars.js │ ├── table │ │ ├── dragicon.png │ │ ├── edittable.css │ │ ├── edittable.html │ │ ├── edittable.js │ │ ├── edittd.html │ │ └── edittip.html │ └── tangram.js │ ├── editor_all.js │ ├── editor_all_min.js │ ├── editor_config.js │ ├── lang │ ├── en │ │ ├── en.js │ │ └── images │ │ │ ├── addimage.png │ │ │ ├── alldeletebtnhoverskin.png │ │ │ ├── alldeletebtnupskin.png │ │ │ ├── background.png │ │ │ ├── button.png │ │ │ ├── copy.png │ │ │ ├── deletedisable.png │ │ │ ├── deleteenable.png │ │ │ ├── imglabel.png │ │ │ ├── listbackground.png │ │ │ ├── localimage.png │ │ │ ├── music.png │ │ │ ├── rotateleftdisable.png │ │ │ ├── rotateleftenable.png │ │ │ ├── rotaterightdisable.png │ │ │ ├── rotaterightenable.png │ │ │ └── upload.png │ └── zh-cn │ │ ├── images │ │ ├── copy.png │ │ ├── imglabel.png │ │ ├── localimage.png │ │ ├── music.png │ │ └── upload.png │ │ └── zh-cn.js │ ├── themes │ ├── default │ │ ├── css │ │ │ └── ueditor.css │ │ ├── dialogbase.css │ │ └── images │ │ │ ├── anchor.gif │ │ │ ├── arrow.png │ │ │ ├── button-bg.gif │ │ │ ├── cancelbutton.gif │ │ │ ├── cursor_h.gif │ │ │ ├── cursor_h.png │ │ │ ├── cursor_v.gif │ │ │ ├── cursor_v.png │ │ │ ├── dialog-title-bg.png │ │ │ ├── filescan.png │ │ │ ├── highlighted.gif │ │ │ ├── icons-all.gif │ │ │ ├── icons.gif │ │ │ ├── icons.png │ │ │ ├── lock.gif │ │ │ ├── neweditor-tab-bg.png │ │ │ ├── pagebreak.gif │ │ │ ├── scale.png │ │ │ ├── spacer.gif │ │ │ ├── sparator_v.png │ │ │ ├── toolbar_bg.png │ │ │ ├── unhighlighted.gif │ │ │ ├── upload.png │ │ │ ├── videologo.gif │ │ │ ├── word.gif │ │ │ └── wordpaste.png │ └── iframe.css │ └── third-party │ └── SyntaxHighlighter │ ├── shCore.js │ └── shCoreDefault.css ├── routes ├── routeProfile.coffee └── routeProfile.js ├── utils.coffee ├── utils.js ├── views ├── admin │ ├── admingroup.hbs │ ├── department.hbs │ └── users.hbs ├── install.hbs ├── login.hbs ├── mobile │ ├── layout.hbs │ ├── login.hbs │ ├── password.hbs │ ├── show.hbs │ ├── showsubordinate.hbs │ └── write.hbs ├── password.hbs ├── show.hbs ├── showsubordinate.hbs └── write.hbs └── vo ├── Response.coffee └── Response.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | *.log 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 一天日报是一个开源的写日报工具,该工具简单易用,包含网页和手机版。使用该日报工具可以随时随地使用手机或者电脑写和浏览日报. 2 | site: http://waltershe.github.io/ribao/ -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies. 3 | */ 4 | 5 | var express = require('express') 6 | , http = require('http') 7 | , connect = require('connect') 8 | , routeProfile = require('./routes/routeProfile') 9 | , path = require('path') 10 | , redis = require("redis") 11 | , redisConfig = require('./config') 12 | , session = require('express-session') 13 | , redisStore = require('connect-redis')(session) 14 | , appport = redisConfig.app.port 15 | , sessiondbconfig = redisConfig.sessiondb; 16 | 17 | var app = express(); 18 | var redisClient = redis.createClient(redisConfig.db.port,redisConfig.db.host); 19 | redisClient.on("error", function(err) { 20 | console.log(err); 21 | }); 22 | 23 | // all environments 24 | app.set('port', appport || process.env.PORT || 3000); 25 | app.set('views', __dirname + '/views'); 26 | app.set('view engine', 'hbs'); 27 | app.use(require('morgan')('dev')); 28 | app.use(require('compression')()); 29 | app.use(require('body-parser')()); 30 | app.use(require('method-override')()); 31 | app.use(require('cookie-parser')()); 32 | app.use(session({ store: new redisStore({host:sessiondbconfig.host, port:sessiondbconfig.port, pass:sessiondbconfig.pass, db:sessiondbconfig.db, prefix:'sess', ttl:3600}), secret: 'iamwaltershe' })); 33 | //app.use(app.router); 34 | app.use(express.static(path.join(__dirname, 'public'))); 35 | 36 | // development only 37 | if ('development' == app.get('env')) { 38 | app.use(require('errorhandler')()); 39 | } 40 | 41 | routeProfile.createRoutes(app); 42 | 43 | http.createServer(app).listen(app.get('port'), function(){ 44 | console.log('Express server listening on port ' + app.get('port')); 45 | }); 46 | -------------------------------------------------------------------------------- /config.coffee: -------------------------------------------------------------------------------- 1 | 2 | exports.db = 3 | host: "127.0.0.1" 4 | port: 6379 5 | db: 0 #Database index to use 6 | pass:null 7 | 8 | exports.sessiondb = 9 | host: "127.0.0.1" 10 | port: 6379 11 | db: 1 #Database index to use 12 | pass:null 13 | 14 | exports.app = 15 | port: 3000 16 | 17 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | 4 | exports.db = { 5 | host: "127.0.0.1", 6 | port: 6379, 7 | db: 0, 8 | pass: null 9 | }; 10 | 11 | exports.sessiondb = { 12 | host: "127.0.0.1", 13 | port: 6379, 14 | db: 1, 15 | pass: null 16 | }; 17 | 18 | exports.app = { 19 | port: 3000 20 | }; 21 | 22 | }).call(this); 23 | -------------------------------------------------------------------------------- /controlers/adminCtr.coffee: -------------------------------------------------------------------------------- 1 | utils = require('../utils') 2 | 3 | exports.index = (req, res) -> 4 | return unless utils.authenticateAdmin(req,res) 5 | res.render("admin/department") 6 | 7 | exports.usersIndex = (req, res) -> 8 | return unless utils.authenticateAdmin(req,res) 9 | res.render("admin/users") 10 | 11 | exports.admingroupIndex = (req, res) -> 12 | return unless utils.authenticateAdmin(req,res) 13 | res.render("admin/admingroup") 14 | 15 | -------------------------------------------------------------------------------- /controlers/adminCtr.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var utils; 4 | 5 | utils = require('../utils'); 6 | 7 | exports.index = function(req, res) { 8 | if (!utils.authenticateAdmin(req, res)) { 9 | return; 10 | } 11 | return res.render("admin/department"); 12 | }; 13 | 14 | exports.usersIndex = function(req, res) { 15 | if (!utils.authenticateAdmin(req, res)) { 16 | return; 17 | } 18 | return res.render("admin/users"); 19 | }; 20 | 21 | exports.admingroupIndex = function(req, res) { 22 | if (!utils.authenticateAdmin(req, res)) { 23 | return; 24 | } 25 | return res.render("admin/admingroup"); 26 | }; 27 | 28 | }).call(this); 29 | -------------------------------------------------------------------------------- /controlers/departmentCtr.coffee: -------------------------------------------------------------------------------- 1 | crypto = require('crypto'); 2 | check = require('validator').check 3 | utils = require('../utils') 4 | departmentModel = require('../models/departmentsModel') 5 | {Response} = require('../vo/Response') 6 | 7 | 8 | #创建一个新部门 9 | exports.createDepartment = (req, res) -> 10 | return unless utils.authenticateAdmin(req,res) 11 | 12 | departmentName = req.body.departmentName 13 | parentId = req.body.pid 14 | try 15 | check(departmentName, "部门名称不能为空").notEmpty().notContains(":") 16 | departmentModel.createDepartment(departmentName, parentId, (response)-> 17 | res.send(response)) 18 | catch error 19 | errorMessage = error.message 20 | res.send(new Response(0, errorMessage)) 21 | 22 | #删除部门 23 | exports.removeDepartment = (req, res) -> 24 | return unless utils.authenticateAdmin(req,res) 25 | 26 | departmentId = req.body.departmentId 27 | departmentModel.removeDepartment(departmentId, (response)-> 28 | res.send(response)) 29 | 30 | #更新部门 31 | exports.updateDepartment = (req, res) -> 32 | return unless utils.authenticateAdmin(req,res) 33 | 34 | departmentId = req.body.departmentId 35 | departmentName = req.body.departmentName 36 | parentId = req.body.pid 37 | try 38 | check(departmentName, "部门名称不能为空").notEmpty().notContains(":") 39 | departmentModel.updateDepartment(departmentId, departmentName, parentId, (response)-> 40 | res.send(response)) 41 | catch error 42 | errorMessage = error.message 43 | res.send(new Response(0,errorMessage)) 44 | 45 | #获取所有部门 46 | exports.getAllDepartments = (req, res) -> 47 | departmentModel.getAllDepartments((response)-> 48 | res.send(response)) 49 | -------------------------------------------------------------------------------- /controlers/departmentCtr.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var Response, check, crypto, departmentModel, utils; 3 | 4 | crypto = require('crypto'); 5 | 6 | check = require('validator').check; 7 | 8 | utils = require('../utils'); 9 | 10 | departmentModel = require('../models/departmentsModel'); 11 | 12 | Response = require('../vo/Response').Response; 13 | 14 | exports.createDepartment = function(req, res) { 15 | var departmentName, error, errorMessage, parentId; 16 | if (!utils.authenticateAdmin(req, res)) { 17 | return; 18 | } 19 | departmentName = req.body.departmentName; 20 | parentId = req.body.pid; 21 | try { 22 | check(departmentName, "部门名称不能为空").notEmpty().notContains(":"); 23 | return departmentModel.createDepartment(departmentName, parentId, function(response) { 24 | return res.send(response); 25 | }); 26 | } catch (_error) { 27 | error = _error; 28 | errorMessage = error.message; 29 | return res.send(new Response(0, errorMessage)); 30 | } 31 | }; 32 | 33 | exports.removeDepartment = function(req, res) { 34 | var departmentId; 35 | if (!utils.authenticateAdmin(req, res)) { 36 | return; 37 | } 38 | departmentId = req.body.departmentId; 39 | return departmentModel.removeDepartment(departmentId, function(response) { 40 | return res.send(response); 41 | }); 42 | }; 43 | 44 | exports.updateDepartment = function(req, res) { 45 | var departmentId, departmentName, error, errorMessage, parentId; 46 | if (!utils.authenticateAdmin(req, res)) { 47 | return; 48 | } 49 | departmentId = req.body.departmentId; 50 | departmentName = req.body.departmentName; 51 | parentId = req.body.pid; 52 | try { 53 | check(departmentName, "部门名称不能为空").notEmpty().notContains(":"); 54 | return departmentModel.updateDepartment(departmentId, departmentName, parentId, function(response) { 55 | return res.send(response); 56 | }); 57 | } catch (_error) { 58 | error = _error; 59 | errorMessage = error.message; 60 | return res.send(new Response(0, errorMessage)); 61 | } 62 | }; 63 | 64 | exports.getAllDepartments = function(req, res) { 65 | return departmentModel.getAllDepartments(function(response) { 66 | return res.send(response); 67 | }); 68 | }; 69 | 70 | }).call(this); 71 | -------------------------------------------------------------------------------- /controlers/installCtr.coffee: -------------------------------------------------------------------------------- 1 | crypto = require('crypto') 2 | userModel = require('../models/usersModel') 3 | 4 | exports.install = (req, res) -> 5 | userName = "admin" 6 | password = "1234567" 7 | hashedPassword = crypto.createHash("sha1").update(password).digest('hex') 8 | userModel.createDefaultAdmin(userName, hashedPassword, (response)-> 9 | res.render("install")) 10 | -------------------------------------------------------------------------------- /controlers/installCtr.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var crypto, userModel; 4 | 5 | crypto = require('crypto'); 6 | 7 | userModel = require('../models/usersModel'); 8 | 9 | exports.install = function(req, res) { 10 | var hashedPassword, password, userName; 11 | userName = "admin"; 12 | password = "1234567"; 13 | hashedPassword = crypto.createHash("sha1").update(password).digest('hex'); 14 | return userModel.createDefaultAdmin(userName, hashedPassword, function(response) { 15 | return res.render("install"); 16 | }); 17 | }; 18 | 19 | }).call(this); 20 | -------------------------------------------------------------------------------- /controlers/reportCtr.coffee: -------------------------------------------------------------------------------- 1 | crypto = require('crypto'); 2 | check = require('validator').check 3 | reportModel = require('../models/reportModel') 4 | userModel = require('../models/usersModel') 5 | utils = require('../utils') 6 | {Response} = require('../vo/Response') 7 | 8 | exports.index = (req, res) -> 9 | return unless utils.authenticateUser(req,res) 10 | res.redirect("/show") 11 | 12 | exports.writeIndex = (req, res) -> 13 | return unless utils.authenticateUser(req,res) 14 | showPage(req, res, "write") 15 | 16 | exports.settingMobile = (req, res) -> 17 | return unless utils.authenticateUser(req,res) 18 | res.render("mobile/settings", {'title':"设置", layout:"mobile/layout.hbs"}) 19 | 20 | exports.writeIndexMobile = (req, res) -> 21 | return unless utils.authenticateUser(req,res) 22 | showPage(req, res, "mobile/write", {'title':"写日报", layout:"mobile/layout.hbs", "currentDateStr": getDateStr(new Date())}) 23 | 24 | getDateStr = (date)-> 25 | today = new Date() 26 | year = date.getFullYear() 27 | month = date.getMonth() + 1 28 | date = date.getDate() 29 | return "#{year}-#{month}-#{date}" 30 | 31 | exports.write = (req, res) -> 32 | return unless utils.authenticateUser(req,res) 33 | userId = req.session.userId 34 | dateStr = req.body.date 35 | content = req.body.content 36 | 37 | try 38 | check(dateStr).notEmpty() 39 | check(content).notEmpty() 40 | [year, months, date] = dateStr.split("-") 41 | #console.log "#{year}-#{months}-#{date}" 42 | check(year).notNull().isNumeric().len(4,4) 43 | check(months).notNull().isNumeric().len(1,2) 44 | check(date).notNull().isNumeric().len(1,2) 45 | reportModel.createReport(userId, content, dateStr, (response)-> 46 | res.send(response)) 47 | catch error 48 | res.send(new Response(0,"日期格式不正确或者内容为空")) 49 | 50 | exports.showIndex = (req, res) -> 51 | return unless utils.authenticateUser(req,res) 52 | showPage(req, res, "show") 53 | 54 | exports.showIndexMobile = (req, res) -> 55 | return unless utils.authenticateUser(req,res) 56 | showPage(req, res, "mobile/show", {'title':"我的日报", layout:"mobile/layout.hbs"}) 57 | 58 | showPage = (req, res, pageTitle, data=null) -> 59 | userId = req.session.userId 60 | data = {} unless data 61 | data["hasSubordinate"] = false 62 | data["isLoginUser"] = utils.isLoginUser(req) 63 | data["isAdmin"] = utils.isAdmin(req) 64 | userModel.hasSubordinate(userId, (result)-> 65 | if result 66 | data["hasSubordinate"] = true 67 | res.render(pageTitle, data)) 68 | 69 | exports.showsubordinateIndex = (req, res) -> 70 | return unless utils.authenticateUser(req,res) 71 | userId = req.session.userId 72 | userModel.hasSubordinate(userId, (result)-> 73 | if result 74 | res.render("showsubordinate", {hasSubordinate:true, isLoginUser:utils.isLoginUser(req),isAdmin:utils.isAdmin(req)}) 75 | else 76 | res.send(new Response(0,'您还没有下属,不需要访问该页面'))) 77 | 78 | exports.subordinateIndexMobile = (req, res) -> 79 | return unless utils.authenticateUser(req,res) 80 | userId = req.session.userId 81 | userModel.hasSubordinate(userId, (result)-> 82 | if result 83 | res.render("mobile/showsubordinate", {title:"下属日报", layout:"mobile/layout.hbs", hasSubordinate:true, isLoginUser:utils.isLoginUser(req),isAdmin:utils.isAdmin(req)}) 84 | else 85 | res.send(new Response(0,'您还没有下属,不需要访问该页面'))) 86 | 87 | 88 | exports.getReports = (req, res) -> 89 | return unless utils.authenticateUser(req,res) 90 | 91 | #第几页 92 | page = req.body.page 93 | userId = req.body.userId 94 | #没有userId表示访问自己的日报 95 | userId = req.session.userId unless userId 96 | 97 | #每页显示条数 98 | numOfPage = req.body.numOfPage 99 | try 100 | check(page).isNumeric().min(1) 101 | check(page).isNumeric().min(1) 102 | reportModel.getReports(userId, page, numOfPage, (response)-> 103 | res.send(response)) 104 | catch error 105 | res.send(new Response(0,"页数和每页显示条数为非负数")) 106 | 107 | exports.getReportNum = (req, res) -> 108 | return unless utils.authenticateUser(req,res) 109 | userId = req.body.userId 110 | #没有userId表示访问自己的日报 111 | userId = req.session.userId unless userId 112 | 113 | reportModel.getReportNum(userId, (response)-> 114 | res.send(response)) 115 | 116 | exports.delete = (req, res) -> 117 | return unless utils.authenticateUser(req,res) 118 | userId = req.session.userId 119 | reportId = req.body.reportId 120 | reportModel.deleteReport(userId, reportId, (response)-> 121 | res.send(response)) 122 | 123 | 124 | exports.getSubordinateUserAndDepartment = (req, res) -> 125 | return unless utils.authenticateUser(req,res) 126 | userId = req.session.userId 127 | reportModel.getSubordinateUserAndDepartment(userId, (response)-> 128 | res.send(response)) -------------------------------------------------------------------------------- /controlers/userCtr.coffee: -------------------------------------------------------------------------------- 1 | crypto = require('crypto') 2 | check = require('validator').check 3 | utils = require('../utils') 4 | userModel = require('../models/usersModel') 5 | {Response} = require('../vo/Response') 6 | 7 | exports.loginIndex = (req, res) -> 8 | res.render("login") 9 | 10 | exports.indexMobile = (req, res) -> 11 | if utils.isLoginUser(req) 12 | res.redirect('/m/write') 13 | else 14 | res.redirect('/m/login') 15 | 16 | exports.loginIndexMobile = (req, res) -> 17 | if utils.isLoginUser(req) 18 | res.redirect('/m/write') 19 | else 20 | res.render("mobile/login", {'title':"登录", layout:"mobile/layout.hbs"}) 21 | 22 | exports.login = (req, res) -> 23 | userName = req.body.userName 24 | password = req.body.password 25 | hashedPassword = crypto.createHash("sha1").update(password).digest('hex') 26 | userModel.getAllUsersWithPassword((response)-> 27 | return res.send(response) if response.state == 0 28 | users = response.data 29 | userId = null 30 | for key, value of users 31 | [id,property] = key.split(":") 32 | 33 | if (property == "user_name" and value == userName) 34 | userId = id 35 | break 36 | 37 | return res.send(new Response(1, "用户名:#{userName}不存在", 0)) unless userId 38 | #return res.render("login",{hasError:true, message:"用户名:#{userName}不存在"}) unless userId 39 | 40 | hasThisUser = false 41 | for key, value of users 42 | [id,property] = key.split(":") 43 | if (id == userId and property == "password" and value == hashedPassword) 44 | userId = id 45 | hasThisUser = true 46 | break 47 | #return res.render("login",{hasError:true, message:"密码错误"}) unless hasThisUser 48 | return res.send(new Response(1, "密码错误", 0)) unless hasThisUser 49 | #console.log "userName:#{userName}, userId:#{userId}" 50 | req.session.userId = userId 51 | 52 | userModel.getAdminIds((response)-> 53 | return res.send(new Response(1, "success", 1)) if response.state == 0 54 | ids = response.data 55 | 56 | for id in ids 57 | if id == userId 58 | req.session.isAdmin = 1 59 | break 60 | res.send(new Response(1, "success", 1)))) 61 | #return res.redirect("/show"))) 62 | 63 | exports.logout = (req, res) -> 64 | return unless utils.authenticateUser(req,res) 65 | req.session.destroy() 66 | res.redirect("/login") 67 | 68 | exports.logoutMobileIndex = (req, res) -> 69 | return unless utils.authenticateUser(req,res) 70 | req.session.destroy() 71 | res.render("mobile/login", {'title':"登录", layout:"mobile/layout.hbs"}) 72 | 73 | exports.passwordIndex = (req, res) -> 74 | return unless utils.authenticateUser(req,res) 75 | userId = req.session.userId 76 | userModel.hasSubordinate(userId, (result)-> 77 | data = {hasSubordinate: result, isLoginUser:utils.isLoginUser(req), isAdmin:utils.isAdmin(req)} 78 | res.render("password", data)) 79 | 80 | exports.passwordMobileIndex = (req, res) -> 81 | return unless utils.authenticateUser(req,res) 82 | userId = req.session.userId 83 | userModel.hasSubordinate(userId, (result)-> 84 | data = {hasSubordinate: result,'title':"修改密码", layout:"mobile/layout.hbs"} 85 | console.log data 86 | res.render("mobile/password", data)) 87 | 88 | exports.changePassword = (req, res) -> 89 | return unless utils.authenticateUser(req,res) 90 | 91 | userId = req.session.userId 92 | oldPassword = crypto.createHash("sha1").update(req.body.oldPassword).digest('hex') 93 | newPassword = crypto.createHash("sha1").update(req.body.newPassword).digest('hex') 94 | 95 | userModel.changePassword(userId, newPassword, oldPassword, (response)-> 96 | res.send(response)) 97 | 98 | 99 | exports.createUser = (req, res) -> 100 | return unless utils.authenticateAdmin(req,res) 101 | 102 | userName = req.body.userName 103 | password = req.body.password 104 | departmentId = req.body.departmentId; 105 | superiorId = req.body.superiorId; 106 | 107 | try 108 | check(userName, "字符长度为2-25").len(2,25) 109 | check(password, "字符长度为7-25").len(7,25) 110 | catch error 111 | errorMessage = error.message 112 | return res.send(new Response(0, errorMessage)) 113 | 114 | userModel.hasUser(userName, (response)-> 115 | return res.send(response) if response.state == 0 or response.data 116 | hashedPassword = crypto.createHash("sha1").update(password).digest('hex') 117 | userModel.createUser(userName, hashedPassword, departmentId, superiorId, (response)-> 118 | res.send(response))) 119 | 120 | exports.removeUser = (req, res) -> 121 | return unless utils.authenticateAdmin(req,res) 122 | userId = req.body.userId 123 | userModel.removeUser(userId, (response)-> 124 | res.send(response)) 125 | 126 | exports.updateUser = (req, res) -> 127 | return unless utils.authenticateAdmin(req,res) 128 | userId = req.body.userId 129 | userName = req.body.userName 130 | password = req.body.password 131 | departmentId = req.body.departmentId; 132 | superiorId = req.body.superiorId; 133 | 134 | try 135 | check(userName, "字符长度为6-25").len(6,25) 136 | hashedPassword = null 137 | hashedPassword = crypto.createHash("sha1").update(password).digest('hex') if password 138 | userModel.updateUser(userId, userName, hashedPassword, departmentId, superiorId, (response)-> 139 | res.send(response)) 140 | catch error 141 | res.send(new Response(0,error.errorMessage)) 142 | 143 | exports.getAllUsers = (req, res) -> 144 | userModel.getAllUsers((response)-> 145 | res.send(response)) 146 | 147 | exports.getAdmins = (req, res) -> 148 | return unless utils.authenticateAdmin(req,res) 149 | userModel.getAdminIds((response)-> 150 | res.send(response)) 151 | 152 | exports.setAdmin = (req, res) -> 153 | return unless utils.authenticateAdmin(req,res) 154 | userId = req.body.userId 155 | userModel.setAdmin(userId, (response)-> 156 | res.send(response)) 157 | 158 | exports.deleteAdmin = (req, res) -> 159 | return unless utils.authenticateAdmin(req,res) 160 | userId = req.body.userId 161 | userModel.deleteAdmin(userId, (response)-> 162 | res.send(response)) 163 | 164 | exports.hasUser = (req, res) -> 165 | userName = req.body.userName 166 | userModel.hasUser(userName, (response)-> 167 | res.send(response)) 168 | -------------------------------------------------------------------------------- /models/departmentsModel.coffee: -------------------------------------------------------------------------------- 1 | 2 | {Response} = require('../vo/Response') 3 | utils = require("../utils") 4 | 5 | exports.createDepartment = (departmentName, parentId, callback) -> 6 | client = utils.createClient() 7 | 8 | client.incr("next_department_id", (err, reply)-> 9 | return utils.showDBError(callback, client) if err 10 | 11 | client.hset("departments", "#{reply}:name", departmentName) 12 | result = {name:departmentName} 13 | 14 | #id 以字符串形式返回 15 | department = {name:departmentName, id:"#{reply}"} 16 | if parentId 17 | client.hset("departments", "#{reply}:pid", parentId) 18 | result["pid"] = parentId 19 | department["pid"] = parentId 20 | 21 | client.quit() 22 | 23 | callback(new Response(1,'success',department))) 24 | 25 | #删除部门 26 | exports.removeDepartment = (departmentId, callback) -> 27 | client = utils.createClient() 28 | client.hdel("departments", "#{departmentId}:name", "#{departmentId}:pid", (err, reply)-> 29 | return utils.showDBError(callback, client) if err 30 | client.hgetall("departments", (err, reply)-> 31 | return utils.showDBError(callback, client) if err 32 | newDepartments = {} 33 | for key, value of reply 34 | childOfKey = key.split(":") 35 | if childOfKey[1] == "pid" and value == departmentId 36 | client.hdel("departments", key) 37 | else 38 | newDepartments[key] = value 39 | 40 | client.hgetall("users", (err, users)-> 41 | return utils.showDBError(callback, client) if err 42 | for key, value of users 43 | childOfKey = key.split(":") 44 | if childOfKey[1] == "department_id" and value == departmentId 45 | client.hdel("users", key) 46 | callback(new Response(1,'success',newDepartments))))) 47 | 48 | #更新部门 49 | exports.updateDepartment = (departmentId, departmentName, parentId, callback)-> 50 | client = utils.createClient() 51 | 52 | replycallback = (err, reply)-> 53 | return utils.showDBError(callback, client) if err 54 | client.hgetall("departments", (err, reply)-> 55 | client.quit() 56 | callback(new Response(1,'success',reply))) 57 | 58 | if parentId 59 | client.hmset("departments", "#{departmentId}:name", departmentName, "#{departmentId}:pid", parentId, replycallback) 60 | else 61 | client.hset("departments", "#{departmentId}:name", departmentName, replycallback) 62 | 63 | exports.getAllDepartments = (callback) -> 64 | client = utils.createClient() 65 | client.hgetall("departments", (err, reply)-> 66 | return utils.showDBError(callback, client) if err 67 | client.quit() 68 | callback(new Response(1,'success',reply))) -------------------------------------------------------------------------------- /models/departmentsModel.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var Response, utils; 4 | 5 | Response = require('../vo/Response').Response; 6 | 7 | utils = require("../utils"); 8 | 9 | exports.createDepartment = function(departmentName, parentId, callback) { 10 | var client; 11 | client = utils.createClient(); 12 | return client.incr("next_department_id", function(err, reply) { 13 | var department, result; 14 | if (err) { 15 | return utils.showDBError(callback, client); 16 | } 17 | client.hset("departments", "" + reply + ":name", departmentName); 18 | result = { 19 | name: departmentName 20 | }; 21 | department = { 22 | name: departmentName, 23 | id: "" + reply 24 | }; 25 | if (parentId) { 26 | client.hset("departments", "" + reply + ":pid", parentId); 27 | result["pid"] = parentId; 28 | department["pid"] = parentId; 29 | } 30 | client.quit(); 31 | return callback(new Response(1, 'success', department)); 32 | }); 33 | }; 34 | 35 | exports.removeDepartment = function(departmentId, callback) { 36 | var client; 37 | client = utils.createClient(); 38 | return client.hdel("departments", "" + departmentId + ":name", "" + departmentId + ":pid", function(err, reply) { 39 | if (err) { 40 | return utils.showDBError(callback, client); 41 | } 42 | return client.hgetall("departments", function(err, reply) { 43 | var childOfKey, key, newDepartments, value; 44 | if (err) { 45 | return utils.showDBError(callback, client); 46 | } 47 | newDepartments = {}; 48 | for (key in reply) { 49 | value = reply[key]; 50 | childOfKey = key.split(":"); 51 | if (childOfKey[1] === "pid" && value === departmentId) { 52 | client.hdel("departments", key); 53 | } else { 54 | newDepartments[key] = value; 55 | } 56 | } 57 | return client.hgetall("users", function(err, users) { 58 | if (err) { 59 | return utils.showDBError(callback, client); 60 | } 61 | for (key in users) { 62 | value = users[key]; 63 | childOfKey = key.split(":"); 64 | if (childOfKey[1] === "department_id" && value === departmentId) { 65 | client.hdel("users", key); 66 | } 67 | } 68 | return callback(new Response(1, 'success', newDepartments)); 69 | }); 70 | }); 71 | }); 72 | }; 73 | 74 | exports.updateDepartment = function(departmentId, departmentName, parentId, callback) { 75 | var client, replycallback; 76 | client = utils.createClient(); 77 | replycallback = function(err, reply) { 78 | if (err) { 79 | return utils.showDBError(callback, client); 80 | } 81 | return client.hgetall("departments", function(err, reply) { 82 | client.quit(); 83 | return callback(new Response(1, 'success', reply)); 84 | }); 85 | }; 86 | if (parentId) { 87 | return client.hmset("departments", "" + departmentId + ":name", departmentName, "" + departmentId + ":pid", parentId, replycallback); 88 | } else { 89 | return client.hset("departments", "" + departmentId + ":name", departmentName, replycallback); 90 | } 91 | }; 92 | 93 | exports.getAllDepartments = function(callback) { 94 | var client; 95 | client = utils.createClient(); 96 | return client.hgetall("departments", function(err, reply) { 97 | if (err) { 98 | return utils.showDBError(callback, client); 99 | } 100 | client.quit(); 101 | return callback(new Response(1, 'success', reply)); 102 | }); 103 | }; 104 | 105 | }).call(this); 106 | -------------------------------------------------------------------------------- /other&this/db-info.md: -------------------------------------------------------------------------------- 1 | 安装redis数据库,安装完成后执行如下命令添加管理员账户: 2 | redis 127.0.0.1:6379> incr next_user_id 3 | (integer) 1 4 | 执行完该命令后表明 next_user_id 的值为1,然后执行如下命令(1:user_name和1:password中的1即为上一步执行incr next_user_id后的 5 | next_user_id的值) 6 | redis 127.0.0.1:6379> hmset users 1:user_name adminn 1:password 20eabe5d64b0e216796e834f52d61f 7 | OK 8 | 执行下面的命令将管理员adminn的id添加到管理员集合中 9 | redis 127.0.0.1:6379> sadd administrators 1 10 | (integer) 1 11 | 12 | 执行完以上命令后我们新增加了一个管理员账户adminn,密码为1234567。 13 | 14 | 下载源代码并解压缩到你的网站根目录,使用命令行工具进入该目录,然后输入 15 | $ npm install 16 | 安装依赖的库文件(确保你有管理员权限可以安装库文件),安装完成后,打开根目录下的config.js文件设置数据库信息和网站端口号。 17 | exports.db对象是数据库配置,exports.sessiondb是seesion数据库的数据库配置,seesion信息都存在redis数据库中,exports.app 对象中的 18 | port属性表示网站端口号,默认是80端口。配置设置好后执行 19 | $ node app.js 20 | 看到输出'Express server listening on port '80' 则表示服务器启动成功(这里的端口号80会和你在config.js中的exports.app.port保持一致) 21 | 进入网站主页你会看到登陆界面,输入管理员账户名 adminn,密码1234567则可以登陆成功。 进入管理后台设置部门,然后建立新用户,把建立好的用户名和密码告知 22 | 用户,用户使用用户名和密码登陆系统就可以写日报和查看日报了。 23 | 24 | 数据库字段说明: 25 | 26 | 用户数据: 27 | next_user_id (类型 string) 用户id值,每生成一个新用户该值通过incr方法递增1 28 | 29 | users (类型 hash) 所有注册用户信息存储在此 30 | 每个user包含如下key:value 31 | hmset("users", "#{userId}:user_name", userName, "#{userId}:password", password, "#{userId}:department_id", departmentId, "#{userId}:superior_id", superiorId) 32 | superiorId 为该用户直接上级用户的Id,如果没有直接上级,那么该 key 不存在 33 | 34 | 部门数据: 35 | next_department_id (类型 string) 部门id 的值,每生成一个新部门该值通过incr方法递增1 36 | 37 | departments (类型 hash) 所有部门信息存储在此 38 | 每个department包含如下key:value 39 | hset("departments", "#{departmentId}:name", departmentName, "#{departmentId}:pid", pid) 40 | pid 为该部门直接上级部门,如果没有直接上级部门,那么该 key 不存在 41 | 42 | 日报数据: 43 | next_report_id (类型 string) 日报id 的值,每生成一个新日报该值通过incr方法递增1 44 | 45 | userid:#{userId}:reportIds (类型 sorted sets) 46 | score 为日期数值 2004-04-09 转换为 20040409 47 | member 为report id 48 | 49 | userid:#{userId}:reports (类型 hash) 50 | #{reportId}:date为日报日期 #{reportId}:content为日报内容 51 | 52 | 管理员: 53 | administrators (类型 set) 存储的是用户id,管理员用户的id都在该集合中 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "one-day-daily-report-software-tool", 3 | "version": "0.9.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node app.js" 7 | }, 8 | "dependencies": { 9 | "express": "4.10.1", 10 | "connect": "3.3.2", 11 | "express-session": "1.9.1", 12 | "body-parser": "1.9.2", 13 | "method-override": "2.3.0", 14 | "cookie-parser": "1.3.3", 15 | "morgan": "1.4.1", 16 | "errorhandler": "1.2.2", 17 | "compression": "1.2.0", 18 | "hbs": "2.7.0", 19 | "redis": "0.12.1", 20 | "connect-redis": "2.1.0", 21 | "validator": "2.1.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /public/css/adminDepartment.css: -------------------------------------------------------------------------------- 1 | #department { 2 | width: 720px; 3 | } 4 | #department #newDepartment, 5 | #department #departmentTree { 6 | float: left; 7 | margin: 20px 20px 0 0; 8 | background-color: #fbeed5; 9 | border: 1px solid #E5E5E5; 10 | border-radius: 5px 5px 5px 5px; 11 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 12 | padding: 10px 16px; 13 | width: 300px; 14 | height: 350px; 15 | overflow: auto; 16 | color: #555; 17 | } 18 | #department #departmentTree { 19 | padding: 10px 16px 10px 0; 20 | } 21 | #department #newDepartment .submitBtn { 22 | margin-top: 20px; 23 | } 24 | #department #newDepartment.update { 25 | background-color: #FAA732; 26 | border: 1px solid #c58433; 27 | } 28 | -------------------------------------------------------------------------------- /public/css/adminDepartment.less: -------------------------------------------------------------------------------- 1 | 2 | #department { 3 | width:720px; 4 | #newDepartment, #departmentTree { 5 | float:left; 6 | margin:20px 20px 0 0; 7 | background-color: #fbeed5; 8 | border: 1px solid #E5E5E5; 9 | border-radius: 5px 5px 5px 5px; 10 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 11 | padding: 10px 16px; 12 | width: 300px; 13 | height:350px; 14 | overflow: auto; 15 | color: #555; 16 | } 17 | 18 | #departmentTree { 19 | padding: 10px 16px 10px 0; 20 | } 21 | 22 | #newDepartment { 23 | .submitBtn { 24 | margin-top: 20px; 25 | } 26 | 27 | &.update { 28 | background-color: #FAA732; 29 | border: 1px solid #c58433; 30 | } 31 | } 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /public/css/adminGroup.css: -------------------------------------------------------------------------------- 1 | body.admin-admingroup section.container { 2 | width: 720px; 3 | } 4 | body.admin-admingroup #newAdministrator, 5 | body.admin-admingroup #adminlist { 6 | float: left; 7 | margin: 20px 20px 0 0; 8 | background-color: #fbeed5; 9 | border: 1px solid #E5E5E5; 10 | border-radius: 5px 5px 5px 5px; 11 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 12 | padding: 10px 16px; 13 | width: 300px; 14 | height: 430px; 15 | overflow: auto; 16 | } 17 | body.admin-admingroup #adminlist a.delete { 18 | float: right; 19 | margin-right: 10px; 20 | } 21 | body.admin-admingroup #adminlist li { 22 | padding: 6px 0 10px 5px; 23 | } 24 | body.admin-admingroup #adminlist li.itemOver { 25 | background-color: #78b608; 26 | border-radius: 5px 5px 5px 5px; 27 | } 28 | -------------------------------------------------------------------------------- /public/css/adminGroup.less: -------------------------------------------------------------------------------- 1 | 2 | body.admin-admingroup { 3 | section.container { 4 | width: 720px; 5 | } 6 | #newAdministrator, #adminlist { 7 | float:left; 8 | margin:20px 20px 0 0; 9 | background-color: #fbeed5; 10 | border: 1px solid #E5E5E5; 11 | border-radius: 5px 5px 5px 5px; 12 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 13 | padding: 10px 16px; 14 | width: 300px; 15 | height:430px; 16 | overflow: auto; 17 | } 18 | 19 | #adminlist { 20 | a.delete { 21 | float:right; 22 | margin-right: 10px; 23 | } 24 | li { 25 | padding: 6px 0 10px 5px; 26 | 27 | &.itemOver { 28 | background-color: #78b608; 29 | border-radius: 5px 5px 5px 5px; 30 | } 31 | } 32 | } 33 | } 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /public/css/adminStyle.css: -------------------------------------------------------------------------------- 1 | .treeList ul { 2 | list-style: none; 3 | } 4 | .treeList li div { 5 | padding: 6px 0 10px 5px; 6 | } 7 | .treeList li div.treeListItemOver { 8 | background-color: #78b608; 9 | border-radius: 5px 5px 5px 5px; 10 | color: white; 11 | } 12 | .treeList li div.treeListItemSelected { 13 | background-color: #FAA732; 14 | border-radius: 5px 5px 5px 5px; 15 | color: white; 16 | } 17 | .treeList li div i { 18 | padding: 1px; 19 | } 20 | .treeList li div i.icon-minus, 21 | .treeList li div i.icon-plus { 22 | width: 12px; 23 | height: 12px; 24 | border: 1px solid #444444; 25 | margin-right: 5px; 26 | cursor: pointer; 27 | } 28 | .treeList li div span.delete, 29 | .treeList li div span.update, 30 | .treeList li div span.review { 31 | margin-right: 8px; 32 | font-size: 12px; 33 | height: 16px; 34 | padding: 2px 8px 4px 8px; 35 | float: right; 36 | } 37 | header { 38 | background-color: #FAFAFA; 39 | background-image: -moz-linear-gradient(center top, #ffffff, #f2f2f2); 40 | background-repeat: repeat-x; 41 | border: 1px solid #D4D4D4; 42 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); 43 | min-height: 40px; 44 | width: 100%; 45 | } 46 | header.navbar a.brand { 47 | padding-left: 40px; 48 | } 49 | #department { 50 | width: 720px; 51 | } 52 | #department #newDepartment, 53 | #department #departmentTree { 54 | float: left; 55 | margin: 20px 20px 0 0; 56 | background-color: #fbeed5; 57 | border: 1px solid #E5E5E5; 58 | border-radius: 5px 5px 5px 5px; 59 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 60 | padding: 10px 16px; 61 | width: 300px; 62 | height: 350px; 63 | overflow: auto; 64 | color: #555; 65 | } 66 | #department #departmentTree { 67 | padding: 10px 16px 10px 0; 68 | } 69 | #department #newDepartment .submitBtn { 70 | margin-top: 20px; 71 | } 72 | #department #newDepartment.update { 73 | background-color: #FAA732; 74 | border: 1px solid #c58433; 75 | } 76 | body.admin-users #users { 77 | width: 720px; 78 | } 79 | body.admin-users #users #newUser, 80 | body.admin-users #users #updateUser, 81 | body.admin-users #users #usersTree { 82 | float: left; 83 | margin: 20px 20px 0 0; 84 | background-color: #fbeed5; 85 | border: 1px solid #E5E5E5; 86 | border-radius: 5px 5px 5px 5px; 87 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 88 | padding: 10px 16px; 89 | width: 300px; 90 | height: 430px; 91 | overflow: auto; 92 | } 93 | body.admin-users #users #usersTree { 94 | padding: 10px 16px 10px 0; 95 | } 96 | body.admin-users #users #updateUser { 97 | background-color: #FAA732; 98 | border: 1px solid #c58433; 99 | } 100 | body.admin-admingroup section.container { 101 | width: 720px; 102 | } 103 | body.admin-admingroup #newAdministrator, 104 | body.admin-admingroup #adminlist { 105 | float: left; 106 | margin: 20px 20px 0 0; 107 | background-color: #fbeed5; 108 | border: 1px solid #E5E5E5; 109 | border-radius: 5px 5px 5px 5px; 110 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 111 | padding: 10px 16px; 112 | width: 300px; 113 | height: 430px; 114 | overflow: auto; 115 | } 116 | body.admin-admingroup #adminlist a.delete { 117 | float: right; 118 | margin-right: 10px; 119 | } 120 | body.admin-admingroup #adminlist li { 121 | padding: 6px 0 10px 5px; 122 | } 123 | body.admin-admingroup #adminlist li.itemOver { 124 | background-color: #78b608; 125 | border-radius: 5px 5px 5px 5px; 126 | } 127 | .no-close .ui-dialog-titlebar-close { 128 | display: none; 129 | } 130 | * { 131 | color: #555; 132 | } 133 | .errorTip { 134 | color: red; 135 | padding-left: 5px; 136 | } 137 | div.title { 138 | margin: 0 0 10px 0; 139 | padding: 0; 140 | } 141 | div.title h2 { 142 | display: inline; 143 | font-size: 16px; 144 | padding-left: 5px; 145 | } 146 | -------------------------------------------------------------------------------- /public/css/adminStyle.less: -------------------------------------------------------------------------------- 1 | @import-once "treeList"; 2 | @import-once "header"; 3 | @import-once "adminDepartment"; 4 | @import-once "adminUser"; 5 | @import-once "adminGroup"; 6 | 7 | //hide dialog close button 8 | .no-close .ui-dialog-titlebar-close { 9 | display: none; 10 | } 11 | 12 | * {color: #555;} 13 | 14 | .errorTip { 15 | color: red; 16 | padding-left:5px; 17 | } 18 | 19 | div.title { 20 | margin:0 0 10px 0; 21 | padding:0; 22 | 23 | h2 { 24 | display: inline; 25 | font-size: 16px; 26 | padding-left: 5px; 27 | } 28 | } -------------------------------------------------------------------------------- /public/css/adminUser.css: -------------------------------------------------------------------------------- 1 | body.admin-users #users { 2 | width: 720px; 3 | } 4 | body.admin-users #users #newUser, 5 | body.admin-users #users #updateUser, 6 | body.admin-users #users #usersTree { 7 | float: left; 8 | margin: 20px 20px 0 0; 9 | background-color: #fbeed5; 10 | border: 1px solid #E5E5E5; 11 | border-radius: 5px 5px 5px 5px; 12 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 13 | padding: 10px 16px; 14 | width: 300px; 15 | height: 430px; 16 | overflow: auto; 17 | } 18 | body.admin-users #users #usersTree { 19 | padding: 10px 16px 10px 0; 20 | } 21 | body.admin-users #users #updateUser { 22 | background-color: #FAA732; 23 | border: 1px solid #c58433; 24 | } 25 | -------------------------------------------------------------------------------- /public/css/adminUser.less: -------------------------------------------------------------------------------- 1 | 2 | body.admin-users { 3 | #users { 4 | width: 720px; 5 | #newUser, #updateUser, #usersTree { 6 | float:left; 7 | margin:20px 20px 0 0; 8 | background-color: #fbeed5; 9 | border: 1px solid #E5E5E5; 10 | border-radius: 5px 5px 5px 5px; 11 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 12 | padding: 10px 16px; 13 | width: 300px; 14 | height:430px; 15 | overflow: auto; 16 | } 17 | 18 | #usersTree { 19 | padding: 10px 16px 10px 0; 20 | } 21 | 22 | #updateUser { 23 | background-color: #FAA732; 24 | border: 1px solid #c58433; 25 | } 26 | } 27 | } 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /public/css/header.css: -------------------------------------------------------------------------------- 1 | header { 2 | background-color: #FAFAFA; 3 | background-image: -moz-linear-gradient(center top, #ffffff, #f2f2f2); 4 | background-repeat: repeat-x; 5 | border: 1px solid #D4D4D4; 6 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); 7 | min-height: 40px; 8 | width: 100%; 9 | } 10 | header.navbar a.brand { 11 | padding-left: 40px; 12 | } 13 | -------------------------------------------------------------------------------- /public/css/header.less: -------------------------------------------------------------------------------- 1 | header { 2 | background-color: #FAFAFA; 3 | background-image: -moz-linear-gradient(center top , #FFFFFF, #F2F2F2); 4 | background-repeat: repeat-x; 5 | border: 1px solid #D4D4D4; 6 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); 7 | min-height: 40px; 8 | width:100%; 9 | 10 | &.navbar a.brand { 11 | padding-left: 40px; 12 | } 13 | } -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/animated-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/animated-overlay.gif -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_diagonal-maze_20_6e4f1c_10x10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_diagonal-maze_20_6e4f1c_10x10.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_diagonal-maze_40_000000_10x10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_diagonal-maze_40_000000_10x10.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_fine-grain_10_eceadf_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_fine-grain_10_eceadf_60x60.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_fine-grain_10_f8f7f6_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_fine-grain_10_f8f7f6_60x60.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_fine-grain_15_eceadf_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_fine-grain_15_eceadf_60x60.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_fine-grain_15_f7f3de_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_fine-grain_15_f7f3de_60x60.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_fine-grain_15_ffffff_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_fine-grain_15_ffffff_60x60.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_fine-grain_65_654b24_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_fine-grain_65_654b24_60x60.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-bg_fine-grain_68_b83400_60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-bg_fine-grain_68_b83400_60x60.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-icons_3572ac_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-icons_3572ac_256x240.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-icons_8c291d_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-icons_8c291d_256x240.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-icons_b83400_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-icons_b83400_256x240.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-icons_fbdb93_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-icons_fbdb93_256x240.png -------------------------------------------------------------------------------- /public/css/pepper-grinder/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/css/pepper-grinder/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /public/css/reportStyle.css: -------------------------------------------------------------------------------- 1 | .treeList ul { 2 | list-style: none; 3 | } 4 | .treeList li div { 5 | padding: 6px 0 10px 5px; 6 | } 7 | .treeList li div.treeListItemOver { 8 | background-color: #78b608; 9 | border-radius: 5px 5px 5px 5px; 10 | color: white; 11 | } 12 | .treeList li div.treeListItemSelected { 13 | background-color: #FAA732; 14 | border-radius: 5px 5px 5px 5px; 15 | color: white; 16 | } 17 | .treeList li div i { 18 | padding: 1px; 19 | } 20 | .treeList li div i.icon-minus, 21 | .treeList li div i.icon-plus { 22 | width: 12px; 23 | height: 12px; 24 | border: 1px solid #444444; 25 | margin-right: 5px; 26 | cursor: pointer; 27 | } 28 | .treeList li div span.delete, 29 | .treeList li div span.update, 30 | .treeList li div span.review { 31 | margin-right: 8px; 32 | font-size: 12px; 33 | height: 16px; 34 | padding: 2px 8px 4px 8px; 35 | float: right; 36 | } 37 | header { 38 | background-color: #FAFAFA; 39 | background-image: -moz-linear-gradient(center top, #ffffff, #f2f2f2); 40 | background-repeat: repeat-x; 41 | border: 1px solid #D4D4D4; 42 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); 43 | min-height: 40px; 44 | width: 100%; 45 | } 46 | header.navbar a.brand { 47 | padding-left: 40px; 48 | } 49 | .no-close .ui-dialog-titlebar-close { 50 | display: none; 51 | } 52 | * { 53 | color: #555; 54 | } 55 | div.title h1 { 56 | display: inline; 57 | font-size: 18px; 58 | padding-left: 5px; 59 | margin: 0; 60 | } 61 | #reportCreation { 62 | background-color: #fbeed5; 63 | border: 1px solid #E5E5E5; 64 | border-radius: 5px 5px 5px 5px; 65 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 66 | padding: 0 20px 18px 20px; 67 | } 68 | #reportCreation textarea { 69 | width: 100%; 70 | } 71 | #reportCreation #dateTxt { 72 | margin-bottom: 20px; 73 | } 74 | #reportCreation #reportSubmitBtn { 75 | margin-top: 20px; 76 | } 77 | html, 78 | body { 79 | height: 100%; 80 | width: 100%; 81 | } 82 | body.subordinate .navbar { 83 | margin-bottom: 0; 84 | } 85 | body.subordinate #userList { 86 | float: left; 87 | margin-top: 0px; 88 | border-right: 1px solid #E5E5E5; 89 | padding: 10px 16px 10px 0; 90 | height: 91%; 91 | width: 310px; 92 | } 93 | body.subordinate #userList div.title { 94 | padding-left: 15px; 95 | } 96 | body.subordinate #userList #userTree { 97 | margin: 0 10px 0 0; 98 | padding: 0; 99 | width: 300px; 100 | } 101 | body.subordinate #reports { 102 | float: left; 103 | padding-left: 30px; 104 | width: 65%; 105 | } 106 | body.subordinate #reports li.report { 107 | border-bottom: 1px solid #E5E5E5; 108 | } 109 | #reportList li.report { 110 | border-bottom: 1px solid #E5E5E5; 111 | padding: 10px; 112 | margin-bottom: 15px; 113 | float: left; 114 | width: 100%; 115 | } 116 | #reportList li.report .date span { 117 | font-size: 18px; 118 | font-weight: bold; 119 | color: #1a700b; 120 | padding-left: 5px; 121 | } 122 | #reportList li.report .content { 123 | margin: 0; 124 | padding: 0; 125 | } 126 | #reportList li.report .reply, 127 | #reportList li.report .delete { 128 | float: right; 129 | padding: 0 20px 0 0; 130 | } 131 | #reportList div.pagination { 132 | float: right; 133 | margin: 5px 0; 134 | } 135 | #reportList div.pagination span { 136 | margin: 0 15px; 137 | font-size: 16px; 138 | } 139 | #reportList div.pagination button { 140 | margin-top: -8px; 141 | } 142 | #loginDiv { 143 | background-color: #fbeed5; 144 | border: 1px solid #E5E5E5; 145 | border-radius: 5px 5px 5px 5px; 146 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 147 | padding: 10px 16px; 148 | width: 230px; 149 | minheight: 230px; 150 | } 151 | #loginDiv #errorTip { 152 | color: red; 153 | margin: 0 0 20px 0; 154 | } 155 | body.passoword section { 156 | background-color: #fbeed5; 157 | border: 1px solid #E5E5E5; 158 | border-radius: 5px 5px 5px 5px; 159 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 160 | padding: 10px 16px; 161 | width: 230px; 162 | height: 280px; 163 | } 164 | body.passoword .errorTip { 165 | color: red; 166 | padding-left: 5px; 167 | } 168 | body.passoword #successTip { 169 | color: green; 170 | padding-top: 10px; 171 | display: none; 172 | } 173 | body.passoword #passwordErrorTip { 174 | color: red; 175 | padding-top: 10px; 176 | display: none; 177 | } 178 | -------------------------------------------------------------------------------- /public/css/reportStyle.less: -------------------------------------------------------------------------------- 1 | @import-once "treeList"; 2 | @import-once "header"; 3 | 4 | //hide dialog close button 5 | .no-close .ui-dialog-titlebar-close { 6 | display: none; 7 | } 8 | 9 | * {color: #555;} 10 | 11 | div.title { 12 | h1 { 13 | display: inline; 14 | font-size: 18px; 15 | padding-left: 5px; 16 | margin:0; 17 | } 18 | } 19 | 20 | //创建日报页面 21 | #reportCreation { 22 | background-color: #fbeed5; 23 | border: 1px solid #E5E5E5; 24 | border-radius: 5px 5px 5px 5px; 25 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 26 | padding: 0 20px 18px 20px; 27 | textarea { 28 | width: 100%; 29 | } 30 | 31 | #dateTxt { 32 | margin-bottom:20px; 33 | } 34 | 35 | 36 | #reportSubmitBtn { 37 | margin-top: 20px; 38 | } 39 | } 40 | 41 | html, body { 42 | height:100%; 43 | width:100%; 44 | } 45 | 46 | //查看下属日报页面 47 | body.subordinate { 48 | .navbar { 49 | margin-bottom: 0;} 50 | 51 | 52 | 53 | #userList { 54 | float:left; 55 | margin-top: 0px; 56 | border-right: 1px solid #E5E5E5; 57 | padding: 10px 16px 10px 0; 58 | height:91%; 59 | width: 310px; 60 | 61 | div.title { 62 | padding-left:15px; 63 | } 64 | 65 | #userTree { 66 | margin:0 10px 0 0; 67 | padding:0; 68 | width: 300px; 69 | } 70 | } 71 | 72 | #reports { 73 | float:left; 74 | padding-left: 30px; 75 | //background-color: #f00; 76 | //min-width:400px; 77 | 78 | 79 | li.report { 80 | //background-color: #eeeeee; 81 | border-bottom: 1px solid #E5E5E5; 82 | } 83 | width:65%; 84 | } 85 | 86 | 87 | } 88 | 89 | //查看我的日报页面 90 | #reportList { 91 | li.report { 92 | //background-color: #eeeeee; 93 | border-bottom: 1px solid #E5E5E5; 94 | //border-radius: 5px 5px 5px 5px; 95 | padding: 10px; 96 | margin-bottom:15px; 97 | float:left; 98 | width:100%; 99 | .date span{ 100 | font-size: 18px; 101 | font-weight: bold; 102 | color: #1a700b; 103 | padding-left:5px; 104 | } 105 | 106 | .content{ 107 | margin:0; 108 | padding:0; 109 | } 110 | 111 | .reply, .delete { 112 | float: right; 113 | padding: 0 20px 0 0; 114 | 115 | } 116 | } 117 | 118 | div.pagination { 119 | float: right; 120 | margin: 5px 0; 121 | 122 | span { 123 | margin:0 15px; 124 | font-size:16px; 125 | } 126 | 127 | button { 128 | margin-top:-8px; 129 | } 130 | } 131 | } 132 | 133 | // 登陆页面 134 | #loginDiv { 135 | background-color: #fbeed5; 136 | border: 1px solid #E5E5E5; 137 | border-radius: 5px 5px 5px 5px; 138 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 139 | padding: 10px 16px; 140 | width: 230px; 141 | minheight:230px; 142 | 143 | #errorTip { 144 | color:red; 145 | margin:0 0 20px 0; 146 | } 147 | } 148 | 149 | //修改密码页面 150 | body.passoword { 151 | section { 152 | background-color: #fbeed5; 153 | border: 1px solid #E5E5E5; 154 | border-radius: 5px 5px 5px 5px; 155 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 156 | padding: 10px 16px; 157 | width: 230px; 158 | height:280px; 159 | } 160 | 161 | .errorTip { 162 | color: red; 163 | padding-left:5px; 164 | } 165 | 166 | #successTip { 167 | color:green; 168 | padding-top:10px; 169 | display:none; 170 | } 171 | 172 | #passwordErrorTip { 173 | color:red; 174 | padding-top:10px; 175 | display:none; 176 | } 177 | } 178 | 179 | 180 | -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | .treeList ul { 2 | list-style: none; 3 | } 4 | .treeList li div { 5 | padding: 6px 0 10px 5px; 6 | } 7 | .treeList li div.treeListItemOver { 8 | background-color: #78b608; 9 | border-radius: 5px 5px 5px 5px; 10 | color: white; 11 | } 12 | .treeList li div.treeListItemSelected { 13 | background-color: #FAA732; 14 | border-radius: 5px 5px 5px 5px; 15 | color: white; 16 | } 17 | .treeList li div i { 18 | padding: 1px; 19 | } 20 | .treeList li div i.icon-minus, 21 | .treeList li div i.icon-plus { 22 | width: 12px; 23 | height: 12px; 24 | border: 1px solid #444444; 25 | margin-right: 5px; 26 | cursor: pointer; 27 | } 28 | .treeList li div span.delete, 29 | .treeList li div span.update, 30 | .treeList li div span.review { 31 | margin-right: 8px; 32 | font-size: 12px; 33 | height: 16px; 34 | padding: 2px 8px 4px 8px; 35 | float: right; 36 | } 37 | header { 38 | background-color: #FAFAFA; 39 | background-image: -moz-linear-gradient(center top, #ffffff, #f2f2f2); 40 | background-repeat: repeat-x; 41 | border: 1px solid #D4D4D4; 42 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); 43 | min-height: 40px; 44 | width: 100%; 45 | } 46 | header.navbar a.brand { 47 | padding-left: 40px; 48 | } 49 | /** 50 | header { 51 | background-color: #FAFAFA; 52 | background-image: -moz-linear-gradient(center top , #FFFFFF, #F2F2F2); 53 | background-repeat: repeat-x; 54 | border: 1px solid #D4D4D4; 55 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); 56 | min-height: 40px; 57 | width:100%; 58 | } 59 | 60 | #reportCreation { 61 | margin-top: 20px; 62 | background-color: #fbeed5; 63 | border: 1px solid #E5E5E5; 64 | border-radius: 5px 5px 5px 5px; 65 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 66 | padding: 18px; 67 | textarea { 68 | width: 98%; 69 | } 70 | 71 | 72 | #submitBtn { 73 | margin-right: 10%; 74 | clear: both; 75 | } 76 | } 77 | 78 | #reportList { 79 | margin-top:30px; 80 | li.report { 81 | background-color: #eeeeee; 82 | border: 1px solid #E5E5E5; 83 | border-radius: 5px 5px 5px 5px; 84 | padding: 5px; 85 | margin-top:10px; 86 | width: 100%; 87 | float:left; 88 | 89 | .date { 90 | font-size: 18px; 91 | font-weight: bold; 92 | } 93 | 94 | .reply, .delete { 95 | float: right; 96 | padding: 0 20px 0 0; 97 | 98 | } 99 | } 100 | 101 | div.pagination { 102 | float: left; 103 | } 104 | } 105 | 106 | #department { 107 | width:720px; 108 | #newDepartment,#departmentTree { 109 | float:left; 110 | margin:20px 20px 0 0; 111 | background-color: #fbeed5; 112 | border: 1px solid #E5E5E5; 113 | border-radius: 5px 5px 5px 5px; 114 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 115 | padding: 10px 16px; 116 | width: 300px; 117 | height:350px; 118 | overflow: auto; 119 | color: #555; 120 | } 121 | 122 | #newDepartment { 123 | .submitBtn { 124 | margin-top: 20px; 125 | } 126 | 127 | &.update { 128 | background-color: #FAA732; 129 | border: 1px solid #c58433; 130 | } 131 | } 132 | 133 | #departmentTree { 134 | li div { 135 | &.on { 136 | background-color: #78b608; 137 | //border: 1px solid #165fe5; 138 | border-radius: 5px 5px 5px 5px; 139 | color:white; 140 | } 141 | 142 | &.selected { 143 | background-color: #FAA732; 144 | border-radius: 5px 5px 5px 5px; 145 | color:white; 146 | } 147 | 148 | 149 | padding: 6px 0 10px 5px; 150 | 151 | i{ 152 | padding:1px; 153 | //background-color: #f00; 154 | &.icon-minus, &.icon-plus { 155 | width:12px; 156 | height:12px; 157 | border: 1px solid #444444; 158 | margin-right: 5px; 159 | cursor: pointer; 160 | } 161 | } 162 | 163 | span.delete, span.update { 164 | margin-right:8px; 165 | font-size: 12px; 166 | height:16px; 167 | padding: 2px 8px 4px 8px; 168 | float:right; 169 | } 170 | } 171 | } 172 | } 173 | 174 | .errorTip { 175 | color: red; 176 | padding-left:5px; 177 | } 178 | 179 | div.title { 180 | margin:0 0 10px 0; 181 | padding:0; 182 | 183 | h2 { 184 | display: inline; 185 | font-size: 16px; 186 | padding-left: 5px; 187 | } 188 | } 189 | 190 | body.login { 191 | #loginDiv { 192 | margin-top: 20px; 193 | background-color: #fbeed5; 194 | border: 1px solid #E5E5E5; 195 | border-radius: 5px 5px 5px 5px; 196 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 197 | padding: 18px; 198 | width: 220px; 199 | 200 | .submitBtn { 201 | margin-top: 20px; 202 | } 203 | } 204 | } 205 | 206 | body.admin-users { 207 | #users { 208 | width: 720px; 209 | #newUser, #usersTree { 210 | float:left; 211 | margin:20px 20px 0 0; 212 | background-color: #fbeed5; 213 | border: 1px solid #E5E5E5; 214 | border-radius: 5px 5px 5px 5px; 215 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 216 | padding: 10px 16px; 217 | width: 300px; 218 | height:430px; 219 | overflow: auto; 220 | color: #555; 221 | } 222 | } 223 | } 224 | 225 | */ 226 | -------------------------------------------------------------------------------- /public/css/style.less: -------------------------------------------------------------------------------- 1 | @import-once "treeList"; 2 | @import-once "header"; 3 | 4 | /** 5 | header { 6 | background-color: #FAFAFA; 7 | background-image: -moz-linear-gradient(center top , #FFFFFF, #F2F2F2); 8 | background-repeat: repeat-x; 9 | border: 1px solid #D4D4D4; 10 | box-shadow: 0 1px 4px rgba(0, 0, 0, 0.067); 11 | min-height: 40px; 12 | width:100%; 13 | } 14 | 15 | #reportCreation { 16 | margin-top: 20px; 17 | background-color: #fbeed5; 18 | border: 1px solid #E5E5E5; 19 | border-radius: 5px 5px 5px 5px; 20 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 21 | padding: 18px; 22 | textarea { 23 | width: 98%; 24 | } 25 | 26 | 27 | #submitBtn { 28 | margin-right: 10%; 29 | clear: both; 30 | } 31 | } 32 | 33 | #reportList { 34 | margin-top:30px; 35 | li.report { 36 | background-color: #eeeeee; 37 | border: 1px solid #E5E5E5; 38 | border-radius: 5px 5px 5px 5px; 39 | padding: 5px; 40 | margin-top:10px; 41 | width: 100%; 42 | float:left; 43 | 44 | .date { 45 | font-size: 18px; 46 | font-weight: bold; 47 | } 48 | 49 | .reply, .delete { 50 | float: right; 51 | padding: 0 20px 0 0; 52 | 53 | } 54 | } 55 | 56 | div.pagination { 57 | float: left; 58 | } 59 | } 60 | 61 | #department { 62 | width:720px; 63 | #newDepartment,#departmentTree { 64 | float:left; 65 | margin:20px 20px 0 0; 66 | background-color: #fbeed5; 67 | border: 1px solid #E5E5E5; 68 | border-radius: 5px 5px 5px 5px; 69 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 70 | padding: 10px 16px; 71 | width: 300px; 72 | height:350px; 73 | overflow: auto; 74 | color: #555; 75 | } 76 | 77 | #newDepartment { 78 | .submitBtn { 79 | margin-top: 20px; 80 | } 81 | 82 | &.update { 83 | background-color: #FAA732; 84 | border: 1px solid #c58433; 85 | } 86 | } 87 | 88 | #departmentTree { 89 | li div { 90 | &.on { 91 | background-color: #78b608; 92 | //border: 1px solid #165fe5; 93 | border-radius: 5px 5px 5px 5px; 94 | color:white; 95 | } 96 | 97 | &.selected { 98 | background-color: #FAA732; 99 | border-radius: 5px 5px 5px 5px; 100 | color:white; 101 | } 102 | 103 | 104 | padding: 6px 0 10px 5px; 105 | 106 | i{ 107 | padding:1px; 108 | //background-color: #f00; 109 | &.icon-minus, &.icon-plus { 110 | width:12px; 111 | height:12px; 112 | border: 1px solid #444444; 113 | margin-right: 5px; 114 | cursor: pointer; 115 | } 116 | } 117 | 118 | span.delete, span.update { 119 | margin-right:8px; 120 | font-size: 12px; 121 | height:16px; 122 | padding: 2px 8px 4px 8px; 123 | float:right; 124 | } 125 | } 126 | } 127 | } 128 | 129 | .errorTip { 130 | color: red; 131 | padding-left:5px; 132 | } 133 | 134 | div.title { 135 | margin:0 0 10px 0; 136 | padding:0; 137 | 138 | h2 { 139 | display: inline; 140 | font-size: 16px; 141 | padding-left: 5px; 142 | } 143 | } 144 | 145 | body.login { 146 | #loginDiv { 147 | margin-top: 20px; 148 | background-color: #fbeed5; 149 | border: 1px solid #E5E5E5; 150 | border-radius: 5px 5px 5px 5px; 151 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 152 | padding: 18px; 153 | width: 220px; 154 | 155 | .submitBtn { 156 | margin-top: 20px; 157 | } 158 | } 159 | } 160 | 161 | body.admin-users { 162 | #users { 163 | width: 720px; 164 | #newUser, #usersTree { 165 | float:left; 166 | margin:20px 20px 0 0; 167 | background-color: #fbeed5; 168 | border: 1px solid #E5E5E5; 169 | border-radius: 5px 5px 5px 5px; 170 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 171 | padding: 10px 16px; 172 | width: 300px; 173 | height:430px; 174 | overflow: auto; 175 | color: #555; 176 | } 177 | } 178 | } 179 | 180 | */ 181 | 182 | -------------------------------------------------------------------------------- /public/css/treeList.css: -------------------------------------------------------------------------------- 1 | .treeList ul { 2 | list-style: none; 3 | } 4 | .treeList li div { 5 | padding: 6px 0 10px 5px; 6 | } 7 | .treeList li div.treeListItemOver { 8 | background-color: #78b608; 9 | border-radius: 5px 5px 5px 5px; 10 | color: white; 11 | } 12 | .treeList li div.treeListItemSelected { 13 | background-color: #FAA732; 14 | border-radius: 5px 5px 5px 5px; 15 | color: white; 16 | } 17 | .treeList li div i { 18 | padding: 1px; 19 | } 20 | .treeList li div i.icon-minus, 21 | .treeList li div i.icon-plus { 22 | width: 12px; 23 | height: 12px; 24 | border: 1px solid #444444; 25 | margin-right: 5px; 26 | cursor: pointer; 27 | } 28 | .treeList li div span.delete, 29 | .treeList li div span.update, 30 | .treeList li div span.review { 31 | margin-right: 8px; 32 | font-size: 12px; 33 | height: 16px; 34 | padding: 2px 8px 4px 8px; 35 | float: right; 36 | } 37 | -------------------------------------------------------------------------------- /public/css/treeList.less: -------------------------------------------------------------------------------- 1 | 2 | .treeList { 3 | ul {list-style: none;} 4 | 5 | li div { 6 | &.treeListItemOver { 7 | background-color: #78b608; 8 | //border: 1px solid #165fe5; 9 | border-radius: 5px 5px 5px 5px; 10 | color:white; 11 | } 12 | 13 | &.treeListItemSelected { 14 | background-color: #FAA732; 15 | border-radius: 5px 5px 5px 5px; 16 | color:white; 17 | } 18 | 19 | padding: 6px 0 10px 5px; 20 | 21 | i{ 22 | padding:1px; 23 | &.icon-minus, &.icon-plus { 24 | width:12px; 25 | height:12px; 26 | border: 1px solid #444444; 27 | margin-right: 5px; 28 | cursor: pointer; 29 | } 30 | } 31 | 32 | span.delete, span.update, span.review { 33 | margin-right:8px; 34 | font-size: 12px; 35 | height:16px; 36 | padding: 2px 8px 4px 8px; 37 | float:right; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /public/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /public/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /public/js/ReportModel.coffee: -------------------------------------------------------------------------------- 1 | # report model层,处理数据调用和解析 --------------------------------------------------------------- 2 | class ReportModel 3 | 4 | @createReport: (data, callback)-> 5 | $.post("/write", data, (response)-> 6 | callback(response) 7 | , "json") 8 | 9 | @deleteReport: (data, callback)-> 10 | $.post("/delete", data, (response)-> 11 | callback(response) 12 | , "json") 13 | 14 | @getReportNum: (userId, callback)-> 15 | $.post("/getreportnum", {userId:userId}, (response)-> 16 | callback(response) 17 | , "json") 18 | 19 | @getSubordinateUserAndDepartment: (callback)-> 20 | $.post("/getsubordinateuseranddepartment",(response)-> 21 | callback(response) 22 | , "json") 23 | 24 | #返回数据格式为[ { date: '2013-4-30',cotent: '


4.30 reports' },{ date: '2013-4-30',content: '4.30 reports' }] 25 | @getReports: (data, callback)-> 26 | $.post("/getreports", data, (response)-> 27 | callback(response) 28 | , "json") 29 | 30 | window.ReportModel = ReportModel -------------------------------------------------------------------------------- /public/js/ReportModel.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var ReportModel; 4 | 5 | ReportModel = (function() { 6 | 7 | function ReportModel() {} 8 | 9 | ReportModel.createReport = function(data, callback) { 10 | return $.post("/write", data, function(response) { 11 | return callback(response); 12 | }, "json"); 13 | }; 14 | 15 | ReportModel.deleteReport = function(data, callback) { 16 | return $.post("/delete", data, function(response) { 17 | return callback(response); 18 | }, "json"); 19 | }; 20 | 21 | ReportModel.getReportNum = function(userId, callback) { 22 | return $.post("/getreportnum", { 23 | userId: userId 24 | }, function(response) { 25 | return callback(response); 26 | }, "json"); 27 | }; 28 | 29 | ReportModel.getSubordinateUserAndDepartment = function(callback) { 30 | return $.post("/getsubordinateuseranddepartment", function(response) { 31 | return callback(response); 32 | }, "json"); 33 | }; 34 | 35 | ReportModel.getReports = function(data, callback) { 36 | return $.post("/getreports", data, function(response) { 37 | return callback(response); 38 | }, "json"); 39 | }; 40 | 41 | return ReportModel; 42 | 43 | })(); 44 | 45 | window.ReportModel = ReportModel; 46 | 47 | }).call(this); 48 | -------------------------------------------------------------------------------- /public/js/TreeList.coffee: -------------------------------------------------------------------------------- 1 | 2 | #树形列表基类 ---------------------------------------------------------------------------------- 3 | class TreeListBase 4 | 5 | constructor: (@containerNode, @dataSource=null)-> 6 | @editingItem = null 7 | 8 | $(@containerNode).addClass("treeList") 9 | 10 | $(@containerNode).on("mouseenter", "li div", (event)-> 11 | $(@).addClass('treeListItemOver') unless $(this) == @editingItem) 12 | 13 | $(@containerNode).on("mouseleave", "li div", (event)-> 14 | $(@).removeClass('treeListItemOver') unless $(this) == @editingItem) 15 | 16 | @treeNodes = {} 17 | 18 | self = @ 19 | $(@containerNode).on("click", "li i.icon-circle-arrow-right", (event)-> 20 | event.stopImmediatePropagation() 21 | $(@).addClass('icon-circle-arrow-down').removeClass('icon-circle-arrow-right') 22 | name = $(@).parent().parent().attr("id") 23 | $("##{name}").append(self.treeNodes[name]) 24 | delete self.treeNodes[name] 25 | 26 | if self.editingItem 27 | $("#{self.containerNode} span.update, #{self.containerNode} span.delete").hide() 28 | else 29 | $("#{self.containerNode} span.update, #{self.containerNode} span.delete").show()) 30 | 31 | $(@containerNode).on("click", "li i.icon-circle-arrow-down", (event)-> 32 | event.stopImmediatePropagation() 33 | $(@).addClass('icon-circle-arrow-right').removeClass('icon-circle-arrow-down') 34 | name = $(@).parent().parent().attr("id") 35 | self.treeNodes[name] = $(@).parent().next().detach()) 36 | 37 | show: (@dataSource)-> 38 | $(@containerNode).empty() 39 | @renderTree(@containerNode, @getDepartTreeData()) 40 | 41 | #收缩的菜单项依旧收缩 42 | for name, _ of @treeNodes 43 | ul = $("##{name}").find("ul:first") 44 | ul.prev().find("i:first").addClass('icon-plus-sign').removeClass('icon-minus-sign') 45 | @treeNodes[name] = ul.detach() 46 | 47 | showEditingItem: -> 48 | return unless @editingItem 49 | @editingItem.parent().removeClass('treeListItemSelected') 50 | $("#{@containerNode} span.update, #{@containerNode} span.delete").show() 51 | @editingItem = null 52 | 53 | getEditingItemId: -> 54 | return null unless @editingItem 55 | @editingItem.parent().attr('id') 56 | 57 | # render a tree 58 | renderTree: (node, data)-> 59 | throw new Error("renderTree method must implement in child class.") 60 | 61 | # render a department tree 62 | getDepartTreeData: -> 63 | departs = @dataSource 64 | treeData = [] 65 | for value in departs 66 | rootnode = {label:value.name, id:value.id}; 67 | treeData.push(rootnode) unless value.pid 68 | 69 | findChidren = (node, departs)-> 70 | for value in departs 71 | if value.pid == node.id 72 | node.children = [] unless node.children 73 | childNode = {label:value.name, id:value.id} 74 | node.children.push(childNode) 75 | findChidren(childNode, departs) 76 | 77 | for node in treeData 78 | findChidren(node, departs) 79 | 80 | treeData 81 | 82 | #树形列表 ---------------------------------------------------------------------------------- 83 | class TreeList extends TreeListBase 84 | constructor: (@containerNode, @dataSource=null)-> 85 | super(@containerNode, @dataSource=null) 86 | 87 | @iconName = "book" 88 | 89 | $(@containerNode).on("click", "span.update", (event)=> 90 | t = $(event.target) 91 | t.parent().removeClass('treeListItemOver').addClass('treeListItemSelected') 92 | $("#{@containerNode} span.update, #{@containerNode} span.delete").hide() 93 | if @editingItem 94 | @editingItem.parent().removeClass('treeListItemSelected') 95 | @editingItem = t 96 | updateEvent = jQuery.Event("update") 97 | updateEvent["itemId"] = t.parent().attr('id') 98 | $(@containerNode).trigger(updateEvent)) 99 | 100 | $(@containerNode).on("click", "span.delete", (event)=> 101 | t = $(event.target) 102 | deleteEvent = jQuery.Event("delete") 103 | deleteEvent["itemId"] = t.parent().attr('id') 104 | $(@containerNode).trigger(deleteEvent)) 105 | 106 | show: (@dataSource, @iconName)-> 107 | console.log @iconName 108 | super(@dataSource) 109 | 110 | 111 | # render a tree 112 | renderTree: (node, data)-> 113 | $(node).append("") 114 | newnode = "#{node} ul:first" 115 | for value in data 116 | linode = "
  • #{value.label}删除编辑
  • " 117 | if value.children 118 | linode = "
  • #{value.label}删除编辑
  • " 119 | 120 | $(newnode).append(linode) 121 | newnode2 = "#{newnode} ##{value.id}node" 122 | if value.children 123 | @renderTree(newnode2, value.children) 124 | null 125 | 126 | window.TreeList = TreeList 127 | 128 | #树形列表2 ---------------------------------------------------------------------------------- 129 | class TreeList2 extends TreeListBase 130 | constructor: (@containerNode, @dataSource=null)-> 131 | super(@containerNode, @dataSource=null) 132 | 133 | $(@containerNode).on("click", "span.review", (event)=> 134 | t = $(event.target) 135 | t.parent().removeClass('treeListItemOver').addClass('treeListItemSelected') 136 | if @editingItem 137 | @editingItem.parent().removeClass('treeListItemSelected') 138 | @editingItem.show() 139 | @editingItem = t 140 | updateEvent = jQuery.Event("review") 141 | updateEvent["itemId"] = t.parent().attr('id') 142 | $(@containerNode).trigger(updateEvent)) 143 | 144 | # render a tree 145 | renderTree: (node, data)-> 146 | $(node).append("
      ") 147 | newnode = "#{node} ul:first" 148 | for value in data 149 | value.node ?= 0 150 | linode = "
    • #{value.label}查看
    • " 151 | if value.node == 1 152 | linode = "
    • #{value.label}
    • " 153 | 154 | $(newnode).append(linode) 155 | newnode2 = "#{newnode} ##{value.id}node#{value.node}" 156 | if value.children 157 | @renderTree(newnode2, value.children) 158 | null 159 | 160 | window.TreeList2 = TreeList2 -------------------------------------------------------------------------------- /public/js/admin/DepartmentUserMode.coffee: -------------------------------------------------------------------------------- 1 | 2 | # department model层,处理数据调用和解析 --------------------------------------------------------------- 3 | class DepartmemtModel 4 | 5 | @getAllDepartments: (callback)-> 6 | $.get("/admin/alldepartments", 7 | (response)-> 8 | if response.state == 1 9 | departments = DepartmemtModel.parseDepartments(response.data) 10 | response['data'] = departments 11 | callback(response) 12 | , "json") 13 | # data 后台返回数据 Object { 1:name="PHP", 2:name="IOS", 3:name="p2", 3:pid="1"} 14 | # 输出数据 Object { 1:{id:1, name:"PHP"}, 2:{id:2, name:"ios"},3:{id:3, name:"p2", pid:"1"}} 15 | @parseDepartments: (data)-> 16 | resultObj = {} 17 | for key, value of data 18 | childOfKey = key.split(":") 19 | departmentId = childOfKey[0] 20 | resultObj[departmentId] ?= {id: departmentId} 21 | if childOfKey[1] == "name" 22 | resultObj[departmentId]["name"] = value 23 | else if childOfKey[1] == "pid" 24 | resultObj[departmentId]["pid"] = value 25 | 26 | result = [] 27 | for key2, value2 of resultObj 28 | result.push(value2) 29 | 30 | # h该函数输出数据 [{id:1, name:"PHP"}, {id:2, name:"ios"},{id:3, name:"p2", pid:"1"}] 31 | result 32 | 33 | @createNewDepartment: (data, callback)-> 34 | $.post("/admin/createDepartment", data, 35 | (response)-> 36 | callback(response) 37 | , "json") 38 | 39 | @updateDepartment: (data, callback)-> 40 | $.post("/admin/updatedepartment", data, 41 | (response)-> 42 | if response.state == 1 43 | departments = DepartmemtModel.parseDepartments(response.data) 44 | response['data'] = departments 45 | callback(response) 46 | , "json") 47 | 48 | @removeDepartment: (data, callback)-> 49 | $.post("/admin/removedepartment", data,(response)-> 50 | if response.state == 1 51 | departments = DepartmemtModel.parseDepartments(response.data) 52 | response.data = departments 53 | callback(response) 54 | , "json") 55 | 56 | window.DepartmemtModel = DepartmemtModel 57 | 58 | # user model层,处理数据调用和解析 --------------------------------------------------------------- 59 | class UserModel 60 | 61 | @setAdministrator: (userId, callback)-> 62 | $.post("/admin/setadmin", {userId:userId}, (response)-> 63 | callback(response) 64 | , "json") 65 | 66 | @deleteAdministrator: (userId, callback)-> 67 | $.post("/admin/deleteadmin", {userId:userId}, (response)-> 68 | callback(response) 69 | , "json") 70 | 71 | @getAdmins: (callback)-> 72 | $.post("/admin/getadmins", (response)-> 73 | callback(response) 74 | , "json") 75 | 76 | @hasUser: (userName, callback)-> 77 | $.post("/admin/hasuser", {userName:userName}, (response)-> 78 | callback(response) 79 | , "json") 80 | 81 | @login: (data, callback)-> 82 | $.post("/login", data, (response)-> 83 | callback(response) 84 | , "json") 85 | 86 | @createUser: (data, callback)-> 87 | $.post("/admin/createuser", data, (response)-> 88 | if response.state == 1 89 | user = response.data 90 | user["name"] = user["userName"] 91 | delete user["userName"] 92 | if user["superiorId"] 93 | user["pid"] = user["superiorId"] 94 | delete user["superiorId"] 95 | response.data = user 96 | UserModel.allUsers.push(user) 97 | callback(response) 98 | , "json") 99 | 100 | @updateUser: (data, callback)-> 101 | $.post("/admin/updateuser", data, (response)-> 102 | if response.state == 1 103 | users = UserModel.parseUsers(response.data) 104 | response.data = users 105 | UserModel.allUsers = users 106 | callback(response) 107 | ,"json") 108 | 109 | @changePassword: (data, callback)-> 110 | $.post("/password", data, (response)-> 111 | if response.state == 1 112 | callback(response) 113 | ,"json") 114 | 115 | @removeUser: (data, callback)-> 116 | $.post("/admin/removeuser", data, (response)-> 117 | if response.state == 1 118 | users = UserModel.parseUsers(response.data) 119 | response.data = users 120 | UserModel.allUsers = users 121 | callback(response) 122 | ,"json") 123 | 124 | @getAllUsers: (callback)-> 125 | $.get("/admin/getallusers",(response)-> 126 | if response.state == 1 127 | users = UserModel.parseUsers(response.data) 128 | response.data = users 129 | UserModel.allUsers = users 130 | callback(response) 131 | , "json") 132 | 133 | @allUsers: [] 134 | 135 | @getLocalAllUsers: -> 136 | @allUsers 137 | 138 | # data 后台返回数据 Object { 1:user_name="walter", 1:department_id="7", 1:superior_id:"3"} 139 | @parseUsers: (data)-> 140 | 141 | resultObj = {} #Object { 1:{id:1, name:"walter",pid:"3", departmentId:"7"}} 142 | for key, value of data 143 | childOfKey = key.split(":") 144 | userId = childOfKey[0] 145 | resultObj[userId] ?= {id: userId} 146 | if childOfKey[1] == "user_name" 147 | resultObj[userId]["name"] = value 148 | else if childOfKey[1] == "department_id" 149 | resultObj[userId]["departmentId"] = value 150 | else if childOfKey[1] == "superior_id" 151 | resultObj[userId]["pid"] = value 152 | 153 | result = [] 154 | for key2, value2 of resultObj 155 | result.push(value2) 156 | 157 | # h该函数输出数据 [{id:1, name:"walter",pid:"3", departmentId:"7"}] 158 | result 159 | 160 | window.UserModel = UserModel -------------------------------------------------------------------------------- /public/js/admin/admingroup.coffee: -------------------------------------------------------------------------------- 1 | 2 | # ----------------------------------------------------------------------------------------------- 3 | AdminGroupViewModel = -> 4 | self = @ 5 | 6 | self.departments = ko.observableArray([]) 7 | self.selectedDepartment = ko.observable(null) 8 | 9 | self.users = ko.observableArray([]) 10 | self.selectedUser = ko.observable(null) 11 | 12 | self.admins = ko.observableArray([]) 13 | 14 | self.valid = ko.computed(-> 15 | self.selectedDepartment() and self.selectedUser()) 16 | 17 | self.submit = -> 18 | console.log "fail: 必须选择一个成员" unless self.valid() 19 | user = self.selectedUser() 20 | UserModel.setAdministrator(user["id"], (response)-> 21 | return if response.state == 0 22 | self.admins.push(user)) 23 | 24 | self 25 | 26 | 27 | # 初始化 ---------------------------------------------------------------------------- 28 | init = -> 29 | adminvm = new AdminGroupViewModel() 30 | ko.applyBindings(adminvm) 31 | 32 | DepartmemtModel.getAllDepartments((response)-> 33 | adminvm.departments(response.data)) 34 | 35 | UserModel.getAllUsers((response)-> 36 | return if response.state == 0 37 | 38 | users = response.data 39 | UserModel.getAdmins((response)-> 40 | return if response.state == 0 41 | adminIds = response.data 42 | admins = getAdmins(users, adminIds) 43 | adminvm.admins(admins)) 44 | null) 45 | 46 | getAdmins = (allUsers, adminIds)-> 47 | result = [] 48 | for adminId in adminIds 49 | for user in allUsers 50 | if adminId == user["id"] 51 | result.push(user) 52 | break 53 | result 54 | 55 | $("#depar").change( -> 56 | departmentId = adminvm.selectedDepartment()?['id'] 57 | users = UserModel.getLocalAllUsers() 58 | departmentUsers = getUsersByDepartmentId(departmentId, users) 59 | adminvm.users(departmentUsers) 60 | admins = adminvm.admins() 61 | #从部门成员中移除管理员 62 | for admin in admins 63 | for user in users 64 | if user["id"] == admin["id"] 65 | adminvm.users.remove(user) 66 | break 67 | ) 68 | 69 | #根据部门Id获取该部门所有成员 70 | getUsersByDepartmentId = (departmentId, allUsers)-> 71 | result = [] 72 | return result unless departmentId 73 | 74 | for user in allUsers 75 | result.push(user) if departmentId == user["departmentId"] 76 | result 77 | 78 | $("#adminlist").on("click", "a.delete", (event)-> 79 | userId = $(@).attr("userid") 80 | confirm(userId)) 81 | 82 | deleteAdmin = (userId)-> 83 | UserModel.deleteAdministrator(userId, (response)-> 84 | return if response.state == 0 85 | admins = adminvm.admins() 86 | for admin in admins 87 | return adminvm.admins.remove(admin) if admin["id"] == userId) 88 | 89 | confirm = (userId)-> 90 | $("#dialog-confirm").dialog({ 91 | dialogClass: "no-close", 92 | resizable: false, 93 | height:160, 94 | modal: true, 95 | buttons: { 96 | "删除": -> 97 | deleteAdmin(userId) 98 | $(@).dialog("close") 99 | Cancel: -> 100 | $(this).dialog("close")}}) 101 | 102 | $("#adminlist").on("mouseenter", "li", (event)-> 103 | $(@).addClass('itemOver')) 104 | 105 | $("#adminlist").on("mouseleave", "li", (event)-> 106 | $(@).removeClass('itemOver')) 107 | 108 | init() -------------------------------------------------------------------------------- /public/js/admin/admingroup.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var AdminGroupViewModel, init; 4 | 5 | AdminGroupViewModel = function() { 6 | var self; 7 | self = this; 8 | self.departments = ko.observableArray([]); 9 | self.selectedDepartment = ko.observable(null); 10 | self.users = ko.observableArray([]); 11 | self.selectedUser = ko.observable(null); 12 | self.admins = ko.observableArray([]); 13 | self.valid = ko.computed(function() { 14 | return self.selectedDepartment() && self.selectedUser(); 15 | }); 16 | self.submit = function() { 17 | var user; 18 | if (!self.valid()) { 19 | console.log("fail: 必须选择一个成员"); 20 | } 21 | user = self.selectedUser(); 22 | return UserModel.setAdministrator(user["id"], function(response) { 23 | if (response.state === 0) { 24 | return; 25 | } 26 | return self.admins.push(user); 27 | }); 28 | }; 29 | return self; 30 | }; 31 | 32 | init = function() { 33 | var adminvm, confirm, deleteAdmin, getAdmins, getUsersByDepartmentId; 34 | adminvm = new AdminGroupViewModel(); 35 | ko.applyBindings(adminvm); 36 | DepartmemtModel.getAllDepartments(function(response) { 37 | return adminvm.departments(response.data); 38 | }); 39 | UserModel.getAllUsers(function(response) { 40 | var users; 41 | if (response.state === 0) { 42 | return; 43 | } 44 | users = response.data; 45 | UserModel.getAdmins(function(response) { 46 | var adminIds, admins; 47 | if (response.state === 0) { 48 | return; 49 | } 50 | adminIds = response.data; 51 | admins = getAdmins(users, adminIds); 52 | return adminvm.admins(admins); 53 | }); 54 | return null; 55 | }); 56 | getAdmins = function(allUsers, adminIds) { 57 | var adminId, result, user, _i, _j, _len, _len1; 58 | result = []; 59 | for (_i = 0, _len = adminIds.length; _i < _len; _i++) { 60 | adminId = adminIds[_i]; 61 | for (_j = 0, _len1 = allUsers.length; _j < _len1; _j++) { 62 | user = allUsers[_j]; 63 | if (adminId === user["id"]) { 64 | result.push(user); 65 | break; 66 | } 67 | } 68 | } 69 | return result; 70 | }; 71 | $("#depar").change(function() { 72 | var admin, admins, departmentId, departmentUsers, user, users, _i, _len, _ref, _results; 73 | departmentId = (_ref = adminvm.selectedDepartment()) != null ? _ref['id'] : void 0; 74 | users = UserModel.getLocalAllUsers(); 75 | departmentUsers = getUsersByDepartmentId(departmentId, users); 76 | adminvm.users(departmentUsers); 77 | admins = adminvm.admins(); 78 | _results = []; 79 | for (_i = 0, _len = admins.length; _i < _len; _i++) { 80 | admin = admins[_i]; 81 | _results.push((function() { 82 | var _j, _len1, _results1; 83 | _results1 = []; 84 | for (_j = 0, _len1 = users.length; _j < _len1; _j++) { 85 | user = users[_j]; 86 | if (user["id"] === admin["id"]) { 87 | adminvm.users.remove(user); 88 | break; 89 | } else { 90 | _results1.push(void 0); 91 | } 92 | } 93 | return _results1; 94 | })()); 95 | } 96 | return _results; 97 | }); 98 | getUsersByDepartmentId = function(departmentId, allUsers) { 99 | var result, user, _i, _len; 100 | result = []; 101 | if (!departmentId) { 102 | return result; 103 | } 104 | for (_i = 0, _len = allUsers.length; _i < _len; _i++) { 105 | user = allUsers[_i]; 106 | if (departmentId === user["departmentId"]) { 107 | result.push(user); 108 | } 109 | } 110 | return result; 111 | }; 112 | $("#adminlist").on("click", "a.delete", function(event) { 113 | var userId; 114 | userId = $(this).attr("userid"); 115 | return confirm(userId); 116 | }); 117 | deleteAdmin = function(userId) { 118 | return UserModel.deleteAdministrator(userId, function(response) { 119 | var admin, admins, _i, _len; 120 | if (response.state === 0) { 121 | return; 122 | } 123 | admins = adminvm.admins(); 124 | for (_i = 0, _len = admins.length; _i < _len; _i++) { 125 | admin = admins[_i]; 126 | if (admin["id"] === userId) { 127 | return adminvm.admins.remove(admin); 128 | } 129 | } 130 | }); 131 | }; 132 | confirm = function(userId) { 133 | return $("#dialog-confirm").dialog({ 134 | dialogClass: "no-close", 135 | resizable: false, 136 | height: 160, 137 | modal: true, 138 | buttons: { 139 | "删除": function() { 140 | deleteAdmin(userId); 141 | return $(this).dialog("close"); 142 | }, 143 | Cancel: function() { 144 | return $(this).dialog("close"); 145 | } 146 | } 147 | }); 148 | }; 149 | $("#adminlist").on("mouseenter", "li", function(event) { 150 | return $(this).addClass('itemOver'); 151 | }); 152 | return $("#adminlist").on("mouseleave", "li", function(event) { 153 | return $(this).removeClass('itemOver'); 154 | }); 155 | }; 156 | 157 | init(); 158 | 159 | }).call(this); 160 | -------------------------------------------------------------------------------- /public/js/admin/department.coffee: -------------------------------------------------------------------------------- 1 | treeList = new TreeList("#departmentTree") 2 | 3 | #ViewModel--------------------------------------------------------------- 4 | DepartmentViewModel = -> 5 | self = @ 6 | self.departmentName = ko.observable('') 7 | self.updateDepartmentName = ko.observable('') 8 | self.validDepartmentName = ko.computed(-> 9 | dname = $.trim(self.departmentName()) 10 | dname.length >= 1) 11 | 12 | self.selectedParentDepartment = ko.observable(null) 13 | 14 | self.validDepartmentRelation = ko.computed(-> 15 | dname = $.trim(self.departmentName()) 16 | self.selectedParentDepartment()?["name"] != dname) 17 | 18 | self.validUpdateDepartmentRelation = ko.computed(-> 19 | dname = $.trim(self.updateDepartmentName()) 20 | self.selectedParentDepartment()?["name"] != dname) 21 | 22 | self.validUpdateDepartmentName = ko.computed(-> 23 | dname = $.trim(self.updateDepartmentName()) 24 | dname.length >= 1) 25 | 26 | self.updateDepartment = ko.observable(null) 27 | 28 | #self.departments = ko.observableArray([{name:'无', id:null},{name:'PHP', id:1},{name:'Tec Center', id:2, pid:1},{name:'ios',id:3,pid:1},{name:'Product', id:4}]) 29 | self.departments = ko.observableArray(null); 30 | 31 | 32 | self.submit = -> 33 | if self.validDepartmentName() 34 | data = {departmentName: $.trim(self.departmentName()), pid: self.selectedParentDepartment()?["id"]} 35 | DepartmemtModel.createNewDepartment(data, (response)-> 36 | return if response.state == 0 37 | self.departments.push(response.data) 38 | treeList.show(self.departments(), "book") ) 39 | 40 | self 41 | 42 | 43 | # 初始化 ---------------------------------------------------------------------------- 44 | init = -> 45 | departmentvm = new DepartmentViewModel() 46 | ko.applyBindings(departmentvm) 47 | 48 | $("#departmentTree").on("update", (event)-> 49 | departmentId = event["itemId"] 50 | department = findDepartment(departmentId) 51 | departmentvm.updateDepartment(department) 52 | departmentvm.updateDepartmentName(department['name']) 53 | departmentvm.selectedParentDepartment(findParentDepartment(department))) 54 | 55 | findDepartment = (departmentId)-> 56 | departments = departmentvm.departments() 57 | for department in departments 58 | if (department['id'] == departmentId) 59 | return department 60 | 61 | findParentDepartment = (department)-> 62 | pid = department["pid"] 63 | if pid 64 | departments = departmentvm.departments() 65 | for department in departments 66 | if (department['id'] == pid) 67 | return department 68 | return null 69 | 70 | $("#cancelUpdateBtn").click( -> 71 | cancelUpdateDepartment()) 72 | 73 | cancelUpdateDepartment = -> 74 | treeList.showEditingItem() 75 | departmentvm.updateDepartment(null) 76 | 77 | $("#updateBtn").click( -> 78 | departmentId = treeList.getEditingItemId() 79 | data = {departmentId:departmentId, departmentName:departmentvm.updateDepartmentName(), pid: departmentvm.selectedParentDepartment()?["id"]} 80 | DepartmemtModel.updateDepartment(data,(response)-> 81 | return if response.state == 0 82 | cancelUpdateDepartment() 83 | departmentvm.departments(response["data"]) 84 | treeList.show(response["data"], "book"))) 85 | 86 | 87 | $("#departmentTree").on("delete", (event)-> 88 | departmentId = event["itemId"] 89 | confirm(departmentId)) 90 | 91 | deleteDepartment = (departmentId)-> 92 | DepartmemtModel.removeDepartment({departmentId:departmentId}, (response)-> 93 | return if response.state == 0 94 | departmentvm.departments(response.data) 95 | treeList.show(response["data"], "book")) 96 | 97 | confirm = (departmentId)-> 98 | $("#dialog-confirm").dialog({ 99 | dialogClass: "no-close", 100 | resizable: false, 101 | height:160, 102 | modal: true, 103 | buttons: { 104 | "删除": -> 105 | deleteDepartment(departmentId) 106 | $(@).dialog("close") 107 | Cancel: -> 108 | $(this).dialog("close")}}) 109 | 110 | DepartmemtModel.getAllDepartments((response)-> 111 | return if response.state == 0 112 | departmentvm.departments(response.data) 113 | treeList.show(response["data"], "book")) 114 | 115 | init() -------------------------------------------------------------------------------- /public/js/admin/department.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var DepartmentViewModel, init, treeList; 4 | 5 | treeList = new TreeList("#departmentTree"); 6 | 7 | DepartmentViewModel = function() { 8 | var self; 9 | self = this; 10 | self.departmentName = ko.observable(''); 11 | self.updateDepartmentName = ko.observable(''); 12 | self.validDepartmentName = ko.computed(function() { 13 | var dname; 14 | dname = $.trim(self.departmentName()); 15 | return dname.length >= 1; 16 | }); 17 | self.selectedParentDepartment = ko.observable(null); 18 | self.validDepartmentRelation = ko.computed(function() { 19 | var dname, _ref; 20 | dname = $.trim(self.departmentName()); 21 | return ((_ref = self.selectedParentDepartment()) != null ? _ref["name"] : void 0) !== dname; 22 | }); 23 | self.validUpdateDepartmentRelation = ko.computed(function() { 24 | var dname, _ref; 25 | dname = $.trim(self.updateDepartmentName()); 26 | return ((_ref = self.selectedParentDepartment()) != null ? _ref["name"] : void 0) !== dname; 27 | }); 28 | self.validUpdateDepartmentName = ko.computed(function() { 29 | var dname; 30 | dname = $.trim(self.updateDepartmentName()); 31 | return dname.length >= 1; 32 | }); 33 | self.updateDepartment = ko.observable(null); 34 | self.departments = ko.observableArray(null); 35 | self.submit = function() { 36 | var data, _ref; 37 | if (self.validDepartmentName()) { 38 | data = { 39 | departmentName: $.trim(self.departmentName()), 40 | pid: (_ref = self.selectedParentDepartment()) != null ? _ref["id"] : void 0 41 | }; 42 | return DepartmemtModel.createNewDepartment(data, function(response) { 43 | if (response.state === 0) { 44 | return; 45 | } 46 | self.departments.push(response.data); 47 | return treeList.show(self.departments(), "book"); 48 | }); 49 | } 50 | }; 51 | return self; 52 | }; 53 | 54 | init = function() { 55 | var cancelUpdateDepartment, confirm, deleteDepartment, departmentvm, findDepartment, findParentDepartment; 56 | departmentvm = new DepartmentViewModel(); 57 | ko.applyBindings(departmentvm); 58 | $("#departmentTree").on("update", function(event) { 59 | var department, departmentId; 60 | departmentId = event["itemId"]; 61 | department = findDepartment(departmentId); 62 | departmentvm.updateDepartment(department); 63 | departmentvm.updateDepartmentName(department['name']); 64 | return departmentvm.selectedParentDepartment(findParentDepartment(department)); 65 | }); 66 | findDepartment = function(departmentId) { 67 | var department, departments, _i, _len; 68 | departments = departmentvm.departments(); 69 | for (_i = 0, _len = departments.length; _i < _len; _i++) { 70 | department = departments[_i]; 71 | if (department['id'] === departmentId) { 72 | return department; 73 | } 74 | } 75 | }; 76 | findParentDepartment = function(department) { 77 | var departments, pid, _i, _len; 78 | pid = department["pid"]; 79 | if (pid) { 80 | departments = departmentvm.departments(); 81 | for (_i = 0, _len = departments.length; _i < _len; _i++) { 82 | department = departments[_i]; 83 | if (department['id'] === pid) { 84 | return department; 85 | } 86 | } 87 | } 88 | return null; 89 | }; 90 | $("#cancelUpdateBtn").click(function() { 91 | return cancelUpdateDepartment(); 92 | }); 93 | cancelUpdateDepartment = function() { 94 | treeList.showEditingItem(); 95 | return departmentvm.updateDepartment(null); 96 | }; 97 | $("#updateBtn").click(function() { 98 | var data, departmentId, _ref; 99 | departmentId = treeList.getEditingItemId(); 100 | data = { 101 | departmentId: departmentId, 102 | departmentName: departmentvm.updateDepartmentName(), 103 | pid: (_ref = departmentvm.selectedParentDepartment()) != null ? _ref["id"] : void 0 104 | }; 105 | return DepartmemtModel.updateDepartment(data, function(response) { 106 | if (response.state === 0) { 107 | return; 108 | } 109 | cancelUpdateDepartment(); 110 | departmentvm.departments(response["data"]); 111 | return treeList.show(response["data"], "book"); 112 | }); 113 | }); 114 | $("#departmentTree").on("delete", function(event) { 115 | var departmentId; 116 | departmentId = event["itemId"]; 117 | return confirm(departmentId); 118 | }); 119 | deleteDepartment = function(departmentId) { 120 | return DepartmemtModel.removeDepartment({ 121 | departmentId: departmentId 122 | }, function(response) { 123 | if (response.state === 0) { 124 | return; 125 | } 126 | departmentvm.departments(response.data); 127 | return treeList.show(response["data"], "book"); 128 | }); 129 | }; 130 | confirm = function(departmentId) { 131 | return $("#dialog-confirm").dialog({ 132 | dialogClass: "no-close", 133 | resizable: false, 134 | height: 160, 135 | modal: true, 136 | buttons: { 137 | "删除": function() { 138 | deleteDepartment(departmentId); 139 | return $(this).dialog("close"); 140 | }, 141 | Cancel: function() { 142 | return $(this).dialog("close"); 143 | } 144 | } 145 | }); 146 | }; 147 | return DepartmemtModel.getAllDepartments(function(response) { 148 | if (response.state === 0) { 149 | return; 150 | } 151 | departmentvm.departments(response.data); 152 | return treeList.show(response["data"], "book"); 153 | }); 154 | }; 155 | 156 | init(); 157 | 158 | }).call(this); 159 | -------------------------------------------------------------------------------- /public/js/cs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license cs 0.4.3 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. 3 | * Available via the MIT or new BSD license. 4 | * see: http://github.com/jrburke/require-cs for details 5 | */ 6 | 7 | /*jslint */ 8 | /*global define, window, XMLHttpRequest, importScripts, Packages, java, 9 | ActiveXObject, process, require */ 10 | 11 | define(['coffee-script'], function (CoffeeScript) { 12 | 'use strict'; 13 | var fs, getXhr, 14 | progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], 15 | fetchText = function () { 16 | throw new Error('Environment unsupported.'); 17 | }, 18 | buildMap = {}; 19 | 20 | if (typeof process !== "undefined" && 21 | process.versions && 22 | !!process.versions.node) { 23 | //Using special require.nodeRequire, something added by r.js. 24 | fs = require.nodeRequire('fs'); 25 | fetchText = function (path, callback) { 26 | callback(fs.readFileSync(path, 'utf8')); 27 | }; 28 | } else if ((typeof window !== "undefined" && window.navigator && window.document) || typeof importScripts !== "undefined") { 29 | // Browser action 30 | getXhr = function () { 31 | //Would love to dump the ActiveX crap in here. Need IE 6 to die first. 32 | var xhr, i, progId; 33 | if (typeof XMLHttpRequest !== "undefined") { 34 | return new XMLHttpRequest(); 35 | } else { 36 | for (i = 0; i < 3; i += 1) { 37 | progId = progIds[i]; 38 | try { 39 | xhr = new ActiveXObject(progId); 40 | } catch (e) {} 41 | 42 | if (xhr) { 43 | progIds = [progId]; // so faster next time 44 | break; 45 | } 46 | } 47 | } 48 | 49 | if (!xhr) { 50 | throw new Error("getXhr(): XMLHttpRequest not available"); 51 | } 52 | 53 | return xhr; 54 | }; 55 | 56 | fetchText = function (url, callback) { 57 | var xhr = getXhr(); 58 | xhr.open('GET', url, true); 59 | xhr.onreadystatechange = function (evt) { 60 | //Do not explicitly handle errors, those should be 61 | //visible via console output in the browser. 62 | if (xhr.readyState === 4) { 63 | callback(xhr.responseText); 64 | } 65 | }; 66 | xhr.send(null); 67 | }; 68 | // end browser.js adapters 69 | } else if (typeof Packages !== 'undefined') { 70 | //Why Java, why is this so awkward? 71 | fetchText = function (path, callback) { 72 | var stringBuffer, line, 73 | encoding = "utf-8", 74 | file = new java.io.File(path), 75 | lineSeparator = java.lang.System.getProperty("line.separator"), 76 | input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), 77 | content = ''; 78 | try { 79 | stringBuffer = new java.lang.StringBuffer(); 80 | line = input.readLine(); 81 | 82 | // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 83 | // http://www.unicode.org/faq/utf_bom.html 84 | 85 | // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: 86 | // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 87 | if (line && line.length() && line.charAt(0) === 0xfeff) { 88 | // Eat the BOM, since we've already found the encoding on this file, 89 | // and we plan to concatenating this buffer with others; the BOM should 90 | // only appear at the top of a file. 91 | line = line.substring(1); 92 | } 93 | 94 | stringBuffer.append(line); 95 | 96 | while ((line = input.readLine()) !== null) { 97 | stringBuffer.append(lineSeparator); 98 | stringBuffer.append(line); 99 | } 100 | //Make sure we return a JavaScript string and not a Java string. 101 | content = String(stringBuffer.toString()); //String 102 | } finally { 103 | input.close(); 104 | } 105 | callback(content); 106 | }; 107 | } 108 | 109 | return { 110 | fetchText: fetchText, 111 | 112 | get: function () { 113 | return CoffeeScript; 114 | }, 115 | 116 | write: function (pluginName, name, write) { 117 | if (buildMap.hasOwnProperty(name)) { 118 | var text = buildMap[name]; 119 | write.asModule(pluginName + "!" + name, text); 120 | } 121 | }, 122 | 123 | version: '0.4.3', 124 | 125 | load: function (name, parentRequire, load, config) { 126 | var path = parentRequire.toUrl(name + '.coffee'); 127 | fetchText(path, function (text) { 128 | 129 | //Do CoffeeScript transform. 130 | try { 131 | text = CoffeeScript.compile(text, config.CoffeeScript); 132 | } catch (err) { 133 | err.message = "In " + path + ", " + err.message; 134 | throw err; 135 | } 136 | 137 | //Hold on to the transformed text if a build. 138 | if (config.isBuild) { 139 | buildMap[name] = text; 140 | } 141 | 142 | //IE with conditional comments on cannot handle the 143 | //sourceURL trick, so skip it if enabled. 144 | /*@if (@_jscript) @else @*/ 145 | if (!config.isBuild) { 146 | text += "\r\n//@ sourceURL=" + path; 147 | } 148 | /*@end@*/ 149 | 150 | load.fromText(name, text); 151 | 152 | //Give result to load. Need to wait until the module 153 | //is fully parse, which will happen after this 154 | //execution. 155 | parentRequire([name], function (value) { 156 | load(value); 157 | }); 158 | }); 159 | } 160 | }; 161 | }); 162 | -------------------------------------------------------------------------------- /public/js/login.coffee: -------------------------------------------------------------------------------- 1 | LoginViewModel = -> 2 | self = @ 3 | self.userName = ko.observable('') 4 | self.password = ko.observable('') 5 | 6 | self.validUserName = ko.computed(-> 7 | un = $.trim(self.userName()) 8 | un.length >= 2 and un.length<=25) 9 | 10 | self.validPassword = ko.computed(-> 11 | pw = $.trim(self.password()) 12 | pw.length >= 7 and pw.length<=25) 13 | 14 | self.errorTip = ko.observable('') 15 | 16 | self.getErrorTip = -> 17 | unless self.validUserName() 18 | return self.errorTip("用户名长度为2-25个字符") 19 | 20 | unless self.validPassword() 21 | return self.errorTip("密码长度为7-25个字符") 22 | 23 | self.errorTip("") 24 | 25 | self.showErrorTip = ko.observable(false) 26 | 27 | self.valid = ko.computed(-> 28 | self.validUserName() and self.validPassword()) 29 | 30 | self.submit = -> 31 | self.showErrorTip(true) 32 | 33 | if self.valid() 34 | data = {userName: $.trim(self.userName()), password:$.trim(self.password())} 35 | UserModel.login(data, (response)-> 36 | return if response.state == 0 37 | if response.data == 0 38 | return self.errorTip(response.message) 39 | if response.data == 1 40 | location.href = "/write") 41 | else 42 | unless self.validUserName() 43 | return result = "用户名长度为2-25个字符" 44 | 45 | unless self.validPassword() 46 | return result = "密码长度为7-25个字符" 47 | 48 | self 49 | 50 | ko.applyBindings(new LoginViewModel()) 51 | -------------------------------------------------------------------------------- /public/js/login.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var LoginViewModel; 4 | 5 | LoginViewModel = function() { 6 | var self; 7 | self = this; 8 | self.userName = ko.observable(''); 9 | self.password = ko.observable(''); 10 | self.validUserName = ko.computed(function() { 11 | var un; 12 | un = $.trim(self.userName()); 13 | return un.length >= 2 && un.length <= 25; 14 | }); 15 | self.validPassword = ko.computed(function() { 16 | var pw; 17 | pw = $.trim(self.password()); 18 | return pw.length >= 7 && pw.length <= 25; 19 | }); 20 | self.errorTip = ko.observable(''); 21 | self.getErrorTip = function() { 22 | if (!self.validUserName()) { 23 | return self.errorTip("用户名长度为2-25个字符"); 24 | } 25 | if (!self.validPassword()) { 26 | return self.errorTip("密码长度为7-25个字符"); 27 | } 28 | return self.errorTip(""); 29 | }; 30 | self.showErrorTip = ko.observable(false); 31 | self.valid = ko.computed(function() { 32 | return self.validUserName() && self.validPassword(); 33 | }); 34 | self.submit = function() { 35 | var data, result; 36 | self.showErrorTip(true); 37 | if (self.valid()) { 38 | data = { 39 | userName: $.trim(self.userName()), 40 | password: $.trim(self.password()) 41 | }; 42 | return UserModel.login(data, function(response) { 43 | if (response.state === 0) { 44 | return; 45 | } 46 | if (response.data === 0) { 47 | return self.errorTip(response.message); 48 | } 49 | if (response.data === 1) { 50 | return location.href = "/write"; 51 | } 52 | }); 53 | } else { 54 | if (!self.validUserName()) { 55 | return result = "用户名长度为2-25个字符"; 56 | } 57 | if (!self.validPassword()) { 58 | return result = "密码长度为7-25个字符"; 59 | } 60 | } 61 | }; 62 | return self; 63 | }; 64 | 65 | ko.applyBindings(new LoginViewModel()); 66 | 67 | }).call(this); 68 | -------------------------------------------------------------------------------- /public/js/password.coffee: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------------------------- 2 | PasswordViewModel = -> 3 | self = @ 4 | 5 | validPassword = (password)-> 6 | pw = $.trim(password) 7 | pw.length >= 7 and pw.length<=25 8 | 9 | self.oldpassword = ko.observable('') 10 | self.newpassword = ko.observable('') 11 | self.renewpassword = ko.observable('') 12 | 13 | self.validOldPassword = ko.computed(-> 14 | validPassword(self.oldpassword())) 15 | 16 | self.validNewPassword = ko.computed(-> 17 | validPassword(self.newpassword())) 18 | 19 | self.validRePassword = ko.computed(-> 20 | $.trim(self.newpassword()) == $.trim(self.renewpassword())) 21 | 22 | self.valid = ko.computed(-> 23 | self.validOldPassword() and self.validNewPassword() and self.validRePassword()) 24 | 25 | self.submit = -> 26 | if self.valid() 27 | data = {newPassword: $.trim(self.newpassword()), oldPassword: $.trim(self.oldpassword())} 28 | UserModel.changePassword(data, (response)-> 29 | return if response.state == 0 30 | if response.data == 1 31 | self.oldpassword('') 32 | self.newpassword('') 33 | self.renewpassword('') 34 | $("#successTip").css("display","block") 35 | $("#passwordErrorTip").css("display","none") 36 | else 37 | $("#passwordErrorTip").css("display","block") 38 | $("#successTip").css("display","none") 39 | ) 40 | else 41 | console.log("creation fail.") 42 | 43 | self 44 | 45 | 46 | # 初始化 ---------------------------------------------------------------------------- 47 | init = -> 48 | passwordvm = new PasswordViewModel() 49 | ko.applyBindings(passwordvm) 50 | 51 | init() -------------------------------------------------------------------------------- /public/js/password.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var PasswordViewModel, init; 4 | 5 | PasswordViewModel = function() { 6 | var self, validPassword; 7 | self = this; 8 | validPassword = function(password) { 9 | var pw; 10 | pw = $.trim(password); 11 | return pw.length >= 7 && pw.length <= 25; 12 | }; 13 | self.oldpassword = ko.observable(''); 14 | self.newpassword = ko.observable(''); 15 | self.renewpassword = ko.observable(''); 16 | self.validOldPassword = ko.computed(function() { 17 | return validPassword(self.oldpassword()); 18 | }); 19 | self.validNewPassword = ko.computed(function() { 20 | return validPassword(self.newpassword()); 21 | }); 22 | self.validRePassword = ko.computed(function() { 23 | return $.trim(self.newpassword()) === $.trim(self.renewpassword()); 24 | }); 25 | self.valid = ko.computed(function() { 26 | return self.validOldPassword() && self.validNewPassword() && self.validRePassword(); 27 | }); 28 | self.submit = function() { 29 | var data; 30 | if (self.valid()) { 31 | data = { 32 | newPassword: $.trim(self.newpassword()), 33 | oldPassword: $.trim(self.oldpassword()) 34 | }; 35 | return UserModel.changePassword(data, function(response) { 36 | if (response.state === 0) { 37 | return; 38 | } 39 | if (response.data === 1) { 40 | self.oldpassword(''); 41 | self.newpassword(''); 42 | self.renewpassword(''); 43 | $("#successTip").css("display", "block"); 44 | return $("#passwordErrorTip").css("display", "none"); 45 | } else { 46 | $("#passwordErrorTip").css("display", "block"); 47 | return $("#successTip").css("display", "none"); 48 | } 49 | }); 50 | } else { 51 | return console.log("creation fail."); 52 | } 53 | }; 54 | return self; 55 | }; 56 | 57 | init = function() { 58 | var passwordvm; 59 | passwordvm = new PasswordViewModel(); 60 | return ko.applyBindings(passwordvm); 61 | }; 62 | 63 | init(); 64 | 65 | }).call(this); 66 | -------------------------------------------------------------------------------- /public/js/reportBase.coffee: -------------------------------------------------------------------------------- 1 | 2 | # ViewModel--------------------------------------------------------------- 3 | ShowReportsViewModel = -> 4 | self = @ 5 | self.reports = ko.observableArray([]) 6 | self.reportNum = ko.observable(0) 7 | self.userId = ko.observable(null) 8 | self.pageNum = ko.computed(-> 9 | pageNum = Math.ceil(self.reportNum() / NUMOFPAGE) 10 | pageNum = 1 if pageNum == 0 11 | pageNum) 12 | 13 | self.currentPage = ko.observable(1) 14 | 15 | self 16 | 17 | # 初始化 --------------------------------------------------------------- 18 | 19 | # 每页显示的日报条数 20 | NUMOFPAGE = 4 21 | 22 | getReports = (userId=null)-> 23 | data = {page:reportvm.currentPage(), numOfPage:NUMOFPAGE, userId:userId} 24 | ReportModel.getReports(data, (response)-> 25 | return if response.state == 0 26 | reportvm.reports(response.data)) 27 | 28 | getReportNum = (userId=null)-> 29 | ReportModel.getReportNum(userId, (response)-> 30 | return if response.state == 0 31 | reportvm.reportNum(response.data)) 32 | 33 | window.initPageState = -> 34 | reportvm.reports([]) 35 | reportvm.reportNum(0) 36 | reportvm.userId(null) 37 | 38 | 39 | reportvm = new ShowReportsViewModel() 40 | ko.applyBindings(reportvm) 41 | 42 | window.getReports = getReports 43 | window.getReportNum = getReportNum 44 | window.reportvm = reportvm 45 | 46 | #翻页组件--------------------------------------- 47 | $("div.pagination").on("click", "button.pageNext", -> 48 | gotoPage(reportvm.currentPage()+1) 49 | false) 50 | 51 | $("div.pagination").on("click", "button.pagePre", -> 52 | gotoPage(reportvm.currentPage()-1) 53 | false) 54 | 55 | window.gotoPage = (page)-> 56 | reportvm.currentPage(page) 57 | getReports(reportvm.userId()) -------------------------------------------------------------------------------- /public/js/reportBase.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var NUMOFPAGE, ShowReportsViewModel, getReportNum, getReports, reportvm; 4 | 5 | ShowReportsViewModel = function() { 6 | var self; 7 | self = this; 8 | self.reports = ko.observableArray([]); 9 | self.reportNum = ko.observable(0); 10 | self.userId = ko.observable(null); 11 | self.pageNum = ko.computed(function() { 12 | var pageNum; 13 | pageNum = Math.ceil(self.reportNum() / NUMOFPAGE); 14 | if (pageNum === 0) { 15 | pageNum = 1; 16 | } 17 | return pageNum; 18 | }); 19 | self.currentPage = ko.observable(1); 20 | return self; 21 | }; 22 | 23 | NUMOFPAGE = 4; 24 | 25 | getReports = function(userId) { 26 | var data; 27 | if (userId == null) { 28 | userId = null; 29 | } 30 | data = { 31 | page: reportvm.currentPage(), 32 | numOfPage: NUMOFPAGE, 33 | userId: userId 34 | }; 35 | return ReportModel.getReports(data, function(response) { 36 | if (response.state === 0) { 37 | return; 38 | } 39 | return reportvm.reports(response.data); 40 | }); 41 | }; 42 | 43 | getReportNum = function(userId) { 44 | if (userId == null) { 45 | userId = null; 46 | } 47 | return ReportModel.getReportNum(userId, function(response) { 48 | if (response.state === 0) { 49 | return; 50 | } 51 | return reportvm.reportNum(response.data); 52 | }); 53 | }; 54 | 55 | window.initPageState = function() { 56 | reportvm.reports([]); 57 | reportvm.reportNum(0); 58 | return reportvm.userId(null); 59 | }; 60 | 61 | reportvm = new ShowReportsViewModel(); 62 | 63 | ko.applyBindings(reportvm); 64 | 65 | window.getReports = getReports; 66 | 67 | window.getReportNum = getReportNum; 68 | 69 | window.reportvm = reportvm; 70 | 71 | $("div.pagination").on("click", "button.pageNext", function() { 72 | gotoPage(reportvm.currentPage() + 1); 73 | return false; 74 | }); 75 | 76 | $("div.pagination").on("click", "button.pagePre", function() { 77 | gotoPage(reportvm.currentPage() - 1); 78 | return false; 79 | }); 80 | 81 | window.gotoPage = function(page) { 82 | reportvm.currentPage(page); 83 | return getReports(reportvm.userId()); 84 | }; 85 | 86 | }).call(this); 87 | -------------------------------------------------------------------------------- /public/js/showReports.coffee: -------------------------------------------------------------------------------- 1 | 2 | getReports() 3 | getReportNum() 4 | 5 | confirm = (reportId)-> 6 | $("#dialog-confirm").dialog({ 7 | dialogClass: "no-close", 8 | resizable: false, 9 | height:160, 10 | modal: true, 11 | buttons: { 12 | "删除": -> 13 | deleteReport(reportId) 14 | $(@).dialog("close") 15 | Cancel: -> 16 | $(this).dialog("close")}}) 17 | 18 | $("#reportList").on("click", "p.delete", -> 19 | reportId = $(this).attr("reportId") 20 | confirm(reportId)) 21 | 22 | 23 | deleteReport = (reportId)-> 24 | ReportModel.deleteReport({reportId:reportId}, (response)-> 25 | return if response.state == 0 26 | 27 | reportvm.reportNum(reportvm.reportNum()-1) 28 | page = reportvm.currentPage() 29 | if (reportvm.reports().length == 1 && reportvm.currentPage() > 1) 30 | page = reportvm.currentPage() - 1 31 | gotoPage(page)) 32 | -------------------------------------------------------------------------------- /public/js/showReports.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var confirm, deleteReport; 4 | 5 | getReports(); 6 | 7 | getReportNum(); 8 | 9 | confirm = function(reportId) { 10 | return $("#dialog-confirm").dialog({ 11 | dialogClass: "no-close", 12 | resizable: false, 13 | height: 160, 14 | modal: true, 15 | buttons: { 16 | "删除": function() { 17 | deleteReport(reportId); 18 | return $(this).dialog("close"); 19 | }, 20 | Cancel: function() { 21 | return $(this).dialog("close"); 22 | } 23 | } 24 | }); 25 | }; 26 | 27 | $("#reportList").on("click", "p.delete", function() { 28 | var reportId; 29 | reportId = $(this).attr("reportId"); 30 | return confirm(reportId); 31 | }); 32 | 33 | deleteReport = function(reportId) { 34 | return ReportModel.deleteReport({ 35 | reportId: reportId 36 | }, function(response) { 37 | var page; 38 | if (response.state === 0) { 39 | return; 40 | } 41 | reportvm.reportNum(reportvm.reportNum() - 1); 42 | page = reportvm.currentPage(); 43 | if (reportvm.reports().length === 1 && reportvm.currentPage() > 1) { 44 | page = reportvm.currentPage() - 1; 45 | } 46 | return gotoPage(page); 47 | }); 48 | }; 49 | 50 | }).call(this); 51 | -------------------------------------------------------------------------------- /public/js/subordinateReports.coffee: -------------------------------------------------------------------------------- 1 | treeList = new TreeList2("#userTree") 2 | 3 | ReportModel.getSubordinateUserAndDepartment((response)-> 4 | return if response.state == 0 5 | treeData = response.data 6 | treeList.renderTree("#userTree", treeData)) 7 | 8 | #设置用户编辑界面状态 9 | $("#userTree").on("review", (event)-> 10 | userId = event["itemId"] 11 | initPageState() 12 | reportvm.userId(userId) 13 | getReports(userId) 14 | getReportNum(userId)) 15 | -------------------------------------------------------------------------------- /public/js/subordinateReports.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var treeList; 4 | 5 | treeList = new TreeList2("#userTree"); 6 | 7 | ReportModel.getSubordinateUserAndDepartment(function(response) { 8 | var treeData; 9 | if (response.state === 0) { 10 | return; 11 | } 12 | treeData = response.data; 13 | return treeList.renderTree("#userTree", treeData); 14 | }); 15 | 16 | $("#userTree").on("review", function(event) { 17 | var userId; 18 | userId = event["itemId"]; 19 | initPageState(); 20 | reportvm.userId(userId); 21 | getReports(userId); 22 | return getReportNum(userId); 23 | }); 24 | 25 | }).call(this); 26 | -------------------------------------------------------------------------------- /public/js/writeReport.coffee: -------------------------------------------------------------------------------- 1 | validator = new Validator() 2 | editor = UE.getEditor('content') 3 | 4 | # ViewModel--------------------------------------------------------------- 5 | WriteReportViewModel = -> 6 | self = @ 7 | self.dateTxt = ko.observable(null) 8 | self.validDateTxt = ko.computed(-> 9 | dateStr = $.trim(self.dateTxt()) 10 | try 11 | validator.check(dateStr).notEmpty() 12 | [year, months, date] = dateStr.split("-") 13 | #console.log "#{year}-#{months}-#{date}" 14 | validator.check(year).notNull().isNumeric().len(4,4) 15 | validator.check(months).notNull().isNumeric().len(1,2) 16 | validator.check(date).notNull().isNumeric().len(1,2) 17 | return true 18 | catch error 19 | return false) 20 | 21 | self 22 | 23 | # 初始化 --------------------------------------------------------------- 24 | init = -> 25 | $("#dateTxt").datepicker(); 26 | $("#dateTxt").datepicker("option", "dateFormat", "yy-mm-dd") 27 | 28 | reportvm = new WriteReportViewModel() 29 | ko.applyBindings(reportvm) 30 | 31 | getDateStr = (date)-> 32 | today = new Date() 33 | year = date.getFullYear() 34 | month = date.getMonth() + 1 35 | date = date.getDate() 36 | return "#{year}-#{month}-#{date}" 37 | 38 | dateStr = getDateStr(new Date()) 39 | reportvm.dateTxt(dateStr) 40 | #console.log $("#dateTxt").datepicker("getDate") 41 | 42 | $("#reportSubmitBtn").click((event)-> 43 | return unless reportvm.validDateTxt() 44 | dateStr = getDateStr($("#dateTxt").datepicker("getDate")) 45 | data = {date:dateStr, content:editor.getContent()} 46 | ReportModel.createReport(data, (response)-> 47 | return if response.state == 0 48 | window.location.href = "/show")) 49 | 50 | init() -------------------------------------------------------------------------------- /public/js/writeReport.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var WriteReportViewModel, editor, init, validator; 4 | 5 | validator = new Validator(); 6 | 7 | editor = UE.getEditor('content'); 8 | 9 | WriteReportViewModel = function() { 10 | var self; 11 | self = this; 12 | self.dateTxt = ko.observable(null); 13 | self.validDateTxt = ko.computed(function() { 14 | var date, dateStr, months, year, _ref; 15 | dateStr = $.trim(self.dateTxt()); 16 | try { 17 | validator.check(dateStr).notEmpty(); 18 | _ref = dateStr.split("-"), year = _ref[0], months = _ref[1], date = _ref[2]; 19 | validator.check(year).notNull().isNumeric().len(4, 4); 20 | validator.check(months).notNull().isNumeric().len(1, 2); 21 | validator.check(date).notNull().isNumeric().len(1, 2); 22 | return true; 23 | } catch (error) { 24 | return false; 25 | } 26 | }); 27 | return self; 28 | }; 29 | 30 | init = function() { 31 | var dateStr, getDateStr, reportvm; 32 | $("#dateTxt").datepicker(); 33 | $("#dateTxt").datepicker("option", "dateFormat", "yy-mm-dd"); 34 | reportvm = new WriteReportViewModel(); 35 | ko.applyBindings(reportvm); 36 | getDateStr = function(date) { 37 | var month, today, year; 38 | today = new Date(); 39 | year = date.getFullYear(); 40 | month = date.getMonth() + 1; 41 | date = date.getDate(); 42 | return "" + year + "-" + month + "-" + date; 43 | }; 44 | dateStr = getDateStr(new Date()); 45 | reportvm.dateTxt(dateStr); 46 | return $("#reportSubmitBtn").click(function(event) { 47 | var data; 48 | if (!reportvm.validDateTxt()) { 49 | return; 50 | } 51 | dateStr = getDateStr($("#dateTxt").datepicker("getDate")); 52 | data = { 53 | date: dateStr, 54 | content: editor.getContent() 55 | }; 56 | return ReportModel.createReport(data, function(response) { 57 | if (response.state === 0) { 58 | return; 59 | } 60 | return window.location.href = "/show"; 61 | }); 62 | }); 63 | }; 64 | 65 | init(); 66 | 67 | }).call(this); 68 | -------------------------------------------------------------------------------- /public/mobile/css/images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/mobile/css/images/ajax-loader.gif -------------------------------------------------------------------------------- /public/mobile/css/images/icons-18-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/mobile/css/images/icons-18-black.png -------------------------------------------------------------------------------- /public/mobile/css/images/icons-18-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/mobile/css/images/icons-18-white.png -------------------------------------------------------------------------------- /public/mobile/css/images/icons-36-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/mobile/css/images/icons-36-black.png -------------------------------------------------------------------------------- /public/mobile/css/images/icons-36-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/mobile/css/images/icons-36-white.png -------------------------------------------------------------------------------- /public/mobile/css/reportStyle.css: -------------------------------------------------------------------------------- 1 | body.subordinate .navbar { 2 | margin-bottom: 0; 3 | } 4 | body.subordinate #userList { 5 | float: left; 6 | margin-top: 0px; 7 | border-right: 1px solid #E5E5E5; 8 | padding: 10px 16px 10px 0; 9 | height: 91%; 10 | width: 310px; 11 | } 12 | body.subordinate #userList div.title { 13 | padding-left: 15px; 14 | } 15 | body.subordinate #userList #userTree { 16 | margin: 0 10px 0 0; 17 | padding: 0; 18 | width: 300px; 19 | } 20 | body.subordinate #reports { 21 | float: left; 22 | padding-left: 30px; 23 | width: 65%; 24 | } 25 | body.subordinate #reports li.report { 26 | border-bottom: 1px solid #E5E5E5; 27 | } 28 | #reportList { 29 | color: #555; 30 | } 31 | #reportList li.report { 32 | border-bottom: 1px solid #E5E5E5; 33 | padding: 10px; 34 | margin-bottom: 15px; 35 | float: left; 36 | width: 100%; 37 | } 38 | #reportList li.report .date span { 39 | font-size: 18px; 40 | font-weight: bold; 41 | color: #1a700b; 42 | padding-left: 5px; 43 | } 44 | #reportList li.report .content { 45 | margin: 0; 46 | padding: 0; 47 | } 48 | #reportList li.report .reply, 49 | #reportList li.report .delete { 50 | float: right; 51 | padding: 0 20px 0 0; 52 | } 53 | div.pageination { 54 | opacity: 0; 55 | } 56 | div.pageination div.pagetip { 57 | text-align: center; 58 | padding-top: 15px; 59 | } 60 | div.pageination div.aligncenter { 61 | text-align: center; 62 | } 63 | -------------------------------------------------------------------------------- /public/mobile/css/reportStyle.less: -------------------------------------------------------------------------------- 1 | 2 | 3 | //查看下属日报页面 4 | body.subordinate { 5 | .navbar { 6 | margin-bottom: 0;} 7 | 8 | 9 | 10 | #userList { 11 | float:left; 12 | margin-top: 0px; 13 | border-right: 1px solid #E5E5E5; 14 | padding: 10px 16px 10px 0; 15 | height:91%; 16 | width: 310px; 17 | 18 | div.title { 19 | padding-left:15px; 20 | } 21 | 22 | #userTree { 23 | margin:0 10px 0 0; 24 | padding:0; 25 | width: 300px; 26 | } 27 | } 28 | 29 | #reports { 30 | float:left; 31 | padding-left: 30px; 32 | //background-color: #f00; 33 | //min-width:400px; 34 | 35 | 36 | li.report { 37 | //background-color: #eeeeee; 38 | border-bottom: 1px solid #E5E5E5; 39 | } 40 | width:65%; 41 | } 42 | 43 | 44 | } 45 | 46 | //查看我的日报页面 47 | #reportList { 48 | color: #555; 49 | li.report { 50 | //background-color: #eeeeee; 51 | border-bottom: 1px solid #E5E5E5; 52 | //border-radius: 5px 5px 5px 5px; 53 | padding: 10px; 54 | margin-bottom:15px; 55 | float:left; 56 | width:100%; 57 | .date span{ 58 | font-size: 18px; 59 | font-weight: bold; 60 | color: #1a700b; 61 | padding-left:5px; 62 | } 63 | 64 | .content{ 65 | margin:0; 66 | padding:0; 67 | } 68 | 69 | .reply, .delete { 70 | float: right; 71 | padding: 0 20px 0 0; 72 | 73 | } 74 | } 75 | } 76 | 77 | div.pageination { 78 | opacity: 0; 79 | 80 | div.pagetip { 81 | text-align:center; 82 | padding-top: 15px; 83 | } 84 | 85 | div.aligncenter { 86 | text-align:center; 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /public/mobile/js/Model.coffee: -------------------------------------------------------------------------------- 1 | # model层,处理数据调用和解析 --------------------------------------------------------------- 2 | class Model 3 | 4 | @login: (data, callback)-> 5 | $.post("/login", data, (response)-> 6 | callback(response) 7 | , "json") 8 | 9 | @logout: (callback)-> 10 | $.post("/m/logout", (response)-> 11 | callback(response) 12 | , "json") 13 | 14 | @createReport: (data, callback)-> 15 | $.post("/write", data, (response)-> 16 | callback(response) 17 | , "json") 18 | 19 | @deleteReport: (data, callback)-> 20 | $.post("/delete", data, (response)-> 21 | callback(response) 22 | , "json") 23 | 24 | @getReportNum: (userId, callback)-> 25 | $.post("/getreportnum", {userId:userId}, (response)-> 26 | callback(response) 27 | , "json") 28 | 29 | @getSubordinateUserAndDepartment: (callback)-> 30 | $.post("/getsubordinateuseranddepartment",(response)-> 31 | callback(response) 32 | , "json") 33 | 34 | #返回数据格式为[ { date: '2013-4-30',cotent: '


      4.30 reports' },{ date: '2013-4-30',content: '4.30 reports' }] 35 | @getReports: (data, callback)-> 36 | $.post("/getreports", data, (response)-> 37 | callback(response) 38 | , "json") 39 | 40 | @changePassword: (data, callback)-> 41 | $.post("/password", data, (response)-> 42 | if response.state == 1 43 | callback(response) 44 | ,"json") 45 | 46 | window.Model = Model -------------------------------------------------------------------------------- /public/mobile/js/Model.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var Model; 4 | 5 | Model = (function() { 6 | 7 | function Model() {} 8 | 9 | Model.login = function(data, callback) { 10 | return $.post("/login", data, function(response) { 11 | return callback(response); 12 | }, "json"); 13 | }; 14 | 15 | Model.logout = function(callback) { 16 | return $.post("/m/logout", function(response) { 17 | return callback(response); 18 | }, "json"); 19 | }; 20 | 21 | Model.createReport = function(data, callback) { 22 | return $.post("/write", data, function(response) { 23 | return callback(response); 24 | }, "json"); 25 | }; 26 | 27 | Model.deleteReport = function(data, callback) { 28 | return $.post("/delete", data, function(response) { 29 | return callback(response); 30 | }, "json"); 31 | }; 32 | 33 | Model.getReportNum = function(userId, callback) { 34 | return $.post("/getreportnum", { 35 | userId: userId 36 | }, function(response) { 37 | return callback(response); 38 | }, "json"); 39 | }; 40 | 41 | Model.getSubordinateUserAndDepartment = function(callback) { 42 | return $.post("/getsubordinateuseranddepartment", function(response) { 43 | return callback(response); 44 | }, "json"); 45 | }; 46 | 47 | Model.getReports = function(data, callback) { 48 | return $.post("/getreports", data, function(response) { 49 | return callback(response); 50 | }, "json"); 51 | }; 52 | 53 | Model.changePassword = function(data, callback) { 54 | return $.post("/password", data, function(response) { 55 | if (response.state === 1) { 56 | return callback(response); 57 | } 58 | }, "json"); 59 | }; 60 | 61 | return Model; 62 | 63 | })(); 64 | 65 | window.Model = Model; 66 | 67 | }).call(this); 68 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/highlightcode/highlightcode.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 16 | 17 | 18 |
      19 |

      20 | 21 | 47 |

      48 | 49 |
      50 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/internal.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var parent = window.parent; 3 | //dialog对象 4 | dialog = parent.$EDITORUI[window.frameElement.id.replace( /_iframe$/, '' )]; 5 | //当前打开dialog的编辑器实例 6 | editor = dialog.editor; 7 | 8 | UE = parent.UE; 9 | 10 | domUtils = UE.dom.domUtils; 11 | 12 | utils = UE.utils; 13 | 14 | browser = UE.browser; 15 | 16 | ajax = UE.ajax; 17 | 18 | $G = function ( id ) { 19 | return document.getElementById( id ) 20 | }; 21 | //focus元素 22 | $focus = function ( node ) { 23 | setTimeout( function () { 24 | if ( browser.ie ) { 25 | var r = node.createTextRange(); 26 | r.collapse( false ); 27 | r.select(); 28 | } else { 29 | node.focus() 30 | } 31 | }, 0 ) 32 | }; 33 | utils.loadFile(document,{ 34 | href:editor.options.themePath + editor.options.theme + "/dialogbase.css?cache="+Math.random(), 35 | tag:"link", 36 | type:"text/css", 37 | rel:"stylesheet" 38 | }); 39 | lang = editor.getLang(dialog.className.split( "-" )[2]); 40 | 41 | domUtils.on(window,'load',function () { 42 | 43 | var langImgPath = editor.options.langPath + editor.options.lang + "/images/"; 44 | //针对静态资源 45 | for ( var i in lang.static ) { 46 | var dom = $G( i ); 47 | if(!dom) continue; 48 | var tagName = dom.tagName, 49 | content = lang.static[i]; 50 | if(content.src){ 51 | //clone 52 | content = utils.extend({},content,false); 53 | content.src = langImgPath + content.src; 54 | } 55 | if(content.style){ 56 | content = utils.extend({},content,false); 57 | content.style = content.style.replace(/url\s*\(/g,"url(" + langImgPath) 58 | } 59 | switch ( tagName.toLowerCase() ) { 60 | case "var": 61 | dom.parentNode.replaceChild( document.createTextNode( content ), dom ); 62 | break; 63 | case "select": 64 | var ops = dom.options; 65 | for ( var j = 0, oj; oj = ops[j]; ) { 66 | oj.innerHTML = content.options[j++]; 67 | } 68 | for ( var p in content ) { 69 | p != "options" && dom.setAttribute( p, content[p] ); 70 | } 71 | break; 72 | default : 73 | domUtils.setAttributes( dom, content); 74 | } 75 | } 76 | } ); 77 | 78 | })(); 79 | 80 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/link/link.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 33 | 34 | 35 | 36 | 37 |
      30 | 31 | 32 |
      38 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/spechars/spechars.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 |
      17 |
      18 |
      19 | 20 | 21 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/spechars/spechars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains PhpStorm. 3 | * User: xuheng 4 | * Date: 12-9-26 5 | * Time: 下午1:09 6 | * To change this template use File | Settings | File Templates. 7 | */ 8 | var charsContent = [ 9 | { name:"tsfh", title:lang.tsfh, content:toArray("、,。,·,ˉ,ˇ,¨,〃,々,—,~,‖,…,‘,’,“,”,〔,〕,〈,〉,《,》,「,」,『,』,〖,〗,【,】,±,×,÷,∶,∧,∨,∑,∏,∪,∩,∈,∷,√,⊥,∥,∠,⌒,⊙,∫,∮,≡,≌,≈,∽,∝,≠,≮,≯,≤,≥,∞,∵,∴,♂,♀,°,′,″,℃,$,¤,¢,£,‰,§,№,☆,★,○,●,◎,◇,◆,□,■,△,▲,※,→,←,↑,↓,〓,〡,〢,〣,〤,〥,〦,〧,〨,〩,㊣,㎎,㎏,㎜,㎝,㎞,㎡,㏄,㏎,㏑,㏒,㏕,︰,¬,¦,℡,ˊ,ˋ,˙,–,―,‥,‵,℅,℉,↖,↗,↘,↙,∕,∟,∣,≒,≦,≧,⊿,═,║,╒,╓,╔,╕,╖,╗,╘,╙,╚,╛,╜,╝,╞,╟,╠,╡,╢,╣,╤,╥,╦,╧,╨,╩,╪,╫,╬,╭,╮,╯,╰,╱,╲,╳,▁,▂,▃,▄,▅,▆,▇,�,█,▉,▊,▋,▌,▍,▎,▏,▓,▔,▕,▼,▽,◢,◣,◤,◥,☉,⊕,〒,〝,〞")}, 10 | { name:"lmsz", title:lang.lmsz, content:toArray("ⅰ,ⅱ,ⅲ,ⅳ,ⅴ,ⅵ,ⅶ,ⅷ,ⅸ,ⅹ,Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ,Ⅷ,Ⅸ,Ⅹ,Ⅺ,Ⅻ")}, 11 | { name:"szfh", title:lang.szfh, content:toArray("⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛,⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿,⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,㈠,㈡,㈢,㈣,㈤,㈥,㈦,㈧,㈨,㈩")}, 12 | { name:"rwfh", title:lang.rwfh, content:toArray("ぁ,あ,ぃ,い,ぅ,う,ぇ,え,ぉ,お,か,が,き,ぎ,く,ぐ,け,げ,こ,ご,さ,ざ,し,じ,す,ず,せ,ぜ,そ,ぞ,た,だ,ち,ぢ,っ,つ,づ,て,で,と,ど,な,に,ぬ,ね,の,は,ば,ぱ,ひ,び,ぴ,ふ,ぶ,ぷ,へ,べ,ぺ,ほ,ぼ,ぽ,ま,み,む,め,も,ゃ,や,ゅ,ゆ,ょ,よ,ら,り,る,れ,ろ,ゎ,わ,ゐ,ゑ,を,ん,ァ,ア,ィ,イ,ゥ,ウ,ェ,エ,ォ,オ,カ,ガ,キ,ギ,ク,グ,ケ,ゲ,コ,ゴ,サ,ザ,シ,ジ,ス,ズ,セ,ゼ,ソ,ゾ,タ,ダ,チ,ヂ,ッ,ツ,ヅ,テ,デ,ト,ド,ナ,ニ,ヌ,ネ,ノ,ハ,バ,パ,ヒ,ビ,ピ,フ,ブ,プ,ヘ,ベ,ペ,ホ,ボ,ポ,マ,ミ,ム,メ,モ,ャ,ヤ,ュ,ユ,ョ,ヨ,ラ,リ,ル,レ,ロ,ヮ,ワ,ヰ,ヱ,ヲ,ン,ヴ,ヵ,ヶ")}, 13 | { name:"xlzm", title:lang.xlzm, content:toArray("Α,Β,Γ,Δ,Ε,Ζ,Η,Θ,Ι,Κ,Λ,Μ,Ν,Ξ,Ο,Π,Ρ,Σ,Τ,Υ,Φ,Χ,Ψ,Ω,α,β,γ,δ,ε,ζ,η,θ,ι,κ,λ,μ,ν,ξ,ο,π,ρ,σ,τ,υ,φ,χ,ψ,ω")}, 14 | { name:"ewzm", title:lang.ewzm, content:toArray("А,Б,В,Г,Д,Е,Ё,Ж,З,И,Й,К,Л,М,Н,О,П,Р,С,Т,У,Ф,Х,Ц,Ч,Ш,Щ,Ъ,Ы,Ь,Э,Ю,Я,а,б,в,г,д,е,ё,ж,з,и,й,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,ъ,ы,ь,э,ю,я")}, 15 | { name:"pyzm", title:lang.pyzm, content:toArray("ā,á,ǎ,à,ē,é,ě,è,ī,í,ǐ,ì,ō,ó,ǒ,ò,ū,ú,ǔ,ù,ǖ,ǘ,ǚ,ǜ,ü")}, 16 | { name:"zyzf", title:lang.zyzf, content:toArray("ㄅ,ㄆ,ㄇ,ㄈ,ㄉ,ㄊ,ㄋ,ㄌ,ㄍ,ㄎ,ㄏ,ㄐ,ㄑ,ㄒ,ㄓ,ㄔ,ㄕ,ㄖ,ㄗ,ㄘ,ㄙ,ㄚ,ㄛ,ㄜ,ㄝ,ㄞ,ㄟ,ㄠ,ㄡ,ㄢ,ㄣ,ㄤ,ㄥ,ㄦ,ㄧ,ㄨ")} 17 | ]; 18 | (function createTab(content) { 19 | for (var i = 0, ci; ci = content[i++];) { 20 | var span = document.createElement("span"); 21 | span.setAttribute("tabSrc", ci.name); 22 | span.innerHTML = ci.title; 23 | if (i == 1)span.className = "focus"; 24 | domUtils.on(span, "click", function () { 25 | var tmps = $G("tabHeads").children; 26 | for (var k = 0, sk; sk = tmps[k++];) { 27 | sk.className = ""; 28 | } 29 | tmps = $G("tabBodys").children; 30 | for (var k = 0, sk; sk = tmps[k++];) { 31 | sk.style.display = "none"; 32 | } 33 | this.className = "focus"; 34 | $G(this.getAttribute("tabSrc")).style.display = ""; 35 | }); 36 | $G("tabHeads").appendChild(span); 37 | domUtils.insertAfter(span, document.createTextNode("\n")); 38 | var div = document.createElement("div"); 39 | div.id = ci.name; 40 | div.style.display = (i == 1) ? "" : "none"; 41 | var cons = ci.content; 42 | for (var j = 0, con; con = cons[j++];) { 43 | var charSpan = document.createElement("span"); 44 | charSpan.innerHTML = con; 45 | domUtils.on(charSpan, "click", function () { 46 | editor.execCommand("insertHTML", this.innerHTML); 47 | dialog.close(); 48 | }); 49 | div.appendChild(charSpan); 50 | } 51 | $G("tabBodys").appendChild(div); 52 | } 53 | })(charsContent); 54 | function toArray(str) { 55 | return str.split(","); 56 | } 57 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/table/dragicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/dialogs/table/dragicon.png -------------------------------------------------------------------------------- /public/ueditor/dialogs/table/edittable.css: -------------------------------------------------------------------------------- 1 | .wrapper { 2 | margin: 10px auto 0; 3 | font-size: 12px; 4 | overflow: hidden; 5 | } 6 | 7 | .clear { 8 | clear: both; 9 | } 10 | 11 | .wrapper .left { 12 | float: left; 13 | margin-left: 10px;; 14 | } 15 | 16 | .wrapper .right { 17 | float: right; 18 | margin-right: 10px; 19 | border-left: 2px dotted #EDEDED; 20 | padding-left: 15px; 21 | } 22 | 23 | .section { 24 | margin-bottom: 20px; 25 | overflow: hidden; 26 | } 27 | 28 | .section h3 { 29 | font-weight: bold; 30 | padding: 5px 0; 31 | margin-bottom: 10px; 32 | border-bottom: 1px solid #EDEDED; 33 | font-size: 12px; 34 | } 35 | 36 | .section ul { 37 | list-style: none; 38 | overflow: hidden; 39 | } 40 | 41 | .section li { 42 | float: left; 43 | } 44 | 45 | .section .tone { 46 | width: 80px;; 47 | } 48 | 49 | .section .preview { 50 | width: 220px; 51 | } 52 | 53 | .section .preview table { 54 | text-align: center; 55 | vertical-align: middle; 56 | color: #666; 57 | } 58 | 59 | .section .preview caption { 60 | font-weight: bold; 61 | } 62 | 63 | .section .preview td { 64 | border-width: 1px; 65 | border-style: solid; 66 | height: 22px; 67 | } 68 | 69 | .section .preview th { 70 | border-style: solid; 71 | border-color: #DDD; 72 | border-width: 2px 1px 1px 1px; 73 | height: 22px; 74 | background-color: #F7F7F7; 75 | } -------------------------------------------------------------------------------- /public/ueditor/dialogs/table/edittable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
      10 |
      11 |
      12 |

      13 |
        14 |
      • 15 | 16 |
      • 17 |
      • 18 | 19 |
      • 20 |
      21 |
      22 |
      23 |
      24 |

      25 |
        26 |
      • 27 | 28 |
      • 29 |
      • 30 | 31 |
      • 32 |
      33 |
      34 |
      35 |
      36 |

      37 |
        38 |
      • 39 | 40 | 41 |
      • 42 |
      43 |
      44 |
      45 |
      46 |
      47 |
      48 |

      49 |
      50 |
      51 |
      52 |
      53 |
      54 | 55 | 56 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/table/edittd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 16 | 17 | 18 |
      19 | 20 | 21 |
      22 | 49 | 50 | -------------------------------------------------------------------------------- /public/ueditor/dialogs/table/edittip.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 表格删除提示 5 | 6 | 17 | 18 | 19 |
      20 |
      21 | 22 |
      23 |
      24 | 25 |
      26 |
      27 | 32 | 33 | -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/addimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/addimage.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/alldeletebtnhoverskin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/alldeletebtnhoverskin.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/alldeletebtnupskin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/alldeletebtnupskin.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/background.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/button.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/copy.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/deletedisable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/deletedisable.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/deleteenable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/deleteenable.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/imglabel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/imglabel.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/listbackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/listbackground.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/localimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/localimage.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/music.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/rotateleftdisable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/rotateleftdisable.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/rotateleftenable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/rotateleftenable.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/rotaterightdisable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/rotaterightdisable.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/rotaterightenable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/rotaterightenable.png -------------------------------------------------------------------------------- /public/ueditor/lang/en/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/en/images/upload.png -------------------------------------------------------------------------------- /public/ueditor/lang/zh-cn/images/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/zh-cn/images/copy.png -------------------------------------------------------------------------------- /public/ueditor/lang/zh-cn/images/imglabel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/zh-cn/images/imglabel.png -------------------------------------------------------------------------------- /public/ueditor/lang/zh-cn/images/localimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/zh-cn/images/localimage.png -------------------------------------------------------------------------------- /public/ueditor/lang/zh-cn/images/music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/zh-cn/images/music.png -------------------------------------------------------------------------------- /public/ueditor/lang/zh-cn/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/lang/zh-cn/images/upload.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/dialogbase.css: -------------------------------------------------------------------------------- 1 | /*弹出对话框页面样式组件 2 | */ 3 | 4 | /*reset 5 | */ 6 | html, body, div, span, applet, object, iframe, 7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 8 | a, abbr, acronym, address, big, cite, code, 9 | del, dfn, em, font, img, ins, kbd, q, s, samp, 10 | small, strike, strong, sub, sup, tt, var, 11 | b, u, i, center, 12 | dl, dt, dd, ol, ul, li, 13 | fieldset, form, label, legend, 14 | table, caption, tbody, tfoot, thead, tr, th, td { 15 | margin: 0; 16 | padding: 0; 17 | outline: 0; 18 | font-size: 100%; 19 | } 20 | 21 | body { 22 | line-height: 1; 23 | } 24 | 25 | ol, ul { 26 | list-style: none; 27 | } 28 | 29 | blockquote, q { 30 | quotes: none; 31 | } 32 | 33 | ins { 34 | text-decoration: none; 35 | } 36 | 37 | del { 38 | text-decoration: line-through; 39 | } 40 | 41 | table { 42 | border-collapse: collapse; 43 | border-spacing: 0; 44 | } 45 | 46 | /*module 47 | */ 48 | body { 49 | background-color: #fff; 50 | font: 12px/1.5 "宋体", "Arial Narrow", HELVETICA; 51 | color: #646464; 52 | } 53 | 54 | /*tab*/ 55 | .tabhead { 56 | position: relative; 57 | z-index: 10; 58 | } 59 | 60 | .tabhead span { 61 | display: inline-block; 62 | padding: 0 5px; 63 | height: 30px; 64 | border: 1px solid #ccc; 65 | background: url("images/dialog-title-bg.png") repeat-x; 66 | text-align: center; 67 | line-height: 30px; 68 | cursor: pointer; 69 | *margin-right: 5px; 70 | } 71 | 72 | .tabhead span.focus { 73 | height: 31px; 74 | border-bottom: none; 75 | background: #fff; 76 | } 77 | 78 | .tabbody { 79 | position: relative; 80 | top: -1px; 81 | margin: 0 auto; 82 | border: 1px solid #ccc; 83 | } 84 | 85 | /*button*/ 86 | a.button { 87 | display: block; 88 | text-align: center; 89 | line-height: 24px; 90 | text-decoration: none; 91 | height: 24px; 92 | width: 95px; 93 | border: 0; 94 | color: #838383; 95 | background: url(../../themes/default/images/icons-all.gif) no-repeat; 96 | } 97 | 98 | a.button:hover { 99 | background-position: 0 -30px; 100 | } -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/anchor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/anchor.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/arrow.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/button-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/button-bg.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/cancelbutton.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/cancelbutton.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/cursor_h.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/cursor_h.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/cursor_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/cursor_h.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/cursor_v.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/cursor_v.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/cursor_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/cursor_v.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/dialog-title-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/dialog-title-bg.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/filescan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/filescan.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/highlighted.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/highlighted.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/icons-all.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/icons-all.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/icons.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/icons.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/icons.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/lock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/lock.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/neweditor-tab-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/neweditor-tab-bg.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/pagebreak.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/pagebreak.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/scale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/scale.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/spacer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/spacer.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/sparator_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/sparator_v.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/toolbar_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/toolbar_bg.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/unhighlighted.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/unhighlighted.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/upload.png -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/videologo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/videologo.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/word.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/word.gif -------------------------------------------------------------------------------- /public/ueditor/themes/default/images/wordpaste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WalterShe/dailyReport/e3fcff6ec9b2f2372f85c38b30898b03521dcc3f/public/ueditor/themes/default/images/wordpaste.png -------------------------------------------------------------------------------- /public/ueditor/themes/iframe.css: -------------------------------------------------------------------------------- 1 | /*可以在这里添加你自己的css*/ 2 | -------------------------------------------------------------------------------- /routes/routeProfile.coffee: -------------------------------------------------------------------------------- 1 | 2 | user = require('../controlers/userCtr') 3 | department = require('../controlers/departmentCtr') 4 | admin = require('../controlers/adminCtr') 5 | report = require('../controlers/reportCtr') 6 | installer = require('../controlers/installCtr') 7 | 8 | exports.createRutes = (app)-> 9 | app.get('/install', installer.install) 10 | app.get('/', report.index); 11 | app.get('/write', report.writeIndex); 12 | app.post('/write', report.write); 13 | app.get('/password', user.passwordIndex); 14 | app.post('/password', user.changePassword); 15 | app.post('/delete', report.delete); 16 | app.get('/show', report.showIndex); 17 | app.post('/getsubordinateuseranddepartment', report.getSubordinateUserAndDepartment); 18 | app.get('/showsubordinate', report.showsubordinateIndex); 19 | app.post('/getreports', report.getReports); 20 | app.post('/getreportnum', report.getReportNum); 21 | app.get('/login', user.loginIndex); 22 | app.get('/logout', user.logout); 23 | app.post('/login', user.login); 24 | app.post('/admin/createuser', user.createUser); 25 | app.post('/admin/removeuser', user.removeUser); 26 | app.get('/admin/getallusers', user.getAllUsers); 27 | app.post('/admin/updateuser', user.updateUser); 28 | app.post('/admin/hasuser', user.hasUser); 29 | 30 | app.get('/admin', admin.index); 31 | app.get('/admin/users', admin.usersIndex); 32 | app.get('/admin/admingroup', admin.admingroupIndex); 33 | 34 | app.post('/admin/createdepartment', department.createDepartment); 35 | app.get('/admin/alldepartments', department.getAllDepartments); 36 | app.post('/admin/removedepartment', department.removeDepartment); 37 | app.post('/admin/updatedepartment', department.updateDepartment); 38 | 39 | app.post('/admin/setadmin', user.setAdmin); 40 | app.post('/admin/deleteadmin', user.deleteAdmin); 41 | app.post('/admin/getadmins', user.getAdmins); 42 | 43 | app.get('/m', user.indexMobile); 44 | app.get('/m/login', user.loginIndexMobile); 45 | app.get('/m/show', report.showIndexMobile); 46 | app.get('/m/write', report.writeIndexMobile); 47 | app.get('/m/showsubordinate', report.subordinateIndexMobile); 48 | app.get('/m/setting', report.settingMobile); 49 | app.get('/m/logout', user.logoutMobileIndex); 50 | app.get('/m/password', user.passwordMobileIndex) -------------------------------------------------------------------------------- /routes/routeProfile.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var admin, department, installer, report, user; 4 | 5 | user = require('../controlers/userCtr'); 6 | 7 | department = require('../controlers/departmentCtr'); 8 | 9 | admin = require('../controlers/adminCtr'); 10 | 11 | report = require('../controlers/reportCtr'); 12 | 13 | installer = require('../controlers/installCtr'); 14 | 15 | exports.createRoutes = function(app) { 16 | app.get('/install', installer.install); 17 | app.get('/', report.index); 18 | app.get('/write', report.writeIndex); 19 | app.post('/write', report.write); 20 | app.get('/password', user.passwordIndex); 21 | app.post('/password', user.changePassword); 22 | app.post('/delete', report["delete"]); 23 | app.get('/show', report.showIndex); 24 | app.post('/getsubordinateuseranddepartment', report.getSubordinateUserAndDepartment); 25 | app.get('/showsubordinate', report.showsubordinateIndex); 26 | app.post('/getreports', report.getReports); 27 | app.post('/getreportnum', report.getReportNum); 28 | app.get('/login', user.loginIndex); 29 | app.get('/logout', user.logout); 30 | app.post('/login', user.login); 31 | app.post('/admin/createuser', user.createUser); 32 | app.post('/admin/removeuser', user.removeUser); 33 | app.get('/admin/getallusers', user.getAllUsers); 34 | app.post('/admin/updateuser', user.updateUser); 35 | app.post('/admin/hasuser', user.hasUser); 36 | app.get('/admin', admin.index); 37 | app.get('/admin/users', admin.usersIndex); 38 | app.get('/admin/admingroup', admin.admingroupIndex); 39 | app.post('/admin/createdepartment', department.createDepartment); 40 | app.get('/admin/alldepartments', department.getAllDepartments); 41 | app.post('/admin/removedepartment', department.removeDepartment); 42 | app.post('/admin/updatedepartment', department.updateDepartment); 43 | app.post('/admin/setadmin', user.setAdmin); 44 | app.post('/admin/deleteadmin', user.deleteAdmin); 45 | app.post('/admin/getadmins', user.getAdmins); 46 | app.get('/m', user.indexMobile); 47 | app.get('/m/login', user.loginIndexMobile); 48 | app.get('/m/show', report.showIndexMobile); 49 | app.get('/m/write', report.writeIndexMobile); 50 | app.get('/m/showsubordinate', report.subordinateIndexMobile); 51 | app.get('/m/setting', report.settingMobile); 52 | app.get('/m/logout', user.logoutMobileIndex); 53 | return app.get('/m/password', user.passwordMobileIndex); 54 | }; 55 | 56 | }).call(this); 57 | -------------------------------------------------------------------------------- /utils.coffee: -------------------------------------------------------------------------------- 1 | redis = require("redis") 2 | {Response} = require('./vo/Response') 3 | dbconfig = require('./config').db 4 | 5 | 6 | #如果用户登陆了,返回true,否则返回false,并且转向登陆界面 7 | exports.authenticateUser = (req,res)-> 8 | result = @isLoginUser(req) 9 | path = "/login" 10 | path = "/m/login" if @isMobileClient(req) 11 | res.redirect(path) unless result 12 | 13 | result 14 | 15 | exports.isMobileClient = (req)-> 16 | urlArray = req.path.split("/") 17 | #console.log urlArray 18 | urlArray[1] == "m" 19 | 20 | #如果用户登陆了,返回true,否则返回false 21 | exports.isLoginUser = (req)-> 22 | req.session?.userId and true 23 | 24 | 25 | #如果用户是管理员,返回true,否则返回false ,并且转向登陆界面 26 | exports.authenticateAdmin = (req,res)-> 27 | result = @isAdmin(req) 28 | unless result 29 | if @isLoginUser(req) 30 | res.redirect('/show') 31 | else 32 | res.redirect('/login') 33 | 34 | result 35 | 36 | #如果用户是管理员,返回true,否则返回false 37 | exports.isAdmin = (req)-> 38 | @isLoginUser(req) and req.session.isAdmin == 1 39 | 40 | exports.showDBError = (callback, client=null, message='数据库错误')-> 41 | client.quit() if client 42 | callback(new Response(0,message)) 43 | 44 | exports.createClient = -> 45 | client = redis.createClient(dbconfig.port, dbconfig.host) 46 | if dbconfig.pass 47 | client.auth(dbconfig.pass, (err)-> 48 | throw err if err) 49 | 50 | client.on("error", (err)-> 51 | console.log(err) 52 | client.end()) 53 | 54 | client 55 | 56 | 57 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var Response, dbconfig, redis; 4 | 5 | redis = require("redis"); 6 | 7 | Response = require('./vo/Response').Response; 8 | 9 | dbconfig = require('./config').db; 10 | 11 | exports.authenticateUser = function(req, res) { 12 | var path, result; 13 | result = this.isLoginUser(req); 14 | path = "/login"; 15 | if (this.isMobileClient(req)) { 16 | path = "/m/login"; 17 | } 18 | if (!result) { 19 | res.redirect(path); 20 | } 21 | return result; 22 | }; 23 | 24 | exports.isMobileClient = function(req) { 25 | var urlArray; 26 | urlArray = req.path.split("/"); 27 | return urlArray[1] === "m"; 28 | }; 29 | 30 | exports.isLoginUser = function(req) { 31 | var _ref; 32 | return ((_ref = req.session) != null ? _ref.userId : void 0) && true; 33 | }; 34 | 35 | exports.authenticateAdmin = function(req, res) { 36 | var result; 37 | result = this.isAdmin(req); 38 | if (!result) { 39 | if (this.isLoginUser(req)) { 40 | res.redirect('/show'); 41 | } else { 42 | res.redirect('/login'); 43 | } 44 | } 45 | return result; 46 | }; 47 | 48 | exports.isAdmin = function(req) { 49 | return this.isLoginUser(req) && req.session.isAdmin === 1; 50 | }; 51 | 52 | exports.showDBError = function(callback, client, message) { 53 | if (client == null) { 54 | client = null; 55 | } 56 | if (message == null) { 57 | message = '数据库错误'; 58 | } 59 | if (client) { 60 | client.quit(); 61 | } 62 | return callback(new Response(0, message)); 63 | }; 64 | 65 | exports.createClient = function() { 66 | var client; 67 | client = redis.createClient(dbconfig.port, dbconfig.host); 68 | if (dbconfig.pass) { 69 | client.auth(dbconfig.pass, function(err) { 70 | if (err) { 71 | throw err; 72 | } 73 | }); 74 | } 75 | client.on("error", function(err) { 76 | console.log(err); 77 | return client.end(); 78 | }); 79 | return client; 80 | }; 81 | 82 | }).call(this); 83 | -------------------------------------------------------------------------------- /views/admin/admingroup.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 管理员设置-日报后台管理系统 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 26 |
      27 |
      28 |

      添加管理员

      29 | 30 | 32 | 33 | 35 |
      37 |
      38 | 39 |
      40 |

      管理员列表

      41 |
        42 |
      • 43 |
      44 |
      45 |
      46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /views/admin/department.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 部门信息-日报后台管理系统 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 26 |
      27 |
      28 |

      创建新部门

      29 |

      编辑部门

      30 |
      31 | 32 |
      33 |
      34 | 35 |
      36 | 37 | 38 | 40 |
      42 | 43 |
      45 |
      47 |
      48 | 49 |
      50 | 51 |
      52 |
      53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /views/admin/users.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 用户管理-日报后台管理 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 23 | 26 |
      27 |
      28 |

      创建新用户

      29 | 32 | 34 |
      35 | 37 | 39 | 41 | 43 |
      44 | 45 | 47 | 48 | 50 |
      52 |
      53 |
      54 |

      更新用户信息

      55 | 57 | 59 |
      60 | 62 | 64 | 66 | 68 |
      69 | 70 | 72 | 73 | 75 |
      77 | 78 |
      79 |
      80 |
      81 |
      82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /views/install.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Install-Daily Report 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 |
      16 |

      恭喜,安装成功!

      17 |

      管理员账户名为:admin,密码:1234567。登陆后进入“管理员控制台”开始设置部门和添加成员

      18 |
      19 | 20 | -------------------------------------------------------------------------------- /views/login.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Login-Daily Report 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 |
      16 |

      用户登陆

      17 |

      18 | 19 | 21 |
      22 | 23 | 25 |
      26 |
      28 |
      29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /views/mobile/layout.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{title}} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {{{body}}} 17 | 18 | -------------------------------------------------------------------------------- /views/mobile/login.hbs: -------------------------------------------------------------------------------- 1 |
      2 |
      3 |

      登录

      4 |
      5 |
      6 |
      7 | 8 | 10 |
      11 | 12 |
      13 | 14 | 16 |
      17 | 18 |
      19 | 21 |
      22 |
      23 | 34 |
      35 | 36 |
      37 |
      38 |

      登录错误提示

      39 |
      40 |
      41 |

      用户名长度为2-25个字符,密码长度为7-25个字符

      42 |
      43 |
      44 | -------------------------------------------------------------------------------- /views/mobile/password.hbs: -------------------------------------------------------------------------------- 1 |
      2 |
      3 |

      修改密码

      4 | 设置 5 |
      6 |
      7 | 8 |
      9 | 10 | 12 |
      13 | 14 |
      15 | 16 | 18 |
      19 | 20 |
      21 | 22 | 24 |
      25 | 26 |
      27 | 29 |
      30 |
      31 |
      32 |
      33 | 40 |
      41 |
      42 |
      43 | 47 |
      48 |
      49 | 50 |
      51 |
      52 |

      修改密码错误提示

      53 |
      54 |
      55 |

      密码长度为7-25个字符并且老密码输入必须正确

      56 |
      57 |
      58 | -------------------------------------------------------------------------------- /views/mobile/show.hbs: -------------------------------------------------------------------------------- 1 | 2 |
      3 |
      4 |

      我的日报

      5 | 设置 6 |
      7 |
      8 |
      9 |
        10 |
        11 |
        12 |
        13 |
        14 |
        1/1
        15 |
        16 |
        17 |
        18 |
        19 | 20 |
        21 |
        22 | 29 |
        30 |
        31 |
        32 | 36 |
        37 |
        38 |
        39 | 40 | 41 |
        42 |
        43 |
        44 | -------------------------------------------------------------------------------- /views/mobile/showsubordinate.hbs: -------------------------------------------------------------------------------- 1 | 2 |
        3 |
        4 | 5 |

        下属日报

        6 | 设置 7 |
        8 |
        9 |
        10 |
        11 |
        12 | 17 |
        18 |
        19 |
        20 | 24 |
        25 |
        26 | -------------------------------------------------------------------------------- /views/mobile/write.hbs: -------------------------------------------------------------------------------- 1 | 2 |
        3 |
        4 |

        写日报

        5 | 设置 6 |
        7 |
        8 |
        9 |
        10 | 11 | 12 |
        13 |
        14 | 15 | 17 |
        18 | 19 |
        20 | 22 |
        23 |
        24 |
        25 | 26 |
        27 |
        28 | 35 |
        36 |
        37 |
        38 | 42 |
        43 |
        44 |
        45 |
        46 |

        错误提示

        47 |
        48 |
        49 |

        日期格式为xxxx-xx-xx(例如 2013-5-3)并且日报内容不能为空。

        50 |
        51 |
        52 | -------------------------------------------------------------------------------- /views/password.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 修改密码 5 | 6 | 7 | 8 | 9 | 10 | 11 | 28 |
        29 |

        修改密码

        30 |
        31 | 33 | 35 | 36 | 38 | 40 | 41 | 43 | 45 | 46 |
        48 |

        恭喜,修改密码成功!

        49 |

        原始密码输入错误!

        50 |
        51 |
        52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /views/show.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 写日报 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 31 | 34 |
        35 |

        日报内容

        36 |
        37 |
          38 |
        • 39 |

          40 |
          41 | 42 | 43 |
        • 44 |
        45 | 52 |
        53 |
        54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /views/showsubordinate.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 写日报 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 29 |
        30 |

        部门成员列表

        31 |
        32 |
        33 |
        34 |

        日报内容

        35 |
        36 |
          37 |
        • 38 |

          39 |
          40 | 41 |
        • 42 |
        43 | 50 |
        51 |
        52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /views/write.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 写日报 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 32 |
        33 |

        写日报

        34 |
        35 |
        36 |
        38 |
        39 | 40 |
        42 | 43 |
        45 |
        46 |
        47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /vo/Response.coffee: -------------------------------------------------------------------------------- 1 | 2 | class Response 3 | constructor: (@state, @message, @data=null) -> 4 | 5 | exports.Response = Response -------------------------------------------------------------------------------- /vo/Response.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.6.1 2 | (function() { 3 | var Response; 4 | 5 | Response = (function() { 6 | 7 | function Response(state, message, data) { 8 | this.state = state; 9 | this.message = message; 10 | this.data = data != null ? data : null; 11 | } 12 | 13 | return Response; 14 | 15 | })(); 16 | 17 | exports.Response = Response; 18 | 19 | }).call(this); 20 | --------------------------------------------------------------------------------