diff --git a/es/index_create.txt b/es/index_create.txt new file mode 100644 index 0000000..9383602 --- /dev/null +++ b/es/index_create.txt @@ -0,0 +1,77 @@ +PUT /novel +{ + "mappings" : { + "book" : { + "properties" : { + "id" : { + "type" : "long" + }, + "authorId" : { + "type" : "long" + }, + "authorName" : { + "type" : "text", + "analyzer": "ik_smart" + }, + + "bookName" : { + "type" : "text", + "analyzer": "ik_smart" + }, + + "bookDesc" : { + "type" : "text", + "analyzer": "ik_smart" + }, + + "bookStatus" : { + "type" : "short" + }, + + "catId" : { + "type" : "integer" + }, + + "catName" : { + "type" : "text", + "analyzer": "ik_smart" + }, + + "lastIndexId" : { + "type" : "long" + }, + + "lastIndexName" : { + "type" : "text", + "analyzer": "ik_smart" + }, + + "lastIndexUpdateTime" : { + "type": "keyword" + }, + + "picUrl" : { + "type" : "keyword" + }, + + "score" : { + "type" : "float" + }, + + "wordCount" : { + "type" : "integer" + }, + + "workDirection" : { + "type" : "short" + }, + + "visitCount" : { + "type": "long" + } + + + } + } + } +} \ No newline at end of file diff --git a/novel-admin/src/main/resources/static/js/plugins/switchery/switchery.js b/novel-admin/src/main/resources/static/js/plugins/switchery/switchery.js index c6d8609..4617bc5 100644 --- a/novel-admin/src/main/resources/static/js/plugins/switchery/switchery.js +++ b/novel-admin/src/main/resources/static/js/plugins/switchery/switchery.js @@ -1 +1 @@ -(function(){function require(path,parent,orig){var resolved=require.resolve(path);if(null==resolved){orig=orig||path;parent=parent||"root";var err=new Error('Failed to require "'+orig+'" from "'+parent+'"');err.path=orig;err.parent=parent;err.require=true;throw err}var module=require.modules[resolved];if(!module._resolving&&!module.exports){var mod={};mod.exports={};mod.client=mod.component=true;module._resolving=true;module.call(this,mod.exports,require.relative(resolved),mod);delete module._resolving;module.exports=mod.exports}return module.exports}require.modules={};require.aliases={};require.resolve=function(path){if(path.charAt(0)==="/")path=path.slice(1);var paths=[path,path+".js",path+".json",path+"/index.js",path+"/index.json"];for(var i=0;i0;FastClick.prototype.deviceIsIOS=/iP(ad|hone|od)/.test(navigator.userAgent);FastClick.prototype.deviceIsIOS4=FastClick.prototype.deviceIsIOS&&/OS 4_\d(_\d)?/.test(navigator.userAgent);FastClick.prototype.deviceIsIOSWithBadTarget=FastClick.prototype.deviceIsIOS&&/OS ([6-9]|\d{2})_\d/.test(navigator.userAgent);FastClick.prototype.needsClick=function(target){"use strict";switch(target.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(target.disabled){return true}break;case"input":if(this.deviceIsIOS&&target.type==="file"||target.disabled){return true}break;case"label":case"video":return true}return/\bneedsclick\b/.test(target.className)};FastClick.prototype.needsFocus=function(target){"use strict";switch(target.nodeName.toLowerCase()){case"textarea":return true;case"select":return!this.deviceIsAndroid;case"input":switch(target.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return false}return!target.disabled&&!target.readOnly;default:return/\bneedsfocus\b/.test(target.className)}};FastClick.prototype.sendClick=function(targetElement,event){"use strict";var clickEvent,touch;if(document.activeElement&&document.activeElement!==targetElement){document.activeElement.blur()}touch=event.changedTouches[0];clickEvent=document.createEvent("MouseEvents");clickEvent.initMouseEvent(this.determineEventType(targetElement),true,true,window,1,touch.screenX,touch.screenY,touch.clientX,touch.clientY,false,false,false,false,0,null);clickEvent.forwardedTouchEvent=true;targetElement.dispatchEvent(clickEvent)};FastClick.prototype.determineEventType=function(targetElement){"use strict";if(this.deviceIsAndroid&&targetElement.tagName.toLowerCase()==="select"){return"mousedown"}return"click"};FastClick.prototype.focus=function(targetElement){"use strict";var length;if(this.deviceIsIOS&&targetElement.setSelectionRange&&targetElement.type.indexOf("date")!==0&&targetElement.type!=="time"){length=targetElement.value.length;targetElement.setSelectionRange(length,length)}else{targetElement.focus()}};FastClick.prototype.updateScrollParent=function(targetElement){"use strict";var scrollParent,parentElement;scrollParent=targetElement.fastClickScrollParent;if(!scrollParent||!scrollParent.contains(targetElement)){parentElement=targetElement;do{if(parentElement.scrollHeight>parentElement.offsetHeight){scrollParent=parentElement;targetElement.fastClickScrollParent=parentElement;break}parentElement=parentElement.parentElement}while(parentElement)}if(scrollParent){scrollParent.fastClickLastScrollTop=scrollParent.scrollTop}};FastClick.prototype.getTargetElementFromEventTarget=function(eventTarget){"use strict";if(eventTarget.nodeType===Node.TEXT_NODE){return eventTarget.parentNode}return eventTarget};FastClick.prototype.onTouchStart=function(event){"use strict";var targetElement,touch,selection;if(event.targetTouches.length>1){return true}targetElement=this.getTargetElementFromEventTarget(event.target);touch=event.targetTouches[0];if(this.deviceIsIOS){selection=window.getSelection();if(selection.rangeCount&&!selection.isCollapsed){return true}if(!this.deviceIsIOS4){if(touch.identifier===this.lastTouchIdentifier){event.preventDefault();return false}this.lastTouchIdentifier=touch.identifier;this.updateScrollParent(targetElement)}}this.trackingClick=true;this.trackingClickStart=event.timeStamp;this.targetElement=targetElement;this.touchStartX=touch.pageX;this.touchStartY=touch.pageY;if(event.timeStamp-this.lastClickTime<200){event.preventDefault()}return true};FastClick.prototype.touchHasMoved=function(event){"use strict";var touch=event.changedTouches[0],boundary=this.touchBoundary;if(Math.abs(touch.pageX-this.touchStartX)>boundary||Math.abs(touch.pageY-this.touchStartY)>boundary){return true}return false};FastClick.prototype.onTouchMove=function(event){"use strict";if(!this.trackingClick){return true}if(this.targetElement!==this.getTargetElementFromEventTarget(event.target)||this.touchHasMoved(event)){this.trackingClick=false;this.targetElement=null}return true};FastClick.prototype.findControl=function(labelElement){"use strict";if(labelElement.control!==undefined){return labelElement.control}if(labelElement.htmlFor){return document.getElementById(labelElement.htmlFor)}return labelElement.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")};FastClick.prototype.onTouchEnd=function(event){"use strict";var forElement,trackingClickStart,targetTagName,scrollParent,touch,targetElement=this.targetElement;if(!this.trackingClick){return true}if(event.timeStamp-this.lastClickTime<200){this.cancelNextClick=true;return true}this.cancelNextClick=false;this.lastClickTime=event.timeStamp;trackingClickStart=this.trackingClickStart;this.trackingClick=false;this.trackingClickStart=0;if(this.deviceIsIOSWithBadTarget){touch=event.changedTouches[0];targetElement=document.elementFromPoint(touch.pageX-window.pageXOffset,touch.pageY-window.pageYOffset)||targetElement;targetElement.fastClickScrollParent=this.targetElement.fastClickScrollParent}targetTagName=targetElement.tagName.toLowerCase();if(targetTagName==="label"){forElement=this.findControl(targetElement);if(forElement){this.focus(targetElement);if(this.deviceIsAndroid){return false}targetElement=forElement}}else if(this.needsFocus(targetElement)){if(event.timeStamp-trackingClickStart>100||this.deviceIsIOS&&window.top!==window&&targetTagName==="input"){this.targetElement=null;return false}this.focus(targetElement);if(!this.deviceIsIOS4||targetTagName!=="select"){this.targetElement=null;event.preventDefault()}return false}if(this.deviceIsIOS&&!this.deviceIsIOS4){scrollParent=targetElement.fastClickScrollParent;if(scrollParent&&scrollParent.fastClickLastScrollTop!==scrollParent.scrollTop){return true}}if(!this.needsClick(targetElement)){event.preventDefault();this.sendClick(targetElement,event)}return false};FastClick.prototype.onTouchCancel=function(){"use strict";this.trackingClick=false;this.targetElement=null};FastClick.prototype.onMouse=function(event){"use strict";if(!this.targetElement){return true}if(event.forwardedTouchEvent){return true}if(!event.cancelable){return true}if(!this.needsClick(this.targetElement)||this.cancelNextClick){if(event.stopImmediatePropagation){event.stopImmediatePropagation()}else{event.propagationStopped=true}event.stopPropagation();event.preventDefault();return false}return true};FastClick.prototype.onClick=function(event){"use strict";var permitted;if(this.trackingClick){this.targetElement=null;this.trackingClick=false;return true}if(event.target.type==="submit"&&event.detail===0){return true}permitted=this.onMouse(event);if(!permitted){this.targetElement=null}return permitted};FastClick.prototype.destroy=function(){"use strict";var layer=this.layer;if(this.deviceIsAndroid){layer.removeEventListener("mouseover",this.onMouse,true);layer.removeEventListener("mousedown",this.onMouse,true);layer.removeEventListener("mouseup",this.onMouse,true)}layer.removeEventListener("click",this.onClick,true);layer.removeEventListener("touchstart",this.onTouchStart,false);layer.removeEventListener("touchmove",this.onTouchMove,false);layer.removeEventListener("touchend",this.onTouchEnd,false);layer.removeEventListener("touchcancel",this.onTouchCancel,false)};FastClick.notNeeded=function(layer){"use strict";var metaViewport;var chromeVersion;if(typeof window.ontouchstart==="undefined"){return true}chromeVersion=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1];if(chromeVersion){if(FastClick.prototype.deviceIsAndroid){metaViewport=document.querySelector("meta[name=viewport]");if(metaViewport){if(metaViewport.content.indexOf("user-scalable=no")!==-1){return true}if(chromeVersion>31&&window.innerWidth<=window.screen.width){return true}}}else{return true}}if(layer.style.msTouchAction==="none"){return true}return false};FastClick.attach=function(layer){"use strict";return new FastClick(layer)};if(typeof define!=="undefined"&&define.amd){define(function(){"use strict";return FastClick})}else if(typeof module!=="undefined"&&module.exports){module.exports=FastClick.attach;module.exports.FastClick=FastClick}else{window.FastClick=FastClick}});require.register("switchery/switchery.js",function(exports,require,module){var transitionize=require("transitionize"),fastclick=require("fastclick");module.exports=Switchery;var defaults={color:"#64bd63",secondaryColor:"#dfdfdf",className:"switchery",disabled:false,disabledOpacity:.5,speed:"0.4s"};function Switchery(element,options){if(!(this instanceof Switchery))return new Switchery(element,options);this.element=element;this.options=options||{};for(var i in defaults){if(this.options[i]==null){this.options[i]=defaults[i]}}if(this.element!=null&&this.element.type=="checkbox")this.init()}Switchery.prototype.hide=function(){this.element.style.display="none"};Switchery.prototype.show=function(){var switcher=this.create();this.insertAfter(this.element,switcher)};Switchery.prototype.create=function(){this.switcher=document.createElement("span");this.jack=document.createElement("small");this.switcher.appendChild(this.jack);this.switcher.className=this.options.className;return this.switcher};Switchery.prototype.insertAfter=function(reference,target){reference.parentNode.insertBefore(target,reference.nextSibling)};Switchery.prototype.isChecked=function(){return this.element.checked};Switchery.prototype.isDisabled=function(){return this.options.disabled||this.element.disabled};Switchery.prototype.setPosition=function(clicked){var checked=this.isChecked(),switcher=this.switcher,jack=this.jack;if(clicked&&checked)checked=false;else if(clicked&&!checked)checked=true;if(checked===true){this.element.checked=true;if(window.getComputedStyle)jack.style.left=parseInt(window.getComputedStyle(switcher).width)-parseInt(window.getComputedStyle(jack).width)+"px";else jack.style.left=parseInt(switcher.currentStyle["width"])-parseInt(jack.currentStyle["width"])+"px";if(this.options.color)this.colorize();this.setSpeed()}else{jack.style.left=0;this.element.checked=false;this.switcher.style.boxShadow="inset 0 0 0 0 "+this.options.secondaryColor;this.switcher.style.borderColor=this.options.secondaryColor;this.switcher.style.backgroundColor="";this.setSpeed()}};Switchery.prototype.setSpeed=function(){var switcherProp={},jackProp={left:this.options.speed.replace(/[a-z]/,"")/2+"s"};if(this.isChecked()){switcherProp={border:this.options.speed,"box-shadow":this.options.speed,"background-color":this.options.speed.replace(/[a-z]/,"")*3+"s"}}else{switcherProp={border:this.options.speed,"box-shadow":this.options.speed}}transitionize(this.switcher,switcherProp);transitionize(this.jack,jackProp)};Switchery.prototype.setAttributes=function(){var id=this.element.getAttribute("id"),name=this.element.getAttribute("name");if(id)this.switcher.setAttribute("id",id);if(name)this.switcher.setAttribute("name",name)};Switchery.prototype.colorize=function(){this.switcher.style.backgroundColor=this.options.color;this.switcher.style.borderColor=this.options.color;this.switcher.style.boxShadow="inset 0 0 0 16px "+this.options.color};Switchery.prototype.handleOnchange=function(state){if(typeof Event==="function"||!document.fireEvent){var event=document.createEvent("HTMLEvents");event.initEvent("change",true,true);this.element.dispatchEvent(event)}else{this.element.fireEvent("onchange")}};Switchery.prototype.handleChange=function(){var self=this,el=this.element;if(el.addEventListener){el.addEventListener("change",function(){self.setPosition()})}else{el.attachEvent("onchange",function(){self.setPosition()})}};Switchery.prototype.handleClick=function(){var self=this,switcher=this.switcher;if(this.isDisabled()===false){fastclick(switcher);if(switcher.addEventListener){switcher.addEventListener("click",function(){self.setPosition(true);self.handleOnchange(self.element.checked)})}else{switcher.attachEvent("onclick",function(){self.setPosition(true);self.handleOnchange(self.element.checked)})}}else{this.element.disabled=true;this.switcher.style.opacity=this.options.disabledOpacity}};Switchery.prototype.disableLabel=function(){var parent=this.element.parentNode,labels=document.getElementsByTagName("label"),attached=null;for(var i=0;i0;FastClick.prototype.deviceIsIOS=/iP(ad|hone|od)/.test(navigator.userAgent);FastClick.prototype.deviceIsIOS4=FastClick.prototype.deviceIsIOS&&/OS 4_\d(_\d)?/.test(navigator.userAgent);FastClick.prototype.deviceIsIOSWithBadTarget=FastClick.prototype.deviceIsIOS&&/OS ([6-9]|\d{2})_\d/.test(navigator.userAgent);FastClick.prototype.needsClick=function(target){"use strict";switch(target.nodeName.toLowerCase()){case"button":case"select":case"textarea":if(target.disabled){return true}break;case"input":if(this.deviceIsIOS&&target.type==="file"||target.disabled){return true}break;case"label":case"video":return true}return/\bneedsclick\b/.test(target.className)};FastClick.prototype.needsFocus=function(target){"use strict";switch(target.nodeName.toLowerCase()){case"textarea":return true;case"select":return!this.deviceIsAndroid;case"input":switch(target.type){case"button":case"checkbox":case"file":case"image":case"radio":case"submit":return false}return!target.disabled&&!target.readOnly;default:return/\bneedsfocus\b/.test(target.className)}};FastClick.prototype.sendClick=function(targetElement,event){"use strict";var clickEvent,touch;if(document.activeElement&&document.activeElement!==targetElement){document.activeElement.blur()}touch=event.changedTouches[0];clickEvent=document.createEvent("MouseEvents");clickEvent.initMouseEvent(this.determineEventType(targetElement),true,true,window,1,touch.screenX,touch.screenY,touch.clientX,touch.clientY,false,false,false,false,0,null);clickEvent.forwardedTouchEvent=true;targetElement.dispatchEvent(clickEvent)};FastClick.prototype.determineEventType=function(targetElement){"use strict";if(this.deviceIsAndroid&&targetElement.tagName.toLowerCase()==="select"){return"mousedown"}return"click"};FastClick.prototype.focus=function(targetElement){"use strict";var length;if(this.deviceIsIOS&&targetElement.setSelectionRange&&targetElement.type.indexOf("date")!==0&&targetElement.type!=="time"){length=targetElement.value.length;targetElement.setSelectionRange(length,length)}else{targetElement.focus()}};FastClick.prototype.updateScrollParent=function(targetElement){"use strict";var scrollParent,parentElement;scrollParent=targetElement.fastClickScrollParent;if(!scrollParent||!scrollParent.contains(targetElement)){parentElement=targetElement;do{if(parentElement.scrollHeight>parentElement.offsetHeight){scrollParent=parentElement;targetElement.fastClickScrollParent=parentElement;break}parentElement=parentElement.parentElement}while(parentElement)}if(scrollParent){scrollParent.fastClickLastScrollTop=scrollParent.scrollTop}};FastClick.prototype.getTargetElementFromEventTarget=function(eventTarget){"use strict";if(eventTarget.nodeType===Node.TEXT_NODE){return eventTarget.parentNode}return eventTarget};FastClick.prototype.onTouchStart=function(event){"use strict";var targetElement,touch,selection;if(event.targetTouches.length>1){return true}targetElement=this.getTargetElementFromEventTarget(event.target);touch=event.targetTouches[0];if(this.deviceIsIOS){selection=window.getSelection();if(selection.rangeCount&&!selection.isCollapsed){return true}if(!this.deviceIsIOS4){if(touch.identifier===this.lastTouchIdentifier){event.preventDefault();return false}this.lastTouchIdentifier=touch.identifier;this.updateScrollParent(targetElement)}}this.trackingClick=true;this.trackingClickStart=event.timeStamp;this.targetElement=targetElement;this.touchStartX=touch.pageX;this.touchStartY=touch.pageY;if(event.timeStamp-this.lastClickTime<200){event.preventDefault()}return true};FastClick.prototype.touchHasMoved=function(event){"use strict";var touch=event.changedTouches[0],boundary=this.touchBoundary;if(Math.abs(touch.pageX-this.touchStartX)>boundary||Math.abs(touch.pageY-this.touchStartY)>boundary){return true}return false};FastClick.prototype.onTouchMove=function(event){"use strict";if(!this.trackingClick){return true}if(this.targetElement!==this.getTargetElementFromEventTarget(event.target)||this.touchHasMoved(event)){this.trackingClick=false;this.targetElement=null}return true};FastClick.prototype.findControl=function(labelElement){"use strict";if(labelElement.control!==undefined){return labelElement.control}if(labelElement.htmlFor){return document.getElementById(labelElement.htmlFor)}return labelElement.querySelector("button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea")};FastClick.prototype.onTouchEnd=function(event){"use strict";var forElement,trackingClickStart,targetTagName,scrollParent,touch,targetElement=this.targetElement;if(!this.trackingClick){return true}if(event.timeStamp-this.lastClickTime<200){this.cancelNextClick=true;return true}this.cancelNextClick=false;this.lastClickTime=event.timeStamp;trackingClickStart=this.trackingClickStart;this.trackingClick=false;this.trackingClickStart=0;if(this.deviceIsIOSWithBadTarget){touch=event.changedTouches[0];targetElement=document.elementFromPoint(touch.pageX-window.pageXOffset,touch.pageY-window.pageYOffset)||targetElement;targetElement.fastClickScrollParent=this.targetElement.fastClickScrollParent}targetTagName=targetElement.tagName.toLowerCase();if(targetTagName==="label"){forElement=this.findControl(targetElement);if(forElement){this.focus(targetElement);if(this.deviceIsAndroid){return false}targetElement=forElement}}else if(this.needsFocus(targetElement)){if(event.timeStamp-trackingClickStart>100||this.deviceIsIOS&&window.top!==window&&targetTagName==="input"){this.targetElement=null;return false}this.focus(targetElement);if(!this.deviceIsIOS4||targetTagName!=="select"){this.targetElement=null;event.preventDefault()}return false}if(this.deviceIsIOS&&!this.deviceIsIOS4){scrollParent=targetElement.fastClickScrollParent;if(scrollParent&&scrollParent.fastClickLastScrollTop!==scrollParent.scrollTop){return true}}if(!this.needsClick(targetElement)){event.preventDefault();this.sendClick(targetElement,event)}return false};FastClick.prototype.onTouchCancel=function(){"use strict";this.trackingClick=false;this.targetElement=null};FastClick.prototype.onMouse=function(event){"use strict";if(!this.targetElement){return true}if(event.forwardedTouchEvent){return true}if(!event.cancelable){return true}if(!this.needsClick(this.targetElement)||this.cancelNextClick){if(event.stopImmediatePropagation){event.stopImmediatePropagation()}else{event.propagationStopped=true}event.stopPropagation();event.preventDefault();return false}return true};FastClick.prototype.onClick=function(event){"use strict";var permitted;if(this.trackingClick){this.targetElement=null;this.trackingClick=false;return true}if(event.target.type==="submit"&&event.detail===0){return true}permitted=this.onMouse(event);if(!permitted){this.targetElement=null}return permitted};FastClick.prototype.destroy=function(){"use strict";var layer=this.layer;if(this.deviceIsAndroid){layer.removeEventListener("mouseover",this.onMouse,true);layer.removeEventListener("mousedown",this.onMouse,true);layer.removeEventListener("mouseup",this.onMouse,true)}layer.removeEventListener("click",this.onClick,true);layer.removeEventListener("touchstart",this.onTouchStart,false);layer.removeEventListener("touchmove",this.onTouchMove,false);layer.removeEventListener("touchend",this.onTouchEnd,false);layer.removeEventListener("touchcancel",this.onTouchCancel,false)};FastClick.notNeeded=function(layer){"use strict";var metaViewport;var chromeVersion;if(typeof window.ontouchstart==="undefined"){return true}chromeVersion=+(/Chrome\/([0-9]+)/.exec(navigator.userAgent)||[,0])[1];if(chromeVersion){if(FastClick.prototype.deviceIsAndroid){metaViewport=document.querySelector("meta[name=viewport]");if(metaViewport){if(metaViewport.content.indexOf("user-scalable=no")!==-1){return true}if(chromeVersion>31&&window.innerWidth<=window.screen.width){return true}}}else{return true}}if(layer.style.msTouchAction==="none"){return true}return false};FastClick.attach=function(layer){"use strict";return new FastClick(layer)};if(typeof define!=="undefined"&&define.amd){define(function(){"use strict";return FastClick})}else if(typeof module!=="undefined"&&module.exports){module.exports=FastClick.attach;module.exports.FastClick=FastClick}else{window.FastClick=FastClick}});require.register("switchery/switchery.js",function(exports,require,module){var transitionize=require("transitionize"),fastclick=require("fastclick");module.exports=Switchery;var defaults={color:"#64bd63",secondaryColor:"#dfdfdf",className:"switchery",disabled:false,disabledOpacity:.5,speed:"0.4s"};function Switchery(element,options){if(!(this instanceof Switchery))return new Switchery(element,options);this.element=element;this.options=options||{};for(var i in defaults){if(this.options[i]==null){this.options[i]=defaults[i]}}if(this.element!=null&&this.element.type=="checkbox")this.init()}Switchery.prototype.hide=function(){this.element.style.display="none"};Switchery.prototype.show=function(){var switcher=this.create();this.insertAfter(this.element,switcher)};Switchery.prototype.create=function(){this.switcher=document.createElement("span");this.jack=document.createElement("small");this.switcher.appendChild(this.jack);this.switcher.className=this.options.className;return this.switcher};Switchery.prototype.insertAfter=function(reference,target){reference.parentNode.insertBefore(target,reference.nextSibling)};Switchery.prototype.isChecked=function(){return this.element.checked};Switchery.prototype.isDisabled=function(){return this.options.disabled||this.element.disabled};Switchery.prototype.setPosition=function(clicked){var checked=this.isChecked(),switcher=this.switcher,jack=this.jack;if(clicked&&checked)checked=false;else if(clicked&&!checked)checked=true;if(checked===true){this.element.checked=true;if(window.getComputedStyle)jack.style.left=parseInt(window.getComputedStyle(switcher).width)-parseInt(window.getComputedStyle(jack).width)+"px";else jack.style.left=parseInt(switcher.currentStyle["width"])-parseInt(jack.currentStyle["width"])+"px";if(this.options.color)this.colorize();this.setSpeed()}else{jack.style.left=0;this.element.checked=false;this.switcher.style.boxShadow="inset 0 0 0 0 "+this.options.secondaryColor;this.switcher.style.borderColor=this.options.secondaryColor;this.switcher.style.backgroundColor="";this.setSpeed()}};Switchery.prototype.setSpeed=function(){var switcherProp={},jackProp={left:this.options.speed.replace(/[a-z]/,"")/2+"s"};if(this.isChecked()){switcherProp={border:this.options.speed,"box-shadow":this.options.speed,"background-color":this.options.speed.replace(/[a-z]/,"")*3+"s"}}else{switcherProp={border:this.options.speed,"box-shadow":this.options.speed}}transitionize(this.switcher,switcherProp);transitionize(this.jack,jackProp)};Switchery.prototype.setAttributes=function(){var id=this.element.getAttribute("id"),name=this.element.getAttribute("name");if(id)this.switcher.setAttribute("id",id);if(name)this.switcher.setAttribute("name",name)};Switchery.prototype.colorize=function(){this.switcher.style.backgroundColor=this.options.color;this.switcher.style.borderColor=this.options.color;this.switcher.style.boxShadow="inset 0 0 0 16px "+this.options.color};Switchery.prototype.handleOnchange=function(state){if(typeof Event==="function"||!document.fireEvent){var event=document.createEvent("HTMLEvents");event.initEvent("change",true,true);this.element.dispatchEvent(event)}else{this.element.fireEvent("onchange")}};Switchery.prototype.handleChange=function(){var self=this,el=this.element;if(el.addEventListener){el.addEventListener("change",function(){self.setPosition()})}else{el.attachEvent("onchange",function(){self.setPosition()})}};Switchery.prototype.handleClick=function(){var self=this,switcher=this.switcher;if(this.isDisabled()===false){fastclick(switcher);if(switcher.addEventListener){switcher.addEventListener("click",function(){self.setPosition(true);self.handleOnchange(self.element.checked)})}else{switcher.attachEvent("onclick",function(){self.setPosition(true);self.handleOnchange(self.element.checked)})}}else{this.element.disabled=true;this.switcher.style.opacity=this.options.disabledOpacity}};Switchery.prototype.disableLabel=function(){var parent=this.element.parentNode,labels=document.getElementsByTagName("label"),attached=null;for(var i=0;i + * 例如:HelloWorld->HELLO_WORLD + * @param name 转换前的驼峰式命名的字符串 + * @return 转换后下划线大写方式命名的字符串 + */ + public static String underscoreName(String name) { + StringBuilder result = new StringBuilder(); + if (name != null && name.length() > 0) { + // 将第一个字符处理成大写 + result.append(name.substring(0, 1).toUpperCase()); + // 循环处理其余字符 + for (int i = 1; i < name.length(); i++) { + String s = name.substring(i, i + 1); + // 在大写字母前添加下划线 + if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) { + result.append("_"); + } + // 其他字符直接转成大写 + result.append(s.toUpperCase()); + } + } + return result.toString(); + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。
+ * 例如:HELLO_WORLD->HelloWorld + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String camelName(String name) { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) { + // 没必要转换 + return ""; + } else if (!name.contains("_")) { + // 不含下划线,仅将首字母小写 + return name.substring(0, 1).toLowerCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String camels[] = name.split("_"); + for (String camel : camels) { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) { + continue; + } + // 处理真正的驼峰片段 + if (result.length() == 0) { + // 第一个驼峰片段,全部字母都小写 + result.append(camel.toLowerCase()); + } else { + // 其他的驼峰片段,首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + } + return result.toString(); + } + +} diff --git a/novel-front/pom.xml b/novel-front/pom.xml index 8752dcb..931b05a 100644 --- a/novel-front/pom.xml +++ b/novel-front/pom.xml @@ -28,6 +28,18 @@ + + io.searchbox + jest + ${jest.version} + + + + org.springframework.boot + spring-boot-starter-data-elasticsearch + + + com.alipay.sdk alipay-sdk-java diff --git a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java index 2b30d5a..4545c71 100644 --- a/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java +++ b/novel-front/src/main/java/com/java2nb/novel/controller/BookController.java @@ -79,8 +79,8 @@ public class BookController extends BaseController{ * */ @PostMapping("searchByPage") public ResultBean searchByPage(BookSP bookSP, @RequestParam(value = "curr", defaultValue = "1") int page, @RequestParam(value = "limit", defaultValue = "20") int pageSize){ - List books = bookService.searchByPage(bookSP,page,pageSize); - return ResultBean.ok(new PageInfo<>(books)); + PageInfo pageInfo = bookService.searchByPage(bookSP,page,pageSize); + return ResultBean.ok(pageInfo); } /** diff --git a/novel-front/src/main/java/com/java2nb/novel/core/schedule/BookToEsSchedule.java b/novel-front/src/main/java/com/java2nb/novel/core/schedule/BookToEsSchedule.java new file mode 100644 index 0000000..a67a7c2 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/core/schedule/BookToEsSchedule.java @@ -0,0 +1,95 @@ +package com.java2nb.novel.core.schedule; + +import com.java2nb.novel.core.cache.CacheKey; +import com.java2nb.novel.core.cache.CacheService; +import com.java2nb.novel.core.utils.BeanUtil; +import com.java2nb.novel.entity.Book; +import com.java2nb.novel.service.BookService; +import com.java2nb.novel.vo.EsBookVO; +import io.searchbox.client.JestClient; +import io.searchbox.core.DocumentResult; +import io.searchbox.core.Index; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +/** + * 小说导入搜索引擎 + * + * @author Administrator + */ +@ConditionalOnProperty(prefix = "spring.elasticsearch", name = "enable", havingValue = "1") +@Service +@RequiredArgsConstructor +@Slf4j +public class BookToEsSchedule { + + private final BookService bookService; + + private final CacheService cacheService; + + private final JestClient jestClient; + + + private boolean lock = false; + + /** + * 5秒导入一次 + */ + @Scheduled(fixedRate = 1000 * 5) + public void saveToEs() { + if (!lock) { + lock = true; + Date currentDate = new Date(); + try { + //查询需要更新的小说 + Date lastDate = (Date) cacheService.getObject(CacheKey.ES_LAST_UPDATE_TIME); + if (lastDate == null) { + lastDate = new SimpleDateFormat("yyyy-MM-dd").parse("2020-01-01"); + } + + long count ; + int page = 1; + do { + + List books = bookService.queryBookByUpdateTimeByPage(lastDate, currentDate,page,100); + for(Book book : books) { + //导入到ES + EsBookVO esBookVO = new EsBookVO(); + BeanUtils.copyProperties(book,esBookVO,"lastIndexUpdateTime"); + esBookVO.setLastIndexUpdateTime(new SimpleDateFormat("yyyy/MM/dd HH:mm").format(book.getLastIndexUpdateTime())); + Index action = new Index.Builder(esBookVO).index("novel").type("book").id(book.getId().toString()).build(); + + jestClient.execute(action); + + } + + count = books.size(); + page++; + + }while (count == 100); + + cacheService.setObject(CacheKey.ES_LAST_UPDATE_TIME, currentDate); + + } catch (Exception e) { + log.error(e.getMessage(),e); + } + + + lock = false; + } + + + } + + +} diff --git a/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java index eaed2d6..eaef7ae 100644 --- a/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java +++ b/novel-front/src/main/java/com/java2nb/novel/mapper/FrontBookMapper.java @@ -5,6 +5,7 @@ import com.java2nb.novel.search.BookSP; import com.java2nb.novel.vo.BookVO; import org.apache.ibatis.annotations.Param; +import java.util.Date; import java.util.List; /** @@ -15,7 +16,7 @@ public interface FrontBookMapper extends BookMapper { List searchByPage(BookSP params); - void addVisitCount(@Param("bookId") Long bookId); + void addVisitCount(@Param("bookId") Long bookId, @Param("date") Date date); List listRecBookByCatId(@Param("catId") Integer catId); diff --git a/novel-front/src/main/java/com/java2nb/novel/service/BookService.java b/novel-front/src/main/java/com/java2nb/novel/service/BookService.java index fea0f2b..a8cc973 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/BookService.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/BookService.java @@ -1,12 +1,14 @@ package com.java2nb.novel.service; +import com.github.pagehelper.PageInfo; import com.java2nb.novel.search.BookSP; import com.java2nb.novel.vo.BookCommentVO; import com.java2nb.novel.vo.BookSettingVO; import com.java2nb.novel.entity.*; import com.java2nb.novel.vo.BookVO; +import java.util.Date; import java.util.List; import java.util.Map; @@ -44,9 +46,9 @@ public interface BookService { * @param params 搜索参数 * @param page 页码 * @param pageSize 分页大小 - * @return 小说集合 + * @return 小说集合分页信息 * */ - List searchByPage(BookSP params, int page, int pageSize); + PageInfo searchByPage(BookSP params, int page, int pageSize); /** * 查询小说分类列表 @@ -224,4 +226,15 @@ public interface BookService { * @param authorId 作者ID * */ void addBookContent(Long bookId, String indexName, String content, Long authorId); + + + /** + * 根据更新时间分页查询书籍列表 + * @param startDate 开始时间,包括该时间 + * @param endDate 结束时间,不包括该时间 + * @param page 页码 + * @param pageSize 每页数量 + * @return 书籍列表 + * */ + List queryBookByUpdateTimeByPage(Date startDate, Date endDate, int page, int pageSize); } diff --git a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java index eeaa8ff..e16d090 100644 --- a/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java +++ b/novel-front/src/main/java/com/java2nb/novel/service/impl/BookServiceImpl.java @@ -1,15 +1,14 @@ package com.java2nb.novel.service.impl; +import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; import com.java2nb.novel.core.cache.CacheKey; import com.java2nb.novel.core.cache.CacheService; import com.java2nb.novel.core.enums.ResponseStatus; import com.java2nb.novel.core.exception.BusinessException; -import com.java2nb.novel.core.utils.BeanUtil; -import com.java2nb.novel.core.utils.Constants; -import com.java2nb.novel.core.utils.FileUtil; -import com.java2nb.novel.core.utils.IdWorker; +import com.java2nb.novel.core.utils.*; import com.java2nb.novel.entity.*; import com.java2nb.novel.entity.Book; import com.java2nb.novel.mapper.*; @@ -19,9 +18,18 @@ import com.java2nb.novel.service.BookService; import com.java2nb.novel.vo.BookCommentVO; import com.java2nb.novel.vo.BookSettingVO; import com.java2nb.novel.vo.BookVO; +import com.java2nb.novel.vo.EsBookVO; +import io.searchbox.client.JestClient; +import io.searchbox.core.*; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; +import org.elasticsearch.search.sort.SortOrder; import org.mybatis.dynamic.sql.SortSpecification; import org.mybatis.dynamic.sql.render.RenderingStrategies; import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; @@ -31,6 +39,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import tk.mybatis.orderbyhelper.OrderByHelper; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -50,6 +59,7 @@ import static org.mybatis.dynamic.sql.select.SelectDSL.select; */ @Service @RequiredArgsConstructor +@Slf4j public class BookServiceImpl implements BookService { /** @@ -58,6 +68,9 @@ public class BookServiceImpl implements BookService { @Value("${pic.save.path}") private String picSavePath; + @Value("${spring.elasticsearch.enable}") + private Integer esEnable; + private final FrontBookSettingMapper bookSettingMapper; private final FrontBookMapper bookMapper; @@ -76,6 +89,8 @@ public class BookServiceImpl implements BookService { private final AuthorService authorService; + private final JestClient jestClient; + @SneakyThrows @Override @@ -170,19 +185,163 @@ public class BookServiceImpl implements BookService { return result; } + @SneakyThrows @Override - public List searchByPage(BookSP params, int page, int pageSize) { - PageHelper.startPage(page, pageSize); + public PageInfo searchByPage(BookSP params, int page, int pageSize) { + + if (params.getUpdatePeriod() != null) { long cur = System.currentTimeMillis(); long period = params.getUpdatePeriod() * 24 * 3600 * 1000; long time = cur - period; params.setUpdateTimeMin(new Date(time)); } - if (StringUtils.isNotBlank(params.getSort())) { - OrderByHelper.orderBy(params.getSort() + " desc"); + + if(esEnable == 1) { + List bookList = new ArrayList<>(0); + + //使用搜索引擎搜索 + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + // 构造查询哪个字段 + if (StringUtils.isNoneBlank(params.getKeyword())) { + boolQueryBuilder = boolQueryBuilder.must(QueryBuilders.queryStringQuery(params.getKeyword())); + } + + // 作品方向 + if (params.getWorkDirection() != null) { + boolQueryBuilder.filter(QueryBuilders.termQuery("workDirection", params.getWorkDirection())); + } + + // 分类 + if (params.getCatId() != null) { + boolQueryBuilder.filter(QueryBuilders.termQuery("catId", params.getCatId())); + } + if (params.getBookStatus() != null) { + boolQueryBuilder.filter(QueryBuilders.termQuery("bookStatus", params.getBookStatus())); + } + + if(params.getWordCountMin() == null){ + params.setWordCountMin(0); + } + if(params.getWordCountMax() == null){ + params.setWordCountMax(Integer.MAX_VALUE); + } + + boolQueryBuilder.filter(QueryBuilders.rangeQuery("wordCount").gte(params.getWordCountMin()).lte(params.getWordCountMax())); + + if(params.getUpdateTimeMin() != null){ + boolQueryBuilder.filter(QueryBuilders.rangeQuery("lastIndexUpdateTime").gte(params.getUpdateTimeMin())); + } + + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + searchSourceBuilder.query(boolQueryBuilder); + + Count count = new Count.Builder().addIndex("novel").addType("book") + .query(searchSourceBuilder.toString()).build(); + CountResult results = jestClient.execute(count); + Double total = results.getCount(); + + // 设置高亮字段 + + // 临时屏蔽小程序未处理的高亮字段,等小程序处理后再放开 + HighlightBuilder highlightBuilder = new HighlightBuilder(); + highlightBuilder.field("authorName"); + highlightBuilder.field("bookName"); + highlightBuilder.field("bookDesc"); + highlightBuilder.field("lastIndexName"); + highlightBuilder.field("catName"); + highlightBuilder.preTags("").postTags(""); + highlightBuilder.fragmentSize(200); + searchSourceBuilder.highlighter(highlightBuilder); + + //设置排序 + if(params.getSort() != null){ + searchSourceBuilder.sort(StringUtil.camelName(params.getSort()), SortOrder.DESC); + } + + // 设置分页 + searchSourceBuilder.from((page - 1) * pageSize); + searchSourceBuilder.size(pageSize); + + // 构建Search对象 + Search search = new Search.Builder(searchSourceBuilder.toString()).addIndex("novel").addType("book").build(); + log.debug(search.toString()); + SearchResult result ; + result = jestClient.execute(search); + log.debug(result.getJsonString()); + + Map resultMap = new ObjectMapper().readValue(result.getJsonString(), Map.class); + if (resultMap.get("hits") != null) { + Map hitsMap = (Map) resultMap.get("hits"); + if (hitsMap.size() > 0 && hitsMap.get("hits") != null) { + List hitsList = (List) hitsMap.get("hits"); + if (hitsList.size() > 0 && result.getSourceAsString() != null) { + + JavaType jt = new ObjectMapper().getTypeFactory().constructParametricType(ArrayList.class, EsBookVO.class); + bookList = new ObjectMapper().readValue("[" + result.getSourceAsString() + "]", jt); + + if (bookList != null) { + for (int i = 0; i < bookList.size(); i++) { + hitsMap = (Map) hitsList.get(i); + Map highlightMap = (Map) hitsMap.get("highlight"); + if (highlightMap != null && highlightMap.size() > 0) { + + List authorNameList = (List) highlightMap.get("authorName"); + if (authorNameList != null && authorNameList.size() > 0) { + bookList.get(i).setAuthorName(authorNameList.get(0)); + } + + List bookNameList = (List) highlightMap.get("bookName"); + if (bookNameList != null && bookNameList.size() > 0) { + bookList.get(i).setBookName(bookNameList.get(0)); + } + + List bookDescList = (List) highlightMap.get("bookDesc"); + if (bookDescList != null && bookDescList.size() > 0) { + bookList.get(i).setBookDesc(bookDescList.get(0)); + } + + List lastIndexNameList = (List) highlightMap.get("lastIndexName"); + if (lastIndexNameList != null && lastIndexNameList.size() > 0) { + bookList.get(i).setLastIndexName(lastIndexNameList.get(0)); + } + + List catNameList = (List) highlightMap.get("catName"); + if (catNameList != null && catNameList.size() > 0) { + bookList.get(i).setCatName(catNameList.get(0)); + } + + + } + } + + + + } + } + } + } + + PageInfo pageInfo = new PageInfo<>(bookList); + pageInfo.setTotal(total.longValue()); + pageInfo.setPageNum(page); + pageInfo.setPageSize(pageSize); + return pageInfo; + + + + + + }else{ + PageHelper.startPage(page, pageSize); + + if (StringUtils.isNotBlank(params.getSort())) { + OrderByHelper.orderBy(params.getSort() + " desc"); + } + return new PageInfo<>(bookMapper.searchByPage(params)); } - return bookMapper.searchByPage(params); + + } @Override @@ -197,7 +356,7 @@ public class BookServiceImpl implements BookService { @Override public Book queryBookDetail(Long bookId) { - SelectStatementProvider selectStatement = select(id, catName, catId, picUrl, bookName, authorId, authorName, bookDesc, bookStatus, visitCount, wordCount, lastIndexId, lastIndexName, lastIndexUpdateTime,score,status) + SelectStatementProvider selectStatement = select(book.allColumns()) .from(book) .where(id, isEqualTo(bookId)) .build() @@ -316,8 +475,7 @@ public class BookServiceImpl implements BookService { @Override public void addVisitCount(Long bookId) { - bookMapper.addVisitCount(bookId); - + bookMapper.addVisitCount(bookId,new Date()); } @Override @@ -503,7 +661,7 @@ public class BookServiceImpl implements BookService { .render(RenderingStrategies.MYBATIS3)); } - @Transactional + @Transactional(rollbackFor = Exception.class) @Override public void addBookContent(Long bookId, String indexName, String content, Long authorId) { @@ -556,5 +714,18 @@ public class BookServiceImpl implements BookService { } + @Override + public List queryBookByUpdateTimeByPage(Date startDate, Date endDate, int page, int pageSize) { + + PageHelper.startPage(page,pageSize); + + return bookMapper.selectMany(select(book.allColumns()) + .from(book) + .where(updateTime,isGreaterThanOrEqualTo(startDate)) + .and(updateTime,isLessThan(endDate)) + .build() + .render(RenderingStrategies.MYBATIS3)); + } + } diff --git a/novel-front/src/main/java/com/java2nb/novel/vo/EsBookVO.java b/novel-front/src/main/java/com/java2nb/novel/vo/EsBookVO.java new file mode 100644 index 0000000..55c5a41 --- /dev/null +++ b/novel-front/src/main/java/com/java2nb/novel/vo/EsBookVO.java @@ -0,0 +1,85 @@ +package com.java2nb.novel.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.java2nb.novel.entity.Book; +import lombok.Data; + +import javax.annotation.Generated; +import java.io.Serializable; +import java.util.Date; + +/** + * @author Administrator + */ +@Data +public class EsBookVO { + + private Long id; + + + private Byte workDirection; + + + private Integer catId; + + + private String catName; + + + private String picUrl; + + + private String bookName; + + + private Long authorId; + + + private String authorName; + + + private String bookDesc; + + + private Float score; + + + private Byte bookStatus; + + + private Long visitCount; + + + private Integer wordCount; + + + private Integer commentCount; + + + private Long lastIndexId; + + + private String lastIndexName; + + private String lastIndexUpdateTime; + + + private Byte isVip; + + + private Byte status; + + + + + private Integer crawlSourceId; + + + private String crawlBookId; + + + + private Byte crawlIsStop; + + +} diff --git a/novel-front/src/main/resources/application.yml b/novel-front/src/main/resources/application.yml index 2303787..0e96ed9 100644 --- a/novel-front/src/main/resources/application.yml +++ b/novel-front/src/main/resources/application.yml @@ -6,6 +6,15 @@ spring: active: dev include: alipay + + elasticsearch: + #是否开启搜索引擎,1:开启,0:不开启 + enable: 0 + jest: + uris: http://198.245.61.51:9200 + + + jwt: secret: novel!#20191230 expiration: 604800 diff --git a/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml b/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml index 98b0687..91e86b0 100644 --- a/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml +++ b/novel-front/src/main/resources/mybatis/mapping/BookMapper.xml @@ -34,8 +34,9 @@ - - update book set visit_count = visit_count + 1 where id = #{bookId} + + update book set visit_count = visit_count + 1 , update_time = #{date} + where id = #{bookId}