angularjs+bootstrap後臺管理樣例
angularjs+bootstrap可以做出很漂亮的管理系統出來,https://wrapbootstrap.com/可以付費購買,下文會提供一個免費的,要講解如何從0到1把ng前端結構搭出來是很漫長的教程,本文僅僅介紹一下這個免費後臺模版的結構,然後重點講解如何改寫這個結構。
開始閱讀之前,假設讀者已經ng入門並且對於ui.router,bootstrap有一定了解。
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
編寫頁面框架模版,我們也可以直接從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>
<!--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 -->
<!--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 -->
<!--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>
給我們的首頁建立一個空白模版admin/dashboard.html
<!--admin/dashboard.html-->
寫我們新的路由
// 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',
})
}
);
修改入口,註釋或刪除掉對原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>
...
到此我們就得到了一套可自由擴充套件的前端框架
3) 接下來我們基於BasicAuth加入系統的使用者驗證功能。
這裡我們採用按功能模組來建立子目錄,區別於原模版框架(原框架是按檔案型別區分子目錄,例如指令碼放在js/裡面,模版放在tpl裡面)。
首先啟動Restful伺服器,然後我們為伺服器配置一個全域性變數,程式碼裡面的host需要修改成伺服器真實地址
// admin/main.js
...
$scope.app = {
host: "http://172.17.9.92:8000",
name: 'Angulr',
...
建立認證功能模組目錄auth
> mkdir admin\auth\
編寫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.fromCha