//两个分页,不同时渲染:一个带分页的表格,点击详情,又出现了另一个带分页的表格。进入页面的时候,将两个分页都给渲染出来,但将后者分页【零参数】渲染并隐藏。点击详情后,改变请求参数,向后台请求,根据后台返回结果,将后者分页重新渲染显示。 //与以往版本的不同:没有了init函数;去掉配置项isUseFilterOptions,因为有配置项isShowFilterOptions即可 //onkeydown:按下键盘上的某个键时,鼠标聚焦的网页元素的onkeydown事件将被触发。如果鼠标聚焦在网页元素input上,你按下键盘上数字“1”键,会触发网页元素input的onkeydown事件;你按下键盘上“enter”键,也会触发网页元素input的onkeydown键。 //<input type="text" onkeydown="if(event.keyCode==13)event.keyCode=9" /> //196、angular对象数据的value被更改后,获取的仍然是旧value。原因可能是,对象指针没变化,获取了缓存的旧value。解决办法是监听。 //1、分页组件 /* <div ng-show="dividePageInstance.numberOfAllPages>=1"> <div> <p> <button ng-hide="dividePageInstance.numberOfAllPages<=10" ng-click="dividePageClick('front') " ng-disabled="dividePageInstance.currentPageNumber===1" >上一页</button> <button ng-repeat="num in dividePageArray track by $index" ng-bind="num" ng-click="dividePageClick(num) " ng-class="num===dividePageInstance.currentPageNumber?'classA':'classB'" ng-disabled="num==='...'"> </button> <button ng-hide="dividePageInstance.numberOfAllPages<=10" ng-click="dividePageClick('back') " ng-disabled="dividePageInstance.currentPageNumber===dividePageInstance.numberOfAllPages" >下一页</button> </p> <p> <span>转到</span> <input type="text" ng-model="customString" ng-keydown="dividePageClick('leap',$event)"> <span>页</span> <button ng-click="dividePageClick('leap',{which:13})">Go</button> </p> </div> <div> <p> <span ng-bind="dividePageInstance.frontMoreText"></span> <span ng-bind="dividePageInstance.totalText||'共'"></span> <span ng-bind="dividePageInstance.itemsNumberOfAllPages"></span> <span ng-bind="dividePageInstance.totalUnit||'条'"></span> <span ng-bind="dividePageInstance.backMoreText"></span> </p> </div> </div> */ directive('dividePageLabel', function () {//执行步骤四。========================= return { resulttrict: 'E', templateUrl: 'module/common-directive/dir-pagination.html', scope: { dividePageInstance: '=dividePageInstance', isInit: '=isInit' }, controller: function ($scope, commonRequest) { //页面通过currentScope['dividePageInstance']把配置数据注入到分页; //在分页控制器里执行$scope.dividePageRequest(1),进而执行函数$scope.dividePageCreate,获取分页实例。 //不需要手动监听数据的变化。 $scope.handleParameters = function (pageNumber) { var allDatas = {}; var pageNumber = {}; var itemNumberOfEveryPage = {}; var otherDatas = $scope.dividePageInstance.otherDatas || {}; pageNumber[$scope.dividePageInstance.KeyOfPageNumber] = pageNumber; itemNumberOfEveryPage[$scope.dividePageInstance.KeyOfItemNumberOfEveryPage] = $scope.dividePageInstance.itemNumberOfEveryPage; allDatas = angular.merge({}, pageNumber, itemNumberOfEveryPage, otherDatas); if ($scope.dividePageInstance.isShowFilterOptions) { allDatas = angular.merge({}, allDatas, $scope.dividePageInstance.filterOptions); } return allDatas; }; $scope.dividePageRequest = $scope.dividePageInstance.dividePageRequest = function (pageNumber, isCircle, message) { //1、一定要传参数,最少是1个,即1或者$scope.dividePageInstance.currentPageNumber //2、参数正常有3个:如:1,true,'刷新成功!' //特殊情形:目前数据在第9页,当我加上过滤条件后,后台发现总数据只有7页,这时后台应该返回第7页的相关数据;实际上,点击“过滤”之类的按钮,应该请求第1页数据。 commonRequest .request({ method: $scope.dividePageInstance.method, url: $scope.dividePageInstance.url, data: $scope.handleParameters(pageNumber), dividePageCircle: isCircle ? $scope.dividePageInstance.loading("tableCircle") : false }) .then(function (result) { var extraServerPathStart = $scope.dividePageInstance.extraServerPath; var extraServerPathLast = 'result'; if (extraServerPathStart) { for (var i = 0; i < extraServerPathStart.length; i++) { extraServerPathLast += '["' + extraServerPathStart[i] + '"]'; } } $scope.dividePageInstance.currentPageNumber = result.data.currentPageNumber || eval(extraServerPathLast)[$scope.dividePageInstance.keyOfCurrentPageNumber]; $scope.dividePageInstance.itemsNumberOfEveryPage = result.data.itemsNumberOfEveryPage || eval(extraServerPathLast)[$scope.dividePageInstance.keyOfItemsNumberOfEveryPage] || 10; $scope.dividePageInstance.numberOfAllPages = result.data.numberOfAllPages || eval(extraServerPathLast)[$scope.dividePageInstance.keyOfNumberOfAllPages]; $scope.dividePageInstance.itemsNumberOfAllPages = result.data.itemsNumberOfAllPages || eval(extraServerPathLast)[$scope.dividePageInstance.keyOfItemsNumberOfAllPages]; $scope.dividePageInstance.tableDatasOfCurrentPage = result.data.tableDatasOfCurrentPage || eval(extraServerPathLast)[$scope.dividePageInstance.keyOfTableDatasOfCurrentPage]; if (isCircle) { layer.message(message || '刷新成功!'); } $scope.dividePageInstance.dividePageCallback(result); $scope.dividePageCreate(); }) .catch(function () { angular.isFunction($scope.dividePageInstance.errorCallback) ? $scope.dividePageInstance.errorCallback() : angular.noop(); }); }; $scope.dividePageCreate = function () { var dividePageArray = []; var numberOfAllPages = $scope.dividePageInstance.numberOfAllPages; var currentPageNumber = $scope.dividePageInstance.currentPageNumber; if (numberOfAllPages >= 1 && numberOfAllPages <= 10) { for (var i = 1; i <= numberOfAllPages; i++) { dividePageArray.push(i); } } else if (numberOfAllPages >= 11) { // 当前页的左边 if (currentPageNumber > 6) {//如果当前页前面超过5项,即包含自身超过6项,那么省略显示; dividePageArray.push(1); dividePageArray.push('...'); dividePageArray.push(currentPageNumber - 3); dividePageArray.push(currentPageNumber - 2); dividePageArray.push(currentPageNumber - 1); dividePageArray.push(currentPageNumber);//这是当前页。 } else {//如果当前页前面不超过5项,即包含自身不超过6项,那么全部显示; for (i = 1; i <= numberOfAllPages; i++) { dividePageArray.push(i); } } // 当前页的右边 if (numberOfAllPages - currentPageNumber >= 6) { //如果当前页后面有6项及以上,那么省略显示; dividePageArray.push(currentPageNumber + 1); dividePageArray.push(currentPageNumber + 2); dividePageArray.push(currentPageNumber + 3); dividePageArray.push('...'); dividePageArray.push(numberOfAllPages); } else {//如果当前页后面有5项及以下,那么全部显示; for (var i = currentPageNumber + 1; i <= numberOfAllPages; i++) { dividePageArray.push(i); } } } $scope.dividePageArray = dividePageArray; }; $scope.dividePageClick = function (stringOfNumber, event) { var numberOfAllPages = $scope.dividePageInstance.numberOfAllPages; var currentPageNumber = $scope.dividePageInstance.currentPageNumber; if (stringOfNumber === 'front' && currentPageNumber != 1) { currentPageNumber--; } else if (stringOfNumber === 'back' && currentPageNumber != numberOfAllPages) { currentPageNumber++; } else if (stringOfNumber === 'leap') { if (event.which != 13) return;//(1)聚焦输入框时,按“Enter”键,不拦截;(2)点击“GO”时,不拦截 var customNumber = Math.ceil(parseFloat($scope.customString)); if (customNumber < 1 || customNumber > numberOfAllPages) { currentPageNumber = numberOfAllPages;//不给提示 } else { currentPageNumber = customNumber; } } else { currentPageNumber = Math.ceil(parseFloat(stringOfNumber)); } $scope.dividePageCreate() $scope.dividePageRequest(currentPageNumber); }; if (!$scope.isInit) { $scope.dividePageRequest(1); } }, link: function () { } }; }) //2、页面 //<dir-pagination dividePageInstance='dividePageInstance' isInit='false'></dir-pagination>//执行步骤三。========================= //3、勾选和分页服务 factory('checkListAndDividePage', function () { function checkListFn(idKey) { return { idKey: idKey ? idKey : 'id',//每条数据的唯一标志 isSelectThisPage: false,//当前页所有项是否全选 addAllId: [],//所有被选中数据的ID构成的数组 removeAllId: [],//所有没被选中数据的ID构成的数组 numOfAllSelected: 0,//所有页被选中数据的条数 textAfterClick: '所有页所有项全选-未启用,没有-已勾选项!',//复选框被点击后的提示文字 allChecked: { noUse: { isTrue: true,//用这个值作为是否“启用”所有页所有项全选的依据,进而决定如何向后台传参。 text: '所有页所有项全选-未启用,' }, partUse: { isTrue: false, text: '所有页所有项全选-已启用,还有-未勾选项。' }, allUse: { isTrue: false,//用这个值告知“页面”是否“勾选”所有页所有项全选,文字说明直接用变量textAfterClick text: '所有页所有项全选-已启用,没有-未勾选项。' }, }, changeAllChecked: function (use, isTrueNoUse, isTruePartUse, isTrueAllUse) { this.allChecked.noUse.isTrue = isTrueNoUse; this.allChecked.partUse.isTrue = isTruePartUse; this.allChecked.allUse.isTrue = isTrueAllUse; this.textAfterClick = this.allChecked[use].text + (this.numOfAllSelected === 0 ? '没有-已勾选项!' : '已选择' + this.numOfAllSelected + '条!'); }, allPagesClick: function (itemArray, numOfAllDatas) {//所有页所有条目全选复选框被点击时执行的函数 this.allChecked.allUse.isTrue = !this.allChecked.allUse.isTrue; angular.forEach(itemArray, function (item) { item.isChecked = this.allChecked.allUse.isTrue; }); this.isSelectThisPage = this.allChecked.allUse.isTrue; if (this.allChecked.allUse.isTrue) { this.removeAllId = []; this.numOfAllSelected = numOfAllDatas; this.changeAllChecked('allUse', false, false, true); } else { this.addAllId = []; that1.numOfAllSelected = 0; this.changeAllChecked('noUse', true, false, false); } }, currentPageClick: function (itemsArray, numOfAllDatas) {//当前页所有条目全选复选框被点击时执行的函数 var that = this; this.isSelectThisPage = !this.isSelectThisPage angular.forEach(itemsArray, function (item) { item.isChecked = that.isSelectThisPage; if (item.isChecked) { that.delID(item[that.idKey], that.removeAllId); that.addID(item[that.idKey], that.addAllId); that.numOfAllSelected = parseInt(that.numOfAllSelected) + 1; } else { that.delID(item[that.idKey], that.addAllId); that.addID(item[that.idKey], that.removeAllId); that.numOfAllSelected = parseInt(that.numOfAllSelected) - 1; } }); if (this.allChecked.noUse.isTrue || (this.numOfAllSelected === 0)) { this.changeAllChecked('noUse', true, false, false); } if (this.allChecked.partUse.isTrue) { this.changeAllChecked('partUse', false, true, false); } if (this.numOfAllSelected === numOfAllDatas) { this.changeAllChecked('allUse', false, false, true); } }, singleItemClick: function (item, itemsArray, numOfAllDatas) {//当前页单个条目复选框被点击时执行的函数 var that = this; item.isChecked = !item.isChecked; if (item.isChecked) { this.isSelectThisPage = true; this.addID(item[this.idKey], this.addAllId); this.delID(item[this.idKey], this.removeAllId); this.numOfAllSelected = parseInt(this.numOfAllSelected) + 1; angular.forEach(itemsArray, function (item) { if (!item.isChecked) { that.isSelectThisPage = false; } }); } else { this.isSelectThisPage = false; this.addID(item[this.idKey], this.removeAllId); this.delID(item[this.idKey], this.addAllId); this.numOfAllSelected = parseInt(this.numOfAllSelected) - 1; } if (this.allChecked.noUse.isTrue || (this.numOfAllSelected === 0)) { this.changeAllChecked('noUse', true, false, false); } if (this.allChecked.partUse.isTrue) { this.changeAllChecked('partUse', false, true, false); } if (this.numOfAllSelected === numOfAllDatas) { this.changeAllChecked('allUse', false, false, true); } }, selectedItemsOfCurrentPageSign: function (itemsArray, numOfAllDatas) {//标注当前页被选中的条目,在翻页成功后执行。 var that = this; if (this.allChecked.noUse.isTrue) { this.numOfAllSelected = this.addAllId.length; angular.forEach(itemsArray, function (item) { for (var i = 0; i < that.addAllId.length; i++) { if (item[that.idKey] === that.addAllId[i]) { item.isChecked = true; } else { item.isChecked = false; } } }); } if (this.allChecked.partUse.isTrue) { this.numOfAllSelected = numOfAllDatas - this.removeAllId.length; angular.forEach(itemsArray, function (item) { for (var i = 0; i < that.removeAllId.length; i++) { if (item[that.idKey] === that.removeAllId[i]) { item.isChecked = false; } else { item.isChecked = true; } } }); } if (this.allChecked.allUse.isTrue) { this.numOfAllSelected = numOfAllDatas; angular.forEach(itemsArray, function (item) { item.isChecked = true; }); } }, addID: function (id, idArray) { for (var i = 0; i < idArray.length; i++) { if (id === idArray[i]) {//如果当前页的单项既有勾选又有非勾选,这时勾选当前页全选,那么需要这个判断,以免重复添加 return } } idArray.push(id); }, delID: function (id, idArray) { for (var i = 0; i < idArray.length; i++) { if (id === idArray[i]) {//有这个判断,避免不必要的循环。 idArray.splice(i, 1) return; } } }, getAllParamsBeforeDelete: function (filterOptions, isUseFilterOptions) {//在向后台发出删除请求前执行这个函数,用于处理异常情形(比如没有删除项)和汇总参数 var allParams; if (this.allChecked.noUse.isTrue) { if (this.addAllId.length === 0) { //弹窗告知:没有删除项 throw new Error('请先选择要删除的项!'); } else { allParams = { allId: this.addAllId, isSelectAll: false }; } } else { allParams = { removeAllId: this.removeAllId, isSelectAll: true }; } if (isUseFilterOptions) { angular.merge(allParams, filterOptions); } return allParams; }, } }; function dividePageFn(dividePageParams) {//下面这些数据,在实例化后,发送给后台之前,有可能会改变 return { //1、请求配置 url: dividePageParams.url || '', method: dividePageParams.method || 'post', extraServerPath: dividePageParams.extraServerPath || '',//多个后台给的数据路径不一致时,需要用这个配置 itemNumberOfEveryPage: dividePageParams.itemNumberOfEveryPage || 10,//前往服务器的每页最多数据数 //2、响应配置 keyOfCurrentPageNumber: dividePageParams.keyOfCurrentPageNumber || 'keyOfCurrentPageNumber',//来自服务器的当前页码key keyOfNumberOfAllPages: dividePageParams.keyOfNumberOfAllPages || 'keyOfNumberOfAllPages',//来自服务器的所有页页数key keyOfItemsNumberOfEveryPage: dividePageParams.keyOfItemsNumberOfEveryPage || 'keyOfItemsNumberOfEveryPage',//来自服务器的每页最多数据数key keyOfItemsNumberOfAllPages: dividePageParams.keyOfItemsNumberOfAllPages || 'keyOfItemsNumberOfAllPages',//来自服务器的所有页数据数key keyOfTableDatasOfCurrentPage: dividePageParams.keyOfTableDatasOfCurrentPage || 'keyOfTableDatasOfCurrentPage',//来自服务器的表格数据key //3、分页展示配置 frontMoreText: dividePageParams.frontMoreText || "",//('文字 ')或者("文字 "+result.numberOne+" 文字 "), backMoreText: dividePageParams.backMoreText || "",//(' 文字')或者("文字 "+result.numberThree+" 文字"), totalText: dividePageParams.totalText || "",//'共', totalUnit: dividePageParams.totalUnit || '条',//总数据的单位 //4、以下不用配置,在页面使用的过程中可能会有改变 currentPageNumber: 0, isShowTableLoading: false,//向后台发送请求时,分页表格是否显示转圈。每个表格都有各自的分页服务实例,因此isShowTableLoading不会造成覆盖 isShowFilterOptions: false,//是否显示过滤条件 filterOptions: {},//过滤条件 otherDatas: {},//其它参数,通过dividePageInstance传给当前页面的分页组件或其它子组件,并在该组件内调用dividePageInstance.dividePageRequest函数,重新渲染当前页面。 //5、以下是现成方法,调用即可 toggleShowFilterOptions: function () { this.isShowFilterOptions = !this.isShowFilterOptions; if (!this.isShowFilterOptions) { this.dividePageRequest(1); } }, /* startFilter: function () { this.dividePageRequest(1); }, */ emptyFilterOptions: function () { //清空选项时,所有值恢复成默认 var that = this; angular.forEach(that.filterOptions, function (value, key) { //大部分选项的默认值是undefined that.filterOptions[key] = undefined; }); for (var i = 0; i < anguments.length; i++) { //少部分选项,比如下拉框的默认值是全部,对应的value为“all”,那么把该项对应的key作为参数传入 that.filterOptions[anguments[i]] = 'all'; } this.dividePageRequest(1); }, loading: function (type) { var that = this; var fn = null; var tableCircle = function (boolean) { //分页表格时用,用时需要在页面加上<dir-tableload isShow="dividePageInstance.isShowTableLoading"></dir-tableload> //每个表格都有各自的分页服务实例,因此isShowTableLoading不会造成覆盖 that.isShowTableLoading = boolean; } var wholeCircle = function (boolean) {//分页时用,全局转圈,在全局页面上加上<dir-load></dir-load> wholeCircleService.isShow = boolean;//把wholeCircleService注入<dir-load>组件并控制该组件的隐现 } if (type === 'tableCircle') { fn = tableCircle } if (type === 'wholeCircle') { fn = wholeCircle } return fn; } } } return function (allConfigures, currentScope, more) {//执行步骤二。========================= var more = more || '';//如果一个页面有两个分页,那么用more进行区分。 var checkListInstance = 'checkListInstance' + more; var dividePageInstance = 'dividePageInstance' + more; currentScope[checkListInstance] = checkListFn(allConfigures.idKey); //配置分页的勾选 currentScope[dividePageInstance] = dividePageFn(allConfigures.dividePageParams); //作用:见下面dividePageParams配置实例。 currentScope[dividePageInstance]['dividePageCallback'] = function (result) {//分页翻页后,执行的回调 angular.isFunction(allConfigures.trueCallback) ? allConfigures.trueCallback(result, currentScope) : angular.noop();//分页翻页后,页面用特殊方式取用后台返回的数据 currentScope[checkListInstance]['signSelectedItemsOfCurrentPage'](currentScope[dividePageInstance].keyOfTableDatasOfCurrentPage, result['keyOfItemsNumberOfAllPages']); //分页翻页后,处理新页面的勾选 }; }; }); //4、勾选和分页服务的实例 checkListAndDividePage(//执行步骤一。========================= { idKey: 'id',//配置分页的勾选 dividePageParams: {//作用如下 //1、请求配置 url: '', method: '', extraServerPath: ['path1', 'path1', 'path1'],//[], itemNumberOfEveryPage: 20, //2、响应配置 keyOfCurrentPageNumber: '', keyOfNumberOfAllPages: '', keyOfItemsNumberOfEveryPage: '', keyOfItemsNumberOfAllPages: '', keyOfTableDatasOfCurrentPage: '', //3、分页展示配置 frontMoreText: '',//('文字 ')或者("文字 "+result.numberOne+" 文字 "), backMoreText: '',//(' 文字')或者("文字 "+result.numberThree+" 文字"), totalText: '',//'共', totalUnit: '条',//总数据的单位 }, trueCallback: function (result, currentScope) {//分页翻页后,此函数放在成功函数里执行 currentScope['true'] = result.data; }, errorCallback: function (result, currentScope) {//分页翻页后,此函数放在catch函数里执行 currentScope['error'] = result.data; } },//第一个参数 $scope,//第二个参数 "dividePageOne"//第三个参数 ) //5、请求服务 /* 弹窗有三种类型 1、提示弹窗:给你警示、告知你成功或失败。你点击确认按钮即可。 2、是否提交弹窗:表单填完以后,你选择点击确认或取消按钮。 3、表格弹窗:没有按钮,只有分页选项 另外,应考虑到这样的情况:第1个表单弹窗提交后不消失,并把后台反馈的错误放到第2个弹窗上,由用户把第2个弹窗关闭,然后在第1个弹窗上面修改*/ /* var allDatas = { method: 'post', url: '', warn: '', responseType: '', dividePageCircle: dividePageService.loading('tableCircle'),//分页转圈 commonWholeCircle: $scope.isWholeCircle,//非分页全局转圈 commonPartCircle: $scope.isPartCircle,//非分页局部转圈 isDirectUseDatas: true,//是否放弃后台反馈的状态码执行逻辑 isShowSecondAlert: true,//实现显示第2个弹窗 isShowAllButtons: true,//是否显示按钮行,如果是表格弹窗,就不显示 isShowCancelButton: true,//是否显示取消按钮,如果是提示弹窗,就不显示 concelText: '',//取消按钮上的文字 confirmText: '',//确认按钮上的文字。alertOne.set({confirmText:allDatas.ConfirmText||'确定',}) confirmCallback: fn ,//点击确认按钮,执行的回调函数 } */ factory('cyRequest', function () { function http(allDatas, deferred) { var allParams = { method: allDatas.method, url: allDatas.url, params: allDatas.params || {} }; if (allDatas.responseType) { angular.merge(allParams, { responseType: allDatas.responseType }); }; if (angular.isFunction(allDatas.dividePageCircle)) { allDatas.dividePageCircle(true): angular.noop(); } else if (allDatas.hasOwnProperty('commonWholeCircle')) { allDatas.commonWholeCircle = true; } else if (allDatas.hasOwnProperty('commonPartCircle')) { allDatas.commonPartCircle = true; } $http(allParams).then(function (result) { //result.status(不是result.allDatas.status)===200时进入这里,否则进入catch if (allDatas.isDirectUseDatas) { deferred.resolve(result); } else { if (result.allDatas.status === 1000) { } else if (result.allDatas.status === 0) { if (allDatas.isShowSecondAlert) { alertTwo.set({ isShowAllButtons: allDatas.isShowAllButtons, isShowCancelButton: allDatas.isShowCancelButton, content: result.allDatas.message, concelText: allDatas.concelText || '取消', confirmText: allDatas.confirmText || '确定', confirmCallback: angular.isFunction(allDatas.confirmCallback) ? allDatas.confirmCallback : null }); } else { alertOne.set({ isShowAllButtons: allDatas.isShowAllButtons, isShowCancelButton: allDatas.isShowCancelButton, content: result.allDatas.message, concelText: allDatas.concelText || '取消', confirmText: allDatas.confirmText || '确定', confirmCallback: angular.isFunction(allDatas.confirmCallback) ? allDatas.confirmCallback : null }); } } else { deferred.resolve(result.allDatas) } } }).catch(function (err) { deferred.reject(err); }).finally(function () { if (angular.isFunction(allDatas.dividePageCircle)) { allDatas.dividePageCircle(false): angular.noop(); } else if (allDatas.hasOwnProperty('commonWholeCircle')) { allDatas.commonWholeCircle = false; } else if (allDatas.hasOwnProperty('commonPartCircle')) { allDatas.commonPartCircle = false; } }); }; return function (allDatas) { var deferred = $q.defer(); if (allDatas.warn) { if (isShowSecondAlert) { alertTwo.set({ button: true, content: allDatas.warn, ok: function () { http(allDatas, deferred); } }); } else { alertOne.set({ /* */ }); } } else { http(allDatas, deferred); } return deferred.promise; }; };