ng+bootstrap可以做出很漂亮的管理系統出來,https://wrapbootstrap.com/可以付費購買,下文會提供一個免費的,要講解如何從0到1把ng前端結構搭出來是很漫長的教程,本文僅僅介紹一下這個免費后台模版的結構,然后重點講解如何改寫這個結構。
開始閱讀之前,假設讀者已經ng入門並且對於ui.router,bootstrap有一定了解。
下載鏈接http://pan.baidu.com/s/1o73ewfK
下載下來以后我們可以掛載到IIS里面看看這個模版的運行效果
1) 后台結構
其中我們需要關注的如下:
index.html: 入口
js: 存放所有業務邏輯代碼
js/app.js:定義ng需要加載的模塊
js/main.js:定義ng的全局配置信息
js/config.router.js:ng的路由器
tpl:存放所有頁面模版
tpl/blocks:頁面框架(頭、尾、側邊欄…)
vendor:存放所有第三方模塊
2) 改寫結構,接管路由
結構簡圖如下
這里接管的原則是盡量不改動原始結構,首先在根目錄創建我們自己的目錄結構.
> mkdir admin > mkdir admin\blocks > copy js\main.js admin\
- 1
- 2
- 3
- 1
- 2
- 3
編寫頁面框架模版,我們也可以直接從tpl目錄復制過來再做修改。簡單起見,我們在模版里面直接使用了中文,這樣會導致頁面亂碼,解決方法:html文件用utf-8編碼格式存儲。
<!--admin/blocks/aside.html--> <div class="aside-wrap"> <div class="navi-wrap"> <!-- nav --> <nav ui-nav class="navi" ng-include="'admin/blocks/nav.html'"></nav> <!-- nav --> </div> </div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
<!--admin/blocks/header.html--> <!-- navbar header --> <div class="navbar-header {{app.settings.navbarHeaderColor}}"> <button class="pull-right visible-xs dk" ui-toggle-class="show" data-target=".navbar-collapse"> <i class="glyphicon glyphicon-cog"></i> </button> <button class="pull-right visible-xs" ui-toggle-class="off-screen" data-target=".app-aside" ui-scroll="app"> <i class="glyphicon glyphicon-align-justify"></i> </button> <!-- brand --> <a href="#/" class="navbar-brand text-lt"> <i class="fa fa-btc"></i> <img src="img/logo.png" alt="." class="hide"> <span class="hidden-folded m-l-xs">{{app.name}}</span> </a> <!-- / brand --> </div> <!-- / navbar header --> <!-- navbar collapse --> <div class="collapse pos-rlt navbar-collapse box-shadow {{app.settings.navbarCollapseColor}}"> <!-- buttons --> <div class="nav navbar-nav hidden-xs"> <a href class="btn no-shadow navbar-btn" ng-click="app.settings.asideFolded = !app.settings.asideFolded"> <i class="fa {{app.settings.asideFolded ? 'fa-indent' : 'fa-dedent'}} fa-fw"></i> </a> </div> <!-- / buttons --> <!-- nabar right --> <ul class="nav navbar-nav navbar-right"> <li class="hidden-xs"> <a ui-fullscreen></a> </li> <li class="dropdown" dropdown> <a href class="dropdown-toggle clear" dropdown-toggle> <span class="thumb-sm avatar pull-right m-t-n-sm m-b-n-sm m-l-sm"> <img src="img/a0.jpg" alt="..."> <i class="on md b-white bottom"></i> </span> <span class="hidden-sm hidden-md"></span> <b class="caret"></b> </a> <!-- dropdown --> <ul class="dropdown-menu animated fadeInRight w"> <li> <a href="#">Logout</a> </li> </ul> <!-- / dropdown --> </li> </ul> <!-- / navbar right --> </div> <!-- / navbar collapse -->
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
<!--admin/blocks/nav.html--> <!-- list --> <ul class="nav"> <li class="hidden-folded padder m-t m-b-sm text-muted text-xs"> <span translate="導航">導航</span> </li> </ul> <!-- / list -->
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
<!--admin/app.html--> <!-- navbar --> <div data-ng-include=" 'admin/blocks/header.html' " class="app-header navbar"> </div> <!-- / navbar --> <!-- menu --> <div data-ng-include=" 'admin/blocks/aside.html' " class="app-aside hidden-xs {{app.settings.asideColor}}"> </div> <!-- / menu --> <!-- content --> <div class="app-content"> <div ui-butterbar></div> <a href class="off-screen-toggle hide" ui-toggle-class="off-screen" data-target=".app-aside" ></a> <div ncy-breadcrumb></div> <div class="app-content-body fade-in-up" ui-view></div> </div> <!-- /content --> <!-- footer --> <div class="app-footer wrapper b-t bg-light"> <span class="pull-right">{{app.version}} <a href ui-scroll="app" class="m-l-sm text-muted"><i class="fa fa-long-arrow-up"></i></a></span> © 2016 Copyright. </div> <!-- / footer --> <div data-ng-include=" 'tpl/blocks/settings.html' " class="settings panel panel-default"> </div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
給我們的首頁創建一個空白模版admin/dashboard.html
<!--admin/dashboard.html-->
- 1
- 1
寫我們新的路由
// admin/router.js 'use strict'; app .run( function ($rootScope, $state, $stateParams) { $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; } ) .config( function ($stateProvider, $urlRouterProvider) { $urlRouterProvider .otherwise('/app/dashboard'); $stateProvider .state('app', { abstract: true, url: '/app', templateUrl: 'admin/app.html', }) .state('app.dashboard', { url: '/dashboard', templateUrl: 'admin/dashboard.html', }) } );
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
修改入口,注釋或刪除掉對原config.router.js、main.js的引用,換成我們的控制接管
<!--index.html--> ... <!--<script src="js/config.router.js"></script>--> <!--<script src="js/main.js"></script>--> <script src="admin/router.js"></script> <script src="admin/main.js"></script> ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
到此我們就得到了一套可自由擴展的前端框架
3) 接下來我們基於BasicAuth加入系統的用戶驗證功能。
這里我們采用按功能模塊來建立子目錄,區別於原模版框架(原框架是按文件類型區分子目錄,例如腳本放在js/里面,模版放在tpl里面)。
首先啟動Restful服務器,然后我們為服務器配置一個全局變量,代碼里面的host需要修改成服務器真實地址
// admin/main.js
... $scope.app = { host: "http://172.17.9.92:8000", name: 'Angulr', ...
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
創建認證功能模塊目錄auth
> mkdir admin\auth\
- 1
- 1
編寫controller(控制器)
// admin/auth/ctrl.js app.controller('LoadingController',function($scope,$resource,$state){ var $com = $resource($scope.app.host + "/auth/info/?"); $com.get(function(){ $state.go('app.dashboard'); },function(){ $state.go('auth.login'); }) }); app.controller('LoginController',function($scope,$state,$http,$resource,Base64){ $scope.login = function(){ $scope.authError = "" var authdata = Base64.encode($scope.user.username + ':' + $scope.user.password); $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; var $com = $resource($scope.app.host + "/auth/info/?"); $com.get(function(){ $state.go('app.dashboard'); },function(){ $scope.authError = "服務器登錄錯誤" }) } }); app.factory('Base64',function(){ var keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; return { encode: function (input) { var output = ""; var chr1, chr2, chr3 = ""; var enc1, enc2, enc3, enc4 = ""; var i = 0; do { chr1 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++); enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); chr1 = chr2 = chr3 = ""; enc1 = enc2 = enc3 = enc4 = ""; } while (i < input.length); return output; }, decode: function (input) { var output = ""; var chr1, chr2, chr3 = ""; var enc1, enc2, enc3, enc4 = ""; var i = 0; // remove all characters that are not A-Z, a-z, 0-9, +, /, or = var base64test = /[^A-Za-z0-9\+\/\=]/g; if (base64test.exec(input)) { window.alert("There were invalid base64 characters in the input text.\n" + "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" + "Expect errors in decoding."); } input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); do { enc1 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++)); enc4 = keyStr.indexOf(input.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; output = output + String.fromCharCode(chr1); if (enc3 != 64) { output = output + String.fromCharCode(chr2); } if (enc4 != 64) { output = output + String.fromCharCode(chr3); } chr1 = chr2 = chr3 = ""; enc1 = enc2 = enc3 = enc4 = ""; } while (i < input.length); return output; } }; })
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 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
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 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
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
編寫template(模版)
<!--admin/auth/loading.html--> <div class="form-group" ng-controller="LoadingController"> <div class="col-md-12 text-center"> <span class="glyphicon glyphicon-refresh glyphicon-refresh-animate"></span> loading... </div> </div>
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
<!--admin/auth/login.html--> <div class="container w-xxl w-auto-xs" ng-controller="LoginController"> <a href class="navbar-brand block m-t">{{app.name}}</a> <div class="m-b-lg"> <div class="wrapper text-center"> <strong>Sign in to get in touch</strong> </div> <form name="form" class="form-validation"> <div class="list-group list-group-sm"> <div class="list-group-item"> <input type="text" placeholder="username" class="form-control no-border" ng-model="user.username" required> </div> <div class="list-group-item"> <input type="password" placeholder="password" class="form-control no-border" ng-model="user.password" required> </div> </div> <button type="submit" class="btn btn-lg btn-primary btn-block" ng-click="login()" ng-disabled='form.$invalid'>Log in</button> <div class="line line-dashed"></div> <div class="text-danger wrapper text-center" ng-show="authError"> {{authError}} </div> </form> </div> </div>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
改寫路由
// admin/router.js
... $urlRouterProvider .otherwise('/auth/loading'); $stateProvider .state('auth',{ abstract: true, url:'/auth', template: '<div ui-view class="fade-in"></div>', resolve: { deps: ['$ocLazyLoad', function( $ocLazyLoad ){ return $ocLazyLoad.load('admin/auth/ctrl.js'); }] } }) .state('auth.loading',{ url:'/loading', templateUrl:'admin/auth/loading.html', }) .state('auth.login',{ url:'/login', templateUrl:'admin/auth/login.html', }) ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
代碼挺多,就不逐行解釋了,最核心的就是:
用Base64加密[用戶名:密碼],在請求頭加入 Authorization: Basic [加密串]
var authdata = Base64.encode(username + ":" + password); $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata;
- 1
- 1
改完以后重新訪問,將實現流程圖中的home->loading->login->dashboard。
事情還沒完,我們再重新訪問,又會重復這個流程,並不會自動登錄,這是因為BasicAuth的特性是在每一次web請求的時候都需要加入Authorization請求頭才行。所以我們還要做點工作:1.登錄成功以后將authdata存在本地,2.給全局http請求統一加入這個請求頭
// admin/auth/ctrl.js
... app.controller('LoginController',function($scope,$state,$http,$resource,Base64,$localStorage) ... $com.get(function(){ $localStorage.auth = authdata; $state.go('app.dashboard'); },function(){ $scope.authError = "服務器登錄錯誤" }) ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
// admin/router.js app .run( function ($rootScope, $state, $stateParams,$localStorage,$http) { $http.defaults.headers.common['Authorization'] = 'Basic ' + $localStorage.auth; $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; } ) ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
重新刷新首頁,頁面將實現自動登錄了,但是事情還沒完,進入系統以后,雖然每次Web請求我們都加入了BasicAuth的請求頭,但是如果服務器端做了帳號修改,一樣會產生401的錯誤,產生的結果就是客戶端點什么操作都不會有反應,我們應該在全局來攔截401,引導客戶端跳轉到重新登錄的界面:
// admin/router.js ... app.config(function ($httpProvider) { $httpProvider.interceptors.push('AuthInterceptor'); }) app.factory('AuthInterceptor', function ($rootScope, $q,$location) { return { responseError: function (response) { if(response.status==401) { $location.url('/auth/login'); } return $q.reject(response); } }; })
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
大功即將告成,還有最后一步,有了登錄必然有登出,BasicAuth協議本身是沒有登出概念的,我們這里做的登出,就是刪除本地那個保存的authdata。
// admin/main.js
angular.module('app') .controller('AppCtrl', ['$scope', '$translate', '$localStorage', '$window', '$state','$http', function( $scope, $translate, $localStorage, $window ,$state,$http) { ... $scope.logout = function(){ $localStorage.auth = null; $http.defaults.headers.common['Authorization'] = "Basic"; $state.go("auth.login"); } function isSmartDevice( $window ){...}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
<!--admin/blocks/header.html--> ... <!-- dropdown --> <ul class="dropdown-menu animated fadeInRight w"> <li> <a ng-click="logout()">Logout</a> </li> </ul> <!-- / dropdown --> ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
錦上添花,標准的后台系統一般會在頁面右上角顯示登錄用戶的帳號信息,我們定義的協議/auth/info/是會把這些信息帶下來的,我們來補全一下這個功能:
// admin/auth/ctrl.js app.controller('LoadingController',function($scope,$resource,$state,$localStorage){ var $com = $resource($scope.app.host + "/auth/info/?"); $com.get(function(data){//引入data $scope.session_user = $localStorage.user = data; //保存用戶信息 $state.go('app.dashboard'); }) }); app.controller('LoginController',function($scope,$state,$http,$resource,Base64,$localStorage){ $scope.login = function(){ $scope.authError = "" var authdata = Base64.encode($scope.user.username + ':' + $scope.user.password); $http.defaults.headers.common['Authorization'] = 'Basic ' + authdata; var $com = $resource($scope.app.host + "/auth/info/?"); $com.get(function(data){//引入data $scope.session_user = $localStorage.user = data; //保存用戶信息 $localStorage.auth = authdata; $state.go('app.dashboard'); },function(){ $scope.authError = "服務器登錄錯誤" }) } }); ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
// admin/main.js
... $scope.session_user = $localStorage.user; $scope.logout = function(){...}
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
<!--admin/blocks/header.html-->
... <span class="hidden-sm hidden-md">{{session_user.username}}</span> <b class="caret"></b> ...
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
4) CRUD
創建news目錄
> mkdir admin\news\
- 1
- 1
增加news導航
<!-- admin/blocks/nav.html --> <!-- list --> <ul class="nav"> <li class="hidden-folded padder m-t m-b-sm text-muted text-xs"> <span translate="導航">導航</span> </li> <li ui-sref-active="active"> <a ui-sref="app.news.list"> <i class="glyphicon glyphicon-book icon text-info-dker"></i> <span class="font-bold">新聞管理</span> </a> </li> </ul> <!-- / list -->
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
書寫控制器
// admin/news/ctrl.js 'use strict'; app.controller('ListController', function($scope, $resource,$stateParams,$modal,$state) { //查詢 $scope.query = function(page,filter){ var $com = $resource($scope.app.host + "/news/?page=:page&search=:filter",{page:'@page',filter:'@filter'}); if(!page){ page=1; }else{ page=parseInt(page); } $com.get({page:page,filter:filter},function(data){ //擴展分頁數據,顯示頁簽,最終效果為 < 1 2 3 4 5 > data.page_index = page; data.pages = []; //頁簽表 var N = 5; //每次顯示5個頁簽 var s = Math.floor(page/N)*N; if(s==page)s-=N; s += 1; var e = Math.min(data.page_count,s+N-1) for(var i=s;i<=e;i++) data.pages.push(i) $scope.data = data; $scope.search_context = filter; }); } //搜索跳轉 $scope.search = function(){ $state.go('app.news.list',{search:$scope.search_context}); } //全選 var selected = false; $scope.selectAll = function(){ selected = !selected; angular.forEach($scope.data.results,function(item){ item.selected = selected; }); } //自定義操作處理,其中1為刪除所選記錄 $scope.exec = function(){ if($scope.operate=="1"){ var ids = []; angular.forEach($scope.data.results,function(item){ if(item.selected){ ids.push(item.id); } }); if(ids.length>0){ //彈出刪除確認 var modalInstance = $modal.open({ templateUrl: 'admin/confirm.html', controller: 'ConfirmController', size:'sm', }); modalInstance.result.then(function () { var $com = $resource($scope.app.host + "/news/deletes/?"); $com.delete({'ids':ids.join(',')},function(){ $state.go('app.news.list'); }); }); } } } //根據url參數(分頁、搜索關鍵字)查詢數據 $scope.query($stateParams.page,$stateParams.search); }); app.controller('ConfirmController', ['$scope', '$modalInstance', function($scope, $modalInstance){ $scope.ok = function () { $modalInstance.close(); }; $scope.cancel = function () { $modalInstance.dismiss('cancel'); }; }]); app.controller('DetailController', function($rootScope,$scope, $resource, $stateParams,$state) { $scope.edit_mode = !!$stateParams.id; if($scope.edit_mode){ var $com = $resource($scope.app.host + "/news/:id/?",{id:'@id'}); var resp = $com.get({id:$stateParams.id},function(data){ $scope.data = resp; }); } else{ $scope.data = {}; } $scope.submit = function(){ if($scope.edit_mode){ var $com = $resource($scope.app.host + "/news/:id/?",{id:'@id'},{ 'update': { method:'PUT' }, }); $com.update({id:$stateParams.id},$scope.data,function(data){ $state.go($rootScope.previousState,$rootScope.previousStateParams); }); } else{ var $com = $resource($scope.app.host + "/news/?"); $com.save($scope.data,function(data){ $state.go('app.news.list'); }); } }; $scope.delete = function(){ var $com = $resource($scope.app.host + "/news/:id/?",{id:'@id'}); $com.delete({id:$stateParams.id},function(){ $state.go('app.news.list'); }) } });
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 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
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 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
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
書寫列表模版
<!-- admin/news/list.html --> <div class="wrapper-md" ng-controller="ListController"> <div class="panel panel-default"> <div class="panel-heading"> <ul class="nav nav-pills pull-right"> <li style=" padding-top:4px; padding-right:4px"><button class="btn m-b-xs btn-sm btn-primary btn-addon" ui-sref="app.news.create()"><i class="fa fa-plus"></i>新增</button></li> </ul> 新聞列表 </div> <div class="row wrapper"> <div class="col-sm-5 m-b-xs"> <select class="input-sm form-control w-sm inline v-middle" ng-model="operate" ng-init="operate=0"> <option value="0">---</option> <option value="1">刪除所選記錄</option> </select> <button class="btn btn-sm btn-default" ng-click="exec()">執行</button> </div> <div class="col-sm-4"> </div> <div class="col-sm-3"> <div class="input-group"> <input type="text" class="input-sm form-control" placeholder="Search" ng-model="search_context"> <span class="input-group-btn"> <button class="btn btn-sm btn-default" ng-click="search()" type="button">Go!</button> </span> </div> </div> </div> <div class="table-responsive" ng-if="data.total_count>0"> <table class="table table-striped b-t b-light"> <thead> <tr> <th style="width:20px;"> <label class="i-checks m-b-none"> <input type="checkbox" ng-click="selectAll()"><i></i> </label> </th> <th>標題</th> <th>創建時間</th> <th style="width:30px;"></th> </tr> </thead> <tbody> <tr ng-repeat="data in data.results"> <td><label class="i-checks m-b-none"><input type="checkbox" ng-model="data.selected"><i></i></label></td> <td>{{data.title}}</td> <td>{{data.create_time|date:'yyyy-MM-dd HH:mm:ss Z'}}</td> <td> <a ui-sref="app.news.detail({id:data.id})" class="active"><i class="fa fa-edit"></i>