├── app ├── robots.txt ├── favicon.ico ├── favicon.png ├── img │ ├── bg.png │ ├── card.png │ ├── line.png │ ├── logo.png │ ├── save.png │ ├── light.png │ ├── line_conn.gif │ ├── loading.gif │ ├── logo-big.png │ ├── plus_alt.png │ ├── breadcrumb.png │ ├── menu-active.png │ ├── configuration2.png │ ├── default-face.png │ ├── loading-login.gif │ ├── loading-tree.gif │ ├── zTreeStandard.gif │ ├── zTreeStandard.png │ ├── app-logo-default.png │ ├── 1380443751_warning.png │ ├── glyphicons-halflings.png │ └── glyphicons-halflings-white.png ├── font │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.eot@ │ ├── fontawesome-webfont.ttf │ └── fontawesome-webfont.woff ├── css │ ├── main.css │ ├── table-fixed-header.css │ ├── nprogress.css │ ├── jquery.gritter.css │ ├── matrix-media.css │ ├── matrix-login.css │ ├── zTreeStyle.css │ └── datepicker.css ├── modules │ └── publish │ │ ├── controllers │ │ ├── lock.js │ │ └── dashboard.js │ │ ├── templetes │ │ └── dashboard.html │ │ ├── init.js │ │ └── route.js ├── config.js ├── lib │ ├── angularJS │ │ ├── bootstrap-datepicker.zh-CN.js │ │ ├── angular-resource.js │ │ ├── angular-route.js │ │ ├── angular-animate.js │ │ └── angular-strap.js │ ├── console-min.js │ ├── jquery │ │ ├── table-fixed-header.js │ │ ├── bootstrap-switch.min.js │ │ ├── nprogress.js │ │ └── jquery.gritter.min.js │ ├── html5shiv.js │ ├── json2.js │ ├── blob.js │ ├── FileSaver.js │ ├── modernizr.js │ └── requireJS │ │ └── require.js ├── common │ ├── directives │ │ ├── blur.js │ │ ├── table-fixed-header.js │ │ ├── bread-crumbs.js │ │ ├── switch.js │ │ ├── ztree.js │ │ ├── action.js │ │ ├── sidebar-menu.js │ │ └── face-uploader.js │ ├── services │ │ ├── acl.js │ │ ├── auth.js │ │ └── action.js │ ├── init.js │ └── controllers │ │ └── menu.js ├── utils │ └── loader.js ├── app.js ├── bootstrap.js ├── index.html └── login.html ├── mock ├── acl.php ├── index.php └── templetes │ └── lock.php ├── .gitignore ├── package.json ├── README.md └── Gruntfile.js /app/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / -------------------------------------------------------------------------------- /mock/acl.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/mock/acl.php -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/favicon.ico -------------------------------------------------------------------------------- /app/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/favicon.png -------------------------------------------------------------------------------- /app/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/bg.png -------------------------------------------------------------------------------- /app/img/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/card.png -------------------------------------------------------------------------------- /app/img/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/line.png -------------------------------------------------------------------------------- /app/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/logo.png -------------------------------------------------------------------------------- /app/img/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/save.png -------------------------------------------------------------------------------- /mock/index.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/mock/index.php -------------------------------------------------------------------------------- /app/img/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/light.png -------------------------------------------------------------------------------- /app/img/line_conn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/line_conn.gif -------------------------------------------------------------------------------- /app/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/loading.gif -------------------------------------------------------------------------------- /app/img/logo-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/logo-big.png -------------------------------------------------------------------------------- /app/img/plus_alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/plus_alt.png -------------------------------------------------------------------------------- /app/img/breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/breadcrumb.png -------------------------------------------------------------------------------- /app/img/menu-active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/menu-active.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | .idea 3 | .svn 4 | .project 5 | .settings 6 | .buildpath 7 | app/config.js 8 | -------------------------------------------------------------------------------- /app/img/configuration2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/configuration2.png -------------------------------------------------------------------------------- /app/img/default-face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/default-face.png -------------------------------------------------------------------------------- /app/img/loading-login.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/loading-login.gif -------------------------------------------------------------------------------- /app/img/loading-tree.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/loading-tree.gif -------------------------------------------------------------------------------- /app/img/zTreeStandard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/zTreeStandard.gif -------------------------------------------------------------------------------- /app/img/zTreeStandard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/zTreeStandard.png -------------------------------------------------------------------------------- /app/img/app-logo-default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/app-logo-default.png -------------------------------------------------------------------------------- /app/img/1380443751_warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/1380443751_warning.png -------------------------------------------------------------------------------- /app/font/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/font/fontawesome-webfont.eot -------------------------------------------------------------------------------- /app/font/fontawesome-webfont.eot@: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/font/fontawesome-webfont.eot@ -------------------------------------------------------------------------------- /app/font/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/font/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /app/font/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/font/fontawesome-webfont.woff -------------------------------------------------------------------------------- /app/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /app/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kazaff/angular-build-seed/HEAD/app/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /app/css/main.css: -------------------------------------------------------------------------------- 1 | @import url('matrix-style.css'); 2 | @import url('matrix-media.css'); 3 | @import url('jquery.gritter.css'); 4 | @import url('font-awesome.css'); 5 | @import url('table-fixed-header.css'); 6 | @import url('nprogress.css'); -------------------------------------------------------------------------------- /app/modules/publish/controllers/lock.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by admin on 14-1-3. 3 | */ 4 | define(function(){ 5 | 'use strict'; 6 | 7 | return ['$scope', 'auth', function($scope, Auth){ 8 | Auth.isLogined(); 9 | 10 | }]; 11 | }); -------------------------------------------------------------------------------- /app/modules/publish/controllers/dashboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-5 5 | * Time: 下午2:45 6 | */ 7 | define([ 8 | 'config' 9 | ], function(config){ 10 | 'use strict'; 11 | 12 | return ['$scope', 'auth', '$http', function($scope, Auth, $http){ 13 | Auth.isLogined(); 14 | }]; 15 | }); -------------------------------------------------------------------------------- /app/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-5 5 | * Time: 下午4:04 6 | */ 7 | define(function(){ 8 | //定义要加载的模块 9 | return window.config = { 10 | host: 'http://localhost/angular-build-seed/app/' 11 | , domain: 'http://localhost/angular-build-seed/mock/index.php?rest/V1/' 12 | , modules:[ 13 | 'modules/publish' 14 | ] 15 | }; 16 | }); -------------------------------------------------------------------------------- /app/css/table-fixed-header.css: -------------------------------------------------------------------------------- 1 | table .header-fixed { 2 | position: fixed; 3 | top: 0px; 4 | z-index: 1020; /* 10 less than .navbar-fixed to prevent any overlap */ 5 | border-bottom: 1px solid #d5d5d5; 6 | -webkit-border-radius: 0; 7 | -moz-border-radius: 0; 8 | border-radius: 0; 9 | -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1); 10 | -moz-box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1); 11 | box-shadow: inset 0 1px 0 #fff, 0 1px 5px rgba(0,0,0,.1); 12 | filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); /* IE6-9 */ 13 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-build-seed", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "kazaff", 10 | "license": "BSD-2-Clause", 11 | "devDependencies": { 12 | "grunt": "~0.4.2", 13 | "grunt-contrib-uglify": "~0.2.7", 14 | "grunt-contrib-concat": "~0.3.0", 15 | "grunt-contrib-requirejs": "~0.4.1", 16 | "grunt-contrib-cssmin": "~0.7.0", 17 | "grunt-contrib-clean": "~0.5.0", 18 | "grunt-contrib-htmlmin": "~0.1.3", 19 | "grunt-hashres": "~0.3.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/modules/publish/templetes/dashboard.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
Welcome
7 |
8 |
9 |
10 |

欢迎

11 |

12 |
13 |
14 |
15 |
16 |
17 |
-------------------------------------------------------------------------------- /mock/templetes/lock.php: -------------------------------------------------------------------------------- 1 | 4 |
5 |
6 |
7 |
8 |
9 |
Welcome
10 |
11 |
12 |
13 |

锁屏

14 |

测试全局加载

15 |
16 |
17 |
18 |
19 |
20 |
-------------------------------------------------------------------------------- /app/lib/angularJS/bootstrap-datepicker.zh-CN.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Simplified Chinese translation for bootstrap-datepicker 3 | * Yuan Cheung 4 | */ 5 | ;(function($){ 6 | $.fn.datepicker.dates['zh-CN'] = { 7 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], 8 | daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], 9 | daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"], 10 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 11 | monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 12 | today: "今日", 13 | format: "yyyy年mm月dd日", 14 | weekStart: 1 15 | }; 16 | }(jQuery)); 17 | -------------------------------------------------------------------------------- /app/modules/publish/init.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-4 5 | * Time: 下午4:22 6 | */ 7 | define([ 8 | //标准库 9 | 'lib/console-min' 10 | , 'angular/angular' 11 | //控制器 12 | , 'modules/publish/controllers/dashboard' 13 | , 'modules/publish/controllers/lock' 14 | //服务 15 | , 'angular/angular-resource' 16 | ], function(console, angular, dashboardCtrl, lockCtrl){ 17 | 'use strict'; 18 | 19 | console.group('公共模块初始化'); 20 | 21 | var publishModule = angular.module('publishModule', ['ngResource']); 22 | publishModule.controller('dashboardCtrl', dashboardCtrl); 23 | publishModule.controller('lockCtrl', lockCtrl); 24 | 25 | console.groupEnd(); 26 | 27 | return publishModule; 28 | }); -------------------------------------------------------------------------------- /app/common/directives/blur.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-10-25 5 | * Time: 下午5:07 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | var initialize = function(module){ 11 | module.directive('ngBlur', ['$parse', function($parse) { 12 | return function(scope, element, attr) { 13 | var fn = $parse(attr['ngBlur']); 14 | element.bind('blur', function(event) { 15 | scope.$apply(function() { 16 | fn(scope, {$event:event}); 17 | }); 18 | }); 19 | } 20 | }]); 21 | 22 | return module; 23 | }; 24 | 25 | return { 26 | initialize: initialize 27 | }; 28 | }); -------------------------------------------------------------------------------- /app/common/directives/table-fixed-header.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-24 5 | * Time: 上午8:43 6 | */ 7 | define([ 8 | 9 | ], function(){ 10 | 'use strict'; 11 | 12 | var initialize = function(module){ 13 | 14 | module.directive('kzTableFixedHeader', [function(){ 15 | return { 16 | restrict: 'A' 17 | , link: function(scope, element, attrs){ 18 | 19 | element.addClass('table-fixed-header'); 20 | element.find('thead').addClass('header') 21 | 22 | element.fixedHeader(); 23 | } 24 | }; 25 | }]); 26 | 27 | return module; 28 | }; 29 | 30 | return { 31 | initialize: initialize 32 | }; 33 | }); -------------------------------------------------------------------------------- /app/utils/loader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-4 5 | * Time: 上午10:42 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | //处理要加载的模块的配置文件地址 11 | var loadModules = function(directorys){ 12 | var deps = []; 13 | 14 | for(var key in directorys){ 15 | deps.push(directorys[key] + '/init'); 16 | } 17 | 18 | return deps; 19 | }; 20 | 21 | //处理要定义的路由规则 22 | var loadRouteRules = function(directorys){ 23 | var deps = []; 24 | 25 | for(var key in directorys){ 26 | deps.push(directorys[key] + '/route'); 27 | } 28 | 29 | return deps; 30 | }; 31 | 32 | return { 33 | loadModules: loadModules 34 | , loadRouteRules: loadRouteRules 35 | }; 36 | }); -------------------------------------------------------------------------------- /app/common/services/acl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-6 5 | * Time: 下午4:40 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | var initialize = function(module){ 10 | module.factory('acl', ["$http", function($http){ 11 | return { 12 | verify: function(argument){ 13 | return $http({ 14 | method: 'GET' 15 | , url: config.domain + 'acl/menu/' + encodeURIComponent(JSON.stringify(argument)) 16 | }); 17 | } 18 | , status: function(api){ 19 | return $http({ 20 | method: 'GET' 21 | , url: config.domain + 'acl/api/' + encodeURIComponent(api) 22 | }); 23 | } 24 | }; 25 | }]); 26 | 27 | return module; 28 | }; 29 | 30 | return { 31 | initialize: initialize 32 | }; 33 | }); -------------------------------------------------------------------------------- /app/modules/publish/route.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-4 5 | * Time: 下午3:43 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | return { 11 | group: 'publish' 12 | , title: '控制台' 13 | , icon: 'icon-home' 14 | , son:[ 15 | { 16 | uri: '/dashboard' 17 | , controller: 'dashboardCtrl' 18 | , templateUrl: 'modules/publish/templetes/dashboard.html' 19 | , ifMenu: true 20 | , name: 'dashboard' 21 | , title: '仪表盘' 22 | , icon: 'icon-th' 23 | , api: 'restV1/dashboard/get' 24 | } 25 | ,{ 26 | uri: '/lock' 27 | , controller: 'lockCtrl' 28 | , templateUrl: '../mock/templetes/lock.php' 29 | , ifMenu: false 30 | , name: 'lock' 31 | , title: '锁屏' 32 | , icon: 'icon-lock' 33 | , api: '' 34 | , status: 1 35 | } 36 | ,{ 37 | ifMenu: false 38 | , name: 'logout' 39 | , title: '退出' 40 | , icon: 'icon-off' 41 | , api: '' 42 | , status: 1 43 | } 44 | ] 45 | }; 46 | }); -------------------------------------------------------------------------------- /app/lib/console-min.js: -------------------------------------------------------------------------------- 1 | // 2 | // Logging 3 | 4 | // @See: http://benalman.com/projects/javascript-debug-console-log/ 5 | window.debug=(function(){var i=this,b=Array.prototype.slice,d=i.console,h={},f,g,m=9,c=["error","warn","info","debug","log"],l="assert clear count dir dirxml exception group groupCollapsed groupEnd profile profileEnd table time timeEnd trace".split(" "),j=l.length,a=[];while(--j>=0){(function(n){h[n]=function(){m!==0&&d&&d[n]&&d[n].apply(d,arguments)}})(l[j])}j=c.length;while(--j>=0){(function(n,o){h[o]=function(){var q=b.call(arguments),p=[o].concat(q);a.push(p);e(p);if(!d||!k(n)){return}d.firebug?d[o].apply(i,q):d[o]?d[o](q):d.log(q)}})(j,c[j])}function e(n){if(f&&(g||!d||!d.log)){f.apply(i,n)}}h.setLevel=function(n){m=typeof n==="number"?n:9};function k(n){return m>0?m>n:c.length+m<=n}h.setCallback=function(){var o=b.call(arguments),n=a.length,p=n;f=o.shift()||null;g=typeof o[0]==="boolean"?o.shift():false;p-=typeof o[0]==="number"?o.shift():n;while(p= headTop && !isFixed) { isFixed = 1; } 24 | else if (scrollTop <= headTop && isFixed) { isFixed = 0; } 25 | isFixed ? $('thead.header-copy', o).removeClass('hide') 26 | : $('thead.header-copy', o).addClass('hide'); 27 | } 28 | $win.on('scroll', processScroll); 29 | 30 | // hack sad times - holdover until rewrite for 2.1 31 | $head.on('click', function () { 32 | if (!isFixed) setTimeout(function () { $win.scrollTop($win.scrollTop() - 47) }, 10); 33 | }) 34 | 35 | $head.clone().removeClass('header').addClass('header-copy header-fixed').appendTo(o); 36 | var ww = []; 37 | o.find('thead.header > tr:first > th').each(function (i, h){ 38 | ww.push($(h).width()); 39 | }); 40 | $.each(ww, function (i, w){ 41 | o.find('thead.header > tr > th:eq('+i+'), thead.header-copy > tr > th:eq('+i+')').css({width: w}); 42 | }); 43 | 44 | o.find('thead.header-copy').css({ margin:'0 auto', 45 | width: o.width(), 46 | 'background-color':config.bgColor }); 47 | processScroll(); 48 | }); 49 | }; 50 | 51 | })(jQuery); 52 | 53 | $(window).on('resize', function(){ 54 | $('.header-copy').width($('.table-fixed-header').width()) 55 | }); -------------------------------------------------------------------------------- /app/common/directives/bread-crumbs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-13 5 | * Time: 2:54 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | var initialize = function(module){ 11 | 12 | module.directive('kzBreadcrumbs', ['$location', function($location){ 13 | return { 14 | restrict: 'EA' 15 | , replace: true 16 | , template: '' 21 | , link: function(scope, element, attrs){ 22 | scope.removeHash = function(){ 23 | $location.hash(''); 24 | }; 25 | 26 | scope.cleanBread = function(index){ 27 | scope.data.splice(index + 1); 28 | window.localStorage.breadCrumbs = JSON.stringify(scope.data); 29 | } 30 | 31 | scope.$watch(function(){ 32 | return $location.hash(); 33 | }, function(hash){ 34 | scope.anchor = hash; 35 | }); 36 | 37 | scope.$on("$routeChangeSuccess", function(){ 38 | scope.data = JSON.parse(window.localStorage.breadCrumbs); 39 | }); 40 | } 41 | }; 42 | }]); 43 | 44 | return module; 45 | }; 46 | 47 | return { 48 | initialize: initialize 49 | }; 50 | }); -------------------------------------------------------------------------------- /app/common/directives/switch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-26 5 | * Time: 下午5:45 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | var initialize = function(module){ 11 | module.directive('kzSwitch', [function(){ 12 | return { 13 | restrict: 'E' 14 | , replace: true 15 | , template: '
' + 16 | '' + 17 | '
' 18 | , scope: { 19 | id: '=' 20 | , method: '&' 21 | , model: '=' 22 | , active: '=' 23 | } 24 | , link: function(scope, element, attrs){ 25 | 26 | element.bootstrapSwitch(); 27 | element.bootstrapSwitch('setState', scope.model); 28 | element.bootstrapSwitch('setActive', scope.active); 29 | 30 | element.on('switch-change', function(e, data){ 31 | scope.method({item: scope.id, status: data.value}).then(function(response){ 32 | element.bootstrapSwitch('setState', !data.value, true); 33 | }); //调用业务回调 34 | scope.$root.$$phase || scope.$apply(); //避免$digest already in progress 35 | }); 36 | 37 | scope.$watch('model', function(value){ 38 | element.bootstrapSwitch('setState', value, true); //第三个参数用于禁止触发'switch-change'事件,避免死循环 39 | }); 40 | 41 | scope.$watch('active', function(value){ 42 | element.bootstrapSwitch('setActive', value); 43 | }); 44 | } 45 | }; 46 | }]); 47 | 48 | return module; 49 | }; 50 | 51 | return { 52 | initialize: initialize 53 | }; 54 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-build-seed 2 | 3 | 4 | ## 基于AngularJS的开发框架模板 5 | 6 | 该项目用于解决试图以[AngularJS](http://angularjs.cn)为基础进行前端项目开发时要面对的一些问题: 7 | 8 | * 项目基于模块的文件结构 9 | * 多人合作开发的约定 10 | * 常用的基于web的管理系统后台功能,例如:权限 11 | 12 | 13 | ## 背景 14 | 15 | 这个需求源自于公司的一个项目的前端重构,我被任命来完成这次重构。 16 | 我不能说旧的代码如何如何的糟糕,我只能说确实有必要进行一次彻底的重构,这并不是盲目的跟风,更不是为了重构而重构。 17 | 18 | 由于主要目的是为了完成现有项目的前端,所以部分设计是为了迁就现有功能模块的一种妥协,而之所以把该项目发布到github,是希望能给他人一个参考,也希望能得到大家的肯定,更希望能得到大家的宝贵意见~ 19 | 20 | ## 依赖 21 | 22 | * [AngularJS](http://angularjs.org) v1.2.0-rc2 23 | * [RequireJS](http://www.requirejs.org) v2.1.8 24 | * [Bootstrap](http://www.bootcss.com) v2.3.2 25 | 26 | 27 | ## 文件目录结构 28 | 29 | ~~~ 30 | app/ 31 | common/ -->通用模块文件夹 32 | controllers/ -->控制器文件夹 33 | menu.js -->主菜单控制器 34 | directives/ -->指令文件夹 35 | action.js -->用于应用中定义链接的指令 36 | services/ -->服务文件夹 37 | acl.js -->授权服务代码 38 | action.js -->用于提供给action指令使用的认证服务 39 | auth.js -->认证服务代码 40 | init.js -->模块的初始化文件 41 | css/ -->项目的样式文件夹 42 | img/ -->项目的图片文件夹 43 | lib/ -->项目使用的第三方js库文件夹,包含requireJS,angularJS等 44 | modules/ -->业务模块文件夹,里面按照每个模块一个独立的文件夹来存放 45 | publish/ 46 | controllers/ -->模块下的控制器文件夹 47 | dashboard.js -->控制器代码文件 48 | templetes/ -->对应的视图文件夹 49 | dashboard.html -->视图文件 50 | init.js -->模块的初始化文件 51 | route.js -->模块的路由配置文件 52 | ... 53 | utils/ -->工具集合文件夹 54 | loader.js -->用于加载模块的函数 55 | ... 56 | app.js -->应用主模块文件 57 | bootstrap.js -->requireJS的配置及应用构建引导文件 58 | config.js -->应用的配置文件 59 | index.html -->应用的入口文件 60 | mock/ -->模拟后端服务 61 | ~~~ 62 | 63 | ![关系图](http://pic.yupoo.com/kazaff/D9SAL5yH/medish.jpg) 64 | 65 | ## 约定 66 | 67 | 每个模块(包含commom和modules下的每个文件夹)文件夹下,都应该包含`init.js`和`route.js`2个文件,前者是用来构造该模块,后者用来提供该模块的路由数据。 68 | 69 | ## 发布 70 | 71 | 执行在根目录下执行`grunt`,用于发布前的优化处理~ 72 | 这里要说明的是,需要把系统所有依赖的文件集中的写在`app/bootstrap.js`的`require`方法的依赖参数数组中,方便grunt-contrib-requirejs的合并~ 73 | 74 | 希望大家支持~ -------------------------------------------------------------------------------- /app/common/directives/ztree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: fengtao 4 | * Date: 13-10-3 5 | * Time: 下午3:13 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | var initialize = function(module){ 11 | module.directive('kzZtree', [function(){ 12 | return { 13 | restrict: 'E' 14 | , replace: true 15 | , template: '' 16 | , scope: { 17 | setting: '=' 18 | , tid: '@' 19 | } 20 | , link: function(scope, element, attrs){ 21 | //若没有指定dom的id,则把当前dom的id指定为scope的编号 22 | if(angular.isUndefined(scope.tid)){ 23 | element.attr('id', scope.$id); 24 | }else{ 25 | element.attr('id', scope.tid); 26 | } 27 | 28 | 29 | var zTree = null; 30 | 31 | if(attrs.type == "dynamic"){ 32 | scope.$watch('setting', function(newValue){ 33 | if(!angular.isUndefined(newValue)){ 34 | init(); 35 | } 36 | }); 37 | }else{ 38 | init(); 39 | } 40 | 41 | //初始化树 42 | function init(){ 43 | var data = null; 44 | if(!angular.isUndefined(scope.setting) && !angular.isUndefined(scope.setting.staticData)){ 45 | data = scope.setting.staticData; 46 | } 47 | zTree = jQuery.fn.zTree.init(element, scope.setting, data); 48 | 49 | if(attrs.expandall === 'true'){ 50 | zTree.expandAll(true); 51 | } 52 | } 53 | } 54 | }; 55 | }]); 56 | return module; 57 | }; 58 | 59 | return { 60 | initialize: initialize 61 | }; 62 | }); -------------------------------------------------------------------------------- /app/common/directives/action.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-10 5 | * Time: 上午9:59 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | var initialize = function(module){ 11 | module.directive('kzAction', ['action', function(action){ 12 | return { 13 | restrict: 'EA' 14 | , replace: true 15 | , template: '' 16 | , scope: {} 17 | , link: function(scope, element, attrs){ 18 | action.link(attrs.name, attrs.group).success(function(response){ 19 | var data = angular.copy(response); 20 | 21 | element.html(' ' + data.title + ''); 22 | element.find('i').tooltip(); 23 | 24 | if(data.status == 0){ 25 | //TODO 需要判断当前用户是否有权限进行该操作 26 | element.remove(); //若无权限,则不显示该链接 27 | //element.addClass('disabled'); //若无权限,则禁用该链接 28 | //element.attr('href', ''); 29 | 30 | }else{ 31 | if(!angular.isUndefined(data.uri)){ 32 | //替换uri中的动态参数 33 | if(!angular.isUndefined(attrs.args) && ! /:(\s*)[,|}]/.test(attrs.args)){ 34 | 35 | //把字符串转换成js对象 36 | var argObj = (new Function('return ' + attrs.args + ';'))(); 37 | 38 | angular.forEach(argObj, function(value, key){ 39 | data.uri = data.uri.replace(':'+key, value); 40 | }); 41 | } 42 | element.attr('href', '#!' + data.uri); 43 | } 44 | } 45 | }); 46 | } 47 | }; 48 | }]); 49 | 50 | return module; 51 | }; 52 | 53 | return { 54 | initialize: initialize 55 | }; 56 | }); -------------------------------------------------------------------------------- /app/lib/html5shiv.js: -------------------------------------------------------------------------------- 1 | /* 2 | HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); 5 | a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x"; 6 | c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| 7 | "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); 8 | for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d ul{border-bottom: 1px solid #37414b} 16 | #sidebar > ul > li { 17 | border-top: 1px solid #37414b; border-bottom: 1px solid #1f262d; 18 | } 19 | #sidebar > ul > li.active { 20 | background-color: #27a9e3; border-bottom: 1px solid #27a9e3; border-top: 1px solid #27a9e3; 21 | } 22 | #sidebar > ul > li.active a{ color:#fff; text-decoration:none;} 23 | 24 | #sidebar > ul > li > a > .label { 25 | background-color:#F66; 26 | } 27 | #sidebar > ul > li > a:hover { 28 | background-color: #27a9e3; color:#fff; 29 | } 30 | #sidebar > ul li ul { 31 | background-color: #1e242b; 32 | } 33 | #sidebar > ul li ul li a{ color:#939da8} 34 | #sidebar > ul li ul li a:hover, #sidebar > ul li ul li.active a { 35 | color: #fff; 36 | background-color: #28b779; 37 | } 38 | 39 | 40 | #search input[type=text] { 41 | background-color: #47515b; color: #fff; 42 | } 43 | #search input[type=text]:focus { 44 | color: #2e363f; color: #fff; box-shadow:none; 45 | } 46 | .dropdown-menu li a:hover, .dropdown-menu .active a, .dropdown-menu .active a:hover { 47 | color: #eeeeee; 48 | background:#666; 49 | 50 | } 51 | .top_message{ float:right; padding:20px 12px; position:relative; top:-13px; border-left:1px solid #3D3A37; font-size:14px; line-height:20px; *line-height:20px; color:#333; text-align:center; vertical-align:middle; cursor:pointer; } 52 | .top_message:hover{ background:#000} 53 | .rightzero{ right:0px; display:none;} 54 | @media (max-width: 480px) { 55 | #sidebar > a { 56 | background:#28b779; 57 | 58 | } 59 | .quick-actions_homepage .quick-actions li{ min-width:100%;} 60 | } 61 | @media (min-width: 768px) and (max-width: 970px) {.quick-actions_homepage .quick-actions li{ min-width:20.5%;}} 62 | @media (min-width: 481px) and (max-width: 767px) { 63 | .uneditable-input[class*="span"], 64 | .row-fluid [class*="span"] { 65 | width: 60%; 66 | } 67 | .span12, .row-fluid .span12 { 68 | width: 100%; 69 | } 70 | #sidebar > ul ul:before { 71 | } 72 | #sidebar > ul ul:after { 73 | border-right: 6px solid #222222; 74 | } 75 | .quick-actions_homepage .quick-actions li{ min-width:47%;} 76 | } 77 | div.tagsinput { border:1px solid #CCC; background: #FFF; padding:5px; width:300px; height:100px; overflow-y: auto;} 78 | div.tagsinput span.tag { border: 1px solid #a5d24a; -moz-border-radius:2px; -webkit-border-radius:2px; display: block; float: left; padding: 5px; text-decoration:none; background: #cde69c; color: #638421; margin-right: 5px; margin-bottom:5px;font-family: helvetica; font-size:13px;} 79 | div.tagsinput span.tag a { font-weight: bold; color: #82ad2b; text-decoration:none; font-size: 11px; } 80 | div.tagsinput input { width:80px; margin:0px; font-family: helvetica; font-size: 13px; border:1px solid transparent; padding:5px; background: transparent; color: #000; outline:0px; margin-right:5px; margin-bottom:5px; } 81 | div.tagsinput div { display:block; float: left; } 82 | .tags_clear { clear: both; width: 100%; height: 0px; } 83 | .not_valid {background: #FBD8DB !important; color: #90111A !important;} -------------------------------------------------------------------------------- /app/lib/angularJS/angular-route.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.0-rc.3 3 | (c) 2010-2012 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(u,c,A){'use strict';function w(c,s,g,b,d){return{restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(l,m,y){return function(p,l,m){function k(){h&&(h.$destroy(),h=null);q&&(d.leave(q),q=null)}function x(){var a=c.current&&c.current.locals,e=a&&a.$template;if(e){var r=p.$new();y(r,function(v){k();v.html(e);d.enter(v,null,l);var f=g(v.contents()),n=c.current;h=n.scope=r;q=v;if(n.controller){a.$scope=h;var p=b(n.controller,a);n.controllerAs&&(h[n.controllerAs]=p); 7 | v.data("$ngControllerController",p);v.children().data("$ngControllerController",p)}f(h);h.$emit("$viewContentLoaded");h.$eval(t);s()})}else k()}var h,q,t=m.onload||"";p.$on("$routeChangeSuccess",x);x()}}}}u=c.module("ngRoute",["ng"]).provider("$route",function(){function u(b,d){return c.extend(new (c.extend(function(){},{prototype:b})),d)}function s(b,c){var l=c.caseInsensitiveMatch,m={originalPath:b,regexp:b},g=m.keys=[];b=b.replace(/([().])/g,"\\$1").replace(/(\/)?:(\w+)([\?|\*])?/g,function(b, 8 | c,d,k){b="?"===k?k:null;k="*"===k?k:null;g.push({name:d,optional:!!b});c=c||"";return""+(b?"":c)+"(?:"+(b?c:"")+(k&&"(.+?)"||"([^/]+)")+(b||"")+")"+(b||"")}).replace(/([\/$\*])/g,"\\$1");m.regexp=RegExp("^"+b+"$",l?"i":"");return m}var g={};this.when=function(b,d){g[b]=c.extend({reloadOnSearch:!0},d,b&&s(b,d));if(b){var l="/"==b[b.length-1]?b.substr(0,b.length-1):b+"/";g[l]=c.extend({redirectTo:b},s(l,d))}return this};this.otherwise=function(b){this.when(null,b);return this};this.$get=["$rootScope", 9 | "$location","$routeParams","$q","$injector","$http","$templateCache","$sce",function(b,d,l,m,s,p,w,z){function k(){var a=x(),e=t.current;if(a&&e&&a.$$route===e.$$route&&c.equals(a.pathParams,e.pathParams)&&!a.reloadOnSearch&&!q)e.params=a.params,c.copy(e.params,l),b.$broadcast("$routeUpdate",e);else if(a||e)q=!1,b.$broadcast("$routeChangeStart",a,e),(t.current=a)&&a.redirectTo&&(c.isString(a.redirectTo)?d.path(h(a.redirectTo,a.params)).search(a.params).replace():d.url(a.redirectTo(a.pathParams,d.path(), 10 | d.search())).replace()),m.when(a).then(function(){if(a){var b=c.extend({},a.resolve),e,f;c.forEach(b,function(a,e){b[e]=c.isString(a)?s.get(a):s.invoke(a)});c.isDefined(e=a.template)?c.isFunction(e)&&(e=e(a.params)):c.isDefined(f=a.templateUrl)&&(c.isFunction(f)&&(f=f(a.params)),f=z.getTrustedResourceUrl(f),c.isDefined(f)&&(a.loadedTemplateUrl=f,e=p.get(f,{cache:w}).then(function(a){return a.data})));c.isDefined(e)&&(b.$template=e);return m.all(b)}}).then(function(d){a==t.current&&(a&&(a.locals=d, 11 | c.copy(a.params,l)),b.$broadcast("$routeChangeSuccess",a,e))},function(c){a==t.current&&b.$broadcast("$routeChangeError",a,e,c)})}function x(){var a,b;c.forEach(g,function(r,k){var f;if(f=!b){var n=d.path();f=r.keys;var h={};if(r.regexp)if(n=r.regexp.exec(n)){for(var g=1,l=n.length;gbootstrap.js': '<%= root %>bootstrap.min.js' 9 | , '<%= root %>config.js': '<%= root %>config.js' 10 | } 11 | } 12 | } 13 | , htmlmin: { 14 | options: { 15 | removeComments: true 16 | , collapseWhitespace: true 17 | } 18 | , frame: { 19 | files: { 20 | "<%= root %>index.html": "<%= root %>index.html" 21 | } 22 | } 23 | , templates: { 24 | expand: true 25 | , cwd: "<%= root %>modules/" 26 | , src: ['**/*.html'] 27 | , dest: "<%= root %>modules/" 28 | } 29 | } 30 | , cssmin: { 31 | minify: { 32 | expand: true 33 | , cwd: '<%= root %>css/' 34 | , src: ['*.css', '!main.css'] 35 | , dest: '<%= root %>css/' 36 | } 37 | , combine: { 38 | files: { 39 | '<%= root %>css/main.css': ['<%= root %>css/matrix-style.css', '<%= root %>css/matrix-media.css', '<%= root %>css/jquery.gritter.css', '<%= root %>css/matrix-media.css', '<%= root %>css/table-fixed-header.css', '<%= root %>css/font-awesome.css', '<%= root %>css/nprogress.css'] 40 | } 41 | } 42 | 43 | } 44 | , requirejs: { 45 | compile:{ 46 | options: { 47 | name: "bootstrap" 48 | , baseUrl: "<%= root %>" 49 | , mainConfigFile: "<%= root %>bootstrap.js" 50 | , out: "<%= root %>bootstrap.min.js" 51 | , optimize: "none" 52 | , useStrict: true 53 | , paths: { 54 | 'angular/angular': 'empty:' 55 | , 'jquery/jquery': 'empty:' 56 | , 'lib/bootstrap': 'empty:' 57 | , 'jquery/jquery.gritter.min': 'empty:' 58 | , 'jquery/table-fixed-header': 'empty:' 59 | , 'jquery/jquery.ztree.all-3.5.min': 'empty:' 60 | , 'angular/angular-resource': 'empty:' 61 | , 'angular/angular-route': 'empty:' 62 | , 'angular/angular-animate': 'empty:' 63 | , 'angular/angular-strap': 'empty:' 64 | , 'angular/bootstrap-datepicker': 'empty:' 65 | , 'angular/bootstrap-datepicker.zh-CN': 'empty:' 66 | , 'jquery/bootstrap-switch.min': 'empty:' 67 | , 'angular/angular-sanitize.min': 'empty:' 68 | , 'lib/console-min': 'empty:' 69 | , 'lib/modernizr': 'empty:' 70 | , 'jquery/nprogress': 'empty:' 71 | } 72 | } 73 | } 74 | } 75 | , hashres: { 76 | options: { 77 | encoding: 'utf8' 78 | , fileNameFormat: '${name}.${hash}.${ext}' 79 | , renameFiles: true 80 | } 81 | , indexJS: { 82 | src: '<%= root %>bootstrap.js' 83 | , dest: '<%= root %>index.html' 84 | } 85 | , configJS: { 86 | src: '<%= root %>config.js' 87 | , dest: '<%= root %>login.html' 88 | } 89 | , mainCSS: { 90 | src: '<%= root %>css/main.css' 91 | , dest: '<%= root %>index.html' 92 | } 93 | } 94 | , clean: { 95 | js: { 96 | src: ['<%= root %>modules/**/controllers', '<%= root %>modules/**/services', '<%= root %>modules/**/init.js', '<%= root %>modules/**/route.js', '<%= root %>common', '<%= root %>bootstrap.min.js', '<%= root %>app.js', '<%= root %>utils'] 97 | } 98 | } 99 | }); 100 | 101 | grunt.loadNpmTasks('grunt-contrib-uglify'); 102 | grunt.loadNpmTasks('grunt-contrib-requirejs'); 103 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 104 | grunt.loadNpmTasks('grunt-contrib-clean'); 105 | grunt.loadNpmTasks('grunt-contrib-htmlmin'); 106 | grunt.loadNpmTasks('grunt-hashres'); 107 | 108 | grunt.registerTask('default', ['requirejs','uglify', 'cssmin', 'htmlmin', 'hashres', 'clean']); 109 | }; -------------------------------------------------------------------------------- /app/css/matrix-login.css: -------------------------------------------------------------------------------- 1 | html, body { width: 100%; height: 90%;} 2 | /*Bootstrap-overlay*/ 3 | 4 | body { 5 | overflow-x: hidden; 6 | margin-top: -10px; font-family: 'Open Sans', sans-serif; font-size:12px; color:#666; 7 | } 8 | a{color:#666;} 9 | a:hover, a:focus { 10 | text-decoration: none; color:#28b779; 11 | } 12 | .dropdown-menu .divider{ margin:4px 0px;} 13 | .dropdown-menu{ min-width:180px;} 14 | .dropdown-menu > li > a{ padding:3px 10px; color:#666; font-size:12px;} 15 | .dropdown-menu > li > a i{ padding-right:3px;} 16 | .userphoto img{ width:19px; height:19px;} 17 | select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input, .label, .dropdown-menu, .btn, .well, .progress, .table-bordered, .btn-group > .btn:first-child, .btn-group > .btn:last-child, .btn-group > .btn:last-child, .btn-group > .dropdown-toggle, .alert{ border-radius:0px;} 18 | .btn, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input{ box-shadow:none;} 19 | .progress, .progress-success .bar, .progress .bar-success, .progress-warning .bar, .progress .bar-warning, .progress-danger .bar, .progress .bar-danger, .progress-info .bar, .progress .bar-info, .btn, .btn-primary{background-image:none;} 20 | .accordion-heading h5{ width:70%; } 21 | .form-horizontal .form-actions{ padding-left:20px; } 22 | #footer{ padding:10px; text-align:center;} 23 | hr{ border-top-color:#dadada;} 24 | .carousel{ margin-bottom:0px;} 25 | .fl { float:left} 26 | .fr {float:right} 27 | .label-important, .badge-important{ background:#f74d4d;} 28 | 29 | /*Metro Background color class*/ 30 | .bg_lb{ background:#27a9e3;} 31 | .bg_db{ background:#2295c9;} 32 | .bg_lg{ background:#28b779;} 33 | .bg_dg{ background:#28b779;} 34 | .bg_ly{ background:#ffb848;} 35 | .bg_dy{ background:#da9628;} 36 | .bg_ls{ background:#2255a4;} 37 | .bg_lo{ background:#da542e;} 38 | .bg_lr{ background:#f74d4d;} 39 | .bg_lv{ background:#603bbc;} 40 | .bg_lh{ background:#b6b3b3;} 41 | 42 | body { background-color:#2E363F; padding: 0; margin-top:10%;} 43 | #logo, #loginbox { width: 50%; margin-left: auto; margin-right: auto; position: relative;} 44 | #logo img { margin: 0 auto; display: block;} 45 | #loginbox { overflow: hidden !important; text-align: left; position: relative; } 46 | #loginbox form{ width:100%; background:#2E363F; position:relative; top:0; left:0; } 47 | #loginbox .form-actions { padding: 14px 20px 15px;} 48 | #loginbox .form-actions .pull-left { margin-top:0px;} 49 | #loginbox form#loginform { z-index: 200; display:block;} 50 | #loginbox form#recoverform { z-index: 100; display:none;} 51 | #loginbox form#recoverform .form-actions { margin-top: 10px;} 52 | #loginbox .main_input_box { margin:0 auto; text-align:center; font-size:13px;} 53 | #loginbox .main_input_box .add-on{ padding:9px 9px; *line-height:31px; color:#fff; width:30px; display:inline-block;} 54 | #loginbox .main_input_box input{ height:30px; border:0px; display:inline-block; width:75%; line-height:28px; margin-bottom:3px;} 55 | #loginbox .controls{ padding:0 20px;} 56 | #loginbox .control-group{ padding:20px 0; margin-bottom:0px;} 57 | .form-vertical, .form-actions { margin-bottom: 0; background:none; border-top:1px solid #3f4954; } 58 | #loginbox .normal_text{ padding:15px 10px; text-align:center; font-size:14px; line-height:20px; background:#2E363F; color:#fff; } 59 | .input-error{ text-align: center;} 60 | .input-error div{ text-align: left;} 61 | @media (max-width:800px){ 62 | #logo { width: 60%; } 63 | #loginbox{ width:80%} 64 | } 65 | @media (max-width: 480px){ 66 | #logo { width: 40%; } 67 | #loginbox{ width:90%} 68 | #loginbox .control-group{ padding:8px 0; margin-bottom:0px;} 69 | } -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-4 5 | * Time: 上午9:54 6 | */ 7 | define([ 8 | //标准库 9 | 'lib/console-min' 10 | , 'angular/angular' 11 | , 'common/init' 12 | , 'angular/angular-resource' 13 | , 'angular/angular-route' 14 | , 'angular/angular-animate' 15 | , 'angular/angular-strap' 16 | ], function(console, angular, common){ 17 | 'use strict'; 18 | 19 | var initialize = function(needModules, routeRules){ 20 | 21 | console.group('初始化主模块配置'); 22 | 23 | var deps = ['ngResource', 'ngRoute', 'ngAnimate', '$strap.directives']; 24 | for(var index in needModules){ 25 | deps.push(needModules[index].name); 26 | } 27 | 28 | console.info('获取主模块依赖的模块:', deps); 29 | 30 | var mainModule = angular.module('webOS', deps); 31 | 32 | console.groupEnd(); 33 | console.info('定义该应用的主模块:', mainModule.name); 34 | 35 | mainModule.config(['$httpProvider', '$locationProvider', '$routeProvider', '$windowProvider', '$compileProvider', function($httpProvider, $locationProvider, $routeProvider, $windowProvider, $compileProvider){ 36 | 37 | $locationProvider.html5Mode(false).hashPrefix('!'); 38 | //解决跨域问题 39 | $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/); 40 | 41 | console.group('初始化主模块的路由规则'); 42 | 43 | angular.forEach(routeRules, function(item){ 44 | if(typeof(item) != 'undefined'){ 45 | angular.forEach(item.son, function(route){ 46 | 47 | if(!angular.isUndefined(route.uri)){ 48 | console.info('增加路由:', route.uri); 49 | 50 | $routeProvider.when(route.uri, { 51 | templateUrl: route.templateUrl 52 | , controller: route.controller 53 | }); 54 | } 55 | }); 56 | } 57 | }); 58 | 59 | //TODO 避免硬编码 60 | $routeProvider.otherwise({redirectTo:'/dashboard'}); 61 | 62 | console.groupEnd(); 63 | 64 | //TODO 为了兼容旧浏览器,需要增加其他浏览器端持久化token的方法 65 | if(window.localStorage.token){ 66 | $httpProvider.defaults.headers.common['AUTH'] = 'MD ' + window.localStorage.token; 67 | } 68 | 69 | //响应拦截器,用于检查登录状态 70 | $httpProvider.interceptors.push(function($q){ 71 | return { 72 | 'response': function(response){ 73 | 74 | //若返回的数据中指示该用户未登录,则触发跳转到登录页面 75 | if(!angular.isUndefined(response.data)){ 76 | if(!angular.isUndefined(response.data.loginStatus) && response.data.loginStatus == 0){ 77 | delete window.localStorage.token; //删除会话id 78 | $windowProvider.$get().location.href = config.host + 'login.html'; 79 | } 80 | 81 | if(!angular.isUndefined(response.data.allow) && response.data.allow == 0){ 82 | delete window.localStorage.token; //删除会话id 83 | $windowProvider.$get().location.href = config.host + 'login.html'; 84 | } 85 | } 86 | 87 | return response || $q.when(response); 88 | } 89 | }; 90 | }); 91 | }]); 92 | 93 | //加载通用模块 94 | common.initialize(mainModule, routeRules); 95 | 96 | //日期控件的配置 97 | mainModule.value('$strapConfig', { 98 | datepicker: { 99 | language: 'zh-CN' 100 | , weekStart: 1 101 | , todayBtn: 1 102 | , autoclose: 1 103 | , todayHighlight: 1 104 | , keyboardNavigation: 1 105 | , pickerPosition: 'bottom-left' 106 | , format: 'yyyy-mm-dd' 107 | } 108 | }); 109 | 110 | return mainModule; 111 | }; 112 | 113 | return { 114 | initialize: initialize 115 | }; 116 | }); -------------------------------------------------------------------------------- /app/common/directives/sidebar-menu.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-9-11 5 | * Time: 上午10:24 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | var initialize = function(module){ 11 | 12 | module 13 | .directive('kzSidebarMenu', [function(){ 14 | return { 15 | restrict: 'EA' 16 | , replace: true 17 | , template: '' 27 | , scope: { 28 | data: '=' 29 | } 30 | , controller: [function(){ 31 | //判断当前菜单组是否被选中:包含当前url显示的页面 32 | //该方法会在菜单出现交互后频繁调用,貌似ngClass会导致动态监听 33 | this.checkActive = function(group){ 34 | var breadCrumbs = null; 35 | if(!angular.isUndefined(window.localStorage.breadCrumbs)){ 36 | breadCrumbs = JSON.parse(window.localStorage.breadCrumbs); 37 | } 38 | var currentLoaction = angular.isUndefined(breadCrumbs[0])? null : breadCrumbs[0]; 39 | return (group === currentLoaction.group)? true: false; 40 | }; 41 | 42 | //初始化链接中的动态参数 43 | this.createLink = function(argObj){ 44 | return function(uri){ 45 | angular.forEach(argObj, function(value, key){ 46 | uri = uri.replace(':'+key, value); 47 | }); 48 | return uri; 49 | }; 50 | } 51 | }] 52 | , link: function(scope, element, attrs, controller){ 53 | scope.checkActive = controller.checkActive; 54 | scope.createLink = controller.createLink((new Function('return ' + attrs.args))()); 55 | 56 | scope.toggle = function(target){ 57 | angular.forEach(scope.data, function(item){ 58 | if(target !== item){ 59 | item.show = false; 60 | } 61 | }); 62 | 63 | target.show = !target.show; 64 | }; 65 | } 66 | }; 67 | }]) 68 | .directive('slideSwitch', ['$animate', function($animate){ 69 | return function(scope, element, attrs){ 70 | scope.$watch(attrs.slideSwitch, function(value){ 71 | if(value){ 72 | $animate.addClass(element, 'slideSwitchAnimate'); 73 | }else{ 74 | $animate.removeClass(element, 'slideSwitchAnimate'); 75 | } 76 | }); 77 | } 78 | }]) 79 | .animation('.slideSwitchAnimate', function(){ 80 | return { 81 | addClass: function(element, className){ 82 | element.slideDown(); 83 | }, 84 | removeClass: function(element, className){ 85 | element.slideUp(); 86 | } 87 | } 88 | }); 89 | 90 | return module; 91 | }; 92 | 93 | return { 94 | initialize: initialize 95 | }; 96 | }); -------------------------------------------------------------------------------- /app/bootstrap.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require.config({ 4 | baseUrl: '.' 5 | , paths: { 6 | 'angular': 'lib/angularJS' 7 | , 'jquery' : 'lib/jquery' 8 | } 9 | , shim: { 10 | 'lib/bootstrap': ['jquery/jquery'] 11 | , 'jquery/jquery.gritter.min': ['jquery/jquery'] 12 | , 'jquery/nprogress': ['jquery/jquery'] 13 | , 'jquery/table-fixed-header': ['jquery/jquery'] 14 | , 'jquery/jquery.ztree.all-3.5.min': ['jquery/jquery'] 15 | , 'angular/angular-resource': ['angular/angular'] 16 | , 'angular/angular-route': ['angular/angular'] 17 | , 'angular/angular-animate': ['angular/angular'] 18 | , 'angular/angular-strap': ['angular/angular', 'lib/bootstrap'] 19 | , 'angular/bootstrap-datepicker': ['angular/angular-strap'] 20 | , 'angular/bootstrap-datepicker.zh-CN': ['angular/bootstrap-datepicker'] 21 | , 'jquery/bootstrap-switch.min': ['jquery/jquery', 'lib/bootstrap'] 22 | , 'angular/angular': { 23 | exports: 'angular' 24 | , deps: ['jquery/jquery'] 25 | } 26 | , 'lib/console-min': { 27 | exports: 'console' 28 | } 29 | } 30 | }); 31 | 32 | require([ 33 | 'require' 34 | 35 | , 'lib/console-min' 36 | , 'utils/loader' 37 | , 'jquery/jquery' 38 | , 'angular/angular' 39 | 40 | , 'config' 41 | 42 | , 'lib/modernizr' 43 | , 'lib/bootstrap' 44 | 45 | , 'jquery/jquery.gritter.min' 46 | , 'jquery/nprogress' 47 | , 'jquery/table-fixed-header' 48 | , 'jquery/bootstrap-switch.min' 49 | , 'jquery/jquery.ztree.all-3.5.min' 50 | , 'angular/bootstrap-datepicker.zh-CN' 51 | 52 | , 'lib/blob' 53 | , 'lib/FileSaver' 54 | 55 | //公共代码 56 | , 'app' 57 | , 'common/services/auth' 58 | , 'common/services/acl' 59 | , 'common/services/action' 60 | , 'common/directives/action' 61 | , 'common/directives/sidebar-menu' 62 | , 'common/directives/bread-crumbs' 63 | , 'common/directives/table-fixed-header' 64 | , 'common/directives/switch' 65 | , 'common/directives/ztree' 66 | , 'common/directives/face-uploader' 67 | , 'common/directives/blur' 68 | , 'common/controllers/menu' 69 | , 'common/init' 70 | //业务代码 71 | , 'modules/publish/controllers/dashboard' 72 | , 'modules/publish/init' 73 | , 'modules/publish/route' 74 | 75 | ], function(require, console, loader, jquery, angular, config){ 76 | 77 | console.group('webOS应用'); 78 | 79 | console.group('判断浏览器是否内置支持json'); 80 | if(!window.JSON){ 81 | console.log('不支持,加载JSON2'); 82 | require(['lib/json2']); 83 | }else{ 84 | console.log('支持'); 85 | } 86 | console.groupEnd(); 87 | 88 | console.group('判断浏览器的JS引擎是否支持ES5标准'); 89 | if(!Function.prototype.bind){ 90 | console.log('不支持,加载es5-shim'); 91 | require(['lib/es5-shim']); 92 | }else{ 93 | console.log('支持'); 94 | } 95 | console.groupEnd(); 96 | 97 | console.group('确定要加载的模块'); 98 | console.info('应用要加载的业务模块:', config.modules); 99 | console.groupEnd(); 100 | 101 | var deps = ['./app'].concat(loader.loadRouteRules(config.modules), loader.loadModules(config.modules)); 102 | require(deps, function(){ 103 | 104 | console.info('requireJS的导入的模块:', arguments); 105 | console.group('计算要创建的路由规则数据'); 106 | 107 | //由于每个合法的模块都会包含init.js和route.js,所以这两类文件的个数应该是相等的 108 | var routes = []; 109 | for(var index = 1, max = (arguments.length - 1) / 2; index <= max; index++){ 110 | routes.push(arguments[index]); 111 | } 112 | 113 | console.info('需要定义的路由数据:', routes); 114 | console.groupEnd(); 115 | console.group('计算要加载的业务模块'); 116 | 117 | var modules = []; 118 | for(var index = (arguments.length - 1) / 2 + 1, max = arguments.length; index < max; index++ ){ 119 | if(typeof(arguments[index]) == 'undefined'){ 120 | throw new Error('欲加载的模块配置文件不符合AMD语法'); 121 | } 122 | 123 | modules.push(arguments[index]); 124 | } 125 | 126 | console.info('需要加载的业务模块:', modules); 127 | console.groupEnd(); 128 | 129 | var mainModule = arguments[0].initialize(modules, routes); 130 | 131 | console.info('主模块赋予根DOM'); 132 | 133 | angular.bootstrap(window.document, [mainModule.name]); 134 | }); 135 | }); -------------------------------------------------------------------------------- /app/lib/angularJS/angular-animate.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.2.0-rc.3 3 | (c) 2010-2012 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(m,f,n){'use strict';f.module("ngAnimate",["ng"]).config(["$provide","$animateProvider",function(A,s){var v=f.noop,w=f.forEach,B=s.$$selectors,k="$$ngAnimateState",x="ng-animate",u={running:!0};A.decorator("$animate",["$delegate","$injector","$sniffer","$rootElement","$timeout","$rootScope",function(q,m,y,n,p,g){function G(a){if(a){var c=[],b={};a=a.substr(1).split(".");(y.transitions||y.animations)&&a.push("");for(var e=0;e=m&&a.elapsedTime>=k&&e()}var h=x(c);if(!(0 2 | 8 | 14 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | web OS 33 | 34 | 35 | 36 | 37 | 40 | 43 | 44 | 45 | 54 | 55 |
56 | 57 | 60 | 61 | 62 | 63 | 74 | 75 | 76 | 77 | 81 | 82 | 83 | 84 |
85 | 86 |
87 | 88 |
89 | 90 | 91 |
92 |
93 | 94 | 95 | 96 | 97 |
98 | 99 |
100 | 101 |
102 | 103 | 121 | 122 | 143 | 144 | 145 | 149 | 150 | -------------------------------------------------------------------------------- /app/css/zTreeStyle.css: -------------------------------------------------------------------------------- 1 | /*------------------------------------- 2 | zTree Style 3 | 4 | version: 3.4 5 | author: Hunter.z 6 | email: hunter.z@263.net 7 | website: http://code.google.com/p/jquerytree/ 8 | 9 | -------------------------------------*/ 10 | 11 | .ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif} 12 | .ztree {margin:0; padding:5px; color:#333} 13 | .ztree li{padding:0; margin:0; list-style:none; line-height:14px; text-align:left; white-space:nowrap; outline:0} 14 | .ztree li ul{ margin:0; padding:0 0 0 18px} 15 | .ztree li ul.line{ background:url(../img/line_conn.gif) 0 0 repeat-y;} 16 | 17 | .ztree li a {padding:1px 3px 0 0; margin:0; cursor:pointer; height:17px; color:#333; background-color: transparent; 18 | text-decoration:none; vertical-align:top; display: inline-block} 19 | .ztree li a:hover {text-decoration:underline} 20 | .ztree li a.curSelectedNode {padding-top:0px; background-color:#ccc; color:black; height:16px; border:1px #000 solid; opacity:0.8;} 21 | .ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;} 22 | .ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#316AC5; color:white; height:16px; border:1px #316AC5 solid; 23 | opacity:0.8; filter:alpha(opacity=80)} 24 | .ztree li a.tmpTargetNode_prev {} 25 | .ztree li a.tmpTargetNode_next {} 26 | .ztree li a input.rename {height:14px; width:80px; padding:0; margin:0; 27 | font-size:12px; border:1px #7EC4CC solid; *border:0px} 28 | .ztree li span {line-height:16px; margin-right:2px} 29 | .ztree li span.button {line-height:0; margin:0; width:16px; height:16px; display: inline-block; vertical-align:middle; 30 | border:0 none; cursor: pointer;outline:none; 31 | background-color:transparent; background-repeat:no-repeat; background-attachment: scroll; 32 | background-image:url("../img/zTreeStandard.png"); *background-image:url("../img/zTreeStandard.gif")} 33 | 34 | .ztree li span.button.chk {width:13px; height:13px; margin:0 3px 0 0; cursor: auto} 35 | .ztree li span.button.chk.checkbox_false_full {background-position:0 0} 36 | .ztree li span.button.chk.checkbox_false_full_focus {background-position:0 -14px} 37 | .ztree li span.button.chk.checkbox_false_part {background-position:0 -28px} 38 | .ztree li span.button.chk.checkbox_false_part_focus {background-position:0 -42px} 39 | .ztree li span.button.chk.checkbox_false_disable {background-position:0 -56px} 40 | .ztree li span.button.chk.checkbox_true_full {background-position:-14px 0} 41 | .ztree li span.button.chk.checkbox_true_full_focus {background-position:-14px -14px} 42 | .ztree li span.button.chk.checkbox_true_part {background-position:-14px -28px} 43 | .ztree li span.button.chk.checkbox_true_part_focus {background-position:-14px -42px} 44 | .ztree li span.button.chk.checkbox_true_disable {background-position:-14px -56px} 45 | .ztree li span.button.chk.radio_false_full {background-position:-28px 0} 46 | .ztree li span.button.chk.radio_false_full_focus {background-position:-28px -14px} 47 | .ztree li span.button.chk.radio_false_part {background-position:-28px -28px} 48 | .ztree li span.button.chk.radio_false_part_focus {background-position:-28px -42px} 49 | .ztree li span.button.chk.radio_false_disable {background-position:-28px -56px} 50 | .ztree li span.button.chk.radio_true_full {background-position:-42px 0} 51 | .ztree li span.button.chk.radio_true_full_focus {background-position:-42px -14px} 52 | .ztree li span.button.chk.radio_true_part {background-position:-42px -28px} 53 | .ztree li span.button.chk.radio_true_part_focus {background-position:-42px -42px} 54 | .ztree li span.button.chk.radio_true_disable {background-position:-42px -56px} 55 | 56 | .ztree li span.button.switch {width:18px; height:18px} 57 | .ztree li span.button.root_open{background-position:-92px -54px} 58 | .ztree li span.button.root_close{background-position:-74px -54px} 59 | .ztree li span.button.roots_open{background-position:-92px 0} 60 | .ztree li span.button.roots_close{background-position:-74px 0} 61 | .ztree li span.button.center_open{background-position:-92px -18px} 62 | .ztree li span.button.center_close{background-position:-74px -18px} 63 | .ztree li span.button.bottom_open{background-position:-92px -36px} 64 | .ztree li span.button.bottom_close{background-position:-74px -36px} 65 | .ztree li span.button.noline_open{background-position:-92px -72px} 66 | .ztree li span.button.noline_close{background-position:-74px -72px} 67 | .ztree li span.button.root_docu{ background:none;} 68 | .ztree li span.button.roots_docu{background-position:-56px 0} 69 | .ztree li span.button.center_docu{background-position:-56px -18px} 70 | .ztree li span.button.bottom_docu{background-position:-56px -36px} 71 | .ztree li span.button.noline_docu{ background:none;} 72 | 73 | .ztree li span.button.ico_open{margin-right:2px; background-position:-110px -16px; vertical-align:top; *vertical-align:middle} 74 | .ztree li span.button.ico_close{margin-right:2px; background-position:-110px 0; vertical-align:top; *vertical-align:middle} 75 | .ztree li span.button.ico_docu{margin-right:2px; background-position:-110px -32px; vertical-align:top; *vertical-align:middle} 76 | .ztree li span.button.edit {margin-right:2px; background-position:-110px -48px; vertical-align:top; *vertical-align:middle} 77 | .ztree li span.button.remove {margin-right:2px; background-position:-110px -64px; vertical-align:top; *vertical-align:middle} 78 | 79 | .ztree li span.button.ico_loading{margin-right:2px; background:url(../img/loading-tree.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle} 80 | 81 | ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)} 82 | 83 | span.tmpzTreeMove_arrow {width:16px; height:16px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute; 84 | background-color:transparent; background-repeat:no-repeat; background-attachment: scroll; 85 | background-position:-110px -80px; background-image:url("../img/zTreeStandard.png"); *background-image:url("../img/zTreeStandard.gif")} 86 | 87 | ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)} 88 | .zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute} 89 | 90 | /* level style*/ 91 | /*.ztree li span.button.level0 { 92 | display:none; 93 | } 94 | .ztree li ul.level0 { 95 | padding:0; 96 | background:none; 97 | }*/ -------------------------------------------------------------------------------- /app/login.html: -------------------------------------------------------------------------------- 1 | 2 | 8 | 14 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | web OS 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 47 | 48 | 49 | 58 | 59 |
60 |
61 |

Logo

62 |
63 |
64 |
65 | 66 | 67 | 68 |
69 | 帐号不能为空哟~ 70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | 78 | 79 | 80 |
81 | 密码不能为空哟~ 82 | 密码不能少于六位哟~ 83 |
84 |
85 |
86 |
87 |
88 | 89 | 93 | 94 |
95 |
96 |
97 | 98 | 99 | 100 | 101 | 106 | 107 | 158 | 162 | 163 | -------------------------------------------------------------------------------- /app/lib/blob.js: -------------------------------------------------------------------------------- 1 | /* Blob.js 2 | * A Blob implementation. 3 | * 2013-06-20 4 | * 5 | * By Eli Grey, http://eligrey.com 6 | * By Devin Samarin, https://github.com/eboyjr 7 | * License: X11/MIT 8 | * See LICENSE.md 9 | */ 10 | 11 | /*global self, unescape */ 12 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, 13 | plusplus: true */ 14 | 15 | /*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ 16 | 17 | if (!(typeof Blob === "function" || typeof Blob === "object") || typeof URL === "undefined") 18 | if ((typeof Blob === "function" || typeof Blob === "object") && typeof webkitURL !== "undefined") self.URL = webkitURL; 19 | else var Blob = (function (view) { 20 | "use strict"; 21 | 22 | var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || view.MSBlobBuilder || (function(view) { 23 | var 24 | get_class = function(object) { 25 | return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; 26 | } 27 | , FakeBlobBuilder = function BlobBuilder() { 28 | this.data = []; 29 | } 30 | , FakeBlob = function Blob(data, type, encoding) { 31 | this.data = data; 32 | this.size = data.length; 33 | this.type = type; 34 | this.encoding = encoding; 35 | } 36 | , FBB_proto = FakeBlobBuilder.prototype 37 | , FB_proto = FakeBlob.prototype 38 | , FileReaderSync = view.FileReaderSync 39 | , FileException = function(type) { 40 | this.code = this[this.name = type]; 41 | } 42 | , file_ex_codes = ( 43 | "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " 44 | + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" 45 | ).split(" ") 46 | , file_ex_code = file_ex_codes.length 47 | , real_URL = view.URL || view.webkitURL || view 48 | , real_create_object_URL = real_URL.createObjectURL 49 | , real_revoke_object_URL = real_URL.revokeObjectURL 50 | , URL = real_URL 51 | , btoa = view.btoa 52 | , atob = view.atob 53 | 54 | , ArrayBuffer = view.ArrayBuffer 55 | , Uint8Array = view.Uint8Array 56 | ; 57 | FakeBlob.fake = FB_proto.fake = true; 58 | while (file_ex_code--) { 59 | FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; 60 | } 61 | if (!real_URL.createObjectURL) { 62 | URL = view.URL = {}; 63 | } 64 | URL.createObjectURL = function(blob) { 65 | var 66 | type = blob.type 67 | , data_URI_header 68 | ; 69 | if (type === null) { 70 | type = "application/octet-stream"; 71 | } 72 | if (blob instanceof FakeBlob) { 73 | data_URI_header = "data:" + type; 74 | if (blob.encoding === "base64") { 75 | return data_URI_header + ";base64," + blob.data; 76 | } else if (blob.encoding === "URI") { 77 | return data_URI_header + "," + decodeURIComponent(blob.data); 78 | } if (btoa) { 79 | return data_URI_header + ";base64," + btoa(blob.data); 80 | } else { 81 | return data_URI_header + "," + encodeURIComponent(blob.data); 82 | } 83 | } else if (real_create_object_URL) { 84 | return real_create_object_URL.call(real_URL, blob); 85 | } 86 | }; 87 | URL.revokeObjectURL = function(object_URL) { 88 | if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { 89 | real_revoke_object_URL.call(real_URL, object_URL); 90 | } 91 | }; 92 | FBB_proto.append = function(data/*, endings*/) { 93 | var bb = this.data; 94 | // decode data to a binary string 95 | if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { 96 | var 97 | str = "" 98 | , buf = new Uint8Array(data) 99 | , i = 0 100 | , buf_len = buf.length 101 | ; 102 | for (; i < buf_len; i++) { 103 | str += String.fromCharCode(buf[i]); 104 | } 105 | bb.push(str); 106 | } else if (get_class(data) === "Blob" || get_class(data) === "File") { 107 | if (FileReaderSync) { 108 | var fr = new FileReaderSync; 109 | bb.push(fr.readAsBinaryString(data)); 110 | } else { 111 | // async FileReader won't work as BlobBuilder is sync 112 | throw new FileException("NOT_READABLE_ERR"); 113 | } 114 | } else if (data instanceof FakeBlob) { 115 | if (data.encoding === "base64" && atob) { 116 | bb.push(atob(data.data)); 117 | } else if (data.encoding === "URI") { 118 | bb.push(decodeURIComponent(data.data)); 119 | } else if (data.encoding === "raw") { 120 | bb.push(data.data); 121 | } 122 | } else { 123 | if (typeof data !== "string") { 124 | data += ""; // convert unsupported types to strings 125 | } 126 | // decode UTF-16 to binary string 127 | bb.push(unescape(encodeURIComponent(data))); 128 | } 129 | }; 130 | FBB_proto.getBlob = function(type) { 131 | if (!arguments.length) { 132 | type = null; 133 | } 134 | return new FakeBlob(this.data.join(""), type, "raw"); 135 | }; 136 | FBB_proto.toString = function() { 137 | return "[object BlobBuilder]"; 138 | }; 139 | FB_proto.slice = function(start, end, type) { 140 | var args = arguments.length; 141 | if (args < 3) { 142 | type = null; 143 | } 144 | return new FakeBlob( 145 | this.data.slice(start, args > 1 ? end : this.data.length) 146 | , type 147 | , this.encoding 148 | ); 149 | }; 150 | FB_proto.toString = function() { 151 | return "[object Blob]"; 152 | }; 153 | return FakeBlobBuilder; 154 | }(view)); 155 | 156 | return function Blob(blobParts, options) { 157 | var type = options ? (options.type || "") : ""; 158 | var builder = new BlobBuilder(); 159 | if (blobParts) { 160 | for (var i = 0, len = blobParts.length; i < len; i++) { 161 | builder.append(blobParts[i]); 162 | } 163 | } 164 | return builder.getBlob(type); 165 | }; 166 | }(self)); -------------------------------------------------------------------------------- /app/common/directives/face-uploader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created with JetBrains WebStorm. 3 | * User: @kazaff 4 | * Date: 13-10-21 5 | * Time: 上午11:11 6 | */ 7 | define(function(){ 8 | 'use strict'; 9 | 10 | var initialize = function(module){ 11 | module.directive('kzFaceuploader', ['$modal', '$q', function($modal, $q){ 12 | return { 13 | restrict: 'A' 14 | , transclude: true 15 | , template: '
' + 16 | '
' + 17 | ' {{ tip }}' + 18 | '
' 19 | , scope: { 20 | tip: '@' 21 | , save: '&' 22 | } 23 | , link: function(scope, element, attrs){ 24 | scope.hover = false; 25 | scope.upload = false; 26 | scope.formData = new FormData(); 27 | scope.loading = false; 28 | 29 | element.hover(function(eventObject){ 30 | scope.hover = true; 31 | scope.$root.$$phase || scope.$apply(); //避免$digest already in progress 32 | }, function(eventObject){ 33 | scope.hover = false; 34 | scope.$root.$$phase || scope.$apply(); //避免$digest already in progress 35 | }); 36 | 37 | var modalPromise = $modal({ 38 | template: 'face.html' 39 | , persist: true 40 | , show: false 41 | , backdrop: 'static' 42 | , scope: scope 43 | }); 44 | var modal = $q.when(modalPromise); 45 | //用于触发 头像上传 的模态窗口 46 | scope.modalWin = function(){ 47 | modal.then(function(modalEl){ 48 | modalEl.modal('show'); 49 | }); 50 | }; 51 | 52 | var titleDom = angular.element(element.children()[1]); 53 | titleDom.on('click', function(event){ 54 | scope.modalWin(); 55 | }); 56 | 57 | scope.reset = function(){ 58 | scope.upload = false; 59 | scope.formData = new FormData(); 60 | jQuery('.face_area .upload_area').removeClass('upload_area_hover'); 61 | }; 62 | 63 | //文件上传方法 64 | scope.uploadFile = function(){ 65 | scope.loading = true; 66 | 67 | scope 68 | .save({data: scope.formData}) 69 | .success(function(data, status, headers, config){ 70 | 71 | angular.element(angular.element(element.children()[0]).children()[0]).attr('src', data.file); 72 | 73 | scope.reset(); 74 | scope.loading = false; 75 | modal.then(function(modalEl){ 76 | modalEl.modal('hide'); 77 | }); 78 | }) 79 | .error(function(data, status, headers, config){ 80 | console.log(data); 81 | }); 82 | }; 83 | } 84 | }; 85 | }]) 86 | .directive('kzFacearea', [function(){ 87 | return { 88 | restrict: 'E' 89 | , replace: true 90 | , template: '
' + 91 | '
' + 92 | '拖拽至此' + 93 | '' + 94 | '' + 95 | ' 选择' + 96 | '' + 97 | '' + 98 | '
' + 99 | '
' + 100 | '' + 101 | '
' + 102 | '
' 103 | , scope: { 104 | flag: '=', 105 | formdata: '=' 106 | } 107 | , link: function(scope, element, attrs){ 108 | 109 | var uploadArea = jQuery('.face_area .upload_area'); 110 | 111 | //监听input更改 112 | jQuery('#face-input').on('change', function(event){ 113 | 114 | var face = event.target.files[0]; 115 | 116 | //检查文件格式 117 | if(!face.type.match('image.*')){ 118 | return; //todo 119 | } 120 | 121 | scope.formdata.append('face', face); //把图片放入表单数据中 122 | 123 | var reader = new FileReader(); 124 | reader.onload = function(event){ 125 | jQuery('.face_area .img-polaroid').attr('src', event.target.result); 126 | }; 127 | reader.readAsDataURL(face); 128 | 129 | scope.flag = true; 130 | scope.$root.$$phase || scope.$apply(); //避免$digest already in progress 131 | }); 132 | 133 | //监听拖拽区域,注意这里必须使用原始的addEventListener方法,不支持jquery提供的on方法 134 | uploadArea[0].addEventListener('dragover', function(event){ 135 | event.stopPropagation(); 136 | event.preventDefault(); 137 | event.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. 138 | 139 | uploadArea.addClass('upload_area_hover'); 140 | 141 | }, false); 142 | 143 | uploadArea.on('dragleave', function(){ 144 | uploadArea.removeClass('upload_area_hover'); 145 | }); 146 | 147 | uploadArea[0].addEventListener('drop', function(event){ 148 | event.stopPropagation(); 149 | event.preventDefault(); 150 | 151 | uploadArea.removeClass('upload_area_hover'); 152 | 153 | var face = event.dataTransfer.files[0]; 154 | 155 | //检查文件格式 156 | if(!face.type.match('image.*')){ 157 | return; //todo 158 | } 159 | 160 | scope.formdata.append('face', face); //把图片放入表单数据中 161 | 162 | var reader = new FileReader(); 163 | reader.onload = function(event){ 164 | jQuery('.face_area .img-polaroid').attr('src', event.target.result); 165 | }; 166 | reader.readAsDataURL(face); 167 | 168 | scope.flag = true; 169 | scope.$root.$$phase || scope.$apply(); //避免$digest already in progress 170 | 171 | }, false); 172 | } 173 | }; 174 | }]); 175 | return module; 176 | }; 177 | 178 | return { 179 | initialize: initialize 180 | }; 181 | }); -------------------------------------------------------------------------------- /app/lib/jquery/bootstrap-switch.min.js: -------------------------------------------------------------------------------- 1 | /*! ============================================================ 2 | * bootstrapSwitch v1.8 by Larentis Mattia @SpiritualGuru 3 | * http://www.larentis.eu/ 4 | * 5 | * Enhanced for radiobuttons by Stein, Peter @BdMdesigN 6 | * http://www.bdmdesign.org/ 7 | * 8 | * Project site: 9 | * http://www.larentis.eu/switch/ 10 | * ============================================================ 11 | * Licensed under the Apache License, Version 2.0 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * ============================================================ */ 14 | !function($){"use strict";$.fn['bootstrapSwitch']=function(method){var inputSelector='input[type!="hidden"]';var methods={init:function(){return this.each(function(){var $element=$(this),$div,$switchLeft,$switchRight,$label,$form=$element.closest('form'),myClasses="",classes=$element.attr('class'),color,moving,onLabel="ON",offLabel="OFF",icon=false,textLabel=false;$.each(['switch-mini','switch-small','switch-large'],function(i,el){if(classes.indexOf(el)>=0)myClasses=el});$element.addClass('has-switch');if($element.data('on')!==undefined)color="switch-"+$element.data('on');if($element.data('on-label')!==undefined)onLabel=$element.data('on-label');if($element.data('off-label')!==undefined)offLabel=$element.data('off-label');if($element.data('label-icon')!==undefined)icon=$element.data('label-icon');if($element.data('text-label')!==undefined)textLabel=$element.data('text-label');$switchLeft=$('').addClass("switch-left").addClass(myClasses).addClass(color).html(onLabel);color='';if($element.data('off')!==undefined)color="switch-"+$element.data('off');$switchRight=$('').addClass("switch-right").addClass(myClasses).addClass(color).html(offLabel);$label=$('