1 /** 2 * 3 * 流程UI 4 * 5 * @fileOverView 业务流基础组件 6 * @author <a href="mailto:zhang.gd@foxmail.com">Zhang Guangda</a> 7 * @date 2012-10-25 8 */ 9 define([ 10 "core", 11 "component/login", 12 "component/dialog", 13 "component/process_components", 14 "component/process_container" 15 ], function() { 16 17 /** 18 * 业务流组件核心的html结构 19 * @type {String} 20 */ 21 var _html = '<div attr="inner:progress"></div><div attr="inner:business"></div>', 22 _exceptionHtml = '<p class="we_cell_exception" attr="exception" style="display:none;"></p>', 23 _exceptionText = '系统异常,请稍后再试', 24 _exceptionTime = 1000, 25 _dialogTitle = '业务流程', 26 // _buttonPrev = '上一步', 27 _buttonPrev = false, // 暂时默认不开放上一步按钮 28 _buttonNext = '下一步', 29 _buttonEnd = '完成', 30 _dialogWidth = 600, 31 _content_class = 'we_pop_content_box', 32 _defaultProcessName = '业务流程', 33 _bizStyle = 'dialog', 34 bInUse = false; // 是否在使用中 35 36 var _isProcessPassed = function(cur, params) { 37 return this.processes[cur] 38 && typeof this.processes[cur].beforeAction == "function" 39 && !this.processes[cur].beforeAction.call(this.processQueue[cur], params); 40 }; 41 42 /** 43 * 业务流对话框组件 44 * @lends $we.widget.process.ui 45 */ 46 $we.widget.reg("process.ui", { 47 /** 48 * interfaces 49 * @memberOf $we.widget.process.ui# 50 */ 51 interfaces: { 52 /** 53 * 流程启动 54 * @memberOf $we.widget.process.ui# 55 */ 56 start: function() { 57 if(!this._inited || bInUse) return; 58 59 /** 60 * 设置是否独立流程 61 */ 62 if(typeof this.config.independent != "undefined") $we.process.setData("independent", this.config.independent); 63 64 // 进度条展示 65 this.progressBar.render(); 66 67 // 第一个流程不存在上一步,所以设置一下button 68 this.setButton({ 69 prev: false, 70 next: this.config.next 71 }); 72 // 将第一个可以启动的流程启动 73 if (_isProcessPassed.call(this, this.cur)) this.notifies.goNext(); 74 else this.processQueue[this.cur].process.start(); 75 76 // 如果正在关闭中,则停止调用 77 if (this.bClosing) return; 78 79 // 打开对话框 80 this.open(); 81 82 bInUse = true; 83 }, 84 /** 85 * 去往下一个流程 86 * @memberOf $we.widget.process.ui# 87 */ 88 next: function() { 89 if(this.cur > this.total - 1 || this.nexting) return; 90 // 标识为正在前往下一个,将在回调中设回false 91 this.nexting = true; 92 // 调用当前业务流组件中的checkSucc,这里面处理具体是否可以往下个流程走的逻辑 93 if(!this.processQueue[this.cur].process.checkSucc() && this.nexting) this.notifies.pause(); 94 95 }, 96 /** 97 * 去往上一个流程 98 * @memberOf $we.widget.process.ui# 99 */ 100 prev: function() { 101 if (this.bClosing) return; 102 if(this.cur == 0) return; 103 104 if(this.processQueue[this.cur].process.end) 105 this.processQueue[this.cur].process.end(); 106 107 if (this.processes[this.cur].hidden) { 108 while (this.cur > 0) { 109 --this.cur; 110 if (_isProcessPassed.call(this, this.cur)) { 111 continue; 112 } 113 break; 114 } 115 } else { 116 while (this.cur > 0) { 117 --this.cur; 118 if (this.processes[this.cur].hidden || _isProcessPassed.call(this, this.cur)) { 119 continue; 120 } 121 break; 122 } 123 } 124 125 // 重置按钮 126 this.setButton({ 127 prev: this.config.prev, 128 next: this.config.next, 129 prevGray: this.config.prevGray, 130 nextGray: this.config.nextGray 131 }); 132 133 // 如果上一个是最开始的,去掉prev 134 if(this.cur == 0) this.setButton({ 135 prev: false 136 }); 137 138 if (this.cur === 0 && _isProcessPassed.call(this, this.cur)) { 139 this.close(); 140 return; 141 } else { 142 this.processQueue[this.cur].process.start(); 143 } 144 145 // 设置进度栏 146 this.progressBar.setCur(this.barQueue[this.cur]); 147 148 this.position(); 149 }, 150 /** 151 * 设置按钮 152 * @memberOf $we.widget.process.ui# 153 * @param {object} config 配置 {<br /> 154 * prev: {string} 按钮的名称, false 表示隐藏,<br /> 155 * next: {string} 按钮的名称, false 表示隐藏<br /> 156 * } 157 */ 158 setButton: function(config) { 159 var btn = $(this.node.notice_button), 160 p = btn.find("a:first"), 161 c = btn.find("a:eq(1)"), 162 n = btn.find("a:last"); 163 164 if(config.prev === false) p.hide(); 165 166 if(config.next === false) n.hide(); 167 168 if(config.cancel) c.show(); 169 else c.hide(); 170 171 if(config.prev) { 172 p.html(config.prev); 173 p.show(); 174 } 175 176 if(config.next) { 177 n.html(config.next); 178 n.show(); 179 } 180 181 if(config.prevGray) p.removeClass("we_button").addClass("we_button_gray"); 182 else if(config.prevGray === false) p.removeClass("we_button_gray").addClass("we_button"); 183 184 if(config.nextGray) n.removeClass("we_button").addClass("we_button_gray"); 185 else if(config.nextGray === false) n.removeClass("we_button_gray").addClass("we_button"); 186 }, 187 /** 188 * 显示异常信息 189 * @memberOf $we.widget.process.ui# 190 * @param {String} text 异常文案 191 * @param {Integer} time 显示的时间 192 */ 193 showException: function(text, time) { 194 text = $we.utils.setValue(text, _exceptionText); 195 time = $we.utils.setValue(time, _exceptionTime); 196 var exp = $(this.node.exception); 197 exp.html(text); 198 exp.slideDown(); 199 setTimeout(function() { 200 exp.slideUp(); 201 }, time); 202 }, 203 /** 204 * 关闭按钮 205 * @memberOf $we.widget.process.ui# 206 */ 207 close: function() { 208 this.bClosing = true; 209 try { 210 this.processQueue[this.cur].process.end(); 211 } catch(e) {} 212 $we.process.clearData(); 213 this.remove(); 214 bInUse = false; 215 }, 216 /** 217 * 重新定位 218 * @memberOf $we.widget.process.ui# 219 */ 220 position: function() { 221 var me = this; 222 $we.dom.imageLoaded(this.node.root, function() { 223 me._super.position(); 224 }) 225 } 226 }, 227 /** 228 * notifies 229 * @memberOf $we.widget.process.ui- 230 */ 231 notifies: { 232 /** 233 * 将interfaces的next暴露给下属组件 234 * @memberOf $we.widget.process.ui- 235 */ 236 next: function() { 237 this.next(); 238 }, 239 /** 240 * 被通知前往下一个 241 * @memberOf $we.widget.process.ui- 242 * @param {mixed} params 参数 243 */ 244 goNext: function(params) { 245 246 if (this.bClosing) return; 247 248 this.renderBottom(""); 249 250 this.processes[this.cur] && typeof this.processes[this.cur].afterAction == "function" && this.processes[this.cur].afterAction.call(this, params); 251 252 // 如果是最后一个,直接关闭 253 if(this.cur >= this.total - 1) { 254 this.close(); 255 return; 256 } 257 258 if(this.processQueue[this.cur].process.end) { 259 try { 260 this.processQueue[this.cur].process.end(); 261 } catch (e) {} 262 } 263 264 while (this.cur++ < this.total) { 265 if (_isProcessPassed.call(this, this.cur, params)) continue; 266 break; 267 } 268 269 // 重置按钮 270 this.setButton({ 271 prev: this.config.prev, 272 next: this.config.next, 273 prevGray: this.config.prevGray, 274 nextGray: this.config.nextGray 275 }); 276 277 // 如果当前是最后一个,将下一步的按钮调整为结束的文字 278 if(this.cur == this.total - 1) this.setButton({ 279 next: this.config.end 280 }); 281 282 if (this.cur === this.total) { 283 this.close(); 284 return; 285 } else { 286 this.processQueue[this.cur].process.start(params); 287 } 288 289 // 设置进度条 290 this.progressBar.setCur(this.barQueue[this.cur]); 291 292 293 this.position(); 294 295 // 重置nexting为false 296 this.nexting = false; 297 }, 298 /** 299 * 被通知前往上一个 300 * @function 301 * @memberOf $we.widget.process.ui- 302 */ 303 goPrev: function() { 304 this.prev(); 305 }, 306 /** 307 * 设置按钮 308 * @function 309 * @memberOf $we.widget.process.ui- 310 */ 311 setButton: function() { 312 this.setButton.apply(this, arguments); 313 }, 314 /** 315 * 被通知暂不走向下一个流程 316 * @memberOf $we.widget.process.ui- 317 */ 318 pause: function() { 319 // 重置nexting为false 320 this.nexting = false; 321 }, 322 /** 323 * 被通知关闭 324 * @memberOf $we.widget.process.ui- 325 */ 326 close: function() { 327 // 重置nexting为false 328 this.nexting = false; 329 this.close(); 330 }, 331 /** 332 * 被通知退出流程 333 * @memberOf $we.widget.process.ui- 334 */ 335 abort: function() { 336 this.nexting = false; 337 this.close(); 338 }, 339 /** 340 * 被通知重新定位 341 * @memberOf $we.widget.process.ui- 342 */ 343 position: function() { 344 this.position(); 345 }, 346 /** 347 * 被通知显示异常 348 * @memberOf $we.widget.process.ui- 349 * @param {String} text 异常文字 350 * @param {Integer} time 异常显示时间 351 */ 352 showException: function(text, time) { 353 this.showException(text, time); 354 }, 355 /** 356 * 将interfaces的next暴露给下属组件 357 * @memberOf $we.widget.process.ui- 358 * @param {String} params 渲染底部的参数 359 */ 360 renderBottom: function(params) { 361 this.renderBottom(params); 362 this.position(); 363 }, 364 /** 365 * 显示进度条 366 * @memberOf $we.widget.process.ui- 367 */ 368 showProgressBar: function() { 369 this.progressBar.render(); 370 }, 371 /** 372 * 隐藏进度条 373 * @memberOf $we.widget.process.ui- 374 */ 375 hideProgressBar: function() { 376 this.progressBar.hide(); 377 } 378 }, 379 /** 380 * 初始化函数 381 * @constructs 382 * @param {array} processes { 383 * name: '流程名称', 384 * widget: '组件名称', 385 * params: [] 386 * } 387 * @param {object} config 配置 388 */ 389 init: function(processes, config) { 390 391 // 标识开始初始化 392 this._inited = false; 393 if(!$.isArray(processes)) return; 394 395 this.config = {}; 396 if (typeof config == "object") { 397 for (var i in config) { 398 this.config[i] = config[i]; 399 } 400 } 401 402 this.config.independent = this.config.independent; 403 this.config.bizStyle = $we.utils.setValue(this.config.bizStyle, _bizStyle); 404 this.config.flow = $we.utils.setValue(this.config.flow, ""); 405 this.config.title = $we.utils.setValue(this.config.title, _dialogTitle); 406 this.config.title = '<i class="we_title_icon"></i>'+this.config.title; 407 this.config.prev = $we.utils.setValue(this.config.prev, _buttonPrev); 408 this.config.next = $we.utils.setValue(this.config.next, _buttonNext); 409 this.config.prevGray = $we.utils.setValue(this.config.prevGray, false); 410 this.config.nextGray = $we.utils.setValue(this.config.nextGray, false); 411 this.config.end = $we.utils.setValue(this.config.end, _buttonEnd); 412 this.config.width = $we.utils.setValue(this.config.width, _dialogWidth); 413 this.config.class_notice_content = $we.utils.setValue(this.config.class_notice_content, _content_class); 414 415 var me = this; 416 417 this.config.mask = true; 418 this.config.close = true; 419 this.config.notice_content = _html; 420 this.config.notice_button_config = [{ 421 name: this.config.prev, 422 click: this.prev 423 }, { 424 name: "取消", 425 type: 'cancel', 426 click: this.close 427 }, { 428 name: this.config.next, 429 click: function(e) { 430 me.next(); 431 // IE 6 下,a链接会触发 onbeforeunload事件,导致jsonp请求被打断。需要干掉它的事件 432 if ($.browser.msie && $.browser.version < 8) { 433 e.preventDefault(); 434 e.stopPropagation(); 435 } 436 437 } 438 }]; 439 440 // 总的流程数 441 this.total = processes.length; 442 443 // if (this.total == 1) { 444 // ++this.total; 445 // processes.push({ 446 // name: "结束流程", 447 // widget: "process.end" 448 // }); 449 // } 450 451 // 渲染对话框 452 switch (this.config.bizStyle) { 453 case "dialog": 454 this.extend('NoticeDialog', [this.config]); 455 break; 456 457 case "div": 458 this.extend('process.container', [this.config.el, this.config]); 459 break; 460 } 461 462 463 var curBar, 464 processNames = [], 465 // 流程名称,array 466 processQueue = [], 467 barQueue = [], 468 // 将流程的object储存在此,这个object是通过$we.process.set new 出来的object 469 pNode = this.node.business; // 每个流程的父节点 470 // 将每个流程分别处理 471 $(processes).each(function(index) { 472 if(!this.widget) return; 473 474 processQueue.push($we.widget.add({ 475 name: this.widget, 476 notifyTo: me 477 }, pNode, this.params)); 478 479 // 如果没有声明名称,我们认为他是隐藏的 480 if(!this.name) this.hidden = true; 481 482 if(!this.hidden) processNames.push(this.name || _defaultProcessName); 483 484 curBar = processNames.length - 1; 485 if (curBar < 0) curBar = 0; 486 barQueue.push(curBar); 487 }); 488 489 // 储存 processQueue 到this 中去 490 this.processQueue = processQueue; 491 this.processes = processes; 492 this.barQueue = barQueue; 493 494 // 设置进度条,将processNames传入其中 495 this.progressBar = $we.widget.add("process.progress", this.node.progress, processNames); 496 497 // 当前流程设置为0 498 this.cur = 0; 499 500 // 添加一个exception 浮层 501 this.before(this.node.notice_content, _exceptionHtml); 502 503 /** 504 * 设置流程总长度 505 */ 506 $we.process.setData("length", this.total); 507 508 /** 509 * 设置流程的id 510 */ 511 if (!$we.process.getData("id")) 512 $we.process.setData("id", $we.conf.RUNTIME.__RANDOMSEED.toString() + (+new Date).toString()); 513 /** 514 * 设置流程名称 515 */ 516 if (!$we.process.getData("flow")) 517 $we.process.setData("flow", this.config.flow); 518 519 // 初始化完成 520 this._inited = true; 521 } 522 }); 523 524 return $we.widget.amd("process.ui"); 525 526 });