神马其余Audit Trail实现方式都是浮云 - 用Ext实现的Time machine(效果图+源码)
神马其他Audit Trail实现方式都是浮云 -- 用Ext实现的Time machine(效果图+源码)
效果图:
源代码:
Ext.ns('SCTMS.dlg'); SCTMS.dlg.TimeMachine = Ext.extend(Ext.Window, { maximized : true, modal : true, closeable: false, closeAction : "hide", layout : "fit", autoScroll : false, cls : "z-timemachine-dlg" , initComponent : function() { this.northPanel = new Ext.Panel({region:'north', height:24, html:'<div style="position:absolute;top:5px;left:5px;color:#ffffff;font-weight:bold;"><a href="javascript:void(0)" onclick="SCTMS.dlg.timeMachine.hide();return false;" title="Go back to Global Clinical">Back</a></div><div style="padding-top:5px;color:#c3c3c3;font-weight:bold;"><center>Time Machine</center></div><div style="position:absolute;top:5px;right:5px;color:#ffffff;font-weight:bold;"><a id="timemachine-link-toggle-version-list" href="javascript:void(0);" onclick="SCTMS.dlg.timeMachine.toggleVersionList();return false;">Hide Version List</a></div>'}); this.dummyCenterPanel = new Ext.Panel({region:'center'}); this.versionListPanel = new Ext.grid.GridPanel({ region : "east", width: 270, header: false, autoScroll : true, cls:' panel-transparent'//, cls:' panel-transparent grid-no-header' , columns: [{header:'#',align:'right',width: 20, dataIndex:'version', renderer:function(v,x,r){ return (v+1) }}, {header:'Author',width:110,dataIndex:'createdBy'} , {header:'Date Created',width:120,dataIndex:'dateCreated'}] , store: new Ext.data.JsonStore({ url: Ext.CONTEXT_PATH + '/rpc/timeMachine/versions', root: 'versions', idProperty: 'version', fields: ['version','dateCreated','createdBy'] }) , bbar: ['->',{xtype:'sexybutton',text:'Compare',handler:this.compare,scope:this}] , listeners: {'rowclick':function(g,i,e){ this.loadVersion({mid:this.mid,version:g.getStore().getAt(i).get('version')}); },scope:this} }); var a = this.panel = new Ext.Panel({ layout : "border", items : [this.northPanel, this.dummyCenterPanel, this.versionListPanel]} ); this.items = [a]; SCTMS.dlg.TimeMachine.superclass.initComponent.apply(this, arguments); } , initEvents : function() { SCTMS.dlg.TimeMachine.superclass.initEvents.apply(this, arguments); } , show : function(mid) { this.mid = mid; SCTMS.dlg.TimeMachine.superclass.show.call(this); this.loadVersion({mid:mid}); var store = this.versionListPanel.getStore(); store.baseParams.mid = mid; store.load(); } , hide : function() { this.dataWin.hide(); if(this.compareWin)this.compareWin.hide(); SCTMS.dlg.TimeMachine.superclass.hide.apply(this, arguments); } , toggleVersionList : function() { var visible = this.versionListPanel.isVisible(); Ext.get('timemachine-link-toggle-version-list').update((visible ? 'Show' : 'Hide') + ' Version List'); this.versionListPanel[visible?'hide':'show'](); } , loadVersion : function(p) { if(!this.dataWin) { this.dataWin = new Ext.Window({layout:'absolute', autoScroll:true, closable:false, resizable:false, cls:' panel-transparent', border:false, bbar:{height:100}}); this._resizeDataWin = function() { var adjustedH = Math.min(document.body.clientHeight/1.1, this.xform.height + 135); var adjustedW = Math.min(document.body.clientWidth/1.1, this.xform.width + 15 + ((document.body.clientHeight/1.1>=this.xform.height + 135)?0:17)); this.dataWin.setSize(adjustedW, adjustedH); try{this.dataWin.center();}catch(e){} }; this.on('resize', this._resizeDataWin, this); } GRS.dispatcher.dispatch("timeMachine/version?view=true", p, function(x) { this.xform = x.form; this.xchanges = x.changes; this.dataWin.setTitle('version ' + (x.oversion+1) + ', modified by ' + x.ocreatedBy+ ' on ' + x.odateCreated); this._resizeDataWin.call(this); this.dataWin.show(); x.form.listeners = x.form.listeners || {}; var dw = this.dataWin; x.form.listeners.subformrender = { scope: this, fn: function() { if(this.xchanges) { for(var k in this.xchanges) { if(/Id$/.test(k)) { continue; } if(this.xchanges.hasOwnProperty(k)) { try{ var ov = this.xchanges[k][1]; if(ov == null) {ov = 'null'} var tooltip_html = 'In previous version it was:<div style="color:#0000ff;font-weight:bold;">' + (!ov||ov==''?' ':ov.replace(/\n/g,'<br>')) + '</div>'; var f = dw.form.findField(k); if(f) { f.addClass('x-form-different-field'); new Ext.ToolTip({target:f.id, html:tooltip_html, dismissDelay: 0}); } else { var special_cased_f = Ext.get(this.xform.id+'_'+k); if(special_cased_f) { special_cased_f.addClass('x-form-different-field'); new Ext.ToolTip({target:this.xform.id+'_'+k, html:tooltip_html, dismissDelay: 0}) } } }catch(err){} } } } } }; GRS.form.FormProcessor.addForm2Panel(this.dataWin, x, {callback:x.form.listeners.subformrender.fn, scope:this, hideEmptyText:true}); if(!x.changes) { this.dataWin.getBottomToolbar().update(''); return; } var changes = []; for(var k in x.changes) { if(/Id$/.test(k)) continue; if(x.changes.hasOwnProperty(k)) { changes.push('<p>♦ <font color="blue">' + k + '</font> <font color="gray">changed from</font> <font color="blue">' + x.changes[k][1] + '</font> <font color="gray">to</font> <font color="blue">' + x.changes[k][0] + '</font></p>'); } } this.dataWin.getBottomToolbar().update('Change Summary<hr><div style="overflow:auto;height:70px;">' + (changes.length ? changes.join('') : 'No changes from previous version.') + '</div>'); }, this); } , compare :function() { var selections = SCTMS.dlg.timeMachine.versionListPanel.getSelectionModel().getSelections(); if(!selections || selections.length < 2) {Ext.MessageBox.alert('', 'You need to select 2 versions to compare.');return} if(!this.compareWin) { this.compareWin = new Ext.Window({ cls:' panel-transparent', border:false , title: '<center><b> <span style="color:blue;">Global Comparator</span></b></center>' , modal:true, resizable:false, closeAction:'hide' , layout: 'border' , items: [ this.comparePanel1 = new Ext.Panel({region:'west', layout:'absolute', autoScroll:false, title:' ', split:true}) //, {region:'center',width:2,border:true,html:'<div style="height:2000px;overflow:hidden;width:2px;border-right:1px dashed #B5B8C8;">'} , this.comparePanel2 = new Ext.Panel({region:'center', layout:'absolute', autoScroll:false, title:' '}) , this.vScroller = new Ext.Panel({region:'east', width:17, autoScroll:true, layout:'absolute', items:[this.ivScroller = new Ext.BoxComponent({width:17})]}) , this.hScroller = new Ext.Panel({region:'south', height:17, autoScroll:true, layout:'absolute', items:[this.ihScroller = new Ext.BoxComponent({height:17})]}) ] }); this._resizeCompareWin = function() { var adjustedH = Math.min(this.xform.height+75, document.body.clientHeight/1.1) + 17; var adjustedW = Math.min(this.xform.width * 2, document.body.clientWidth/1.1) + 17; this.compareWin.setSize(adjustedW, adjustedH); var w = Math.min(document.body.clientWidth/2.2, this.xform.width) , h = Math.min(document.body.clientHeight/1.1, this.xform.height); this.comparePanel1.setSize(w, h); this.comparePanel2.setSize(w, h); this.vScroller.setSize(17, h);this.ivScroller.setSize(17, this.xform.height); this.hScroller.setSize(w*2, 17);this.ihScroller.setSize(this.xform.width*2, 17); try{this.compareWin.center();}catch(e){} }; this.comparePanel1.on('render', function(){ Ext.TaskMgr.start({interval : 300, scope : this, run : function(){ if(this.comparePanel1.form && this.comparePanel2.form) { var st = SCTMS.dlg.timeMachine.ivScroller.el.dom.parentNode.scrollTop; var sl = SCTMS.dlg.timeMachine.ihScroller.el.dom.parentNode.scrollLeft/2; if(st>0)st+=17;if(sl>0)sl+=17; Ext.get(Ext.get(this.comparePanel1.form.id).dom.parentNode.parentNode.id).dom.parentNode.scrollTop = Ext.get(Ext.get(this.comparePanel2.form.id).dom.parentNode.parentNode.id).dom.parentNode.scrollTop = st; Ext.get(Ext.get(this.comparePanel1.form.id).dom.parentNode.parentNode.id).dom.parentNode.scrollLeft = Ext.get(Ext.get(this.comparePanel2.form.id).dom.parentNode.parentNode.id).dom.parentNode.scrollLeft = sl; } }}); this.on('resize', this._resizeCompareWin, this); }, this); } var p = {mid:this.mid, v1:selections[0].get('version'), v2:selections[1].get('version')}; GRS.dispatcher.dispatch("timeMachine/compare?view=true", p, function(x) { this.xform = x.form; this._resizeCompareWin.call(this); this.compareWin.show(); GRS.form.FormProcessor.addForms2ComparePanels(this.compareWin, this.comparePanel1, this.comparePanel2, x); }, this); } });