ImportExplorer.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. MWF.xDesktop.requireApp("Attendance", "Explorer", null, false);
  2. MWF.xDesktop.requireApp("Template", "MPopupForm", null, false);
  3. MWF.xDesktop.requireApp("Template", "MDomItem", null, false);
  4. MWF.xDesktop.requireApp("Selector", "package", null, false);
  5. MWF.xApplication.Attendance.ImportExplorer = new Class({
  6. Extends: MWF.xApplication.Attendance.Explorer,
  7. Implements: [Options, Events],
  8. initialize: function(node, app, actions, options){
  9. this.setOptions(options);
  10. this.app = app;
  11. this.path = "../x_component_Attendance/$ImportExplorer/";
  12. this.cssPath = "../x_component_Attendance/$ImportExplorer/"+this.options.style+"/css.wcss";
  13. this._loadCss();
  14. this.actions = actions;
  15. this.node = $(node);
  16. this.initData();
  17. if (!this.personActions) this.personActions = new MWF.xAction.org.express.RestActions();
  18. },
  19. loadView : function(){
  20. this.view = new MWF.xApplication.Attendance.ImportExplorer.View(this.elementContentNode, this.app,this, this.viewData, this.options.searchKey );
  21. this.view.load();
  22. this.setContentSize();
  23. },
  24. createDocument: function(){
  25. if(this.view)this.view._createDocument();
  26. },
  27. importExcel : function(){
  28. //this.importer = new MWF.xApplication.Attendance.ImportExplorer.Importer( this );
  29. //this.importer.upload();
  30. this.upload();
  31. },
  32. upload : function(){
  33. if (!this.uploadFileAreaNode){
  34. this.uploadFileAreaNode = new Element("div");
  35. var html = "<input name=\"file\" type=\"file\"/>";
  36. this.uploadFileAreaNode.set("html", html);
  37. this.fileUploadNode = this.uploadFileAreaNode.getFirst();
  38. this.fileUploadNode.addEvent("change", function(){
  39. var files = fileNode.files;
  40. if (files.length){
  41. for (var i = 0; i < files.length; i++) {
  42. var file = files.item(i);
  43. var tmp = file.name.split(".");
  44. this.uploadFileName = file.name;
  45. if( tmp[tmp.length-1].toLowerCase() != "xls" && tmp[tmp.length-1].toLowerCase() != "xlsx" ){
  46. this.app.notice("请导入excel文件!","error");
  47. return;
  48. }
  49. var formData = new FormData();
  50. formData.append('file', file);
  51. this.actions.uploadAttachment( function( json ){
  52. var id = json.id;
  53. this.actions.getAttachmentInfo( id, function( info ){
  54. var progress = new MWF.xApplication.Attendance.ImportExplorer.Progress(id, this.actions);
  55. progress.load( function(){
  56. var form = new MWF.xApplication.Attendance.ImportExplorer.Result(this, info.data, { id : id }, { app : this.app , actions : this.app.restActions, css : {} });
  57. form.open();
  58. this.view.reload();
  59. }.bind(this))
  60. }.bind(this));
  61. }.bind(this), function(xhr, text, error){
  62. var errorText = error;
  63. if (xhr) errorText = xhr.responseText;
  64. this.app.notice( errorText,"error");
  65. }.bind(this), formData, file);
  66. }
  67. }
  68. }.bind(this));
  69. }
  70. var fileNode = this.uploadFileAreaNode.getFirst();
  71. fileNode.click();
  72. },
  73. checkData : function(){
  74. var selector = new MWF.xApplication.Attendance.ImportExplorer.YearMonthSelctor(this);
  75. selector.edit();
  76. },
  77. analyseData : function(){
  78. this.actions.analyseDetail("0","0",function(){
  79. this.app.notice("分析考勤数据成功","success")
  80. }.bind(this))
  81. },
  82. staticData : function(){
  83. this.actions.staticAllDetail(function(){
  84. this.app.notice("统计考勤数据成功","success")
  85. }.bind(this))
  86. },
  87. downloadTemplate : function(){
  88. window.open( o2.filterUrl(this.path + encodeURIComponent( "dataTemplate.xls" ), "_blank" ))
  89. },
  90. showDescription: function( el ){
  91. if( this.descriptionNode ){
  92. this.descriptionNode.setStyle("display","block");
  93. this.descriptionNode.position({
  94. relativeTo: el,
  95. position: 'bottomLeft',
  96. edge: 'upperCenter',
  97. offset:{
  98. x : -60,
  99. y : 0
  100. }
  101. });
  102. }else{
  103. this.descriptionNode = new Element("div", {"styles": this.css.descriptionNode}).inject(this.node);
  104. this.descriptionNode.position({
  105. relativeTo: el,
  106. position: 'bottomLeft',
  107. edge: 'upperCenter',
  108. offset:{
  109. x : -60,
  110. y : 0
  111. }
  112. });
  113. this.descriptionNode.addEvent("mousedown", function(e){e.stopPropagation();});
  114. document.body.addEvent("mousedown", function(){ this.descriptionNode.setStyle("display","none")}.bind(this));
  115. var table = new Element("table", {
  116. "width" : "100%", "border" : "0", "cellpadding" : "5", "cellspacing" : "0", "styles" : this.css.filterTable, "class" : "filterTable"
  117. }).inject( this.descriptionNode );
  118. var tr = new Element("tr").inject(table);
  119. new Element("td",{ "text" : "数据导入步骤" , "styles" : this.css.descriptionTdHead }).inject(tr);
  120. var tr = new Element("tr").inject(table);
  121. new Element("td",{ "text" :"1、下载Excel模板,根据模板格式填写考勤数据;" , "styles" : this.css.descriptionTdValue }).inject(tr);
  122. var tr = new Element("tr").inject(table);
  123. new Element("td",{ "text" : "2、点击导入考勤数据按钮,选择考勤数据并确定,系统将校验考勤数据是否正确并导入数据;" , "styles" : this.css.descriptionTdValue }).inject(tr);
  124. var tr = new Element("tr").inject(table);
  125. new Element("td",{ "text" : "3、点击核对考勤数据按钮,选择需要核对的年度和月份,系统将核对需要考勤的人员的数据;" , "styles" : this.css.descriptionTdValue }).inject(tr);
  126. var tr = new Element("tr").inject(table);
  127. new Element("td",{ "text" : "4、点击分析考勤数据按钮,系统将生成出勤明细数据;" , "styles" : this.css.descriptionTdValue }).inject(tr);
  128. var tr = new Element("tr").inject(table);
  129. new Element("td",{ "text" : "5、点击统计考勤数据按钮,系统将生成个人、部门、公司的出勤率统计。" , "styles" : this.css.descriptionTdValue }).inject(tr);
  130. }
  131. }
  132. });
  133. MWF.xApplication.Attendance.ImportExplorer.View = new Class({
  134. Extends: MWF.xApplication.Attendance.Explorer.View,
  135. _createItem: function(data){
  136. return new MWF.xApplication.Attendance.ImportExplorer.Document(this.table, data, this.explorer, this);
  137. },
  138. _getCurrentPageData: function(callback, count){
  139. this.actions.listAttachmentInfo(function(json){
  140. if (callback) callback(json);
  141. });
  142. },
  143. _removeDocument: function(document, all){
  144. this.actions.deleteAttachment(document.id, function(json){
  145. this.explorer.view.reload();
  146. this.app.notice(this.app.lp.deleteDocumentOK, "success");
  147. }.bind(this));
  148. },
  149. _createDocument: function(){
  150. //var permission = new MWF.xApplication.Attendance.ImportExplorer.Importer(this.explorer);
  151. //permission.create();
  152. },
  153. _openDocument: function( documentData ){
  154. this.actions.getAttachmentStream( documentData.id )
  155. }
  156. });
  157. MWF.xApplication.Attendance.ImportExplorer.Document = new Class({
  158. Extends: MWF.xApplication.Attendance.Explorer.Document,
  159. openVaild : function( e ){
  160. //this.importer = new MWF.xApplication.Attendance.ImportExplorer.Importer( this );
  161. },
  162. openResult: function(){
  163. var form = new MWF.xApplication.Attendance.ImportExplorer.Result(this, this.data, { id : this.data.id }, { app : this.app , actions : this.app.restActions, css : {} });
  164. form.open();
  165. }
  166. });
  167. MWF.xApplication.Attendance.ImportExplorer.YearMonthSelctor = new Class({
  168. Extends: MPopupForm,
  169. options : {
  170. "style" : "attendance",
  171. "width": 500,
  172. "height": 300,
  173. "hasTop" : true,
  174. "hasBottom" : true,
  175. "title" : "选择核对月份",
  176. "draggable" : true,
  177. "closeAction" : true,
  178. "false" : true
  179. },
  180. _createTableContent: function(){
  181. this.formTableContainer.setStyles({
  182. "width" : "300px"
  183. });
  184. var html = "<table width='100%' bordr='0' cellpadding='5' cellspacing='0' styles='formTable'>"+
  185. //"<tr><td colspan='2' styles='formTableHead'>选择核对月份</td></tr>" +
  186. "<tr><td styles='formTabelTitle' lable='cycleYear'></td>"+
  187. " <td styles='formTableValue' item='cycleYear'></td></tr>" +
  188. "<tr><td styles='formTabelTitle' lable='cycleMonth'></td>"+
  189. " <td styles='formTableValue' item='cycleMonth'></td></tr>" +
  190. "</table>";
  191. this.formTableArea.set("html",html);
  192. MWF.xDesktop.requireApp("Template", "MForm", function(){
  193. this.form = new MForm( this.formTableArea, {}, {
  194. isEdited : this.isEdited || this.isNew,
  195. itemTemplate : {
  196. cycleYear : {
  197. text:"年度",
  198. type : "select",
  199. selectValue : function(){
  200. var years = []; d = new Date();
  201. for(var i=0 ; i<5; i++){
  202. years.push(d.getFullYear());
  203. d.setFullYear(d.getFullYear()-1)
  204. }
  205. return years;
  206. }
  207. },
  208. cycleMonth : {
  209. text:"月份",
  210. type : "select",
  211. defaultValue : function(){ return new Date().getMonth(); },
  212. selectValue : ["1","2","3","4","5","6","7","8","9","10","11","12"]
  213. }
  214. }
  215. }, this.app);
  216. this.form.load();
  217. }.bind(this), true);
  218. },
  219. _ok: function( data, callback ){
  220. this.app.restActions.checkDetail( data.cycleYear, data.cycleMonth, function(json){
  221. this.app.notice("考勤数据核对成功");
  222. this.close();
  223. }.bind(this));
  224. }
  225. });
  226. MWF.xApplication.Attendance.ImportExplorer.Result = new Class({
  227. Extends: MPopupForm,
  228. options : {
  229. "style" : "attendance",
  230. "width": 800,
  231. "height": 600,
  232. "hasTop" : true,
  233. "hasBottom" : false,
  234. "title" : "考勤数据导入结果",
  235. "draggable" : true,
  236. "closeAction" : true,
  237. "hasScroll" : true,
  238. "closeByClickMask" : true,
  239. "id" : ""
  240. },
  241. _createTableContent: function(){
  242. this.actions.getImportStatusDetail( this.options.id, function( json ){
  243. this.checkData = json.data;
  244. this.createImportContent();
  245. }.bind(this));
  246. },
  247. createImportContent : function(){
  248. if( this.checkData.errorCount == 0 ){
  249. var text ="您上传的文件:“" + this.data.fileName + "”已经成功导入。下面显示其中的"+this.checkData.detailList.length+"条:" ;
  250. } else{
  251. var text ="您上传的文件:“" + this.data.fileName + "”未通过校验,有"+ this.checkData.errorCount +"条错误数据。请修改后重新导入。下面显示其中的"+this.checkData.detailList.length+"条:" ;
  252. }
  253. this.formDescriptionNode = new Element("div", {
  254. "styles": this.css.formDescriptionNode,
  255. "text" : text
  256. }).inject(this.formTableArea);
  257. var table = new Element("table", {
  258. "width" : "100%", "border" : "", "cellpadding" : "5", "cellspacing" : "0", "styles" : this.css.editTable, "class" : "editTable"
  259. }).inject( this.formTableArea );
  260. var tr = new Element("tr").inject(table);
  261. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "行号" }).inject(tr);
  262. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "员工号" }).inject(tr);
  263. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "员工名字" }).inject(tr);
  264. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "日期" }).inject(tr);
  265. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "上午上班打卡时间" }).inject(tr);
  266. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "上午下班打卡时间" }).inject(tr);
  267. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "下午上班打卡时间" }).inject(tr);
  268. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "下午下班打卡时间" }).inject(tr);
  269. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "检查结果" }).inject(tr);
  270. var td = new Element("td", { "styles" : this.css.editTableTitle, "text" : "描述" }).inject(tr);
  271. td.setStyle( "width" , "300px" );
  272. this.checkData.detailList.each(function( d ){
  273. var tr = new Element("tr").inject(table);
  274. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.curRow }).inject(tr);
  275. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.employeeNo }).inject(tr);
  276. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.employeeName.split('@')[0] }).inject(tr);
  277. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.recordDateString }).inject(tr);
  278. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.onDutyTime }).inject(tr);
  279. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.morningOffDutyTime }).inject(tr);
  280. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.afternoonOnDutyTime }).inject(tr);
  281. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.offDutyTime }).inject(tr);
  282. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.checkStatus == "error" ? "错误" : "正确" }).inject(tr);
  283. var td = new Element("td", { "styles" : this.css.editTableValue , "text": d.description }).inject(tr);
  284. }.bind(this))
  285. }
  286. });
  287. MWF.xApplication.Attendance.ImportExplorer.Progress = new Class({
  288. initialize : function( id, actions ){
  289. this.id = id;
  290. this.actions = actions;
  291. },
  292. load : function( callback ){
  293. this.currentDate = new Date();
  294. this.addFormDataMessage();
  295. this.status = "ready";
  296. this.intervalId = setInterval( function(){
  297. this.actions.getImportStatus( this.id, function( json ){
  298. var data = json.data;
  299. if( data.processing && data.currentProcessName != "COMPLETE"){
  300. if( data.currentProcessName == "VALIDATE" ){
  301. if( this.status != data.currentProcessName ){
  302. this.setMessageTitle( "正在检查数据" );
  303. this.setMessageText( "开始检查数据,共"+data.process_validate_total+"条" );
  304. this.status = data.currentProcessName;
  305. }
  306. this.updateProgress( data.currentProcessName, data.process_validate_count, data.process_validate_total, data.errorCount );
  307. }else if( data.currentProcessName == "SAVEDATA" ){
  308. if( this.status != data.currentProcessName ){
  309. this.setMessageTitle( "正在导入数据" );
  310. this.setMessageText( "开始导入数据,共"+data.process_save_total+"条" );
  311. this.status = data.currentProcessName;
  312. }
  313. this.updateProgress( data.currentProcessName, data.process_save_count, data.process_save_total, data.errorCount );
  314. }
  315. }else{
  316. this.status = data.currentProcessName;
  317. clearInterval( this.intervalId );
  318. this.transferComplete( data );
  319. if( callback )callback();
  320. }
  321. }.bind(this), null)
  322. }.bind(this), 500 );
  323. },
  324. addFormDataMessage: function( noProgress ){
  325. var contentHTML = "";
  326. if (noProgress){
  327. contentHTML = "<div style=\"height: 20px; line-height: 20px\">"+"正在准备导入数据..."+"</div></div>" ;
  328. }else{
  329. contentHTML = "<div style=\"overflow: hidden\"><div style=\"height: 3px; border:1px solid #999; margin: 3px 0px\">" +
  330. "<div style=\"height: 3px; background-color: #acdab9; width: 0px;\"></div></div>" +
  331. "<div style=\"height: 20px; line-height: 20px\">"+"正在准备导入数据..."+"</div></div>" ;
  332. }
  333. var msg = {
  334. "subject": "准备导入数据",
  335. "content": contentHTML
  336. };
  337. this.messageItem = layout.desktop.message.addMessage(msg);
  338. this.messageItem.status = "ready";
  339. window.setTimeout(function(){
  340. if (!layout.desktop.message.isShow) layout.desktop.message.show();
  341. }.bind(this), 100);
  342. },
  343. updateProgress: function(type, loaded, total, errorCount){
  344. var messageItem = this.messageItem;
  345. var processed = errorCount ? ( loaded + errorCount ) : loaded;
  346. var percent = 100*(processed/total);
  347. var sendDate = new Date();
  348. var lastDate = this.lastTime || this.currentDate;
  349. var ms = sendDate.getTime() - lastDate.getTime();
  350. var speed = ( (processed - ( this.lastProcessed || 0 )) * 1000)/ms ;
  351. var u = "条/秒";
  352. speed = speed.round(2);
  353. if (messageItem.contentNode){
  354. var progressNode = messageItem.contentNode.getFirst("div").getFirst("div");
  355. var progressPercentNode = progressNode.getFirst("div");
  356. var progressInforNode = messageItem.contentNode.getFirst("div").getLast("div");
  357. progressPercentNode.setStyle("width", ""+percent+"%");
  358. if( type == "VALIDATE" ){
  359. var text = "正检查数据"+": "+speed+u + ",共"+total+"条,剩余"+( total - loaded )+"条";
  360. text += errorCount ? ",出错"+errorCount+"条" : ""
  361. }else{
  362. var text = "正导入数据"+": "+speed+u + ",共"+total+"条,剩余"+( total - loaded )+"条";
  363. text += errorCount ? ",出错"+errorCount+"条" : ""
  364. }
  365. progressInforNode.set("text", text);
  366. }
  367. this.lastProcessed = processed;
  368. this.lastTime = new Date();
  369. },
  370. transferComplete: function( data ){
  371. var errorCount = data.errorCount;
  372. var messageItem = this.messageItem;
  373. var sendDate = new Date();
  374. var ms = sendDate.getTime()-this.currentDate.getTime();
  375. var timeStr = "";
  376. if (ms>3600000){
  377. var h = ms/3600000;
  378. var m_s = ms % 3600000;
  379. var m = m_s / 60000;
  380. var s_s = m_s % 60000;
  381. var s = s_s/1000;
  382. timeStr = ""+h.toInt()+"小时"+m.toInt()+"分"+s.toInt()+"秒";
  383. }else if (ms>60000){
  384. var m = ms / 60000;
  385. var s_s = ms % 60000;
  386. var s = s_s/1000;
  387. timeStr = ""+m.toInt()+"分"+s.toInt()+"秒";
  388. }else{
  389. var s = ms/1000;
  390. timeStr = ""+s.toInt()+"秒";
  391. }
  392. if( errorCount == 0 ){
  393. var size = data.process_save_total;
  394. var speed = (size * 1000)/ms ;
  395. var u = "条/秒";
  396. speed = speed.round(2);
  397. this.setMessageTitle( "导入成功");
  398. this.setMessageText( "共导入数据"+size+"条 速度"+": "+speed+u+" "+"耗时"+": "+timeStr);
  399. }else{
  400. var size = data.process_validate_total;
  401. this.setMessageTitle( "导入失败");
  402. this.setMessageText( "共有数据"+size+"条 出错"+ errorCount +"条 耗时"+": "+timeStr +" 请修改后重新导入");
  403. }
  404. this.clearMessageProgress();
  405. },
  406. setMessageText: function( text){
  407. var progressPercentNode = this.getProgessNode().getFirst("div");
  408. this.getProgressInforNode().set("text", text);
  409. this.messageItem.dateNode.set("text", (new Date()).format("db"));
  410. },
  411. setMessageTitle: function( text){
  412. this.messageItem.subjectNode.set("text", text);
  413. },
  414. clearMessageProgress: function(){
  415. var progressNode = this.getProgessNode();
  416. progressNode.destroy();
  417. },
  418. getProgessNode : function(){
  419. if(!this.progressNode)this.progressNode = this.messageItem.contentNode.getFirst("div").getFirst("div");
  420. return this.progressNode;
  421. },
  422. getProgressInforNode : function(){
  423. if(!this.progressInforNode)this.progressInforNode = this.messageItem.contentNode.getFirst("div").getLast("div");
  424. return this.progressInforNode;
  425. }
  426. });