baseServices.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. (function (){
  2. var paths = [
  3. ];
  4. for (var i=0,pi;pi = paths[i++];) {
  5. document.write('<script type="text/javascript" src="'+ __ctx + pi +'"></script>');
  6. }
  7. })();
  8. var baseServices = angular.module( "baseServices", ["authApp",'ComplexService'] );
  9. baseServices.factory("$jsonToFormData",function() {
  10. function transformRequest( data, getHeaders ) {
  11. var headers = getHeaders();
  12. headers["Content-Type"] = "application/x-www-form-urlencoded; charset=utf-8";
  13. return $.param(data);
  14. }
  15. return( transformRequest );
  16. })
  17. .directive('htCheckbox', function() {
  18. return {
  19. restrict: 'A',
  20. link: function(scope, element, attrs) {
  21. var key = attrs["htCheckbox"];
  22. var getValAry = function(){
  23. var val = getValByScope(element,key);
  24. if(val){
  25. if(typeof val == "string"){
  26. return {type:"string",data:val.split(",")};
  27. }
  28. else{
  29. return {type:"object",data:val};
  30. }
  31. }
  32. return {type:"string",data:[]};
  33. };
  34. scope.$watch(key,function(newVal,oldVal){
  35. if(!newVal)return;
  36. if(newVal!==oldVal || !element.data("notFirstTime")){
  37. element.data("notFirstTime",true);
  38. if(typeof newVal == "string"){
  39. if(newVal==element.val()||newVal.split(",").indexOf(element.val())!=-1){
  40. element[0].checked = true;
  41. }
  42. else{
  43. element[0].checked = false;
  44. }
  45. }
  46. else{
  47. if(newVal.indexOf(element.val())!=-1){
  48. element[0].checked = true;
  49. }
  50. else{
  51. element[0].checked = false;
  52. }
  53. }
  54. }
  55. },false);
  56. element.bind('change',function(){
  57. var elementVal = element[0].checked,
  58. option = attrs["value"],
  59. array = getValAry();
  60. if(elementVal){
  61. if(!isInArray(array.data,option)){
  62. array.data.push(option);
  63. }
  64. }
  65. else{
  66. array.data.remove(option);
  67. }
  68. if(array.data.length > 1){
  69. array.data.remove("");
  70. }
  71. else if(array.data.length == 0){
  72. array.data.push("");
  73. }
  74. if(array.type=="string"){
  75. setValToScope(element,array.data.join(','),null,key);
  76. }
  77. else{
  78. setValToScope(element,array.data,null,key);
  79. }
  80. });
  81. }
  82. };
  83. })
  84. .provider('DemotionPermission',function(){
  85. //是否需要权限降级
  86. var _demotion = false;
  87. this.setDemotion = function(t){
  88. _demotion = !!t;
  89. }
  90. this.$get = function(){
  91. return {
  92. demotion : _demotion
  93. };
  94. }
  95. })
  96. /**
  97. * 表单权限控制
  98. */
  99. .directive('htPermission', ['$compile','DemotionPermission',function($compile,DemotionPermission) {
  100. return {
  101. priority:5,
  102. link:function(scope,elm,attrs){
  103. scope.handlerPermission = function(newVal,el,attr){
  104. //需要权限降级时 将必填、编辑 权限降级为只读
  105. if(DemotionPermission.demotion){
  106. if(newVal!="y"||newVal!="r"){
  107. newVal = "r";
  108. }
  109. }
  110. var ngModel=attr.ngModel,scopeVal = '';
  111. if(el.attr("type") == "subGroupTr"){
  112. scope.subFieldPermission(newVal,el);
  113. }
  114. else if(el.attr("type") == "subGroup"){
  115. scope.subFieldPermission(newVal,el);
  116. }else {
  117. scopeVal= getValByScope(el,ngModel,scope) || '';
  118. scope.fieldPermission(newVal,el,scopeVal);
  119. }
  120. };
  121. scope.$watch(attrs.htPermission,function(newVal,oldVal){
  122. if(!newVal)return;
  123. if (newVal !== oldVal || !elm.data("notFirstTime")) {
  124. elm.data("notFirstTime", true);
  125. if((attrs.htSelectorDef&&parseToJson(attrs.htSelectorDef)['showCurrent'])||(elm.hasClass("selector-home")&&attrs.selectorType))
  126. window.setTimeout(function(){
  127. scope.handlerPermission(newVal,elm,attrs);
  128. },100);
  129. else
  130. scope.handlerPermission(newVal,elm,attrs);
  131. }
  132. });
  133. /**
  134. * 复合字段(子表)权限
  135. */
  136. scope.subFieldPermission = function(val,elm){
  137. switch (val) {
  138. case 'b': //必填
  139. var temp = attrs.htPermission.split("."),
  140. ngModel = "data."+temp[temp.length-1];
  141. scope.$watch(ngModel.replaceAll("\\$\\$","."),function(n,o){
  142. if(n.length==0){
  143. elm.addClass("field-home");
  144. elm.validMe({text:"",rule:"{'required':true}"});
  145. }else{
  146. elm.qtipSuccess();
  147. }
  148. },true);
  149. break;
  150. case 'r': //只读
  151. var inputList = elm.find("[ht-permission]");
  152. inputList.each(function(){
  153. var scopeVal = getValByScope($(this),"","");
  154. $(this).after("<span>"+scopeVal+"</span>");
  155. $(this).remove();
  156. });
  157. elm.children(".group-title").find("a[ng-click]").remove();
  158. elm.children(".owner-div").find("a[ng-click]").remove();
  159. break;
  160. case 'y': //隐藏
  161. elm.remove();
  162. break;
  163. default://编辑没修改(w)
  164. break;
  165. }
  166. };
  167. /**
  168. * 字段权限
  169. */
  170. function setToReadCall(elm,scopeVal){
  171. if(isComplexTag(elm)){
  172. elm.parent().html("<span>"+scopeVal+"</span>");
  173. }else if(elm.hasClass("file-div")){
  174. if(scopeVal){
  175. elm.next().remove();
  176. elm.next().remove();
  177. var temp = [];
  178. for(var i =0 ;i<scopeVal.length;i++){
  179. temp.push("<a onclick='downLoadFileById(\""+scopeVal[i].fileId+"\")' class='file-down' title='点击下载附件'>"+scopeVal[i].fileName+"</a>");
  180. }
  181. elm.after("<span>"+temp.join(",")+"</span>");
  182. }else{
  183. elm.closest(".s-closest").remove();
  184. }
  185. }else{
  186. elm.after("<span>"+scopeVal+"</span>");
  187. }
  188. elm.remove();
  189. }
  190. function setToRead(elem,scopeVal){
  191. if(scopeVal){
  192. setToReadCall(elem,scopeVal);
  193. return;
  194. }
  195. var showCuEl = elem.attr("selector-def-div");
  196. if(!showCuEl){
  197. setToReadCall(elem,scopeVal);
  198. return;
  199. }
  200. showCuEl = parseToJson(showCuEl);
  201. if(!showCuEl.showCurrent){
  202. setToReadCall(elem,scopeVal);
  203. return;
  204. }
  205. window.setTimeout(function(){
  206. setToRead(elem,getValByScope(elem));
  207. },1000);
  208. }
  209. scope.fieldPermission = function(val,elm,scopeVal){
  210. var elmParent = elm.parent();
  211. switch (val) {
  212. case 'b': //必填
  213. //让字段必填 ht-field-valid="{'required':true}"
  214. var tempValid = elm.attr("ht-field-valid");
  215. if(tempValid){
  216. tempValid = parseToJson(tempValid);
  217. }else{
  218. tempValid = {};
  219. elm.addClass("field-home");
  220. }
  221. tempValid.required=true;
  222. var ngModelVal = elm.attr("ng-model");
  223. elm.removeAttr("ng-model");
  224. elm.attr("ht-field-valid",JSON.stringify(tempValid));
  225. $compile(elm)(elm.scope());
  226. ngModelVal&&elm.attr("ng-model",ngModelVal);
  227. break;
  228. case 'r': //只读
  229. setToRead(elm,scopeVal);
  230. break;
  231. case 'y': //隐藏
  232. if(isComplexTag(elm)||elm.attr("ht-file")){
  233. elm = elm.closest(".field-home");
  234. elm.prev('th').remove();
  235. }else{
  236. elm.parent().prev('th').remove();
  237. }
  238. var closestTR = elm.closest("tr") ;
  239. var closestSubGroup = elm.closest("[type='subGroup']") ;
  240. var tdths=closestTR.children();
  241. elm.remove();
  242. var isNull = true;
  243. tdths.each(function(){
  244. if($(this).html()){
  245. isNull=false;
  246. return true;
  247. }
  248. });
  249. if(isNull) closestTR.remove();
  250. //如果是子表,那么当字表中的tbody为空时 就隐藏
  251. if(closestSubGroup[0]&&!closestSubGroup.find('tbody').html()) closestSubGroup.remove();
  252. break;
  253. default://编辑没修改(w)
  254. break;
  255. }
  256. };
  257. //在需要权限降级时,如果没有配置字段权限,默认为只读权限
  258. if(DemotionPermission.demotion){
  259. scope.handlerPermission('r',elm,attrs);
  260. }
  261. }
  262. };
  263. }])
  264. .directive('htDate', function() {
  265. return {
  266. restrict: 'A',
  267. link: function(scope, element, attrs) {
  268. var ngModel = attrs.ngModel;
  269. switch(attrs.htDate){
  270. case "date":
  271. $(element).on("focus",function(){
  272. var me = $(this);
  273. WdatePicker({dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true});
  274. me.blur();
  275. scope.$apply(function(){
  276. eval("(scope." + ngModel + "='" + me.val() + "')");
  277. });
  278. });
  279. break;
  280. case "datetime":
  281. $(element).on("focus",function(){
  282. var me = $(this);
  283. WdatePicker({dateFmt:'yyyy-MM-dd',alwaysUseStartDate:true});
  284. me.blur();
  285. scope.$apply(function(){
  286. eval("(scope." + ngModel + "='" + me.val() + "')");
  287. });
  288. });
  289. break;
  290. case "wdateTime":
  291. $(element).on("focus",function(){
  292. var me = $(this), dateFmt= (me.attr('datefmt')?me.attr('datefmt'):'yyyy-MM-dd');
  293. WdatePicker({dateFmt:dateFmt,alwaysUseStartDate:true});
  294. me.blur();
  295. scope.$apply(function(){
  296. eval("(scope." + ngModel + "='" + me.val() + "')");
  297. });
  298. });
  299. break;
  300. }
  301. }
  302. };
  303. })
  304. /**
  305. * 对时间进行格式化处理 控件格式如下
  306. * <input type="text"
  307. * ng-model="data.person.born"
  308. * class="inputText"
  309. * ht-date-format="
  310. * {'currentTime':true,'exp':'yyyy-MM-dd HH:mm:ss'}
  311. * ">
  312. * currentTime:表示是否显示当前日期
  313. * exp:格式化表达式
  314. */
  315. .directive('htDateFormat', function($injector) {
  316. var link = function(scope, element, attrs, $ctrl) {
  317. var json = parseToJson(attrs['htDateFormat']);
  318. element.addClass("dateformat");
  319. if(json.currentTime){
  320. var now=new Date().Format(json.exp);
  321. setValToScope(element,now);
  322. }
  323. };
  324. return {
  325. restrict : 'A',
  326. require : "ngModel",
  327. compile : function() {
  328. return link;
  329. }
  330. };
  331. })
  332. .directive('htDic', function(){
  333. return {
  334. restrict: 'EAC',
  335. require : "ngModel",
  336. link: function(scope, element, attrs) {
  337. if(!attrs.htDic)return;
  338. scope.$watch(attrs.ngModel,function(newVal,oldVal){
  339. if (newVal !== oldVal || !element.data('dictionary')) {
  340. element.data('dictionary', true);
  341. scope.update(newVal);
  342. }
  343. },false);
  344. //ngModel的值变化 与 数据字典的初始化 是两条生命周期线,要进行赋值需要在两者都完成的时候进行
  345. scope.update = function(val){
  346. var dicReady = element.data("dictionaryReady");
  347. if(typeof dicReady=='undefined'){
  348. element.data("dictionaryReady",(typeof val=='undefined')?true:val);
  349. }
  350. else{
  351. var relVal = (typeof val=='undefined')?dicReady:val;
  352. element.combotree("clear");
  353. //选中数据字典中key与ngModel值相同的节点
  354. element.eachComboNode(function(node){
  355. if(node.key&&node.key==relVal){
  356. element.combotree('setValue',node.id);
  357. return false;
  358. }
  359. return true;
  360. });
  361. }
  362. }
  363. var url = __ctx +"/platform/system/dataDict/getByTypeKeyForComBo.ht?typeKey="+attrs.htDic;
  364. element.combotree({
  365. url:url,
  366. onLoadSuccess:function(node,data){
  367. scope.update();
  368. },
  369. onClick:function(node){
  370. setValToScope(element,node.key);
  371. }
  372. });
  373. }
  374. };
  375. })
  376. .directive('htFileUpload', [function() {
  377. return {
  378. restrict: 'EAC',
  379. scope:{
  380. htFileUpload:'='
  381. },
  382. link: function(scope, element, attrs) {
  383. scope.choose = function(){
  384. UploadDialog(scope.setting);
  385. }
  386. scope.download = function(item){
  387. window.open(__ctx + "/platform/system/file/download.ht?id="+item.id);
  388. }
  389. //移除某项
  390. scope.remove = function(index){
  391. scope.file.splice(index,1);
  392. scope.updateValue(false);
  393. }
  394. scope.updateValue = function(digest){
  395. var v = scope.file.length==0?"":angular.toJson(scope.file);
  396. //更新数据到父作用域
  397. if("ng"==scope.setting.bindType){
  398. var ngModel = attrs['ngModel'];
  399. if(!ngModel)return;
  400. eval('scope.$parent.' + ngModel + '=' + (v?v:"''"));
  401. digest&&scope.$parent.$digest();
  402. }
  403. //更新数据到对象元素
  404. else if("jq"==scope.setting.bindType){
  405. if(!scope.bindObj)return;
  406. scope.bindObj.val(v);
  407. }
  408. }
  409. var setting = {
  410. download:true, //true:允许下载,false:不允许下载
  411. bindType:'ng' //ng:ng-model模式,jq:jquery模式,jq模式下需要配置bind属性
  412. };
  413. if($.extend(true,setting,scope.htFileUpload||{})){
  414. scope.setting = setting;
  415. scope.setting.callback = function(data){
  416. !angular.isArray(scope.file)&&(scope.file==[]);
  417. scope.file = scope.file.concat(data);
  418. scope.updateValue(true);
  419. }
  420. if("ng"==scope.setting.bindType){
  421. var ngModel = attrs['ngModel'];
  422. if(!ngModel)return;
  423. scope.$parent.$watch(ngModel,function(newVal,oldVal){
  424. if (newVal !== oldVal || !element.data('file')) {
  425. element.data('file', true);
  426. scope.file = newVal || [];
  427. }
  428. },false);
  429. }
  430. else if("jq"==scope.setting.bindType){
  431. var bindObj = angular.element(scope.setting.bind);
  432. if(!bindObj)return;
  433. scope.bindObj = bindObj;
  434. scope.file = parseToJson(bindObj.val()||'');
  435. }
  436. }
  437. },
  438. template: '<span><div class="ht-input"><span class="span-user owner-span" ng-repeat="item in file">'
  439. +'<a title="下载该文件" ng-if="setting.download" ng-click="download(item)">{{item.name}}</a><span ng-if="!setting.download">{{item.name}}</span>'
  440. +'<a class="btn btn-xs fa-remove" style="margin-bottom:4px;" title="移除该项" ng-click="remove($index)"></a></span>'
  441. +'</div><a class="btn btn-sm btn-primary fa-upload" ng-click="choose()"><span>上传</span></a></span>',
  442. replace: true
  443. };
  444. }])
  445. /**
  446. * ht-select-ajax 动态加载select的options数据
  447. * 列如: <select ng-model="form.typeId" ng-options="(m.id) as m.text for m in formTypeList"
  448. * ht-select-ajax="{url:'${ctx}/platform/system/sysType/getByGroupKey.ht?groupKey=FORM_TYPE',field:'formTypeList'}">
  449. * <option value="">请选择</option>
  450. * </select>
  451. * 传入参数
  452. * url : 请求地址
  453. * field : formTypeList 对应于 ng-options 中的 formTypeList (两者必须相同)
  454. */
  455. .directive('htSelectAjax', function($injector) {
  456. return {
  457. restrict: 'A',
  458. link: function(scope, element, attrs) {
  459. var BaseService = $injector.get("BaseService");
  460. var option=attrs["htSelectAjax"];
  461. option=eval("("+option+")");
  462. if(scope.$root.$$childHead[option.field]) return;
  463. BaseService.get(option.url,function(data){
  464. if(option.dataRoot){
  465. data = data[option.dataRoot];
  466. }
  467. scope[option.field] = data;
  468. scope.$root.$$childHead[option.field] = scope[option.field];
  469. });
  470. }
  471. };
  472. })
  473. .directive('htTip', function($injector) {
  474. return {
  475. restrict: 'A',
  476. scope:{
  477. htTip:"="
  478. },
  479. link: function(scope, element, attrs) {
  480. var defaultSetting = {
  481. hide: {
  482. event:'mouseleave',
  483. leave: false,
  484. fixed:true,
  485. delay:100
  486. },
  487. style: {
  488. classes: 'qtip-default qtip qtip-bootstrap qtip-shadow'
  489. }
  490. };
  491. var setting = angular.extend(scope.htTip || {},defaultSetting);
  492. element.qtip(setting);
  493. }
  494. };
  495. })
  496. .directive('htZtree', ['BaseService',function(BaseService) {
  497. return {
  498. restrict: 'A',
  499. scope:{
  500. htZtree:"=",
  501. htCallback:"=",
  502. htDataKey:"=",
  503. htCheck:"="
  504. },
  505. link: function(scope, element, attrs) {
  506. element.addClass("ztree");
  507. if(!element.prop("id")){
  508. //ztree所在ul标签必须有唯一的id属性,否则当页面有两个ztree时回调函数会出现问题
  509. element.prop("id",BaseService.guid());
  510. }
  511. scope.setting = {
  512. view:{
  513. dblClickExpand:false
  514. },
  515. data:{
  516. key:scope.htDataKey||{}
  517. },
  518. check:scope.htCheck||{},
  519. callback: scope.htCallback||{}
  520. };
  521. scope.$watch("htZtree",function(newVal,oldVal){
  522. if(newVal!==oldVal){
  523. $.fn.zTree.init($(element),scope.setting, newVal);
  524. }
  525. },true);
  526. }
  527. };
  528. }])
  529. .directive('htBindHtml', function($compile) {
  530. return {
  531. restrict : 'A',
  532. link : function(scope, elm, attrs) {
  533. scope.unbindWatch = scope.$watch(attrs.htBindHtml, function(newVal, oldVal) {
  534. if (newVal !== oldVal) {
  535. if(newVal){
  536. elm.data('unbindWatchTag',true);
  537. elm.html(newVal);
  538. scope.htmlFn&&scope.htmlFn.call();
  539. $compile(elm)(scope);
  540. }
  541. else{
  542. elm.html('');
  543. //避免重复添加监视
  544. elm.data('unbindWatchTag')&&scope.unbindWatch();
  545. }
  546. }
  547. });
  548. }
  549. };
  550. })
  551. .directive('htInit', function($compile) {
  552. return {
  553. restrict : 'A',
  554. link : function(scope, elm, attrs) {
  555. var json = parseToJson(attrs["htInit"]);
  556. for(var i in json){
  557. setValToScope(null,json[i],null,i,scope);
  558. }
  559. }
  560. };
  561. })
  562. //显示用户的指令,使用示例:<input ht-user-tag="1" />
  563. .directive('htUserTag', ["BaseService",function(BaseService) {
  564. return {
  565. restrict : 'A',
  566. scope:{
  567. //userId
  568. htUserTag:"=",
  569. },
  570. controller: function($scope,$element){
  571. $scope.showDetail = function(userId){
  572. new UserInfoDialog(userId).show();
  573. }
  574. },
  575. link : function(scope, elm, attrs) {
  576. if(scope.htUserTag){
  577. BaseService.post(__ctx + "/platform/org/user/userInfo.ht",{id:scope.htUserTag},function(data){
  578. scope.user = data;
  579. });
  580. }
  581. },
  582. template:'<span class="owner-span" ng-hide="user | isEmpty"><a href="#" ng-click="showDetail(user.id)">{{user.name}}</a></span>',
  583. replace:true
  584. };
  585. }])
  586. .directive('onFinishRenderFilters', function ($timeout) {
  587. return {
  588. restrict: 'A',
  589. link: function(scope, element, attr) {
  590. if (scope.$last === true) {
  591. $timeout(function() {
  592. scope.$emit('ngRepeatFinished');
  593. });
  594. }
  595. }
  596. };
  597. })
  598. .service('BaseService', ['$http','$jsonToFormData', function($http,$jsonToFormData) {
  599. var service = {
  600. get:function(url,callback){
  601. $http.get(url).success(function(data,status){
  602. if(callback){
  603. callback(data,status);
  604. }
  605. })
  606. .error(function(data,status){
  607. if(callback){
  608. callback(data,status);
  609. }
  610. //TODO 根据返回的错误状态(status)显示对应的全局提示
  611. });
  612. },
  613. post:function(url,param,callback){
  614. $http.post(url,param,{transformRequest:$jsonToFormData})
  615. .success(function(data,status){
  616. if(callback){
  617. callback(data,status);
  618. }
  619. })
  620. .error(function(data,status){
  621. if(callback){
  622. callback(data,status);
  623. }
  624. //TODO 根据返回的错误状态(status)显示对应的全局提示
  625. });
  626. },
  627. //m内容,b:true->alert输出;false:console
  628. show:function(m,b){
  629. if(b==null||b==false){
  630. console.info(m);
  631. }else{
  632. alert(m+"");
  633. }
  634. },
  635. //生成ID
  636. guid:function(){
  637. return Math.random().toString(36).substring(2, 15) +
  638. Math.random().toString(36).substring(2, 15);
  639. }
  640. };
  641. return service;
  642. }])
  643. .filter('isEmpty', function () {
  644. var bar = "";
  645. return function (obj) {
  646. for (bar in obj) {
  647. if (obj.hasOwnProperty(bar)) {
  648. return false;
  649. }
  650. }
  651. return true;
  652. };
  653. })
  654. .filter('htTime', function () {
  655. //毫秒转换成 **天**小时**分**秒的格式
  656. return function (input) {
  657. var day = (input / 1000 / 60 / 60 / 24) << 0
  658. hour = (input / 1000 / 60 /60) % 24 << 0,
  659. min = (input / 1000 / 60) % 60 << 0,
  660. sec = Math.round((input / 1000) % 60),
  661. result = [];
  662. if(day){
  663. result.push(day + '天');
  664. }
  665. if(hour){
  666. result.push(hour+'小时');
  667. }
  668. if(min){
  669. result.push(min+'分');
  670. }
  671. if(!isNaN(sec)&&sec){
  672. result.push(sec+'秒');
  673. }
  674. return result.join('');
  675. };
  676. });