[TOC]
## Angularjs
[百度百科](https://baike.baidu.com/item/AngularJS/7140293?fr=aladdin "百度吧")
## inspina
bootstrap比较好的后台管理模板,本身就支持了Angularjs版本,jumpserver就是使用的inspina的jquery版本
## 登录界面
![](https://box.kancloud.cn/b1602d9a6deb432a2aab0c07d567e128_1680x1050.png)
### 登录界面代码
```html
<div class="middle-box text-center loginscreen animated fadeInDown">
<div>
<div>
<h1 class="logo-name">SO</h1>
</div>
<h3>欢迎使用SmartOps</h3>
{{ errorMessage }}
<form class="m-t" ng-submit="login()">
<div class="form-group">
<input type="email" value="mail@shuaibo.wang" class="form-control" ng-model="loginForm.email" placeholder="登录邮箱" required="">
</div>
<div class="form-group">
<input type="password" value="123456" class="form-control" placeholder="密码" ng-model="loginForm.password" required="">
</div>
<button type="submit" class="btn btn-primary block full-width m-b">Login</button>
<a ui-sref="forgot_password"><small>忘记密码?</small></a>
<p class="text-muted text-center"><small>没有账号?</small></p>
<a class="btn btn-sm btn-white btn-block" ui-sref="register">创建账号</a>
</form>
<p class="m-t"> <small>SmartOps © 2018</small> </p>
</div>
</div>
```
### 关于Angularjs的一些解答
ng-submit: 可以理解为交给那个函数去处理
ng-model: 可以理解为函数需要的参数
这里使用了login函数
```js
function LoginCtrl($scope, $location, AuthService) {
$scope.login = function () {
AuthService.login($scope.loginForm.email,
$scope.loginForm.password
).then(function () {
$location.path('/')
}
).catch(function (reason) {
$scope.errorMessage = reason;
})
}
}
```
#### 认证服务
这里面有利用到了一个AuthService,这个可以理解成为一个认证服务,用来检测用户是否登录没有登录就跳转到登录界面让用户去登录,由于采用了JSONRPC这种开发模式,后端就不会控制前端去跳转,所以只能靠前端代码判断是否登录了
```
angular.module('inspinia').factory('AuthService',
['$q', '$timeout', 'jsonrpc',
function ($q, $timeout, jsonrpc) {
// 定义判断用户是否在线和token的变量
var user = null;
var token = null;
var next = 'index.main';
// return available functions for use in controllers
return ({
isLoggedIn: isLoggedIn,
login: login,
logout: logout,
register: register,
getUserStatus: getUserStatus
});
function isLoggedIn() {
if (user) {
return true;
} else {
return false;
}
}
function login(email, password) {
var deferred = $q.defer();
jsonrpc.request('user.verify', {
username: email,
password: password
})
.then(function (result) {
if (result.status == 0) {
// 如果用户登录成功,记录其token,并将其设置成在线
token = result.token;
user = true;
deferred.resolve();
}
else {
user = false
deferred.reject();
}
})
.catch(function (error) {
user = false;
deferred.reject();
})
return deferred.promise;
}
function logout() {
return
}
function register(email, password) {
return
}
// 这里写了一个用户状态的接口,这个接口需要token认证,认证通过了就判断当前用户可以请求资源
function getUserStatus() {
return jsonrpc.request('user.status', {token: token}).then(function (result) {
if (result.status == 0) {
user = true
}
else {
user = false
}
}).catch(function (reason) {
user=false
})
}
}]);
```
### 禁止没登录去访问页面
angularjs访问每个页面会触发事件。这个需要在config.js去配置,比如访问这个页面需不需要认证,认证不通过然后控制其跳转
```js
angular
.module('inspinia')
.config(config)
.run(function ($rootScope, $state, AuthService) {
$rootScope.$state = $state
$rootScope.$on('$stateChangeStart',
function (event, toState, toParams, fromState, fromParams) {
// 获取用户状态
AuthService.getUserStatus().then(function () {
// 判断这个页面是不是需要登录,需要登录就判断当前有没有登录,没有登录就跳转到登录界面
if (toState.access.restricted && !AuthService.isLoggedIn()) {
// 如果是从别的页面跳转过来的记录一下跳转之前的url,登录成功之后还跳转到之前的页面
AuthService.next=toState.name
$state.go('login')
}
})
})
})
```
### angularjs自己的路由
angularjs拥有自己的路由功能通常的url是这样的
```
index.html?#/模块名
```
这个需要在config里面定义
```js
function config($stateProvider, $urlRouterProvider, $ocLazyLoadProvider) {
$urlRouterProvider.otherwise("/index/main");
$ocLazyLoadProvider.config({
// Set to true if you want to see what and when is dynamically loaded
debug: true
});
$stateProvider
.state('index', {
abstract: true,
url: "/index",
templateUrl: "static/views/common/content.html",
})
.state('index.main', {
url: "/main",
templateUrl: "static/views/main.html",
data: {pageTitle: 'Example view'},
access: {restricted: true}
})
.state('index.minor', {
url: "/minor",
templateUrl: "static/views/minor.html",
data: {pageTitle: 'Example view'},
access: {restricted: true} //这个就是判断需不需要登录
})
.state('login', {
url: '/login',
access: {restricted: false}, //登录界面就不要登录
templateUrl: "static/views/login.html",
controller: 'LoginCtrl',
}
)
}
```
### angularjs自己的控制器
Angularjs还有一个概念那就是controller,我js有100个函数,但是这个页面就需要1个,或者两个页面有相同的函数名但是功能不一样,这样做出来的项目很复杂,也容易混淆,协同起来也是有难度,这个控制器可以理解成一个个箱子把东西隔开了。
```js
.state('login', {
url: '/login',
access: {restricted: false}, //登录界面就不要登录
templateUrl: "static/views/login.html",
controller: 'LoginCtrl',
}
)
```
这里就是login使用longinCtrl
loginCtl里面包含了登录界面需要使用的login函数
```
function LoginCtrl($scope, $state, AuthService) {
$scope.login = function () {
AuthService.login($scope.loginForm.email,
$scope.loginForm.password
).then(function () {
$state.go(AuthService.next)
}
).catch(function (reason) {
$scope.errorMessage = reason;
})
}
}
```
### 怎么加载到Angular里面
```
angular
.module('inspinia')
.config(function (jsonrpcConfigProvider) {
jsonrpcConfigProvider.set({
url: '/api',
returnHttpPromise: false
});
})
.controller('MainCtrl', MainCtrl)
.controller('LoginCtrl', ['$scope', '$location', 'AuthService', LoginCtrl])
```
这样一个登录的界面就做好了,别的页面也差不多就这些概念
### Angularjs的插件
上面其实用到了一个插件[angular-jsonrpc-client](https://github.com/joostvunderink/angular-jsonrpc-client "angular-jsonrpc-client")
Angular的插件注册需要在引用js的最上面
index.html
```html
<!-- Main Angular scripts-->
<script src="static/js/angular/angular.min.js"></script>
<script src="static/js/plugins/oclazyload/dist/ocLazyLoad.min.js"></script>
<script src="static/js/ui-router/angular-ui-router.min.js"></script>
<script src="static/js/plugins/angular-jsonrpc-client.js"></script>
<script src="static/js/bootstrap/ui-bootstrap-tpls-1.1.2.min.js"></script>
<!-- Anglar App Script -->
<script src="static/js/app.js"></script>
```
app.js
```
(function () {
angular.module('inspinia', [
'ui.router', // Routing
'oc.lazyLoad', // ocLazyLoad
'ui.bootstrap', // Ui Bootstrap
'angular-jsonrpc-client'
])
})();
```
## 登录身份的有效期
之前实现的有点小瑕疵,就是按F5刷新之后自动跳到登录界面,原因是因为service的token随着页面的刷新就被重置了。这里就需要做一些改动了,就是登录成功之后不仅要把token重新赋值,还写到cookie里面,然后刷新页面token从cookie里取出来,而不是null导致重新登录。需要改动的是services.js
这里需要用到了ngCookies自行app.js里面添加
services.js
```js
angular.module('inspinia').factory('AuthService',
['$q', '$timeout', 'jsonrpc', '$cookies',
function ($q, $timeout, jsonrpc, $cookies) {
....
// 刷新界面从cookie里面读取回来
var token = $cookies.get('token');
.....
function login(email, password) {
// create a new instance of deferred
var deferred = $q.defer();
// send a post request to the server
jsonrpc.request('user.verify', {
username: email,
password: password
})
.then(function (result) {
if (result.status == 0) {
var expireDate = new Date();
expireDate.setDate(expireDate.getDate() + 1);
token = result.token;
// 登录成功后设置token到cookie
$cookies.put("token",token,{'expires': expireDate});
user = true;
deferred.resolve();
}
else {
user = false
deferred.reject();
}
})
.catch(function (error) {
user = false;
deferred.reject();
})
// return promise object
return deferred.promise;
}
........
}]);
```
## 注销功能
注销功能相对是比较简单的,只需要将cookie里的token删除或者设置为空就可以
```js
function logout() {
// create a new instance of deferred
var deferred = $q.defer();
$cookies.remove('token')
// return promise object
return deferred.promise;
}
```