├── .autod.conf.js ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .travis.yml ├── README.md ├── app ├── controller │ ├── admin │ │ ├── admin.js │ │ ├── permission.js │ │ ├── role.js │ │ └── user.js │ └── home.js ├── middleware │ ├── auth.js │ └── csrf.js ├── model │ ├── permission.js │ ├── role.js │ ├── role_permission.js │ └── user.js ├── public │ ├── css │ │ ├── app.css │ │ └── bootstrap.css │ └── js │ │ ├── bootstrap.js │ │ └── jquery.js ├── router.js ├── service │ ├── auth.js │ ├── permission.js │ ├── role.js │ ├── rolePermission.js │ └── user.js └── view │ ├── admin.html │ ├── index.html │ ├── login │ ├── login.html │ ├── noPermission.html │ └── register.html │ ├── permission │ ├── add.html │ ├── edit.html │ └── index.html │ ├── public │ ├── page_footer.html │ ├── page_header.html │ └── page_nav.html │ ├── role │ ├── add.html │ ├── auth.html │ ├── edit.html │ └── index.html │ └── user │ ├── add.html │ ├── edit.html │ └── index.html ├── appveyor.yml ├── config ├── config.default.js └── plugin.js ├── eggrbac.sql ├── jsconfig.json ├── package.json └── test └── app └── controller └── home.test.js /.autod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | write: true, 5 | prefix: '^', 6 | plugin: 'autod-egg', 7 | test: [ 8 | 'test', 9 | 'benchmark', 10 | ], 11 | dep: [ 12 | 'egg', 13 | 'egg-scripts', 14 | ], 15 | devdep: [ 16 | 'egg-ci', 17 | 'egg-bin', 18 | 'egg-mock', 19 | 'autod', 20 | 'autod-egg', 21 | 'eslint', 22 | 'eslint-config-egg', 23 | 'webstorm-disable-index', 24 | ], 25 | exclude: [ 26 | './test/fixtures', 27 | './dist', 28 | ], 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | // "extends": "eslint-config-egg" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | yarn-error.log 4 | node_modules/ 5 | package-lock.json 6 | yarn.lock 7 | coverage/ 8 | .idea/ 9 | run/ 10 | .DS_Store 11 | *.sw* 12 | *.un~ 13 | typings/ 14 | .nyc_output/ 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '8' 5 | install: 6 | - npm i npminstall && npminstall 7 | script: 8 | - npm run ci 9 | after_script: 10 | - npminstall codecov && codecov 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rbac 2 | 3 | 4 | 5 | ## QuickStart 6 | 7 | 8 | 9 | see [egg docs][egg] for more detail. 10 | 11 | ### Development 12 | 13 | ```bash 14 | $ npm i 15 | $ npm run dev 16 | $ open http://localhost:7001/ 17 | ``` 18 | 19 | ### Deploy 20 | 21 | ```bash 22 | $ npm start 23 | $ npm stop 24 | ``` 25 | 26 | ### npm scripts 27 | 28 | - Use `npm run lint` to check code style. 29 | - Use `npm test` to run unit test. 30 | - Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail. 31 | 32 | 33 | [egg]: https://eggjs.org -------------------------------------------------------------------------------- /app/controller/admin/admin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class AdminController extends Controller { 6 | async index() { 7 | await this.ctx.render('admin') 8 | 9 | } 10 | async register() { 11 | const roleList = await this.ctx.service.role.findAll(); 12 | await this.ctx.render('login/register', { 13 | roleList 14 | }) 15 | } 16 | async doRegister() { 17 | let newUser = this.ctx.request.body; 18 | await this.ctx.service.user.create(newUser) 19 | this.ctx.redirect('/admin') 20 | } 21 | async login() { 22 | 23 | await this.ctx.render('login/login') 24 | } 25 | async doLogin() { 26 | let userInfo = this.ctx.request.body; 27 | // 根据用户名查找密码 28 | let users = await this.ctx.model.User.findAll({ 29 | where: { 30 | username: userInfo.username 31 | } 32 | }) 33 | // 如果有这个用户,保存session 34 | // console.log(user) 35 | if (users) { 36 | this.ctx.session.userInfo = users[0] 37 | this.ctx.redirect('/admin') 38 | } 39 | } 40 | 41 | async loginout() { 42 | this.ctx.session.userInfo = null; 43 | this.ctx.redirect('/admin/login') 44 | } 45 | //如果没有权限,就跳转到这里 46 | async noPermission() { 47 | await this.ctx.render('login/noPermission') 48 | } 49 | } 50 | 51 | module.exports = AdminController; -------------------------------------------------------------------------------- /app/controller/admin/permission.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class PermissionController extends Controller { 6 | async index() { 7 | const permissionList = await this.ctx.service.permission.findAll(); 8 | console.log('cc') 9 | console.log(JSON.stringify(permissionList)) 10 | await this.ctx.render('permission/index', { 11 | permissionList, 12 | }); 13 | } 14 | async add() { 15 | const permissionList = await this.ctx.service.permission.findAll(); 16 | await this.ctx.render('permission/add', { 17 | permissionList 18 | }); 19 | } 20 | async doAdd() { 21 | const newPermission = this.ctx.request.body; 22 | await this.ctx.service.permission.create(newPermission); 23 | this.ctx.redirect('/admin/permission') 24 | } 25 | async edit() { 26 | const id = this.ctx.query.id; 27 | const permission = await this.ctx.service.permission.findById(id); 28 | await this.ctx.render('permission/edit', { 29 | permission 30 | }); 31 | } 32 | async doEdit() { 33 | const newPermission = this.ctx.request.body; 34 | await this.ctx.service.permission.update(newPermission); 35 | this.ctx.redirect('/admin/permission') 36 | } 37 | async delete() { 38 | const id = this.ctx.params.id; 39 | await this.ctx.service.permission.destroy(id); 40 | this.ctx.redirect('/admin/permission') 41 | } 42 | } 43 | 44 | module.exports = PermissionController; -------------------------------------------------------------------------------- /app/controller/admin/role.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class RoleController extends Controller { 6 | async index() { 7 | const roleList = await this.ctx.service.role.findAll(); 8 | await this.ctx.render('role/index', { 9 | roleList, 10 | }); 11 | } 12 | async add() { 13 | await this.ctx.render('role/add'); 14 | } 15 | async doAdd() { 16 | const newRole = this.ctx.request.body; 17 | await this.ctx.service.role.create(newRole); 18 | this.ctx.redirect('/admin/role') 19 | } 20 | async edit() { 21 | const id = this.ctx.query.id; 22 | const role = await this.ctx.service.role.findById(id); 23 | await this.ctx.render('role/edit', { 24 | role 25 | }); 26 | } 27 | async doEdit() { 28 | const newRole = this.ctx.request.body; 29 | await this.ctx.service.role.update(newRole); 30 | this.ctx.redirect('/admin/role') 31 | } 32 | async delete() { 33 | const id = this.ctx.params.id; 34 | await this.ctx.service.role.destroy(id); 35 | this.ctx.redirect('/admin/role') 36 | } 37 | /* 38 | 1.找出所有的权限 39 | 2.根据角色,找出角色所拥有的权限 40 | */ 41 | async auth() { 42 | let roleId = this.ctx.query.id; 43 | let permissionList = await this.ctx.service.permission.findAll(); 44 | let rolePermissionList = await this.ctx.service.rolePermission.findPermissionByRoleId(roleId) 45 | permissionList = JSON.parse(JSON.stringify(permissionList)) 46 | //permissionList如果有rolePermissionList,就增加一个字段check==true 47 | rolePermissionList.forEach(item => { 48 | permissionList.forEach(item1 => { 49 | if (item.id == item1.id) { 50 | item1.check = true 51 | } 52 | item1.permissions.forEach(item2 => { 53 | if (item.id == item2.id) { 54 | item2.check = true 55 | } 56 | }) 57 | }) 58 | }) 59 | await this.ctx.render('role/auth', { 60 | permissionList, 61 | roleId, 62 | 63 | }); 64 | } 65 | async doAuth() { 66 | var body = this.ctx.request.body; 67 | console.log('----') 68 | console.log(JSON.stringify(body)) 69 | await this.ctx.service.rolePermission.create(body) 70 | this.ctx.redirect('/admin/role') 71 | 72 | } 73 | } 74 | 75 | module.exports = RoleController; -------------------------------------------------------------------------------- /app/controller/admin/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class UserController extends Controller { 6 | async index() { 7 | const userList = await this.ctx.service.user.findAll(); 8 | await this.ctx.render('user/index', { 9 | userList, 10 | }); 11 | } 12 | async add() { 13 | const roleList = await this.ctx.service.role.findAll(); 14 | await this.ctx.render('user/add', { 15 | roleList 16 | }); 17 | } 18 | async doAdd() { 19 | const newUser = this.ctx.request.body; 20 | await this.ctx.service.user.create(newUser); 21 | this.ctx.redirect('/admin/user') 22 | } 23 | async edit() { 24 | const id = this.ctx.query.id; 25 | const user = await this.ctx.service.user.findById(id); 26 | const roleList = await this.ctx.service.role.findAll(); 27 | await this.ctx.render('user/edit', { 28 | user, 29 | roleList 30 | }); 31 | } 32 | async doEdit() { 33 | const newUser = this.ctx.request.body; 34 | await this.ctx.service.user.update(newUser); 35 | this.ctx.redirect('/admin/user') 36 | } 37 | async delete() { 38 | const id = this.ctx.params.id; 39 | await this.ctx.service.user.destroy(id); 40 | this.ctx.redirect('/admin/user') 41 | } 42 | } 43 | 44 | module.exports = UserController; -------------------------------------------------------------------------------- /app/controller/home.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Controller = require('egg').Controller; 4 | 5 | class HomeController extends Controller { 6 | async index() { 7 | const { ctx } = this; 8 | ctx.body = "index"; 9 | } 10 | 11 | 12 | } 13 | 14 | module.exports = HomeController; -------------------------------------------------------------------------------- /app/middleware/auth.js: -------------------------------------------------------------------------------- 1 | const url = require('url') 2 | module.exports = (options, app) => { 3 | return async function adminauth(ctx, next) { 4 | // 1. 如果没有登录,跳转登录 5 | // 2.如果登录,判断当前用户对应的角色,是否有权限 6 | 7 | let pathname = url.parse(ctx.request.url).pathname; 8 | ctx.state.prevUrl = ctx.request.headers['referer']; //获取上一页的url 9 | if (ctx.session.userInfo) { 10 | ctx.state.userInfo = ctx.session.userInfo; 11 | var roleId = ctx.session.userInfo.role_id; 12 | // var d = await ctx.service.rolePermission.findAccess(roleId) 13 | 14 | let isPermission = await ctx.service.auth.checkAdmin(); 15 | console.log('是否有权限') 16 | console.log(isPermission) 17 | if (isPermission) { 18 | //左侧导航 19 | let getAdminList = await ctx.service.auth.getAdminList(roleId); 20 | // console.log('左侧导航') 21 | // console.log(JSON.stringify(getAdminList)) 22 | ctx.state.pageNav = getAdminList; 23 | await next() 24 | } else { 25 | 26 | // ctx.body = '你没有权限' 27 | await ctx.render('login/noPermission') 28 | } 29 | } else { 30 | if (pathname == '/admin' || pathname == '/admin/login' || pathname == '/admin/register' || pathname == '/admin/loginout') { 31 | await next() 32 | } else { 33 | ctx.redirect('/admin/login') 34 | } 35 | } 36 | }; 37 | }; -------------------------------------------------------------------------------- /app/middleware/csrf.js: -------------------------------------------------------------------------------- 1 | module.exports = (options, app) => { 2 | return async function adminauth(ctx, next) { 3 | 4 | ctx.state.csrf = ctx.csrf; // 全局变量 5 | // console.log('aa'); 6 | await next(); 7 | }; 8 | }; 9 | -------------------------------------------------------------------------------- /app/model/permission.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = app => { 4 | const { INTEGER, STRING, DATE } = app.Sequelize; 5 | const Permission = app.model.define('permission', { 6 | id: { 7 | type: INTEGER, 8 | primaryKey: true, 9 | autoIncrement: true, 10 | }, 11 | title: { 12 | type: STRING, 13 | }, 14 | url: { 15 | type: STRING, 16 | }, 17 | status: { 18 | type: INTEGER, 19 | }, 20 | type: { 21 | type: INTEGER, 22 | }, 23 | created_at: DATE, 24 | updated_at: DATE, 25 | permission_id: { 26 | type: INTEGER, 27 | }, 28 | }, { 29 | freezeTableName: true, 30 | }); 31 | Permission.associate = function() { 32 | app.model.Permission.hasMany(app.model.Permission, { as: 'permissions', foreignKey: 'permission_id' }); 33 | }; 34 | return Permission; 35 | }; -------------------------------------------------------------------------------- /app/model/role.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = app => { 4 | const { INTEGER, STRING, DATE } = app.Sequelize; 5 | const Role = app.model.define('role', { 6 | id: { 7 | type: INTEGER, 8 | primaryKey: true, 9 | autoIncrement: true, 10 | }, 11 | name: { 12 | type: STRING, 13 | }, 14 | status: { 15 | type: INTEGER, 16 | }, 17 | created_at: app.Sequelize.DATE, 18 | updated_at: { 19 | type: app.Sequelize.DATE, 20 | }, 21 | }, { 22 | freezeTableName: true, 23 | // underscored: true, 24 | }); 25 | Role.associate = function() { 26 | app.model.Role.hasMany(app.model.User, { as: 'user' }); 27 | }; 28 | return Role; 29 | }; 30 | -------------------------------------------------------------------------------- /app/model/role_permission.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = app => { 4 | const { INTEGER, STRING, DATE } = app.Sequelize; 5 | const RolePermission = app.model.define('role_permission', { 6 | id: { 7 | type: INTEGER, 8 | primaryKey: true, 9 | autoIncrement: true, 10 | }, 11 | role_id: { 12 | type: INTEGER, 13 | }, 14 | permission_id: { 15 | type: INTEGER, 16 | }, 17 | created_at: DATE, 18 | updated_at: DATE, 19 | }, { 20 | freezeTableName: true, 21 | }); 22 | RolePermission.associate = function() { 23 | app.model.RolePermission.belongsTo(app.model.Role, { as: 'role' }); 24 | app.model.RolePermission.belongsTo(app.model.Permission, { as: 'permission' }); 25 | }; 26 | return RolePermission; 27 | }; -------------------------------------------------------------------------------- /app/model/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = app => { 4 | const { INTEGER, STRING, DATE } = app.Sequelize; 5 | const User = app.model.define('user', { 6 | id: { 7 | type: INTEGER, 8 | primaryKey: true, 9 | autoIncrement: true, 10 | }, 11 | username: { 12 | type: STRING, 13 | }, 14 | password: { 15 | type: STRING, 16 | }, 17 | created_at: DATE, 18 | updated_at: DATE, 19 | roleId: { 20 | type: INTEGER, 21 | field: 'role_id', 22 | }, 23 | }, { 24 | freezeTableName: true, 25 | }); 26 | User.associate = function() { 27 | app.model.User.belongsTo(app.model.Role, { as: 'role' }); 28 | }; 29 | return User; 30 | }; -------------------------------------------------------------------------------- /app/public/css/app.css: -------------------------------------------------------------------------------- 1 | html { 2 | padding-top: 70px; 3 | } 4 | 5 | .app-layout { 6 | /* padding-top: 50px; */ 7 | } 8 | 9 | .app-layout .layout-nav { 10 | position: fixed; 11 | left: 0; 12 | top: 70px; 13 | width: 200px; 14 | height: 100%; 15 | box-sizing: border-box; 16 | border-right: 1px solid #ccc; 17 | } 18 | 19 | .app-layout .layout-main { 20 | margin-left: 220px; 21 | } 22 | 23 | tr.actived { 24 | background-color: #00aaee; 25 | } 26 | 27 | .access-box { 28 | display: flex; 29 | } 30 | 31 | .access-box .box-left { 32 | flex: 0 0 100px; 33 | width: 100px; 34 | } 35 | 36 | .access-box .box-right { 37 | flex: 1; 38 | } 39 | 40 | .app-header { 41 | position: fixed; 42 | left: 0; 43 | right: 0; 44 | top: 0; 45 | display: flex; 46 | align-items: center; 47 | justify-content: space-between; 48 | height: 50px; 49 | padding: 0 20px; 50 | box-sizing: border-box; 51 | box-shadow: 0 2px 2px #ccc; 52 | } 53 | 54 | .app-footer { 55 | position: fixed; 56 | left: 0; 57 | right: 0; 58 | bottom: 0; 59 | height: 50px; 60 | margin-left: 220px; 61 | text-align: center; 62 | } -------------------------------------------------------------------------------- /app/public/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under the MIT license 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); -------------------------------------------------------------------------------- /app/public/js/jquery.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.2.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a); 3 | }),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S),a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}}),r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var _a,ab=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return T(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?_a:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),_a={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ab[b]||r.find.attr;ab[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=ab[g],ab[g]=e,e=null!=c(a,b,d)?g:null,ab[g]=f),e}});var bb=/^(?:input|select|textarea|button)$/i,cb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function db(a){var b=a.match(L)||[];return b.join(" ")}function eb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,eb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=eb(c),d=1===c.nodeType&&" "+db(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=db(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,eb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=eb(c),d=1===c.nodeType&&" "+db(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=db(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,eb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=eb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+db(eb(c))+" ").indexOf(b)>-1)return!0;return!1}});var fb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(fb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:db(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var gb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!gb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,gb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var hb=/\[\]$/,ib=/\r?\n/g,jb=/^(?:submit|button|image|reset|file)$/i,kb=/^(?:input|select|textarea|keygen)/i;function lb(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||hb.test(a)?d(a,e):lb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d); 4 | });else if(c||"object"!==r.type(b))d(a,b);else for(e in b)lb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)lb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&kb.test(this.nodeName)&&!jb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ib,"\r\n")}}):{name:b.name,value:c.replace(ib,"\r\n")}}).get()}}),r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="
",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=C.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=qa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),b=f.ownerDocument,c=b.documentElement,e=b.defaultView,{top:d.top+e.pageYOffset-c.clientTop,left:d.left+e.pageXOffset-c.clientLeft}):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),B(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||ra})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return T(this,function(a,d,e){var f;return r.isWindow(a)?f=a:9===a.nodeType&&(f=a.defaultView),void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Pa(o.pixelPosition,function(a,c){if(c)return c=Oa(a,b),Ma.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return T(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.holdReady=function(a){a?r.readyWait++:r.ready(!0)},r.isArray=Array.isArray,r.parseJSON=JSON.parse,r.nodeName=B,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var mb=a.jQuery,nb=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=nb),b&&a.jQuery===r&&(a.jQuery=mb),r},b||(a.jQuery=a.$=r),r}); -------------------------------------------------------------------------------- /app/router.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @param {Egg.Application} app - egg application 5 | */ 6 | module.exports = app => { 7 | const { router, controller } = app; 8 | router.get('/', controller.home.index); 9 | router.get('/admin', controller.admin.admin.index); 10 | router.get('/admin/register', controller.admin.admin.register); 11 | router.get('/admin/login', controller.admin.admin.login); 12 | router.post('/admin/login', controller.admin.admin.doLogin); 13 | router.get('/admin/loginout', controller.admin.admin.loginout); 14 | router.get('/admin/noPermission', controller.admin.admin.noPermission); 15 | //角色 16 | router.get('/admin/role', controller.admin.role.index); 17 | router.get('/admin/role/add', controller.admin.role.add); 18 | router.post('/admin/role/add', controller.admin.role.doAdd); 19 | router.get('/admin/role/edit', controller.admin.role.edit); 20 | router.post('/admin/role/edit', controller.admin.role.doEdit); 21 | router.get('/admin/role/delete/:id', controller.admin.role.delete); 22 | router.get('/admin/role/auth', controller.admin.role.auth); 23 | router.post('/admin/role/auth', controller.admin.role.doAuth); 24 | 25 | //用户 26 | router.get('/admin/user', controller.admin.user.index); 27 | router.get('/admin/user/add', controller.admin.user.add); 28 | router.post('/admin/user/add', controller.admin.user.doAdd); 29 | router.get('/admin/user/edit', controller.admin.user.edit); 30 | router.post('/admin/user/edit', controller.admin.user.doEdit); 31 | router.get('/admin/user/delete/:id', controller.admin.user.delete); 32 | //权限 33 | router.get('/admin/permission', controller.admin.permission.index); 34 | router.get('/admin/permission/add', controller.admin.permission.add); 35 | router.post('/admin/permission/add', controller.admin.permission.doAdd); 36 | router.get('/admin/permission/edit', controller.admin.permission.edit); 37 | router.post('/admin/permission/edit', controller.admin.permission.doEdit); 38 | router.get('/admin/permission/delete/:id', controller.admin.permission.delete); 39 | }; -------------------------------------------------------------------------------- /app/service/auth.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const url = require('url') 3 | const Service = require('egg').Service; 4 | 5 | class AuthService extends Service { 6 | // 是否有权限 7 | async checkAdmin() { 8 | const Op = this.ctx.app.Sequelize.Op; 9 | const { ctx } = this; 10 | let pathname = url.parse(ctx.request.url).pathname; 11 | // 1.获取当前角色 12 | // 2.根据当前角色查出对应权限 13 | // 3.将权限里url,拼接成一个url数组 14 | // 4.当前仿问的url是否在url数组里 15 | 16 | // 1. 17 | let userInfo = ctx.session.userInfo; 18 | let roleId = userInfo.role_id; 19 | // 忽略权限判断的地址,超级管理员 20 | var ignoreUrl = ['/admin', '/admin/login', '/admin/register', '/admin/loginout'] 21 | if (ignoreUrl.indexOf(pathname) != -1 || userInfo.id == '1') { 22 | return true; 23 | } 24 | //2. 25 | let permission = await ctx.model.RolePermission.findAll({ 26 | where: { 27 | role_id: roleId 28 | } 29 | }) 30 | // 得到所有的权限ids 31 | let permissionIds = []; 32 | permission.forEach(item => { 33 | permissionIds.push(item.permission_id) 34 | }) 35 | let permissions = await ctx.model.Permission.findAll({ 36 | where: { 37 | id: { 38 | [Op.or]: permissionIds 39 | } 40 | } 41 | }) 42 | // 3. 43 | let permissionUrls = [] 44 | permissions.forEach(item => { 45 | permissionUrls.push(item.url) 46 | }) 47 | console.log('当前url与权限url数组对比') 48 | console.log(JSON.stringify(permissionUrls)) 49 | console.log(pathname) 50 | // 4. 51 | if(pathname.indexOf('delete') != -1){ 52 | console.log('有delete') 53 | let strIndex = pathname.lastIndexOf('/') 54 | console.log(strIndex) 55 | pathname= pathname.slice(0,strIndex) 56 | console.log(pathname) 57 | } 58 | if (permissionUrls.indexOf(pathname) != -1) { 59 | return true; 60 | } 61 | return false; 62 | } 63 | //左侧导航 64 | async getAdminList(roleId) { 65 | 66 | const Op = this.ctx.app.Sequelize.Op; 67 | const { ctx } = this; 68 | let permission = await ctx.model.RolePermission.findAll({ 69 | where: { 70 | role_id: roleId 71 | } 72 | }) 73 | // 得到所有的权限ids 74 | // console.log('得到所有的权限ids') 75 | // console.log(roleId) 76 | // console.log(JSON.stringify(permission)) 77 | let permissionIds = []; 78 | permission.forEach(item => { 79 | permissionIds.push(item.permission_id) 80 | }) 81 | let permissions = await ctx.model.Permission.findAll({ 82 | where: { 83 | id: { 84 | [Op.or]: permissionIds 85 | }, 86 | permission_id: 0, 87 | }, 88 | include: [{ 89 | model: this.ctx.model.Permission, 90 | as: 'permissions', 91 | where: { 92 | type: { 93 | [Op.in]: [1, 2] 94 | } 95 | } 96 | }] 97 | }) 98 | 99 | // console.log('permissions:') 100 | // console.log(JSON.stringify(permissions)) 101 | return permissions; 102 | } 103 | } 104 | 105 | module.exports = AuthService; -------------------------------------------------------------------------------- /app/service/permission.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Service = require('egg').Service; 4 | 5 | class PermissionService extends Service { 6 | async findAll() { 7 | try { 8 | const permissionList = await this.ctx.model.Permission.findAll({ 9 | where: { 10 | permission_id: 0 11 | }, 12 | include: [{ 13 | model: this.ctx.model.Permission, 14 | as: 'permissions', 15 | }] 16 | }); 17 | return permissionList; 18 | } catch (error) { 19 | console.log(error) 20 | } 21 | } 22 | async findById(id) { 23 | try { 24 | const permission = await this.ctx.model.Permission.findById(id); 25 | return permission; 26 | } catch (error) { 27 | console.log(error) 28 | } 29 | } 30 | 31 | async create(newPermission) { 32 | try { 33 | await this.ctx.model.Permission.create(newPermission); 34 | } catch (error) { 35 | console.log(error) 36 | } 37 | } 38 | 39 | async update(newPermission) { 40 | try { 41 | const permissionDB = await this.ctx.model.Permission.findById(newPermission.id); 42 | await permissionDB.update(newPermission); 43 | } catch (error) { 44 | console.log(error) 45 | } 46 | } 47 | 48 | async destroy(id) { 49 | try { 50 | const permission = await this.ctx.model.Permission.findById(id); 51 | await permission.destroy(); 52 | } catch (error) { 53 | console.log(error) 54 | } 55 | } 56 | } 57 | 58 | module.exports = PermissionService; -------------------------------------------------------------------------------- /app/service/role.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Service = require('egg').Service; 4 | 5 | class RoleService extends Service { 6 | async findAll() { 7 | try { 8 | const roleList = await this.ctx.model.Role.findAll(); 9 | return roleList; 10 | } catch (error) { 11 | console.log(error) 12 | } 13 | } 14 | async findById(id) { 15 | try { 16 | const role = await this.ctx.model.Role.findById(id); 17 | return role; 18 | } catch (error) { 19 | console.log(error) 20 | } 21 | } 22 | 23 | async create(newRole) { 24 | try { 25 | await this.ctx.model.Role.create(newRole); 26 | } catch (error) { 27 | console.log(error) 28 | } 29 | } 30 | 31 | async update(newRole) { 32 | try { 33 | const roleDB = await this.ctx.model.Role.findById(newRole.id); 34 | await roleDB.update(newRole); 35 | } catch (error) { 36 | console.log(error) 37 | } 38 | } 39 | 40 | async destroy(id) { 41 | try { 42 | const role = await this.ctx.model.Role.findById(id); 43 | await role.destroy(); 44 | } catch (error) { 45 | console.log(error) 46 | } 47 | } 48 | async findPermission() { 49 | const permissionList = await this.ctx.model.Permission.findAll({ 50 | where: { 51 | permission_id: 0 52 | }, 53 | include: [{ 54 | model: this.ctx.model.Permission, 55 | as: 'permissions', 56 | }] 57 | }); 58 | return permissionList 59 | } 60 | } 61 | 62 | module.exports = RoleService; -------------------------------------------------------------------------------- /app/service/rolePermission.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Service = require('egg').Service; 4 | 5 | class RolePermissionService extends Service { 6 | async create(body) { 7 | try { 8 | let id = body.roleId; 9 | let permissionId = body.permissionIds; 10 | //先删除 11 | await this.ctx.model.RolePermission.destroy({ 12 | where: { 13 | role_id: id 14 | } 15 | }) 16 | //后增加 17 | permissionId.forEach(async(item) => { 18 | await this.ctx.model.RolePermission.create({ 19 | role_id: id, 20 | permission_id: parseInt(item), 21 | status: 1 22 | }) 23 | }) 24 | } catch (error) { 25 | console.log(error) 26 | } 27 | } 28 | //根据角色,得到权限 29 | async findPermissionByRoleId(roleId) { 30 | const Op = this.ctx.app.Sequelize.Op; 31 | var rolePermissions = await this.ctx.model.RolePermission.findAll({ 32 | where: { 33 | role_id: roleId 34 | } 35 | }); 36 | let permissionIds = []; 37 | rolePermissions.forEach((item) => { 38 | permissionIds.push(item.permission_id) 39 | }) 40 | var permissions = await this.ctx.model.Permission.findAll({ 41 | where: { 42 | id: { 43 | [Op.or]: permissionIds 44 | }, 45 | }, 46 | }) 47 | return permissions 48 | } 49 | } 50 | 51 | module.exports = RolePermissionService; -------------------------------------------------------------------------------- /app/service/user.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Service = require('egg').Service; 4 | 5 | class UserService extends Service { 6 | async findAll() { 7 | try { 8 | const userList = await this.ctx.model.User.findAll({ 9 | include: [{ 10 | model: this.ctx.model.Role, 11 | as: 'role', 12 | attributes: ['name'], 13 | }] 14 | }); 15 | // console.log(JSON.stringify(userList)) 16 | return userList; 17 | } catch (error) { 18 | console.log(error) 19 | } 20 | } 21 | async findById(id) { 22 | try { 23 | const user = await this.ctx.model.User.findById(id); 24 | return user; 25 | } catch (error) { 26 | console.log(error) 27 | } 28 | } 29 | 30 | async create(newUser) { 31 | try { 32 | await this.ctx.model.User.create(newUser); 33 | } catch (error) { 34 | console.log(error) 35 | } 36 | } 37 | 38 | async update(newUser) { 39 | try { 40 | const userDB = await this.ctx.model.User.findById(newUser.id); 41 | await userDB.update(newUser); 42 | } catch (error) { 43 | console.log(error) 44 | } 45 | } 46 | 47 | async destroy(id) { 48 | try { 49 | const user = await this.ctx.model.User.findById(id); 50 | await user.destroy(); 51 | } catch (error) { 52 | console.log(error) 53 | } 54 | } 55 | } 56 | 57 | module.exports = UserService; -------------------------------------------------------------------------------- /app/view/admin.html: -------------------------------------------------------------------------------- 1 | <%- include ./public/page_header.html %> 2 |
3 | <%- include ./public/page_nav.html %> 4 |
5 | admin 6 |
7 |
8 | <%- include ./public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/index.html: -------------------------------------------------------------------------------- 1 | <%- include ./public/page_header.html %> 2 |
3 | 8 |
9 |
10 | 11 | 12 | 13 |
14 | <%- include ./public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/login/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 | 13 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/view/login/noPermission.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | 没有权限哦 4 | 返回上一页 5 |
6 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/login/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 |

register

13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 |
24 | 25 |
26 |
27 |
28 | 29 |
30 | 35 |
36 |
37 |
38 |
39 | 40 |
41 |
42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /app/view/permission/add.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

权限增加

6 |
7 | 8 |
9 | 10 |
11 | 12 |
13 |
14 |
15 | 16 |
17 | 22 |
23 |
24 |
25 | 26 |
27 | 28 |
29 |
30 |
31 | 32 |
33 | 44 |
45 |
46 |
47 | 48 |
49 | 52 | 55 |
56 |
57 |
58 |
59 | 60 |
61 |
62 |
63 |
64 |
65 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/permission/edit.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

权限编辑

6 |
7 | 8 | 9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 |
24 | 28 | 32 | 36 |
37 |
38 |
39 |
40 | 41 |
42 |
43 |
44 |
45 |
46 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/permission/index.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

权限列表

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | <%for(var i =0;i 21 | 22 | 24 | 27 | 30 | 39 | 42 | 45 | 51 | 55 | 56 | <%for(var j =0;j 57 | 58 | 61 | 64 | 73 | 76 | 79 | 85 | 89 | <%}%> 90 | 91 | <%}%> 92 | 93 | 94 |
id标题节点类型url所属模块操作
25 | <%= permissionList[i].id%> 26 | 28 | <%= permissionList[i].title%> 29 | 31 | <%if(permissionList[i].type==1){%> 32 | 模块 33 | <%}else if(permissionList[i].type==2){%> 34 | 菜单 35 | <%}else{%> 36 | 操作 37 | <%}%> 38 | 40 | <%= permissionList[i].url%> 41 | 43 | <%= permissionList[i].title%> 44 | 52 | 编辑 53 | 删除 54 |
59 | <%= permissionList[i].permissions[j].id%> 60 | 62 | <%= permissionList[i].permissions[j].title%> 63 | 65 | <%if(permissionList[i].permissions[j].type==1){%> 66 | 模块 67 | <%}else if(permissionList[i].permissions[j].type==2){%> 68 | 菜单 69 | <%}else{%> 70 | 操作 71 | <%}%> 72 | 74 | <%= permissionList[i].permissions[j].url%> 75 | 77 | <%= permissionList[i].title%> 78 | 86 | 编辑 87 | 删除 88 |
95 |
96 |
97 | 98 | 99 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/public/page_footer.html: -------------------------------------------------------------------------------- 1 |
footer
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/view/public/page_header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
egg-rgac
17 |
18 | <%if(userInfo){%> 19 | <%=userInfo.username%> 20 | <%}else {%> 21 | 登录 22 | <%}%> 23 | 24 | 退出 25 |
26 |
-------------------------------------------------------------------------------- /app/view/public/page_nav.html: -------------------------------------------------------------------------------- 1 |
2 | 11 |
-------------------------------------------------------------------------------- /app/view/role/add.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

角色增加

6 |
7 | 8 |
9 | 10 |
11 | 12 |
13 |
14 |
15 | 16 |
17 | 20 | 23 |
24 |
25 |
26 |
27 | 28 |
29 |
30 |
31 |
32 |
33 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/role/auth.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

角色授权

6 |
7 | 8 | 9 | <%for(var i =0;i 10 |
    11 |
  • 12 |
    13 | 18 |
    19 |
    20 | 21 | <%for(var j=0;j 22 | 27 | <%}%> 28 |
    29 |
  • 30 |
31 | <%}%> 32 |
33 | 34 |
35 | 36 |
37 |
38 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/role/edit.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

角色编辑

6 |
7 | 8 | 9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 21 | 24 |
25 |
26 |
27 |
28 | 29 |
30 |
31 |
32 |
33 |
34 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/role/index.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

角色列表

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | <%for(var i =0;i 17 | 18 | 19 | 22 | 25 | 28 | 34 | 39 | 40 | <%}%> 41 | 42 | 43 |
idname状态操作
20 | <%= roleList[i].id%> 21 | 23 | <%= roleList[i].name%> 24 | 26 | <%= roleList[i].status%> 27 | 35 | 授权 36 | 编辑 37 | 删除 38 |
44 |
45 |
46 | 47 | 48 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/user/add.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

用户增加

6 |
7 | 8 |
9 | 10 |
11 | 12 |
13 |
14 |
15 | 16 |
17 | 18 |
19 |
20 |
21 | 22 |
23 | 28 |
29 |
30 |
31 |
32 | 33 |
34 |
35 |
36 |
37 |
38 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/user/edit.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

用户编辑

6 |
7 | 8 | 9 |
10 | 11 |
12 | 13 |
14 |
15 |
16 | 17 |
18 | 19 |
20 |
21 |
22 | 23 |
24 | 29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 |
39 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /app/view/user/index.html: -------------------------------------------------------------------------------- 1 | <%- include ../public/page_header.html %> 2 |
3 | <%- include ../public/page_nav.html %> 4 |
5 |

用户列表

6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | <%for(var i =0;i 19 | 20 | 21 | 24 | 27 | 30 | 36 | 40 | 41 | <%}%> 42 | 43 | 44 |
idusername角色操作
22 | <%= userList[i].id%> 23 | 25 | <%= userList[i].username%> 26 | 28 | <%= userList[i].role.name%> 29 | 37 | 编辑 38 | 删除 39 |
45 |
46 |
47 | 48 | 49 | <%- include ../public/page_footer.html %> -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '8' 4 | 5 | install: 6 | - ps: Install-Product node $env:nodejs_version 7 | - npm i npminstall && node_modules\.bin\npminstall 8 | 9 | test_script: 10 | - node --version 11 | - npm --version 12 | - npm run test 13 | 14 | build: off 15 | -------------------------------------------------------------------------------- /config/config.default.js: -------------------------------------------------------------------------------- 1 | /* eslint valid-jsdoc: "off" */ 2 | 3 | 'use strict'; 4 | 5 | /** 6 | * @param {Egg.EggAppInfo} appInfo app info 7 | */ 8 | module.exports = appInfo => { 9 | /** 10 | * built-in config 11 | * @type {Egg.EggAppConfig} 12 | **/ 13 | const config = {}; 14 | 15 | // use for cookie sign key, should change to your own and keep security 16 | config.keys = appInfo.name + '_1551165895018_921'; 17 | 18 | // add your middleware config here 19 | config.middleware = ['csrf', 'auth']; 20 | config.sequelize = { 21 | dialect: 'mysql', // support: mysql, mariadb, postgres, mssql 22 | dialectOptions: { 23 | charset: 'utf8mb4', 24 | }, 25 | database: 'eggrbac', 26 | host: 'localhost', 27 | port: '3306', 28 | username: 'root', 29 | password: '123456', 30 | timezone: '+08:00', 31 | // define: { 32 | // // 字段以下划线(_)来分割(默认是驼峰命名风格) 33 | // underscored: false, 34 | // }, 35 | }; 36 | config.view = { 37 | mapping: { 38 | '.html': 'ejs', 39 | }, 40 | }; 41 | config.session = { 42 | key: 'SESSION_ID', // key名字 43 | maxAge: 1000 * 60 * 24, 44 | httpOnly: true, 45 | encrypt: true, // 加密 46 | renew: true, // 最大时间范围内,刷新,自动增加最大时间 47 | }; 48 | config.cluster = { 49 | listen: { 50 | port: 8003, 51 | }, 52 | }; 53 | // add your user config here 54 | const userConfig = { 55 | // myAppName: 'egg', 56 | }; 57 | 58 | return { 59 | ...config, 60 | ...userConfig, 61 | }; 62 | }; -------------------------------------------------------------------------------- /config/plugin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** @type Egg.EggPlugin */ 4 | module.exports = { 5 | // had enabled by egg 6 | // static: { 7 | // enable: true, 8 | // } 9 | ejs: { 10 | enable: true, 11 | package: 'egg-view-ejs', 12 | }, 13 | sequelize: { 14 | enable: true, 15 | package: 'egg-sequelize', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /eggrbac.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : localhost_3306 5 | Source Server Version : 50720 6 | Source Host : localhost:3306 7 | Source Database : eggrbac 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50720 11 | File Encoding : 65001 12 | 13 | Date: 2019-05-28 14:47:42 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for permission 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `permission`; 22 | CREATE TABLE `permission` ( 23 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限id', 24 | `title` varchar(255) DEFAULT NULL COMMENT '标题', 25 | `type` int(255) DEFAULT NULL COMMENT '节点类型,1:表示模块 2:表示菜单3:操作', 26 | `url` varchar(255) DEFAULT NULL COMMENT '连接地址', 27 | `status` int(1) DEFAULT '1' COMMENT '0:不可用,1:可用', 28 | `created_at` datetime DEFAULT NULL COMMENT '创建时间', 29 | `updated_at` datetime DEFAULT NULL COMMENT '更改时间', 30 | `permission_id` int(11) DEFAULT NULL COMMENT '当前表id', 31 | PRIMARY KEY (`id`), 32 | UNIQUE KEY `title` (`title`) 33 | ) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COMMENT='权限'; 34 | 35 | -- ---------------------------- 36 | -- Records of permission 37 | -- ---------------------------- 38 | INSERT INTO `permission` VALUES ('11', '角色管理', '1', '', '1', '2019-03-19 16:59:20', '2019-03-19 16:59:20', '0'); 39 | INSERT INTO `permission` VALUES ('12', '角色列表', '2', '/admin/role', '1', '2019-03-19 16:59:57', '2019-03-19 16:59:57', '11'); 40 | INSERT INTO `permission` VALUES ('13', '增加角色', '2', '/admin/role/add', '1', '2019-03-19 17:00:35', '2019-03-19 17:00:35', '11'); 41 | INSERT INTO `permission` VALUES ('14', '用户管理', '1', '', '1', '2019-03-19 17:04:35', '2019-03-19 17:04:35', '0'); 42 | INSERT INTO `permission` VALUES ('15', '用户列表', '2', '/admin/user', '1', '2019-03-19 17:04:53', '2019-03-19 17:04:53', '14'); 43 | INSERT INTO `permission` VALUES ('16', '用户增加', '2', '/admin/user/add', '1', '2019-03-19 17:05:15', '2019-03-19 17:05:15', '14'); 44 | INSERT INTO `permission` VALUES ('17', '权限管理', '1', '', '1', '2019-03-20 16:34:25', '2019-03-20 16:34:25', '0'); 45 | INSERT INTO `permission` VALUES ('18', '权限列表', '2', '/admin/permission', '1', '2019-03-20 16:34:55', '2019-03-20 16:34:55', '17'); 46 | INSERT INTO `permission` VALUES ('19', '权限增加', '2', '/admin/permission/add', '1', '2019-03-20 16:35:24', '2019-03-20 16:35:24', '17'); 47 | INSERT INTO `permission` VALUES ('20', '权限编辑', '3', '/admin/permission/edit', '1', '2019-03-20 16:37:11', '2019-03-20 16:37:11', '17'); 48 | INSERT INTO `permission` VALUES ('21', '权限删除', '3', '/admin/permission/delete', '1', '2019-03-20 16:38:02', '2019-03-20 16:38:02', '17'); 49 | INSERT INTO `permission` VALUES ('22', '用户编辑', '3', '/admin/user/edit', '1', '2019-03-20 16:45:41', '2019-03-20 16:45:41', '14'); 50 | INSERT INTO `permission` VALUES ('23', '用户删除', '3', '/admin/user/delete', '1', '2019-03-20 16:46:14', '2019-03-20 16:46:14', '14'); 51 | INSERT INTO `permission` VALUES ('24', '角色编辑', '3', '/admin/role/edit', '1', '2019-03-20 16:46:51', '2019-03-20 16:48:23', '11'); 52 | INSERT INTO `permission` VALUES ('25', '角色删除', '3', '/admin/role/delete', '1', '2019-03-20 16:48:53', '2019-03-20 16:48:53', '11'); 53 | 54 | -- ---------------------------- 55 | -- Table structure for role 56 | -- ---------------------------- 57 | DROP TABLE IF EXISTS `role`; 58 | CREATE TABLE `role` ( 59 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色id', 60 | `name` varchar(255) DEFAULT NULL COMMENT '标题', 61 | `status` int(1) DEFAULT '1' COMMENT '0:不可用,1:可用', 62 | `created_at` datetime DEFAULT NULL COMMENT '创建时间', 63 | `updated_at` datetime DEFAULT NULL COMMENT '更改时间', 64 | PRIMARY KEY (`id`), 65 | UNIQUE KEY `title` (`name`) 66 | ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='角色'; 67 | 68 | -- ---------------------------- 69 | -- Records of role 70 | -- ---------------------------- 71 | INSERT INTO `role` VALUES ('1', '超级管理员', '1', '2019-02-26 15:36:26', '2019-03-01 14:33:37'); 72 | INSERT INTO `role` VALUES ('5', '校长', '1', '2019-03-19 16:46:42', '2019-03-19 16:46:42'); 73 | INSERT INTO `role` VALUES ('6', '老师', '1', '2019-03-19 16:46:53', '2019-03-19 16:46:53'); 74 | INSERT INTO `role` VALUES ('7', '学生', '1', '2019-03-19 16:46:58', '2019-03-19 16:46:58'); 75 | 76 | -- ---------------------------- 77 | -- Table structure for role_permission 78 | -- ---------------------------- 79 | DROP TABLE IF EXISTS `role_permission`; 80 | CREATE TABLE `role_permission` ( 81 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '角色权限id', 82 | `role_id` int(11) DEFAULT NULL COMMENT '角色id', 83 | `permission_id` int(11) DEFAULT NULL COMMENT '权限id', 84 | `created_at` datetime DEFAULT NULL, 85 | `updated_at` datetime DEFAULT NULL, 86 | PRIMARY KEY (`id`) 87 | ) ENGINE=InnoDB AUTO_INCREMENT=256 DEFAULT CHARSET=utf8mb4 COMMENT='角色权限多对多'; 88 | 89 | -- ---------------------------- 90 | -- Records of role_permission 91 | -- ---------------------------- 92 | INSERT INTO `role_permission` VALUES ('21', '4', '10', '2019-03-13 16:43:49', '2019-03-13 16:43:49'); 93 | INSERT INTO `role_permission` VALUES ('22', '4', '8', '2019-03-13 16:43:49', '2019-03-13 16:43:49'); 94 | INSERT INTO `role_permission` VALUES ('23', '4', '9', '2019-03-13 16:43:49', '2019-03-13 16:43:49'); 95 | INSERT INTO `role_permission` VALUES ('222', '5', '11', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 96 | INSERT INTO `role_permission` VALUES ('223', '5', '13', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 97 | INSERT INTO `role_permission` VALUES ('224', '5', '24', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 98 | INSERT INTO `role_permission` VALUES ('225', '5', '12', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 99 | INSERT INTO `role_permission` VALUES ('226', '5', '25', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 100 | INSERT INTO `role_permission` VALUES ('227', '5', '14', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 101 | INSERT INTO `role_permission` VALUES ('228', '5', '15', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 102 | INSERT INTO `role_permission` VALUES ('229', '5', '16', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 103 | INSERT INTO `role_permission` VALUES ('230', '5', '22', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 104 | INSERT INTO `role_permission` VALUES ('231', '5', '23', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 105 | INSERT INTO `role_permission` VALUES ('232', '5', '17', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 106 | INSERT INTO `role_permission` VALUES ('233', '5', '18', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 107 | INSERT INTO `role_permission` VALUES ('234', '5', '19', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 108 | INSERT INTO `role_permission` VALUES ('235', '5', '20', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 109 | INSERT INTO `role_permission` VALUES ('236', '5', '21', '2019-03-21 13:39:10', '2019-03-21 13:39:10'); 110 | INSERT INTO `role_permission` VALUES ('247', '7', '14', '2019-03-21 13:40:21', '2019-03-21 13:40:21'); 111 | INSERT INTO `role_permission` VALUES ('248', '7', '22', '2019-03-21 13:40:21', '2019-03-21 13:40:21'); 112 | INSERT INTO `role_permission` VALUES ('249', '7', '15', '2019-03-21 13:40:21', '2019-03-21 13:40:21'); 113 | INSERT INTO `role_permission` VALUES ('250', '7', '16', '2019-03-21 13:40:21', '2019-03-21 13:40:21'); 114 | INSERT INTO `role_permission` VALUES ('251', '6', '14', '2019-03-21 13:40:33', '2019-03-21 13:40:33'); 115 | INSERT INTO `role_permission` VALUES ('252', '6', '15', '2019-03-21 13:40:33', '2019-03-21 13:40:33'); 116 | INSERT INTO `role_permission` VALUES ('253', '6', '16', '2019-03-21 13:40:33', '2019-03-21 13:40:33'); 117 | INSERT INTO `role_permission` VALUES ('254', '6', '22', '2019-03-21 13:40:33', '2019-03-21 13:40:33'); 118 | INSERT INTO `role_permission` VALUES ('255', '6', '23', '2019-03-21 13:40:33', '2019-03-21 13:40:33'); 119 | 120 | -- ---------------------------- 121 | -- Table structure for user 122 | -- ---------------------------- 123 | DROP TABLE IF EXISTS `user`; 124 | CREATE TABLE `user` ( 125 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id', 126 | `username` varchar(255) DEFAULT NULL COMMENT '用户名', 127 | `password` varchar(255) DEFAULT NULL COMMENT '用户密码', 128 | `created_at` datetime DEFAULT NULL COMMENT '创建时间', 129 | `updated_at` datetime DEFAULT NULL COMMENT '更改时间', 130 | `role_id` int(11) DEFAULT NULL, 131 | PRIMARY KEY (`id`), 132 | UNIQUE KEY `username` (`username`) 133 | ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; 134 | 135 | -- ---------------------------- 136 | -- Records of user 137 | -- ---------------------------- 138 | INSERT INTO `user` VALUES ('1', 'admin', '123456', '2019-02-26 15:46:32', '2019-02-26 15:46:34', '1'); 139 | INSERT INTO `user` VALUES ('2', '李校长', '123456', '2019-03-20 15:36:51', '2019-03-20 15:37:12', '5'); 140 | INSERT INTO `user` VALUES ('3', '李老师', '123456', '2019-03-20 15:37:25', '2019-03-20 15:37:25', '6'); 141 | INSERT INTO `user` VALUES ('5', '李学生11', '123456', '2019-03-20 16:50:00', '2019-03-21 13:55:14', '7'); 142 | INSERT INTO `user` VALUES ('6', '李学生2', '123456', '2019-03-21 13:41:15', '2019-03-21 13:41:15', '7'); 143 | INSERT INTO `user` VALUES ('7', '李学生3', '123456', '2019-03-21 13:59:49', '2019-03-21 13:59:49', '7'); 144 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "**/*" 4 | ] 5 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rbac", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "egg": { 7 | "declarations": true 8 | }, 9 | "dependencies": { 10 | "egg": "^2.15.1", 11 | "egg-scripts": "^2.11.0", 12 | "egg-sequelize": "^4.3.1", 13 | "egg-view-ejs": "^2.0.0", 14 | "mysql2": "^1.6.5" 15 | }, 16 | "devDependencies": { 17 | "autod": "^3.0.1", 18 | "autod-egg": "^1.1.0", 19 | "egg-bin": "^4.11.0", 20 | "egg-ci": "^1.11.0", 21 | "egg-mock": "^3.21.0", 22 | "eslint": "^5.13.0", 23 | "eslint-config-egg": "^7.1.0", 24 | "webstorm-disable-index": "^1.2.0" 25 | }, 26 | "engines": { 27 | "node": ">=8.9.0" 28 | }, 29 | "scripts": { 30 | "start": "egg-scripts start --daemon --title=egg-server-rbac", 31 | "stop": "egg-scripts stop --title=egg-server-rbac", 32 | "dev": "egg-bin dev", 33 | "debug": "egg-bin debug", 34 | "test": "npm run lint -- --fix && npm run test-local", 35 | "test-local": "egg-bin test", 36 | "cov": "egg-bin cov", 37 | "lint": "eslint .", 38 | "ci": "npm run lint && npm run cov", 39 | "autod": "autod" 40 | }, 41 | "ci": { 42 | "version": "8" 43 | }, 44 | "repository": { 45 | "type": "git", 46 | "url": "" 47 | }, 48 | "author": "", 49 | "license": "MIT" 50 | } 51 | -------------------------------------------------------------------------------- /test/app/controller/home.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { app, assert } = require('egg-mock/bootstrap'); 4 | 5 | describe('test/app/controller/home.test.js', () => { 6 | it('should assert', function* () { 7 | const pkg = require('../../../package.json'); 8 | assert(app.config.keys.startsWith(pkg.name)); 9 | 10 | // const ctx = app.mockContext({}); 11 | // yield ctx.service.xx(); 12 | }); 13 | 14 | it('should GET /', () => { 15 | return app.httpRequest() 16 | .get('/') 17 | .expect('hi, egg') 18 | .expect(200); 19 | }); 20 | }); 21 | --------------------------------------------------------------------------------