提交 38cca6fd 编写于 作者: 江南一点雨

V部落 SpringBoot后端

上级 30d4df9f
target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
\ No newline at end of file
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven2 Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Migwn, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
echo $MAVEN_PROJECTBASEDIR
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven2 Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sang</groupId>
<artifactId>blogserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>blogserver</name>
<description>Vue博客服务端</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package org.sang;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling//开启定时任务支持
public class BlogserverApplication {
public static void main(String[] args) {
SpringApplication.run(BlogserverApplication.class, args);
}
}
package org.sang.bean;
import java.sql.Timestamp;
import java.util.List;
/**
* Created by sang on 2017/12/20.
*/
public class Article {
private Long id;
private String title;
private String mdContent;
private String htmlContent;
private String summary;
private Long cid;
private Long uid;
private Timestamp publishDate;
private Integer state;
private Integer pageView;
private Timestamp editTime;
private String[] dynamicTags;
private String nickname;
private String cateName;
private List<Tags> tags;
private String stateStr;
public String getStateStr() {
return stateStr;
}
public void setStateStr(String stateStr) {
this.stateStr = stateStr;
}
public List<Tags> getTags() {
return tags;
}
public void setTags(List<Tags> tags) {
this.tags = tags;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getCateName() {
return cateName;
}
public void setCateName(String cateName) {
this.cateName = cateName;
}
public String[] getDynamicTags() {
return dynamicTags;
}
public void setDynamicTags(String[] dynamicTags) {
this.dynamicTags = dynamicTags;
}
public Timestamp getEditTime() {
return editTime;
}
public void setEditTime(Timestamp editTime) {
this.editTime = editTime;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMdContent() {
return mdContent;
}
public void setMdContent(String mdContent) {
this.mdContent = mdContent;
}
public String getHtmlContent() {
return htmlContent;
}
public void setHtmlContent(String htmlContent) {
this.htmlContent = htmlContent;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public Long getCid() {
return cid;
}
public void setCid(Long cid) {
this.cid = cid;
}
public Long getUid() {
return uid;
}
public void setUid(Long uid) {
this.uid = uid;
}
public Timestamp getPublishDate() {
return publishDate;
}
public void setPublishDate(Timestamp publishDate) {
this.publishDate = publishDate;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public Integer getPageView() {
return pageView;
}
public void setPageView(Integer pageView) {
this.pageView = pageView;
}
}
package org.sang.bean;
import java.sql.Timestamp;
/**
* Created by sang on 2017/12/19.
*/
public class Category {
private Long id;
private String cateName;
private Timestamp date;
public Category() {
}
public Timestamp getDate() {
return date;
}
public void setDate(Timestamp date) {
this.date = date;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCateName() {
return cateName;
}
public void setCateName(String cateName) {
this.cateName = cateName;
}
}
package org.sang.bean;
/**
* Created by sang on 2017/12/17.
*/
public class RespBean {
private String status;
private String msg;
public RespBean() {
}
public RespBean(String status, String msg) {
this.status = status;
this.msg = msg;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package org.sang.bean;
/**
* Created by sang on 2017/12/17.
*/
public class Role {
private Long id;
private String name;
public Role() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Role(Long id, String name) {
this.id = id;
this.name = name;
}
}
package org.sang.bean;
/**
* Created by sang on 2017/12/21.
*/
public class Tags {
private Long id;
private String tagName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
}
package org.sang.bean;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
/**
* Created by sang on 2017/12/17.
*/
public class User implements UserDetails {
private Long id;
private String username;
private String password;
private String nickname;
private boolean enabled;
private List<Role> roles;
private String email;
private String userface;
private Timestamp regTime;
public Timestamp getRegTime() {
return regTime;
}
public void setRegTime(Timestamp regTime) {
this.regTime = regTime;
}
public String getUserface() {
return userface;
}
public void setUserface(String userface) {
this.userface = userface;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
@Override
@JsonIgnore
public boolean isAccountNonExpired() {
return true;
}
@Override
@JsonIgnore
public boolean isAccountNonLocked() {
return true;
}
@Override
@JsonIgnore
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
@JsonIgnore
public List<GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
}
return authorities;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
}
package org.sang.config;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by sang on 2017/12/22.
*/
public class AuthenticationAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse resp, AccessDeniedException e) throws IOException, ServletException {
resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.write("权限不足,请联系管理员!");
out.flush();
out.close();
}
}
package org.sang.config;
import org.sang.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.util.DigestUtils;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by sang on 2017/12/17.
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
}
/**
* @param charSequence 明文
* @param s 密文
* @return
*/
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));
}
});
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/category/all").authenticated()
.antMatchers("/admin/**","/reg").hasRole("超级管理员")///admin/**的URL都需要有超级管理员角色,如果使用.hasAuthority()方法来配置,需要在参数中加上ROLE_,如下.hasAuthority("ROLE_超级管理员")
.anyRequest().authenticated()//其他的路径都是登录后即可访问
.and().formLogin().loginPage("/login_page").successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter out = httpServletResponse.getWriter();
out.write("{\"status\":\"success\",\"msg\":\"登录成功\"}");
out.flush();
out.close();
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setContentType("application/json;charset=utf-8");
PrintWriter out = httpServletResponse.getWriter();
out.write("{\"status\":\"error\",\"msg\":\"登录失败\"}");
out.flush();
out.close();
}
}).loginProcessingUrl("/login")
.usernameParameter("username").passwordParameter("password").permitAll()
.and().logout().permitAll().and().csrf().disable().exceptionHandling().accessDeniedHandler(getAccessDeniedHandler());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/blogimg/**","/index.html","/static/**");
}
@Bean
AccessDeniedHandler getAccessDeniedHandler() {
return new AuthenticationAccessDeniedHandler();
}
}
\ No newline at end of file
package org.sang.controller;
import org.apache.commons.io.IOUtils;
import org.sang.bean.Article;
import org.sang.bean.RespBean;
import org.sang.service.ArticleService;
import org.sang.utils.Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Created by sang on 2017/12/20.
*/
@RestController
@RequestMapping("/article")
public class ArticleController {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
@Autowired
ArticleService articleService;
@RequestMapping(value = "/", method = RequestMethod.POST)
public RespBean addNewArticle(Article article) {
int result = articleService.addNewArticle(article);
if (result == 1) {
return new RespBean("success", article.getId() + "");
} else {
return new RespBean("error", article.getState() == 0 ? "文章保存失败!" : "文章发表失败!");
}
}
/**
* 上传图片
*
* @return 返回值为图片的地址
*/
@RequestMapping(value = "/uploadimg", method = RequestMethod.POST)
public RespBean uploadImg(HttpServletRequest req, MultipartFile image) {
StringBuffer url = new StringBuffer();
String filePath = "/blogimg/" + sdf.format(new Date());
String imgFolderPath = req.getServletContext().getRealPath(filePath);
File imgFolder = new File(imgFolderPath);
if (!imgFolder.exists()) {
imgFolder.mkdirs();
}
url.append(req.getScheme())
.append("://")
.append(req.getServerName())
.append(":")
.append(req.getServerPort())
.append(req.getContextPath())
.append(filePath);
String imgName = UUID.randomUUID() + "_" + image.getOriginalFilename().replaceAll(" ", "");
try {
IOUtils.write(image.getBytes(), new FileOutputStream(new File(imgFolder, imgName)));
url.append("/").append(imgName);
return new RespBean("success", url.toString());
} catch (IOException e) {
e.printStackTrace();
}
return new RespBean("error", "上传失败!");
}
@RequestMapping(value = "/all", method = RequestMethod.GET)
public Map<String, Object> getArticleByState(@RequestParam(value = "state", defaultValue = "-1") Integer state, @RequestParam(value = "page", defaultValue = "1") Integer page, @RequestParam(value = "count", defaultValue = "6") Integer count,String keywords) {
int totalCount = articleService.getArticleCountByState(state, Util.getCurrentUser().getId(),keywords);
List<Article> articles = articleService.getArticleByState(state, page, count,keywords);
Map<String, Object> map = new HashMap<>();
map.put("totalCount", totalCount);
map.put("articles", articles);
return map;
}
@RequestMapping(value = "/{aid}", method = RequestMethod.GET)
public Article getArticleById(@PathVariable Long aid) {
return articleService.getArticleById(aid);
}
@RequestMapping(value = "/dustbin", method = RequestMethod.PUT)
public RespBean updateArticleState(Long[] aids, Integer state) {
if (articleService.updateArticleState(aids, state) == aids.length) {
return new RespBean("success", "删除成功!");
}
return new RespBean("error", "删除失败!");
}
@RequestMapping("/dataStatistics")
public Map<String,Object> dataStatistics() {
Map<String, Object> map = new HashMap<>();
List<String> categories = articleService.getCategories();
List<Integer> dataStatistics = articleService.getDataStatistics();
map.put("categories", categories);
map.put("ds", dataStatistics);
return map;
}
}
package org.sang.controller;
import org.sang.bean.Category;
import org.sang.bean.RespBean;
import org.sang.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 超级管理员专属Controller
*/
@RestController
@RequestMapping("/admin/category")
public class CategoryController {
@Autowired
CategoryService categoryService;
@RequestMapping(value = "/all", method = RequestMethod.GET)
public List<Category> getAllCategories() {
return categoryService.getAllCategories();
}
@RequestMapping(value = "/{ids}", method = RequestMethod.DELETE)
public RespBean deleteById(@PathVariable String ids) {
boolean result = categoryService.deleteCategoryByIds(ids);
if (result) {
return new RespBean("success", "删除成功!");
}
return new RespBean("error", "删除失败!");
}
@RequestMapping(value = "/", method = RequestMethod.POST)
public RespBean addNewCate(Category category) {
int result = categoryService.addCategory(category);
if (result == 1) {
return new RespBean("success", "添加成功!");
}
return new RespBean("error", "添加失败!");
}
@RequestMapping(value = "/", method = RequestMethod.PUT)
public RespBean updateCate(Category category) {
int i = categoryService.updateCategoryById(category);
if (i == 1) {
return new RespBean("success", "修改成功!");
}
return new RespBean("error", "修改失败!");
}
}
package org.sang.controller;
import org.sang.bean.RespBean;
import org.sang.bean.User;
import org.sang.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by sang on 2017/12/17.
*/
@RestController
public class LoginRegController {
@Autowired
UserService userService;
@RequestMapping("/login_error")
public RespBean loginError() {
return new RespBean("error", "登录失败!");
}
@RequestMapping("/login_success")
public RespBean loginSuccess() {
return new RespBean("success", "登录成功!");
}
/**
* 如果自动跳转到这个页面,说明用户未登录,返回相应的提示即可
* <p>
* 如果要支持表单登录,可以在这个方法中判断请求的类型,进而决定返回JSON还是HTML页面
*
* @return
*/
@RequestMapping("/login_page")
public RespBean loginPage() {
return new RespBean("error", "尚未登录,请登录!");
}
@RequestMapping("/reg")
public RespBean reg(User user) {
int result = userService.reg(user);
if (result == 0) {
//成功
return new RespBean("success", "注册成功!");
} else if (result == 1) {
return new RespBean("error", "用户名重复,注册失败!");
} else {
//失败
return new RespBean("error", "注册失败!");
}
}
}
package org.sang.controller;
import org.sang.bean.RespBean;
import org.sang.service.UserService;
import org.sang.utils.Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* Created by sang on 2017/12/24.
*/
@RestController
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/currentUserName")
public String currentUserName() {
return Util.getCurrentUser().getNickname();
}
@RequestMapping("/currentUserId")
public Long currentUserId() {
return Util.getCurrentUser().getId();
}
@RequestMapping("/currentUserEmail")
public String currentUserEmail() {
return Util.getCurrentUser().getEmail();
}
@RequestMapping("/isAdmin")
public Boolean isAdmin() {
List<GrantedAuthority> authorities = Util.getCurrentUser().getAuthorities();
for (GrantedAuthority authority : authorities) {
if (authority.getAuthority().contains("超级管理员")) {
return true;
}
}
return false;
}
@RequestMapping(value = "/updateUserEmail",method = RequestMethod.PUT)
public RespBean updateUserEmail(String email) {
if (userService.updateUserEmail(email) == 1) {
return new RespBean("success", "开启成功!");
}
return new RespBean("error", "开启失败!");
}
}
package org.sang.controller.admin;
import org.sang.bean.Article;
import org.sang.bean.RespBean;
import org.sang.service.ArticleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 超级管理员专属Controller
*/
@RestController
@RequestMapping("/admin")
public class AdminController {
@Autowired
ArticleService articleService;
@RequestMapping(value = "/article/all", method = RequestMethod.GET)
public Map<String, Object> getArticleByStateByAdmin(@RequestParam(value = "page", defaultValue = "1") Integer page, @RequestParam(value = "count", defaultValue = "6") Integer count, String keywords) {
List<Article> articles = articleService.getArticleByState(-2, page, count, keywords);
Map<String, Object> map = new HashMap<>();
map.put("articles", articles);
map.put("totalCount", articleService.getArticleCountByState(1, null, keywords));
return map;
}
@RequestMapping(value = "/article/dustbin", method = RequestMethod.PUT)
public RespBean updateArticleState(Long[] aids, Integer state) {
if (articleService.updateArticleState(aids, state) == aids.length) {
return new RespBean("success", "删除成功!");
}
return new RespBean("error", "删除失败!");
}
}
package org.sang.controller.admin;
import org.sang.bean.RespBean;
import org.sang.bean.Role;
import org.sang.bean.User;
import org.sang.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* Created by sang on 2017/12/24.
*/
@RestController
@RequestMapping("/admin")
public class UserManaController {
@Autowired
UserService userService;
@RequestMapping(value = "/user", method = RequestMethod.GET)
public List<User> getUserByNickname(String nickname) {
return userService.getUserByNickname(nickname);
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
@RequestMapping(value = "/roles", method = RequestMethod.GET)
public List<Role> getAllRole() {
return userService.getAllRole();
}
@RequestMapping(value = "/user/enabled", method = RequestMethod.PUT)
public RespBean updateUserEnabled(Boolean enabled, Long uid) {
if (userService.updateUserEnabled(enabled, uid) == 1) {
return new RespBean("success", "更新成功!");
} else {
return new RespBean("error", "更新失败!");
}
}
@RequestMapping(value = "/user/{uid}", method = RequestMethod.DELETE)
public RespBean deleteUserById(@PathVariable Long uid) {
if (userService.deleteUserById(uid) == 1) {
return new RespBean("success", "删除成功!");
} else {
return new RespBean("error", "删除失败!");
}
}
@RequestMapping(value = "/user/role", method = RequestMethod.PUT)
public RespBean updateUserRoles(Long[] rids, Long id) {
if (userService.updateUserRoles(rids, id) == rids.length) {
return new RespBean("success", "更新成功!");
} else {
return new RespBean("error", "更新失败!");
}
}
}
package org.sang.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.sang.bean.Article;
import java.util.List;
/**
* Created by sang on 2017/12/20.
*/
@Mapper
public interface ArticleMapper {
int addNewArticle(Article article);
int updateArticle(Article article);
List<Article> getArticleByState(@Param("state") Integer state, @Param("start") Integer start, @Param("count") Integer count, @Param("uid") Long uid,@Param("keywords") String keywords);
// List<Article> getArticleByStateByAdmin(@Param("start") int start, @Param("count") Integer count, @Param("keywords") String keywords);
int getArticleCountByState(@Param("state") Integer state, @Param("uid") Long uid, @Param("keywords") String keywords);
int updateArticleState(@Param("aids") Long aids[], @Param("state") Integer state);
int deleteArticleById(@Param("aids") Long[] aids);
Article getArticleById(Long aid);
void pvIncrement(Long aid);
//INSERT INTO pv(countDate,pv,uid) SELECT NOW(),SUM(pageView),uid FROM article GROUP BY uid
void pvStatisticsPerDay();
List<String> getCategories(Long uid);
List<Integer> getDataStatistics(Long uid);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.mapper.ArticleMapper">
<insert id="addNewArticle" parameterType="org.sang.bean.Article" useGeneratedKeys="true" keyProperty="id">
INSERT INTO article SET title=#{title},mdContent=#{mdContent},htmlContent=#{htmlContent},summary=#{summary},cid=#{cid},uid=#{uid},publishDate=#{publishDate},state=#{state},editTime=#{editTime}
</insert>
<update id="pvIncrement" parameterType="Long">
UPDATE article set pageView=pageView+1 WHERE id=#{aid}
</update>
<update id="updateArticle" parameterType="org.sang.bean.Article">
UPDATE article SET
title=#{title},mdContent=#{mdContent},htmlContent=#{htmlContent},summary=#{summary},cid=#{cid},editTime=#{editTime}
<if test="state==1">
,state=1
</if>
<if test="publishDate!=null">
,publishDate=#{publishDate}
</if>
WHERE id=#{id}
</update>
<select id="getArticleByState" resultType="org.sang.bean.Article">
SELECT a.id,a.`title`,a.`editTime`,a.`pageView`,a.`state`,u.`nickname`,c.`cateName`,a.uid FROM article a,user
u,category c WHERE a.`cid`=c.`id` AND a.`uid`=u.`id`
<if test="state!=-2">
and a.uid=#{uid}
</if>
<if test="state!=-1 and state!=-2">
and a.state=#{state}
</if>
<if test="state==-2">
and a.state=1
</if>
<if test="keywords!=null">
AND title LIKE concat('%',#{keywords},'%')
</if>
ORDER BY a.editTime DESC limit #{start},#{count};
</select>
<select id="getArticleByStateByAdmin" resultType="org.sang.bean.Article">
SELECT a.id,a.`title`,a.`editTime`,a.`pageView`,a.`state`,u.`nickname`,c.`cateName`,a.uid FROM article a,user
u,category c WHERE a.`cid`=c.`id` AND a.`uid`=u.`id` and a.state=1
<if test="keywords!=null">
AND title LIKE concat('%',#{keywords},'%')
</if>
ORDER BY a.editTime DESC limit #{start},#{count};
</select>
<select id="getArticleCountByState" resultType="int">
SELECT count(*) FROM article
<where>
<if test="state!=-1">
AND state=#{state}
</if>
<if test="uid!=null">
AND uid=#{uid}
</if>
<if test="keywords!=null">
AND title LIKE concat('%',#{keywords},'%')
</if>
</where>
</select>
<update id="updateArticleState">
UPDATE article SET state=#{state} WHERE id IN
<foreach collection="aids" item="aid" separator="," open="(" close=")">
#{aid}
</foreach>
</update>
<delete id="deleteArticleById">
DELETE FROM article WHERE id IN
<foreach collection="aids" item="aid" open="(" close=")" separator=",">
#{aid}
</foreach>
</delete>
<select id="getArticleById" parameterType="Long" resultMap="BaseResultMap">
SELECT a.*,t.`tagName`,t.`id` AS tid,u.`nickname`,c.`cateName` FROM article a LEFT JOIN article_tags ats ON a.`id`=ats.`aid` LEFT JOIN tags t ON ats.`tid`=t.`id` LEFT JOIN user u ON a.`uid`=u.`id` LEFT JOIN category c ON a.`cid`=c.`id` WHERE a.id=#{aid}
</select>
<resultMap id="BaseResultMap" type="org.sang.bean.Article">
<id column="id" property="id"/>
<result column="title" property="title"/>
<result column="cid" property="cid"/>
<result column="uid" property="uid"/>
<result column="publishDate" property="publishDate"/>
<result column="editTime" property="editTime"/>
<result column="state" property="state"/>
<result column="pageView" property="pageView"/>
<result column="mdContent" property="mdContent"/>
<result column="htmlContent" property="htmlContent"/>
<result column="summary" property="summary"/>
<result column="nickname" property="nickname"/>
<result column="cateName" property="cateName"/>
<collection property="tags" ofType="org.sang.bean.Tags" column="tagName">
<id property="id" column="tid"/>
<result property="tagName" column="tagName"/>
</collection>
</resultMap>
<insert id="pvStatisticsPerDay">
INSERT INTO pv(countDate,pv,uid) SELECT CURRENT_DATE(),totalPv-pv,t.`uid` FROM pvview p,totalpvview t WHERE p.`uid`=t.`uid`
</insert>
<select id="getCategories" resultType="String" parameterType="long">
SELECT countDate from pv WHERE uid=#{uid} ORDER by countDate limit 7
</select>
<select parameterType="long" id="getDataStatistics" resultType="int">
SELECT pv from pv WHERE uid=#{uid} ORDER by countDate limit 7
</select>
</mapper>
\ No newline at end of file
package org.sang.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.sang.bean.Category;
import java.util.List;
/**
* Created by sang on 2017/12/19.
*/
@Mapper
public interface CategoryMapper {
List<Category> getAllCategories();
int deleteCategoryByIds(@Param("ids") String[] ids);
int updateCategoryById(Category category);
int addCategory(Category category);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.mapper.CategoryMapper">
<select id="getAllCategories" resultType="org.sang.bean.Category">
SELECT * FROM category
</select>
<delete id="deleteCategoryByIds">
DELETE FROM category WHERE id IN
<foreach collection="ids" separator="," open="(" close=")" item="id">
#{id}
</foreach>
</delete>
<update id="updateCategoryById" parameterType="org.sang.bean.Category">
UPDATE category SET cateName=#{cateName} WHERE id=#{id}
</update>
<insert id="addCategory" parameterType="org.sang.bean.Category">
INSERT INTO category SET date=#{date},cateName=#{cateName}
</insert>
</mapper>
\ No newline at end of file
package org.sang.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.sang.bean.Role;
import java.util.List;
/**
* Created by sang on 2017/12/17.
*/
@Mapper
public interface RolesMapper {
int addRoles(@Param("roles") String[] roles, @Param("uid") Long uid);
List<Role> getRolesByUid(Long uid);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.mapper.RolesMapper">
<insert id="addRoles">
INSERT INTO roles_user VALUES
<foreach collection="roles" item="role" separator=",">
(null,#{role},#{uid})
</foreach>
</insert>
<select id="getRolesByUid" parameterType="long" resultType="org.sang.bean.Role">
SELECT r.* FROM roles r,roles_user ru WHERE r.`id`=ru.`rid` AND ru.`uid`=#{uid}
</select>
</mapper>
\ No newline at end of file
package org.sang.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Created by sang on 2017/12/21.
*/
@Mapper
public interface TagsMapper {
int deleteTagsByAid(Long aid);
int saveTags(@Param("tags") String[] tags);
List<Long> getTagsIdByTagName(@Param("tagNames") String[] tagNames);
int saveTags2ArticleTags(@Param("tagIds") List<Long> tagIds, @Param("aid") Long aid);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.mapper.TagsMapper">
<delete id="deleteTagsByAid" parameterType="Long">
DELETE FROM article_tags WHERE aid=#{aid}
</delete>
<insert id="saveTags">
INSERT IGNORE INTO tags(tagName) VALUES
<foreach collection="tags" item="tag" separator=",">
(#{tag})
</foreach>
</insert>
<select id="getTagsIdByTagName" resultType="long">
SELECT id FROM tags WHERE tagName IN
<foreach collection="tagNames" item="tagName" separator="," open="(" close=")">
#{tagName}
</foreach>
</select>
<insert id="saveTags2ArticleTags">
INSERT INTO article_tags(aid,tid) VALUES
<foreach collection="tagIds" item="tagId" separator=",">
(#{aid},#{tagId})
</foreach>
</insert>
</mapper>
\ No newline at end of file
package org.sang.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.sang.bean.Role;
import org.sang.bean.User;
import java.util.List;
/**
* Created by sang on 2017/12/17.
*/
@Mapper
public interface UserMapper {
User loadUserByUsername(@Param("username") String username);
long reg(User user);
int updateUserEmail(@Param("email") String email, @Param("id") Long id);
List<User> getUserByNickname(@Param("nickname") String nickname);
List<Role> getAllRole();
int updateUserEnabled(@Param("enabled") Boolean enabled, @Param("uid") Long uid);
int deleteUserById(Long uid);
int deleteUserRolesByUid(Long id);
int setUserRoles(@Param("rids") Long[] rids, @Param("id") Long id);
User getUserById(@Param("id") Long id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.mapper.UserMapper">
<select id="loadUserByUsername" resultType="org.sang.bean.User">
SELECT * FROM user WHERE username=#{username}
</select>
<insert id="reg" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user set username=#{username},password=#{password},nickname=#{nickname}
</insert>
<update id="updateUserEmail">
UPDATE user set email=#{email} WHERE id=#{id}
</update>
<select id="getUserByNickname" resultMap="BaseResultMap">
SELECT u.*,r.`id` AS rid,r.`name` AS rname FROM user u,roles r,roles_user ru WHERE u.`id`=ru.`uid` AND
r.`id`=ru.`rid` AND u.`id` NOT IN(SELECT u.`id` FROM user u,roles_user ru WHERE u.`id`=ru.`uid` AND ru.`rid`=1)
<choose>
<when test="nickname!=null and nickname!=''">
and u.nickname like concat('%',#{nickname},'%') ORDER BY u.`id`
</when>
<otherwise>
ORDER BY u.`id` limit 20
</otherwise>
</choose>
</select>
<select id="getUserById" resultMap="BaseResultMap">
SELECT u.*,r.`id` AS rid,r.`name` AS rname FROM user u,roles r,roles_user ru WHERE u.`id`=ru.`uid` AND
r.`id`=ru.`rid` AND u.`id`=#{id}
</select>
<resultMap id="BaseResultMap" type="org.sang.bean.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="nickname" property="nickname"/>
<result column="password" property="password"/>
<result column="enabled" property="enabled"/>
<result column="email" property="email"/>
<result column="userface" property="userface"/>
<result column="regTime" property="regTime"/>
<collection property="roles" ofType="org.sang.bean.Role">
<id column="rid" property="id"/>
<result column="rname" property="name"/>
</collection>
</resultMap>
<select id="getAllRole" resultType="org.sang.bean.Role">
select * from roles;
</select>
<update id="updateUserEnabled">
UPDATE user set enabled=#{enabled} WHERE id=#{uid}
</update>
<delete id="deleteUserById">
DELETE FROM user WHERE id=#{id}
</delete>
<delete id="deleteUserRolesByUid">
DELETE FROM roles_user WHERE uid=#{id}
</delete>
<insert id="setUserRoles">
INSERT INTO roles_user(rid,uid) VALUES
<foreach collection="rids" separator="," item="rid">
(#{rid},#{id})
</foreach>
</insert>
</mapper>
\ No newline at end of file
package org.sang.service;
import org.sang.bean.Article;
import org.sang.mapper.ArticleMapper;
import org.sang.mapper.TagsMapper;
import org.sang.utils.Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
/**
* Created by sang on 2017/12/20.
*/
@Service
@Transactional
public class ArticleService {
@Autowired
ArticleMapper articleMapper;
@Autowired
TagsMapper tagsMapper;
public int addNewArticle(Article article) {
//处理文章摘要
if (article.getSummary() == null || "".equals(article.getSummary())) {
//直接截取
String stripHtml = stripHtml(article.getHtmlContent());
article.setSummary(stripHtml.substring(0, stripHtml.length() > 50 ? 50 : stripHtml.length()));
}
if (article.getId() == -1) {
//添加操作
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
if (article.getState() == 1) {
//设置发表日期
article.setPublishDate(timestamp);
}
article.setEditTime(timestamp);
//设置当前用户
article.setUid(Util.getCurrentUser().getId());
int i = articleMapper.addNewArticle(article);
//打标签
String[] dynamicTags = article.getDynamicTags();
if (dynamicTags != null && dynamicTags.length > 0) {
int tags = addTagsToArticle(dynamicTags, article.getId());
if (tags == -1) {
return tags;
}
}
return i;
} else {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
if (article.getState() == 1) {
//设置发表日期
article.setPublishDate(timestamp);
}
//更新
article.setEditTime(new Timestamp(System.currentTimeMillis()));
int i = articleMapper.updateArticle(article);
//修改标签
String[] dynamicTags = article.getDynamicTags();
if (dynamicTags != null && dynamicTags.length > 0) {
int tags = addTagsToArticle(dynamicTags, article.getId());
if (tags == -1) {
return tags;
}
}
return i;
}
}
private int addTagsToArticle(String[] dynamicTags, Long aid) {
//1.删除该文章目前所有的标签
tagsMapper.deleteTagsByAid(aid);
//2.将上传上来的标签全部存入数据库
tagsMapper.saveTags(dynamicTags);
//3.查询这些标签的id
List<Long> tIds = tagsMapper.getTagsIdByTagName(dynamicTags);
//4.重新给文章设置标签
int i = tagsMapper.saveTags2ArticleTags(tIds, aid);
return i == dynamicTags.length ? i : -1;
}
public String stripHtml(String content) {
content = content.replaceAll("<p .*?>", "");
content = content.replaceAll("<br\\s*/?>", "");
content = content.replaceAll("\\<.*?>", "");
return content;
}
public List<Article> getArticleByState(Integer state, Integer page, Integer count,String keywords) {
int start = (page - 1) * count;
Long uid = Util.getCurrentUser().getId();
return articleMapper.getArticleByState(state, start, count, uid,keywords);
}
// public List<Article> getArticleByStateByAdmin(Integer page, Integer count,String keywords) {
// int start = (page - 1) * count;
// return articleMapper.getArticleByStateByAdmin(start, count,keywords);
// }
public int getArticleCountByState(Integer state, Long uid,String keywords) {
return articleMapper.getArticleCountByState(state, uid,keywords);
}
public int updateArticleState(Long[] aids, Integer state) {
if (state == 2) {
return articleMapper.deleteArticleById(aids);
} else {
return articleMapper.updateArticleState(aids, 2);//放入到回收站中
}
}
public Article getArticleById(Long aid) {
Article article = articleMapper.getArticleById(aid);
articleMapper.pvIncrement(aid);
return article;
}
public void pvStatisticsPerDay() {
articleMapper.pvStatisticsPerDay();
}
/**
* 获取最近七天的日期
* @return
*/
public List<String> getCategories() {
return articleMapper.getCategories(Util.getCurrentUser().getId());
}
/**
* 获取最近七天的数据
* @return
*/
public List<Integer> getDataStatistics() {
return articleMapper.getDataStatistics(Util.getCurrentUser().getId());
}
}
package org.sang.service;
import org.sang.bean.Category;
import org.sang.mapper.CategoryMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Timestamp;
import java.util.List;
/**
* Created by sang on 2017/12/19.
*/
@Service
@Transactional
public class CategoryService {
@Autowired
CategoryMapper categoryMapper;
public List<Category> getAllCategories() {
return categoryMapper.getAllCategories();
}
public boolean deleteCategoryByIds(String ids) {
String[] split = ids.split(",");
int result = categoryMapper.deleteCategoryByIds(split);
return result == split.length;
}
public int updateCategoryById(Category category) {
return categoryMapper.updateCategoryById(category);
}
public int addCategory(Category category) {
category.setDate(new Timestamp(System.currentTimeMillis()));
return categoryMapper.addCategory(category);
}
}
package org.sang.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* Created by sang on 2017/12/25.
*/
@Component
public class DataStatisticsComponent {
@Autowired
ArticleService articleService;
//每天执行一次,统计PV
@Scheduled(cron = "1 0 0 * * ?")
public void pvStatisticsPerDay() {
articleService.pvStatisticsPerDay();
}
}
package org.sang.service;
import org.sang.bean.Role;
import org.sang.bean.User;
import org.sang.mapper.RolesMapper;
import org.sang.mapper.UserMapper;
import org.sang.utils.Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import java.util.List;
/**
* Created by sang on 2017/12/17.
*/
@Service
@Transactional
public class UserService implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Autowired
RolesMapper rolesMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userMapper.loadUserByUsername(s);
if (user == null) {
//避免返回null,这里返回一个不含有任何值的User对象,在后期的密码比对过程中一样会验证失败
return new User();
}
//查询用户的角色信息,并返回存入user中
List<Role> roles = rolesMapper.getRolesByUid(user.getId());
user.setRoles(roles);
return user;
}
/**
* @param user
* @return 0表示成功
* 1表示用户名重复
* 2表示失败
*/
public int reg(User user) {
User loadUserByUsername = userMapper.loadUserByUsername(user.getUsername());
if (loadUserByUsername != null) {
return 1;
}
//插入用户,插入之前先对密码进行加密
user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
user.setEnabled(true);//用户可用
long result = userMapper.reg(user);
//配置用户的角色,默认都是普通用户
String[] roles = new String[]{"2"};
int i = rolesMapper.addRoles(roles, user.getId());
boolean b = i == roles.length && result == 1;
if (b) {
return 0;
} else {
return 2;
}
}
public int updateUserEmail(String email) {
return userMapper.updateUserEmail(email, Util.getCurrentUser().getId());
}
public List<User> getUserByNickname(String nickname) {
List<User> list = userMapper.getUserByNickname(nickname);
return list;
}
public List<Role> getAllRole() {
return userMapper.getAllRole();
}
public int updateUserEnabled(Boolean enabled, Long uid) {
return userMapper.updateUserEnabled(enabled, uid);
}
public int deleteUserById(Long uid) {
return userMapper.deleteUserById(uid);
}
public int updateUserRoles(Long[] rids, Long id) {
int i = userMapper.deleteUserRolesByUid(id);
return userMapper.setUserRoles(rids, id);
}
public User getUserById(Long id) {
return userMapper.getUserById(id);
}
}
package org.sang.utils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
/**
* Created by sang on 2017/12/25.
*/
@MappedJdbcTypes(JdbcType.DATE)
@MappedTypes(String.class)
public class DateTypeHandler implements TypeHandler<String> {
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@Override
public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
}
@Override
public String getResult(ResultSet rs, String columnName) throws SQLException {
return sdf.format(rs.getDate(columnName));
}
@Override
public String getResult(ResultSet rs, int columnIndex) throws SQLException {
return sdf.format(rs.getDate(columnIndex));
}
@Override
public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
return sdf.format(cs.getDate(columnIndex));
}
}
package org.sang.utils;
import org.sang.bean.User;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Created by sang on 2017/12/20.
*/
public class Util {
public static User getCurrentUser() {
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return user;
}
}
spring.datasource.url=jdbc:mysql:///vueblog?useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=username
spring.datasource.password=password
mybatis.config-location=classpath:/mybatis-config.xml
server.port=8081
logging.level.org.springframework.security=info
\ No newline at end of file
log4j.rootLogger=DEBUG,stdout
log4j.logger.org.mybatis=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
</configuration>
\ No newline at end of file
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>V部落</title><link href=/static/css/app.bc863c01bd283b4b819e7aecef3aac7f.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.fc113b1d276302e2cab1.js></script><script type=text/javascript src=/static/js/vendor.dd31c3932b33cfeec940.js></script><script type=text/javascript src=/static/js/app.68f5c35407ca9cd40d8b.js></script></body></html>
\ No newline at end of file
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2017 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="bold" unicode="&#xe800;" d="M310 1q41-18 78-18 210 0 210 187 0 64-23 101-15 24-34 41t-38 26-45 14-47 6-53 1q-40 0-56-6 0-29 0-88t-1-88q0-5 0-38t0-54 2-47 7-37z m-8 417q23-4 61-4 46 0 80 7t61 25 42 50 14 79q0 39-16 68t-45 46-60 24-69 8q-28 0-73-7 0-28 3-84t2-85q0-15 0-45t-1-44q0-26 1-38z m-302-497l1 53q9 2 48 9t59 15q4 7 7 15t4 19 4 18 1 21 0 19v36q0 548-12 572-2 5-12 8t-25 6-28 4-27 3-17 2l-2 46q55 1 190 6t208 6q13 0 38-1t38 0q39 0 76-7t72-24 60-39 41-59 16-76q0-29-9-54t-22-40-36-32-41-25-47-22q86-20 144-75t57-138q0-56-20-101t-52-72-77-48-91-27-98-8q-25 0-74 2t-74 1q-59 0-171-6t-129-7z" horiz-adv-x="785.7" />
<glyph glyph-name="italic" unicode="&#xe801;" d="M0-78l10 48q12 4 34 9t40 11 33 13q16 19 23 56 1 4 35 162t63 303 29 165v14q-13 8-30 11t-39 4-32 3l10 58q19-1 67-4t84-4 67-1q27 0 55 1t68 4 54 4q-2-22-10-50-17-6-57-16t-60-19q-5-10-8-23t-5-23-4-25-4-24q-15-82-49-234t-43-198q-1-5-7-32t-11-51-9-46-4-32l1-10q9-3 103-18-2-24-9-55-6 0-18-1t-18-1q-16 0-49 6t-48 6q-77 1-115 1-28 0-79-5t-68-7z" horiz-adv-x="571.4" />
<glyph glyph-name="thumb-tack" unicode="&#xe802;" d="M650 779q12 0 24-5 19-8 29-23t11-35v-719q0-19-11-35t-29-23q-10-4-24-4-27 0-47 18l-246 236-246-236q-20-19-46-19-13 0-25 5-18 7-29 23t-11 35v719q0 19 11 35t29 23q12 5 25 5h585z" horiz-adv-x="714.3" />
<glyph glyph-name="link" unicode="&#xe803;" d="M813 171q0 23-16 38l-116 116q-16 16-38 16-24 0-40-18 1-1 10-10t12-12 9-11 7-14 2-15q0-23-16-38t-38-16q-8 0-15 2t-14 7-11 9-12 12-10 10q-19-17-19-40 0-23 16-38l115-116q15-15 38-15 22 0 38 15l82 81q16 16 16 37z m-393 394q0 22-15 38l-115 115q-16 16-38 16-22 0-38-15l-82-82q-16-15-16-37 0-22 16-38l116-116q15-15 38-15 23 0 40 17-2 2-11 11t-12 12-8 10-7 14-2 16q0 22 15 38t38 15q9 0 16-2t14-7 11-8 12-12 10-11q18 17 18 41z m500-394q0-66-48-113l-82-81q-46-47-113-47-68 0-114 48l-115 115q-46 47-46 114 0 68 49 116l-49 49q-48-49-116-49-67 0-114 47l-116 116q-47 47-47 114t47 113l82 82q47 46 114 46 67 0 114-47l115-116q46-46 46-113 0-69-49-117l49-49q48 49 116 49 67 0 114-47l116-116q47-47 47-114z" horiz-adv-x="928.6" />
<glyph glyph-name="picture-o" unicode="&#xe804;" d="M357 529q0-45-31-76t-76-32-76 32-31 76 31 76 76 31 76-31 31-76z m572-215v-250h-786v107l178 179 90-89 285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-7 6-13t12-5h893q7 0 13 5t5 13v678q0 8-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
<glyph glyph-name="repeat" unicode="&#xe805;" d="M857 707v-250q0-14-10-25t-26-11h-250q-23 0-32 23-10 22 7 38l77 77q-82 77-194 77-58 0-111-23t-91-61-61-91-23-111 23-111 61-91 91-61 111-23q66 0 125 29t100 82q4 6 13 7 8 0 14-5l76-77q5-4 6-11t-5-13q-60-74-147-114t-182-41q-87 0-167 34t-136 92-92 137-34 166 34 166 92 137 136 92 167 34q82 0 158-31t137-88l72 72q17 18 39 8 22-9 22-33z" horiz-adv-x="857.1" />
<glyph glyph-name="undo" unicode="&#xe806;" d="M857 350q0-87-34-166t-91-137-137-92-166-34q-96 0-183 41t-147 114q-4 6-4 13t5 11l76 77q6 5 14 5 9-1 13-7 41-53 100-82t126-29q58 0 110 23t92 61 61 91 22 111-22 111-61 91-92 61-110 23q-55 0-105-20t-90-57l77-77q17-16 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l72-72q60 57 137 88t159 31q87 0 166-34t137-92 91-137 34-166z" horiz-adv-x="857.1" />
<glyph glyph-name="trash-o" unicode="&#xe807;" d="M286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q23 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
<glyph glyph-name="floppy-o" unicode="&#xe808;" d="M214-7h429v214h-429v-214z m500 0h72v500q0 8-6 21t-11 20l-157 156q-5 6-19 12t-22 5v-232q0-22-15-38t-38-16h-322q-22 0-37 16t-16 38v232h-72v-714h72v232q0 22 16 38t37 16h465q22 0 38-16t15-38v-232z m-214 518v178q0 8-5 13t-13 5h-107q-7 0-13-5t-5-13v-178q0-7 5-13t13-5h107q7 0 13 5t5 13z m357-18v-518q0-22-15-38t-38-16h-750q-23 0-38 16t-16 38v750q0 22 16 38t38 16h517q23 0 50-12t42-26l156-157q16-15 27-42t11-49z" horiz-adv-x="857.1" />
<glyph glyph-name="compress" unicode="&#xe809;" d="M429 314v-250q0-14-11-25t-25-10-25 10l-81 81-185-186q-5-5-13-5t-12 5l-64 64q-6 6-6 13t6 13l185 185-80 80q-11 11-11 25t11 25 25 11h250q14 0 25-11t11-25z m421 375q0-7-6-12l-185-186 80-80q11-11 11-25t-11-25-25-11h-250q-14 0-25 11t-10 25v250q0 14 10 25t25 10 25-10l81-80 185 185q6 5 13 5t13-5l63-64q6-5 6-13z" horiz-adv-x="857.1" />
<glyph glyph-name="eye" unicode="&#xe80a;" d="M929 314q-85 132-213 197 34-58 34-125 0-103-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197 75-114 187-182t242-68 243 68 186 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38t11 39q78 128 210 205t279 78 279-78 210-205q11-20 11-39z" horiz-adv-x="1000" />
<glyph glyph-name="eye-slash" unicode="&#xe80b;" d="M310 105l43 79q-48 35-76 88t-27 114q0 67 34 125-128-65-213-197 94-144 239-209z m217 424q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m202 106q0-4 0-5-59-105-176-316t-176-316l-28-50q-5-9-15-9-7 0-75 39-9 6-9 16 0 7 25 49-80 36-147 96t-117 137q-11 17-11 38t11 39q86 131 212 207t277 76q50 0 100-10l31 54q5 9 15 9 3 0 10-3t18-9 18-10 18-10 10-7q9-5 9-15z m21-249q0-78-44-142t-117-91l157 280q4-25 4-47z m250-72q0-19-11-38-22-36-61-81-84-96-194-149t-234-53l41 74q119 10 219 76t169 171q-65 100-158 164l35 63q53-36 102-85t81-103q11-19 11-39z" horiz-adv-x="1000" />
<glyph glyph-name="question-circle" unicode="&#xe80c;" d="M500 82v107q0 8-5 13t-13 5h-107q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h107q8 0 13 5t5 13z m143 375q0 49-31 91t-77 65-95 23q-136 0-207-119-9-13 4-24l74-55q4-4 10-4 9 0 14 7 30 38 48 51 19 14 48 14 27 0 48-15t21-33q0-21-11-34t-38-25q-35-15-65-48t-29-70v-20q0-8 5-13t13-5h107q8 0 13 5t5 13q0 10 12 27t30 28q18 10 28 16t25 19 25 27 16 34 7 45z m214-107q0-117-57-215t-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
<glyph glyph-name="times" unicode="&#xe80d;" d="M724 112q0-22-15-38l-76-76q-16-15-38-15t-38 15l-164 165-164-165q-16-15-38-15t-38 15l-76 76q-16 16-16 38t16 38l164 164-164 164q-16 16-16 38t16 38l76 76q16 16 38 16t38-16l164-164 164 164q16 16 38 16t38-16l76-76q15-15 15-38t-15-38l-164-164 164-164q15-15 15-38z" horiz-adv-x="785.7" />
<glyph glyph-name="align-left" unicode="&#xe80f;" d="M1000 100v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m-214 214v-71q0-15-11-25t-25-11h-714q-15 0-25 11t-11 25v71q0 15 11 25t25 11h714q15 0 25-11t11-25z m143 215v-72q0-14-11-25t-25-11h-857q-15 0-25 11t-11 25v72q0 14 11 25t25 10h857q14 0 25-10t11-25z m-215 214v-72q0-14-10-25t-25-10h-643q-15 0-25 10t-11 25v72q0 14 11 25t25 11h643q14 0 25-11t10-25z" horiz-adv-x="1000" />
<glyph glyph-name="align-center" unicode="&#xe810;" d="M1000 100v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m-214 214v-71q0-15-11-25t-25-11h-500q-14 0-25 11t-11 25v71q0 15 11 25t25 11h500q15 0 25-11t11-25z m143 215v-72q0-14-11-25t-25-11h-786q-14 0-25 11t-11 25v72q0 14 11 25t25 10h786q14 0 25-10t11-25z m-215 214v-72q0-14-10-25t-25-10h-358q-14 0-25 10t-10 25v72q0 14 10 25t25 11h358q14 0 25-11t10-25z" horiz-adv-x="1000" />
<glyph glyph-name="align-right" unicode="&#xe811;" d="M1000 100v-71q0-15-11-25t-25-11h-928q-15 0-25 11t-11 25v71q0 15 11 25t25 11h928q15 0 25-11t11-25z m0 214v-71q0-15-11-25t-25-11h-714q-14 0-25 11t-11 25v71q0 15 11 25t25 11h714q15 0 25-11t11-25z m0 215v-72q0-14-11-25t-25-11h-857q-14 0-25 11t-11 25v72q0 14 11 25t25 10h857q15 0 25-10t11-25z m0 214v-72q0-14-11-25t-25-10h-643q-14 0-25 10t-10 25v72q0 14 10 25t25 11h643q15 0 25-11t11-25z" horiz-adv-x="1000" />
<glyph glyph-name="arrows-alt" unicode="&#xf0b2;" d="M716 548l-198-198 198-198 80 80q17 18 39 8 22-9 22-33v-250q0-14-10-25t-26-11h-250q-23 0-32 23-10 21 7 38l81 81-198 198-198-198 80-81q17-17 8-38-10-23-33-23h-250q-15 0-25 11t-11 25v250q0 24 22 33 22 10 39-8l80-80 198 198-198 198-80-80q-11-11-25-11-7 0-14 3-22 9-22 33v250q0 14 11 25t25 11h250q23 0 33-23 9-21-8-38l-80-81 198-198 198 198-81 81q-17 17-7 38 9 23 32 23h250q15 0 26-11t10-25v-250q0-24-22-33-7-3-14-3-14 0-25 11z" horiz-adv-x="857.1" />
<glyph glyph-name="bars" unicode="&#xf0c9;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
<glyph glyph-name="list-ul" unicode="&#xf0ca;" d="M214 64q0-44-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m0 286q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m786-232v-107q0-7-5-13t-13-5h-678q-8 0-13 5t-5 13v107q0 7 5 12t13 6h678q7 0 13-6t5-12z m-786 518q0-45-31-76t-76-31-76 31-31 76 31 76 76 31 76-31 31-76z m786-232v-108q0-7-5-12t-13-5h-678q-8 0-13 5t-5 12v108q0 7 5 12t13 5h678q7 0 13-5t5-12z m0 285v-107q0-7-5-12t-13-6h-678q-8 0-13 6t-5 12v107q0 8 5 13t13 5h678q7 0 13-5t5-13z" horiz-adv-x="1000" />
<glyph glyph-name="list-ol" unicode="&#xf0cb;" d="M213-54q0-45-31-70t-75-26q-60 0-96 37l31 49q28-25 60-25 16 0 28 8t12 24q0 35-59 31l-14 31q4 6 18 24t24 31 20 21v1q-9 0-27-1t-27 0v-30h-59v85h186v-49l-53-65q28-6 45-27t17-49z m1 350v-89h-202q-4 20-4 30 0 29 14 52t31 38 37 27 31 24 14 25q0 14-9 22t-22 7q-25 0-45-32l-47 33q13 28 40 44t59 16q40 0 68-23t28-63q0-28-19-51t-42-36-42-28-20-30h71v34h59z m786-178v-107q0-7-5-13t-13-5h-678q-8 0-13 5t-5 13v107q0 8 5 13t13 5h678q7 0 13-6t5-12z m-786 502v-56h-187v56h60q0 22 0 67t1 68v7h-1q-5-10-28-30l-40 42 76 71h59v-225h60z m786-216v-108q0-7-5-12t-13-5h-678q-8 0-13 5t-5 12v108q0 7 5 12t13 5h678q7 0 13-5t5-12z m0 285v-107q0-7-5-12t-13-6h-678q-8 0-13 6t-5 12v107q0 8 5 13t13 5h678q7 0 13-5t5-13z" horiz-adv-x="1000" />
<glyph glyph-name="strikethrough" unicode="&#xf0cc;" d="M982 350q8 0 13-5t5-13v-36q0-7-5-12t-13-5h-964q-8 0-13 5t-5 12v36q0 8 5 13t13 5h964z m-712 36q-16 19-29 44-27 55-27 105 0 101 75 173 74 71 219 71 28 0 94-11 36-7 98-27 6-21 12-66 8-68 8-102 0-10-3-25l-7-2-46 4-8 1q-28 83-58 114-49 51-117 51-64 0-101-33-38-32-38-81 0-41 37-78t156-72q38-12 96-37 33-16 53-29h-414z m283-143h229q4-22 4-51 0-62-23-119-13-31-40-58-20-19-61-45-44-27-85-37-45-12-113-12-64 0-109 13l-78 23q-32 8-40 15-5 5-5 12v8q0 60-1 87 0 17 0 38l1 20v25l57 1q8-19 17-40t12-31 7-15q20-32 45-52 24-20 59-32 33-12 73-12 36 0 78 15 43 14 68 48 26 34 26 72 0 47-45 87-19 16-76 40z" horiz-adv-x="1000" />
<glyph glyph-name="underline" unicode="&#xf0cd;" d="M27 726q-21 1-25 2l-2 49q7 1 22 1 34 0 63-3 74-4 93-4 47 0 93 2 65 2 82 3 31 0 48 1l-1-8 1-36v-5q-33-5-69-5-33 0-44-14-7-7-7-73 0-7 0-18t0-15l1-127 8-157q3-69 28-112 20-33 54-52 49-26 98-26 59 0 107 16 31 10 55 28 27 20 37 36 20 31 29 63 12 41 12 128 0 44-2 72t-6 68-8 89l-2 33q-3 37-13 49-19 20-43 19l-56-1-8 2 1 48h47l114-6q43-2 110 6l10-1q3-22 3-29 0-4-2-17-25-7-47-8-41-6-44-9-8-8-8-23 0-4 0-15t1-17q5-11 13-221 3-109-9-170-8-42-23-68-21-36-62-69-42-31-102-49-61-19-142-19-93 0-159 26-66 26-99 68-34 42-47 109-9 45-9 132v186q0 105-9 119-14 20-82 22z m830-787v36q0 8-5 13t-13 5h-821q-8 0-13-5t-5-13v-36q0-8 5-13t13-5h821q8 0 13 5t5 13z" horiz-adv-x="857.1" />
<glyph glyph-name="table" unicode="&#xf0ce;" d="M286 82v107q0 8-5 13t-13 5h-179q-7 0-12-5t-6-13v-107q0-8 6-13t12-5h179q8 0 13 5t5 13z m0 214v108q0 7-5 12t-13 5h-179q-7 0-12-5t-6-12v-108q0-7 6-12t12-5h179q8 0 13 5t5 12z m285-214v107q0 8-5 13t-12 5h-179q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h179q7 0 12 5t5 13z m-285 429v107q0 8-5 13t-13 5h-179q-7 0-12-5t-6-13v-107q0-8 6-13t12-5h179q8 0 13 5t5 13z m285-215v108q0 7-5 12t-12 5h-179q-8 0-13-5t-5-12v-108q0-7 5-12t13-5h179q7 0 12 5t5 12z m286-214v107q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h178q8 0 13 5t5 13z m-286 429v107q0 8-5 13t-12 5h-179q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h179q7 0 12 5t5 13z m286-215v108q0 7-5 12t-13 5h-178q-8 0-13-5t-5-12v-108q0-7 5-12t13-5h178q8 0 13 5t5 12z m0 215v107q0 8-5 13t-13 5h-178q-8 0-13-5t-5-13v-107q0-8 5-13t13-5h178q8 0 13 5t5 13z m72 178v-607q0-37-27-63t-63-26h-750q-36 0-63 26t-26 63v607q0 37 26 63t63 27h750q37 0 63-27t27-63z" horiz-adv-x="928.6" />
<glyph glyph-name="columns" unicode="&#xf0db;" d="M89-7h340v643h-358v-625q0-7 6-13t12-5z m768 18v625h-357v-643h339q8 0 13 5t5 13z m72 678v-678q0-37-27-63t-63-27h-750q-36 0-63 27t-26 63v678q0 37 26 63t63 27h750q37 0 63-27t27-63z" horiz-adv-x="928.6" />
<glyph glyph-name="quote-left" unicode="&#xf10d;" d="M429 314v-214q0-45-32-76t-76-31h-214q-44 0-76 31t-31 76v393q0 58 23 111t61 91 91 61 111 23h35q15 0 26-11t10-25v-72q0-14-10-25t-26-10h-35q-59 0-101-42t-42-101v-18q0-22 16-38t37-16h125q45 0 76-31t32-76z m500 0v-214q0-45-32-76t-76-31h-214q-44 0-76 31t-31 76v393q0 58 23 111t61 91 91 61 111 23h35q15 0 26-11t10-25v-72q0-14-10-25t-26-10h-35q-59 0-101-42t-42-101v-18q0-22 16-38t37-16h125q45 0 76-31t32-76z" horiz-adv-x="928.6" />
<glyph glyph-name="code" unicode="&#xf121;" d="M344 69l-28-28q-5-5-12-5t-13 5l-260 261q-6 5-6 12t6 13l260 260q5 6 13 6t12-6l28-28q6-5 6-13t-6-12l-219-220 219-219q6-6 6-13t-6-13z m330 596l-208-721q-2-7-9-11t-13-1l-34 9q-8 3-11 9t-2 14l209 720q2 8 8 11t13 2l35-10q7-2 11-9t1-13z m367-363l-260-261q-6-5-13-5t-13 5l-28 28q-5 6-5 13t5 13l219 219-219 220q-5 5-5 12t5 13l28 28q6 6 13 6t13-6l260-260q5-5 5-13t-5-12z" horiz-adv-x="1071.4" />
<glyph glyph-name="superscript" unicode="&#xf12b;" d="M501 86v-93h-139l-89 141-13 23q-4 5-6 12h-2q0-2-1-4t-2-4-2-4q-5-11-14-25l-86-139h-144v93h71l110 162-103 152h-76v94h154l77-127q1-2 13-24 4-5 6-11h2q1 5 6 11l14 24 78 127h143v-94h-69l-103-149 114-165h61z m355 379v-115h-287l-1 15q-3 16-3 26 0 36 15 65t36 48 47 37 47 30 36 30 15 36q0 21-17 35t-39 13q-29 0-54-21-8-6-20-22l-59 52q15 20 35 37 47 36 105 36 61 0 99-33t38-89q0-31-13-57t-35-43-45-33-46-28-37-28-17-36h130v45h70z" horiz-adv-x="857.1" />
<glyph glyph-name="subscript" unicode="&#xf12c;" d="M501 86v-93h-139l-89 141-13 23q-4 5-6 12h-2q0-2-1-4t-2-4-2-4q-5-11-14-25l-86-139h-144v93h71l110 162-103 152h-76v94h154l77-127q1-2 13-24 4-5 6-11h2q1 5 6 11l14 24 78 127h143v-94h-69l-103-149 114-165h61z m356-121v-115h-287l-2 15q-2 25-2 26 0 35 15 65t36 48 47 37 47 30 36 30 15 36q0 21-17 35t-39 13q-28 0-54-21-8-6-20-22l-59 52q15 20 35 37 45 36 105 36 62 0 100-33t37-89q0-37-19-66t-47-48-55-35-49-35-23-41h130v45h70z" horiz-adv-x="857.1" />
<glyph glyph-name="header" unicode="&#xf1dc;" d="M939-79q-25 0-74 2t-75 2q-24 0-73-2t-74-2q-13 0-21 12t-7 25q0 18 9 26t22 9 29 4 25 9q18 11 18 78l0 218q0 12-1 17-7 3-28 3h-376q-22 0-29-3 0-5 0-17l-1-207q0-79 21-91 9-6 26-8t32-2 25-8 11-26q0-14-6-26t-21-13q-26 0-78 2t-77 2q-24 0-71-2t-71-2q-13 0-20 12t-7 25q0 17 9 25t20 10 26 4 24 9q18 13 18 80l-1 31v454q0 2 1 15t0 20-1 21-2 24-4 20-6 18-9 10q-8 5-25 7t-29 1-23 7-10 26q0 14 6 26t20 13q26 0 78-2t77-2q23 0 71 2t70 2q14 0 21-13t7-26q0-17-9-25t-22-8-27-2-24-7q-20-12-20-90l1-178q0-12 0-18 7-2 22-2h390q14 0 21 2 1 6 1 18l0 178q0 78-19 90-10 6-33 7t-37 7-14 28q0 14 7 26t21 13q24 0 74-2t73-2q24 0 72 2t72 2q14 0 21-13t7-26q0-17-10-25t-22-8-29-2-24-7q-20-13-20-90l1-526q0-66 19-78 9-6 25-8t30-2 23-9 10-25q0-14-6-26t-20-13z" horiz-adv-x="1000" />
<glyph glyph-name="window-maximize" unicode="&#xf2d0;" d="M143 64h714v429h-714v-429z m857 625v-678q0-37-26-63t-63-27h-822q-36 0-63 27t-26 63v678q0 37 26 63t63 27h822q37 0 63-27t26-63z" horiz-adv-x="1000" />
</font>
</defs>
</svg>
\ No newline at end of file
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var i,u,f,s=0,l=[];s<t.length;s++)u=t[s],o[u]&&l.push(o[u][0]),o[u]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(r&&r(t,c,a);l.length;)l.shift()();if(a)for(s=0;s<a.length;s++)f=n(n.s=a[s]);return f};var t={},o={2:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(u);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+"static/js/"+e+"."+{0:"dd31c3932b33cfeec940",1:"68f5c35407ca9cd40d8b"}[e]+".js";var u=setTimeout(r,12e4);return i.onerror=i.onload=r,a.appendChild(i),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/",n.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.fc113b1d276302e2cab1.js.map
\ No newline at end of file
{"version":3,"sources":["webpack:///webpack/bootstrap ac24a0864a201f07cdd1"],"names":["__webpack_require__","moduleId","installedModules","exports","module","i","l","modules","call","parentJsonpFunction","window","chunkIds","moreModules","executeModules","chunkId","result","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","shift","s","2","e","onScriptComplete","script","onerror","onload","clearTimeout","timeout","chunk","Error","undefined","installedChunkData","Promise","resolve","promise","reject","head","document","getElementsByTagName","createElement","type","charset","async","nc","setAttribute","src","p","0","1","setTimeout","appendChild","m","c","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","oe","err","console","error"],"mappings":"aAuCA,SAAAA,EAAAC,GAGA,GAAAC,EAAAD,GACA,OAAAC,EAAAD,GAAAE,QAGA,IAAAC,EAAAF,EAAAD,IACAI,EAAAJ,EACAK,GAAA,EACAH,YAUA,OANAI,EAAAN,GAAAO,KAAAJ,EAAAD,QAAAC,IAAAD,QAAAH,GAGAI,EAAAE,GAAA,EAGAF,EAAAD,QA1DA,IAAAM,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAZ,EAAAa,EAAAC,EAAAV,EAAA,EAAAW,KACQX,EAAAM,EAAAM,OAAoBZ,IAC5BS,EAAAH,EAAAN,GACAa,EAAAJ,IACAE,EAAAG,KAAAD,EAAAJ,GAAA,IAEAI,EAAAJ,GAAA,EAEA,IAAAb,KAAAW,EACAQ,OAAAC,UAAAC,eAAAd,KAAAI,EAAAX,KACAM,EAAAN,GAAAW,EAAAX,IAIA,IADAQ,KAAAE,EAAAC,EAAAC,GACAG,EAAAC,QACAD,EAAAO,OAAAP,GAEA,GAAAH,EACA,IAAAR,EAAA,EAAYA,EAAAQ,EAAAI,OAA2BZ,IACvCU,EAAAf,IAAAwB,EAAAX,EAAAR,IAGA,OAAAU,GAIA,IAAAb,KAGAgB,GACAO,EAAA,GA6BAzB,EAAA0B,EAAA,SAAAZ,GA+BA,SAAAa,IAEAC,EAAAC,QAAAD,EAAAE,OAAA,KACAC,aAAAC,GACA,IAAAC,EAAAf,EAAAJ,GACA,IAAAmB,IACAA,GACAA,EAAA,OAAAC,MAAA,iBAAApB,EAAA,aAEAI,EAAAJ,QAAAqB,GAvCA,IAAAC,EAAAlB,EAAAJ,GACA,OAAAsB,EACA,WAAAC,QAAA,SAAAC,GAA0CA,MAI1C,GAAAF,EACA,OAAAA,EAAA,GAIA,IAAAG,EAAA,IAAAF,QAAA,SAAAC,EAAAE,GACAJ,EAAAlB,EAAAJ,IAAAwB,EAAAE,KAEAJ,EAAA,GAAAG,EAGA,IAAAE,EAAAC,SAAAC,qBAAA,WACAf,EAAAc,SAAAE,cAAA,UACAhB,EAAAiB,KAAA,kBACAjB,EAAAkB,QAAA,QACAlB,EAAAmB,OAAA,EACAnB,EAAAI,QAAA,KAEAhC,EAAAgD,IACApB,EAAAqB,aAAA,QAAAjD,EAAAgD,IAEApB,EAAAsB,IAAAlD,EAAAmD,EAAA,aAAArC,EAAA,KAAwEsC,EAAA,uBAAAC,EAAA,wBAAsDvC,GAAA,MAC9H,IAAAkB,EAAAsB,WAAA3B,EAAA,MAgBA,OAfAC,EAAAC,QAAAD,EAAAE,OAAAH,EAaAc,EAAAc,YAAA3B,GAEAW,GAIAvC,EAAAwD,EAAAjD,EAGAP,EAAAyD,EAAAvD,EAGAF,EAAA0D,EAAA,SAAAvD,EAAAwD,EAAAC,GACA5D,EAAA6D,EAAA1D,EAAAwD,IACAvC,OAAA0C,eAAA3D,EAAAwD,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMA5D,EAAAkE,EAAA,SAAA9D,GACA,IAAAwD,EAAAxD,KAAA+D,WACA,WAA2B,OAAA/D,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAJ,EAAA0D,EAAAE,EAAA,IAAAA,GACAA,GAIA5D,EAAA6D,EAAA,SAAAO,EAAAC,GAAsD,OAAAjD,OAAAC,UAAAC,eAAAd,KAAA4D,EAAAC,IAGtDrE,EAAAmD,EAAA,IAGAnD,EAAAsE,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA","file":"static/js/manifest.fc113b1d276302e2cab1.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t2: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tvar installedChunkData = installedChunks[chunkId];\n \t\tif(installedChunkData === 0) {\n \t\t\treturn new Promise(function(resolve) { resolve(); });\n \t\t}\n\n \t\t// a Promise means \"currently loading\".\n \t\tif(installedChunkData) {\n \t\t\treturn installedChunkData[2];\n \t\t}\n\n \t\t// setup Promise in chunk cache\n \t\tvar promise = new Promise(function(resolve, reject) {\n \t\t\tinstalledChunkData = installedChunks[chunkId] = [resolve, reject];\n \t\t});\n \t\tinstalledChunkData[2] = promise;\n\n \t\t// start chunk loading\n \t\tvar head = document.getElementsByTagName('head')[0];\n \t\tvar script = document.createElement('script');\n \t\tscript.type = 'text/javascript';\n \t\tscript.charset = 'utf-8';\n \t\tscript.async = true;\n \t\tscript.timeout = 120000;\n\n \t\tif (__webpack_require__.nc) {\n \t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n \t\t}\n \t\tscript.src = __webpack_require__.p + \"static/js/\" + chunkId + \".\" + {\"0\":\"dd31c3932b33cfeec940\",\"1\":\"68f5c35407ca9cd40d8b\"}[chunkId] + \".js\";\n \t\tvar timeout = setTimeout(onScriptComplete, 120000);\n \t\tscript.onerror = script.onload = onScriptComplete;\n \t\tfunction onScriptComplete() {\n \t\t\t// avoid mem leaks in IE.\n \t\t\tscript.onerror = script.onload = null;\n \t\t\tclearTimeout(timeout);\n \t\t\tvar chunk = installedChunks[chunkId];\n \t\t\tif(chunk !== 0) {\n \t\t\t\tif(chunk) {\n \t\t\t\t\tchunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));\n \t\t\t\t}\n \t\t\t\tinstalledChunks[chunkId] = undefined;\n \t\t\t}\n \t\t};\n \t\thead.appendChild(script);\n\n \t\treturn promise;\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap ac24a0864a201f07cdd1"],"sourceRoot":""}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>01.html</h1>
</body>
</html>
\ No newline at end of file
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册