=e&&t.s<=e+n}},_findTargetItemIndex:function(n){return this._showController?(this.getContentGroup().eachChild(function(t,e){var i=t.__legendDataIndex;null==a&&null!=i&&(a=e),i===n&&(o=e)}),null!=o?o:a):0;var o,a}});_f("legendScroll","legendscroll",function(t,e){var i=t.scrollDataIndex;null!=i&&e.eachComponent({mainType:"legend",subType:"scroll",query:t},function(t){t.setScrollDataIndex(i)})});cD.extend({type:"dataZoom.slider",layoutMode:"box",defaultOption:{show:!0,right:"ph",top:"ph",width:"ph",height:"ph",left:null,bottom:null,backgroundColor:"rgba(47,69,84,0)",dataBackground:{lineStyle:{color:"#2f4554",width:.5,opacity:.3},areaStyle:{color:"rgba(47,69,84,0.3)",opacity:.3}},borderColor:"#ddd",fillerColor:"rgba(167,183,204,0.4)",handleIcon:"M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z",handleSize:"100%",handleStyle:{color:"#a7b7cc"},labelPrecision:null,labelFormatter:null,showDetail:!0,showDataShadow:"auto",realtime:!0,zoomLock:!1,textStyle:{color:"#333"}}});var lL=rs,uL=Rl,hL=Bl,cL=A,dL=R,fL="horizontal",pL="vertical",gL=["line","bar","candlestick","scatter"],mL=pD.extend({type:"dataZoom.slider",init:function(t,e){this._displayables={},this._orient,this._range,this._handleEnds,this._size,this._handleWidth,this._handleHeight,this._location,this._dragging,this._dataShadowInfo,this.api=e},render:function(t,e,i,n){mL.superApply(this,"render",arguments),kc(this,"_dispatchZoomAction",this.dataZoomModel.get("throttle"),"fixRate"),this._orient=t.get("orient"),!1!==this.dataZoomModel.get("show")?(n&&"dataZoom"===n.type&&n.from===this.uid||this._buildView(),this._updateView()):this.group.removeAll()},remove:function(){mL.superApply(this,"remove",arguments),Pc(this,"_dispatchZoomAction")},dispose:function(){mL.superApply(this,"dispose",arguments),Pc(this,"_dispatchZoomAction")},_buildView:function(){var t=this.group;t.removeAll(),this._resetLocation(),this._resetInterval();var e=this._displayables.barGroup=new Ci;this._renderBackground(),this._renderHandle(),this._renderDataShadow(),t.add(e),this._positionGroup()},_resetLocation:function(){var t=this.dataZoomModel,e=this.api,i=this._findCoordRect(),n={width:e.getWidth(),height:e.getHeight()},o=this._orient===fL?{right:n.width-i.x-i.width,top:n.height-30-7,width:i.width,height:30}:{right:7,top:i.y,width:30,height:i.height},a=Iu(t.option);R(["right","top","width","height"],function(t){"ph"===a[t]&&(a[t]=o[t])});var r=bu(a,n,t.padding);this._location={x:r.x,y:r.y},this._size=[r.width,r.height],this._orient===pL&&this._size.reverse()},_positionGroup:function(){var t=this.group,e=this._location,i=this._orient,n=this.dataZoomModel.getFirstTargetAxisModel(),o=n&&n.get("inverse"),a=this._displayables.barGroup,r=(this._dataShadowInfo||{}).otherAxisInverse;a.attr(i!==fL||o?i===fL&&o?{scale:r?[-1,1]:[-1,-1]}:i!==pL||o?{scale:r?[-1,-1]:[-1,1],rotation:Math.PI/2}:{scale:r?[1,-1]:[1,1],rotation:Math.PI/2}:{scale:r?[1,1]:[1,-1]});var s=t.getBoundingRect([a]);t.attr("position",[e.x-s.x,e.y-s.y])},_getViewExtent:function(){return[0,this._size[0]]},_renderBackground:function(){var t=this.dataZoomModel,e=this._size,i=this._displayables.barGroup;i.add(new lL({silent:!0,shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:t.get("backgroundColor")},z2:-40})),i.add(new lL({shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:"transparent"},z2:0,onclick:A(this._onClickPanelClick,this)}))},_renderDataShadow:function(){var t=this._dataShadowInfo=this._prepareDataShadowInfo();if(t){var e=this._size,i=t.series,n=i.getRawData(),o=i.getShadowDim?i.getShadowDim():t.otherDim;if(null!=o){var a=n.getDataExtent(o),r=.3*(a[1]-a[0]);a=[a[0]-r,a[1]+r];var s,l=[0,e[1]],u=[0,e[0]],h=[[e[0],0],[0,0]],c=[],d=u[1]/(n.count()-1),f=0,p=Math.round(n.count()/e[0]);n.each([o],function(t,e){if(0e[0]||i[1]<0||i[1]>e[1])){var n=this._handleEnds,o=(n[0]+n[1])/2,a=this._updateInterval("all",i[0]-o);this._updateView(),a&&this._dispatchZoomAction()}},_dispatchZoomAction:function(){var t=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,start:t[0],end:t[1]})},_findCoordRect:function(){var i;if(dL(this.getTargetCoordInfo(),function(t){if(!i&&t.length){var e=t[0].model.coordinateSystem;i=e.getRect&&e.getRect()}}),!i){var t=this.api.getWidth(),e=this.api.getHeight();i={x:.2*t,y:.2*e,width:.6*t,height:.6*e}}return i}});function vL(t){return"vertical"===t?"ns-resize":"ew-resize"}cD.extend({type:"dataZoom.inside",defaultOption:{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}});var yL="\0_ec_dataZoom_roams";function xL(t,n){var e=wL(t),o=n.dataZoomId,a=n.coordId;R(e,function(t,e){var i=t.dataZoomInfos;i[o]&&_(n.allCoordIds,a)<0&&(delete i[o],t.count--)}),bL(e);var i=e[a];i||((i=e[a]={coordId:a,dataZoomInfos:{},count:0}).controller=function(t,r){var e=new Vy(t.getZr());return R(["pan","zoom","scrollMove"],function(a){e.on(a,function(n){var o=[];R(r.dataZoomInfos,function(t){if(n.isAvailableBehavior(t.dataZoomModel.option)){var e=(t.getRange||{})[a],i=e&&e(r.controller,n);!t.dataZoomModel.get("disabled",!0)&&i&&o.push({dataZoomId:t.dataZoomId,start:i[0],end:i[1]})}}),o.length&&r.dispatchAction(o)})}),e}(t,i),i.dispatchAction=T(SL,t)),i.dataZoomInfos[o]||i.count++,i.dataZoomInfos[o]=n;var r=function(t){var n,o={type_true:2,type_move:1,type_false:0,type_undefined:-1},a=!0;return R(t,function(t){var e=t.dataZoomModel,i=!e.get("disabled",!0)&&(!e.get("zoomLock",!0)||"move");o["type_"+n]"],L(t)&&(t=t.slice(),n=!0),o=e?t:n?[u(t[0]),u(t[1])]:u(t),E(l)?l.replace("{value}",n?o[0]:o).replace("{value2}",n?o[1]:o):C(l)?n?l(t[0],t[1]):l(t):n?t[0]===s[0]?i[0]+" "+o[1]:t[1]===s[1]?i[1]+" "+o[0]:o[0]+" - "+o[1]:o;function u(t){return t===s[0]?"min":t===s[1]?"max":(+t).toFixed(Math.min(r,20))}},resetExtent:function(){var t=this.option,e=GL([t.min,t.max]);this._dataExtent=e},getDataDimension:function(t){var e=this.option.dimension,i=t.dimensions;if(null!=e||i.length){if(null!=e)return t.getDimension(e);for(var n=t.dimensions,o=n.length-1;0<=o;o--){var a=n[o];if(!t.getDimensionInfo(a).isCalculationCoord)return a}}},getExtent:function(){return this._dataExtent.slice()},completeVisualOption:function(){var t=this.ecModel,e=this.option,i={inRange:e.inRange,outOfRange:e.outOfRange},n=e.target||(e.target={}),o=e.controller||(e.controller={});m(n,i),m(o,i);var u=this.isCategory();function a(n){BL(e.color)&&!n.inRange&&(n.inRange={color:e.color.slice().reverse()}),n.inRange=n.inRange||{color:t.get("gradientColor")},VL(this.stateList,function(t){var e=n[t];if(E(e)){var i=OL(e,"active",u);i?(n[t]={},n[t][e]=i):delete n[t]}},this)}a.call(this,n),a.call(this,o),function(t,e,i){var n=t[e],o=t[i];n&&!o&&(o=t[i]={},VL(n,function(t,e){if(g_.isValidType(e)){var i=OL(e,"inactive",u);null!=i&&(o[e]=i,"color"!==e||o.hasOwnProperty("opacity")||o.hasOwnProperty("colorAlpha")||(o.opacity=[0,0]))}}))}.call(this,n,"inRange","outOfRange"),function(a){var r=(a.inRange||{}).symbol||(a.outOfRange||{}).symbol,s=(a.inRange||{}).symbolSize||(a.outOfRange||{}).symbolSize,l=this.get("inactiveColor");VL(this.stateList,function(t){var e=this.itemSize,i=a[t];null==(i=i||(a[t]={color:u?l:[l]})).symbol&&(i.symbol=r&&k(r)||(u?"roundRect":["roundRect"])),null==i.symbolSize&&(i.symbolSize=s&&k(s)||(u?e[0]:[e[0],e[0]])),i.symbol=EL(i.symbol,function(t){return"none"===t||"square"===t?"roundRect":t});var n=i.symbolSize;if(null!=n){var o=-1/0;zL(n,function(t){oe[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},completeVisualOption:function(){WL.prototype.completeVisualOption.apply(this,arguments),R(this.stateList,function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=0)},this)},setSelected:function(t){this.option.range=t.slice(),this._resetRange()},getSelected:function(){var t=this.getExtent(),e=Bl((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]=i[1]||t<=e[1])?"inRange":"outOfRange"},findTargetDataIndices:function(n){var o=[];return this.eachTargetSeries(function(t){var i=[],e=t.getData();e.each(this.getDataDimension(e),function(t,e){n[0]<=t&&t<=n[1]&&i.push(e)},this),o.push({seriesId:t.id,dataIndex:i})},this),o},getVisualMeta:function(i){var t=UL(this,"outOfRange",this.getExtent()),e=UL(this,"inRange",this.option.range.slice()),n=[];function o(t,e){n.push({value:t,color:i(t,e)})}for(var a=0,r=0,s=e.length,l=t.length;rt[1])break;i.push({color:this.getControllerVisual(a,"color",e),offset:o/100})}return i.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),i},_createBarPoints:function(t,e){var i=this.visualMapModel.itemSize;return[[i[0]-e[0],t[0]],[i[0],t[0]],[i[0],t[1]],[i[0]-e[1],t[1]]]},_createBarGroup:function(t){var e=this._orient,i=this.visualMapModel.get("inverse");return new Ci("horizontal"!==e||i?"horizontal"===e&&i?{scale:"bottom"===t?[-1,1]:[1,1],rotation:-Math.PI/2}:"vertical"!==e||i?{scale:"left"===t?[1,1]:[-1,1]}:{scale:"left"===t?[1,-1]:[-1,-1]}:{scale:"bottom"===t?[1,1]:[-1,1],rotation:Math.PI/2})},_updateHandle:function(n,o){if(this._useHandle){var a=this._shapes,r=this.visualMapModel,s=a.handleThumbs,l=a.handleLabels;KL([0,1],function(t){var e=s[t];e.setStyle("fill",o.handlesColor[t]),e.position[1]=n[t];var i=pl(a.handleLabelPoints[t],fl(e,this.group));l[t].setStyle({x:i[0],y:i[1],text:r.formatValueText(this._dataInterval[t]),textVerticalAlign:"middle",textAlign:this._applyTransform("horizontal"===this._orient?0===t?"bottom":"top":"left",a.barGroup)})},this)}},_showIndicator:function(t,e,i,n){var o=this.visualMapModel,a=o.getExtent(),r=o.itemSize,s=[0,r[1]],l=qL(t,a,s,!0),u=this._shapes,h=u.indicator;if(h){h.position[1]=l,h.attr("invisible",!1),h.setShape("points",function(t,e,i,n){return t?[[0,-$L(e,JL(i,0))],[6,0],[0,$L(e,JL(n-i,0))]]:[[0,0],[5,-5],[5,5]]}(!!i,n,l,r[1]));var c=this.getControllerVisual(t,"color",{convertOpacityToAlpha:!0});h.setStyle("fill",c);var d=pl(u.indicatorLabelPoint,fl(h,this.group)),f=u.indicatorLabel;f.attr("invisible",!1);var p=this._applyTransform("left",u.barGroup),g=this._orient;f.setStyle({text:(i||"")+o.formatValueText(e),textVerticalAlign:"horizontal"===g?p:"middle",textAlign:"horizontal"===g?"center":p,x:d[0],y:d[1]})}},_enableHoverLinkToSeries:function(){var n=this;this._shapes.barGroup.on("mousemove",function(t){if(n._hovering=!0,!n._dragging){var e=n.visualMapModel.itemSize,i=n._applyTransform([t.offsetX,t.offsetY],n._shapes.barGroup,!0,!0);i[1]=$L(JL(0,i[1]),e[1]),n._doHoverLinkToSeries(i[1],0<=i[0]&&i[0]<=e[0])}}).on("mouseout",function(){n._hovering=!1,n._dragging||n._clearHoverLinkToSeries()})},_enableHoverLinkFromSeries:function(){var t=this.api.getZr();this.visualMapModel.option.hoverLink?(t.on("mouseover",this._hoverLinkFromSeriesMouseOver,this),t.on("mouseout",this._hideIndicator,this)):this._clearHoverLinkFromSeries()},_doHoverLinkToSeries:function(t,e){var i=this.visualMapModel,n=i.itemSize;if(i.option.hoverLink){var o=[0,n[1]],a=i.getExtent();t=$L(JL(o[0],t),o[1]);var r=function(t,e,i){var n=6,o=t.get("hoverLinkDataSize");o&&(n=qL(o,e,i,!0)/2);return n}(i,a,o),s=[t-r,t+r],l=qL(t,o,a,!0),u=[qL(s[0],o,a,!0),qL(s[1],o,a,!0)];s[0] ",r):this._showIndicator(l,l,"≈ ",r));var h=this._hoverLinkDataIndices,c=[];(e||ek(i))&&(c=this._hoverLinkDataIndices=i.findTargetDataIndices(u));var d=function(t,e){var i={},n={};return o(t||[],i),o(e||[],n,i),[a(i),a(n)];function o(t,e,i){for(var n=0,o=t.length;ni&&n([i,e[0]],"outOfRange"),n(e.slice()),i=e[1])},this),{stops:a,outerColors:r}}function n(t,e){var i=s.getRepresentValue({interval:t});e=e||s.getValueState(i);var n=o(i,e);t[0]===-1/0?r[0]=n:t[1]===1/0?r[1]=n:a.push({value:t[0],color:n},{value:t[1],color:n})}}}),ok={splitNumber:function(){var t=this.option,e=this._pieceList,i=Math.min(t.precision,20),n=this.getExtent(),o=t.splitNumber;o=Math.max(parseInt(o,10),1),t.splitNumber=o;for(var a=(n[1]-n[0])/o;+a.toFixed(i)!==a&&i<5;)i++;t.precision=i,a=+a.toFixed(i),t.minOpen&&e.push({interval:[-1/0,n[0]],close:[0,0]});for(var r=0,s=n[0];r","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,i)},this)}};function ak(t,e){var i=t.inverse;("vertical"===t.orient?!i:i)&&e.reverse()}XL.extend({type:"visualMap.piecewise",doRender:function(){var a=this.group;a.removeAll();var r=this.visualMapModel,s=r.get("textGap"),t=r.textStyleModel,l=t.getFont(),u=t.getTextColor(),h=this._getItemAlign(),c=r.itemSize,e=this._getViewData(),i=e.endsText,d=W(r.get("showLabel",!0),!i);i&&this._renderEndsText(a,i[0],c,d,h),R(e.viewPieceList,function(t){var e=t.piece,i=new Ci;i.onclick=A(this._onItemClick,this,e),this._enableHoverLink(i,t.indexInModelPieceList);var n=r.getRepresentValue(e);if(this._createItemSymbol(i,n,[0,0,c[0],c[1]]),d){var o=this.visualMapModel.getValueState(n);i.add(new Ur({style:{x:"right"===h?-s:c[0]+s,y:c[1]/2,text:e.text,textVerticalAlign:"middle",textAlign:h,textFont:l,textFill:u,opacity:"outOfRange"===o?.5:1}}))}a.add(i)},this),i&&this._renderEndsText(a,i[1],c,d,h),wu(r.get("orient"),a,r.get("itemGap")),this.renderBackground(a),this.positionGroup(a)},_enableHoverLink:function(t,i){function e(t){var e=this.visualMapModel;e.option.hoverLink&&this.api.dispatchAction({type:t,batch:jL(e.findTargetDataIndices(i),e)})}t.on("mouseover",A(e,this,"highlight")).on("mouseout",A(e,this,"downplay"))},_getItemAlign:function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return YL(t,this.api,t.itemSize);var i=e.align;return i&&"auto"!==i||(i="left"),i},_renderEndsText:function(t,e,i,n,o){if(e){var a=new Ci,r=this.visualMapModel.textStyleModel;a.add(new Ur({style:{x:n?"right"===o?i[0]:0:i[0]/2,y:i[1]/2,textVerticalAlign:"middle",textAlign:n?o:"center",text:e,textFont:r.getFont(),textFill:r.getTextColor()}})),t.add(a)}},_getViewData:function(){var t=this.visualMapModel,e=O(t.getPieceList(),function(t,e){return{piece:t,indexInModelPieceList:e}}),i=t.get("text"),n=t.get("orient"),o=t.get("inverse");return("horizontal"===n?o:!o)?e.reverse():i=i&&i.slice().reverse(),{viewPieceList:e,endsText:i}},_createItemSymbol:function(t,e,i){t.add(wg(this.getControllerVisual(e,"symbol"),i[0],i[1],i[2],i[3],this.getControllerVisual(e,"color")))},_onItemClick:function(t){var e=this.visualMapModel,i=e.option,n=k(i.selected),o=e.getSelectedMapKey(t);"single"===i.selectedMode?(n[o]=!0,R(n,function(t,e){n[e]=e===o})):n[o]=!n[o],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:n})}});yf(DL);var rk,sk="urn:schemas-microsoft-com:vml",lk="undefined"==typeof window?null:window,uk=!1,hk=lk&&lk.document;function ck(t){return rk(t)}if(hk&&!v.canvasSupported)try{hk.namespaces.zrvml||hk.namespaces.add("zrvml",sk),rk=function(t){return hk.createElement("')}}catch(t){rk=function(t){return hk.createElement("<"+t+' xmlns="'+sk+'" class="zrvml">')}}var dk,fk=rr.CMD,pk=Math.round,gk=Math.sqrt,mk=Math.abs,vk=Math.cos,yk=Math.sin,xk=Math.max;if(!v.canvasSupported){var _k=",",wk="progid:DXImageTransform.Microsoft",bk=21600,Sk=bk/2,Mk=function(t){t.style.cssText="position:absolute;left:0;top:0;width:1px;height:1px;",t.coordsize=bk+","+bk,t.coordorigin="0,0"},Ik=function(t,e,i){return"rgb("+[t,e,i].join(",")+")"},Tk=function(t,e){e&&t&&e.parentNode!==t&&t.appendChild(e)},Ak=function(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)},Dk=function(t,e,i){return 1e5*(parseFloat(t)||0)+1e3*(parseFloat(e)||0)+i},Ck=Yn,Lk=function(t,e,i){var n=Fe(e);i=+i,isNaN(i)&&(i=1),n&&(t.color=Ik(n[0],n[1],n[2]),t.opacity=i*n[3])},kk=function(t,e,i,n){var o="fill"===e,a=t.getElementsByTagName(e)[0];null!=i[e]&&"none"!==i[e]&&(o||!o&&i.lineWidth)?(t[o?"filled":"stroked"]="true",i[e]instanceof cs&&Ak(t,a),a=a||ck(e),o?function(t,e,i){var n,o,a=e.fill;if(null!=a)if(a instanceof cs){var r,s=0,l=[0,0],u=0,h=1,c=i.getBoundingRect(),d=c.width,f=c.height;if("linear"===a.type){r="gradient";var p=i.transform,g=[a.x*d,a.y*f],m=[a.x2*d,a.y2*f];p&&(bt(g,g,p),bt(m,m,p));var v=m[0]-g[0],y=m[1]-g[1];(s=180*Math.atan2(v,y)/Math.PI)<0&&(s+=360),s<1e-6&&(s=0)}else{r="gradientradial";g=[a.x*d,a.y*f],p=i.transform;var x=i.scale,_=d,w=f;l=[(g[0]-c.x)/_,(g[1]-c.y)/w],p&&bt(g,g,p),_/=x[0]*bk,w/=x[1]*bk;var b=xk(_,w);u=0/b,h=2*a.r/b-u}var S=a.colorStops.slice();S.sort(function(t,e){return t.offset-e.offset});for(var M=S.length,I=[],T=[],A=0;A=c&&d<=i+1){for(var n=[],o=0;o=c&&d<=o+1)return _P(h,e.components,u,l);p[t]=e}else p[t]=void 0}var s;f++}for(;f<=e;){var r=a();if(r)return r}},pushComponent:function(t,e,i){var n=t[t.length-1];n&&n.added===e&&n.removed===i?t[t.length-1]={count:n.count+1,added:e,removed:i}:t.push({count:1,added:e,removed:i})},extractCommon:function(t,e,i,n){for(var o=e.length,a=i.length,r=t.newPos,s=r-n,l=0;r+1\n\r<"))}},R(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","pathToImage"],function(t){OP.prototype[t]=function(t){return function(){vi('In SVG mode painter not support method "'+t+'"')}}(t)}),Po("svg",OP),t.version="4.9.0",t.dependencies={zrender:"4.3.2"},t.PRIORITY=Ld,t.init=function(t,e,i){var n=mf(t);if(n)return n;var o=new Ed(t,e,i);return o.id="ec_"+cf++,uf[o.id]=o,Jo(t,ff,o.id),function(n){var o="__connectUpdateStatus";function a(t,e){for(var i=0;i3?0:(e-e%10!=10)*e%10]}};var g={D:function(e){return e.getDay()},DD:function(e){return d(e.getDay())},Do:function(e,t){return t.DoFn(e.getDate())},d:function(e){return e.getDate()},dd:function(e){return d(e.getDate())},ddd:function(e,t){return t.dayNamesShort[e.getDay()]},dddd:function(e,t){return t.dayNames[e.getDay()]},M:function(e){return e.getMonth()+1},MM:function(e){return d(e.getMonth()+1)},MMM:function(e,t){return t.monthNamesShort[e.getMonth()]},MMMM:function(e,t){return t.monthNames[e.getMonth()]},yy:function(e){return d(String(e.getFullYear()),4).substr(2)},yyyy:function(e){return d(e.getFullYear(),4)},h:function(e){return e.getHours()%12||12},hh:function(e){return d(e.getHours()%12||12)},H:function(e){return e.getHours()},HH:function(e){return d(e.getHours())},m:function(e){return e.getMinutes()},mm:function(e){return d(e.getMinutes())},s:function(e){return e.getSeconds()},ss:function(e){return d(e.getSeconds())},S:function(e){return Math.round(e.getMilliseconds()/100)},SS:function(e){return d(Math.round(e.getMilliseconds()/10),2)},SSS:function(e){return d(e.getMilliseconds(),3)},a:function(e,t){return e.getHours()<12?t.amPm[0]:t.amPm[1]},A:function(e,t){return e.getHours()<12?t.amPm[0].toUpperCase():t.amPm[1].toUpperCase()},ZZ:function(e){var t=e.getTimezoneOffset();return(t>0?"-":"+")+d(100*Math.floor(Math.abs(t)/60)+Math.abs(t)%60,4)}},b={d:["\\d\\d?",function(e,t){e.day=t}],Do:["\\d\\d?"+o,function(e,t){e.day=parseInt(t,10)}],M:["\\d\\d?",function(e,t){e.month=t-1}],yy:["\\d\\d?",function(e,t){var i=+(""+(new Date).getFullYear()).substr(0,2);e.year=""+(t>68?i-1:i)+t}],h:["\\d\\d?",function(e,t){e.hour=t}],m:["\\d\\d?",function(e,t){e.minute=t}],s:["\\d\\d?",function(e,t){e.second=t}],yyyy:["\\d{4}",function(e,t){e.year=t}],S:["\\d",function(e,t){e.millisecond=100*t}],SS:["\\d{2}",function(e,t){e.millisecond=10*t}],SSS:["\\d{3}",function(e,t){e.millisecond=t}],D:["\\d\\d?",u],ddd:[o,u],MMM:[o,h("monthNamesShort")],MMMM:[o,h("monthNames")],a:[o,function(e,t,i){var n=t.toLowerCase();n===i.amPm[0]?e.isPm=!1:n===i.amPm[1]&&(e.isPm=!0)}],ZZ:["[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z",function(e,t){var i,n=(t+"").match(/([+-]|\d\d)/gi);n&&(i=60*n[1]+parseInt(n[2],10),e.timezoneOffset="+"===n[0]?i:-i)}]};b.dd=b.d,b.dddd=b.ddd,b.DD=b.D,b.mm=b.m,b.hh=b.H=b.HH=b.h,b.MM=b.M,b.ss=b.s,b.A=b.a,s.masks={default:"ddd MMM dd yyyy HH:mm:ss",shortDate:"M/D/yy",mediumDate:"MMM d, yyyy",longDate:"MMMM d, yyyy",fullDate:"dddd, MMMM d, yyyy",shortTime:"HH:mm",mediumTime:"HH:mm:ss",longTime:"HH:mm:ss.SSS"},s.format=function(e,t,i){var n=i||s.i18n;if("number"==typeof e&&(e=new Date(e)),"[object Date]"!==Object.prototype.toString.call(e)||isNaN(e.getTime()))throw new Error("Invalid Date in fecha.format");t=s.masks[t]||t||s.masks.default;var r=[];return(t=(t=t.replace(l,function(e,t){return r.push(t),"@@@"})).replace(a,function(t){return t in g?g[t](e,n):t.slice(1,t.length-1)})).replace(/@@@/g,function(){return r.shift()})},s.parse=function(e,t,i){var n=i||s.i18n;if("string"!=typeof t)throw new Error("Invalid format in fecha.parse");if(t=s.masks[t]||t,e.length>1e3)return null;var r={},o=[],u=[];t=t.replace(l,function(e,t){return u.push(t),"@@@"});var c,h=(c=t,c.replace(/[|\\{()[^$+*?.-]/g,"\\$&")).replace(a,function(e){if(b[e]){var t=b[e];return o.push(t[1]),"("+t[0]+")"}return e});h=h.replace(/@@@/g,function(){return u.shift()});var d=e.match(new RegExp(h,"i"));if(!d)return null;for(var p=1;pe?u():!0!==t&&(r=setTimeout(n?function(){r=void 0}:u,void 0===n?e-o:e))}}},function(e,t){var i=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=i)},function(e,t){var i=/^(attrs|props|on|nativeOn|class|style|hook)$/;function n(e,t){return function(){e&&e.apply(this,arguments),t&&t.apply(this,arguments)}}e.exports=function(e){return e.reduce(function(e,t){var r,s,a,o,l;for(a in t)if(r=e[a],s=t[a],r&&i.test(a))if("class"===a&&("string"==typeof r&&(l=r,e[a]=r={},r[l]=!0),"string"==typeof s&&(l=s,t[a]=s={},s[l]=!0)),"on"===a||"nativeOn"===a||"hook"===a)for(o in s)r[o]=n(r[o],s[o]);else if(Array.isArray(r))e[a]=r.concat(s);else if(Array.isArray(s))e[a]=[r].concat(s);else for(o in s)r[o]=s[o];else e[a]=t[a];return e},{})}},function(e,t){var i={}.hasOwnProperty;e.exports=function(e,t){return i.call(e,t)}},function(e,t,i){"use strict";t.__esModule=!0;var n,r=i(56),s=(n=r)&&n.__esModule?n:{default:n};t.default=s.default||function(e){for(var t=1;t0?n:i)(e)}},function(e,t,i){var n=i(28)("keys"),r=i(21);e.exports=function(e){return n[e]||(n[e]=r(e))}},function(e,t,i){var n=i(14),r=i(5),s=r["__core-js_shared__"]||(r["__core-js_shared__"]={});(e.exports=function(e,t){return s[e]||(s[e]=void 0!==t?t:{})})("versions",[]).push({version:n.version,mode:i(20)?"pure":"global",copyright:"© 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t){t.f=Object.getOwnPropertySymbols},function(e,t){e.exports={}},function(e,t,i){var n=i(10).f,r=i(7),s=i(13)("toStringTag");e.exports=function(e,t,i){e&&!r(e=i?e:e.prototype,s)&&n(e,s,{configurable:!0,value:t})}},function(e,t,i){t.f=i(13)},function(e,t,i){var n=i(5),r=i(14),s=i(20),a=i(33),o=i(10).f;e.exports=function(e){var t=r.Symbol||(r.Symbol=s?{}:n.Symbol||{});"_"==e.charAt(0)||e in t||o(t,e,{value:a.f(e)})}},function(e,t,i){var n=i(4),r=i(1);e.exports={throttle:n,debounce:r}},function(e,t,i){e.exports=!i(11)&&!i(16)(function(){return 7!=Object.defineProperty(i(37)("div"),"a",{get:function(){return 7}}).a})},function(e,t,i){var n=i(15),r=i(5).document,s=n(r)&&n(r.createElement);e.exports=function(e){return s?r.createElement(e):{}}},function(e,t,i){var n=i(7),r=i(12),s=i(62)(!1),a=i(27)("IE_PROTO");e.exports=function(e,t){var i,o=r(e),l=0,u=[];for(i in o)i!=a&&n(o,i)&&u.push(i);for(;t.length>l;)n(o,i=t[l++])&&(~s(u,i)||u.push(i));return u}},function(e,t,i){var n=i(40);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==n(e)?e.split(""):Object(e)}},function(e,t){var i={}.toString;e.exports=function(e){return i.call(e).slice(8,-1)}},function(e,t,i){var n=i(25);e.exports=function(e){return Object(n(e))}},function(e,t,i){"use strict";var n=i(20),r=i(23),s=i(43),a=i(9),o=i(31),l=i(69),u=i(32),c=i(72),h=i(13)("iterator"),d=!([].keys&&"next"in[].keys()),p=function(){return this};e.exports=function(e,t,i,f,m,v,g){l(i,t,f);var b,y,w,_=function(e){if(!d&&e in S)return S[e];switch(e){case"keys":case"values":return function(){return new i(this,e)}}return function(){return new i(this,e)}},x=t+" Iterator",C="values"==m,k=!1,S=e.prototype,D=S[h]||S["@@iterator"]||m&&S[m],$=D||_(m),E=m?C?_("entries"):$:void 0,T="Array"==t&&S.entries||D;if(T&&(w=c(T.call(new e)))!==Object.prototype&&w.next&&(u(w,x,!0),n||"function"==typeof w[h]||a(w,h,p)),C&&D&&"values"!==D.name&&(k=!0,$=function(){return D.call(this)}),n&&!g||!d&&!k&&S[h]||a(S,h,$),o[t]=$,o[x]=p,m)if(b={values:C?$:_("values"),keys:v?$:_("keys"),entries:E},g)for(y in b)y in S||s(S,y,b[y]);else r(r.P+r.F*(d||k),t,b);return b}},function(e,t,i){e.exports=i(9)},function(e,t,i){var n=i(17),r=i(70),s=i(29),a=i(27)("IE_PROTO"),o=function(){},l=function(){var e,t=i(37)("iframe"),n=s.length;for(t.style.display="none",i(71).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("
\ No newline at end of file
diff --git a/src/main/resources/templates/layout/default.ftl b/src/main/resources/templates/layout/default.ftl
index fa93dd2..ac31e87 100644
--- a/src/main/resources/templates/layout/default.ftl
+++ b/src/main/resources/templates/layout/default.ftl
@@ -1,7 +1,7 @@
-
+ ${title?default("管理系统")}
diff --git a/src/main/resources/templates/nginx.conf.ftl b/src/main/resources/templates/nginx.conf.ftl
deleted file mode 100644
index 461fab3..0000000
--- a/src/main/resources/templates/nginx.conf.ftl
+++ /dev/null
@@ -1,66 +0,0 @@
-
-#user nobody;
-worker_processes 1;
-
-#error_log logs/error.log;
-#error_log logs/error.log notice;
-#error_log logs/error.log info;
-
-#pid logs/nginx.pid;
-
-
-events {
- worker_connections 1024;
-}
-
-
-http {
- include mime.types;
- default_type application/octet-stream;
-
- #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
- # '$status $body_bytes_sent "$http_referer" '
- # '"$http_user_agent" "$http_x_forwarded_for"';
-
- #access_log logs/access.log main;
-
- sendfile on;
- #tcp_nopush on;
-
- #keepalive_timeout 0;
- keepalive_timeout 65;
-
- #gzip on;
-<#list services?keys as key>
-
- server {
- listen ${key};
- server_name localhost;
-
-<#list services[key] as mapping>
-<#if mapping.type="HTTP">
- location ${mapping.path} {
- proxy_pass ${mapping.location};
- proxy_set_header Host $remote_addr:$server_port;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header request_uri $scheme://$remote_addr:$server_port$request_uri;
- proxy_set_header proxy_context ${mapping.path};
- index index.html index.htm index.jsp index.do;
- }
-<#elseif mapping.type="FILE">
- location ${mapping.path} {
- root ${mapping.location};
- index index.html index.htm;
- autoindex on;
- }
-#if>
-#list>
-
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root html;
- }
- }
-#list>
-}
diff --git a/src/main/resources/templates/screen/admin/config.ftl b/src/main/resources/templates/screen/admin/config.ftl
new file mode 100644
index 0000000..94a2dfe
--- /dev/null
+++ b/src/main/resources/templates/screen/admin/config.ftl
@@ -0,0 +1,289 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+ <#if token.hasRes("/ajax/admin/config/create")>
+ 新增
+ #if>
+ <#if token.hasRes("/ajax/admin/config/delete")>
+ 删除
+ #if>
+
+
+
+ <#if token.hasRes("/ajax/admin/config/template")>
+
+
+
+ #if>
+
+ <#if token.hasRes("/ajax/admin/config/imports")>
+
+
+
+ #if>
+
+ <#if token.hasRes("/ajax/admin/config/exports")>
+
+
+
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 全局配置
+ 主机配置
+ 路径配置
+
+
+
+
+
+
+
+
+
+
+
+ <#if token.hasRes("/ajax/admin/config/update")>
+ 编辑
+ #if>
+ <#if token.hasRes("/ajax/admin/config/delete")>
+ 删除
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/screen/admin/locations.ftl b/src/main/resources/templates/screen/admin/locations.ftl
new file mode 100644
index 0000000..7b4f8d7
--- /dev/null
+++ b/src/main/resources/templates/screen/admin/locations.ftl
@@ -0,0 +1,355 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+ <#if token.hasRes("/ajax/admin/locations/create")>
+ 新增
+ #if>
+ <#if token.hasRes("/ajax/admin/locations/delete")>
+ 删除
+ #if>
+
+
+
+ <#if token.hasRes("/ajax/admin/locations/template")>
+
+
+
+ #if>
+
+ <#if token.hasRes("/ajax/admin/locations/imports")>
+
+
+
+ #if>
+
+ <#if token.hasRes("/ajax/admin/locations/exports")>
+
+
+
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 是
+ 否
+
+
+
+
+ 是
+ 否
+
+
+
+
+
+
+
+
+
+ <#if token.hasRes("/ajax/admin/locations/update")>
+ 编辑
+ #if>
+ <#if token.hasRes("/ajax/admin/locations/delete")>
+ 删除
+ #if>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/screen/helpDev.ftl b/src/main/resources/templates/screen/helpDev.ftl
new file mode 100644
index 0000000..f2e31fd
--- /dev/null
+++ b/src/main/resources/templates/screen/helpDev.ftl
@@ -0,0 +1,1591 @@
+
+
+
+
+
+ 主要颜色
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 中性色
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 主要框架
+
+
+ -
+ SpringBoot v2.1.2.RELEASE
+
+ -
+ Ehcache v-2.6.11 缓存框架
+
+ -
+ Freemarker v2.1.2.RELEASE
+ Html模板引擎
+
+ -
+ pagehelper v1.2.5
+ 分页插件、提供便捷的分页功能
+
+ -
+ dozer v5.5.1
+ 对象复制拷贝
+
+ -
+ logback v1.2.3
+ 日志框架
+
+ -
+ easyexcel 2.2.6
+ EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
+
+ -
+ jQuery v3.2.1
+ 前端JavaScript框架(保留),打包进base.min.js,但请尽量勿使用jQuery直接操作Dom
+
+ -
+ Vue v2.5.17
+ DOM渲染引擎
+
+ -
+ ElementUI v2.8.2
+ 前端UI框架,提供统一风格控件
+
+ -
+ Maven
+ 后端构建管理工具
+
+ -
+ JDK 8+
+ SpringBoot2.x开始不再支持JDK 7及以下,所以请将JDk升级到8+
+
+
+
+
+
+
+
+
+
+
+ 占位输出
+
+
+ 正常输出
+ ${r'${hello}'}
+
+
+ 输出带默认值
+ ${r'${hello?default("默认")}'}
+
+
+ HTML输出
+ ${r"${'<a>a标签</a>'?html}"}
+
+
+ $表达式
+ ${r"${r'${hello}'}"}
+
+
+ 布尔值输出
+ ${r"${true?c}"}
+
+
+ 三元表达式
+ ${r"${true?string('yes','no')}"}
+
+
+ 输出当前日期
+ ${r'${.now?string["yyyy-MM-dd HH:mm:ss"]}'}
+
+
+
+
+
+
+
+ 条件输出
+
+
+ ${'<#if status == 0>'}
+
+ status is 0
+
+ ${'<#elseif status ==1>'}
+
+ status = 1
+
+ ${'<#else>'}
+
+ status != 0 && status !=1
+
+ ${'</#if>'}
+
+
+
+
+
+
+
+ 遍历集合
+
+
+ ${'<#list citys as city>'}
+
+ ${r' ${city_index} --> ${city}'}
+
+ ${'</#list>'}
+
+
+
+
+
+
+
+
+
1、表单控件集合及验证
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 立即创建
+ 重置
+
+
+
+
+
+
+
2、表格数据
+
+
+
+
+
+
+ {{ scope.row.date }}
+
+
+
+
+
+
+
+ 编辑
+
+ 删除
+
+
+
+
+
+
+
+
+
+
3、分页
+
+
+
+
+
+
+
+
+
+
4、按钮
+
+
+
+ 默认按钮
+ 主要按钮
+ 成功按钮
+ 信息按钮
+ 警告按钮
+ 危险按钮
+
+
+
+ 朴素按钮
+ 主要按钮
+ 成功按钮
+ 信息按钮
+ 警告按钮
+ 危险按钮
+
+
+
+ 圆角按钮
+ 主要按钮
+ 成功按钮
+ 信息按钮
+ 警告按钮
+
+
+
+ 危险按钮
+ 加载中
+
+
+
+
+
+
+
+
+
+ 默认按钮
+ 主要按钮
+ 成功按钮
+ 信息按钮
+ 警告按钮
+ 危险按钮
+
+
+
+ 朴素按钮
+ 主要按钮
+ 成功按钮
+ 信息按钮
+ 警告按钮
+ 危险按钮
+
+
+ 文字按钮
+ 文字按钮
+
+
+
+
+
+ 搜索
+ 上传
+
+
+
+
+ 上一页
+ 下一页
+
+
+
+
+
+
+
+
+
+ 默认按钮
+ 中等按钮
+ 小型按钮
+ 超小按钮
+
+
+ 默认按钮
+ 中等按钮
+ 小型按钮
+ 超小按钮
+
+
+
+
+
+
5、Link 文字链接
+
+
+
+ 默认链接
+ 主要链接
+ 成功链接
+ 警告链接
+ 危险链接
+ 信息链接
+
+
+
+ 默认链接
+ 主要链接
+ 成功链接
+ 警告链接
+ 危险链接
+ 信息链接
+
+
+
+ 无下划线
+ 有下划线
+ 编辑
+ 查看
+
+
+
+
+
+
6、Tabs 标签页
+
+
+
+ 用户管理
+ 配置管理
+ 角色管理
+ 定时任务补偿
+
+
+
+ Tabs位置共有4个位置分别为:
+
+ top
+
+ right
+
+ bottom
+
+ left
+
+
+
+
+
+
7、弹框、对话框、通知
+
+
+
+
+ 消息
+
+
+ 通知
+
+
+ 消息Box
+
+
+ 消息确认Box
+
+
+
+ hover 激活
+
+
+
+
+ 对话框Dialog
+
+
+ 这是一段信息
+
+
+
+
+
+
+
+
+
+
6、其他小控件
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 标签一
+ 标签二
+ 标签三
+ 标签四
+ 标签五
+
+
+
+ 标签一
+ 标签二
+ 标签三
+ 标签四
+ 标签五
+
+
+
+ 默认标签
+ 中等标签
+ 小型标签
+ 超小标签
+
+
+
+
+ 评论
+
+
+ 回复
+
+
+ 评论
+
+
+ 回复
+
+
+ 数据查询
+
+
+
+
+
+
+
+ 评论(最大值)
+
+
+ 回复(最大值)
+
+
+
+ 评论
+
+
+ 回复
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 首页
+ 活动管理
+ 活动列表
+ 活动详情
+
+
+
+
+
+ 下拉菜单
+
+ 黄金糕
+ 狮子头
+ 螺蛳粉
+ 双皮奶
+ 蚵仔煎
+
+
+
+
+ 默认尺寸
+
+ 黄金糕
+ 狮子头
+ 螺蛳粉
+ 双皮奶
+ 蚵仔煎
+
+
+
+
+ 中等尺寸
+
+ 黄金糕
+ 狮子头
+ 螺蛳粉
+ 双皮奶
+ 蚵仔煎
+
+
+
+
+ 小型尺寸
+
+ 黄金糕
+ 狮子头
+ 螺蛳粉
+ 双皮奶
+ 蚵仔煎
+
+
+
+
+ 超小尺寸
+
+ 黄金糕
+ 狮子头
+ 螺蛳粉
+ 双皮奶
+ 蚵仔煎
+
+
+
+
+ 头上一片晴天,心中一个想念
+ 少年包青天
+ 饿了别叫妈, 叫饿了么
+
+ 为了无法计算的价值
+ 阿里云
+
+
+
+ 雨纷纷
+
+ 旧故里
+
+ 草木深
+
+
+
+
+
+
+
+
+
+
+
+
Vue动画
+
+
+ 淡入动画
+
+ ${''?html}
+ ${''?html}
+
+ zoom 缩放
+
+ ${''?html}
+ ${''?html}
+ ${''?html}
+
+ 折叠动画
+
+ ${''?html}
+
+ 左进右出动画
+
+ ${''?html}
+
+ 右进左出动画
+
+ ${''?html}
+
+
+
+
+
+
CSS动画
+
+
+ 淡入动画
+
+ ${'
'?html}
+
+ 淡出动画
+
+ ${'
'?html}
+
+ 从底部淡入动画
+
+ ${'
'?html}
+
+ 从顶部淡出动画
+
+ ${'
'?html}
+
+ 震颤(抖动)动画
+
+ ${'
'?html}
+
+ 无限旋转动画
+
+ ${'
'?html}
+
+
+
+
+
+
+
+
+ 调用AJAX接口
+
+
+
+ new Ajax("wadmin", "user", "find").post({}, function (response) {
+ if (response.errors.length > 0) {
+ nav.e(response.errors[0].message);
+ } else {
+ nav.i("Ajax调用成功!");
+ }
+ }.bind(this))
+
+
+
+
+ 点击上传
+ 只能上传jpg/png文件,且不超过500kb
+
+
+
+
+ new Ajax("wadmin","file","upload").post(req.file,function (response) {
+ if (response.errors.length > 0) {
+ req.onError();
+ nav.e(response.errors[0].message);
+ } else {
+ req.onSuccess();
+ nav.i("文件上传成功!");
+ }
+ }.bind(this))
+
+
+
+
+
+
+
+
+ 开始推送
+
+ 停止推送
+
+
+
+ var evtSource = new EventSource('http://localhost:8080/sse/1');
+
+ evtSource.addEventListener('message', function (e) {
+
+ console.log(e.data);
+
+ });
+
+
+
+
+
+
+ 普通消息
+ 错误消息
+ 成功消息
+ 警告消息
+
+
+
+ nav.i('消息')
+ nav.e('错误')
+ nav.s('成功')
+ nav.w('警告')
+
+
+
+ 加载提示框
+ 关闭提示框
+
+
+
+ nav.tipShow('加载中')
+ nav.tipClose()
+
+
+
+ 请求进度条
+ 成功
+ 失败
+
1、最终调用index对象的barStart(),barFinish(),barError();
+
+
+
+ nav.barShow()
+ nav.barFinish()
+ nav.barError()
+
+
+
+ 简单对话框(确认)
+ 示例
+
+ 简单对话框(确认取消)
+ 示例
+
+ 简单对话框(输入)
+ 示例
+
+ 简单对话框(HTML)
+ 你好!')">示例
+
+
+
+ nav.boxYes(title, message, callback)
+ nav.boxYesNo(title, message, callback)
+ nav.boxInput(title, message, callback)
+ nav.boxHtml(title, htmlMessage, callback)
+
+
+
+ 切换网页全屏,取消网页全屏
+ 全屏
+ 取消全屏
+
+
+
+ nav.screenFull()
+ nav.screenNotFull()
+
+
+
+ 设置Cookie
+
+
+
+ nav.setCookie(name, value, expiretime)
+ nav.getCookie(name)
+ nav.clearCookie(name)
+
+
+
+
+
+ 回到或打开HOME页
+
+
+
+ index.onHome()
+
+
+
+ 请求进度条
+
+
+
+ index.barStart()
+ index.barFinish()
+ index.barError()
+
+
+
+ 左侧菜单收缩切换方法
+
+
+
+ index.collapseSwitch()
+
+
+
+ 网页全屏切换方法
+
1、最终调用nav对象的nav.screenFull()和nav.screenNotFull()
+
+
+
+ index.switchFullScreen()
+
+
+
+ 添加新Tab
+
+
+
+ var tab = {
+ title: '首页',
+ name: 'home',
+ url: '/home.htm'
+ }
+ index.addTab(tab)
+
+
+
+ 移除Tab
+
+
+
+ index.removeTab(tabName)
+
+
+
+
+ 所有js相关基本方法皆以打包进lib.min.js文件
+
+
+ 获取url参数
+
+
+
+ $.getSearchParam('id')
+
+
+
+ 打开游览器新标签
+
+
+
+ $w.openUrl('www.baidu.com')
+
+
+
+ 日期格式化
+
+
+
+ new Date().format('yyyy-MM-dd hh:mm:ss')
+
+
+
+ 数组移除
+
+
+
+ var arr = ['A', 'B'];
+ arr.remove('A')
+
+
+
+ 数组替换
+
+
+
+ var arr = ['A', 'B'];
+ arr.replace('A', 'C')
+
+
+
+ 数组位置调整
+
+
+
+ var arr = ['A', 'B'];
+ arr.exchange(0, 1)
+
+
+
+ 数组异步循环
+
+
+
+ var arr = ['A', 'B'];
+ arr.forAsync(function (item, next) {
+ setTimeout(function () {
+ console.log(item);
+ next();
+ }, 1000)
+ })
+
+
+
+ 数组异步循环(完成通知)
+
+
+
+ var arr = ['A', 'B'];
+ arr.forAsync(function (item, next) {
+ setTimeout(function () {
+ console.log(item);
+ next();
+ }, 1000)
+ }, function () {
+ nav.i("异步循环完成.");
+ })
+
+
+
+ 数组递归循环
+
1、forTree第二参数为子类属性,默认为[children]
+
+
+
+ var arr = [{
+ name: 'A',
+ children: [
+ {name: 'AA'},
+ {name: 'AB'},
+ ]
+ }]
+ arr.forTree(function (item) {
+ console.log(item.name)
+ })
+
+
+
+ 数组递归循环(处理函数可以知道当前循环深度)
+
+
+
+ var arr = [{
+ name: 'A',
+ children: [
+ {name: 'AA'},
+ {name: 'AB'},
+ ]
+ }]
+ arr.forTreeDepth(function (item, depth) {
+ console.log(item.name);
+ console.log(depth);//[0],[0, 0],[0, 1]
+ })
+
+
+
+ 自定义Map对象
+
1、放置对象 map.put(key, value)
+
2、获取对象 map.get(key)
+
3、获取键集合 map.getKeys()
+
4、获取对象集合 map.getValues()
+
5、移除对象 map.remove(key)
+
6、返回大小 map.size()
+
7、判断是否为空 map.isEmpty()
+
8、清空 map.clear()
+
9、是否包含键 map.containsKey(key)
+
10、是否包含值 map.containsValue(value)
+
11、循环 map.forEach(callBack) // 函数接收两个参数(key, value)
+
12、异步循环 map.forAsync(callBack, finish) // 函数接收两个参数(key, value),完成函数(可选)
+
+
+
+ var map = new Map();
+ map.put("name", "hello world!");
+ console.log(map.get("name"));
+
+
+
+ 文件选择 $w.selectFile(cb)
+
+
+
+ $w.selectFile(function (files) {
+ new Ajax("wadmin","file","upload").post(files[0],function (response) {
+ if (response.errors.length > 0) {
+ nav.e(response.errors[0].message);
+ } else {
+ nav.i("文件上传成功!");
+ }
+ })
+ })
+
+
+
+ Blob二进制文件异步下载
+
+
+
+ $w.blobtoDown(name, blob)
+
+
+
+ base64转为String
+
+
+
+ $w.base64toString(base64)
+
+
+
+ String转为base64
+
+
+
+ $w.stringtoBase64(str)
+
+
+
+ base64转为字节数组
+
+
+
+ $w.base64toBytes(base64)
+
+
+
+ base64字符转Blob对象
+
+
+
+ $w.base64toBlob(base64)
+
+
+
+ 动态加载Js或css文件
+
+
+
+ $w.loadJsCss(url)
+
+
+
+ 深拷贝对象
+
+
+
+ $w.copy(obj)
+
+
+
+
+
+
+
1、页面初始化前闪现源代码
+
+
+ ${''?html}
+
+
+ ${'
'?html}
+
+
${'...'?html}
+
+
${'
'?html}
+
+
+
+
+
2、为什么Long类型返回json字符串变为String
+
+
+ 因为Long可支持的长度比JavaScript中Number支持的位数更多,所以当Long数值很大时转为Json再转为Number就会丢失精度,造成难以发现的Bug,所以本系统默认处理了该问题。
+
+
+
+
+
3、Date类型格式化问题
+
+
+ 默认启用全局Date格式化
+ yyyy-MM-dd HH:mm:ss
+ ,需要关闭请在
+ application-*
+ 中关闭。
+
+
+ 对于个别返回结果的Date格式化可以通过注解方式
+ @JsonFormat(pattern = "yyyy-MM-dd")
+
+
+
+
+
+
+
4、权限问题
+
+
+ 1、本系统启用自定义Token来控制权限,任何访问都会有一个全局Token,任何一处都可以通过
+ LocalData.getToken()
+ 来获取
+ 当前访问对象的Token。其中Token充当着访问对象的通行证,其中包含访问对象的
+ 用户ID
+ 、
+ 用户名
+ 、
+ 可访问资源
+ 等信息。
+
+
+ 2、对于未登录对象会提供临时(访客)
+ LocalData.getTempToken()
+ (有限的权限)来提供访问系统。
+
+
+ 3、如果系统存在Task等定时任务时,是不存在访问对象,通过
+ LocalData.getSystemToken()
+ 来获取系统层的Token来操作系统。
+
+
+
+
+
+
+
5、Token配置
+
+
+ Springboot环境配置文件application-*中配置了系统中需要验证权限和不需要验证的url。而需要验证权限的URl会在
+ SecurityConfig.getAuthorization()
+ 方法中通过Parameter或Cookies中获取当前访问对象的登录信息,从而为当前访问对象组装Token对象。
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/screen/login.ftl b/src/main/resources/templates/screen/login.ftl
index fea5e3f..dd000a2 100644
--- a/src/main/resources/templates/screen/login.ftl
+++ b/src/main/resources/templates/screen/login.ftl
@@ -1,18 +1,39 @@
-
+
+
+
+
系统登录
-
+
-
+
+
+
+
+
+
+
+
+
+
- 登录
+ 登录
+
@@ -22,32 +43,35 @@
diff --git a/src/test/java/xyz/wbsite/admin/ConfigDataTest.java b/src/test/java/xyz/wbsite/admin/ConfigDataTest.java
new file mode 100644
index 0000000..2eae83e
--- /dev/null
+++ b/src/test/java/xyz/wbsite/admin/ConfigDataTest.java
@@ -0,0 +1,116 @@
+package xyz.wbsite.admin;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+import xyz.wbsite.frame.base.Token;
+import xyz.wbsite.module.admin.mgr.ConfigDataManager;
+import xyz.wbsite.module.admin.req.ConfigDataCreateRequest;
+import xyz.wbsite.module.admin.req.ConfigDataDeleteRequest;
+import xyz.wbsite.module.admin.req.ConfigDataFindRequest;
+import xyz.wbsite.module.admin.req.ConfigDataUpdateRequest;
+import xyz.wbsite.module.admin.rsp.ConfigDataCreateResponse;
+import xyz.wbsite.module.admin.rsp.ConfigDataDeleteResponse;
+import xyz.wbsite.module.admin.rsp.ConfigDataFindResponse;
+import xyz.wbsite.module.admin.rsp.ConfigDataUpdateResponse;
+
+import static junit.framework.TestCase.assertTrue;
+
+/**
+ * ConfigDataTest - - 配置数据测试用例
+ *
+ * @author wangbing
+ * @version 0.0.1
+ * @since 2021-02-07
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Transactional
+public class ConfigDataTest {
+
+ @Autowired
+ private Token token;
+
+ @Autowired
+ private ConfigDataManager configDataManager;
+
+ @Test
+ public void testCreate() {
+ ConfigDataCreateRequest request = new ConfigDataCreateRequest();
+ request.setTargetId(1L);
+ request.setConfName("配置名称");
+ request.setConfType("value");
+ request.setConfValue("配置属值");
+ request.setConfNote("配置备注");
+
+ ConfigDataCreateResponse response = configDataManager.create(request,token);
+
+ assertTrue(!response.hasError());
+ }
+
+ @Test
+ public void testDelete() {
+
+ //创建数据
+ ConfigDataCreateRequest createRequest = new ConfigDataCreateRequest();
+ createRequest.setTargetId(1L);
+ createRequest.setConfName("配置名称");
+ createRequest.setConfType("value");
+ createRequest.setConfValue("配置属值");
+ createRequest.setConfNote("配置备注");
+
+ ConfigDataCreateResponse createResponse = configDataManager.create(createRequest,token);
+
+ assertTrue(!createResponse.hasError() && createResponse.getId() > 0);
+ //删除数据
+ ConfigDataDeleteRequest request = new ConfigDataDeleteRequest();
+ request.setId(createResponse.getId());
+
+ ConfigDataDeleteResponse response = configDataManager.delete(request,token);
+
+ assertTrue(!response.hasError() && response.getResult() == 1L);
+ }
+
+ @Test
+ public void testUpdate() {
+ //创建数据
+ ConfigDataCreateRequest createRequest = new ConfigDataCreateRequest();
+ createRequest.setTargetId(1L);
+ createRequest.setConfName("配置名称");
+ createRequest.setConfType("value");
+ createRequest.setConfValue("配置属值");
+ createRequest.setConfNote("配置备注");
+
+ ConfigDataCreateResponse createResponse = configDataManager.create(createRequest, token);
+
+ assertTrue(!createResponse.hasError());
+
+ //更新数据
+ ConfigDataUpdateRequest request = new ConfigDataUpdateRequest();
+ request.setId(createResponse.getId());
+ request.setTargetId(1L);
+ request.setConfName("配置名称");
+ request.setConfType("value");
+ request.setConfValue("配置属值");
+ request.setConfNote("配置备注");
+
+ ConfigDataUpdateResponse response = configDataManager.update(request,token);
+
+ assertTrue(!response.hasError() && response.getResult() == 1L);
+ }
+
+ @Test
+ public void testFind() {
+ ConfigDataFindRequest request = new ConfigDataFindRequest();
+ request.setTargetId(1L);
+ request.setConfName("配置名称");
+ request.setConfType("value");
+
+ ConfigDataFindResponse response = configDataManager.find(request,token);
+
+ assertTrue(!response.hasError());
+ }
+}
diff --git a/src/test/java/xyz/wbsite/admin/ConfigTest.java b/src/test/java/xyz/wbsite/admin/ConfigTest.java
new file mode 100644
index 0000000..c2cd94d
--- /dev/null
+++ b/src/test/java/xyz/wbsite/admin/ConfigTest.java
@@ -0,0 +1,111 @@
+package xyz.wbsite.admin;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+import xyz.wbsite.frame.base.Token;
+import xyz.wbsite.module.admin.mgr.ConfigManager;
+import xyz.wbsite.module.admin.req.ConfigCreateRequest;
+import xyz.wbsite.module.admin.req.ConfigDeleteRequest;
+import xyz.wbsite.module.admin.req.ConfigFindRequest;
+import xyz.wbsite.module.admin.req.ConfigUpdateRequest;
+import xyz.wbsite.module.admin.rsp.ConfigCreateResponse;
+import xyz.wbsite.module.admin.rsp.ConfigDeleteResponse;
+import xyz.wbsite.module.admin.rsp.ConfigFindResponse;
+import xyz.wbsite.module.admin.rsp.ConfigUpdateResponse;
+
+import static junit.framework.TestCase.assertTrue;
+
+/**
+ * ConfigTest - - 配置预设测试用例
+ *
+ * @author wangbing
+ * @version 0.0.1
+ * @since 2021-02-07
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Transactional
+public class ConfigTest {
+
+ @Autowired
+ private Token token;
+
+ @Autowired
+ private ConfigManager configManager;
+
+ @Test
+ public void testCreate() {
+ ConfigCreateRequest request = new ConfigCreateRequest();
+ request.setConfName("配置名称");
+ request.setConfType("value");
+ request.setConfValue("配置属值");
+ request.setConfNote("配置备注");
+
+ ConfigCreateResponse response = configManager.create(request,token);
+
+ assertTrue(!response.hasError());
+ }
+
+ @Test
+ public void testDelete() {
+
+ //创建数据
+ ConfigCreateRequest createRequest = new ConfigCreateRequest();
+ createRequest.setConfName("配置名称");
+ createRequest.setConfType("value");
+ createRequest.setConfValue("配置属值");
+ createRequest.setConfNote("配置备注");
+
+ ConfigCreateResponse createResponse = configManager.create(createRequest,token);
+
+ assertTrue(!createResponse.hasError() && createResponse.getId() > 0);
+ //删除数据
+ ConfigDeleteRequest request = new ConfigDeleteRequest();
+ request.setId(createResponse.getId());
+
+ ConfigDeleteResponse response = configManager.delete(request,token);
+
+ assertTrue(!response.hasError() && response.getResult() == 1L);
+ }
+
+ @Test
+ public void testUpdate() {
+ //创建数据
+ ConfigCreateRequest createRequest = new ConfigCreateRequest();
+ createRequest.setConfName("配置名称");
+ createRequest.setConfType("value");
+ createRequest.setConfValue("配置属值");
+ createRequest.setConfNote("配置备注");
+
+ ConfigCreateResponse createResponse = configManager.create(createRequest, token);
+
+ assertTrue(!createResponse.hasError());
+
+ //更新数据
+ ConfigUpdateRequest request = new ConfigUpdateRequest();
+ request.setId(createResponse.getId());
+ request.setConfName("配置名称");
+ request.setConfType("value");
+ request.setConfValue("配置属值");
+ request.setConfNote("配置备注");
+
+ ConfigUpdateResponse response = configManager.update(request,token);
+
+ assertTrue(!response.hasError() && response.getResult() == 1L);
+ }
+
+ @Test
+ public void testFind() {
+ ConfigFindRequest request = new ConfigFindRequest();
+ request.setConfName("配置名称");
+ request.setConfType("value");
+
+ ConfigFindResponse response = configManager.find(request,token);
+
+ assertTrue(!response.hasError());
+ }
+}
diff --git a/src/test/java/xyz/wbsite/admin/ServicesTest.java b/src/test/java/xyz/wbsite/admin/ServicesTest.java
new file mode 100644
index 0000000..876de5c
--- /dev/null
+++ b/src/test/java/xyz/wbsite/admin/ServicesTest.java
@@ -0,0 +1,127 @@
+package xyz.wbsite.admin;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+import xyz.wbsite.frame.base.Token;
+import xyz.wbsite.module.admin.mgr.ServicesManager;
+import xyz.wbsite.module.admin.req.ServicesCreateRequest;
+import xyz.wbsite.module.admin.req.ServicesDeleteRequest;
+import xyz.wbsite.module.admin.req.ServicesFindRequest;
+import xyz.wbsite.module.admin.req.ServicesUpdateRequest;
+import xyz.wbsite.module.admin.rsp.ServicesCreateResponse;
+import xyz.wbsite.module.admin.rsp.ServicesDeleteResponse;
+import xyz.wbsite.module.admin.rsp.ServicesFindResponse;
+import xyz.wbsite.module.admin.rsp.ServicesUpdateResponse;
+
+import static junit.framework.TestCase.assertTrue;
+
+/**
+ * ServicesTest - - 虚拟主机测试用例
+ *
+ * @author wangbing
+ * @version 0.0.1
+ * @since 2021-02-07
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Transactional
+public class ServicesTest {
+
+ @Autowired
+ private Token token;
+
+ @Autowired
+ private ServicesManager servicesManager;
+
+ @Test
+ public void testCreate() {
+ ServicesCreateRequest request = new ServicesCreateRequest();
+ request.setTitle("主机标题");
+ request.setDomain("主机域名");
+ request.setType("value");
+ request.setPort(1);
+ request.setValid(true);
+ request.setFilter(true);
+ request.setFilterConf("过滤配置");
+
+ ServicesCreateResponse response = servicesManager.create(request,token);
+
+ assertTrue(!response.hasError());
+ }
+
+ @Test
+ public void testDelete() {
+
+ //创建数据
+ ServicesCreateRequest createRequest = new ServicesCreateRequest();
+ createRequest.setTitle("主机标题");
+ createRequest.setDomain("主机域名");
+ createRequest.setType("value");
+ createRequest.setPort(1);
+ createRequest.setValid(true);
+ createRequest.setFilter(true);
+ createRequest.setFilterConf("过滤配置");
+
+ ServicesCreateResponse createResponse = servicesManager.create(createRequest,token);
+
+ assertTrue(!createResponse.hasError() && createResponse.getId() > 0);
+ //删除数据
+ ServicesDeleteRequest request = new ServicesDeleteRequest();
+ request.setId(createResponse.getId());
+
+ ServicesDeleteResponse response = servicesManager.delete(request,token);
+
+ assertTrue(!response.hasError() && response.getResult() == 1L);
+ }
+
+ @Test
+ public void testUpdate() {
+ //创建数据
+ ServicesCreateRequest createRequest = new ServicesCreateRequest();
+ createRequest.setTitle("主机标题");
+ createRequest.setDomain("主机域名");
+ createRequest.setType("value");
+ createRequest.setPort(1);
+ createRequest.setValid(true);
+ createRequest.setFilter(true);
+ createRequest.setFilterConf("过滤配置");
+
+ ServicesCreateResponse createResponse = servicesManager.create(createRequest, token);
+
+ assertTrue(!createResponse.hasError());
+
+ //更新数据
+ ServicesUpdateRequest request = new ServicesUpdateRequest();
+ request.setId(createResponse.getId());
+ request.setTitle("主机标题");
+ request.setDomain("主机域名");
+ request.setType("value");
+ request.setPort(1);
+ request.setValid(true);
+ request.setFilter(true);
+ request.setFilterConf("过滤配置");
+
+ ServicesUpdateResponse response = servicesManager.update(request,token);
+
+ assertTrue(!response.hasError() && response.getResult() == 1L);
+ }
+
+ @Test
+ public void testFind() {
+ ServicesFindRequest request = new ServicesFindRequest();
+ request.setTitle("主机标题");
+ request.setDomain("主机域名");
+ request.setType("value");
+ request.setPort(1);
+ request.setValid(true);
+ request.setFilter(true);
+
+ ServicesFindResponse response = servicesManager.find(request,token);
+
+ assertTrue(!response.hasError());
+ }
+}
diff --git a/src/test/java/xyz/wbsite/config/TestConfig.java b/src/test/java/xyz/wbsite/config/TestConfig.java
index e9222ce..8397358 100644
--- a/src/test/java/xyz/wbsite/config/TestConfig.java
+++ b/src/test/java/xyz/wbsite/config/TestConfig.java
@@ -1,11 +1,25 @@
package xyz.wbsite.config;
-import xyz.wbsite.frame.auth.Token;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import xyz.wbsite.frame.base.LocalData;
+import xyz.wbsite.frame.base.Token;
+
+import javax.annotation.PostConstruct;
+
@Configuration
public class TestConfig {
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ @PostConstruct
+ public void initLocalData() {
+ LocalData.setContext(applicationContext);
+ }
+
@Bean
public Token getTestToken() {
Token token = new Token();
diff --git a/src/test/java/xyz/wbsite/wframe/ExcelTest.java b/src/test/java/xyz/wbsite/wframe/ExcelTest.java
new file mode 100644
index 0000000..e940f31
--- /dev/null
+++ b/src/test/java/xyz/wbsite/wframe/ExcelTest.java
@@ -0,0 +1,74 @@
+package xyz.wbsite.wframe;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+import xyz.wbsite.frame.excel.DemoData;
+import xyz.wbsite.frame.excel.WExcel;
+import xyz.wbsite.frame.excel.exception.TemplateNotMatchException;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * ExcelTest - - 测试用例
+ *
+ * @author wangbing
+ * @version 0.0.1
+ * @since 2017-01-01
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@Transactional
+public class ExcelTest {
+
+ @Test
+ public void testExcel() throws IOException, TemplateNotMatchException {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ System.out.println("数据创建开始:" + dateFormat.format(new Date()));
+ // 写
+ List
visitors = new ArrayList<>();
+ for (int i = 0; i < 100; i++) {
+ DemoData demoData = new DemoData();
+ demoData.setStr1("我是标题Str1" + i);
+ demoData.setStr2("我是标题Str2" + i);
+ demoData.setStr3("我是标题Str3" + i);
+ demoData.setStr4("我是标题Str4" + i);
+ demoData.setSint((short) 1);
+ demoData.setMint(1);
+ demoData.setLint(1L);
+ demoData.setDbn(0.01);
+ demoData.setFln(0.01f);
+ demoData.setDate(new Date());
+ demoData.setValid(i % 5 == 0);
+ visitors.add(demoData);
+ }
+ System.out.println("数据创建完成:" + dateFormat.format(new Date()));
+ new WExcel<>(DemoData.class).addDatas(visitors, null).toFile(new File("D:\\xx.xlsx"));
+ System.out.println("数据导出完成:" + dateFormat.format(new Date()));
+
+ System.out.println();
+
+ // 读
+ System.out.println("数据导入开始:" + dateFormat.format(new Date()));
+ WExcel wExcel = new WExcel<>(DemoData.class).read(new File("D:\\xx.xlsx"), (demoData, index) -> {
+ if (index % 50 == 0) {
+ return Arrays.asList("测试,第" + index + "条有错误");
+ }
+ return null;
+ });
+ System.out.println("数据导入完成:" + dateFormat.format(new Date()));
+ System.out.println();
+ System.out.println("错误导出开始:" + dateFormat.format(new Date()));
+ wExcel.toFile(new File("D:\\xx-err.xlsx"));
+ System.out.println("错误导出结束:" + dateFormat.format(new Date()));
+ System.out.println();
+ }
+}
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index f07e94a..6420997 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -14,9 +14,9 @@ server.tomcat.uri-encoding=UTF-8
# 日志配置
logging.path=D://
logging.levels=DEBUG
-# SQLite spring.datasource.url=jdbc:sqlite::resource:example.db
+# SQLite spring.datasource.url=jdbc:sqlite::resource:example.db3
spring.datasource.driver-class-name=org.sqlite.JDBC
-spring.datasource.url=jdbc:sqlite:nginx-admin.db?date_string_format=yyyy-MM-dd HH:mm:ss
+spring.datasource.url=jdbc:sqlite:nginx-admin.db3?date_string_format=yyyy-MM-dd HH:mm:ss
spring.datasource.username=test
spring.datasource.password=123456
# mybatis
@@ -33,6 +33,11 @@ spring.jackson.time-zone=GMT+8
spring.jackson.default-property-inclusion=non_null
spring.jackson.mapper.sort-properties-alphabetically=true
spring.jackson.deserialization.fail-on-unknown-properties=false
+# 文件上传配置
+spring.servlet.multipart.resolveLazily=false
+spring.servlet.multipart.max-file-size=100MB
+spring.servlet.multipart.max-request-size=100MB
+server.tomcat.max-http-post-size=-1
# freemarker
spring.freemarker.enabled=true
spring.freemarker.allow-request-override=false
@@ -51,24 +56,16 @@ spring.freemarker.settings.number_format=#.##
spring.freemarker.settings.classic_compatible=true
spring.freemarker.settings.whitespace_stripping=true
spring.freemarker.settings.url_escaping_charset=utf-8
-# 文件上传配置
-spring.servlet.multipart.resolveLazily=false
-spring.servlet.multipart.max-file-size=100MB
-spring.servlet.multipart.max-request-size=100MB
-server.tomcat.max-http-post-size=-1
# 自定义配置
# 根路径默认页,'/'跳转至该页
-web.home.page=/index.htm
+web.url.index=/index.htm
# 登录页
-web.login.page=/login.htm
+web.url.login=/login.htm
# 拦截验证
web.url.auth.included=/,/**/*.htm,/ajax/**,/api/**
# 直接放行
-web.url.auth.excluded=/login.htm,/ajax/system/User/login
+web.url.auth.excluded=/login.htm,/ajax/wsys/User/login
# 超级管理员
web.url.auth.admin=admin
-web.url.auth.pwd=17fac3376f76d65943d1d26d1f7cb1e5
-
-nginx-path=
-mapping.default.port=80
\ No newline at end of file
+web.url.auth.pwd=17fac3376f76d65943d1d26d1f7cb1e5
\ No newline at end of file
diff --git a/wsqlite/src/main/java/xyz/wbsite/wsqlite/Client.java b/wsqlite/src/main/java/xyz/wbsite/wsqlite/Client.java
deleted file mode 100644
index 0cfe64d..0000000
--- a/wsqlite/src/main/java/xyz/wbsite/wsqlite/Client.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package xyz.wbsite.wsqlite;
-
-import java.io.File;
-import java.sql.*;
-
-/**
- * xyz.wbsite.wsqlite.Client
- *
- * @author wangbing
- */
-public class Client {
-
- Connection connection;
- ResultSet resultSet;
- String dbFilePath;
-
- /**
- * 构造函数
- *
- * @param dbFile 文件
- * @throws ClassNotFoundException
- * @throws SQLException
- */
- public Client(File dbFile) throws ClassNotFoundException, SQLException {
- this.dbFilePath = dbFile.getAbsolutePath();
- if (!dbFile.exists()) {
- connection = getConnection();
- }
- }
-
- /**
- * 执行sql语句
- *
- * @param sql
- * @throws SQLException
- * @throws ClassNotFoundException
- */
- public void execute(String sql) throws SQLException, ClassNotFoundException {
- try {
- executeUpdate(sql);
- } finally {
- destroyed();
- }
- }
-
- /**
- * 执行sql查询语句
- *
- * @param sql
- * @throws SQLException
- * @throws ClassNotFoundException
- */
- public ResultSet executeQuery(String sql, Object... args) throws SQLException, ClassNotFoundException {
- PreparedStatement preparedStatement = getConnection().prepareStatement(sql);
- setArg(preparedStatement, args);
- return preparedStatement.executeQuery();
- }
-
- /**
- * 执行sql语句
- *
- * @param sql
- * @throws SQLException
- * @throws ClassNotFoundException
- */
- public int executeUpdate(String sql, Object... args) throws SQLException, ClassNotFoundException {
- try {
- PreparedStatement preparedStatement = getConnection().prepareStatement(sql);
- setArg(preparedStatement, args);
- return preparedStatement.executeUpdate();
- } finally {
- destroyed();
- }
- }
-
- private void setArg(PreparedStatement ps, Object... args) throws SQLException {
- for (int i = 0; i < args.length; i++) {
- Object arg = args[i];
-
- if (arg == null) {
- ps.setNull(i + 1, Types.NULL);
- } else if (arg instanceof String) {
- ps.setString(i + 1, (String) arg);
- } else if (arg instanceof Date) {
- ps.setDate(i + 1, (Date) arg);
- } else if (arg instanceof Time) {
- ps.setTime(i + 1, (Time) arg);
- } else if (arg instanceof java.util.Date) {
- ps.setLong(i + 1, ((java.util.Date) arg).getTime());
- } else if (arg instanceof Boolean) {
- ps.setBoolean(i + 1, (Boolean) arg);
- } else if (arg instanceof Byte) {
- ps.setByte(i + 1, (Byte) arg);
- } else if (arg instanceof Short) {
- ps.setShort(i + 1, (Short) arg);
- } else if (arg instanceof Integer) {
- ps.setInt(i + 1, (int) arg);
- } else if (arg instanceof Long) {
- ps.setLong(i + 1, (long) arg);
- } else if (arg instanceof Float) {
- ps.setFloat(i + 1, (float) arg);
- } else if (arg instanceof Double) {
- ps.setDouble(i + 1, (double) arg);
- } else if (arg instanceof byte[]) {
- ps.setBytes(i + 1, (byte[]) arg);
- }
- }
- }
-
- /**
- * 获取数据库连接
- *
- * @return 数据库连接
- * @throws ClassNotFoundException
- * @throws SQLException
- */
- Connection getConnection() throws ClassNotFoundException, SQLException {
- if (null == connection) {
- Class.forName("org.sqlite.JDBC");
- connection = DriverManager.getConnection("jdbc:sqlite:" + dbFilePath);
- }
- return connection;
- }
-
- /**
- * 数据库资源关闭和释放
- */
- public void destroyed() {
-// try {
-// if (null != resultSet) {
-// resultSet.close();
-// resultSet = null;
-// }
-//
-// if (null != connection) {
-// connection.close();
-// connection = null;
-// }
-//
-// } catch (SQLException e) {
-// e.printStackTrace();
-// }
- }
-}
\ No newline at end of file
diff --git a/wsqlite/src/main/java/xyz/wbsite/wsqlite/ObjectClient.java b/wsqlite/src/main/java/xyz/wbsite/wsqlite/ObjectClient.java
deleted file mode 100644
index 6d643cf..0000000
--- a/wsqlite/src/main/java/xyz/wbsite/wsqlite/ObjectClient.java
+++ /dev/null
@@ -1,319 +0,0 @@
-package xyz.wbsite.wsqlite;
-
-import xyz.wbsite.wsqlite.anonation.TableField;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.sql.SQLException;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-/**
- * xyz.wbsite.wsqlite.Client
- *
- * @author wangbing
- */
-public class ObjectClient extends Client {
-
- private Map classMap = new HashMap<>();
-
- /**
- * 构造函数
- *
- * @param dbFile 文件
- * @param classList 注册对象
- * @throws ClassNotFoundException
- * @throws SQLException
- */
- public ObjectClient(File dbFile, List classList) throws ClassNotFoundException, SQLException {
- super(dbFile);
- for (Class aClass : classList) {
- classMap.put(aClass.getName(), aClass);
- }
- for (String key : classMap.keySet()) {
- Class object = classMap.get(key);
- StringBuffer sql = new StringBuffer();
- String name = object.getSimpleName();
-
- sql.append("CREATE TABLE IF NOT EXISTS ");
- sql.append(name);
- sql.append(" (");
-
- Field[] fields = object.getDeclaredFields();
- for (Field f : fields) {
- if (f.isAnnotationPresent(TableField.class)) {
- TableField bind = f.getAnnotation(TableField.class);
- int length = bind.value();
-
- if (f.getType() == String.class) {
- sql.append(f.getName().toUpperCase());
- sql.append(" VARCHAR(" + length + "),");
- } else if (f.getType() == Boolean.class || f.getType() == boolean.class) {
- sql.append(f.getName().toUpperCase());
- sql.append(" BOOLEAN,");
- } else if (f.getType() == Byte.class || f.getType() == byte.class ||
- f.getType() == Short.class || f.getType() == short.class ||
- f.getType() == Character.class || f.getType() == char.class ||
- f.getType() == Integer.class || f.getType() == int.class ||
- f.getType() == Long.class || f.getType() == long.class) {
- sql.append(f.getName().toUpperCase());
- sql.append(" INTEGER,");
- } else if (f.getType() == Float.class || f.getType() == float.class ||
- f.getType() == Double.class || f.getType() == double.class) {
- sql.append(f.getName().toUpperCase());
- sql.append(" REAL,");
- } else if (f.getType() == Byte[].class || f.getType() == byte[].class) {
- sql.append(f.getName().toUpperCase());
- sql.append(" BLOB,");
- } else if (f.getType() == Date.class) {
- sql.append(f.getName().toUpperCase());
- sql.append(" TIMESTAMP,");
- }
- }
- }
-
- sql.replace(sql.length() - 1, sql.length(), "");
- sql.append(")");
- System.out.println("SQL ==> " + sql.toString());
- execute(sql.toString());
- }
- }
-
- public int insert(Class poClass, T po) throws SQLException, ClassNotFoundException {
- try {
- Class aClass = classMap.get(poClass.getName());
- if (aClass == null) {
- System.err.println(poClass.getName() + " not found.");
- } else {
- StringBuffer sql = new StringBuffer();
- sql.append("INSERT INTO ");
- sql.append(aClass.getSimpleName());
- sql.append("(");
-
- //获取字段列表
- List fs = getFields(poClass);
-
- StringBuffer fieldsSql = new StringBuffer();
- StringBuffer valueSql = new StringBuffer();
- Object[] values = new Object[fs.size()];
-
- for (int i = 0; i < fs.size(); i++) {
- Field f = fs.get(i);
- f.setAccessible(true);
- fieldsSql.append(f.getName().toUpperCase());
- valueSql.append("?");
- Object o = f.get(po);
- values[i] = o;
- if (i != fs.size() - 1) {
- fieldsSql.append(",");
- valueSql.append(",");
- }
- }
-
- sql.append(fieldsSql);
- sql.append(") VALUES (");
- sql.append(valueSql);
- sql.append(")");
- System.out.println("SQL ==> " + sql.toString());
- return executeUpdate(sql.toString(), values);
- }
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } finally {
- destroyed();
- }
- return 0;
- }
-
- public int delete(Class poClass, Where where) throws SQLException, ClassNotFoundException {
- try {
- Class aClass = classMap.get(poClass.getName());
- if (aClass == null) {
- System.err.println(poClass.getName() + " not found.");
- } else {
- StringBuffer sql = new StringBuffer();
- sql.append("DELETE FROM ");
- sql.append(aClass.getSimpleName());
- sql.append(where.getSql());
- System.out.println("SQL ==> " + sql.toString());
- return executeUpdate(sql.toString(), where.getArgs());
- }
- } finally {
- destroyed();
- }
- return 0;
- }
-
- public int update(Class poClass, T po, Where where) throws SQLException, ClassNotFoundException {
- try {
- Class aClass = classMap.get(poClass.getName());
- if (aClass == null) {
- System.err.println(poClass.getName() + " not found.");
- } else {
- //获取字段列表
- List fs = getFields(poClass);
-
- StringBuffer sql = new StringBuffer();
- Object[] values = new Object[fs.size()];
- sql.append("UPDATE ");
- sql.append(aClass.getSimpleName());
- sql.append(" SET ");
-
- for (int i = 0; i < fs.size(); i++) {
- Field f = fs.get(i);
- f.setAccessible(true);
- sql.append(f.getName());
- sql.append(" = ?");
- values[i] = f.get(po);
- if (i != fs.size() - 1) {
- sql.append(",");
- }
- }
-
- // 条件
- sql.append(where.getSql());
-
- System.out.println("SQL ==> " + sql.toString());
- return executeUpdate(sql.toString(), concat(values, where.getArgs()));
- }
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } finally {
- destroyed();
- }
- return 0;
- }
-
- public List select(Class poClass, Where where, int pageNumber, int pageSize) throws SQLException, ClassNotFoundException {
- ArrayList list = new ArrayList<>();
- try {
- Class aClass = classMap.get(poClass.getName());
- if (aClass == null) {
- System.err.println(poClass.getName() + " not found.");
- } else {
- StringBuffer sql = new StringBuffer();
- sql.append("SELECT ");
-
- //获取字段列表
- List fs = getFields(poClass);
-
- for (int i = 0; i < fs.size(); i++) {
- Field f = fs.get(i);
- sql.append(f.getName().toUpperCase());
- if (i != fs.size() - 1) {
- sql.append(",");
- }
- }
-
- sql.append(" FROM ");
- sql.append(aClass.getSimpleName());
-
- // 条件
- sql.append(where.getSql());
-
- //分页参数
- if (pageSize > 0) {
- sql.append(" LIMIT " + (pageNumber - 1) + "," + pageSize);
- }
-
- System.out.println("SQL ==> " + sql.toString());
- list.addAll(executeQuery(poClass, sql.toString(), where.getArgs()));
- }
- } finally {
- destroyed();
- }
- return list;
- }
-
- /**
- * 执行select查询,返回结果列表
- *
- * @param sql sql select 语句
- * @param poClass 结果集的行数据处理类对象
- * @return
- * @throws SQLException
- * @throws ClassNotFoundException
- */
- public List executeQuery(Class poClass, String sql, Object... args) throws SQLException, ClassNotFoundException {
- List rsList = new ArrayList();
- try {
- resultSet = executeQuery(sql, args);
-
- //获取字段列表
- List fs = getFields(poClass);
-
- while (resultSet.next()) {
- try {
- T o = poClass.newInstance();
- for (int i = 0; i < fs.size(); i++) {
- Field f = fs.get(i);
- f.setAccessible(true);
-
- if (f.getType() == String.class) {
- String v = resultSet.getString(f.getName());
- f.set(o, v);
- } else if (f.getType() == Boolean.class || f.getType() == boolean.class) {
- boolean v = resultSet.getBoolean(f.getName());
- f.set(o, v);
- } else if (f.getType() == Byte.class || f.getType() == byte.class) {
- byte v = resultSet.getByte(f.getName());
- f.set(o, v);
- } else if (f.getType() == Short.class || f.getType() == short.class) {
- short v = resultSet.getShort(f.getName());
- f.set(o, v);
- } else if (f.getType() == Character.class || f.getType() == char.class) {
- short v = resultSet.getShort(f.getName());
- f.set(o, (char) v);
- } else if (f.getType() == Integer.class || f.getType() == int.class) {
- int v = resultSet.getInt(f.getName());
- f.set(o, v);
- } else if (f.getType() == Long.class || f.getType() == long.class) {
- long v = resultSet.getLong(f.getName());
- f.set(o, v);
- } else if (f.getType() == Float.class || f.getType() == float.class) {
- float v = resultSet.getFloat(f.getName());
- f.set(o, v);
- } else if (f.getType() == Double.class || f.getType() == double.class) {
- double v = resultSet.getDouble(f.getName());
- f.set(o, v);
- } else if (f.getType() == Byte[].class || f.getType() == byte[].class) {
- byte[] v = resultSet.getBytes(f.getName());
- f.set(o, v);
- } else if (f.getType() == Date.class) {
- Date v = resultSet.getTimestamp(f.getName());
- f.set(o, v);
- } else {
- String v = resultSet.getString(f.getName());
- f.set(o, v);
- }
- }
- rsList.add(o);
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- } finally {
- destroyed();
- }
- return rsList;
- }
-
- private List getFields(Class aClass) {
- List fs = new ArrayList<>();
- for (Field f : aClass.getDeclaredFields()) {
- if (f.isAnnotationPresent(TableField.class)) {
- fs.add(f);
- }
- }
- return fs;
- }
-
- private T[] concat(T[] arr1, T[] arr2) {
- List temp = new ArrayList<>();
- temp.addAll(Arrays.asList(arr1));
- temp.addAll(Arrays.asList(arr2));
- return (T[]) temp.toArray();
- }
-}
\ No newline at end of file
diff --git a/wsqlite/src/main/java/xyz/wbsite/wsqlite/Where.java b/wsqlite/src/main/java/xyz/wbsite/wsqlite/Where.java
deleted file mode 100644
index bb46f8b..0000000
--- a/wsqlite/src/main/java/xyz/wbsite/wsqlite/Where.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package xyz.wbsite.wsqlite;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Where {
- private String sql;
- private Object[] args;
-
- private Where() {
- }
-
- public String getSql() {
- return sql;
- }
-
- public void setSql(String sql) {
- this.sql = sql;
- }
-
- public Object[] getArgs() {
- return args;
- }
-
- public void setArgs(Object[] args) {
- this.args = args;
- }
-
- public Where(String sql, Object[] args) {
- this.sql = sql;
- this.args = args;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
- private StringBuilder sb = new StringBuilder();
- private List