PersonIndex.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. MWF.xApplication.Attendance = MWF.xApplication.Attendance || {};
  2. MWF.require("MWF.xAction.org.express.RestActions", null,false);
  3. MWF.xDesktop.requireApp("Attendance", "lp."+MWF.language, null, false);
  4. MWF.xDesktop.requireApp("Attendance", "Common", null, false);
  5. MWF.xApplication.Attendance.PersonIndex = new Class({
  6. Extends: MWF.widget.Common,
  7. Implements: [Options, Events],
  8. options: {
  9. "style": "default"
  10. },
  11. statusColor : {
  12. "normal" : "#9acd32", //绿色,正常
  13. "levelAsked":"#4f94cd", //蓝色,请假
  14. "late":"#fede03", //黄色,迟到
  15. //"leaveEarly":"#fe8d03", //橙色,早退
  16. "noSign":"#ee807f", //粉红色,未签到
  17. "appealSuccess" : "#2ac497", //黄绿色,申诉通过
  18. "lackOfTime" : "#dec674",//工时不足人次
  19. "abNormalDuty" : "#fedcbd"//异常打卡人次
  20. },
  21. initialize: function(node, app, actions, options){
  22. this.setOptions(options);
  23. this.app = app;
  24. this.lp = app.lp;
  25. this.path = "/x_component_Attendance/$PersonIndex/";
  26. this.cssPath = "/x_component_Attendance/$PersonIndex/"+this.options.style+"/css.wcss";
  27. this._loadCss();
  28. this.actions = actions;
  29. this.node = $(node);
  30. this.holidayData = {};
  31. this.today = new Date();
  32. //this.preMonthDate = new Date();
  33. //this.preMonthDate.decrement("month", 1);
  34. this.setDate();
  35. this.todayDate = this.today.format( this.lp.dateFormatDay );
  36. this.todayHloidayName = "";
  37. this.todayIsWorkDay = false; //是否调修工作日
  38. this.userName = layout.desktop.session.user.name;
  39. },
  40. setDate : function( date ){
  41. this.date = date || new Date(); //this.preMonthDate
  42. this.year = this.date.getFullYear().toString();
  43. var month = this.date.getMonth()+1;
  44. this.month = month.toString().length == 2 ? month : "0"+month;
  45. this.getCycleDate();
  46. },
  47. destroy: function(){
  48. this.node.empty();
  49. },
  50. reload: function(){
  51. this.node.empty();
  52. this.load();
  53. },
  54. load: function(){
  55. this.loadTitleNode();
  56. this.loadContent();
  57. },
  58. loadTitleNode : function(){
  59. var text = this.date.format(this.app.lp.dateFormatMonth);
  60. this.titleNode = new Element("div.titleNode",{
  61. "styles" : this.css.titleNode
  62. }).inject(this.node);
  63. //this.titleLeftArrowNode = new Element("div",{
  64. // "styles" : this.css.titleLeftArrowNode
  65. //}).inject(this.titleNode);
  66. this.titleTextNode = new Element("div",{
  67. "styles" : this.css.titleTextNode,
  68. "text" : text
  69. }).inject(this.titleNode);
  70. this.titleTextNode.setStyles( {
  71. "margin-left": "30px",
  72. "cursor" : "default"
  73. } )
  74. //this.titleRightArrowNode = new Element("div",{
  75. // "styles" : this.css.titleRightArrowNode
  76. //}).inject(this.titleNode);
  77. var cycleText = "考勤周期:"+ this.cycleStartDateString + "至" + this.cycleEndDateString;
  78. this.titleCycleTextNode = new Element("div",{
  79. "styles" : this.css.titleCycleTextNode,
  80. "text" : cycleText
  81. }).inject(this.titleNode);
  82. this.titleScheduleIconNode = new Element("div",{
  83. "styles" : this.css.titleScheduleIconNode,
  84. "title" : this.lp.seeSchedule
  85. }).inject(this.titleNode);
  86. //this.titleLeftArrowNode.addEvents({
  87. // "mouseover": function(){this.titleLeftArrowNode.setStyles(this.css.titleLeftArrowNode_over);}.bind(this),
  88. // "mouseout": function(){this.titleLeftArrowNode.setStyles(this.css.titleLeftArrowNode);}.bind(this),
  89. // "mousedown": function(){this.titleLeftArrowNode.setStyles(this.css.titleLeftArrowNode_down);}.bind(this),
  90. // "mouseup": function(){this.titleLeftArrowNode.setStyles(this.css.titleLeftArrowNode_over);}.bind(this),
  91. // "click": function(){this.changeMonthPrev();}.bind(this)
  92. //});
  93. //this.titleRightArrowNode.addEvents({
  94. // "mouseover": function(){this.titleRightArrowNode.setStyles(this.css.titleRightArrowNode_over);}.bind(this),
  95. // "mouseout": function(){this.titleRightArrowNode.setStyles(this.css.titleRightArrowNode);}.bind(this),
  96. // "mousedown": function(){this.titleRightArrowNode.setStyles(this.css.titleRightArrowNode_down);}.bind(this),
  97. // "mouseup": function(){this.titleRightArrowNode.setStyles(this.css.titleRightArrowNode_over);}.bind(this),
  98. // "click": function(){this.changeMonthNext();}.bind(this)
  99. //});
  100. //this.titleTextNode.addEvents({
  101. // "mouseover": function(){this.titleTextNode.setStyles(this.css.titleTextNode_over);}.bind(this),
  102. // "mouseout": function(){this.titleTextNode.setStyles(this.css.titleTextNode);}.bind(this),
  103. // "mousedown": function(){this.titleTextNode.setStyles(this.css.titleTextNode_down);}.bind(this),
  104. // "mouseup": function(){this.titleTextNode.setStyles(this.css.titleTextNode_over);}.bind(this),
  105. // "click": function(){this.changeMonthSelect();}.bind(this)
  106. //});
  107. this.titleScheduleIconNode.addEvents({
  108. "mouseover": function(){this.titleScheduleIconNode.setStyles(this.css.titleScheduleIconNode_over);}.bind(this),
  109. "mouseout": function(){this.titleScheduleIconNode.setStyles(this.css.titleScheduleIconNode);}.bind(this),
  110. "mousedown": function(){this.titleScheduleIconNode.setStyles(this.css.titleScheduleIconNode_down);}.bind(this),
  111. "mouseup": function(){this.titleScheduleIconNode.setStyles(this.css.titleScheduleIconNode_over);}.bind(this),
  112. "click": function(){this.showSchedule();}.bind(this)
  113. });
  114. },
  115. changeMonthPrev: function(){
  116. this.date.decrement("month", 1);
  117. this.setDate( this.date );
  118. var text = this.date.format(this.app.lp.dateFormatMonth);
  119. this.titleTextNode.set("text", text);
  120. this.reloadContent();
  121. },
  122. changeMonthNext: function(){
  123. this.date.increment("month", 1);
  124. this.setDate( this.date );
  125. var text = this.date.format(this.app.lp.dateFormatMonth);
  126. this.titleTextNode.set("text", text);
  127. this.reloadContent();
  128. },
  129. changeMonthSelect: function(){
  130. if (!this.monthSelector) this.createMonthSelector();
  131. this.monthSelector.show();
  132. },
  133. createMonthSelector: function(){
  134. this.monthSelector = new MWF.xApplication.Attendance.MonthSelector(this.date, this);
  135. },
  136. changeMonthTo: function(d){
  137. this.setDate( d )
  138. var text = this.date.format(this.app.lp.dateFormatMonth);
  139. this.titleTextNode.set("text", text);
  140. this.reloadContent();
  141. },
  142. getCycleDate : function(){
  143. this.actions.getCyclePerson( this.year, this.month, function( json ){
  144. json.data = json.data || [];
  145. this.cycleStartDateString = json.data.cycleStartDateString;
  146. this.cycleEndDateString = json.data.cycleEndDateString;
  147. this.cycleStartDate = new Date( this.cycleStartDateString );
  148. this.cycleEndDate = new Date( this.cycleEndDateString );
  149. //this.cycleStartDateString = "2016-02-25";
  150. //this.cycleEndDateString = "2016-03-25";
  151. //this.cycleStartDate = new Date( this.cycleStartDateString );
  152. //this.cycleEndDate = new Date( this.cycleEndDateString );
  153. this.isCrossMonth = (this.cycleStartDate.getMonth() != this.cycleEndDate.getMonth());
  154. }.bind(this), null, false )
  155. },
  156. getScheduleData : function( callback ){
  157. this.actions.listDepartmentByPerson( function( json ){
  158. if( json.data.length > 0 ){
  159. this.actions.listScheduleByDepartment( json.data[0].name, function( json ){
  160. if( json.data && json.data.length > 0 ){
  161. if(callback)callback(json.data);
  162. }else{
  163. this.actions.listScheduleByCompany( json.data[0].company, function( json ){
  164. if(callback)callback(json.data);
  165. }.bind(this))
  166. }
  167. }.bind(this))
  168. }else{
  169. if(callback)callback();
  170. }
  171. }.bind(this), null, this.userName, false)
  172. },
  173. showSchedule: function( ){
  174. if( this.scheduleNode ){
  175. this.scheduleNode.setStyle("display","block");
  176. this.scheduleNode.position({
  177. relativeTo: this.titleScheduleIconNode,
  178. position: 'bottomLeft',
  179. edge: 'upperCenter',
  180. offset:{
  181. x : -60,
  182. y : 0
  183. }
  184. });
  185. }else{
  186. this.getScheduleData(function( data ){
  187. if( !data || data.length == 0 ){
  188. this.app.notice( this.lp.unfindSchedule,"error");
  189. }else{
  190. this.scheduleNode = new Element("div", {"styles": this.css.scheduleNode}).inject(this.node);
  191. this.scheduleNode.position({
  192. relativeTo: this.titleScheduleIconNode,
  193. position: 'bottomLeft',
  194. edge: 'upperCenter',
  195. offset:{
  196. x : -60,
  197. y : 0
  198. }
  199. });
  200. this.scheduleNode.addEvent("mousedown", function(e){e.stopPropagation();});
  201. document.body.addEvent("mousedown", function(){ this.scheduleNode.setStyle("display","none")}.bind(this));
  202. var d = data[0];
  203. var table = new Element("table", {
  204. "width" : "100%", "border" : "0", "cellpadding" : "5", "cellspacing" : "0", "styles" : this.css.filterTable, "class" : "filterTable"
  205. }).inject( this.scheduleNode );
  206. var tr = new Element("tr").inject(table);
  207. new Element("td",{ "text" : this.lp.scheduleTable , "styles" : this.css.scheduleTdHead, "colspan" : "2" }).inject(tr);
  208. var tr = new Element("tr").inject(table);
  209. new Element("td",{ "text" : this.lp.schedule.workTime + ":" , "styles" : this.css.scheduleTdTitle }).inject(tr);
  210. new Element("td",{ "text" : d.onDutyTime || "" , "styles" : this.css.scheduleTdValue }).inject(tr);
  211. var tr = new Element("tr").inject(table);
  212. new Element("td",{ "text" : this.lp.schedule.offTime +":" , "styles" : this.css.scheduleTdTitle }).inject(tr);
  213. new Element("td",{ "text" : d.offDutyTime || "" , "styles" : this.css.scheduleTdValue }).inject(tr);
  214. var tr = new Element("tr").inject(table);
  215. new Element("td",{ "text" : this.lp.schedule.lateTime + ":" , "styles" : this.css.scheduleTdTitle }).inject(tr);
  216. new Element("td",{ "text" : d.lateStartTime || "" , "styles" : this.css.scheduleTdValue }).inject(tr);
  217. var tr = new Element("tr").inject(table);
  218. new Element("td",{ "text" : this.lp.schedule.leaveEarlyTime + ":" , "styles" : this.css.scheduleTdTitle }).inject(tr);
  219. new Element("td",{ "text" : d.leaveEarlyStartTime || "" , "styles" : this.css.scheduleTdValue }).inject(tr);
  220. var tr = new Element("tr").inject(table);
  221. new Element("td",{ "text" : this.lp.schedule.absenteeismTime+":" , "styles" : this.css.scheduleTdTitle }).inject(tr);
  222. new Element("td",{ "text" : d.absenceStartTime || "" , "styles" : this.css.scheduleTdValue }).inject(tr);
  223. }
  224. }.bind(this))
  225. }
  226. },
  227. reloadContent : function(){
  228. this.calendarArea.empty();
  229. this.statusColorArea.empty();
  230. this.pieChartArea.empty();
  231. this.lineChartArea.empty();
  232. this.loadData();
  233. },
  234. loadContent : function(){
  235. this.loadContentNode();
  236. this.loadData();
  237. this.setNodeScroll();
  238. this.setContentSize();
  239. },
  240. reloadChart : function(){
  241. this.pieChartArea.empty();
  242. this.lineChartArea.empty();
  243. this.loadPieChart();
  244. this.loadLineChart();
  245. },
  246. loadContentNode: function(){
  247. this.elementContentNode = new Element("div.elementContentNode", {
  248. "styles": this.css.elementContentNode
  249. }).inject(this.node);
  250. this.app.addEvent("resize", function(){
  251. this.setContentSize();
  252. this.reloadChart();
  253. }.bind(this));
  254. this.elementContentListNode = new Element("div.elementContentListNode", {
  255. "styles": this.css.elementContentListNode
  256. }).inject(this.elementContentNode);
  257. this.topContentArea = new Element("div.topContentArea",{
  258. "styles" : this.css.topContentArea
  259. }).inject(this.elementContentListNode)
  260. this.calendarArea = new Element("div.calendarArea",{
  261. "styles" : this.css.calendarArea
  262. }).inject(this.topContentArea)
  263. this.statusColorArea = new Element("div.statusColorArea",{
  264. "styles" : this.css.statusColorArea
  265. }).inject(this.topContentArea)
  266. this.pieChartArea = new Element("div.pieChartArea",{
  267. "styles" : this.css.pieChartArea
  268. }).inject(this.topContentArea)
  269. this.middleContentArea = new Element("div.middleContentArea",{
  270. "styles" : this.css.middleContentArea
  271. }).inject(this.elementContentListNode)
  272. this.lineChartArea = new Element("div.lineChartArea",{
  273. "styles" : this.css.lineChartArea
  274. }).inject(this.middleContentArea)
  275. },
  276. loadData : function(){
  277. this.listDetailFilterUser( function( data ){
  278. this.detailData = data || {};
  279. this.anaylyseDetail();
  280. this.loadStatusColorNode();
  281. this.loadPieChart();
  282. this.loadLineChart();
  283. this.loadHolidayData(function(){
  284. this.loadCalendarContent();
  285. //if(!this.titleInforNode)this.loadTitleInforNode();
  286. }.bind(this));
  287. }.bind(this), this.userName, this.year, this.month )
  288. },
  289. loadHolidayData : function( callback ){
  290. if( this.holidayData && this.holidayData[ this.year ] ) {
  291. //this.loadCalendarContent();
  292. if(callback)callback();
  293. }else{
  294. this.listHolidayFilter( function(data){
  295. var dates = {
  296. workdays : [],
  297. holidays : [],
  298. names : []
  299. }
  300. data.each( function(d){
  301. if( !dates.names.contains(d.configName) ){
  302. dates.names.push( d.configName )
  303. }
  304. if( !dates[d.configName] ){
  305. dates[d.configName] = {};
  306. dates[d.configName].holidays = [];
  307. dates[d.configName].workdays = [];
  308. }
  309. if( d.configType == "Holiday" ){
  310. if( d.configDate == this.todayDate ){
  311. this.todayHloidayName = d.configName;
  312. }
  313. dates.holidays.push( d.configDate )
  314. dates[d.configName].holidays.push( d.configDate )
  315. }else{
  316. if( d.configDate == this.todayDate ){
  317. this.todayIsWorkDay = true;
  318. }
  319. dates.workdays.push( d.configDate )
  320. dates[d.configName].workdays.push( d.configDate )
  321. }
  322. })
  323. this.holidayData[this.year] = dates;
  324. if(callback)callback();
  325. }.bind(this), null, this.year)
  326. }
  327. },
  328. loadCalendarContent : function(){
  329. //this.calendarTitle = new Element("div.calendarTitle",{
  330. // "styles" : this.css.calendarTitle,
  331. // "text" : this.lp.index.attendanceCalendar
  332. //}).inject(this.calendarArea)
  333. this.canlendarToolbar = new Element("div.canlendarToolbar",{
  334. "styles" : this.css.canlendarToolbar
  335. }).inject(this.calendarArea)
  336. this.canlendarToolbarText = new Element("div",{
  337. "styles" : this.css.canlendarToolbarText,
  338. "text" : this.lp.index.attendanceCalendar
  339. }).inject(this.canlendarToolbar)
  340. this.calendarDate = this.date.clone();
  341. if( this.isCrossMonth ){
  342. this.calendarRightArrowNode = new Element("div",{
  343. "styles" : this.css.calendarRightArrowNode
  344. }).inject(this.canlendarToolbar);
  345. this.calendarCurrentMonthNode = new Element("div",{
  346. "styles" : this.css.calendarCurrentMonthNode,
  347. "text" : (this.calendarDate.getMonth()+1)+"月"
  348. }).inject(this.canlendarToolbar);
  349. this.calendarLeftArrowNode = new Element("div",{
  350. "styles" : this.css.calendarLeftArrowNode
  351. }).inject(this.canlendarToolbar);
  352. this.calendarLeftArrowNode.addEvents({
  353. //"mouseover": function(){this.calendarLeftArrowNode.setStyles(this.css.calendarLeftArrowNode_over);}.bind(this),
  354. // "mouseout": function(){this.calendarLeftArrowNode.setStyles(this.css.calendarLeftArrowNode);}.bind(this),
  355. //"mousedown": function(){this.calendarLeftArrowNode.setStyles(this.css.calendarLeftArrowNode_down);}.bind(this),
  356. //"mouseup": function(){this.calendarLeftArrowNode.setStyles(this.css.calendarLeftArrowNode_over);}.bind(this),
  357. "click": function(){this.changeCalendarMonthPrev();}.bind(this)
  358. });
  359. this.calendarRightArrowNode.addEvents({
  360. //"mouseover": function(){this.calendarRightArrowNode.setStyles(this.css.calendarRightArrowNode_over);}.bind(this),
  361. //"mouseout": function(){this.calendarRightArrowNode.setStyles(this.css.calendarRightArrowNode);}.bind(this),
  362. //"mousedown": function(){this.calendarRightArrowNode.setStyles(this.css.calendarRightArrowNode_down);}.bind(this),
  363. //"mouseup": function(){this.calendarRightArrowNode.setStyles(this.css.calendarRightArrowNode_over);}.bind(this),
  364. "click": function(){this.changeCalendarMonthNext();}.bind(this)
  365. });
  366. this.switchCalendarArrow( this.calendarDate );
  367. }
  368. //this.loadHolidayNode();
  369. this.calendarNode = new Element("div.calendarNode",{
  370. "styles" : this.css.calendarNode
  371. }).inject(this.calendarArea)
  372. this.calendar = new MWF.xApplication.Attendance.Calendar(this.calendarNode, this,
  373. {
  374. "holiday" :this.holidayData[this.year],
  375. "detail" :this.detailData,
  376. "eventData" : this.eventData
  377. },
  378. {
  379. date : this.date,
  380. cycleStart : this.cycleStartDate,
  381. cycleEnd : this.cycleEndDate
  382. }
  383. );
  384. this.calendar.load();
  385. },
  386. switchCalendarArrow : function( date ){
  387. var firstDate = new Date( date.getFullYear() , date.getMonth() , 1, 0, 0, 0 );
  388. if( firstDate <= this.cycleStartDate ){
  389. this.calendarLeftArrowNode.setStyles( this.css.calendarLeftArrowNode_disable );
  390. this.calendarLeftDisable = true;
  391. }else{
  392. this.calendarLeftArrowNode.setStyles( this.css.calendarLeftArrowNode );
  393. this.calendarLeftDisable = false;
  394. }
  395. //alert( "firstDate="+firstDate.format("db") + " " +"cycleStartDate="+ this.cycleStartDate.format("db"))
  396. var lastDate = new Date( date.getFullYear(),date.getMonth()+1, 0, 23, 59, 59);
  397. if( lastDate >= this.cycleEndDate ){
  398. this.calendarRightArrowNode.setStyles( this.css.calendarRightArrowNode_disable );
  399. this.calendarRightDisable = true;
  400. }else{
  401. this.calendarRightArrowNode.setStyles( this.css.calendarRightArrowNode );
  402. this.calendarRightDisable = false;
  403. }
  404. },
  405. changeCalendarMonthPrev: function(){
  406. if( this.calendarLeftDisable )return ;
  407. jQuery(this.calendarNode).fullCalendar( 'prev' );
  408. this.calendarDate.decrement("month", 1);
  409. this.calendarCurrentMonthNode.set("text",(this.calendarDate.getMonth()+1)+"月");
  410. this.switchCalendarArrow( this.calendarDate );
  411. },
  412. changeCalendarMonthNext: function(){
  413. if( this.calendarRightDisable )return ;
  414. jQuery(this.calendarNode).fullCalendar( 'next' );
  415. this.calendarDate.increment("month", 1);
  416. this.calendarCurrentMonthNode.set("text",(this.calendarDate.getMonth()+1)+"月");
  417. this.switchCalendarArrow( this.calendarDate );
  418. //this.date.increment("month", 1);
  419. //this.setDate( this.date );
  420. //var text = this.date.format(this.app.lp.dateFormatMonth);
  421. //this.titleTextNode.set("text", text);
  422. //this.reloadContent();
  423. },
  424. listHolidayFilter : function( callback, name,year,month ){
  425. /*{'q_Year':'2016','q_Name':'五一劳动节','q_Month':'03'}*/
  426. var filter = {};
  427. if( name )filter.q_Name = name;
  428. if( year )filter.q_Year = year;
  429. if( month ){
  430. filter.q_Month = month.toString().length == 2 ? month : "0"+month;
  431. }else{
  432. filter.q_Month = "(0)"
  433. }
  434. this.actions.listHolidayFilter( filter, function(json){
  435. if( callback )callback(json.data);
  436. }.bind(this))
  437. },
  438. loadHolidayNode : function() {
  439. this.holidayAreaNode = new Element("div.holidayAreaNode",{
  440. "styles" : this.css.holidayAreaNode
  441. }).inject(this.canlendarToolbar)
  442. this.holidayActionNode = new Element("div",{
  443. "styles" : this.css.holidayActionNode
  444. }).inject(this.holidayAreaNode)
  445. this.holidayActionTextNode = new Element("div",{
  446. "styles" : this.css.holidayActionTextNode,
  447. "text" : this.lp.holiday.holidaySchedule
  448. }).inject(this.holidayActionNode)
  449. this.holidayActionIconNode = new Element("div",{
  450. "styles" : this.css.holidayActionIconNode,
  451. }).inject(this.holidayActionNode)
  452. this.holidayActionNode.addEvents({
  453. "mouseover": function(){this.holidayActionIconNode.setStyles(this.css.holidayActionIconNode_over);}.bind(this),
  454. "mouseout": function(){this.holidayActionIconNode.setStyles(this.css.holidayActionIconNode);}.bind(this),
  455. "click" : function( ev ){
  456. this.switchHoliday( ev.target )
  457. ev.stopPropagation();
  458. }.bind(this)
  459. })
  460. },
  461. switchHoliday: function( el ){
  462. var _self = this;
  463. var flag = false;
  464. if(this.holidayListNode ){
  465. if(this.holidayListNode.retrieve("year") == this.year){
  466. flag = true;
  467. }else{
  468. this.holidayListNode.destroy();
  469. }
  470. }
  471. if(flag){
  472. var parentNode = el.getParent();
  473. this.holidayListNode.inject(parentNode);
  474. if( this.holidayListNode.getStyle("display") == "block" ){
  475. this.holidayListNode.setStyle("display","none");
  476. }else{
  477. this.holidayListNode.setStyle("display","block");
  478. }
  479. }else{
  480. var holidays = this.holidayData[this.year];
  481. var holidayListNode = this.holidayListNode = new Element("div",{
  482. "styles" : this.css.holidayListNode
  483. })
  484. this.holidayListNode.store("year",this.year);
  485. this.app.content.addEvent("click",function(){
  486. _self.holidayListNode.setStyle("display","none");
  487. })
  488. holidays.names.each(function( n ){
  489. var holidayNode = new Element("div",{
  490. "text" : n,
  491. "styles" : this.css.holidayNode
  492. }).inject(holidayListNode);
  493. holidayNode.store("holidays", holidays[n].holidays );
  494. holidayNode.store("workdays", holidays[n].workdays );
  495. holidayNode.addEvents({
  496. "mouseover" : function(){
  497. this.setStyles(_self.css.holidayNode_over);
  498. },
  499. "mouseout" : function(){
  500. this.setStyles(_self.css.holidayNode);
  501. },
  502. "click" : function(e){
  503. _self.holidayListNode.setStyle("display","none");
  504. var holidays = this.retrieve("holidays");
  505. var workdays = this.retrieve("workdays");
  506. this.setStyles(_self.css.holidayNode);
  507. _self.changeMonthTo( new Date((holidays || workdays )[0]) )
  508. //jQuery(_self.calendarNode).fullCalendar( 'gotoDate', (holidays || workdays )[0] );
  509. e.stopPropagation();
  510. }
  511. })
  512. }.bind(this))
  513. var parentNode = el.getParent();
  514. this.holidayListNode.inject(parentNode);
  515. }
  516. },
  517. loadStatusColorNode : function(){
  518. this.statusColorTable = new Element("table",{
  519. "styles" : this.css.statusColorTable
  520. }).inject(this.statusColorArea)
  521. for(var status in this.statusColor){
  522. var tr = new Element("tr",{
  523. "styles" : this.css.statusColorTr
  524. }).inject(this.statusColorTable)
  525. var td = new Element("td",{
  526. "styles" : this.css.statusColorTd
  527. }).inject(tr)
  528. td.setStyle("background-color",this.statusColor[status]);
  529. var tr = new Element("tr",{
  530. "styles" : this.css.statusTextTr
  531. }).inject(this.statusColorTable)
  532. var td = new Element("td",{
  533. "styles" : this.css.statusTextTd,
  534. "text" : this.lp[status] +this.totalData[status]+"天" + ( this.rateData[status] ? "("+this.rateData[status]+")" : "" )
  535. }).inject(tr)
  536. }
  537. },
  538. loadPieChart : function(){
  539. //this.pieChartTitle = new Element("div.pieChartTitle",{
  540. // "styles" : this.css.pieChartTitle,
  541. // "text" : this.lp.index.pieChart
  542. //}).inject(this.pieChartArea)
  543. this.pieChartNode = new Element("div.pieChartNode",{
  544. "styles" : this.css.pieChartNode
  545. }).inject(this.pieChartArea)
  546. this.pieChart = new MWF.xApplication.Attendance.Echarts(this.pieChartNode, this, this.totalData, this.css);
  547. this.pieChart.load();
  548. },
  549. loadLineChart : function(){
  550. //this.lineChartTitle = new Element("div.lineChartTitle",{
  551. // "styles" : this.css.lineChartTitle,
  552. // "text" : this.lp.index.lineChart
  553. //}).inject(this.lineChartArea)
  554. this.lineChartNode = new Element("div.lineChartNode",{
  555. "styles" : this.css.lineChartNode
  556. }).inject(this.lineChartArea)
  557. //this.lineChart = new MWF.xApplication.Attendance.Echarts(this.lineChartNode, this.app, this.actions, this.css, {"type":"line"});
  558. //this.lineChart.load();
  559. this.lineChart = new MWF.xApplication.Attendance.Echarts(this.lineChartNode, this, this.detailData, {
  560. "type":"line",
  561. "date":this.date,
  562. "cycleStart" : new Date( this.cycleStartDate.getFullYear(), this.cycleStartDate.getMonth(), this.cycleStartDate.getDate() ),
  563. "cycleEnd" : new Date( this.cycleEndDate.getFullYear(), this.cycleEndDate.getMonth(), this.cycleEndDate.getDate() )
  564. });
  565. this.lineChart.load();
  566. },
  567. listDetailFilterUser :function( callback, name, year, month ){
  568. //{'q_empName':'林玲','q_year':'2016','q_month':'03'}
  569. var filter = {};
  570. if( name )filter.q_empName = name;
  571. if( year )filter.cycleYear = year;
  572. if( month )filter.cycleMonth = month.toString().length == 2 ? month : "0"+month;
  573. this.actions.listDetailFilterUser( filter, function(json){
  574. var data = json.data || [];
  575. data.sort( function( a, b ){
  576. return parseInt( a.recordDateString.replace(/-/g,"") ) - parseInt( b.recordDateString.replace(/-/g,"") );
  577. //return a.recordDateString - b.recordDateString
  578. })
  579. if( callback )callback(data);
  580. }.bind(this))
  581. },
  582. setContentSize: function(){
  583. var toolbarSize = this.toolbarNode ? this.toolbarNode.getSize() : {"x":0,"y":0};
  584. var titlebarSize = this.titleNode ? this.titleNode.getSize() : {"x":0,"y":0};
  585. var nodeSize = this.node.getSize();
  586. var pt = this.elementContentNode.getStyle("padding-top").toFloat();
  587. var pb = this.elementContentNode.getStyle("padding-bottom").toFloat();
  588. //var filterSize = this.filterNode.getSize();
  589. var filterConditionSize = this.filterConditionNode ? this.filterConditionNode.getSize() : {"x":0,"y":0};
  590. var height = nodeSize.y-toolbarSize.y-pt-pb-filterConditionSize.y-titlebarSize.y;
  591. this.elementContentNode.setStyle("height", ""+height+"px");
  592. },
  593. setNodeScroll: function(){
  594. var _self = this;
  595. MWF.require("MWF.widget.ScrollBar", function(){
  596. new MWF.widget.ScrollBar(this.elementContentNode, {
  597. "indent": false,"style":"xApp_TaskList", "where": "before", "distance": 30, "friction": 4, "axis": {"x": false, "y": true},
  598. "onScroll": function(y){
  599. }
  600. });
  601. }.bind(this));
  602. },
  603. anaylyseDetail : function(){
  604. var events = [];
  605. var totals = {
  606. levelAsked : 0,
  607. noSign : 0,
  608. late : 0,
  609. appealSuccess : 0,
  610. //leaveEarly : 0,
  611. lackOfTime : 0,
  612. abNormalDuty : 0,
  613. normal : 0
  614. };
  615. this.detailData.each( function( d ){
  616. if( this.isAskForLevel(d,"am") ){
  617. events.push( { text:this.lp.levelAsked, start: d.recordDateString, backgroundColor :this.statusColor.levelAsked } )
  618. totals.levelAsked = totals.levelAsked + 0.5
  619. }else if( this.isAppealSuccess(d,"am")){
  620. events.push( { text: this.lp.appealSuccess, start: d.recordDateString, backgroundColor :this.statusColor.appealSuccess } )
  621. totals.appealSuccess = totals.appealSuccess + 0.5
  622. }else if( this.isAbsent(d,"am")){
  623. events.push( { text: this.lp.noSign, start: d.recordDateString, backgroundColor :this.statusColor.noSign } )
  624. totals.noSign = totals.noSign + 0.5
  625. }else if( this.isLate(d,"am")) {
  626. events.push({
  627. text: this.lp.late + ',' + this.lp.signTime + ':' + d.onDutyTime, //+ "迟到时长" + d.lateTimeDuration,
  628. start: d.recordDateString,
  629. backgroundColor: this.statusColor.late
  630. })
  631. totals.late = totals.late + 0.5
  632. }else if( this.isLackOfTime(d,"am")){
  633. events.push( { text: this.lp.lackOfTime + ',' + this.lp.signTime + ':' + d.onDutyTime, start: d.recordDateString, backgroundColor :this.statusColor.lackOfTime } )
  634. totals.lackOfTime = totals.lackOfTime + 0.5
  635. }else if( this.isAbnormalDuty(d,"am")){
  636. events.push( { text: this.lp.abNormalDuty + ',' + this.lp.signTime + ':' + d.onDutyTime, start: d.recordDateString, backgroundColor :this.statusColor.abNormalDuty } )
  637. totals.abNormalDuty = totals.abNormalDuty + 0.5
  638. }else if( this.isHoliday(d, "am") ){
  639. return;
  640. }else if( this.isWeekend(d, "am") ){
  641. return;
  642. }else{
  643. totals.normal = totals.normal + 0.5
  644. events.push( { text: this.lp.normal + ','+this.lp.signTime +':' + d.onDutyTime, start: d.recordDateString, backgroundColor :this.statusColor.normal } )
  645. }
  646. if( this.isAskForLevel(d,"pm") ){
  647. totals.levelAsked = totals.levelAsked + 0.5
  648. events.push( { text: '请假或外出报备', start: d.recordDateString, backgroundColor :this.statusColor.levelAsked } )
  649. }else if( this.isAppealSuccess(d,"pm")){
  650. events.push( { text: this.lp.appealSuccess, start: d.recordDateString, backgroundColor :this.statusColor.appealSuccess } )
  651. totals.appealSuccess = totals.appealSuccess + 0.5
  652. //}else if( this.isLeaveEarlier(d,"pm")) {
  653. // events.push({
  654. // text: '早退,打卡时间:' + d.offDutyTime, // + "早退时长" + d.leaveEarlierTimeDuration,
  655. // start: d.recordDateString,
  656. // backgroundColor: this.statusColor.leaveEarly
  657. // })
  658. // totals.leaveEarly = totals.leaveEarly + 0.5
  659. }else if( this.isAbsent(d,"pm")){
  660. totals.noSign = totals.noSign + 0.5
  661. events.push( { text: '缺勤', start: d.recordDateString, backgroundColor :this.statusColor.noSign } )
  662. }else if( this.isLackOfTime(d,"pm")){
  663. events.push( { text: this.lp.lackOfTime + ',' + this.lp.signTime + ':' + d.offDutyTime, start: d.recordDateString, backgroundColor :this.statusColor.lackOfTime } )
  664. totals.lackOfTime = totals.lackOfTime + 0.5
  665. }else if( this.isAbnormalDuty(d,"pm")){
  666. events.push( { text: this.lp.abNormalDuty + ',' + this.lp.signTime + ':' + d.offDutyTime, start: d.recordDateString, backgroundColor :this.statusColor.abNormalDuty } )
  667. totals.abNormalDuty = totals.abNormalDuty + 0.5
  668. }else if( this.isHoliday(d, "pm") ){
  669. return;
  670. }else if( this.isWeekend(d, "pm") ){
  671. return;
  672. }else{
  673. totals.normal = totals.normal + 0.5
  674. events.push( { text: '出勤,打卡时间:'+ d.offDutyTime, start: d.recordDateString, backgroundColor :this.statusColor.normal } )
  675. }
  676. }.bind(this) )
  677. this.totalData = totals;
  678. var total = 0;
  679. for( var n in totals ){
  680. total += totals[n];
  681. }
  682. this.rateData = {
  683. levelAsked : (!totals.levelAsked || !total) ? 0 : ((totals.levelAsked/total * 100).toFixed(2) + "%"),
  684. noSign : (!totals.noSign || !total) ? 0 : ((totals.noSign/total * 100).toFixed(2) + "%"),
  685. late : (!totals.late || !total) ? 0 : ((totals.late/total * 100).toFixed(2) + "%"),
  686. //leaveEarly : (!totals.leaveEarly || !total) ? 0 : ((totals.leaveEarly/total* 100).toFixed(2) + "%"),
  687. lackOfTime : (!totals.lackOfTime || !total) ? 0 : ((totals.lackOfTime/total * 100).toFixed(2) + "%"),
  688. abNormalDuty : (!totals.abNormalDuty || !total) ? 0 : ((totals.abNormalDuty/total* 100).toFixed(2) + "%"),
  689. normal : (!totals.normal || !total) ? 0 : ((totals.normal/total* 100).toFixed(2) + "%"),
  690. appealSuccess : (!totals.appealSuccess || !total) ? 0 : ((totals.appealSuccess/total * 100).toFixed(2) + "%")
  691. }
  692. this.eventData = events;
  693. },
  694. isAppealSuccess : function( d, ap ){
  695. return d.appealStatus == 9
  696. },
  697. isAskForLevel : function( d , ap ){
  698. if( ap == "am" ){
  699. return d.isGetSelfHolidays && ( d.selfHolidayDayTime == "全天" || d.selfHolidayDayTime == "上午" )
  700. }else{
  701. return d.isGetSelfHolidays && ( d.selfHolidayDayTime == "全天" || d.selfHolidayDayTime == "下午" )
  702. }
  703. },
  704. isAbsent : function(d , ap ){
  705. if( ap == "am" ){
  706. return d.isAbsent && ( d.absentDayTime == "全天" || d.absentDayTime == "上午" )
  707. }else{
  708. return d.isAbsent && ( d.absentDayTime == "全天" || d.absentDayTime == "下午" )
  709. }
  710. },
  711. isLate : function(d, ap ){
  712. return d.isLate
  713. },
  714. //isLeaveEarlier : function( d ){
  715. // return d.isLeaveEarlier
  716. //},
  717. isWorkOvertime : function( d, ap){
  718. return d.isWorkOvertime
  719. },
  720. isLackOfTime : function( d, ap){
  721. return d.isLackOfTime
  722. },
  723. isAbnormalDuty : function(d , ap ){
  724. if( ap == "am" ){
  725. return d.isAbnormalDuty && ( d.abnormalDutyDayTime == "全天" || d.abnormalDutyDayTime == "上午" )
  726. }else{
  727. return d.isAbnormalDuty && ( d.abnormalDutyDayTime == "全天" || d.abnormalDutyDayTime == "下午" )
  728. }
  729. },
  730. isHoliday : function( d, ap ){
  731. if( ap == "am" ){
  732. return d.isHoliday && (!d.onDutyTime || d.onDutyTime == "")
  733. }else{
  734. return d.isHoliday && (!d.offDutyTime || d.offDutyTime == "")
  735. }
  736. },
  737. isWeekend : function( d, ap ){
  738. if(d.isWorkday )return false;
  739. if( ap == "am" ){
  740. return d.isWeekend && (!d.onDutyTime || d.onDutyTime == "")
  741. }else{
  742. return d.isWeekend && (!d.offDutyTime || d.offDutyTime == "")
  743. }
  744. },
  745. toFixed: function (num, d) {
  746. var s=num+"";
  747. if(!d)d=0;
  748. if(s.indexOf(".")==-1)s+=".";
  749. s+=new Array(d+1).join("0");
  750. if(new RegExp("^(-|\\+)?(\\d+(\\.\\d{0,"+(d+1)+"})?)\\d*$").test(s)){
  751. var s="0"+RegExp.$2,pm=RegExp.$1,a=RegExp.$3.length,b=true;
  752. if(a==d+2){
  753. a=s.match(/\d/g);
  754. if(parseInt(a[a.length-1])>4){
  755. for(var i=a.length-2;i>=0;i--){
  756. a[i]=parseInt(a[i])+1;
  757. if(a[i]==10){
  758. a[i]=0;
  759. b=i!=1;
  760. }else break;
  761. }
  762. }
  763. s=a.join("").replace(new RegExp("(\\d+)(\\d{"+d+"})\\d$"),"$1.$2");
  764. }if(b)s=s.substr(1);
  765. return (pm+s).replace(/\.$/,"");
  766. }return this+"";
  767. }
  768. });