很早以前就大概看过一点angualrjs,但是没有项目,一直没有进行下去,就是干巴巴的看着,过了一段时间发现什么也不记得了。

来yulebaby我的第一个后台管理是用easyui做的,做完那个以后发现有很多局限,因为easyui里面都是内嵌了iframe,当时在iframe中操作js的时候我真的是头疼想死呀。然后我就想着还是用angualr来弄吧,这也是现在前后台分离的方向,然后就有了接下来那些有趣的事情。

Angularjs虽然很强大,但是你要是掌握了其中这几大块其实也是那么回事,双向数据绑定,作用域,指令,控制器,服务,路由,过滤器,我这次项目中也就用到了这几块的内容,不过接触的也不复杂,都是些基本的。

首先我大致说一下我们这个后台管理的原型和需求。

我们的后台管理分3种角色,不过目前我们只做了2种,设备助理和财务,设备助理主要是用来添加设备,生成设备销售单的,还有就是设备销售单管理和设备销售单退单管理;财务主要用来管理设备库的,财务也有设备销售单管理和设备销售单退单管理的权限,只是有些是可看不可操作的,具体的不同的角色有不同的权限这个就不细说了......

而且我们在做权限控制这块还用到了监听路由改变,然后将没有权限的url进行拦截,这个主要是因为,我们的后台是java,他们用了一个古老的框架,由于后台框架的限制,我们的angualr项目不能放到他们的webinfor下面,单独拿出来以后,权限什么的就不受他们控制了,所以当时我们在没有办法的情况下就用了一个比较笨的方法来控制权限了,具体如下:

app.run(function ($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams, options){
function getCookie(name){
var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
if(arr=document.cookie.match(reg)){
return (arr[2]);
}
else{
return null;
}
}
var roleId = getCookie('roleId');
var caiwu = ['error', 'router', 'index', 'equipSaleManageAllCw','equipSaleManageAllCwdefult','equipSaleManageDetailCw','equipReturnAllCw','equipReturnDetailCw','equipListCw','equipPackageCw','equipClassCw','equipDetailsCw','addEquipmentCw','equipPackageDetailsCw','equipClassDetailsCw','equipNewClassCw'];
var sbzli = ['error', 'router', 'index', 'equipAdd','equipSaleManageAll','equipSaleManageAlldefult','equipSaleManageDetail','equipSaleManagethDetail','equipReturnAll','equipReturnDetail'];
if(roleId == 23){
if(caiwu.indexOf(toState.name) < 0){
event.preventDefault();
$state.go('error');
}
}
if(roleId == 27){
if(sbzli.indexOf(toState.name) < 0){
event.preventDefault();
$state.go('error');
}
}
})
})

 然后这个项目中有个比较麻烦的就是分页和图片上传了,首先说一下分页,我们的分页是自己分装了一个指令,

<div class="bby-page-box" ng-show="page.count > 1">
<a href="javascript: void(0);" ng-show="page.pageNo!==1" ng-click="queryData(page.pageNo - 1)">上一页</a><!--
--><a href="javascript: void(0);" ng-show="page.pageNo - 4 > 0 && page.count > 7" ng-click="queryData(1)">1</a><!--
--><a href="javascript: void(0);" ng-show="page.pageNo - 4 > 0 && page.count > 7" class="bby-page-ellipsis">…</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo - 6)" ng-show="page.pageNo - 6 > 0 && page.count <= 7">{{page.pageNo - 6}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo - 5)" ng-show="page.pageNo - 5 > 0 && page.count <= 7">{{page.pageNo - 5}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo - 4)" ng-show="page.pageNo - 4 > 0 && page.count <= 7">{{page.pageNo - 4}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo - 3)" ng-show="page.pageNo - 3 > 0">{{page.pageNo - 3}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo - 2)" ng-show="page.pageNo - 2 > 0">{{page.pageNo - 2}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo - 1)" ng-show="page.pageNo - 1 > 0">{{page.pageNo - 1}}</a><!--
--><a href="javascript: void(0);" class="active">{{page.pageNo}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo + 1)" ng-show="page.pageNo + 1 <= page.count">{{page.pageNo + 1}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo + 2)" ng-show="page.pageNo + 2 <= page.count">{{page.pageNo + 2}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo + 3)" ng-show="page.pageNo + 3 <= page.count">{{page.pageNo + 3}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo + 4)" ng-show="page.pageNo + 4 <= page.count && page.pageNo + 4 < 8">{{page.pageNo + 4}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo + 5)" ng-show="page.pageNo + 5 <= page.count && page.pageNo + 5 < 8">{{page.pageNo + 5}}</a><!--
--><a href="javascript: void(0);" ng-click="queryData(page.pageNo + 6)" ng-show="page.pageNo + 6 <= page.count && page.pageNo + 6 < 8">{{page.pageNo + 6}}</a><!--
--><a href="javascript: void(0);" ng-show="page.count >= page.pageNo + 4 && page.count > 7" class="bby-page-ellipsis">…</a><!--
--><a href="javascript: void(0);" ng-show="page.count >= page.pageNo + 4 && page.count > 7" ng-click="queryData(page.count)">{{page.count}}</a><!--
--><a href="javascript: void(0);" ng-show="page.pageNo !== page.count" ng-click="queryData(page.pageNo + 1)">下一页</a><!--
--><span>
到第<!--
--><input type="text" ng-model="gonum" placeholder="1" ng-change="ongonum()"><!--
-->页<!--
--><a href="javascript: void(0);" ng-click="queryData(gonum)">确定</a>
</span><!-- --><select ng-model="pageNumber" ng-options="pageNumber.text for pageNumber in pageNumList" ng-init="pageNumber = pageNumList[0]">
</select>
<span>共{{page.count}}页{{page.pageCount}}条</span>
</div>
app.directive('pagination', function(){
return {
controller: function($scope, $element, $attrs, $transclude, $http) {
/* 每页显示条数 */
$scope.pageNumList = [{value: 10, text: 10},{value: 20, text: 20},{value: 30, text: 30},{value: 50, text: 50},{value: 100, text: 100}];
/* 监听每页显示条数 */
$scope.$watch('pageNumber', function (n, o) {
if(n.value !== o.value){$scope.queryData(1);}
})
$scope.queryData = function (pegeNo, query) {
$scope.gonum = '';//点击确认调转页数以后清空输入框
$scope.queryCriteria = query !== undefined ? query : $scope.queryCriteria;
$scope.pageNo = pegeNo !== undefined ? pegeNo : 1;
try{
$scope.param = $scope.pageNumber.value ? $scope.pageNumber.value : 10;
}catch (e) {
$scope.param = 10;
}
$scope.pageNo = pegeNo ? pegeNo : 1;
var params = {
pageNo: $scope.pageNo,
pageSize: $scope.param
};
if($scope.queryCriteria){
for(var v in $scope.queryCriteria){
params[v] = $scope.queryCriteria[v];
}
}
$scope.$emit('loading', {});
$scope.loading = true;
$http({
url: $scope.URL,
method: 'get',
params: params
}).then(function (res) {
$scope.page = res.data;
$scope.page.count = Math.ceil(res.data.pageCount/res.data.pageSize);
$scope.$emit('items', res.data);
},function (e) {
$scope.loading = false;
$scope.$emit('items', {code: 1, message: "网络异常,请刷新页面"});
})
}
$scope.queryData(1,$scope.defult);
$scope.$on('query', function (e, d) {
$scope.queryData(1, d);
})
$scope.$emit('onload', {});
},
restrict: 'EA',
templateUrl: 'script/directives/directiveView/pagination.html',
replace: true,
link: function (scope, ele, attrs){
scope.ongonum = function () {
if(!scope.gonum){return;}
var vue = parseInt(scope.gonum.replace(/[^\d]/g,''));
if(!vue){scope.gonum = '1';return;}
if(vue > scope.page.count){
scope.gonum = scope.page.count;
}else if(vue < 1){
scope.gonum = 1;
}else{
scope.gonum = vue;
}
}
}
};
});

分页指令封装好了,然后在html页面调用就直接写上<pagination></pagination>这个就好了,指令调用的方式有4种,EACM,元素,属性,类名,注释。

然后在控制器中使用直接接收指令传输过来的数据:

$scope.$on('items', function (e, data) {
$scope.loading = false;
if(data.code == 1000){
if(data.data){
$scope.items = data.data;
}else{
$scope.items = [];
}
}else{
$scope.items = [];
$scope.promptBlen = true;
$scope.promptText = data.message;
}
$scope.init=function(){
angular.forEach($scope.items, function(data){
if(data.status == 7){
data.returnRule=true; //把returnRule绑定到每个对象显示退货按钮
}else{
data.returnRule=false;
}
});
}
$scope.init();
$scope.flag=true;
});

这里要直接注意下,指令与控制器之间的通信方式,还有控制器用控制器直接的通信方式,反正我就是记住一点,通信用$on来接收数据,如果是父控制器向子控制器传播数据就是广播,$broadcast,如果是子控制器向父控制器传送数据就是$emit,向上传递数据。这个很重要,如果记起来比较困难的,再去百度下就好了。

分页的成品如下:

然后还有就是图片上传:

我们的图片上传采用的是可以单张上传,也可以多张上传的,但是不能超过6张,最开始准备在网上找个angualr图片上传的插件,但是后来还是用jquery来写了,js具体如下:

app.factory('$preview', function () {
// getUrlFn(window.location.href)
var getUrlFn = function(str){
var oaPosition = str.indexOf('oa');
return str.substring(0,oaPosition+2);
}
return {
upfile: function (id, status, see){
window.delParent = '';
var imgContainer = $("#photoItemsBox"); //存放图片的父亲元素
var data = {};
var numUp;
if(status == 0){
data.equOrderNo = id
}else{
data.orderReturnNo = id;
}
if(see){
$('.z_file').hide();
}
$.ajax({
url: getUrlFn(window.location.href) + '/equipment/equImgUpload/queryImgs.do',
type: 'get',
data: data,
dataType: 'json',
success: function (data) {
if(data.code == 1000){
if(data.data!=undefined && data.data!=null && data.data.length>0){
for(var i = 0; i < data.data.length; i++){
(function (){
var box = $('<div class="up-section"></div>');
var closeBg = $('<a href="javascript: void(0);" class="close-upimg">×</a>'); var imgThis = $('<img class="up-img" src="'+ data.data[i].imgUrl +'" />');
box.append(imgThis);
var input = $('<input id="imgIds" name="imgIds" value="'+ data.data[i].id +'" type="hidden"/>'); if(!see){
box.append(closeBg);
box.append(input);
}
imgContainer.append(box);
})()
}
}
numUp = $('.up-section').length;
if(numUp < 6 && !see){
$(".z_file").show();
}else{
$(".z_file").hide();
}
}
}
}) var defaults = {
fileType : ["jpg","png","gif","jpeg"], // 上传文件的类型
fileSize : 1024 * 1024 * 5
};
/*点击图片的文本框*/
$("#file").change(function(){
var idFile = $(this).attr("id");
var file = document.getElementById(idFile);
var fileList = file.files; //获取的图片文件
var imgArr = [];
//遍历得到的图片文件
var numUp = imgContainer.find(".up-section").length;
var totalNum = numUp + fileList.length;
if(fileList.length > 6 || totalNum > 6 ){
alert("图片超出6张,请删除多余图片后再上传");
}else if(numUp < 6){
fileList = validateUp(fileList);
var formData = new FormData();
for(v in data){
formData.append(v, data[v]);
}
for(var i = 0; i < fileList.length; i++){
var imgUrl = window.URL.createObjectURL(fileList[i]);
imgArr.push(imgUrl); var OrderImg = 'OrderImg'+(i+1);
var OrderImgName = 'OrderImgName'+(i+1); formData.append(OrderImg, fileList[i]);
formData.append(OrderImgName, fileList[i].name); (function (){
var box = $('<div class="up-section"></div>');
var loading = $('<div class="line-scale"><div></div><div></div><div></div><div></div><div></div></div>');
box.append(loading);
var closeBg = $('<a href="javascript: void(0);" class="close-upimg">×</a>');
box.append(closeBg);
var imgThis = $('<img class="up-img" src="'+ imgArr[i] +'" />');
box.append(imgThis);
var input = $('<input id="imgIds" name="imgIds" type="hidden"/>');
box.append(input);
imgContainer.append(box);
})()
}
$.ajax({
url: getUrlFn(window.location.href) + "/equipment/equImgUpload/addImgs.do",
type: 'POST',
cache: false,
data: formData,
processData: false,
contentType: false,
success: function(data) {
if(data.code == 1000){
$('.line-scale').hide();
for(var i = 0; i < data.data.length; i++){
imgContainer.children('div').eq(i).find('.up-img').attr('src', data.data[i].imgUrl);
imgContainer.children('div').eq(i).find('input').val(data.data[i].id);
}
}
console.log("成功");
},
error: function(e) {
console.log('失败')
}
});
}
numUp = imgContainer.find(".up-section").length;
if(numUp >= 6){
$(this).parent().hide();
} //input内容清空
$(this).val("");
}); $("body").on("click",'.close-upimg',function(){
event.preventDefault();
event.stopPropagation();
$(".works-mask").show();
window.delParent = $(this).parent();
deleteId = $(this).siblings('input').val();
}); $(".wsdel-ok").click(function(){
$(".works-mask").hide();
var dataD = data;
dataD.imgIds1 = deleteId
$.ajax({
url: getUrlFn(window.location.href) + '/equipment/equImgUpload/delete.do',
type: 'get',
data: dataD,
dataType: 'json',
success: function (data) {
if(data.code == 1000){
var numUp = window.delParent.siblings().length;
if(numUp < 7){
$(".z_file").show();
}
window.delParent.remove();
}else{
alert(data.message);
}
},
error: function (e) {
console.log('请求失败');
}
}) }); $(".wsdel-no").click(function(){
$(".works-mask").hide();
}); function validateUp(files){
var arrFiles = [];//替换的文件数组
for(var i = 0, file; file = files[i]; i++){
//获取文件上传的后缀名
var newStr = file.name.split("").reverse().join("");
if(newStr.split(".")[0] != null){
var type = newStr.split(".")[0].split("").reverse().join("");
if(jQuery.inArray(type, defaults.fileType) > -1){
// 类型符合,可以上传
if (file.size >= defaults.fileSize) {
alert('您这个"'+ file.name + '-----' + file.size +'"文件大小过大');
} else {
// 在这里需要判断当前所有文件中
arrFiles.push(file);
}
}else{
alert('您这个"'+ file.name +'"上传类型不符合');
}
}else{
alert('您这个"'+ file.name +'"没有类型, 无法识别');
}
}
return arrFiles;
}
}
}
})

我们是封装了一个服务,然后在页面引入html

<!--上传图片 -->
<div class="bby-form-item" ng-show="statu!=1" class="upPhoto">
<label for="" class="bby-form-label">交款凭证图:</label>
<div class="bby-input-block">
<div class="z_photo" id="photoItemsBox"></div>
<div class="z_file">
<label for="file" class="add-img">点击上传图片</label>
<input type="file" name="file" id="file" accept="image/jpg,image/jpeg,image/png,image/gif" multiple />
</div>
<div class="mask works-mask">
<div class="mask-content">
<p class="del-p">确定要删除该图片吗?</p>
<p class="check-p"><span class="del-com wsdel-ok">确定</span><span class="wsdel-no">取消</span></p>
</div>
</div>
</div>
</div>

  然后在控制器依赖注入这个服务,直接调用就好了

上传图片成品如下:(包括显示图片,上传图片,点击查看大图,删除图片)

这里,我们的图片服务器出来点问题,所以图片失效了,线上的是没有问题的。

反正做这个项目的难点和思路大概也就这么些,第一次用angualr,还有很多东西做的很粗糙,今天写的博客也稀里糊涂的,思路不太清晰,就是随便写写,记录下自己的成长,未来的路还很长,慢慢来.......

第一次用angularJS做后台管理点滴的更多相关文章

  1. MVC + LigerUI 做后台管理还真是清爽

    LigerUI是基于Jquery,轻量级UI框架.具体可以看官方演示 http://www.ligerui.com/ 我的简单后台 模拟Winodw桌面效果,挺不错呢.最喜欢的还是他的,下拉列表绑定G ...

  2. 换个思维,boot结合vue做后台管理

    可以添加,可以删除.动态的添加数据. 不用操作dom,只要操作json数据即可. <form class="form-horizontal addForm" id=" ...

  3. 使用layui 做后台管理界面,在Tab中的链接点击后添加一个新TAB的解决方法

    给链接或按钮  添加 onclick="self.parent.addTab('百度','http://www.baidu.com','icon-add')" 如: <a h ...

  4. MVC5 网站开发实践 2、后台管理

    目录 MVC5 网站开发实践 概述 MVC5 网站开发实践 1.建立项目   从这一部分开始做后台管理,首先是基本框架的 一.Data项目 1.项目添加EntityFramework引用 在Data项 ...

  5. python3.6环境中django2.0与xadmin0.6结合的后台管理

    1.xadmin简介 django的admin管理后台页面很简洁,对个人来说做后台管理非常简单:xadmin的比较admin优化界面,看着也舒服. xadmin界面效果如下: 2.xadmin安装 从 ...

  6. docloud后台管理项目(开篇)

    最近朋友做app需要web做后台管理,所以花了一周时间做了这个项目. 废话不多说,开发环境是nginx+php5.3,使用thinkphp框架.是一个医疗器械数据统计的后台,业务功能很简单就是查看用户 ...

  7. 后台管理UI的选择

    最近要做一个企业的OA系统,以前一直使用EasyUI,一切都好,但感觉有点土了,想换成现在流行的Bootstrap为基础的后台UI风格,想满足的条件应该达到如下几个: 1.美观.大方.简洁 2.兼容I ...

  8. 后台管理UI皮肤的选择

    后台管理UI的选择 目录 一.EasyUI 二.DWZ JUI 三.HUI 四.BUI 五.Ace Admin 六.Metronic 七.H+ UI 八.Admin LTE 九.INSPINIA 十. ...

  9. 后台管理UI推荐

    目录 一.EasyUI 二.DWZ JUI 三.HUI 四.BUI 五.Ace Admin 六.Metronic 七.H+ UI 八.其它UI 九.总结 最近要做一个企业的OA系统,以前一直使用Eas ...

随机推荐

  1. Bootstrap FileInput

    fileuploaded 事件 fileuploaded 事件是异步方法,如果在模态框中使用没上传完就释放模态框的内容会无法触发. $fileinput.on("fileuploaded&q ...

  2. ubuntu 配置pptp

    PPTP是点对点隧道协议,用于在公网上建立两个节点之间的专用用网络.普通的用户一般是通过拨号的方式,接入ISP提供的网络,由于国内的上网环境,是访问不了google的,所以必须首先要有一台可以上goo ...

  3. java.io.IOException: Malformed \uxxxx encoding.

    java.io.IOException: Malformed \uxxxx encoding.  at com.dong.frame.util.ReadProperties.read(ReadProp ...

  4. 16/7/11_PHP-图形图像操作

    GD库简介 GD指的是Graphic Device,PHP的GD库是用来处理图形的扩展库,通过GD库提供的一系列API,可以对图像进行处理或者直接生成新的图片. PHP除了能进行文本处理以外,通过GD ...

  5. Python几行代码实现邮件发送

    话不多说直接进入正题 首先我们需要安装一个名为'zmail'的包,终端执行'pip install zmail'即可实现安装. 直接上代码 import zmail mail = { 'subject ...

  6. 基于vux的Vue路由切换动画

    const history = window.sessionStorage history.clear() let historyCount = history.getItem('count') * ...

  7. Markdown列表中嵌套代码带来的问题

    目录 1.问题描述 2.原因查找 3.问题解决 使用Markdown时,在有序列表中嵌套代码块引发了有序列表编号中断(重新从1开始)的问题,最终已解决. 1.问题描述 代码: 1. title tex ...

  8. pgsql删除重复记录

    如下: DELETE FROM categories a WHERE ( a.id, a.name, a.parent_id ) ) ) 关键点:oracle中有内部id为rowid, 在postgr ...

  9. array_map() 函数

    定义和用法 array_map() 函数返回用户自定义函数作用后的数组.回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致. 语法 array_map(function,a ...

  10. Oracle-随笔笔记

    1.重命名数据库表.重命名字段 alter table tablename1 rename to tablename2; alter table tablename1 rename column co ...