前后端整合

master
HZXhuang 3 years ago
parent deec8527f4
commit 84fa3a31f4

25
.gitignore vendored

@ -0,0 +1,25 @@
.DS_Store
node_modules
dist
target
project
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

@ -0,0 +1,185 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot</name>
<description>中国语言文化传播效果分析系统</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.3</version>
</dependency>
<!-- excel导出依赖-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 支付宝SDK -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.2.0</version>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.7</version>
</dependency>
<!-- Spring Mail依赖(发送邮件) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- FreeMarker模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.7.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.23</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>aliyun nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="web" name="Web">
<configuration>
<webroots />
<sourceRoots>
<root url="file://$MODULE_DIR$/src/main/java" />
<root url="file://$MODULE_DIR$/src/main/resources" />
</sourceRoots>
</configuration>
</facet>
<facet type="Spring" name="Spring">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/${project.build.directory}/classes" />
<excludeFolder url="file://$MODULE_DIR$/${project.build.directory}/test-classes" />
<excludeFolder url="file://$MODULE_DIR$/target" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.5.2" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.3" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.14.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.14.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.31" level="project" />
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.28" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.5.2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.12.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.12.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.48" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.48" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.48" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:5.5.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:5.5.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:5.5.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:5.5.1" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.5.2" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:4.0.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.2.0" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.7" level="project" />
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.6" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:8.0.25" level="project" />
<orderEntry type="library" name="Maven: com.alibaba:druid:1.2.3" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
<orderEntry type="library" name="Maven: org.projectlombok:lombok:1.18.20" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-boot-starter:3.4.3.1" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus:3.4.3.1" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.4.3.1" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.4.3.1" level="project" />
<orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.4.3.1" level="project" />
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:4.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.5.2" level="project" />
<orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.7.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.4" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-math3:3.6.1" level="project" />
<orderEntry type="library" name="Maven: com.zaxxer:SparseBitSet:1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:4.1.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:3.1.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.19" level="project" />
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.06" level="project" />
<orderEntry type="library" name="Maven: com.aliyun.oss:aliyun-sdk-oss:3.10.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.13" level="project" />
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.14" level="project" />
<orderEntry type="library" name="Maven: org.jdom:jdom2:2.0.6" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.jettison:jettison:1.1" level="project" />
<orderEntry type="library" name="Maven: stax:stax-api:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-core:3.4.0" level="project" />
<orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-ram:3.0.0" level="project" />
<orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-sts:3.0.0" level="project" />
<orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-ecs:4.2.0" level="project" />
<orderEntry type="library" name="Maven: com.aliyun:aliyun-java-sdk-kms:2.7.0" level="project" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.7" level="project" />
<orderEntry type="library" name="Maven: com.auth0:java-jwt:3.4.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.12.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.12.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.12.3" level="project" />
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.15" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.11.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-websocket:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-messaging:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-websocket:5.3.8" level="project" />
<orderEntry type="library" name="Maven: com.alipay.sdk:alipay-easysdk:2.2.0" level="project" />
<orderEntry type="library" name="Maven: com.alipay.sdk:easysdk-kernel:1.0.8" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.31" level="project" />
<orderEntry type="library" name="Maven: com.aliyun:tea:1.0.7" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:3.14.9" level="project" />
<orderEntry type="library" name="Maven: com.squareup.okio:okio:1.17.2" level="project" />
<orderEntry type="library" name="Maven: org.jacoco:org.jacoco.agent:runtime:0.8.4" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:28.1-jre" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
<orderEntry type="library" name="Maven: org.checkerframework:checker-qual:2.8.1" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.2" level="project" />
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.18" level="project" />
<orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.64" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring-boot-starter:2.0.7" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring-boot-autoconfigure:2.0.7" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring:2.0.7" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-annotations:2.0.7" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-core:2.0.7" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.25.0-GA" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-models:1.5.22" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-annotations:1.5.22" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger2:2.10.5" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spi:2.10.5" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-core:2.10.5" level="project" />
<orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.10.22" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-schema:2.10.5" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-swagger-common:2.10.5" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spring-web:2.10.5" level="project" />
<orderEntry type="library" name="Maven: io.github.classgraph:classgraph:4.1.7" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-core:2.0.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.plugin:spring-plugin-metadata:2.0.0.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.mapstruct:mapstruct:1.3.1.Final" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-bean-validators:2.10.5" level="project" />
<orderEntry type="library" name="Maven: io.springfox:springfox-spring-webmvc:2.10.5" level="project" />
<orderEntry type="library" name="Maven: com.github.xiaoymin:knife4j-spring-ui:2.0.7" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-mail:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.3.8" level="project" />
<orderEntry type="library" name="Maven: com.sun.mail:jakarta.mail:1.6.7" level="project" />
<orderEntry type="library" name="Maven: com.sun.activation:jakarta.activation:1.2.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-freemarker:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.freemarker:freemarker:2.3.31" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.7.5" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.5.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.13.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:2.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.3.23" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.3.8" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.3.8" level="project" />
</component>
</module>

@ -0,0 +1,13 @@
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@SpringBootApplication
@EnableWebSecurity //开启security
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

@ -0,0 +1,69 @@
package com.example.demo.common;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.demo.entity.Admin;
import com.example.demo.entity.User;
import com.example.demo.enums.RoleEnum;
import com.example.demo.exception.CustomException;
import com.example.demo.mapper.UserMapper;
import com.example.demo.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// request.getLocalAddr();
String uri = request.getRequestURI();
System.out.println("request: " + uri);
String token = null;
try {
token = TokenUtils.getToken(); // 获取token
} catch (Exception e) {
e.printStackTrace();
throw new CustomException("401", "未获取到token, 请重新登录");
}
if (StrUtil.isBlank(token)) {
throw new CustomException("401", "未获取到token, 请重新登录");
}
String userType = TokenUtils.getUserType();
// System.out.println(userType);
if (RoleEnum.USER.getLabel().equals(userType)) { // 普通的用户
User loginUser = TokenUtils.getLoginUser();
if (loginUser == null) {
throw new CustomException("401", "token不合法");
}
// 验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(loginUser.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (Exception e) {
throw new CustomException("401", "token不合法");
}
} else if (RoleEnum.ADMIN.getLabel().equals(userType)) { // 管理员用户
Admin loginAdmin = TokenUtils.getLoginAdmin();
if (loginAdmin == null) {
throw new CustomException("401", "token不合法");
}
// 验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(loginAdmin.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (Exception e) {
throw new CustomException("401", "token不合法");
}
} else {
throw new CustomException("401", "token不合法");
}
return true;
}
}

@ -0,0 +1,59 @@
package com.example.demo.common;
public class Result<T> {
private String code;
private String msg;
private T data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Result() {
}
public Result(T data) {
this.data = data;
}
public static Result success() {
Result result = new Result<>();
result.setCode("0");
result.setMsg("成功");
return result;
}
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>(data);
result.setCode("0");
result.setMsg("成功");
return result;
}
public static Result error(String code, String msg) {
Result result = new Result();
result.setCode(code);
result.setMsg(msg);
return result;
}
}

@ -0,0 +1,30 @@
package com.example.demo.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
// 当前跨域请求最大有效时长。这里默认1天
private static final long MAX_AGE = 24 * 60 * 60;
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
corsConfiguration.setMaxAge(MAX_AGE);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
return new CorsFilter(source);
}
}

@ -0,0 +1,35 @@
package com.example.demo.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfiguration {
// 地址 ip:port/doc
@Bean(value = "SpringBoot-Vue-Demo-Api")
public Docket cloudMallApi() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("接口文档列表")
.description("接口文档")
.termsOfServiceUrl("http://www.springboot.vue.com")
.version("1.0")
.build())
//分组名称
.groupName("2.X版本")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}

@ -0,0 +1,27 @@
package com.example.demo.common.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mybatis-plus
*/
@Configuration
@MapperScan("com.example.demo.mapper")
public class MybatisPlusConfig {
/**
*
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

@ -0,0 +1,42 @@
package com.example.demo.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* @author hzx
* @version 1.0
* @Description Spring security
* @Date 2021/12/3 21:35
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// 授权
.antMatchers("/**")
.anonymous()
.anyRequest()
// 权限认证
.authenticated()
.and().csrf().disable(); // 跨域请求验证
}
/*
* BCryptPasswordEncoder
*/
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
// public static void main(String[] args) {
// String encode = new BCryptPasswordEncoder().encode("admin");
// System.out.println(encode);
// }
}

@ -0,0 +1,43 @@
package com.example.demo.common.config;
import com.example.demo.common.AuthInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
// 拦截器配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
*
* @param registry xx
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(authInterceptor())
// .addPathPatterns("/**/update", "/**/add", "/**/delete/**",
// "/**/import", "/**/export", "/**/importTemplate") // 拦截请求
// 指定的请求拦截的释放
/*.excludePathPatterns("/api/user/login", "/api/user/register",
"/api/admin/login", "/api/admin/register",
"/api/hot-work/**",
"/imserver/**", "/files/**", "/alipay/**",
"/doc.html", "/webjars/**", "/swagger-resources/**")*/;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//配置拦截器访问静态资源
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean
public AuthInterceptor authInterceptor() {
return new AuthInterceptor();
}
}

@ -0,0 +1,290 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.Admin;
import com.example.demo.entity.User;
import com.example.demo.enums.PwdEnum;
import com.example.demo.mapper.AdminMapper;
import com.example.demo.utils.AdminTokenUtils;
import com.example.demo.utils.AliOssUtil;
import com.example.demo.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
@RestController
@RequestMapping("/api/admin")
public class AdminController {
@Autowired
AdminMapper adminMapper;
@Autowired
BCryptPasswordEncoder bCryptPasswordEncoder; // crypt加密器
@PostMapping("/login")
public Result<?> login(@RequestBody Admin adminParam) {
Admin admin = adminMapper.selectByUsername(adminParam.getUsername()); // 通过管理员账号username查询
if (admin == null) {
return Result.error("-1", "管理员用户不存在!");
}
// 数据库中该管理员的的密码(密文)和输入的密码(明文)进行比较,
if (!bCryptPasswordEncoder.matches(adminParam.getPassword(), admin.getPassword())) {
return Result.error("-1", "密码错误!");
}
// 生成token
String token = TokenUtils.genToken(admin);
admin.setToken(token);
return Result.success(admin); // 返回成功
}
// 注册
@PostMapping("/register")
public Result<?> register(@RequestBody Admin admin) {
// 双冒号 lambda表达式
Admin res = adminMapper.selectOne(Wrappers.<Admin>lambdaQuery().eq(Admin::getUsername, admin.getUsername()));
if (res != null) {
return Result.error("-1", "用户名重复");
}
String password = admin.getPassword();
if (password == null || "".equals(password.trim())) password = PwdEnum.PASSWORD.getPassword(); // 如果密码为空,设置成默认的密码
String name = admin.getName();
if (name == null || "".equals(name.trim())) name = "管理员" + IdWorker.getId();
Admin adminInfo = Admin.builder()
.username(admin.getUsername())
.password(bCryptPasswordEncoder.encode(password))
.name(name) // 默认的名称
.level(2)
.build();
adminMapper.insert(adminInfo);
return Result.success();
}
// 保存(更新)管理员信息
@PutMapping("/update")
public Result<?> save(@RequestBody Admin admin) {
if (admin.getPassword() == null) {
admin.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
}
adminMapper.updateById(admin); // 通过主键id更新
return Result.success();
}
// 重置管理员的密码
@PutMapping("/resetPwd")
public Result<?> resetPwd(@RequestParam Integer adminId) {
Admin admin = adminMapper.selectById(adminId);
if (admin == null) {
return Result.error("-1", "未找到用户");
}
// 重置密码
admin.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
adminMapper.updateById(admin);
return Result.success();
}
// 上传管理员的头像接口
@PostMapping("/uploadAvatar")
public Result<?> uploadAvatar(MultipartFile file) {
if (!file.isEmpty()) {
Admin loginAdmin = TokenUtils.getLoginAdmin();
if (loginAdmin == null) {
return Result.error("401", "管理员未登录");
}
String avatar = AliOssUtil.upload("images/", file); // 上传文件到阿里云OSS存储服务器
loginAdmin.setAvatar(avatar);
int res = adminMapper.updateById(loginAdmin);
if (res > 0) {
return Result.success(avatar);
}
return Result.error("-1", "上传管理员头像失败");
}
return Result.error("-1", "上传的文件为空");
}
// 更改管理员密码
@PutMapping("/pass")
public Result<?> pass(@RequestBody Map<String, Object> map) {
Admin loginAdmin = TokenUtils.getLoginAdmin();
if (loginAdmin == null) {
return Result.error("-1", "未找到管理员");
}
String password = loginAdmin.getPassword(); // 获取管理员的密码
if (!TokenUtils.matchPassword(map.get("oldPwd").toString(), password)) {
return Result.error("-1", "修改密码失败,旧密码错误!");
}
if (TokenUtils.matchPassword(map.get("newPwd").toString(), password)) {
return Result.error("-1", "新密码不能与旧密码相同!");
}
map.put("newPwd", (bCryptPasswordEncoder.encode(map.get("newPwd").toString())));
map.put("id", loginAdmin.getId());
int res = adminMapper.updatePass(map);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改失败");
}
// 删除指定管理员
@DeleteMapping("/delete/{ids}")
public Result<?> delete(@PathVariable Long[] ids) {
int res = adminMapper.deleteBatchIds(Arrays.asList(ids));
if (res > 0) {
return Result.success();
}
return Result.error("-1", "删除失败!");
}
@GetMapping("/id/{id}") // 查询指定id的管理员
public Result<?> getById(@PathVariable Long id) {
return Result.success(adminMapper.selectById(id));
}
@GetMapping("/all") // 查询所有
public Result<?> findAll() {
return Result.success(adminMapper.selectList(null));
}
// 获取当前登录的管理员的个人信息
@GetMapping("/profile")
public Result<?> getProfile() {
return Result.success(TokenUtils.getLoginAdmin());
}
/**
*
* @param pageNum
* @param pageSize
* @param searchName
* @param searchUsername
* @return
*/
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(defaultValue = "") String searchUsername,
@RequestParam(defaultValue = "") String searchName) {
Page<Admin> adminPage = adminMapper.findByPage(new Page<>(pageNum, pageSize), searchUsername, searchName);
return Result.success(adminPage);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<Admin> admins = adminMapper.selectList(null);
for (Admin admin : admins) {
Map<String, Object> row1 = new LinkedHashMap<>();
row1.put("用户名", admin.getUsername());
row1.put("昵称", admin.getName());
row1.put("手机号码", admin.getPhone());
row1.put("邮箱", admin.getEmail());
list.add(row1);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("管理员信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row1 = new LinkedHashMap<>();
row1.put("用户名", "");
row1.put("昵称", "");
row1.put("手机号码", "");
row1.put("邮箱", "");
list.add(row1);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("管理员信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
* 使 Excel
*
* @param file Excel
* @return json
* @throws IOException IO
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException {
InputStream inputStream = file.getInputStream();
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<Admin> saveList = new ArrayList<>();
for (List<Object> row : lists) { // 遍历每一行
Admin admin = new Admin();
admin.setUsername(row.get(0).toString());
admin.setName(row.get(1).toString());
admin.setPhone(row.get(2).toString());
admin.setEmail(row.get(3).toString());
admin.setPassword(PwdEnum.PASSWORD.getPassword()); // 默认的密码 123
saveList.add(admin);
}
for (Admin admin : saveList) {
adminMapper.insert(admin);
}
return Result.success();
}
}

@ -0,0 +1,30 @@
package com.example.demo.controller;
import com.auth0.jwt.JWT;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
public class BaseController {
@Autowired
private UserMapper userMapper;
@Autowired
private HttpServletRequest request;
/**
* token
* @return user
*/
public User getUser() {
String token = request.getHeader("token");
String aud = JWT.decode(token).getAudience().get(0);
Integer userId = Integer.valueOf(aud);
return userMapper.selectById(userId);
}
}

@ -0,0 +1,127 @@
package com.example.demo.controller;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.example.demo.common.Result;
import com.example.demo.entity.dto.FileVO;
import com.example.demo.utils.AliOssUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
@RestController
@RequestMapping("/files")
public class FileController extends BaseController {
@Value("${server.port}")
private String port;
@Value("${file.ip}")
private String ip;
/**
*
* @param file
* @return
* @throws IOException
*/
@PostMapping("/upload")
public Result<?> upload(MultipartFile file) throws IOException {
String originalFilename = file.getOriginalFilename(); // 获取源文件的名称
// 定义文件的唯一标识(前缀)
String flag = IdUtil.fastSimpleUUID();
String rootFilePath = System.getProperty("user.dir") + "/files/" + flag + "_" + originalFilename; // 获取上传的路径
File rootFile = new File(rootFilePath);
if (!rootFile.getParentFile().exists()) {
rootFile.getParentFile().mkdirs();
}
FileUtil.writeBytes(file.getBytes(), rootFilePath); // 把文件写入到上传的路径
return Result.success("http://" + ip + ":" + port + "/files/" + flag); // 返回结果 url
}
/**
*
* @param file
* @return
* @throws IOException
*/
@PostMapping("/editor/upload")
public JSON editorUpload(MultipartFile file) throws IOException {
String originalFilename = file.getOriginalFilename(); // 获取源文件的名称
// 定义文件的唯一标识(前缀)
String flag = IdUtil.fastSimpleUUID();
String rootFilePath = System.getProperty("user.dir") + "/files/" + flag + "_" + originalFilename; // 获取上传的路径
File rootFile = new File(rootFilePath);
if (!rootFile.getParentFile().exists()) {
rootFile.getParentFile().mkdirs();
}
FileUtil.writeBytes(file.getBytes(), rootFilePath); // 把文件写入到上传的路径
String url = "http://" + ip + ":" + port + "/files/" + flag;
JSONObject json = new JSONObject();
json.set("errno", 0);
JSONArray arr = new JSONArray();
JSONObject data = new JSONObject();
arr.add(data);
data.set("url", url);
json.set("data", arr);
return json; // 返回结果 url
}
/**
*
* @param flag
* @param response
*/
@GetMapping("/{flag}")
public void getFiles(@PathVariable String flag, HttpServletResponse response) {
OutputStream os; // 新建一个输出流对象
String basePath = System.getProperty("user.dir") + "/files/"; // 定于文件上传的根路径
List<String> fileNames = FileUtil.listFileNames(basePath); // 获取所有的文件名称
String fileName = fileNames.stream().filter(name -> name.contains(flag)).findAny().orElse(""); // 找到跟参数一致的文件
try {
if (StrUtil.isNotEmpty(fileName)) {
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
response.setContentType("application/octet-stream");
byte[] bytes = FileUtil.readBytes(basePath + fileName); // 通过文件的路径读取文件字节流
os = response.getOutputStream(); // 通过输出流返回文件
os.write(bytes);
os.flush();
os.close();
}
} catch (Exception e) {
System.out.println("文件下载失败");
}
}
/**
* OSS
* @param file
* @return
*/
@PostMapping("/upload/oss")
public Result<?> ossUpload(MultipartFile file) {
return Result.success(AliOssUtil.upload("images/", file)); // 返回结果 url
}
/**
* OSS
* @param fileVO
* @return
*/
@DeleteMapping("/delete/oss")
public Result<?> ossUpload(@RequestBody FileVO fileVO) {
AliOssUtil.delete(fileVO.getFilekey());
return Result.success();
}
}

@ -0,0 +1,192 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.HotWork;
import com.example.demo.mapper.HotWorkMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
// 热点文化作品信息
@RequestMapping("/api/hot-work")
@RestController
public class HotWorkController {
@Autowired
private HotWorkMapper hotWorkMapper;
// 查询所有的热点作品信息
@GetMapping("/all")
public Result<?> findAll() {
List<HotWork> hotWorks = hotWorkMapper.selectList(null);
return Result.success(hotWorks);
}
@GetMapping("/id/{id}")
public Result<?> findById(@PathVariable Long id) {
HotWork hotWork = hotWorkMapper.selectById(id);
return Result.success(hotWork);
}
// 分页 搜索查询
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(required = false, defaultValue = "") String searchName,
@RequestParam(required = false, defaultValue = "") String searchCategory,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
LambdaQueryWrapper<HotWork> queryWrapper = Wrappers.<HotWork>lambdaQuery()
.like(HotWork::getName, searchName)
.like(HotWork::getCategory, searchCategory)
.orderByAsc(HotWork::getId);
return Result.success(hotWorkMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper));
}
// 根据id删除指定热点作品
@DeleteMapping("/delete/{id}")
public Result<?> deleteById(@PathVariable Long id) {
int res = hotWorkMapper.deleteById(id);
if (res > 0) {
Result.success();
}
return Result.error("-1", "该热点作品已经被删除了");
}
// 新增热点文化作品
@PostMapping("/add")
public Result<?> add(@RequestBody HotWork hotWork) {
int res = hotWorkMapper.insert(hotWork);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "插入热点作品失败");
}
// 修改热点文化作品信息
@PutMapping("/update")
public Result<?> update(@RequestBody HotWork hotWork) {
int res = hotWorkMapper.updateById(hotWork);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改热点文化作品失败");
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<HotWork> all = hotWorkMapper.selectList(null);
for (HotWork hotWork : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("热点文化作品名称", hotWork.getName());
row.put("作品类型", hotWork.getCategory());
row.put("作品介绍标题", hotWork.getTitle());
row.put("作品介绍内容", hotWork.getContent());
row.put("作品介绍网址", hotWork.getCiteUrl());
row.put("作品介绍图片url", hotWork.getImgUrl());
row.put("作品报道时间", hotWork.getPostTime());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("热点文化作品介绍信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row = new LinkedHashMap<>();
row.put("热点文化作品名称", "");
row.put("作品类型", "");
row.put("作品介绍标题", "");
row.put("作品介绍内容", "");
row.put("作品介绍网址", "");
row.put("作品介绍图片url", "");
row.put("作品报道时间", "");
list.add(row);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("热点文化作品介绍信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param file Excel
* @return
* @throws IOException
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException, ParseException {
InputStream inputStream = file.getInputStream();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 获取excel表中的每一行数据
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<HotWork> saveList = new ArrayList<>();
for (List<Object> row : lists) { // 将数据保存到列表中
HotWork hotWork = new HotWork();
hotWork.setName(row.get(0).toString());
hotWork.setCategory(row.get(1).toString());
hotWork.setTitle(row.get(2).toString());
hotWork.setContent(row.get(3).toString());
hotWork.setCiteUrl(row.get(4).toString());
hotWork.setImgUrl(row.get(5).toString());
hotWork.setPostTime(sdf.parse(row.get(6).toString()));
saveList.add(hotWork);
}
for (HotWork hotWork : saveList) {
hotWorkMapper.insert(hotWork); // 插入数据
}
return Result.success();
}
}

@ -0,0 +1,153 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.MonitorRequest;
import com.example.demo.entity.MonitorWork;
import com.example.demo.mapper.MonitorRequestMapper;
import com.example.demo.mapper.MonitorWorkMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
// 监测请求信息
@RequestMapping("/api/monitor-request")
@RestController
public class MonitorRequestController {
@Autowired
private MonitorRequestMapper monitorRequestMapper;
@Autowired
private MonitorWorkMapper monitorWorkMapper;
// 查询所有的监测请求信息
@GetMapping("/all")
public Result<?> findAll() {
List<MonitorRequest> monitorRequests = monitorRequestMapper.selectAll("", "");
return Result.success(monitorRequests);
}
// 根据监测请求id查询监测请求信息
@GetMapping("/id/{id}")
public Result<?> findById(@PathVariable Long id) {
MonitorRequest monitorRequest = monitorRequestMapper.selectById(id);
return Result.success(monitorRequest);
}
// 根据用户id查询监测请求信息
@GetMapping("/byUserId")
public Result<?> findByUserId(@RequestParam(required = true) Integer userId,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize
) {
Page<MonitorRequest> byUserId = monitorRequestMapper
.selectByUserId(new Page<>(pageNum, pageSize), userId);
return Result.success(byUserId);
}
// 分页 搜索查询 搜索关键词:用户名、作品名
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(required = false, defaultValue = "") String searchUsername,
@RequestParam(required = false, defaultValue = "") String searchWorkName,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
Page<MonitorRequest> requestPage = monitorRequestMapper
.findPage(new Page<>(pageNum, pageSize), searchUsername, searchWorkName);
return Result.success(requestPage);
}
// 根据id删除指定监测请求
@DeleteMapping("/delete/{id}")
public Result<?> deleteById(@PathVariable Long id) {
int res = monitorRequestMapper.deleteById(id);
if (res > 0) {
Result.success();
}
return Result.error("-1", "该监测请求已经被删除了");
}
// 新增监测请求 首先把作品插入监测作品表(如果该作品原来不在监测作品表中)再插入监测请求表
@PostMapping("/add")
public Result<?> add(@RequestBody MonitorRequest monitorRequest) {
MonitorWork monitorWork = monitorRequest.getMonitorWork();
String workName = monitorWork.getName();
LambdaQueryWrapper<MonitorWork> wrapper = Wrappers.<MonitorWork>lambdaQuery()
.like(MonitorWork::getName, workName);
List<MonitorWork> monitorWorks = monitorWorkMapper.selectList(wrapper);
if (monitorWorks.size() == 0) { // 请求的监测作品不在监测作品表中,需要把该监测作品先插入监测作品表
monitorWork.setCreateTime(new Date()); // 监测作品的检测开始时间先设置为当前时间
monitorWorkMapper.insert(monitorWork); // 插入监测作品
MonitorWork newWork = monitorWorkMapper.selectList(wrapper).get(0);
monitorRequest.setWorkId(newWork.getId());
} else {
monitorRequest.setWorkId(monitorWorks.get(0).getId());
}
monitorRequest.setCreateTime(new Date()); // 请求时间设置为当前时间
int res = monitorRequestMapper.insert(monitorRequest);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "新增监测请求失败");
}
// 修改监测请求信息
@PutMapping("/update")
public Result<?> update(@RequestBody MonitorRequest monitorRequest) {
int res = monitorRequestMapper.updateById(monitorRequest);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改监测请求失败");
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<MonitorRequest> all = monitorRequestMapper.selectAll("", "");
for (MonitorRequest monitorRequest : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("监测请求ID", monitorRequest.getId());
row.put("用户ID", monitorRequest.getUserId());
row.put("用户名", monitorRequest.getUser().getUsername());
row.put("监测作品ID", monitorRequest.getWorkId());
row.put("监测作品名", monitorRequest.getMonitorWork().getName());
row.put("监测请求的创建时间", monitorRequest.getCreateTime());
row.put("是否通过审核", monitorRequest.getChecked());
row.put("是否完成监测", monitorRequest.getComplete());
row.put("请求作品监测的完成时间", monitorRequest.getMonitorWork().getEndTime());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("文化作品的监测请求信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
}

@ -0,0 +1,203 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.dto.CommentPlatformDto;
import com.example.demo.entity.MonitorWork;
import com.example.demo.mapper.MonitorWorkMapper;
import com.example.demo.mapper.RawCommentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
// 监测文化作品信息
@RequestMapping("/api/monitor-work")
@RestController
public class MonitorWorkController {
@Autowired
private MonitorWorkMapper monitorWorkMapper;
@Autowired
private RawCommentMapper rawCommentMapper;
// 查询所有的监测作品信息
@GetMapping("/all")
public Result<?> findAll() {
List<MonitorWork> monitorWorks = monitorWorkMapper.selectList(null);
return Result.success(monitorWorks);
}
// 根据作品id查询指定的文化作品
@GetMapping("/id/{id}")
public Result<?> findById(@PathVariable Long id) {
MonitorWork monitorWork = monitorWorkMapper.selectById(id);
return Result.success(monitorWork);
}
// 分页 搜索查询
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(required = false, defaultValue = "") String searchName,
@RequestParam(required = false, defaultValue = "") String searchCategory,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
LambdaQueryWrapper<MonitorWork> queryWrapper = Wrappers.<MonitorWork>lambdaQuery()
.like(MonitorWork::getName, searchName)
.like(MonitorWork::getCategory, searchCategory)
.orderByAsc(MonitorWork::getId);
return Result.success(monitorWorkMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper));
}
// 根据id删除指定监测作品
@DeleteMapping("/delete/{id}")
public Result<?> deleteById(@PathVariable Long id) {
int res = monitorWorkMapper.deleteById(id);
if (res > 0) {
Result.success();
}
return Result.error("-1", "该监测作品已经被删除了");
}
// 新增监测文化作品
@PostMapping("/add")
public Result<?> add(@RequestBody MonitorWork monitorWork) {
monitorWork.setCreateTime(new Date());
int res = monitorWorkMapper.insert(monitorWork);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "插入监测作品失败");
}
// 修改热点文化作品信息
@PutMapping("/update")
public Result<?> update(@RequestBody MonitorWork monitorWork) {
int res = monitorWorkMapper.updateById(monitorWork);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改监测文化作品失败");
}
// 通过用户的id获取用户申请的监测作品信息
@GetMapping("/byUserId")
public Result<?> findAllByUserId(@RequestParam(required = false, defaultValue = "-1") Integer userId) {
List<MonitorWork> monitorWorks = monitorWorkMapper.selectByUserId(userId);
return Result.success(monitorWorks);
}
// 获取指定文化作品的平台来源统计信息
@GetMapping("/countPlatform")
public Result<?> countPlatform(@RequestParam Integer workId) {
List<CommentPlatformDto> platformDtos = rawCommentMapper.countPlatformByWorkId(workId);
return Result.success(platformDtos);
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<MonitorWork> all = monitorWorkMapper.selectList(null);
for (MonitorWork monitorWork : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("热点文化作品名称", monitorWork.getName());
row.put("作品类型", monitorWork.getName());
row.put("作品监测创建时间", monitorWork.getCreateTime());
row.put("作品监测完成时间", monitorWork.getEndTime());
row.put("是否完成评论数据爬取", monitorWork.getCrawlOk());
row.put("是否完成情感分析", monitorWork.getSentimentOk());
row.put("是否完成情感极性分析", monitorWork.getPolarityOk());
row.put("是否完成词云图分析", monitorWork.getWordCloudOk());
row.put("是否完成语义网络分析", monitorWork.getGramNetOk());
row.put("是否全部完成", monitorWork.getAllDone());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("监测文化作品信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row = new LinkedHashMap<>();
row.put("热点文化作品名称", "");
row.put("作品类型", "");
list.add(row);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("监测文化作品信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param file Excel
* @return
* @throws IOException
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException {
InputStream inputStream = file.getInputStream();
// 获取excel表中的每一行数据
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<MonitorWork> saveList = new ArrayList<>();
for (List<Object> row : lists) { // 将数据保存到列表中
MonitorWork monitorWork = new MonitorWork();
monitorWork.setName(row.get(0).toString());
monitorWork.setCategory(row.get(1).toString());
saveList.add(monitorWork);
}
for (MonitorWork monitorWork : saveList) {
monitorWorkMapper.insert(monitorWork); // 插入数据
}
return Result.success();
}
}

@ -0,0 +1,244 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.MonitorWork;
import com.example.demo.entity.PolarityAnalysis;
import com.example.demo.entity.dto.PolarityDto;
import com.example.demo.entity.dto.PolarityStatisticsDto;
import com.example.demo.mapper.MonitorWorkMapper;
import com.example.demo.mapper.PolarityAnalysisMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
// 监测作品的情感极性分析
@RequestMapping("/api/polarity")
@RestController
public class PolarityAnalysisController {
@Autowired
private PolarityAnalysisMapper polarityAnalysisMapper;
@Autowired
private MonitorWorkMapper monitorWorkMapper;
// 查询所有的情感极性分析结果
@GetMapping("/all")
public Result<?> findAll() {
List<PolarityAnalysis> polarityAnalyses = polarityAnalysisMapper.findAll();
return Result.success(polarityAnalyses);
}
@GetMapping("/id/{id}")
public Result<?> findById(@PathVariable Long id) {
PolarityAnalysis polarityAnalysis = polarityAnalysisMapper.selectById(id);
return Result.success(polarityAnalysis);
}
// 分页 搜索查询
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(required = false, defaultValue = "") String searchWorkName,
@RequestParam(required = false, defaultValue = "") String searchCountry,
@RequestParam(required = false, defaultValue = "") String searchPlatform,
@RequestParam(required = false, defaultValue = "") String searchTime,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
Page<PolarityAnalysis> mapperPage = polarityAnalysisMapper
.findPage(new Page<>(pageNum, pageSize),
searchWorkName,
searchCountry,
searchPlatform,
searchTime);
return Result.success(mapperPage);
}
// 统计不同情感极性的评论数
@GetMapping("/countDaily")
public Result<?> countDaily(@RequestParam Integer workId,
@RequestParam String country,
@RequestParam String postTime
) {
QueryWrapper<PolarityAnalysis> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("workId", workId);
queryWrapper.eq("country", country);
queryWrapper.eq("time", postTime);
List<PolarityAnalysis> polarityAnalyses
= polarityAnalysisMapper.selectList(queryWrapper);
PolarityDto polarityDto = new PolarityDto();
for (PolarityAnalysis polarityAnalysis: polarityAnalyses) {
polarityDto.positiveAdd(polarityAnalysis.getPositive());
polarityDto.negativeAdd(polarityAnalysis.getNegative());
polarityDto.neutralityAdd(polarityAnalysis.getNeutrality());
}
return Result.success(polarityDto);
}
// 统计不同情感极性的评论数
@GetMapping("/countDayInterval")
public Result<?> countDayInterval(@RequestParam Integer workId,
@RequestParam String country,
@RequestParam String startTime,
@RequestParam Integer dayInterval
) {
MonitorWork monitorWork = monitorWorkMapper.selectById(workId);
String workName = monitorWork.getName();
PolarityStatisticsDto polarityStatisticsDto = new PolarityStatisticsDto();
List<PolarityDto> polarityAnalyses
= polarityAnalysisMapper.selectDayInterval(workId, country, startTime, dayInterval);
polarityStatisticsDto.setWorkId(workId);
polarityStatisticsDto.setWorkName(workName);
polarityStatisticsDto.setCountry(country);
polarityStatisticsDto.setStatisticsInfo(polarityAnalyses);
return Result.success(polarityStatisticsDto);
}
// 根据id删除指定情感极性分析结果
@DeleteMapping("/delete/{id}")
public Result<?> deleteById(@PathVariable Long id) {
int res = polarityAnalysisMapper.deleteById(id);
if (res > 0) {
Result.success();
}
return Result.error("-1", "该情感极性分析结果已经被删除了");
}
// 新增情感极性分析
@PostMapping("/add")
public Result<?> add(@RequestBody PolarityAnalysis polarityAnalysis) {
int res = polarityAnalysisMapper.insert(polarityAnalysis);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "插入情感极性分析结果失败");
}
// 修改情感极性分析结果
@PutMapping("/update")
public Result<?> update(@RequestBody PolarityAnalysis polarityAnalysis) {
int res = polarityAnalysisMapper.updateById(polarityAnalysis);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改情感极性分析结果失败");
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<PolarityAnalysis> all = polarityAnalysisMapper.findAll();
for (PolarityAnalysis polarityAnalysis : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("情感极性分析ID", polarityAnalysis.getId());
row.put("所属作品ID", polarityAnalysis.getWorkId());
row.put("所属作品名", polarityAnalysis.getMonitorWork().getName());
row.put("所属作品类型", polarityAnalysis.getMonitorWork().getCategory());
row.put("所属国家", polarityAnalysis.getCountry());
row.put("所分析评论的发布时间", polarityAnalysis.getTime());
row.put("所属平台", polarityAnalysis.getPlatform());
row.put("积极的评论数", polarityAnalysis.getPositive());
row.put("消极的评论数", polarityAnalysis.getNegative());
row.put("中立的评论数", polarityAnalysis.getNeutrality());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("情感极性分析信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row = new LinkedHashMap<>();
row.put("所属作品ID", "");
row.put("所属国家", "");
row.put("所分析评论的发布时间", "");
row.put("所属平台", "");
row.put("积极的评论数", "");
row.put("消极的评论数", "");
row.put("中立的评论数", "");
list.add(row);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("情感极性分析信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param file Excel
* @return
* @throws IOException
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException, ParseException {
InputStream inputStream = file.getInputStream();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 获取excel表中的每一行数据
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<PolarityAnalysis> saveList = new ArrayList<>();
for (List<Object> row : lists) { // 将数据保存到列表中
PolarityAnalysis polarityAnalysis = new PolarityAnalysis();
polarityAnalysis.setWorkId(Integer.valueOf(row.get(0).toString()));
polarityAnalysis.setCountry(row.get(1).toString());
polarityAnalysis.setTime(sdf.parse(row.get(2).toString()));
polarityAnalysis.setPlatform(row.get(3).toString());
polarityAnalysis.setPositive(Integer.valueOf(row.get(4).toString()));
polarityAnalysis.setNegative(Integer.valueOf(row.get(5).toString()));
polarityAnalysis.setNeutrality(Integer.valueOf(row.get(6).toString()));
saveList.add(polarityAnalysis);
}
for (PolarityAnalysis polarityAnalysis : saveList) {
polarityAnalysisMapper.insert(polarityAnalysis); // 插入数据
}
return Result.success();
}
}

@ -0,0 +1,216 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.RawComment;
import com.example.demo.mapper.RawCommentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
// 监测文化作品信息
@RequestMapping("/api/comment")
@RestController
public class RawCommentController {
@Autowired
private RawCommentMapper rawCommentMapper;
// 查询所有的评论信息
@GetMapping("/all")
public Result<?> findAll() {
List<RawComment> rawComments = rawCommentMapper.selectList(null);
return Result.success(rawComments);
}
// 根据评论id查询评论信息
@GetMapping("/id/{id}")
public Result<?> findById(@PathVariable Long id) {
RawComment rawComment = rawCommentMapper.selectById(id);
return Result.success(rawComment);
}
// 查询所有的国家信息列表
@GetMapping("/countries")
public Result<?> findAllCountry() {
List<String> list = rawCommentMapper.selectAllCountry();
return Result.success(list);
}
// 查询所有的国家信息列表
@GetMapping("/platforms")
public Result<?> findAllPlatform() {
List<String> list = rawCommentMapper.selectAllPlatform();
return Result.success(list);
}
// 带搜索关键词的分页查询评论信息
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(required = false, defaultValue = "-1") Integer workId,
@RequestParam(required = false, defaultValue = "") String searchContent,
@RequestParam(required = false, defaultValue = "") String searchCountry,
@RequestParam(required = false, defaultValue = "") String searchPlatform,
@RequestParam(required = false, defaultValue = "") String searchTime,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) throws ParseException {
LambdaQueryWrapper<RawComment> queryWrapper = Wrappers.<RawComment>lambdaQuery()
.like(RawComment::getContent, searchContent)
.like(RawComment::getCountry, searchCountry)
.like(RawComment::getPlatform, searchPlatform)
.orderByDesc(RawComment::getLikes);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
if (StringUtils.isNotBlank(searchTime)) {
queryWrapper.eq(RawComment::getPostTime, sdf.parse(searchTime));
}
if (workId != -1) queryWrapper.eq(RawComment::getWorkId, workId);
return Result.success(rawCommentMapper.selectPage(new Page<>(pageNum, pageSize), queryWrapper));
}
// 根据id删除指定评论
@DeleteMapping("/delete/{id}")
public Result<?> deleteById(@PathVariable Long id) {
int res = rawCommentMapper.deleteById(id);
if (res > 0) {
Result.success();
}
return Result.error("-1", "该评论已经被删除了");
}
// 新增评论信息
@PostMapping("/add")
public Result<?> add(@RequestBody RawComment rawComment) {
int res = rawCommentMapper.insert(rawComment);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "插入评论失败");
}
// 修改热点文化作品信息
@PutMapping("/update")
public Result<?> update(@RequestBody RawComment rawComment) {
int res = rawCommentMapper.updateById(rawComment);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改评论失败");
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<RawComment> all = rawCommentMapper.selectList(null);
for (RawComment rawComment : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("评论内容", rawComment.getContent());
row.put("评论点赞数", rawComment.getLikes());
row.put("评论的情感倾向", rawComment.getSentiment());
row.put("评论所属国家", rawComment.getCountry());
row.put("评论所属平台", rawComment.getPlatform());
row.put("评论发布的时间", rawComment.getPostTime());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("作品相关评论信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row = new LinkedHashMap<>();
row.put("评论内容", "");
row.put("评论的作品ID", "");
row.put("评论点赞数", "");
row.put("评论的情感倾向", "");
row.put("评论所属国家", "");
row.put("评论所属平台", "");
row.put("评论发布的时间", "");
list.add(row);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("作品相关评论信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param file Excel
* @return
* @throws IOException
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException, ParseException {
InputStream inputStream = file.getInputStream();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 获取excel表中的每一行数据
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<RawComment> saveList = new ArrayList<>();
for (List<Object> row : lists) { // 将数据保存到列表中
RawComment rawComment = new RawComment();
rawComment.setContent(row.get(0).toString());
rawComment.setLikes(Integer.valueOf(row.get(1).toString()));
rawComment.setWorkId(Integer.valueOf(row.get(2).toString()));
rawComment.setSentiment(row.get(3).toString());
rawComment.setCountry(row.get(4).toString());
rawComment.setPlatform(row.get(5).toString());
rawComment.setPostTime(sdf.parse(row.get(6).toString()));
saveList.add(rawComment);
}
for (RawComment rawComment : saveList) {
rawCommentMapper.insert(rawComment); // 插入数据
}
return Result.success();
}
}

@ -0,0 +1,233 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.SentimentAnalysis;
import com.example.demo.entity.dto.SentimentDto;
import com.example.demo.mapper.SentimentAnalysisMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
// 监测作品的细腻情感分析
@RequestMapping("/api/sentiment")
@RestController
public class SentimentAnalysisController {
@Autowired
private SentimentAnalysisMapper sentimentAnalysisMapper;
// 查询所有的情感分析结果
@GetMapping("/all")
public Result<?> findAll() {
List<SentimentAnalysis> sentimentAnalyses = sentimentAnalysisMapper.findAll();
return Result.success(sentimentAnalyses);
}
// 根据情感分析id查询情感分析结果
@GetMapping("/id/{id}")
public Result<?> findById(@PathVariable Long id) {
SentimentAnalysis sentimentAnalysis = sentimentAnalysisMapper.selectById(id);
return Result.success(sentimentAnalysis);
}
// 分页 搜索查询
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(required = false, defaultValue = "") String searchWorkName,
@RequestParam(required = false, defaultValue = "") String searchCountry,
@RequestParam(required = false, defaultValue = "") String searchPlatform,
@RequestParam(required = false, defaultValue = "") String searchTime,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
Page<SentimentAnalysis> mapperPage = sentimentAnalysisMapper
.findPage(new Page<>(pageNum, pageSize),
searchWorkName,
searchCountry,
searchPlatform,
searchTime);
return Result.success(mapperPage);
}
// 统计不同情感倾向的评论数
@GetMapping("/countDaily")
public Result<?> countDaily(@RequestParam Integer workId,
@RequestParam String country,
@RequestParam String postTime
) {
QueryWrapper<SentimentAnalysis> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("workId", workId);
queryWrapper.eq("country", country);
queryWrapper.eq("time", postTime);
List<SentimentAnalysis> sentimentAnalyses
= sentimentAnalysisMapper.selectList(queryWrapper);
SentimentDto sentimentDto = new SentimentDto();
for (SentimentAnalysis sentimentAnalysis: sentimentAnalyses) {
sentimentDto.happyAdd(sentimentAnalysis.getHappy());
sentimentDto.amazedAdd(sentimentAnalysis.getAmazed());
sentimentDto.neutralityAdd(sentimentAnalysis.getNeutrality());
sentimentDto.hateAdd(sentimentAnalysis.getHate());
sentimentDto.angryAdd(sentimentAnalysis.getAngry());
sentimentDto.fearAdd(sentimentAnalysis.getFear());
}
return Result.success(sentimentDto);
}
// 根据id删除指定情感分析结果
@DeleteMapping("/delete/{id}")
public Result<?> deleteById(@PathVariable Long id) {
int res = sentimentAnalysisMapper.deleteById(id);
if (res > 0) {
Result.success();
}
return Result.error("-1", "该情感分析结果已经被删除了");
}
// 新增情感分析结果
@PostMapping("/add")
public Result<?> add(@RequestBody SentimentAnalysis sentimentAnalysis) {
int res = sentimentAnalysisMapper.insert(sentimentAnalysis);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "插入情感分析结果失败");
}
// 修改情感分析结果
@PutMapping("/update")
public Result<?> update(@RequestBody SentimentAnalysis sentimentAnalysis) {
int res = sentimentAnalysisMapper.updateById(sentimentAnalysis);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改情感分析结果失败");
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<SentimentAnalysis> all = sentimentAnalysisMapper.findAll();
for (SentimentAnalysis sentimentAnalysis : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("情感分析ID", sentimentAnalysis.getId());
row.put("所属作品ID", sentimentAnalysis.getWorkId());
row.put("所属作品名", sentimentAnalysis.getMonitorWork().getName());
row.put("所属作品类型", sentimentAnalysis.getMonitorWork().getCategory());
row.put("所属国家", sentimentAnalysis.getCountry());
row.put("所分析评论的发布时间", sentimentAnalysis.getTime());
row.put("所属平台", sentimentAnalysis.getPlatform());
row.put("开心的评论数", sentimentAnalysis.getHappy());
row.put("惊讶的评论数", sentimentAnalysis.getAmazed());
row.put("中立的评论数", sentimentAnalysis.getNeutrality());
row.put("厌恶的评论数", sentimentAnalysis.getHate());
row.put("愤怒的评论数", sentimentAnalysis.getAngry());
row.put("恐惧的评论数", sentimentAnalysis.getFear());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("细腻情感分析信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row = new LinkedHashMap<>();
row.put("所属作品ID", "");
row.put("所属国家", "");
row.put("所分析评论的发布时间", "");
row.put("所属平台", "");
row.put("开心的评论数", "");
row.put("惊讶的评论数", "");
row.put("中立的评论数", "");
row.put("厌恶的评论数", "");
row.put("愤怒的评论数", "");
row.put("恐惧的评论数", "");
list.add(row);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("细腻情感分析信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param file Excel
* @return
* @throws IOException
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException, ParseException {
InputStream inputStream = file.getInputStream();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 获取excel表中的每一行数据
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<SentimentAnalysis> saveList = new ArrayList<>();
for (List<Object> row : lists) { // 将数据保存到列表中
SentimentAnalysis sentimentAnalysis = new SentimentAnalysis();
sentimentAnalysis.setWorkId(Integer.valueOf(row.get(0).toString()));
sentimentAnalysis.setCountry(row.get(1).toString());
sentimentAnalysis.setTime(sdf.parse(row.get(2).toString()));
sentimentAnalysis.setPlatform(row.get(3).toString());
sentimentAnalysis.setHappy(Integer.valueOf(row.get(4).toString()));
sentimentAnalysis.setAmazed(Integer.valueOf(row.get(5).toString()));
sentimentAnalysis.setNeutrality(Integer.valueOf(row.get(6).toString()));
sentimentAnalysis.setHate(Integer.valueOf(row.get(7).toString()));
sentimentAnalysis.setAngry(Integer.valueOf(row.get(8).toString()));
sentimentAnalysis.setFear(Integer.valueOf(row.get(9).toString()));
saveList.add(sentimentAnalysis);
}
for (SentimentAnalysis sentimentAnalysis : saveList) {
sentimentAnalysisMapper.insert(sentimentAnalysis); // 插入数据
}
return Result.success();
}
}

@ -0,0 +1,305 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.*;
import com.example.demo.enums.PwdEnum;
import com.example.demo.mapper.UserMapper;
import com.example.demo.utils.AliOssUtil;
import com.example.demo.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
@RestController
@RequestMapping("/api/user")
public class UserController extends BaseController {
@Resource
UserMapper userMapper;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder; //注入bcryct加密
@PostMapping("/login")
public Result<?> login(@RequestBody User userParam) {
User res = userMapper.selectByUsername(userParam.getUsername());
/*QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", userParam.getUsername());
queryWrapper.eq("password", userPwd.getPassword());
User res = userMapper.selectOne(queryWrapper);*/
if (res == null) {
return Result.error("-1", "用户不存在!");
}
// 判断密码是否正确
if (!bCryptPasswordEncoder.matches(userParam.getPassword(), res.getPassword())) {
return Result.error("-1", "密码错误!");
}
// 生成token
String token = TokenUtils.genToken(res);
res.setToken(token);
return Result.success(res);
}
@PostMapping("/register")
public Result<?> register(@RequestBody User user) {
User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, user.getUsername()));
if (res != null) {
return Result.error("-1", "用户名重复");
}
String password = user.getPassword();
if (password == null || "".equals(password.trim())) { // 用户输入的密码为空或者空字符串,设置为默认的密码
user.setPassword("123456");
}
String name = user.getName();
if (name == null || "".equals(name.trim())) name = "用户" + IdWorker.getId();
User userInfo = User.builder()
.username(user.getUsername())
.password(bCryptPasswordEncoder.encode(user.getPassword())) // 加密
.name(name)
.workUnit(user.getWorkUnit())
.email(user.getEmail())
.phone(user.getPhone())
.build();
userMapper.insert(userInfo);
/*UserRole userRole = UserRole.builder()
.userId(userInfo.getId())
.roleId(RoleEnum.USER.getRoleId())
.build();
userRoleMapper.insert(userRole);*/
return Result.success();
}
// 更新用户的信息 根据id
@PutMapping("/update")
public Result<?> update(@RequestBody User user) {
if (user.getPassword() == null) {
user.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
}
userMapper.updateById(user);
return Result.success();
}
// 删除用户
@DeleteMapping("/delete/{ids}")
public Result<?> delete(@PathVariable Integer[] ids) {
int res = userMapper.deleteBatchIds(Arrays.asList(ids));
if (res > 0) {
return Result.success();
}
return Result.error("-1", "删除失败!");
}
// 更改用户密码
@PutMapping("/pass")
public Result<?> pass(@RequestBody Map<String, Object> map) {
User loginUser = TokenUtils.getLoginUser();
if (loginUser == null) {
return Result.error("-1", "未找到用户");
}
String password = loginUser.getPassword(); // 获取用户的密码
if (!TokenUtils.matchPassword(map.get("oldPwd").toString(), password)) {
return Result.error("-1", "修改密码失败,旧密码错误!");
}
if (TokenUtils.matchPassword(map.get("newPwd").toString(), password)) {
return Result.error("-1", "新密码不能与旧密码相同!");
}
map.put("newPwd", (bCryptPasswordEncoder.encode(map.get("newPwd").toString())));
map.put("id", loginUser.getId());
userMapper.updatePass(map);
return Result.success();
}
// 重置用户的密码
@PutMapping("/resetPwd")
public Result<?> resetPwd(@RequestParam Integer userId) {
User user = userMapper.selectById(userId);
if (user == null) {
return Result.error("-1", "未找到用户");
}
// 重置密码
user.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
userMapper.updateById(user);
return Result.success();
}
// 上传管理员的头像接口
@PostMapping("/uploadAvatar")
public Result<?> uploadAvatar(MultipartFile file) {
if (!file.isEmpty()) {
User loginUser = TokenUtils.getLoginUser();
if (loginUser == null) {
return Result.error("401", "用户未登录");
}
String avatar = AliOssUtil.upload("images/", file); // 上传文件到阿里云OSS存储服务器
loginUser.setAvatar(avatar);
int res = userMapper.updateById(loginUser);
if (res > 0) {
return Result.success(avatar);
}
return Result.error("-1", "上传用户头像失败");
}
return Result.error("-1", "上传的文件为空");
}
@GetMapping("/id/{id}")
public Result<?> getById(@PathVariable Long id) {
return Result.success(userMapper.selectById(id));
}
@GetMapping("/all")
public Result<?> findAll() {
return Result.success(userMapper.selectList(null));
}
/**
*
*
* @return
*/
@GetMapping("/countWorkUnit")
public Result<?> count() {
// User user = getUser(); // 当前登录的用户信息
return Result.success(userMapper.countWorkUnit());
}
/**
*
*
* @param pageNum
* @param pageSize
* @param searchUsername
* @param searchName
* @return
*/
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(defaultValue = "") String searchUsername,
@RequestParam(defaultValue = "") String searchName) {
Page<User> userPage = userMapper.findPage(new Page<>(pageNum, pageSize), searchUsername, searchName);
return Result.success(userPage);
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@RequestMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<User> all = userMapper.selectList(null);
for (User user : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("用户名", user.getUsername());
row.put("昵称", user.getName());
row.put("工作单位", user.getWorkUnit());
row.put("邮箱", user.getEmail());
row.put("电话号码", user.getPhone());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("用户信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@RequestMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row = new LinkedHashMap<>();
row.put("用户名", "");
row.put("昵称", "");
row.put("工作单位", "");
row.put("邮箱", "");
row.put("电话号码", "");
list.add(row);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("用户信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param file Excel
* @return
* @throws IOException
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException {
InputStream inputStream = file.getInputStream();
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<User> saveList = new ArrayList<>();
for (List<Object> row : lists) {
User user = new User();
user.setUsername(row.get(0).toString());
user.setName(row.get(1).toString());
user.setWorkUnit(row.get(2).toString());
user.setEmail(row.get(3).toString());
user.setPhone(row.get(4).toString());
// 设置成默认的密码
user.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
saveList.add(user);
}
for (User user : saveList) {
userMapper.insert(user);
}
return Result.success();
}
}

@ -0,0 +1,259 @@
package com.example.demo.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.SentimentAnalysis;
import com.example.demo.entity.WordFreqAnalysis;
import com.example.demo.entity.dto.WordFreqDto;
import com.example.demo.mapper.MonitorWorkMapper;
import com.example.demo.mapper.WordFreqAnalysisMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
// 关于监测作品的评论的词频分析
@RequestMapping("/api/word-freq")
@RestController
public class WordFreqAnalysisController {
@Autowired
private WordFreqAnalysisMapper wordFreqAnalysisMapper;
@Autowired
private MonitorWorkMapper monitorWorkMapper;
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 查询所有的词频统计结果
@GetMapping("/all")
public Result<?> findAll() {
List<WordFreqAnalysis> wordFreqAnalyses = wordFreqAnalysisMapper.selectList(null);
return Result.success(wordFreqAnalyses);
}
// 根据词频统计id查询词频统计结果
@GetMapping("/id/{id}")
public Result<?> findById(@PathVariable Long id) {
WordFreqAnalysis wordFreqAnalysis = wordFreqAnalysisMapper.selectById(id);
return Result.success(wordFreqAnalysis);
}
// 分页 搜索查询
@GetMapping("/byPage")
public Result<?> findPage(@RequestParam(required = false, defaultValue = "") String searchWorkName,
@RequestParam(required = false, defaultValue = "") String searchCountry,
@RequestParam(required = false, defaultValue = "") String searchPlatform,
@RequestParam(required = false, defaultValue = "") String searchTime,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
Page<WordFreqAnalysis> mapperPage = wordFreqAnalysisMapper
.findPage(new Page<>(pageNum, pageSize),
searchWorkName,
searchCountry,
searchPlatform,
searchTime);
return Result.success(mapperPage);
}
// 查询指定作品的词频统计结果
@GetMapping("/query-res")
public Result<?> getWordFreq(@RequestParam Integer searchWorkId,
@RequestParam(required = false, defaultValue = "") String searchTime,
@RequestParam(required = false, defaultValue = "") String searchCountry,
@RequestParam(required = false, defaultValue = "") String searchPlatform) throws ParseException {
LambdaQueryWrapper<WordFreqAnalysis> query = Wrappers.<WordFreqAnalysis>lambdaQuery();
query.eq(WordFreqAnalysis::getWorkId, searchWorkId);
WordFreqDto.WordFreqDtoBuilder builder = WordFreqDto.builder();
if (!"".equals(searchTime)) {
query.eq(WordFreqAnalysis::getTime, searchTime);
builder.time(sdf.parse(searchTime));
}
if (!"".equals(searchCountry)) {
query.eq(WordFreqAnalysis::getCountry, searchCountry);
builder.country(searchCountry);
}
if (!"".equals(searchPlatform)) {
query.eq(WordFreqAnalysis::getPlatform, searchPlatform);
builder.platform(searchPlatform);
}
List<WordFreqAnalysis> wordFreqAnalyses = wordFreqAnalysisMapper.selectList(query);
WordFreqDto freqDto = builder.workName(monitorWorkMapper.findWorkName(searchWorkId)).build();
List<WordFreqDto.WordInfo> list = new ArrayList<>();
List<String> words = new ArrayList<>();
for (WordFreqAnalysis wordFreqAnalysis: wordFreqAnalyses) {
String[] keywords = wordFreqAnalysis.getKeywords().split("\\s+");
String[] polarity = wordFreqAnalysis.getPolarity().split("\\s+");
String[] frequency = wordFreqAnalysis.getFrequency().split("\\s+");
System.out.println(Arrays.toString(keywords));
System.out.println(Arrays.toString(polarity));
System.out.println(Arrays.toString(frequency));
for (int i = 0; i < keywords.length; i++) {
if (!words.contains(keywords[i])) { // 保证关键词不重复
words.add(keywords[i]);
WordFreqDto.WordInfo wordInfo = new WordFreqDto.WordInfo(keywords[i], polarity[i],
Integer.valueOf(frequency[i]));
list.add(wordInfo);
} else {
int idx = words.indexOf(keywords[i]);
WordFreqDto.WordInfo info = list.get(idx);
info.countsAdd(Integer.valueOf(frequency[i]));
}
}
}
freqDto.setKeywords(list);
return Result.success(freqDto);
}
// 根据id删除指定词频分析结果
@DeleteMapping("/delete/{id}")
public Result<?> deleteById(@PathVariable Long id) {
int res = wordFreqAnalysisMapper.deleteById(id);
if (res > 0) {
Result.success();
}
return Result.error("-1", "该词频统计结果已经被删除了");
}
// 新增词频分析结果
@PostMapping("/add")
public Result<?> add(@RequestBody WordFreqAnalysis wordFreqAnalysis) {
int res = wordFreqAnalysisMapper.insert(wordFreqAnalysis);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "插入词频统计结果失败");
}
// 修改词频统计结果
@PutMapping("/update")
public Result<?> update(@RequestBody WordFreqAnalysis wordFreqAnalysis) {
int res = wordFreqAnalysisMapper.updateById(wordFreqAnalysis);
if (res > 0) {
return Result.success();
}
return Result.error("-1", "修改词频统计结果失败");
}
/**
* Excel
*
* @param response
* @throws IOException
*/
@GetMapping("/export")
public void export(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
List<WordFreqAnalysis> all = wordFreqAnalysisMapper.findAll();
for (WordFreqAnalysis wordFreqAnalysis : all) {
Map<String, Object> row = new LinkedHashMap<>();
row.put("词频统计ID", wordFreqAnalysis.getId());
row.put("所属作品ID", wordFreqAnalysis.getWorkId());
row.put("所属作品名", wordFreqAnalysis.getMonitorWork().getName());
row.put("所属作品类型", wordFreqAnalysis.getMonitorWork().getCategory());
row.put("所属国家", wordFreqAnalysis.getCountry());
row.put("所统计评论的发布时间", wordFreqAnalysis.getTime());
row.put("所属平台", wordFreqAnalysis.getPlatform());
row.put("情感极性数组", wordFreqAnalysis.getPolarity());
row.put("高频词数组", wordFreqAnalysis.getKeywords());
row.put("高频词频数数组", wordFreqAnalysis.getFrequency());
list.add(row);
}
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("词频统计信息", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param response
* @throws IOException IO
*/
@GetMapping("/importTemplate")
public void importTemplate(HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = CollUtil.newArrayList();
Map<String, Object> row = new LinkedHashMap<>();
row.put("所属作品ID", "");
row.put("所属国家", "");
row.put("所统计评论的发布时间", "");
row.put("所属平台", "");
row.put("情感极性数组", "");
row.put("高频词数组", "");
row.put("高频词频数数组", "");
list.add(row);
// 2. 写excel
ExcelWriter writer = ExcelUtil.getWriter(true);
writer.write(list, true);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("词频统计信息导入模板", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
writer.close();
IoUtil.close(System.out);
}
/**
* Excel
*
* @param file Excel
* @return
* @throws IOException
*/
@PostMapping("/import")
public Result<?> upload(MultipartFile file) throws IOException, ParseException {
InputStream inputStream = file.getInputStream();
// 获取excel表中的每一行数据
List<List<Object>> lists = ExcelUtil.getReader(inputStream).read(1);
List<WordFreqAnalysis> saveList = new ArrayList<>();
for (List<Object> row : lists) { // 将数据保存到列表中
WordFreqAnalysis wordFreqAnalysis = new WordFreqAnalysis();
wordFreqAnalysis.setWorkId(Integer.valueOf(row.get(0).toString()));
wordFreqAnalysis.setCountry(row.get(1).toString());
wordFreqAnalysis.setTime(sdf.parse(row.get(2).toString()));
wordFreqAnalysis.setPlatform(row.get(3).toString());
wordFreqAnalysis.setPolarity(row.get(4).toString());
wordFreqAnalysis.setKeywords(row.get(5).toString());
wordFreqAnalysis.setFrequency(row.get(6).toString());
saveList.add(wordFreqAnalysis);
}
for (WordFreqAnalysis wordFreqAnalysis : saveList) {
wordFreqAnalysisMapper.insert(wordFreqAnalysis); // 插入数据
}
return Result.success();
}
}

@ -0,0 +1,35 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@TableName("admin")
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Admin {
@TableId(type = IdType.AUTO) // 自动增长
private Integer id; // 编号id
private String username; // 管理员账号
private String password; // 密码
private String name; // 名字
private int level;
private String avatar; // 头像的url
private String phone; // 手机号码
private String email; // 邮箱
@TableField(exist = false)
private String token; // 用户凭证
}

@ -0,0 +1,37 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@TableName("hot_work")
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class HotWork {
@TableId(type = IdType.AUTO)
private Integer id; // 自增主键
private String name; // 热点作品名称
private String category; // 作品类型
private String title; // 作品介绍标题
private String content; // 作品介绍内容
private String citeUrl; // 网址
private String imgUrl; // 图片url
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date postTime; // 发布日期
}

@ -0,0 +1,40 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@TableName("monitor_request")
@Data
@Builder
@AllArgsConstructor // 全参构造
@NoArgsConstructor // 无参构造
public class MonitorRequest {
@TableId(type = IdType.AUTO)
private Integer id; // 自增主键
private Integer userId;
@TableField(exist = false)
private User user; // 用户 不是表的字段
private Integer workId; // 监测文化作品id
@TableField(exist = false)
private MonitorWork monitorWork; // 监测作品, 不在表中
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime; // 监测请求创建的时间
private Short checked = 0; // 请求是否通过审核
private Short complete = 0; // 是否完成
}

@ -0,0 +1,45 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@TableName("monitor_work")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MonitorWork {
@TableId(type = IdType.AUTO)
private Integer id; // 自增主键
private String name; // 文化作品名称
private String category; // 类别
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "UTC")
private Date createTime; // 监测作品的创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date endTime; // 完成作品监测的时间
private Short crawlOk = 0; // 是否完成数据爬取
private Short sentimentOk = 0; // 是否完成情感分析
private Short polarityOk = 0; // 是否完成情感极性分析
private Short wordCloudOk = 0; // 是否完成词云图分析
private Short gramNetOk = 0; // 是否完成语义网络分析
private Short allDone = 0; // 是否完成所有监测工作
}

@ -0,0 +1,35 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@TableName("polarity_analy")
@Data
public class PolarityAnalysis {
@TableId(type = IdType.AUTO)
private Integer id; // 自增主键
private Integer workId; // 作品id
@TableField(exist = false)
private MonitorWork monitorWork; // 监测作品
private String country; // 所属国家
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date time; // 情感极性分析的评论发布时间
private String platform; // 平台
private Integer positive; // 积极的评论数
private Integer negative; // 消极评论数
private Integer neutrality; // 中立的评论数
}

@ -0,0 +1,41 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@TableName("raw_comment")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RawComment {
@TableId(type = IdType.AUTO)
private Integer id; // 自增主键
private String content; // 评论的具体内容
private Integer likes; // 评论的点赞数
private Integer workId; // 监测作品id
@TableField(exist = false)
private MonitorWork monitorWork; // 评论所属的文化作品
private String sentiment; // 评论的情感倾向
private String country; // 评论所属的国家
private String platform; // 评论所属的平台
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date postTime; // 评论发布的时间 精确到天
}

@ -0,0 +1,41 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@TableName("sentiment_analy")
@Data
public class SentimentAnalysis {
@TableId(type = IdType.AUTO)
private Integer id; // 自增主键
private Integer workId; // 作品id
@TableField(exist = false)
private MonitorWork monitorWork; // 监测作品
private String country; // 所属国家
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "UTC")
private Date time; // 情感极性分析的评论发布时间
private String platform; // 平台
private Integer happy; // 开心的评论数
private Integer amazed; // 惊讶的评论数
private Integer neutrality; // 中立的评论数
private Integer hate; // 讨厌的评论数
private Integer angry; // 愤怒的评论数
private Integer fear; // 恐惧的评论数
}

@ -0,0 +1,35 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
@TableName("user")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
private String username;
private String password;
private String name;
private String workUnit;
private String email;
private String phone;
private String avatar; // 用户的头像url
@TableField(exist = false)
private String token;
}

@ -0,0 +1,35 @@
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@TableName("word_freq_analy")
@Data
public class WordFreqAnalysis {
@TableId(type = IdType.AUTO)
private Integer id; // 自增主键
private Integer workId; // 作品id
@TableField(exist = false)
private MonitorWork monitorWork; // 监测作品
private String country; // 所属国家
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date time; // 情感极性分析的评论发布时间
private String platform; // 平台
private String polarity; // 评论中的高频词的情感极性数组
private String keywords; // 评论中出现的高频词数组
private String frequency; // 评论中出现的高频词频数数组
}

@ -0,0 +1,9 @@
package com.example.demo.entity.dto;
import lombok.Data;
@Data
public class CommentPlatformDto {
private String platform;
private Integer count;
}

@ -0,0 +1,8 @@
package com.example.demo.entity.dto;
import lombok.Data;
@Data
public class FileVO {
private String filekey;
}

@ -0,0 +1,28 @@
package com.example.demo.entity.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class PolarityDto {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date time; // 时间
private Integer positive = 0; // 积极评论数
private Integer negative = 0; // 消极评论数
private Integer neutrality = 0; // 中立评论数
public void positiveAdd(Integer offset) {
this.positive += offset;
}
public void negativeAdd(Integer offset) {
this.negative += offset;
}
public void neutralityAdd(Integer offset) {
this.neutrality += offset;
}
}

@ -0,0 +1,18 @@
package com.example.demo.entity.dto;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Data
@Slf4j
public class PolarityStatisticsDto {
private Integer workId; // 作品id
private String workName; // 作品名
private String country; // 统计的评论所属国家
private List<PolarityDto> statisticsInfo;
}

@ -0,0 +1,37 @@
package com.example.demo.entity.dto;
import lombok.Data;
@Data
public class SentimentDto {
private Integer happy = 0; // 开心评论数
private Integer amazed = 0; // 惊讶评论数
private Integer neutrality = 0; // 中立评论数
private Integer hate = 0; // 厌恶评论数
private Integer angry = 0; // 愤怒评论数
private Integer fear = 0; // 恐惧评论数
public void happyAdd(Integer offset) {
this.happy += offset;
}
public void amazedAdd(Integer offset) {
this.amazed += offset;
}
public void neutralityAdd(Integer offset) {
this.neutrality += offset;
}
public void hateAdd(Integer offset) {
this.hate += offset;
}
public void angryAdd(Integer offset) {
this.angry += offset;
}
public void fearAdd(Integer offset) {
this.fear += offset;
}
}

@ -0,0 +1,9 @@
package com.example.demo.entity.dto;
import lombok.Data;
@Data
public class UserWorkUnitDto {
private String workUnit;
private Integer count;
}

@ -0,0 +1,59 @@
package com.example.demo.entity.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
import java.util.List;
@Data
@Slf4j
@Builder
public class WordFreqDto {
private String workName; // 作品名
private String country; // 国家
private String platform; // 平台
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date time; // 时间
private List<WordInfo> keywords;
public static class WordInfo {
private String word;
private String polarity; // 情感极性
private Integer counts; // 词频
public WordInfo() {
}
public WordInfo(String word, String polarity, Integer counts) {
this.word = word;
this.polarity = polarity;
this.counts = counts;
}
public void countsAdd(Integer num) {
this.counts += num;
}
public String getPolarity() {
return polarity;
}
public Integer getCounts() {
return counts;
}
public String getWord() {
return word;
}
}
// private String wordCloudImg; // 词云图
}

@ -0,0 +1,22 @@
package com.example.demo.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author
* @version 1.0
* @Description
* @Date 2021/12/3 22:25
*/
@Getter
@AllArgsConstructor
public enum PwdEnum {
/**
*
*/
PASSWORD("123456");
private final String password;
}

@ -0,0 +1,41 @@
package com.example.demo.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author
* @version 1.0
* @Description
* @Date 2021/12/3 21:40
*/
@Getter
@AllArgsConstructor
public enum RoleEnum {
/**
*
*/
ADMIN(1, "管理员", "admin"),
/**
*
*/
USER(2, "普通用户", "user");
/**
* id
*/
private final Integer roleId;
/**
*
*/
private final String name;
/**
*
*/
private final String label;
}

@ -0,0 +1,19 @@
package com.example.demo.exception;
public class CustomException extends RuntimeException {
private String code;
private String msg;
public CustomException(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
}

@ -0,0 +1,33 @@
package com.example.demo.exception;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.example.demo.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice(basePackages = "com.example.demo.controller")
public class GlobalExceptionHandler {
private static final Log log = LogFactory.get();
//统一异常处理@ExceptionHandler,主要用于Exception
@ExceptionHandler(CustomException.class)
@ResponseBody//返回json串
public Result<?> customer(HttpServletRequest request, CustomException e) {
return Result.error(e.getCode(), e.getMsg());
}
//统一异常处理@ExceptionHandler,主要用于Exception
@ExceptionHandler(Exception.class)
@ResponseBody//返回json串
public Result<?> error(HttpServletRequest request, Exception e) {
log.error("异常信息:", e);
return Result.error("-1", "系统异常");
}
}

@ -0,0 +1,17 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Admin;
import org.apache.ibatis.annotations.Param;
import java.util.Map;
public interface AdminMapper extends BaseMapper<Admin> {
Admin selectByUsername(String username);
Page<Admin> findByPage(Page<Admin> page, @Param("username") String username,
@Param("name") String name);
int updatePass(Map<String, Object> map);
}

@ -0,0 +1,8 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.HotWork;
public interface HotWorkMapper extends BaseMapper<HotWork> {
}

@ -0,0 +1,20 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.MonitorRequest;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface MonitorRequestMapper extends BaseMapper<MonitorRequest> {
Page<MonitorRequest> findPage(Page<MonitorRequest> page,
@Param("username") String username,
@Param("workName") String workName);
List<MonitorRequest> selectAll(@Param("username") String username,
@Param("workName") String workName);
Page<MonitorRequest> selectByUserId(Page<MonitorRequest> page,
Integer userId);
}

@ -0,0 +1,13 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.MonitorWork;
import java.util.List;
public interface MonitorWorkMapper extends BaseMapper<MonitorWork> {
// 根据用户id查询出他所申请的监测作品包括默认用户root所申请的监测作品
List<MonitorWork> selectByUserId(Integer userId);
String findWorkName(Integer workId);
}

@ -0,0 +1,26 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.PolarityAnalysis;
import com.example.demo.entity.dto.PolarityDto;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface PolarityAnalysisMapper extends BaseMapper<PolarityAnalysis> {
Page<PolarityAnalysis> findPage(Page<PolarityAnalysis> page,
@Param("workName") String workName,
@Param("country") String country,
@Param("platform") String platform,
@Param("time") String time
);
List<PolarityAnalysis> findAll();
// 查询一个日期区间的情感记性分析统计信息
List<PolarityDto> selectDayInterval(@Param("workId") Integer workId,
@Param("country") String country,
@Param("startTime") String startTime,
@Param("interval") Integer interval);
}

@ -0,0 +1,17 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.dto.CommentPlatformDto;
import com.example.demo.entity.RawComment;
import java.util.List;
public interface RawCommentMapper extends BaseMapper<RawComment> {
List<CommentPlatformDto> countPlatformByWorkId(Integer workId);
// 查询所有的国家
List<String> selectAllCountry();
// 查询所有的平台
List<String> selectAllPlatform();
}

@ -0,0 +1,19 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.SentimentAnalysis;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface SentimentAnalysisMapper extends BaseMapper<SentimentAnalysis> {
List<SentimentAnalysis> findAll();
Page<SentimentAnalysis> findPage(Page<SentimentAnalysis> page,
@Param("workName") String workName,
@Param("country") String country,
@Param("platform") String platform,
@Param("time") String time
);
}

@ -0,0 +1,25 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.dto.UserWorkUnitDto;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
public interface UserMapper extends BaseMapper<User> {
// 一对多查询
Page<User> findPage(Page<User> page,
@Param("username") String username,
@Param("name") String name);
// 统计各个单位的人数
List<UserWorkUnitDto> countWorkUnit();
// 查询用户名
User selectByUsername(String username);
int updatePass(Map<String, Object> map);
}

@ -0,0 +1,20 @@
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.WordFreqAnalysis;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface WordFreqAnalysisMapper extends BaseMapper<WordFreqAnalysis> {
List<WordFreqAnalysis> findAll();
Page<WordFreqAnalysis> findPage(Page<WordFreqAnalysis> page,
@Param("workName") String workName,
@Param("country") String country,
@Param("platform") String platform,
@Param("time") String time
);
}

@ -0,0 +1,50 @@
package com.example.demo.utils;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.demo.entity.Admin;
import com.example.demo.mapper.AdminMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Slf4j
@Component
public class AdminTokenUtils {
@Autowired
private AdminMapper adminMapper;
private static AdminMapper staticAdminMapper;
@PostConstruct
public void init() {
staticAdminMapper = adminMapper;
}
// 生成token
public static String genToken(Admin admin) {
return JWT.create().withExpiresAt(DateUtil.offsetDay(new Date(), 1)).withAudience(admin.getId().toString())
.sign(Algorithm.HMAC256(admin.getPassword()));
}
// 获取token中的用户信息
public static Admin getAdmin() {
try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String token = request.getHeader("token");
String aud = JWT.decode(token).getAudience().get(0); // 获取用户的id
Integer id = Integer.valueOf(aud);
return staticAdminMapper.selectById(id);
} catch (Exception e) {
log.error("解析token失败", e);
return null;
}
}
}

@ -0,0 +1,156 @@
package com.example.demo.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.druid.util.StringUtils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.DownloadFileRequest;
import com.aliyun.oss.model.GenericRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.example.demo.utils.config.OssConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@Component
@Slf4j // 生成日志变量, 用于记录日志
public class AliOssUtil {
@Autowired
private OssConfigProperties ossConfigProperties;
private static OssConfigProperties configProperties;
@PostConstruct
public void init() {
configProperties = this.ossConfigProperties;
}
private static OSS createClient() {
// 初始化 OssClient
return new OSSClientBuilder().build(configProperties.getEndpoint(), configProperties.getAccessKeyId(),
configProperties.getAccessKeySecret());
}
/**
*
* https://help.aliyun.com/document_detail/84778.html
*
* @param fileDir
* @param file
* @return
*/
public static String upload(String fileDir, MultipartFile file) {
OSS ossClient = createClient();
String url = "";
// 生成文件存储路径
StringBuilder fileKey = new StringBuilder();
if (!fileDir.endsWith("/")) {
fileDir = fileDir.concat("/");
}
String originalFilename = file.getOriginalFilename();
String filename = FilenameUtils.getBaseName(originalFilename);
System.out.println(filename);
int lastIndex = originalFilename.lastIndexOf(".");
String mainName = "";
String ext = "";
if (lastIndex == -1) {
mainName += originalFilename;
ext = getExtension(file);
} else {
mainName = originalFilename.substring(0, lastIndex);
ext = originalFilename.substring(lastIndex + 1);
}
String fileName = mainName + "-" + IdUtil.getSnowflake().nextIdStr() + "." + ext;
fileKey.append(fileDir).append(fileName);
log.info("filekey={}", fileKey);
// 上传文件
try {
ossClient.putObject(configProperties.getBucketName(), fileKey.toString(), file.getInputStream());
Date expiration = DateUtil.offsetMonth(new Date(), 12);
url = ossClient.generatePresignedUrl(configProperties.getBucketName(), fileKey.toString(), expiration).toString();
} catch (IOException e) {
log.error("oss文件上传出错\n", e);
} finally {
ossClient.shutdown();
}
log.info("文件:" + originalFilename + "存入OSS成功。");
return url;
}
/**
*
* https://help.aliyun.com/document_detail/84842.html
*
* @param fileKey
*
*/
public static void delete(String fileKey) {
OSS ossClient = createClient();
try {
GenericRequest genericRequest = new GenericRequest(configProperties.getBucketName()).withKey(fileKey);
ossClient.deleteObject(genericRequest);
log.info("删除文件:" + fileKey + "成功。");
} catch (Exception e) {
log.error("oss删除文件出错\n", e);
} finally {
ossClient.shutdown();
}
}
/**
*
*
* @param file
* @return
*/
public static final String getExtension(MultipartFile file)
{
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension))
{
extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
}
return extension;
}
/**
*
* @param filekey
*/
public static void download(String filekey) {
OSS ossClient = createClient();
DownloadFileRequest dfr = new DownloadFileRequest(configProperties.getBucketName(), filekey);
try {
ossClient.downloadFile(dfr);
} catch (Throwable throwable) {
log.error("oss文件下载失败", throwable);
}
}
public static void showBucketObjects() {
OSS ossClient = createClient();
// 查看Bucket中的Object。详细请参看“SDK手册 > Java-SDK > 管理文件”。
// 链接地址是https://help.aliyun.com/document_detail/oss/sdk/java-sdk/manage_object.html?spm=5176.docoss/sdk/java-sdk/manage_bucket
ObjectListing objectListing = ossClient.listObjects(configProperties.getBucketName());
List<OSSObjectSummary> objectSummary = objectListing.getObjectSummaries();
System.out.println("您有以下Object");
for (OSSObjectSummary object : objectSummary) {
System.out.println("\t" + object.getKey());
}
ossClient.shutdown();
}
}

@ -0,0 +1,88 @@
package com.example.demo.utils;
import com.example.demo.DemoApplication;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
@Component
@Slf4j
public class EmailUtil {
@Autowired
private JavaMailSender javaMailSender;
// 获取yml配置的发送者邮箱
@Value("${spring.mail.username}")
private String mainUserName;
//发送人昵称
@Value("${spring.mail.nickname}")
private String nickname;
private String subject = "文化作品传播效果监测完成通知";
/**
*
*/
public void sendSimpleMail(String target, String content) {
// 构建一个邮件对象
SimpleMailMessage message = new SimpleMailMessage();
// 设置邮件主题
message.setSubject(subject);
// 设置邮件发送者,昵称+<邮箱地址>
message.setFrom(nickname+'<'+mainUserName+'>');
// 设置邮件接收者,可以有多个接收者,多个接受者参数需要数组形式
message.setTo(target);
/*// 设置邮件抄送人,可以有多个抄送人
message.setCc("12****32*qq.com");
// 设置隐秘抄送人,可以有多个
message.setBcc("7******9@qq.com");*/
// 设置邮件发送日期
message.setSentDate(new Date());
// 设置邮件的正文
message.setText(content);
// 发送邮件
javaMailSender.send(message);
}
public void sendHtmlMail(String target, String username) throws IOException, TemplateException {
// 首先配置 FreeMarker 模版位置
Configuration configuration = new Configuration(Configuration.VERSION_2_3_0);
// MailDemoApplication是启动类类名
ClassLoader loader = DemoApplication.class.getClassLoader();
configuration.setClassLoaderForTemplateLoading(loader, "templates");
// 配置模版文件
Template template = configuration.getTemplate("mail.html");
// 渲染模版
StringWriter mail = new StringWriter();
HashMap<String, Object> map = new HashMap<>();
map.put("user", username);
template.process(map, mail);
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper;
try {
messageHelper = new MimeMessageHelper(message, true);
messageHelper.setFrom(nickname+'<'+mainUserName+'>');
messageHelper.setTo(target);
message.setSubject(subject);
messageHelper.setText(mail.toString(), true);
javaMailSender.send(message);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,53 @@
package com.example.demo.utils;
public class MimeTypeUtils {
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_JPG = "image/jpg";
public static final String IMAGE_JPEG = "image/jpeg";
public static final String IMAGE_BMP = "image/bmp";
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
public static final String[] FLASH_EXTENSION = { "swf", "flv" };
public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
"asf", "rm", "rmvb" };
public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf" };
public static String getExtension(String prefix)
{
switch (prefix)
{
case IMAGE_PNG:
return "png";
case IMAGE_JPG:
return "jpg";
case IMAGE_JPEG:
return "jpeg";
case IMAGE_BMP:
return "bmp";
case IMAGE_GIF:
return "gif";
default:
return "";
}
}
}

@ -0,0 +1,120 @@
package com.example.demo.utils;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.demo.entity.Admin;
import com.example.demo.entity.User;
import com.example.demo.enums.RoleEnum;
import com.example.demo.mapper.AdminMapper;
import com.example.demo.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;
@Slf4j
@Component
public class TokenUtils {
@Autowired
private UserMapper userMapper;
@Autowired
private AdminMapper adminMapper;
private static UserMapper staticUserMapper;
private static AdminMapper staticAdminMapper;
@PostConstruct
public void init() {
staticUserMapper = userMapper;
staticAdminMapper = adminMapper;
}
/**
* token
* @param user
* @return token
*/
public static String genToken(User user) {
return JWT.create()
.withExpiresAt(DateUtil.offsetDay(new Date(), 1))
.withAudience(user.getId().toString(), RoleEnum.USER.getLabel())
.sign(Algorithm.HMAC256(user.getPassword()));
}
/**
* token
* @param admin
* @return token
*/
public static String genToken(Admin admin) {
return JWT.create()
.withExpiresAt(DateUtil.offsetDay(new Date(), 1))
.withAudience(admin.getId().toString(), RoleEnum.ADMIN.getLabel())
.sign(Algorithm.HMAC256(admin.getPassword()));
}
/**
* token
* @return
*/
public static User getLoginUser() {
try {
return staticUserMapper.selectById(getId());
} catch (Exception e) {
log.error("解析token失败", e);
return null;
}
}
public static Admin getLoginAdmin() {
try {
return staticAdminMapper.selectById(getId());
} catch (Exception e) {
log.error("解析token失败", e);
return null;
}
}
/**
* token
* @return token
*/
public static String getToken() {
HttpServletRequest request = ((ServletRequestAttributes) Objects
.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
return request.getHeader("token"); // 获取请求头中的token
}
public static Integer getId() {
String token = getToken();
String aud = JWT.decode(token).getAudience().get(0); // 解析token得到用户id
return Integer.valueOf(aud);
}
public static String getUserType() {
String token = getToken();
return JWT.decode(token).getAudience().get(1);
}
/**
*
* @param rawPassword
* @param encodedPassword
* @return
*/
public static boolean matchPassword(String rawPassword, String encodedPassword) {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder.matches(rawPassword, encodedPassword);
}
}

@ -0,0 +1,20 @@
package com.example.demo.utils.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "aliyun.oss")
public class OssConfigProperties {
//地域节点
private String endpoint;
//个人域名
private String domain;
//bucketName
private String bucketName;
private String accessKeyId;
private String accessKeySecret;
}

@ -0,0 +1,7 @@
spring.datasource.url=jdbc:mysql://42.192.220.227:3306/springboot-vue?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
spring.datasource.username=root
spring.datasource.password=
file.ip=42.192.220.227
#spring.jackson.date-format=yyyy-MM-dd

@ -0,0 +1,48 @@
server.port=9090
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/analysis_sys_db?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 时区设置
spring.jackson.time-zone=GMT+8
# 上传文件的最大大小
spring.servlet.multipart.max-file-size=100MB
# 邮件服务配置
spring.mail.host=123.126.97.113
spring.mail.username=hzx1966752024@163.com
# POP3/IMAP/SMTP服务授权码
spring.mail.password=JCLECTJHLVEACWXQ
spring.mail.nickname=hzx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.port=465
# 配置SSL 加密工厂
spring.mail.properties.mail.smtp.socketFactory.class = javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.socketFactory.fallback = false
# 端口号465或994
spring.mail.port=465
# 默认的邮件编码为UTF-8
spring.mail.default-encoding=UTF-8
#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误
spring.mail.properties.mail.debug=false
file.ip=localhost
#spring.jackson.date-format=yyyy-MM-dd
# mybatis-plus \u5F00\u542Fsql\u65E5\u5FD7
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 不开启驼峰转换
mybatis-plus.configuration.map-underscore-to-camel-case=false
# oss配置
aliyun.oss.endpoint=oss-cn-guangzhou.aliyuncs.com
aliyun.oss.bucket-name=hzx-oss
aliyun.oss.access-key-id=LTAI5tQcjbvbjA5JjMMkUkc1
aliyun.oss.access-key-secret=GpUJboqMqecakDNBSVlUPhnaKfjGfY

@ -0,0 +1,23 @@
<?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="com.example.demo.mapper.AdminMapper">
<!--<resultMap id="adminMap" type="com.example.demo.entity.Admin">
<result property="id" column="id" />
<result property="username" column="username" />
<result property="password" column="password" />
<result property="name" column="name" />
<result property="level" column="level" />
</resultMap>-->
<select id="selectByUsername" resultType="com.example.demo.entity.Admin">
select * from admin where username = #{username}
</select>
<select id="findByPage" resultType="com.example.demo.entity.Admin">
select * from admin where name like '%${name}%' and username like concat('%', #{username}, '%')
</select>
<update id="updatePass" parameterType="map">
update admin set password = #{newPwd} where id = #{id}
</update>
</mapper>

@ -0,0 +1,55 @@
<?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="com.example.demo.mapper.MonitorRequestMapper">
<!-- 分步查询 -->
<resultMap id="monitorRequestMapByStep" type="com.example.demo.entity.MonitorRequest">
<id property="id" column="id" />
<result property="createTime" column="createTime" />
<result property="checked" column="check" />
<result property="complete" column="complete" />
<result property="workId" column="workId" />
<result property="userId" column="userId" />
<association property="user"
javaType="com.example.demo.entity.User">
<id property="id" column="userId" />
<result property="username" column="username" />
</association>
<association property="monitorWork"
javaType="com.example.demo.entity.MonitorWork">
<id property="id" column="userId" />
<result property="name" column="workName" />
</association>
</resultMap>
<sql id="selectAllColEm">
select mr.*, mw.name as workName, us.username as username
from monitor_request mr
inner join monitor_work mw
on (mr.workId = mw.id)
inner join user us
on (mr.userId = us.id)
</sql>
<sql id="cond1">
where mw.name like '%${workName}%'
and us.username like '%${username}%'
</sql>
<sql id="cond2">
where mr.userId = #{userId}
</sql>
<select id="findPage" resultMap="monitorRequestMapByStep">
<include refid="selectAllColEm"></include>
<include refid="cond1"></include>
</select>
<select id="selectAll" resultMap="monitorRequestMapByStep">
<include refid="selectAllColEm"></include>
<include refid="cond1"></include>
</select>
<select id="selectByUserId" resultMap="monitorRequestMapByStep">
<include refid="selectAllColEm" />
<include refid="cond2"></include>
</select>
</mapper>

@ -0,0 +1,19 @@
<?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="com.example.demo.mapper.MonitorWorkMapper">
<select id="selectByUserId" resultType="com.example.demo.entity.MonitorWork">
select *
from monitor_work
where id in (
select workId from monitor_request mr
inner join user us on (mr.userId = us.id)
where us.username = 'root' or us.id = #{userId}
)
</select>
<select id="findWorkName" resultType="string">
select name
from monitor_work
where id = #{workId}
</select>
</mapper>

@ -0,0 +1,54 @@
<?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="com.example.demo.mapper.PolarityAnalysisMapper">
<!-- 分步查询 -->
<resultMap id="polarityByStep" type="com.example.demo.entity.PolarityAnalysis">
<id property="id" column="id" />
<result property="workId" column="workId" />
<result property="country" column="country" />
<result property="time" column="time" />
<result property="platform" column="platform" />
<result property="positive" column="positive" />
<result property="negative" column="negative" />
<result property="neutrality" column="neutrality" />
<association property="monitorWork"
javaType="com.example.demo.entity.MonitorWork">
<id property="id" column="userId" />
<result property="name" column="name" />
<result property="category" column="category" />
</association>
</resultMap>
<select id="findPage" resultMap="polarityByStep">
select poa.*, mw.name, mw.category
from polarity_analy poa
inner join monitor_work mw
on (poa.workId = mw.id)
where mw.name like '%${workName}%'
and poa.country like '%${country}%'
and poa.platform like '%${platform}%'
<if test="time != null and time != ''">
and time = #{time}
</if>
order by poa.id
</select>
<select id="findAll" resultMap="polarityByStep">
select poa.*, mw.name, mw.category
from polarity_analy poa
inner join monitor_work mw
on (poa.workId = mw.id)
order by poa.id
</select>
<select id="selectDayInterval" resultType="com.example.demo.entity.dto.PolarityDto">
select time, sum(positive) as positive,
sum(negative) as negative, sum(neutrality) as neutrality
from polarity_analy
where workId = #{workId}
and country = #{country}
and TO_DAYS(time) - TO_DAYS(#{startTime}) between 0 and (#{interval} - 1)
group by time
order by time asc
</select>
</mapper>

@ -0,0 +1,18 @@
<?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="com.example.demo.mapper.RawCommentMapper">
<select id="countPlatformByWorkId" resultType="com.example.demo.entity.dto.CommentPlatformDto">
select count(id) as count, platform
from raw_comment
where workId = #{workId}
group by platform
</select>
<select id="selectAllCountry" resultType="java.lang.String">
select distinct country from raw_comment
</select>
<select id="selectAllPlatform" resultType="java.lang.String">
select distinct platform from raw_comment
</select>
</mapper>

@ -0,0 +1,46 @@
<?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="com.example.demo.mapper.SentimentAnalysisMapper">
<!-- 分步查询 -->
<resultMap id="sentimentByStep" type="com.example.demo.entity.SentimentAnalysis">
<id property="id" column="id" />
<result property="workId" column="workId" />
<result property="country" column="country" />
<result property="time" column="time" />
<result property="platform" column="platform" />
<result property="happy" column="happy" />
<result property="amazed" column="amazed" />
<result property="neutrality" column="neutrality" />
<result property="hate" column="hate" />
<result property="angry" column="angry" />
<result property="fear" column="fear" />
<association property="monitorWork"
javaType="com.example.demo.entity.MonitorWork">
<id property="id" column="userId" />
<result property="name" column="name" />
<result property="category" column="category" />
</association>
</resultMap>
<select id="findPage" resultMap="sentimentByStep">
select senti.*, mw.name, mw.category
from sentiment_analy senti
inner join monitor_work mw
on (senti.workId = mw.id)
where mw.name like '%${workName}%'
and senti.country like '%${country}%'
and senti.platform like '%${platform}%'
<if test="time != null and time != ''">
and time = #{time}
</if>
order by senti.id
</select>
<select id="findAll" resultMap="sentimentByStep">
select senti.*, mw.name, mw.category
from sentiment_analy senti
inner join monitor_work mw
on (senti.workId = mw.id)
order by senti.id
</select>
</mapper>

@ -0,0 +1,32 @@
<?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="com.example.demo.mapper.UserMapper">
<!--<resultMap id="userMap" type="com.example.demo.entity.User">
<result property="id" column="id"/>
<result property="username" column="username"/>
<result property="password" column="password"/>
<collection property="bookList" javaType="ArrayList" ofType="com.example.demo.entity.Book">
<result column="b_id" property="id" />
<result column="b_name" property="name" />
<result column="b_price" property="price" />
</collection>
</resultMap>-->
<update id="updatePass" parameterType="map">
update user set password = #{newPwd} where id = #{id}
</update>
<select id="findPage" resultType="com.example.demo.entity.User">
SELECT *
from user
where name like concat('%', #{name}, '%') and username like concat('%', #{username}, '%')
</select>
<select id="countWorkUnit" resultType="com.example.demo.entity.dto.UserWorkUnitDto">
select count(id) count, workUnit from user group by workUnit
</select>
<select id="selectByUsername" resultType="com.example.demo.entity.User" parameterType="java.lang.String">
select * from user where username=#{username}
</select>
</mapper>

@ -0,0 +1,44 @@
<?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="com.example.demo.mapper.WordFreqAnalysisMapper">
<!-- 分步查询 -->
<resultMap id="wordFreqByStep" type="com.example.demo.entity.WordFreqAnalysis">
<id property="id" column="id" />
<result property="workId" column="workId" />
<result property="country" column="country" />
<result property="time" column="time" />
<result property="platform" column="platform" />
<result property="polarity" column="polarity" />
<result property="keywords" column="keywords" />
<result property="frequency" column="frequency" />
<association property="monitorWork"
javaType="com.example.demo.entity.MonitorWork"
fetchType="lazy">
<id property="id" column="userId" />
<result property="name" column="name" />
<result property="category" column="category" />
</association>
</resultMap>
<select id="findAll" resultMap="wordFreqByStep">
select wfa.*, mw.name, mw.category
from word_freq_analy wfa
inner join monitor_work mw
on (wfa.workId = mw.id)
order by wfa.id
</select>
<select id="findPage" resultMap="wordFreqByStep">
select wfa.*, mw.name, mw.category
from word_freq_analy wfa
inner join monitor_work mw
on (wfa.workId = mw.id)
where mw.name like '%${workName}%'
and wfa.country like '%${country}%'
and wfa.platform like '%${platform}%'
<if test="time != null and time != ''">
and time = #{time}
</if>
order by wfa.id
</select>
</mapper>

@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="xxxx">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>邮件通知</title>
<style type="text/css">
#tab {
width: 800px;height: 100%;
margin: 0px auto;
text-align: left;
position: relative;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
font-size: 14px;
font-family:微软雅黑, 黑体;
line-height: 1.5;
box-shadow: rgb(153, 153, 153) 0px 0px 5px;
border-collapse: collapse;
background-position: initial;
background-repeat: initial;
background:#fff;
}
#title {
height: 25px;
line-height: 25px;
padding: 15px 35px;
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #42a3d3;
background-color: #49bcff;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
}
#main {
padding:10px 10px 0;
border-top:1px solid #ccc;
color:#747474;
margin-bottom:20px;
line-height:1.3em;
font-size:12px;
}
</style>
</head>
<body>
<div style="background-color:#ECECEC; padding: 35px;">
<table id="tab" cellpadding="0" align="center"
style="">
<tbody>
<tr>
<th valign="middle" id="title">
<font face="微软雅黑" size="5" style="color: rgb(255, 255, 255); ">邮件通知</font>
</th>
</tr>
<tr>
<td style="word-break:break-all">
<div style="padding:25px 35px 40px; background-color:#fff;">
<h2 style="margin: 5px 0px; ">
<font color="#333333" style="line-height: 20px; ">
<font style="line-height: 22px; " size="4">
尊敬的用户:</font>
</font>
</h2>
<!-- 中文 -->
<p>${user},您申请的文化作品传播监测已经被处理并完成,
您可以<a href="https://www.baidu.com">前往查看</a></p><br>
<!-- 英文 -->
<h2 style="margin: 5px 0px; ">
<font color="#333333" style="line-height: 20px; ">
<font style="line-height: 22px; " size="4">
Dear user</font>
</font>
</h2>
<p>
${user}, Your request for the monitoring of the dissemination
of cultural works has been processed and completed,
and you can <a href="https://www.baidu.com">visit it</a>
</p>
<div style="width:700px;margin:0 auto;">
<div id="main">
<p>湖南师范大学</p>
<p>办公电话13283472322</p>
<p>电子邮箱:<a href="mailto:hzx1966752024@163.com">hzx1966752024@163.com</a> </p>
<p>通讯地址:湖南省长沙市岳麓区桔子洲街道</p><br>
<p>此为系统邮件,请勿回复<br>
Please do not reply to this system email
</p>
<!--<p>©***</p>-->
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

@ -0,0 +1,37 @@
package com.example.demo;
import com.example.demo.utils.EmailUtil;
import freemarker.template.TemplateException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@SpringBootTest(classes = {DemoApplication.class})
@RunWith(SpringRunner.class)
public class MailDemoApplicationTests {
@Autowired
private EmailUtil emailUtil;
@Test
public void testEmailSend() {
// emailUtil.sendSimpleMail("1728326545@qq.com", "这是一封测试邮件");
try {
emailUtil.sendHtmlMail("3149125715@qq.com", "张凯芹");
} catch (IOException | TemplateException e) {
e.printStackTrace();
}
}
@Test
public void test2() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
System.out.println(sdf.parse("2023/7/1 0:00"));
}
}

@ -0,0 +1,23 @@
package com.example.demo;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class Test1 {
public static void main(String[] args) {
/*BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String encode = encoder.encode("123456");
System.out.println(encode);*/
/*System.out.println(encoder.matches("123456", "" +
"$2a$10$ioF9GdWF6ahRStp8Tj4iiOeKe1im/jaaHbk0rRiYIN6wb838EVWay"));*/
// SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
// System.out.println(dateFormat.format(new Date()));
// String s = "1 2 3 4 5 6 7 7 9 20";
// String[] split = s.split("\\s+");
// System.out.println(Arrays.toString(split));
}
}

@ -0,0 +1,12 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"]
}

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

@ -0,0 +1,14 @@
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

@ -0,0 +1,10 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 lidonghui
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,209 @@
# vue搭建后台管理界面模版PC端
------------------------
<img src="./static/gif.gif" width="100%" height="519px"/>
#### 技术栈
vue2 + vuex + vue-router + webpack + ES6/7 + axios + elementUI + 阿里图标iconfont
#### 项目预览
[http://nmgwap.gitee.io/vueproject/#/login](http://nmgwap.gitee.io/vueproject/#/login)
#### 说明
> 本项目主要用于熟悉如何用 vue2 架构一个后端管理平台项目
> 为了方便后期修改使用,模拟数据在页面中,具体修改看下面【强调】
> 如果对您有帮助,您可以点右上角 "Star" 支持一下 谢谢! ^_^
> 或者您可以 "follow" 一下,我会不断开源更多的有趣的项目
> 开发环境 w7 Chrome 61
> 如有问题请直接在 Issues 中提,或者您发现问题并有非常好的解决方案,欢迎 PR 👍
#### 目录结构
------------------------
```bash
├── /build/ # 项目构建(webpack)相关配置
├── /config/ # 项目开发环境配置
├── /src/ # 源码目录
│ ├── /api/ # 请求
│ ├── /assets/ # 组件静态资源(图片)
│ ├── /components/ # 公共组件
| ├── /api/ # 请求接口
│ ├── /router/ # 路由配置
│ ├── /vuex/ # vuex状态管理
│ ├── /views/ # 路由组件(页面维度)
│ ├── /config/ # 接口配置文件(请求地址)
│ ├── App.vue # 组件入口
│ └── main.js # 程序入口
├── /static/ # 非组件静态资源
├── .babelrc # ES6语法编译配置
├── .editorconfig # 定义代码格式
├── .eslintignore # ES6规范忽略文件
├── .eslintrc.js # ES6语法规范配置
├── .gitignore # git忽略文件
├── index.html # 页面入口
├── package.json # 项目依赖
└── README.md # 项目文档
```
#### 强调
项目请求已经改为假数据,例如:
``` bash
// 模拟数据开始
let res = {
code: 0,
msg: null,
count: 12,
data: [
{
addUser: '1',
editUser: '1',
addTime: null,
editTime: 1527411068000,
userId: 1,
systemNo: 'pmd',
userName: 'root',
userPassword: 'e10adc3949ba59abbe56e057f20f883e',
userRealName: '超级管理员',
userSex: '女',
userMobile: '138123456789',
userEmail: '111@qq.com',
isLock: 'N',
deptId: 1,
deptName: 'xxxx',
roleId: 1
}
]
}
this.loading = false
this.userData = res.data
// 分页赋值
this.pageparm.currentPage = this.formInline.page
this.pageparm.pageSize = this.formInline.limit
this.pageparm.total = res.count
// 模拟数据结束
/***
* 调用接口,注释上面模拟数据 取消下面注释
*/
// 获取用户列表
// userList(parameter).then(res => {
// this.loading = false
// if (res.success == false) {
// this.$message({
// type: 'info',
// message: res.msg
// })
// } else {
// this.userData = res.data
// // 分页赋值
// this.pageparm.currentPage = this.formInline.page
// this.pageparm.pageSize = this.formInline.limit
// this.pageparm.total = res.count
// }
// })
```
把模拟数据开始到结束注释掉,下面解除注释即可,
接口地址需要修改config/index.js文件 dev
``` bash
proxyTable: {
'/api': {
target: 'http://xxx.xxx.xxx.xxx:xxx', // 你请求的第三方接口
changeOrigin: true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
pathRewrite: { // 路径重写,
'^/api': '/api' // 替换target中的请求地址也就是说以后你在请求http://api.jisuapi.com/XXXXX这个地址的时候直接写成/api即可。
}
}
},
```
#### 完成功能
- [x] 登录 -- 完成
- [x] 路由拦截 -- 完成
- [x] 商品管理(增加、编辑、搜索、删除) -- 完成
- [x] 角色管理(增加、编辑、搜索、删除、权限管理) -- 完成
- [x] 交易订单(增加、编辑、搜索、删除) -- 完成
- [x] 用户管理(增加、编辑、搜索、删除、数据权限、刷新缓存) -- 完成
- [x] 支付配置(增加、编辑、搜索、删除) -- 完成
- [x] 系统环境变量(增加、编辑、搜索、删除) -- 完成
- [x] 权限管理(增加、编辑、搜索、删除、配置权限) -- 完成
- [x] 菜单管理(增加、编辑、搜索、删除) -- 完成
- [x] 公司管理(增加、编辑、搜索、删除) -- 完成
#### 部分截图
------------------------
商品管理
![商品管理](./static/商品管理.png "商品管理")
角色管理
![角色管理](./static/角色管理.png "角色管理")
交易订单
![交易订单](./static/交易订单.png "交易订单")
编辑
![编辑](./static/编辑.png "编辑")
用户管理
![用户管理](./static/用户管理.png "用户管理")
支付配置
![支付配置](./static/支付配置.png "支付配置")
展开与压缩
![展开与压缩](./static/展开与压缩.png "展开与压缩")
#### 运行项目
------------------------
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
# run unit tests
npm run unit
# run e2e tests
npm run e2e
# run all tests
npm test
```
#### 项目源码地址:
------------------------
码云地址https://gitee.com/ldhblog/vue-element.git
github地址https://github.com/nmgwap/vue-ManagementPlatform.git
#### 微信公众号
------------------------
<img src="/static/wx.jpg" width = "270" height = "270"/>

@ -0,0 +1,41 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})

@ -0,0 +1,54 @@
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

@ -0,0 +1,102 @@
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function(_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production' ?
config.build.assetsSubDirectory :
config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function(options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders(loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
publicPath: '../../',
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function(options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}

@ -0,0 +1,22 @@
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}

@ -0,0 +1,94 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
},
{
test: /\.svg$/,
include: [path.resolve('./src/assets/icons/svg')],
use: {
loader: 'svg-sprite-loader',
options: {
symbolId: 'icon-[name]'
}
}
},
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}

@ -0,0 +1,91 @@
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true,
favicon: './favicon.ico'
}),
// copy custom static assets
new CopyWebpackPlugin([{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors ?
utils.createNotifierCallback() : undefined
}))
resolve(devWebpackConfig)
}
})
})

@ -0,0 +1,145 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

@ -0,0 +1,100 @@
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'http://localhost:9090', // 你请求的第三方接口
changeOrigin: true, // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
pathRewrite: { // 路径重写,
'^/api': '/api' // 替换target中的请求地址也就是说以后你在请求http://api.jisuapi.com/XXXXX这个地址的时候直接写成/api即可。
}
},
},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 9999, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: true,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: './',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report,
/*chainWebpack(config) {
// set svg-sprite-loader
config.module
rule('svg')
.exclude.add(resolve('src/assets/icons'))
.end()
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/assets/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
}*/
},
}

@ -0,0 +1,4 @@
'use strict'
module.exports = {
NODE_ENV: '"production"'
}

@ -0,0 +1,48 @@
{
"editor.tabSize": 2,
"files.associations": {
"*.vue": "vue"
},
"eslint.autoFixOnSave": true,
"eslint.options": {
"extensions": [
".js",
".vue"
]
},
"eslint.validate": [
"javascript",
"javascriptreact",
"vue",
"vue-html"
],
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/dist": true
},
"emmet.syntaxProfiles": {
"javascript": "jsx",
"vue": "html",
"vue-html": "html"
},
"git.confirmSync": false,
"window.zoomLevel": 0,
"vsicons.projectDetection.autoReload": true,
"typescript.check.tscVersion": false,
"editor.renderWhitespace": "boundary",
"editor.cursorBlinking": "smooth",
"workbench.colorTheme": "Solarized Light",
"workbench.iconTheme": "vscode-great-icons",
"editor.minimap.enabled": true,
"editor.minimap.renderCharacters": false,
"tslint.autoFixOnSave": true,
"editor.fontFamily": "'Droid Sans Mono', 'Courier New', monospace, 'Droid Sans Fallback'",
"beautify.tabSize": 2,
"window.title": "${dirty}${activeEditorMedium}${separator}${rootName}",
"typescript.extension.sortImports.maxNamedImportsInSingleLine": 5,
"typescript.extension.sortImports.omitSemicolon": true,
"editor.codeLens": true,
"editor.snippetSuggestions": "top",
"react-native-storybooks.port": 6006
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- 页面增加icon图标 -->
<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" rel="external nofollow" />
<title>后端管理平台</title>
</head>
<body>
<!-- built files will be auto injected -->
<div id="app"></div>
</body>
</html>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,73 @@
{
"name": "vue-ele-project",
"version": "1.0.0",
"description": "vue-ele-project",
"author": "lidonghui",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build": "node build/build.js"
},
"dependencies": {
"echarts": "^4.2.0-rc.2",
"element-ui": "^2.3.2",
"file-saver": "^2.0.5",
"http-proxy-middleware": "^0.18.0",
"js-md5": "^0.7.3",
"vue": "^2.5.2",
"vue-cropper": "0.5.5",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"axios": "^0.18.0",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"sass": "^1.26.5",
"sass-loader": "^7.3.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"svg-sprite-loader": "^5.2.1",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save