feat: 练题模块完成
This commit is contained in:
178
qing-yu-club-practice/qing-yu-club-practice-server/pom.xml
Normal file
178
qing-yu-club-practice/qing-yu-club-practice-server/pom.xml
Normal file
@@ -0,0 +1,178 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.landaiqing</groupId>
|
||||
<artifactId>qing-yu-club-practice</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>qing-yu-club-practice-server</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>qing-yu-practice-server</name>
|
||||
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<spring-boot.version>2.4.2</spring-boot.version>
|
||||
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
|
||||
<spring-cloud.version>2020.0.6</spring-cloud.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.28</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
<version>1.4.2.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>1.4.2.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
<version>2.4.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.79</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>19.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
<version>2.4.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
<version>2.4.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.1.22</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.33</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.4.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
<version>3.0.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.landaiqing</groupId>
|
||||
<artifactId>qing-yu-club-practice-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.landaiqing</groupId>
|
||||
<artifactId>qing-yu-club-auth-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
|
||||
<version>${spring-cloud-alibaba.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<!--打包成jar包时的名字-->
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.3.0.RELEASE</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@@ -0,0 +1,21 @@
|
||||
package com.landaiqing.practice.server;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* 练习微服务启动类
|
||||
*
|
||||
* @author: landaiqing
|
||||
* @date: 2024/2/7
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@ComponentScan("com.landaiqing")
|
||||
@MapperScan("com.landaiqing.**.dao")
|
||||
public class PracticeApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(PracticeApplication.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package com.landaiqing.practice.server.config;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.landaiqing.practice.server.config.interceptor.LoginInterceptor;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Classname GlobalConfig
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.subject.application.config
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-02-16 15:57
|
||||
* @Description: MVC全局处理
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Configuration
|
||||
public class GlobalConfig extends WebMvcConfigurationSupport {
|
||||
@Override
|
||||
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
super.configureMessageConverters(converters);
|
||||
converters.add(mappingJackson2HttpMessageConverter());
|
||||
}
|
||||
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
|
||||
ObjectMapper objectMapper=new ObjectMapper();
|
||||
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false);
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
MappingJackson2HttpMessageConverter converter=new MappingJackson2HttpMessageConverter(objectMapper);
|
||||
return converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new LoginInterceptor())
|
||||
.addPathPatterns("/**");
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package com.landaiqing.practice.server.config.context;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @Classname LoginContextHolder
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.subject.application.context
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-03 18:11
|
||||
* @Description: 登录上下文对象
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class LoginContextHolder {
|
||||
private static final InheritableThreadLocal <Map<String,Object>> THREAD_LOCAL=new InheritableThreadLocal<>();
|
||||
|
||||
public static void set(String key,Object val){
|
||||
Map<String,Object> map=getThreadLoacalMap();
|
||||
map.put(key, val);
|
||||
}
|
||||
public static Object get(String key){
|
||||
Map<String,Object> threadLoacalMap=getThreadLoacalMap();
|
||||
return threadLoacalMap.get(key);
|
||||
}
|
||||
public static void remove(){
|
||||
THREAD_LOCAL.remove();
|
||||
}
|
||||
|
||||
public static String getLoginId(){
|
||||
return (String) getThreadLoacalMap().get("loginId");
|
||||
}
|
||||
public static Map<String,Object> getThreadLoacalMap(){
|
||||
Map<String,Object> map =THREAD_LOCAL.get();
|
||||
if (Objects.isNull(map)){
|
||||
map=new ConcurrentHashMap<>();
|
||||
THREAD_LOCAL.set(map);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.landaiqing.practice.server.config.interceptor;
|
||||
|
||||
|
||||
import com.landaiqing.practice.server.config.context.LoginContextHolder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @Classname LoginInterceptor
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.subject.application.interceptor
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-03 18:05
|
||||
* @Description: 登录拦截器
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class LoginInterceptor implements HandlerInterceptor {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String loginId = request.getHeader("loginId");
|
||||
if (StringUtils.isNotBlank(loginId)) {
|
||||
LoginContextHolder.set("loginId", loginId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
|
||||
LoginContextHolder.remove();
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package com.landaiqing.practice.server.config.mybatis;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class MybatisConfiguration {
|
||||
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor(){
|
||||
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
|
||||
mybatisPlusInterceptor.addInnerInterceptor(new MybatisPlusAllSqlLog());
|
||||
return mybatisPlusInterceptor;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,116 @@
|
||||
package com.landaiqing.practice.server.config.mybatis;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class MybatisPlusAllSqlLog implements InnerInterceptor {
|
||||
public static final Logger log = LoggerFactory.getLogger("sys-sql");
|
||||
|
||||
@Override
|
||||
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
|
||||
logInfo(boundSql, ms, parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) throws SQLException {
|
||||
BoundSql boundSql = ms.getBoundSql(parameter);
|
||||
logInfo(boundSql, ms, parameter);
|
||||
}
|
||||
|
||||
private static void logInfo(BoundSql boundSql, MappedStatement ms, Object parameter) {
|
||||
try {
|
||||
log.info("parameter = " + parameter);
|
||||
// 获取到节点的id,即sql语句的id
|
||||
String sqlId = ms.getId();
|
||||
log.info("sqlId = " + sqlId);
|
||||
// 获取节点的配置
|
||||
Configuration configuration = ms.getConfiguration();
|
||||
// 获取到最终的sql语句
|
||||
String sql = getSql(configuration, boundSql, sqlId);
|
||||
log.info("完整的sql:{}", sql);
|
||||
} catch (Exception e) {
|
||||
log.error("异常:{}", e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// 封装了一下sql语句,使得结果返回完整xml路径下的sql语句节点id + sql语句
|
||||
public static String getSql(Configuration configuration, BoundSql boundSql, String sqlId) {
|
||||
return sqlId + ":" + showSql(configuration, boundSql);
|
||||
}
|
||||
|
||||
// 进行?的替换
|
||||
public static String showSql(Configuration configuration, BoundSql boundSql) {
|
||||
// 获取参数
|
||||
Object parameterObject = boundSql.getParameterObject();
|
||||
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
|
||||
// sql语句中多个空格都用一个空格代替
|
||||
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
|
||||
if (!CollectionUtils.isEmpty(parameterMappings) && parameterObject != null) {
|
||||
// 获取类型处理器注册器,类型处理器的功能是进行java类型和数据库类型的转换
|
||||
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
|
||||
// 如果根据parameterObject.getClass()可以找到对应的类型,则替换
|
||||
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
|
||||
sql = sql.replaceFirst("\\?",
|
||||
Matcher.quoteReplacement(getParameterValue(parameterObject)));
|
||||
} else {
|
||||
// MetaObject主要是封装了originalObject对象,提供了get和set的方法用于获取和设置originalObject的属性值,主要支持对JavaBean、Collection、Map三种类型对象的操作
|
||||
MetaObject metaObject = configuration.newMetaObject(parameterObject);
|
||||
for (ParameterMapping parameterMapping : parameterMappings) {
|
||||
String propertyName = parameterMapping.getProperty();
|
||||
if (metaObject.hasGetter(propertyName)) {
|
||||
Object obj = metaObject.getValue(propertyName);
|
||||
sql = sql.replaceFirst("\\?",
|
||||
Matcher.quoteReplacement(getParameterValue(obj)));
|
||||
} else if (boundSql.hasAdditionalParameter(propertyName)) {
|
||||
// 该分支是动态sql
|
||||
Object obj = boundSql.getAdditionalParameter(propertyName);
|
||||
sql = sql.replaceFirst("\\?",
|
||||
Matcher.quoteReplacement(getParameterValue(obj)));
|
||||
} else {
|
||||
// 打印出缺失,提醒该参数缺失并防止错位
|
||||
sql = sql.replaceFirst("\\?", "缺失");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
// 如果参数是String,则添加单引号, 如果是日期,则转换为时间格式器并加单引号; 对参数是null和不是null的情况作了处理
|
||||
private static String getParameterValue(Object obj) {
|
||||
String value;
|
||||
if (obj instanceof String) {
|
||||
value = "'" + obj.toString() + "'";
|
||||
} else if (obj instanceof Date) {
|
||||
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT,
|
||||
DateFormat.DEFAULT, Locale.CHINA);
|
||||
value = "'" + formatter.format(new Date()) + "'";
|
||||
} else {
|
||||
if (obj != null) {
|
||||
value = obj.toString();
|
||||
} else {
|
||||
value = "";
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
package com.landaiqing.practice.server.config.mybatis;
|
||||
|
||||
import org.apache.ibatis.cache.CacheKey;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
@Intercepts({
|
||||
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class,
|
||||
Object.class}),
|
||||
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class,
|
||||
Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})})
|
||||
public class SqlStatementInterceptor implements Interceptor {
|
||||
|
||||
public static final Logger log = LoggerFactory.getLogger("sys-sql");
|
||||
|
||||
@Override
|
||||
public Object intercept(Invocation invocation) throws Throwable {
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
return invocation.proceed();
|
||||
} finally {
|
||||
long timeConsuming = System.currentTimeMillis() - startTime;
|
||||
log.info("执行SQL:{}ms", timeConsuming);
|
||||
if (timeConsuming > 999 && timeConsuming < 5000) {
|
||||
log.info("执行SQL大于1s:{}ms", timeConsuming);
|
||||
} else if (timeConsuming >= 5000 && timeConsuming < 10000) {
|
||||
log.info("执行SQL大于5s:{}ms", timeConsuming);
|
||||
} else if (timeConsuming >= 10000) {
|
||||
log.info("执行SQL大于10s:{}ms", timeConsuming);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object plugin(Object target) {
|
||||
return Plugin.wrap(target, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package com.landaiqing.practice.server.config.redis;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
* Redis的config处理
|
||||
*
|
||||
* @author: landaiqing
|
||||
*/
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
redisTemplate.setKeySerializer(redisSerializer);
|
||||
redisTemplate.setHashKeySerializer(redisSerializer);
|
||||
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
|
||||
Jackson2JsonRedisSerializer<Object> jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
|
||||
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
|
||||
jsonRedisSerializer.setObjectMapper(objectMapper);
|
||||
return jsonRedisSerializer;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,141 @@
|
||||
package com.landaiqing.practice.server.config.redis;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.Cursor;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.core.ScanOptions;
|
||||
import org.springframework.data.redis.core.ZSetOperations;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* RedisUtil工具类
|
||||
*
|
||||
* @author: landaiqing
|
||||
* @date: 2024/2/19
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RedisUtil {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate redisTemplate;
|
||||
|
||||
private static final String CACHE_KEY_SEPARATOR = ".";
|
||||
|
||||
/**
|
||||
* 构建缓存key
|
||||
*/
|
||||
public String buildKey(String... strObjs) {
|
||||
return Stream.of(strObjs).collect(Collectors.joining(CACHE_KEY_SEPARATOR));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在key
|
||||
*/
|
||||
public boolean exist(String key) {
|
||||
return redisTemplate.hasKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除key
|
||||
*/
|
||||
public boolean del(String key) {
|
||||
return redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* set(不带过期)
|
||||
*/
|
||||
public void set(String key, String value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* set(带过期)
|
||||
*/
|
||||
public boolean setNx(String key, String value, Long time, TimeUnit timeUnit) {
|
||||
return redisTemplate.opsForValue().setIfAbsent(key, value, time, timeUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取string类型缓存
|
||||
*/
|
||||
public String get(String key) {
|
||||
return (String) redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
public Boolean zAdd(String key, String value, Long score) {
|
||||
return redisTemplate.opsForZSet().add(key, value, Double.valueOf(String.valueOf(score)));
|
||||
}
|
||||
|
||||
public Long countZset(String key) {
|
||||
return redisTemplate.opsForZSet().size(key);
|
||||
}
|
||||
|
||||
public Set<String> rangeZset(String key, long start, long end) {
|
||||
return redisTemplate.opsForZSet().range(key, start, end);
|
||||
}
|
||||
|
||||
public Long removeZset(String key, Object value) {
|
||||
return redisTemplate.opsForZSet().remove(key, value);
|
||||
}
|
||||
|
||||
public void removeZsetList(String key, Set<String> value) {
|
||||
value.stream().forEach((val) -> redisTemplate.opsForZSet().remove(key, val));
|
||||
}
|
||||
|
||||
public Double score(String key, Object value) {
|
||||
return redisTemplate.opsForZSet().score(key, value);
|
||||
}
|
||||
|
||||
public Set<String> rangeByScore(String key, long start, long end) {
|
||||
return redisTemplate.opsForZSet().rangeByScore(key, Double.valueOf(String.valueOf(start)), Double.valueOf(String.valueOf(end)));
|
||||
}
|
||||
|
||||
public Object addScore(String key, Object obj, double score) {
|
||||
return redisTemplate.opsForZSet().incrementScore(key, obj, score);
|
||||
}
|
||||
|
||||
public Object rank(String key, Object obj) {
|
||||
return redisTemplate.opsForZSet().rank(key, obj);
|
||||
}
|
||||
|
||||
|
||||
public Set rankWithScore(String key, long start, long end) {
|
||||
Set<ZSetOperations.TypedTuple<String>> set = redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
|
||||
return set;
|
||||
}
|
||||
|
||||
public void putHash(String key, String hashKey, Object hashVal) {
|
||||
redisTemplate.opsForHash().put(key, hashKey, hashVal);
|
||||
}
|
||||
|
||||
public Integer getInt(String key) {
|
||||
return (Integer) redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
public void increment(String key, Integer count) {
|
||||
redisTemplate.opsForValue().increment(key,count);
|
||||
}
|
||||
public Map<Object, Object> getHashAndDelete(String key) {
|
||||
Map<Object, Object> map = new HashMap<>();
|
||||
Cursor<Map.Entry<Object, Object>> cursor = redisTemplate.opsForHash().scan(key, ScanOptions.NONE);
|
||||
while (cursor.hasNext()) {
|
||||
Map.Entry<Object, Object> entry = cursor.next();
|
||||
Object hashKey = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
map.put(hashKey, value);
|
||||
redisTemplate.opsForHash().delete(key, hashKey);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
package com.landaiqing.practice.server.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @Classname DemoController
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.practice.server.controller
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-10 17:22
|
||||
* @Description: 测试controller启动
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("practice")
|
||||
@Slf4j
|
||||
public class DemoController {
|
||||
@RequestMapping("/test")
|
||||
public String isLogin() {
|
||||
return "test " ;
|
||||
}
|
||||
}
|
@@ -0,0 +1,194 @@
|
||||
package com.landaiqing.practice.server.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.landaiqing.practice.api.common.Result;
|
||||
import com.landaiqing.practice.api.req.*;
|
||||
import com.landaiqing.practice.api.vo.RankVO;
|
||||
import com.landaiqing.practice.api.vo.ReportVO;
|
||||
import com.landaiqing.practice.api.vo.ScoreDetailVO;
|
||||
import com.landaiqing.practice.api.vo.SubjectDetailVO;
|
||||
import com.landaiqing.practice.server.service.PracticeDetailService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping("/practice/detail")
|
||||
public class PracticeDetailController {
|
||||
|
||||
@Resource
|
||||
private PracticeDetailService practiceDetailService;
|
||||
|
||||
/**
|
||||
* 提交题目
|
||||
*/
|
||||
@PostMapping(value = "/submitSubject")
|
||||
public Result<Boolean> submitSubject(@RequestBody SubmitSubjectDetailReq req) {
|
||||
try {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("练习提交题目入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getPracticeId()), "练习id不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSubjectId()), "题目id不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSubjectType()), "题目类型不能为空!");
|
||||
Preconditions.checkArgument(!StringUtils.isBlank(req.getTimeUse()), "用时不能为空!");
|
||||
Boolean result = practiceDetailService.submitSubject(req);
|
||||
log.info("练习提交题目出参{}", result);
|
||||
return Result.ok(result);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("练习提交题目异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("练习提交题目异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交练题情况
|
||||
*/
|
||||
@PostMapping(value = "/submit")
|
||||
public Result<Boolean> submit(@RequestBody SubmitPracticeDetailReq req) {
|
||||
try {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("提交练题情况入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSetId()), "套题id不能为空!");
|
||||
Preconditions.checkArgument(!StringUtils.isBlank(req.getSubmitTime()), "交卷时间不能为空!");
|
||||
Preconditions.checkArgument(!StringUtils.isBlank(req.getTimeUse()), "用时不能为空!");
|
||||
Boolean result = practiceDetailService.submit(req);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("提交练题情况出参{}", JSON.toJSONString(result));
|
||||
}
|
||||
return Result.ok(result);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("提交练题情况异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("提交练题情况异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 答案解析-每题得分
|
||||
*/
|
||||
@PostMapping(value = "/getScoreDetail")
|
||||
public Result<List<ScoreDetailVO>> getScoreDetail(@RequestBody GetScoreDetailReq req) {
|
||||
try {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("每题得分入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getPracticeId()), "练习id不能为空!");
|
||||
List<ScoreDetailVO> list = practiceDetailService.getScoreDetail(req);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("每题得分出参{}", JSON.toJSONString(list));
|
||||
}
|
||||
return Result.ok(list);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("每题得分异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("每题得分异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 答案解析-答题详情
|
||||
*/
|
||||
@PostMapping(value = "/getSubjectDetail")
|
||||
public Result<SubjectDetailVO> getSubjectDetail(@RequestBody GetSubjectDetailReq req) {
|
||||
try {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("答案详情入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSubjectId()), "题目id不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSubjectType()), "题目类型不能为空!");
|
||||
SubjectDetailVO subjectDetailVO = practiceDetailService.getSubjectDetail(req);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("答案详情出参{}", JSON.toJSONString(subjectDetailVO));
|
||||
}
|
||||
return Result.ok(subjectDetailVO);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("答案详情异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("答案详情异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 答案解析-评估报告
|
||||
*/
|
||||
@PostMapping(value = "/getReport")
|
||||
public Result<ReportVO> getReport(@RequestBody GetReportReq req) {
|
||||
try {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取评估报告入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getPracticeId()), "练习id不能为空!");
|
||||
ReportVO reportVO = practiceDetailService.getReport(req);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取评估报告出参{}", JSON.toJSONString(reportVO));
|
||||
}
|
||||
return Result.ok(reportVO);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取评估报告异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("获取评估报告异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取练习榜
|
||||
*/
|
||||
@PostMapping(value = "/getPracticeRankList")
|
||||
public Result<List<RankVO>> getPracticeRankList() {
|
||||
try {
|
||||
List<RankVO> list = practiceDetailService.getPracticeRankList();
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("练习榜出参{}", list);
|
||||
}
|
||||
return Result.ok(list);
|
||||
} catch (Exception e) {
|
||||
log.error("练习榜报错!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("练习榜异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 放弃练习
|
||||
*/
|
||||
@PostMapping(value = "/giveUp")
|
||||
public Result<Boolean> giveUp(@RequestParam("practiceId") Long practiceId) {
|
||||
try {
|
||||
log.info("放弃练习入参{}", practiceId);
|
||||
Preconditions.checkArgument(!Objects.isNull(practiceId), "练习id不能为空!");
|
||||
Boolean result = practiceDetailService.giveUp(practiceId);
|
||||
log.info("放弃练习出参{}", result);
|
||||
return Result.ok(result);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("放弃练习异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("放弃练习异常!");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,184 @@
|
||||
package com.landaiqing.practice.server.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.landaiqing.practice.api.common.PageResult;
|
||||
import com.landaiqing.practice.api.common.Result;
|
||||
import com.landaiqing.practice.api.req.*;
|
||||
import com.landaiqing.practice.api.vo.*;
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSetDTO;
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSubjectDTO;
|
||||
import com.landaiqing.practice.server.service.PracticeSetService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @Classname PracticeSetController
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.practice.server.controller
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-12 17:22
|
||||
* @Description: TODO
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping("/practice/set/")
|
||||
public class PracticeSetController {
|
||||
@Resource
|
||||
private PracticeSetService practiceSetService;
|
||||
|
||||
@RequestMapping("getSpecialPracticeContent")
|
||||
public Result<List<SpecialPracticeVO>> getSpecialPracticeContent() {
|
||||
try {
|
||||
List<SpecialPracticeVO> result = practiceSetService.getSpecialPracticeContent();
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("PracticeSetController.getSpecialPracticeContent.result: {}", JSON.toJSONString(result));
|
||||
}
|
||||
return Result.ok(result);
|
||||
} catch (Exception e) {
|
||||
log.error("PracticeSetController.getSpecialPracticeContent.error: {}", e.getMessage(), e);
|
||||
return Result.fail("获取专项练习内容失败!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始练习
|
||||
*/
|
||||
@PostMapping(value = "/addPractice")
|
||||
public Result<PracticeSetVO> addPractice(@RequestBody GetPracticeSubjectListReq req) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取练习题入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
try {
|
||||
//参数校验
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!CollectionUtils.isEmpty(req.getAssembleIds()), "标签ids不能为空!");
|
||||
PracticeSubjectDTO dto = new PracticeSubjectDTO();
|
||||
dto.setAssembleIds(req.getAssembleIds());
|
||||
PracticeSetVO practiceSetVO = practiceSetService.addPractice(dto);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取练习题目列表出参{}", JSON.toJSONString(practiceSetVO));
|
||||
}
|
||||
return Result.ok(practiceSetVO);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取练习题目列表异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("获取练习题目列表异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取练习题
|
||||
*/
|
||||
@PostMapping(value = "/getSubjects")
|
||||
public Result<PracticeSubjectListVO> getSubjects(@RequestBody GetPracticeSubjectsReq req) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取练习题入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
try {
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSetId()), "练习id不能为空!");
|
||||
PracticeSubjectListVO list = practiceSetService.getSubjects(req);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取练习题目列表出参{}", JSON.toJSONString(list));
|
||||
}
|
||||
return Result.ok(list);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取练习题目列表异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("获取练习题目列表异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取题目详情
|
||||
*/
|
||||
@PostMapping(value = "/getPracticeSubject")
|
||||
public Result<PracticeSubjectVO> getPracticeSubject(@RequestBody GetPracticeSubjectReq req) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取练习题详情入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
try {
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSubjectId()), "题目id不能为空!");
|
||||
Preconditions.checkArgument(!Objects.isNull(req.getSubjectType()), "题目类型不能为空!");
|
||||
PracticeSubjectDTO dto = new PracticeSubjectDTO();
|
||||
dto.setSubjectId(req.getSubjectId());
|
||||
dto.setSubjectType(req.getSubjectType());
|
||||
PracticeSubjectVO vo = practiceSetService.getPracticeSubject(dto);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取练习题目详情出参{}", JSON.toJSONString(vo));
|
||||
}
|
||||
return Result.ok(vo);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取练习详情异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("获取练习题目详情异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模拟套题内容
|
||||
*/
|
||||
@PostMapping(value = "/getPreSetContent")
|
||||
public Result<PageResult<PracticeSetVO>> getPreSetContent(@RequestBody GetPreSetReq req) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取模拟套题内容入参{}", JSON.toJSONString(req));
|
||||
}
|
||||
try {
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
PracticeSetDTO dto = new PracticeSetDTO();
|
||||
dto.setOrderType(req.getOrderType());
|
||||
dto.setPageInfo(req.getPageInfo());
|
||||
dto.setSetName(req.getSetName());
|
||||
PageResult<PracticeSetVO> list = practiceSetService.getPreSetContent(dto);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取模拟套题内容出参{}", JSON.toJSONString(list));
|
||||
}
|
||||
return Result.ok(list);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取模拟套题内容异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("获取模拟套题内容异常!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未完成的练题内容
|
||||
*/
|
||||
@PostMapping(value = "/getUnCompletePractice")
|
||||
public Result<PageResult<UnCompletePracticeSetVO>> getUnCompletePractice(@RequestBody GetUnCompletePracticeReq req) {
|
||||
try {
|
||||
Preconditions.checkArgument(!Objects.isNull(req), "参数不能为空!");
|
||||
PageResult<UnCompletePracticeSetVO> list = practiceSetService.getUnCompletePractice(req);
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取未完成练习内容出参{}", JSON.toJSONString(list));
|
||||
}
|
||||
return Result.ok(list);
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("参数异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail(e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取未完成练习内容异常!错误原因{}", e.getMessage(), e);
|
||||
return Result.fail("获取未完成练习内容异常!");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.PracticePO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PracticeDao {
|
||||
|
||||
/**
|
||||
* 根据练题id获取详情
|
||||
*/
|
||||
PracticePO selectById(Long id);
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
int insert(PracticePO practicePO);
|
||||
|
||||
/**
|
||||
* 更新练习详情
|
||||
*/
|
||||
int update(PracticePO practicePO);
|
||||
|
||||
/**
|
||||
* 删除练习
|
||||
*/
|
||||
int deleteById(Long id);
|
||||
|
||||
/**
|
||||
* 查询未完成的练习题数量
|
||||
*/
|
||||
Integer getUnCompleteCount(String loginId);
|
||||
|
||||
/**
|
||||
* 查询未完成的练习题
|
||||
*/
|
||||
List<PracticePO> getUnCompleteList(@Param("loginId") String loginId,
|
||||
@Param("limit") int limit,
|
||||
@Param("offset") int pageSize);
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.PracticeDetailPO;
|
||||
import com.landaiqing.practice.server.entity.po.PracticeRankPO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PracticeDetailDao {
|
||||
|
||||
/**
|
||||
* 获取正确答案数量
|
||||
*/
|
||||
int selectCorrectCount(Long practiceId);
|
||||
|
||||
/**
|
||||
* 获取得分情况
|
||||
*/
|
||||
List<PracticeDetailPO> selectByPracticeId(Long practiceId);
|
||||
|
||||
/**
|
||||
* 插入练题记录
|
||||
*/
|
||||
int insertSingle(PracticeDetailPO practiceDetailPO);
|
||||
|
||||
/**
|
||||
* 根据练习id,题目id,查询详情
|
||||
*/
|
||||
PracticeDetailPO selectDetail(@Param("practiceId") Long practiceId,
|
||||
@Param("subjectId") Long subjectId,
|
||||
@Param("loginId") String loginId);
|
||||
|
||||
/**
|
||||
* 更新练习详情
|
||||
*/
|
||||
int update(PracticeDetailPO practiceDetailPO);
|
||||
|
||||
/**
|
||||
* 获取答案情况
|
||||
*/
|
||||
PracticeDetailPO selectAnswer(@Param("practiceId") Long practiceId,@Param("subjectId") Long subjectId);
|
||||
|
||||
/**
|
||||
* 获取排行榜情况
|
||||
*/
|
||||
List<PracticeRankPO> getPracticeCount();
|
||||
|
||||
/**
|
||||
* 删除练习详情
|
||||
*/
|
||||
int deleteByPracticeId(Long practiceId);
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSetDTO;
|
||||
import com.landaiqing.practice.server.entity.po.PracticeSetPO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PracticeSetDao {
|
||||
|
||||
/**
|
||||
* 新增套题
|
||||
*/
|
||||
int add(PracticeSetPO po);
|
||||
|
||||
PracticeSetPO selectById(Long setId);
|
||||
|
||||
int updateHeat(Long setId);
|
||||
|
||||
/**
|
||||
* 获取模拟考卷列表数量
|
||||
*/
|
||||
Integer getListCount(PracticeSetDTO dto);
|
||||
|
||||
/**
|
||||
* 获取模拟考卷列表
|
||||
*/
|
||||
List<PracticeSetPO> getSetList(@Param("dto") PracticeSetDTO dto,
|
||||
@Param("limit") int limit,
|
||||
@Param("offset") int offset);
|
||||
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.PracticeSetDetailPO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PracticeSetDetailDao {
|
||||
|
||||
/**
|
||||
* 新增套题
|
||||
*/
|
||||
int add(PracticeSetDetailPO po);
|
||||
|
||||
List<PracticeSetDetailPO> selectBySetId(Long setId);
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
|
||||
import com.landaiqing.practice.server.entity.dto.CategoryDTO;
|
||||
import com.landaiqing.practice.server.entity.po.CategoryPO;
|
||||
import com.landaiqing.practice.server.entity.po.PrimaryCategoryPO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 题目分类(SubjectCategory)表数据库访问层
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2023-10-01 21:49:58
|
||||
*/
|
||||
public interface SubjectCategoryDao {
|
||||
|
||||
List<PrimaryCategoryPO> getPrimaryCategory(CategoryDTO categoryDTO);
|
||||
|
||||
CategoryPO selectById(Long id);
|
||||
|
||||
List<CategoryPO> selectList(CategoryDTO categoryDTOTemp);
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,19 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSubjectDTO;
|
||||
import com.landaiqing.practice.server.entity.po.SubjectPO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SubjectDao {
|
||||
|
||||
|
||||
/**
|
||||
* 获取练习面试题目
|
||||
*/
|
||||
List<SubjectPO> getPracticeSubject(PracticeSubjectDTO dto);
|
||||
|
||||
SubjectPO selectById(Long subjectId);
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.SubjectJudgePO;
|
||||
|
||||
public interface SubjectJudgeDao {
|
||||
|
||||
|
||||
SubjectJudgePO selectBySubjectId(Long repeatSubjectId);
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.SubjectLabelPO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 题目标签表(SubjectLabel)表数据库访问层
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2023-10-03 21:50:29
|
||||
*/
|
||||
public interface SubjectLabelDao {
|
||||
|
||||
/**
|
||||
* 通过ID查询单条数据
|
||||
*
|
||||
* @param id 主键
|
||||
* @return 实例对象
|
||||
*/
|
||||
SubjectLabelPO queryById(Long id);
|
||||
|
||||
/**
|
||||
* 批量查询当前题目的标签名称
|
||||
*/
|
||||
List<String> getLabelNameByIds(@Param("labelIds") List<Long> labelIds);
|
||||
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,24 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.LabelCountPO;
|
||||
import com.landaiqing.practice.server.entity.po.SubjectMappingPO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 题目分类关系表(SubjectMapping)表数据库访问层
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2023-10-03 22:17:07
|
||||
*/
|
||||
public interface SubjectMappingDao {
|
||||
|
||||
List<LabelCountPO> getLabelSubjectCount(@Param("categoryId") Long categoryId,
|
||||
@Param("subjectTypeList") List<Integer> subjectTypeList);
|
||||
|
||||
List<SubjectMappingPO> getLabelIdsBySubjectId(Long subjectId);
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.SubjectMultiplePO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SubjectMultipleDao {
|
||||
|
||||
/**
|
||||
* 查询题目
|
||||
*/
|
||||
List<SubjectMultiplePO> selectBySubjectId(Long subjectId);
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package com.landaiqing.practice.server.dao;
|
||||
|
||||
import com.landaiqing.practice.server.entity.po.SubjectRadioPO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SubjectRadioDao {
|
||||
|
||||
/**
|
||||
* 根据题目id查询单选题目
|
||||
*/
|
||||
List<SubjectRadioPO> selectBySubjectId(Long subjectId);
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
存放dao
|
@@ -0,0 +1,23 @@
|
||||
package com.landaiqing.practice.server.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Classname CategoryDTO
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.practice.server.entity.dto
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-12 17:45
|
||||
* @Description: TODO
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class CategoryDTO {
|
||||
|
||||
private List<Integer> subjectTypeList;
|
||||
|
||||
private Integer categoryType;
|
||||
private Long parentId;
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
package com.landaiqing.practice.server.entity.dto;
|
||||
|
||||
import com.landaiqing.practice.api.common.PageInfo;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PracticeSetDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 排除的套题id
|
||||
*/
|
||||
private List<Long> excludeSetId;
|
||||
|
||||
/**
|
||||
* 套题类型
|
||||
*/
|
||||
private Integer setType;
|
||||
|
||||
/**
|
||||
* 大类id
|
||||
*/
|
||||
private Long primaryCategoryId;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer limitCount;
|
||||
|
||||
/**
|
||||
* 排序类型 1默认 2最新 3最热
|
||||
*/
|
||||
private Integer orderType;
|
||||
|
||||
/**
|
||||
* 套题名称
|
||||
*/
|
||||
private String setName;
|
||||
|
||||
/**
|
||||
* 分页信息
|
||||
*/
|
||||
private PageInfo pageInfo;
|
||||
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.landaiqing.practice.server.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PracticeSubjectDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 分类与标签组合的ids
|
||||
*/
|
||||
private List<String> assembleIds;
|
||||
|
||||
/**
|
||||
* 题目类型
|
||||
*/
|
||||
private Integer subjectType;
|
||||
|
||||
/**
|
||||
* 题目数量
|
||||
*/
|
||||
private Integer subjectCount;
|
||||
|
||||
/**
|
||||
* 要排除的题目id
|
||||
*/
|
||||
private List<Long> excludeSubjectIds;
|
||||
/**
|
||||
* 题目类型
|
||||
*/
|
||||
private Long subjectId;
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package com.landaiqing.practice.server.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SubjectDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long subjectId;
|
||||
|
||||
/**
|
||||
* 题目名称
|
||||
*/
|
||||
private String subjectName;
|
||||
|
||||
/**
|
||||
* 题目类型
|
||||
*/
|
||||
private Integer subjectType;
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package com.landaiqing.practice.server.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SubjectDetailDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 题目名称
|
||||
*/
|
||||
private String subjectName;
|
||||
|
||||
/**
|
||||
* 判断题答案
|
||||
*/
|
||||
private Integer isCorrect;
|
||||
|
||||
/**
|
||||
* 题目解析
|
||||
*/
|
||||
private String subjectParse;
|
||||
|
||||
/**
|
||||
* 单选、多选、判断题目答案
|
||||
*/
|
||||
private List<SubjectOptionDTO> optionList;
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package com.landaiqing.practice.server.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SubjectOptionDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 答案类型
|
||||
*/
|
||||
private Integer optionType;
|
||||
|
||||
/**
|
||||
* 答案内容
|
||||
*/
|
||||
private String optionContent;
|
||||
|
||||
/**
|
||||
* 是否为正确答案
|
||||
*/
|
||||
private Integer isCorrect;
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package com.landaiqing.practice.server.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserInfo {
|
||||
|
||||
private String userName;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String avatar;
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Classname PrimaryCategoryPO
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.practice.server.entity.po
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-12 17:52
|
||||
* @Description: TODO
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class CategoryPO {
|
||||
private Long id;
|
||||
|
||||
private String categoryName;
|
||||
private Integer categoryType;
|
||||
|
||||
private Long parentId;
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Classname PrimaryCategoryPO
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.practice.server.entity.po
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-12 17:52
|
||||
* @Description: TODO
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class LabelCountPO {
|
||||
private Long labelId;
|
||||
private Integer count;
|
||||
|
||||
private String labelName;
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class PracticeDetailPO implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 练题id
|
||||
*/
|
||||
private Long practiceId;
|
||||
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long subjectId;
|
||||
|
||||
/**
|
||||
* 题目类型
|
||||
*/
|
||||
private Integer subjectType;
|
||||
|
||||
/**
|
||||
* 是否正确 1正确 0错误
|
||||
*/
|
||||
private Integer answerStatus;
|
||||
|
||||
/**
|
||||
* 答案内容
|
||||
*/
|
||||
private String answerContent;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class PracticePO implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 套题id
|
||||
*/
|
||||
private Long setId;
|
||||
|
||||
/**
|
||||
* 完成情况 1完成 0未完成
|
||||
*/
|
||||
private Integer completeStatus;
|
||||
|
||||
/**
|
||||
* 所用时间
|
||||
*/
|
||||
private String timeUse;
|
||||
|
||||
/**
|
||||
* 交卷时间
|
||||
*/
|
||||
private Date submitTime;
|
||||
|
||||
/**
|
||||
* 正确率
|
||||
*/
|
||||
private BigDecimal correctRate;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class PracticeRankPO implements Serializable {
|
||||
|
||||
/**
|
||||
* 练习数量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class PracticeSetDetailPO implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 套题id
|
||||
*/
|
||||
private Long setId;
|
||||
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long subjectId;
|
||||
|
||||
/**
|
||||
* 题目类型
|
||||
*/
|
||||
private Integer subjectType;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
private Integer isDeleted;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class PracticeSetPO implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 套题名称
|
||||
*/
|
||||
private String setName;
|
||||
|
||||
/**
|
||||
* 1实时生成 2预设套题
|
||||
*/
|
||||
private Integer setType;
|
||||
|
||||
/**
|
||||
* 套题热度
|
||||
*/
|
||||
private Integer setHeat;
|
||||
|
||||
/**
|
||||
* 套题描述
|
||||
*/
|
||||
private String setDesc;
|
||||
|
||||
/**
|
||||
* 大类id
|
||||
*/
|
||||
private Long primaryCategoryId;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
private Integer isDeleted;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Classname PrimaryCategoryPO
|
||||
* @BelongsProject: qing-yu-club
|
||||
* @BelongsPackage: com.landaiqing.practice.server.entity.po
|
||||
* @Author: landaiqing
|
||||
* @CreateTime: 2024-03-12 17:52
|
||||
* @Description: TODO
|
||||
* @Version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class PrimaryCategoryPO {
|
||||
private Long id;
|
||||
|
||||
private String categoryName;
|
||||
private Integer categoryType;
|
||||
|
||||
private Long parentId;
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SubjectJudgePO implements Serializable {
|
||||
private static final long serialVersionUID = 725783721496341698L;
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long subjectId;
|
||||
/**
|
||||
* 是否正确
|
||||
*/
|
||||
private Integer isCorrect;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 题目标签表(SubjectLabel)实体类
|
||||
*
|
||||
* @author landaiqing
|
||||
* @since 2024-02-14 17:08:06
|
||||
*/
|
||||
@Data
|
||||
public class SubjectLabelPO implements Serializable {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 标签分类
|
||||
*/
|
||||
private String labelName;
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
private Integer sortNum;
|
||||
|
||||
private Long categoryId;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,47 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SubjectMappingPO implements Serializable {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long subjectId;
|
||||
/**
|
||||
* 分类id
|
||||
*/
|
||||
private Long categoryId;
|
||||
/**
|
||||
* 标签id
|
||||
*/
|
||||
private Long labelId;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 修改时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
private Integer isDeleted;
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SubjectMultiplePO implements Serializable {
|
||||
private static final long serialVersionUID = 575755837160743772L;
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long subjectId;
|
||||
/**
|
||||
* 选项类型
|
||||
*/
|
||||
private Integer optionType;
|
||||
/**
|
||||
* 选项内容
|
||||
*/
|
||||
private String optionContent;
|
||||
/**
|
||||
* 是否正确
|
||||
*/
|
||||
private Integer isCorrect;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
private Integer isDeleted;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class SubjectPO implements Serializable {
|
||||
|
||||
/**
|
||||
* 题目id/主键
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* es的文档id
|
||||
*/
|
||||
private Long docId;
|
||||
|
||||
/**
|
||||
* 题目名称
|
||||
*/
|
||||
private String subjectName;
|
||||
|
||||
/**
|
||||
* 题目答案
|
||||
*/
|
||||
private String subjectAnswer;
|
||||
|
||||
/**
|
||||
* 题目难度 DifficultyTypeEnum
|
||||
*/
|
||||
private Integer difficulty;
|
||||
|
||||
/**
|
||||
* 出题人erp
|
||||
*/
|
||||
private String setterErp;
|
||||
|
||||
/**
|
||||
* 出题人姓名
|
||||
*/
|
||||
private String setterName;
|
||||
|
||||
/**
|
||||
* 是否推送
|
||||
*/
|
||||
private Integer isPush;
|
||||
|
||||
/**
|
||||
* 题目类型
|
||||
*/
|
||||
private Integer subjectType;
|
||||
|
||||
/**
|
||||
* 题目分数
|
||||
*/
|
||||
private Integer subjectScore;
|
||||
|
||||
/**
|
||||
* 题目解析
|
||||
*/
|
||||
private String subjectParse;
|
||||
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
package com.landaiqing.practice.server.entity.po;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class SubjectRadioPO implements Serializable {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 题目id
|
||||
*/
|
||||
private Long subjectId;
|
||||
/**
|
||||
* a,b,c,d
|
||||
*/
|
||||
private Integer optionType;
|
||||
/**
|
||||
* 选项内容
|
||||
*/
|
||||
private String optionContent;
|
||||
/**
|
||||
* 是否正确
|
||||
*/
|
||||
private Integer isCorrect;
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createdBy;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createdTime;
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
private Integer isDeleted;
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package com.landaiqing.practice.server.rpc;
|
||||
|
||||
import com.landaiqing.auth.api.UserFeignService;
|
||||
import com.landaiqing.auth.entity.AuthUserDTO;
|
||||
import com.landaiqing.auth.entity.Result;
|
||||
import com.landaiqing.practice.server.entity.dto.UserInfo;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Component
|
||||
public class UserRpc {
|
||||
|
||||
@Resource
|
||||
private UserFeignService userFeignService;
|
||||
|
||||
public UserInfo getUserInfo(String userName) {
|
||||
AuthUserDTO authUserDTO = new AuthUserDTO();
|
||||
authUserDTO.setUserName(userName);
|
||||
Result<AuthUserDTO> result = userFeignService.getUserInfo(authUserDTO);
|
||||
UserInfo userInfo = new UserInfo();
|
||||
if (!result.getSuccess()) {
|
||||
return userInfo;
|
||||
}
|
||||
AuthUserDTO data = result.getData();
|
||||
userInfo.setUserName(data.getUserName());
|
||||
userInfo.setNickName(data.getNickName());
|
||||
userInfo.setAvatar(data.getAvatar());
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package com.landaiqing.practice.server.service;
|
||||
|
||||
import com.landaiqing.practice.api.req.*;
|
||||
import com.landaiqing.practice.api.vo.RankVO;
|
||||
import com.landaiqing.practice.api.vo.ReportVO;
|
||||
import com.landaiqing.practice.api.vo.ScoreDetailVO;
|
||||
import com.landaiqing.practice.api.vo.SubjectDetailVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PracticeDetailService {
|
||||
|
||||
/**
|
||||
* 练习提交题目
|
||||
*/
|
||||
Boolean submitSubject(SubmitSubjectDetailReq req);
|
||||
|
||||
/**
|
||||
* 提交练题情况
|
||||
*/
|
||||
Boolean submit(SubmitPracticeDetailReq req);
|
||||
|
||||
/**
|
||||
* 每题得分详情
|
||||
*/
|
||||
List<ScoreDetailVO> getScoreDetail(GetScoreDetailReq req);
|
||||
|
||||
/**
|
||||
* 获得答案详情
|
||||
*/
|
||||
SubjectDetailVO getSubjectDetail(GetSubjectDetailReq req);
|
||||
|
||||
/**
|
||||
* 答案解析-评估报告
|
||||
*/
|
||||
ReportVO getReport(GetReportReq req);
|
||||
|
||||
/**
|
||||
* 练习榜
|
||||
*/
|
||||
List<RankVO> getPracticeRankList();
|
||||
|
||||
/**
|
||||
* 放弃练习
|
||||
*/
|
||||
Boolean giveUp(Long practiceId);
|
||||
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package com.landaiqing.practice.server.service;
|
||||
|
||||
import com.landaiqing.practice.api.common.PageResult;
|
||||
import com.landaiqing.practice.api.req.GetPracticeSubjectsReq;
|
||||
import com.landaiqing.practice.api.req.GetUnCompletePracticeReq;
|
||||
import com.landaiqing.practice.api.vo.*;
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSetDTO;
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSubjectDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PracticeSetService {
|
||||
/**
|
||||
* 获取专项练习内容
|
||||
*/
|
||||
List<SpecialPracticeVO> getSpecialPracticeContent();
|
||||
|
||||
/**
|
||||
* 开始练习
|
||||
*/
|
||||
PracticeSetVO addPractice(PracticeSubjectDTO dto);
|
||||
|
||||
/**
|
||||
* 获取练习题
|
||||
*/
|
||||
PracticeSubjectListVO getSubjects(GetPracticeSubjectsReq req);
|
||||
|
||||
/**
|
||||
* 获取题目
|
||||
*/
|
||||
PracticeSubjectVO getPracticeSubject(PracticeSubjectDTO dto);
|
||||
|
||||
/**
|
||||
* 获取模拟套题内容
|
||||
*/
|
||||
PageResult<PracticeSetVO> getPreSetContent(PracticeSetDTO dto);
|
||||
|
||||
/**
|
||||
* 获取未完成练习内容
|
||||
*/
|
||||
PageResult<UnCompletePracticeSetVO> getUnCompletePractice(GetUnCompletePracticeReq req);
|
||||
|
||||
}
|
@@ -0,0 +1,400 @@
|
||||
package com.landaiqing.practice.server.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.landaiqing.practice.api.enums.*;
|
||||
import com.landaiqing.practice.api.req.*;
|
||||
import com.landaiqing.practice.api.vo.*;
|
||||
import com.landaiqing.practice.server.dao.*;
|
||||
import com.landaiqing.practice.server.entity.dto.*;
|
||||
import com.landaiqing.practice.server.entity.po.*;
|
||||
import com.landaiqing.practice.server.rpc.UserRpc;
|
||||
import com.landaiqing.practice.server.service.PracticeDetailService;
|
||||
import com.landaiqing.practice.server.util.DateUtils;
|
||||
import com.landaiqing.practice.server.util.LoginUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PracticeDetailServiceImpl implements PracticeDetailService {
|
||||
|
||||
@Resource
|
||||
private PracticeDetailDao practiceDetailDao;
|
||||
|
||||
@Resource
|
||||
private PracticeSetDao practiceSetDao;
|
||||
|
||||
@Resource
|
||||
private PracticeSetDetailDao practiceSetDetailDao;
|
||||
|
||||
@Resource
|
||||
private PracticeDao practiceDao;
|
||||
|
||||
@Resource
|
||||
private SubjectDao subjectDao;
|
||||
|
||||
@Resource
|
||||
private SubjectRadioDao subjectRadioDao;
|
||||
|
||||
@Resource
|
||||
private SubjectMultipleDao subjectMultipleDao;
|
||||
|
||||
@Resource
|
||||
private SubjectJudgeDao subjectJudgeDao;
|
||||
|
||||
@Resource
|
||||
private SubjectMappingDao subjectMappingDao;
|
||||
|
||||
@Resource
|
||||
private SubjectLabelDao subjectLabelDao;
|
||||
|
||||
@Resource
|
||||
private UserRpc userRpc;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
|
||||
public Boolean submit(SubmitPracticeDetailReq req) {
|
||||
PracticePO practicePO = new PracticePO();
|
||||
Long practiceId = req.getPracticeId();
|
||||
Long setId = req.getSetId();
|
||||
practicePO.setSetId(setId);
|
||||
String timeUse = req.getTimeUse();
|
||||
String hour = timeUse.substring(0, 2);
|
||||
String minute = timeUse.substring(2, 4);
|
||||
String second = timeUse.substring(4, 6);
|
||||
practicePO.setTimeUse(hour + ":" + minute + ":" + second);
|
||||
practicePO.setSubmitTime(DateUtils.parseStrToDate(req.getSubmitTime()));
|
||||
practicePO.setCompleteStatus(CompleteStatusEnum.COMPLETE.getCode());
|
||||
practicePO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
|
||||
practicePO.setCreatedBy(LoginUtil.getLoginId());
|
||||
practicePO.setCreatedTime(new Date());
|
||||
//计算正确率
|
||||
Integer correctCount = practiceDetailDao.selectCorrectCount(practiceId);
|
||||
List<PracticeSetDetailPO> practiceSetDetailPOS = practiceSetDetailDao.selectBySetId(setId);
|
||||
Integer totalCount = practiceSetDetailPOS.size();
|
||||
BigDecimal correctRate = new BigDecimal(correctCount).divide(new BigDecimal(totalCount), 4, BigDecimal.ROUND_HALF_UP)
|
||||
.multiply(new BigDecimal("100.00"));
|
||||
practicePO.setCorrectRate(correctRate);
|
||||
PracticePO po = practiceDao.selectById(practiceId);
|
||||
if (Objects.isNull(po)) {
|
||||
practiceDao.insert(practicePO);
|
||||
} else {
|
||||
practicePO.setId(practiceId);
|
||||
practiceDao.update(practicePO);
|
||||
}
|
||||
practiceSetDao.updateHeat(setId);
|
||||
//补充剩余题目的记录
|
||||
List<PracticeDetailPO> practiceDetailPOList = practiceDetailDao.selectByPracticeId(practiceId);
|
||||
List<PracticeSetDetailPO> minusList = practiceSetDetailPOS.stream()
|
||||
.filter(item -> !practiceDetailPOList.stream()
|
||||
.map(e -> e.getSubjectId())
|
||||
.collect(Collectors.toList())
|
||||
.contains(item.getSubjectId()))
|
||||
.collect(Collectors.toList());
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("题目差集{}", JSON.toJSONString(minusList));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(minusList)) {
|
||||
minusList.forEach(e -> {
|
||||
PracticeDetailPO practiceDetailPO = new PracticeDetailPO();
|
||||
practiceDetailPO.setPracticeId(practiceId);
|
||||
practiceDetailPO.setSubjectType(e.getSubjectType());
|
||||
practiceDetailPO.setSubjectId(e.getSubjectId());
|
||||
practiceDetailPO.setAnswerStatus(0);
|
||||
practiceDetailPO.setAnswerContent("");
|
||||
practiceDetailPO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
|
||||
practiceDetailPO.setCreatedTime(new Date());
|
||||
practiceDetailPO.setCreatedBy(LoginUtil.getLoginId());
|
||||
practiceDetailDao.insertSingle(practiceDetailPO);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean submitSubject(SubmitSubjectDetailReq req) {
|
||||
String timeUse = req.getTimeUse();
|
||||
if (timeUse.equals("0")) {
|
||||
timeUse = "000000";
|
||||
}
|
||||
String hour = timeUse.substring(0, 2);
|
||||
String minute = timeUse.substring(2, 4);
|
||||
String second = timeUse.substring(4, 6);
|
||||
PracticePO practicePO = new PracticePO();
|
||||
practicePO.setId(req.getPracticeId());
|
||||
practicePO.setTimeUse(hour + ":" + minute + ":" + second);
|
||||
practicePO.setSubmitTime(new Date());
|
||||
practiceDao.update(practicePO);
|
||||
|
||||
PracticeDetailPO practiceDetailPO = new PracticeDetailPO();
|
||||
practiceDetailPO.setPracticeId(req.getPracticeId());
|
||||
practiceDetailPO.setSubjectId(req.getSubjectId());
|
||||
practiceDetailPO.setSubjectType(req.getSubjectType());
|
||||
String answerContent = "";
|
||||
//排序答案
|
||||
if (CollectionUtils.isNotEmpty(req.getAnswerContents())) {
|
||||
List<Integer> answerContents = req.getAnswerContents();
|
||||
Collections.sort(answerContents);
|
||||
answerContent = StringUtils.join(answerContents, ",");
|
||||
}
|
||||
practiceDetailPO.setAnswerContent(answerContent);
|
||||
SubjectDTO subjectDTO = new SubjectDTO();
|
||||
subjectDTO.setSubjectId(req.getSubjectId());
|
||||
subjectDTO.setSubjectType(req.getSubjectType());
|
||||
//获取正确答案,并判断答案是否正确
|
||||
SubjectDetailDTO subjectDetail = getSubjectDetail(subjectDTO);
|
||||
StringBuffer correctAnswer = new StringBuffer();
|
||||
if (req.getSubjectType().equals(SubjectInfoTypeEnum.JUDGE.getCode())) {
|
||||
Integer isCorrect = subjectDetail.getIsCorrect();
|
||||
correctAnswer.append(isCorrect);
|
||||
} else {
|
||||
subjectDetail.getOptionList().forEach(e -> {
|
||||
if (Objects.equals(e.getIsCorrect(), 1)) {
|
||||
correctAnswer.append(e.getOptionType()).append(",");
|
||||
}
|
||||
});
|
||||
if (correctAnswer.length() > 0) {
|
||||
correctAnswer.deleteCharAt(correctAnswer.length() - 1);
|
||||
}
|
||||
}
|
||||
if (Objects.equals(correctAnswer.toString(), answerContent)) {
|
||||
practiceDetailPO.setAnswerStatus(1);
|
||||
} else {
|
||||
practiceDetailPO.setAnswerStatus(0);
|
||||
}
|
||||
practiceDetailPO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
|
||||
practiceDetailPO.setCreatedBy(LoginUtil.getLoginId());
|
||||
practiceDetailPO.setCreatedTime(new Date());
|
||||
PracticeDetailPO existDetail = practiceDetailDao.selectDetail(req.getPracticeId(), req.getSubjectId(), LoginUtil.getLoginId());
|
||||
if (Objects.isNull(existDetail)) {
|
||||
practiceDetailDao.insertSingle(practiceDetailPO);
|
||||
} else {
|
||||
practiceDetailPO.setId(existDetail.getId());
|
||||
practiceDetailDao.update(practiceDetailPO);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public SubjectDetailDTO getSubjectDetail(SubjectDTO dto) {
|
||||
SubjectDetailDTO subjectDetailDTO = new SubjectDetailDTO();
|
||||
SubjectPO subjectPO = subjectDao.selectById(dto.getSubjectId());
|
||||
if (dto.getSubjectType() == SubjectInfoTypeEnum.RADIO.getCode()) {
|
||||
List<SubjectOptionDTO> optionList = new LinkedList<>();
|
||||
List<SubjectRadioPO> radioSubjectPOS = subjectRadioDao.selectBySubjectId(subjectPO.getId());
|
||||
radioSubjectPOS.forEach(e -> {
|
||||
SubjectOptionDTO subjectOptionDTO = new SubjectOptionDTO();
|
||||
subjectOptionDTO.setOptionContent(e.getOptionContent());
|
||||
subjectOptionDTO.setOptionType(e.getOptionType());
|
||||
subjectOptionDTO.setIsCorrect(e.getIsCorrect());
|
||||
optionList.add(subjectOptionDTO);
|
||||
});
|
||||
subjectDetailDTO.setOptionList(optionList);
|
||||
}
|
||||
if (dto.getSubjectType() == SubjectInfoTypeEnum.MULTIPLE.getCode()) {
|
||||
List<SubjectOptionDTO> optionList = new LinkedList<>();
|
||||
List<SubjectMultiplePO> multipleSubjectPOS = subjectMultipleDao.selectBySubjectId(subjectPO.getId());
|
||||
multipleSubjectPOS.forEach(e -> {
|
||||
SubjectOptionDTO subjectOptionDTO = new SubjectOptionDTO();
|
||||
subjectOptionDTO.setOptionContent(e.getOptionContent());
|
||||
subjectOptionDTO.setOptionType(e.getOptionType());
|
||||
subjectOptionDTO.setIsCorrect(e.getIsCorrect());
|
||||
optionList.add(subjectOptionDTO);
|
||||
});
|
||||
subjectDetailDTO.setOptionList(optionList);
|
||||
}
|
||||
if (dto.getSubjectType() == SubjectInfoTypeEnum.JUDGE.getCode()) {
|
||||
SubjectJudgePO judgeSubjectPO = subjectJudgeDao.selectBySubjectId(subjectPO.getId());
|
||||
subjectDetailDTO.setIsCorrect(judgeSubjectPO.getIsCorrect());
|
||||
}
|
||||
subjectDetailDTO.setSubjectParse(subjectPO.getSubjectParse());
|
||||
subjectDetailDTO.setSubjectName(subjectPO.getSubjectName());
|
||||
return subjectDetailDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ScoreDetailVO> getScoreDetail(GetScoreDetailReq req) {
|
||||
Long practiceId = req.getPracticeId();
|
||||
List<ScoreDetailVO> list = new LinkedList<>();
|
||||
List<PracticeDetailPO> practiceDetailPOList = practiceDetailDao.selectByPracticeId(practiceId);
|
||||
if (CollectionUtils.isEmpty(practiceDetailPOList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
practiceDetailPOList.forEach(po -> {
|
||||
ScoreDetailVO scoreDetailVO = new ScoreDetailVO();
|
||||
scoreDetailVO.setSubjectId(po.getSubjectId());
|
||||
scoreDetailVO.setSubjectType(po.getSubjectType());
|
||||
scoreDetailVO.setIsCorrect(po.getAnswerStatus());
|
||||
list.add(scoreDetailVO);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubjectDetailVO getSubjectDetail(GetSubjectDetailReq req) {
|
||||
SubjectDetailVO subjectDetailVO = new SubjectDetailVO();
|
||||
Long subjectId = req.getSubjectId();
|
||||
Integer subjectType = req.getSubjectType();
|
||||
SubjectDTO subjectDTO = new SubjectDTO();
|
||||
subjectDTO.setSubjectId(subjectId);
|
||||
subjectDTO.setSubjectType(subjectType);
|
||||
SubjectDetailDTO subjectDetail = getSubjectDetail(subjectDTO);
|
||||
List<SubjectOptionDTO> optionList = subjectDetail.getOptionList();
|
||||
List<PracticeSubjectOptionVO> optionVOList = new LinkedList<>();
|
||||
List<Integer> correctAnswer = new LinkedList<>();
|
||||
if (CollectionUtils.isNotEmpty(optionList)) {
|
||||
optionList.forEach(option -> {
|
||||
PracticeSubjectOptionVO optionVO = new PracticeSubjectOptionVO();
|
||||
optionVO.setOptionType(option.getOptionType());
|
||||
optionVO.setOptionContent(option.getOptionContent());
|
||||
optionVO.setIsCorrect(option.getIsCorrect());
|
||||
optionVOList.add(optionVO);
|
||||
if (option.getIsCorrect() == 1) {
|
||||
correctAnswer.add(option.getOptionType());
|
||||
}
|
||||
});
|
||||
}
|
||||
if (subjectType.equals(SubjectInfoTypeEnum.JUDGE.getCode())) {
|
||||
Integer isCorrect = subjectDetail.getIsCorrect();
|
||||
PracticeSubjectOptionVO correctOption = new PracticeSubjectOptionVO();
|
||||
correctOption.setOptionType(1);
|
||||
correctOption.setOptionContent("正确");
|
||||
correctOption.setIsCorrect(isCorrect == 1 ? 1 : 0);
|
||||
PracticeSubjectOptionVO errorOptionVO = new PracticeSubjectOptionVO();
|
||||
errorOptionVO.setOptionType(2);
|
||||
errorOptionVO.setOptionContent("错误");
|
||||
errorOptionVO.setIsCorrect(isCorrect == 0 ? 1 : 0);
|
||||
optionVOList.add(correctOption);
|
||||
optionVOList.add(errorOptionVO);
|
||||
correctAnswer.add(subjectDetail.getIsCorrect());
|
||||
}
|
||||
subjectDetailVO.setOptionList(optionVOList);
|
||||
subjectDetailVO.setSubjectParse(subjectDetail.getSubjectParse());
|
||||
subjectDetailVO.setSubjectName(subjectDetail.getSubjectName());
|
||||
subjectDetailVO.setCorrectAnswer(correctAnswer);
|
||||
//自己的答题答案
|
||||
List<Integer> respondAnswer = new LinkedList<>();
|
||||
PracticeDetailPO practiceDetailPO = practiceDetailDao.selectAnswer(req.getPracticeId(), subjectId);
|
||||
String answerContent = practiceDetailPO.getAnswerContent();
|
||||
if (StringUtils.isNotBlank(answerContent)) {
|
||||
String[] split = answerContent.split(",");
|
||||
for (String s : split) {
|
||||
respondAnswer.add(Integer.valueOf(s));
|
||||
}
|
||||
}
|
||||
subjectDetailVO.setRespondAnswer(respondAnswer);
|
||||
List<SubjectMappingPO> subjectMappingPOList = subjectMappingDao.getLabelIdsBySubjectId(subjectId);
|
||||
List<Long> labelIdList = new LinkedList<>();
|
||||
subjectMappingPOList.forEach(subjectMappingPO -> {
|
||||
labelIdList.add(subjectMappingPO.getLabelId());
|
||||
});
|
||||
List<String> labelNameList = subjectLabelDao.getLabelNameByIds(labelIdList);
|
||||
subjectDetailVO.setLabelNames(labelNameList);
|
||||
return subjectDetailVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportVO getReport(GetReportReq req) {
|
||||
ReportVO reportVO = new ReportVO();
|
||||
Long practiceId = req.getPracticeId();
|
||||
PracticePO practicePO = practiceDao.selectById(practiceId);
|
||||
Long setId = practicePO.getSetId();
|
||||
PracticeSetPO practiceSetPO = practiceSetDao.selectById(setId);
|
||||
reportVO.setTitle(practiceSetPO.getSetName());
|
||||
List<PracticeDetailPO> practiceDetailPOList = practiceDetailDao.selectByPracticeId(practiceId);
|
||||
if (CollectionUtils.isEmpty(practiceDetailPOList)) {
|
||||
return null;
|
||||
}
|
||||
int totalCount = practiceDetailPOList.size();
|
||||
List<PracticeDetailPO> correctPoList = practiceDetailPOList.stream().filter(e ->
|
||||
Objects.equals(e.getAnswerStatus(), AnswerStatusEnum.CORRECT.getCode())).collect(Collectors.toList());
|
||||
reportVO.setCorrectSubject(correctPoList.size() + "/" + totalCount);
|
||||
List<ReportSkillVO> reportSkillVOS = new LinkedList<>();
|
||||
Map<Long, Integer> totalMap = getSubjectLabelMap(practiceDetailPOList);
|
||||
Map<Long, Integer> correctMap = getSubjectLabelMap(correctPoList);
|
||||
totalMap.forEach((key, val) -> {
|
||||
ReportSkillVO skillVO = new ReportSkillVO();
|
||||
SubjectLabelPO labelPO = subjectLabelDao.queryById(key);
|
||||
String labelName = labelPO.getLabelName();
|
||||
Integer correctCount = correctMap.get(key);
|
||||
if (Objects.isNull(correctCount)) {
|
||||
correctCount = 0;
|
||||
}
|
||||
skillVO.setName(labelName);
|
||||
BigDecimal rate = BigDecimal.ZERO;
|
||||
if (!Objects.equals(val, 0)) {
|
||||
rate = new BigDecimal(correctCount.toString()).divide(new BigDecimal(val.toString()), 4,
|
||||
BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
|
||||
}
|
||||
skillVO.setStar(rate);
|
||||
reportSkillVOS.add(skillVO);
|
||||
});
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取到的正确率{}", JSON.toJSONString(reportSkillVOS));
|
||||
}
|
||||
reportVO.setSkill(reportSkillVOS);
|
||||
return reportVO;
|
||||
}
|
||||
|
||||
|
||||
private Map<Long, Integer> getSubjectLabelMap(List<PracticeDetailPO> practiceDetailPOList) {
|
||||
if (CollectionUtils.isEmpty(practiceDetailPOList)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<Long, Integer> map = new HashMap<>();
|
||||
practiceDetailPOList.forEach(detail -> {
|
||||
Long subjectId = detail.getSubjectId();
|
||||
List<SubjectMappingPO> labelIdPO = subjectMappingDao.getLabelIdsBySubjectId(subjectId);
|
||||
labelIdPO.forEach(po -> {
|
||||
Long labelId = po.getLabelId();
|
||||
if (Objects.isNull(map.get(labelId))) {
|
||||
map.put(labelId, 1);
|
||||
return;
|
||||
}
|
||||
map.put(labelId, map.get(labelId) + 1);
|
||||
});
|
||||
});
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取到的题目对应的标签map{}", JSON.toJSONString(map));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RankVO> getPracticeRankList() {
|
||||
List<RankVO> list = new LinkedList<>();
|
||||
List<PracticeRankPO> poList = practiceDetailDao.getPracticeCount();
|
||||
if (CollectionUtils.isEmpty(poList)) {
|
||||
return list;
|
||||
}
|
||||
poList.forEach(e -> {
|
||||
RankVO rankVO = new RankVO();
|
||||
rankVO.setCount(e.getCount());
|
||||
UserInfo userInfo = userRpc.getUserInfo(e.getCreatedBy());
|
||||
rankVO.setName(userInfo.getNickName());
|
||||
rankVO.setAvatar(userInfo.getAvatar());
|
||||
list.add(rankVO);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean giveUp(Long practiceId) {
|
||||
practiceDetailDao.deleteByPracticeId(practiceId);
|
||||
practiceDao.deleteById(practiceId);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,394 @@
|
||||
package com.landaiqing.practice.server.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.landaiqing.practice.api.common.PageInfo;
|
||||
import com.landaiqing.practice.api.common.PageResult;
|
||||
import com.landaiqing.practice.api.enums.CompleteStatusEnum;
|
||||
import com.landaiqing.practice.api.enums.IsDeletedFlagEnum;
|
||||
import com.landaiqing.practice.api.enums.SubjectInfoTypeEnum;
|
||||
import com.landaiqing.practice.api.req.GetPracticeSubjectsReq;
|
||||
import com.landaiqing.practice.api.req.GetUnCompletePracticeReq;
|
||||
import com.landaiqing.practice.api.vo.*;
|
||||
import com.landaiqing.practice.server.dao.*;
|
||||
import com.landaiqing.practice.server.entity.dto.CategoryDTO;
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSetDTO;
|
||||
import com.landaiqing.practice.server.entity.dto.PracticeSubjectDTO;
|
||||
import com.landaiqing.practice.server.entity.po.*;
|
||||
import com.landaiqing.practice.server.service.PracticeSetService;
|
||||
import com.landaiqing.practice.server.util.DateUtils;
|
||||
import com.landaiqing.practice.server.util.LoginUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PracticeSetServiceImpl implements PracticeSetService {
|
||||
|
||||
@Resource
|
||||
private SubjectCategoryDao subjectCategoryDao;
|
||||
|
||||
@Resource
|
||||
private SubjectMappingDao subjectMappingDao;
|
||||
|
||||
@Resource
|
||||
private SubjectLabelDao subjectLabelDao;
|
||||
|
||||
@Resource
|
||||
private PracticeSetDetailDao practiceSetDetailDao;
|
||||
|
||||
@Resource
|
||||
private PracticeSetDao practiceSetDao;
|
||||
|
||||
@Resource
|
||||
private SubjectDao subjectDao;
|
||||
|
||||
@Resource
|
||||
private PracticeDetailDao practiceDetailDao;
|
||||
|
||||
@Resource
|
||||
private PracticeDao practiceDao;
|
||||
|
||||
@Resource
|
||||
private SubjectRadioDao subjectRadioDao;
|
||||
|
||||
@Resource
|
||||
private SubjectMultipleDao subjectMultipleDao;
|
||||
|
||||
@Override
|
||||
public List<SpecialPracticeVO> getSpecialPracticeContent() {
|
||||
List<SpecialPracticeVO> specialPracticeVOList = new LinkedList<>();
|
||||
List<Integer> subjectTypeList = new LinkedList<>();
|
||||
subjectTypeList.add(SubjectInfoTypeEnum.RADIO.getCode());
|
||||
subjectTypeList.add(SubjectInfoTypeEnum.MULTIPLE.getCode());
|
||||
subjectTypeList.add(SubjectInfoTypeEnum.JUDGE.getCode());
|
||||
CategoryDTO categoryDTO = new CategoryDTO();
|
||||
categoryDTO.setSubjectTypeList(subjectTypeList);
|
||||
List<PrimaryCategoryPO> poList = subjectCategoryDao.getPrimaryCategory(categoryDTO);
|
||||
if (CollectionUtils.isEmpty(poList)) {
|
||||
return specialPracticeVOList;
|
||||
}
|
||||
poList.forEach(primaryCategoryPO -> {
|
||||
SpecialPracticeVO specialPracticeVO = new SpecialPracticeVO();
|
||||
specialPracticeVO.setPrimaryCategoryId(primaryCategoryPO.getParentId());
|
||||
CategoryPO categoryPO = subjectCategoryDao.selectById(primaryCategoryPO.getParentId());
|
||||
specialPracticeVO.setPrimaryCategoryName(categoryPO.getCategoryName());
|
||||
CategoryDTO categoryDTOTemp = new CategoryDTO();
|
||||
categoryDTOTemp.setCategoryType(2);
|
||||
categoryDTOTemp.setParentId(primaryCategoryPO.getParentId());
|
||||
List<CategoryPO> smallPoList = subjectCategoryDao.selectList(categoryDTOTemp);
|
||||
if (CollectionUtils.isEmpty(smallPoList)) {
|
||||
return;
|
||||
}
|
||||
List<SpecialPracticeCategoryVO> categoryList = new LinkedList();
|
||||
smallPoList.forEach(smallPo -> {
|
||||
List<SpecialPracticeLabelVO> labelVOList = getLabelVOList(smallPo.getId(), subjectTypeList);
|
||||
if (CollectionUtils.isEmpty(labelVOList)) {
|
||||
return;
|
||||
}
|
||||
SpecialPracticeCategoryVO specialPracticeCategoryVO = new SpecialPracticeCategoryVO();
|
||||
specialPracticeCategoryVO.setCategoryId(smallPo.getId());
|
||||
specialPracticeCategoryVO.setCategoryName(smallPo.getCategoryName());
|
||||
List<SpecialPracticeLabelVO> labelList = new LinkedList<>();
|
||||
labelVOList.forEach(labelVo -> {
|
||||
SpecialPracticeLabelVO specialPracticeLabelVO = new SpecialPracticeLabelVO();
|
||||
specialPracticeLabelVO.setId(labelVo.getId());
|
||||
specialPracticeLabelVO.setAssembleId(labelVo.getAssembleId());
|
||||
specialPracticeLabelVO.setLabelName(labelVo.getLabelName());
|
||||
labelList.add(specialPracticeLabelVO);
|
||||
});
|
||||
specialPracticeCategoryVO.setLabelList(labelList);
|
||||
categoryList.add(specialPracticeCategoryVO);
|
||||
});
|
||||
specialPracticeVO.setCategoryList(categoryList);
|
||||
specialPracticeVOList.add(specialPracticeVO);
|
||||
});
|
||||
return specialPracticeVOList;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public PracticeSetVO addPractice(PracticeSubjectDTO dto) {
|
||||
PracticeSetVO setVO = new PracticeSetVO();
|
||||
List<PracticeSubjectDetailVO> practiceList = getPracticeList(dto);
|
||||
if (CollectionUtils.isEmpty(practiceList)) {
|
||||
return setVO;
|
||||
}
|
||||
PracticeSetPO practiceSetPO = new PracticeSetPO();
|
||||
practiceSetPO.setSetType(1);
|
||||
List<String> assembleIds = dto.getAssembleIds();
|
||||
Set<Long> categoryIdSet = new HashSet<>();
|
||||
assembleIds.forEach(assembleId -> {
|
||||
Long categoryId = Long.valueOf(assembleId.split("-")[0]);
|
||||
categoryIdSet.add(categoryId);
|
||||
});
|
||||
StringBuffer setName = new StringBuffer();
|
||||
int i = 1;
|
||||
for (Long categoryId : categoryIdSet) {
|
||||
if (i > 2) {
|
||||
break;
|
||||
}
|
||||
CategoryPO categoryPO = subjectCategoryDao.selectById(categoryId);
|
||||
setName.append(categoryPO.getCategoryName());
|
||||
setName.append("、");
|
||||
i = i + 1;
|
||||
}
|
||||
setName.deleteCharAt(setName.length() - 1);
|
||||
if (i == 2) {
|
||||
setName.append("专项练习");
|
||||
} else {
|
||||
setName.append("等专项练习");
|
||||
}
|
||||
practiceSetPO.setSetName(setName.toString());
|
||||
String labelId = assembleIds.get(0).split("-")[1];
|
||||
SubjectLabelPO labelPO = subjectLabelDao.queryById(Long.valueOf(labelId));
|
||||
practiceSetPO.setPrimaryCategoryId(labelPO.getCategoryId());
|
||||
practiceSetPO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
|
||||
practiceSetPO.setCreatedBy(LoginUtil.getLoginId());
|
||||
practiceSetPO.setCreatedTime(new Date());
|
||||
practiceSetDao.add(practiceSetPO);
|
||||
Long practiceSetId = practiceSetPO.getId();
|
||||
|
||||
//思考,这里哪里不符合规范,配合听视频的延伸
|
||||
practiceList.forEach(e -> {
|
||||
PracticeSetDetailPO detailPO = new PracticeSetDetailPO();
|
||||
detailPO.setSetId(practiceSetId);
|
||||
detailPO.setSubjectId(e.getSubjectId());
|
||||
detailPO.setSubjectType(e.getSubjectType());
|
||||
detailPO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
|
||||
detailPO.setCreatedBy(LoginUtil.getLoginId());
|
||||
detailPO.setCreatedTime(new Date());
|
||||
practiceSetDetailDao.add(detailPO);
|
||||
});
|
||||
setVO.setSetId(practiceSetId);
|
||||
return setVO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取套卷题目信息
|
||||
*/
|
||||
private List<PracticeSubjectDetailVO> getPracticeList(PracticeSubjectDTO dto) {
|
||||
List<PracticeSubjectDetailVO> practiceSubjectListVOS = new LinkedList<>();
|
||||
//避免重复
|
||||
List<Long> excludeSubjectIds = new LinkedList<>();
|
||||
|
||||
//设置题目数量,之后优化到nacos动态配置
|
||||
Integer radioSubjectCount = 10;
|
||||
Integer multipleSubjectCount = 6;
|
||||
Integer judgeSubjectCount = 4;
|
||||
Integer totalSubjectCount = 20;
|
||||
//查询单选
|
||||
dto.setSubjectCount(radioSubjectCount);
|
||||
dto.setSubjectType(SubjectInfoTypeEnum.RADIO.getCode());
|
||||
assembleList(dto, practiceSubjectListVOS, excludeSubjectIds);
|
||||
//查询多选
|
||||
dto.setSubjectCount(multipleSubjectCount);
|
||||
dto.setSubjectType(SubjectInfoTypeEnum.MULTIPLE.getCode());
|
||||
assembleList(dto, practiceSubjectListVOS, excludeSubjectIds);
|
||||
//查询判断
|
||||
dto.setSubjectCount(judgeSubjectCount);
|
||||
dto.setSubjectType(SubjectInfoTypeEnum.JUDGE.getCode());
|
||||
assembleList(dto, practiceSubjectListVOS, excludeSubjectIds);
|
||||
//补充题目
|
||||
if (practiceSubjectListVOS.size() == totalSubjectCount) {
|
||||
return practiceSubjectListVOS;
|
||||
}
|
||||
Integer remainCount = totalSubjectCount - practiceSubjectListVOS.size();
|
||||
dto.setSubjectCount(remainCount);
|
||||
dto.setSubjectType(1);
|
||||
assembleList(dto, practiceSubjectListVOS, excludeSubjectIds);
|
||||
return practiceSubjectListVOS;
|
||||
}
|
||||
|
||||
private List<PracticeSubjectDetailVO> assembleList(PracticeSubjectDTO dto, List<PracticeSubjectDetailVO> list, List<Long> excludeSubjectIds) {
|
||||
dto.setExcludeSubjectIds(excludeSubjectIds);
|
||||
List<SubjectPO> subjectPOList = subjectDao.getPracticeSubject(dto);
|
||||
if (CollectionUtils.isEmpty(subjectPOList)) {
|
||||
return list;
|
||||
}
|
||||
subjectPOList.forEach(e -> {
|
||||
PracticeSubjectDetailVO vo = new PracticeSubjectDetailVO();
|
||||
vo.setSubjectId(e.getId());
|
||||
vo.setSubjectType(e.getSubjectType());
|
||||
excludeSubjectIds.add(e.getId());
|
||||
list.add(vo);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<SpecialPracticeLabelVO> getLabelVOList(Long categoryId, List<Integer> subjectTypeList) {
|
||||
List<LabelCountPO> countPOList = subjectMappingDao.getLabelSubjectCount(categoryId, subjectTypeList);
|
||||
if (CollectionUtils.isEmpty(countPOList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<SpecialPracticeLabelVO> voList = new LinkedList<>();
|
||||
countPOList.forEach(countPo -> {
|
||||
SpecialPracticeLabelVO vo = new SpecialPracticeLabelVO();
|
||||
vo.setId(countPo.getLabelId());
|
||||
vo.setAssembleId(categoryId + "-" + countPo.getLabelId());
|
||||
SubjectLabelPO subjectLabelPO = subjectLabelDao.queryById(countPo.getLabelId());
|
||||
vo.setLabelName(subjectLabelPO.getLabelName());
|
||||
voList.add(vo);
|
||||
});
|
||||
return voList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PracticeSubjectListVO getSubjects(GetPracticeSubjectsReq req) {
|
||||
Long setId = req.getSetId();
|
||||
PracticeSubjectListVO vo = new PracticeSubjectListVO();
|
||||
List<PracticeSubjectDetailVO> practiceSubjectListVOS = new LinkedList<>();
|
||||
List<PracticeSetDetailPO> practiceSetDetailPOS = practiceSetDetailDao.selectBySetId(setId);
|
||||
if (CollectionUtils.isEmpty(practiceSetDetailPOS)) {
|
||||
return vo;
|
||||
}
|
||||
String loginId = LoginUtil.getLoginId();
|
||||
Long practiceId = req.getPracticeId();
|
||||
practiceSetDetailPOS.forEach(e -> {
|
||||
PracticeSubjectDetailVO practiceSubjectListVO = new PracticeSubjectDetailVO();
|
||||
practiceSubjectListVO.setSubjectId(e.getSubjectId());
|
||||
practiceSubjectListVO.setSubjectType(e.getSubjectType());
|
||||
if (Objects.nonNull(practiceId)) {
|
||||
PracticeDetailPO practiceDetailPO = practiceDetailDao.selectDetail(practiceId, e.getSubjectId(), loginId);
|
||||
if (Objects.nonNull(practiceDetailPO) && StringUtils.isNotBlank(practiceDetailPO.getAnswerContent())) {
|
||||
practiceSubjectListVO.setIsAnswer(1);
|
||||
} else {
|
||||
practiceSubjectListVO.setIsAnswer(0);
|
||||
}
|
||||
}
|
||||
practiceSubjectListVOS.add(practiceSubjectListVO);
|
||||
});
|
||||
vo.setSubjectList(practiceSubjectListVOS);
|
||||
PracticeSetPO practiceSetPO = practiceSetDao.selectById(setId);
|
||||
vo.setTitle(practiceSetPO.getSetName());
|
||||
if (Objects.isNull(practiceId)) {
|
||||
Long newPracticeId = insertUnCompletePractice(setId);
|
||||
vo.setPracticeId(newPracticeId);
|
||||
} else {
|
||||
updateUnCompletePractice(practiceId);
|
||||
PracticePO practicePO = practiceDao.selectById(practiceId);
|
||||
vo.setTimeUse(practicePO.getTimeUse());
|
||||
vo.setPracticeId(practiceId);
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
private Long insertUnCompletePractice(Long practiceSetId) {
|
||||
PracticePO practicePO = new PracticePO();
|
||||
practicePO.setSetId(practiceSetId);
|
||||
practicePO.setCompleteStatus(CompleteStatusEnum.NO_COMPLETE.getCode());
|
||||
practicePO.setTimeUse("00:00:00");
|
||||
practicePO.setSubmitTime(new Date());
|
||||
practicePO.setCorrectRate(new BigDecimal("0.00"));
|
||||
practicePO.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
|
||||
practicePO.setCreatedBy(LoginUtil.getLoginId());
|
||||
practicePO.setCreatedTime(new Date());
|
||||
practiceDao.insert(practicePO);
|
||||
return practicePO.getId();
|
||||
}
|
||||
|
||||
private void updateUnCompletePractice(Long practiceId) {
|
||||
PracticePO practicePO = new PracticePO();
|
||||
practicePO.setId(practiceId);
|
||||
practicePO.setSubmitTime(new Date());
|
||||
practiceDao.update(practicePO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PracticeSubjectVO getPracticeSubject(PracticeSubjectDTO dto) {
|
||||
PracticeSubjectVO practiceSubjectVO = new PracticeSubjectVO();
|
||||
SubjectPO subjectPO = subjectDao.selectById(dto.getSubjectId());
|
||||
practiceSubjectVO.setSubjectName(subjectPO.getSubjectName());
|
||||
practiceSubjectVO.setSubjectType(subjectPO.getSubjectType());
|
||||
if (dto.getSubjectType() == SubjectInfoTypeEnum.RADIO.getCode()) {
|
||||
List<PracticeSubjectOptionVO> optionList = new LinkedList<>();
|
||||
List<SubjectRadioPO> radioSubjectPOS = subjectRadioDao.selectBySubjectId(subjectPO.getId());
|
||||
radioSubjectPOS.forEach(e -> {
|
||||
PracticeSubjectOptionVO practiceSubjectOptionVO = new PracticeSubjectOptionVO();
|
||||
practiceSubjectOptionVO.setOptionContent(e.getOptionContent());
|
||||
practiceSubjectOptionVO.setOptionType(e.getOptionType());
|
||||
optionList.add(practiceSubjectOptionVO);
|
||||
});
|
||||
practiceSubjectVO.setOptionList(optionList);
|
||||
}
|
||||
if (dto.getSubjectType() == SubjectInfoTypeEnum.MULTIPLE.getCode()) {
|
||||
List<PracticeSubjectOptionVO> optionList = new LinkedList<>();
|
||||
List<SubjectMultiplePO> multipleSubjectPOS = subjectMultipleDao.selectBySubjectId(subjectPO.getId());
|
||||
multipleSubjectPOS.forEach(e -> {
|
||||
PracticeSubjectOptionVO practiceSubjectOptionVO = new PracticeSubjectOptionVO();
|
||||
practiceSubjectOptionVO.setOptionContent(e.getOptionContent());
|
||||
practiceSubjectOptionVO.setOptionType(e.getOptionType());
|
||||
optionList.add(practiceSubjectOptionVO);
|
||||
});
|
||||
practiceSubjectVO.setOptionList(optionList);
|
||||
}
|
||||
return practiceSubjectVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<PracticeSetVO> getPreSetContent(PracticeSetDTO dto) {
|
||||
PageResult<PracticeSetVO> pageResult = new PageResult<>();
|
||||
PageInfo pageInfo = dto.getPageInfo();
|
||||
pageResult.setPageNo(pageInfo.getPageNo());
|
||||
pageResult.setPageSize(pageInfo.getPageSize());
|
||||
int start = (pageInfo.getPageNo() - 1) * pageInfo.getPageSize();
|
||||
Integer count = practiceSetDao.getListCount(dto);
|
||||
if (count == 0) {
|
||||
return pageResult;
|
||||
}
|
||||
List<PracticeSetPO> setPOList = practiceSetDao.getSetList(dto, start, dto.getPageInfo().getPageSize());
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取的模拟考卷列表{}", JSON.toJSONString(setPOList));
|
||||
}
|
||||
List<PracticeSetVO> list = new LinkedList<>();
|
||||
setPOList.forEach(e -> {
|
||||
PracticeSetVO vo = new PracticeSetVO();
|
||||
vo.setSetId(e.getId());
|
||||
vo.setSetName(e.getSetName());
|
||||
vo.setSetHeat(e.getSetHeat());
|
||||
vo.setSetDesc(e.getSetDesc());
|
||||
list.add(vo);
|
||||
});
|
||||
pageResult.setRecords(list);
|
||||
pageResult.setTotal(count);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<UnCompletePracticeSetVO> getUnCompletePractice(GetUnCompletePracticeReq req) {
|
||||
PageResult<UnCompletePracticeSetVO> pageResult = new PageResult<>();
|
||||
PageInfo pageInfo = req.getPageInfo();
|
||||
pageResult.setPageNo(pageInfo.getPageNo());
|
||||
pageResult.setPageSize(pageInfo.getPageSize());
|
||||
int start = (pageInfo.getPageNo() - 1) * pageInfo.getPageSize();
|
||||
String loginId = LoginUtil.getLoginId();
|
||||
Integer count = practiceDao.getUnCompleteCount(loginId);
|
||||
if (count == 0) {
|
||||
return pageResult;
|
||||
}
|
||||
List<PracticePO> poList = practiceDao.getUnCompleteList(loginId, start, req.getPageInfo().getPageSize());
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("获取未完成的考卷列表{}", JSON.toJSONString(poList));
|
||||
}
|
||||
List<UnCompletePracticeSetVO> list = new LinkedList<>();
|
||||
poList.forEach(e -> {
|
||||
UnCompletePracticeSetVO vo = new UnCompletePracticeSetVO();
|
||||
vo.setSetId(e.getSetId());
|
||||
vo.setPracticeId(e.getId());
|
||||
vo.setPracticeTime(DateUtils.format(e.getSubmitTime(), "yyyy-MM-dd"));
|
||||
PracticeSetPO practiceSetPO = practiceSetDao.selectById(e.getSetId());
|
||||
vo.setTitle(practiceSetPO.getSetName());
|
||||
list.add(vo);
|
||||
});
|
||||
pageResult.setRecords(list);
|
||||
pageResult.setTotal(count);
|
||||
return pageResult;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
存放service
|
@@ -0,0 +1,40 @@
|
||||
package com.landaiqing.practice.server.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
public class DateUtils {
|
||||
|
||||
/**
|
||||
* 字符串转时间
|
||||
*/
|
||||
public static Date parseStrToDate(String timestamp) {
|
||||
try {
|
||||
SimpleDateFormat sm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return sm.parse(timestamp);
|
||||
} catch (Exception e) {
|
||||
log.error("parseDate异常{}", timestamp, e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 日期格式化
|
||||
*/
|
||||
public static String format(Date date, String format) {
|
||||
try {
|
||||
if (date == null) {
|
||||
return null;
|
||||
}
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
||||
return sdf.format(date);
|
||||
} catch (Exception e) {
|
||||
log.error("日期格式化失败{}", e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package com.landaiqing.practice.server.util;
|
||||
|
||||
import com.alibaba.druid.filter.config.ConfigTools;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
||||
/**
|
||||
* 数据库加密util
|
||||
*
|
||||
* @author: landaiqing
|
||||
* @date: 2024/2/7
|
||||
*/
|
||||
public class DruidEncryptUtil {
|
||||
|
||||
private static String publicKey;
|
||||
|
||||
private static String privateKey;
|
||||
|
||||
static {
|
||||
try {
|
||||
String[] keyPair = ConfigTools.genKeyPair(512);
|
||||
privateKey=keyPair[0];
|
||||
System.out.println("privateKey:"+privateKey);
|
||||
publicKey=keyPair[1];
|
||||
System.out.println("publicKey:"+publicKey);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchProviderException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public static String encrypt(String plainText) throws Exception {
|
||||
String encrypt = ConfigTools.encrypt(privateKey, plainText);
|
||||
System.out.println("encrypt:"+encrypt);
|
||||
return encrypt;
|
||||
}
|
||||
public static String decrypt(String encryptText) throws Exception {
|
||||
String decrypt = ConfigTools.decrypt(publicKey, encryptText);
|
||||
System.out.println("decrypt:"+decrypt);
|
||||
return decrypt;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String encrypt = encrypt("$LDQ20020618xxx$");
|
||||
System.out.println("encrypt:"+encrypt);
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.landaiqing.practice.server.util;
|
||||
|
||||
import com.landaiqing.practice.server.config.context.LoginContextHolder;
|
||||
|
||||
/**
|
||||
* 用户登录util
|
||||
*
|
||||
* @author: ChickenWing
|
||||
* @date: 2023/11/26
|
||||
*/
|
||||
public class LoginUtil {
|
||||
|
||||
public static String getLoginId() {
|
||||
return LoginContextHolder.getLoginId();
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
server:
|
||||
port: 3012
|
||||
spring:
|
||||
datasource:
|
||||
username: landaiqing
|
||||
password: HvUtEzfJSLoCY8Oe+6BFhen8RM90h0Jmz/a8uHR/z90Ech1iksWHTeroWXjY+OZhsamVwDmJzPGJfKf2RiXFgA==
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://116.196.80.239:3306/qing-yu-club?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
druid:
|
||||
initial-size: 20
|
||||
min-idle: 20
|
||||
max-active: 100
|
||||
max-wait: 60000
|
||||
connectionProperties: config.decrypt=true;config.decrypt.key=${publicKey};
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
login-username: admin
|
||||
login-password: 123456
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
slow-sql-millis: 2000
|
||||
log-slow-sql: true
|
||||
wall:
|
||||
enabled: true
|
||||
config:
|
||||
enabled: true
|
||||
# redis配置
|
||||
redis:
|
||||
# Redis数据库索引(默认为0)
|
||||
database: 0
|
||||
# Redis服务器地址
|
||||
host: 116.196.80.239
|
||||
# Redis服务器连接端口
|
||||
port: 6379
|
||||
# Redis服务器连接密码(默认为空)
|
||||
password: LDQ20020618xxx
|
||||
# 连接超时时间
|
||||
timeout: 2s
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数
|
||||
max-active: 200
|
||||
# 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
max-wait: -1ms
|
||||
# 连接池中的最大空闲连接
|
||||
max-idle: 10
|
||||
# 连接池中的最小空闲连接
|
||||
min-idle: 0
|
||||
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ9zUefu5PFeiy4nNNRCIaNT5IY3IxRrlHMiotffSPstMensKg4PoSWJsRRrp/zQEzWegxz2Bkv3F5vfGqqM9N0CAwEAAQ==
|
||||
logging:
|
||||
config: classpath:log4j2-spring.xml
|
@@ -0,0 +1,17 @@
|
||||
spring:
|
||||
application:
|
||||
name: qing-yu-club-practice-dev
|
||||
profiles:
|
||||
active: dev
|
||||
cloud:
|
||||
nacos:
|
||||
config:
|
||||
server-addr: 116.196.80.239:8848
|
||||
prefix: ${spring.application.name}
|
||||
group: DEFAULT_GROUP
|
||||
namespace:
|
||||
file-extension: yaml
|
||||
discovery:
|
||||
enabled: true
|
||||
server-addr: 116.196.80.239:8848
|
||||
|
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
|
||||
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
|
||||
<configuration status="INFO" monitorInterval="5">
|
||||
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
|
||||
<!--变量配置-->
|
||||
<Properties>
|
||||
<!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
|
||||
<!-- %logger{36} 表示 Logger 名字最长36个字符 -->
|
||||
<property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} %X{PFTID} [%thread] %-5level %logger{36} - %msg%n" />
|
||||
<!-- 定义日志存储的路径 -->
|
||||
<property name="FILE_PATH" value="../log" />
|
||||
<property name="FILE_NAME" value="qing-yuClub-Practice.log" />
|
||||
</Properties>
|
||||
|
||||
<!--https://logging.apache.org/log4j/2.x/manual/appenders.html-->
|
||||
<appenders>
|
||||
|
||||
<console name="Console" target="SYSTEM_OUT">
|
||||
<!--输出日志的格式-->
|
||||
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||
<!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
|
||||
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||
</console>
|
||||
|
||||
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
|
||||
<File name="fileLog" fileName="${FILE_PATH}/temp.log" append="false">
|
||||
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||
</File>
|
||||
|
||||
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
|
||||
<RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log" filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
|
||||
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
|
||||
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||
<Policies>
|
||||
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
|
||||
<TimeBasedTriggeringPolicy interval="1"/>
|
||||
<SizeBasedTriggeringPolicy size="10MB"/>
|
||||
</Policies>
|
||||
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
|
||||
<DefaultRolloverStrategy max="15"/>
|
||||
</RollingFile>
|
||||
|
||||
<!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
|
||||
<RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log" filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
|
||||
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
|
||||
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||
<Policies>
|
||||
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
|
||||
<TimeBasedTriggeringPolicy interval="1"/>
|
||||
<SizeBasedTriggeringPolicy size="10MB"/>
|
||||
</Policies>
|
||||
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
|
||||
<DefaultRolloverStrategy max="15"/>
|
||||
</RollingFile>
|
||||
|
||||
<!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
|
||||
<RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log" filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
|
||||
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
|
||||
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
|
||||
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||
<Policies>
|
||||
<!--interval属性用来指定多久滚动一次,默认是1 hour-->
|
||||
<TimeBasedTriggeringPolicy interval="1"/>
|
||||
<SizeBasedTriggeringPolicy size="10MB"/>
|
||||
</Policies>
|
||||
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
|
||||
<DefaultRolloverStrategy max="15"/>
|
||||
</RollingFile>
|
||||
|
||||
</appenders>
|
||||
|
||||
<!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->
|
||||
<!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->
|
||||
<loggers>
|
||||
<root level="info">
|
||||
<appender-ref ref="Console"/>
|
||||
<appender-ref ref="RollingFileInfo"/>
|
||||
<appender-ref ref="RollingFileWarn"/>
|
||||
<appender-ref ref="RollingFileError"/>
|
||||
<appender-ref ref="fileLog"/>
|
||||
</root>
|
||||
</loggers>
|
||||
|
||||
</configuration>
|
@@ -0,0 +1,74 @@
|
||||
<?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.landaiqing.practice.server.dao.PracticeDao">
|
||||
|
||||
|
||||
<select id="selectById"
|
||||
resultType="com.landaiqing.practice.server.entity.po.PracticePO">
|
||||
select set_id as setId, time_use as timeUse, submit_time as submitTime, correct_rate as correctRate
|
||||
from practice_info
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
and is_deleted = 0
|
||||
</select>
|
||||
|
||||
<insert id="insert">
|
||||
<selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER">
|
||||
SELECT LAST_INSERT_ID()
|
||||
</selectKey>
|
||||
INSERT INTO practice_info(set_id, complete_status,time_use,submit_time,correct_rate, is_deleted,
|
||||
created_by, created_time)
|
||||
values (#{setId,jdbcType=BIGINT},
|
||||
#{completeStatus,jdbcType=INTEGER},
|
||||
#{timeUse,jdbcType=VARCHAR},
|
||||
#{submitTime,jdbcType=TIMESTAMP},
|
||||
#{correctRate,jdbcType=VARCHAR},
|
||||
#{isDeleted,jdbcType=INTEGER},
|
||||
#{createdBy,jdbcType=VARCHAR},
|
||||
#{createdTime,jdbcType=TIMESTAMP})
|
||||
</insert>
|
||||
|
||||
<update id="update">
|
||||
update practice_info
|
||||
<set>
|
||||
<if test="submitTime != null">
|
||||
submit_time = #{submitTime},
|
||||
</if>
|
||||
<if test="timeUse != null">
|
||||
time_use = #{timeUse},
|
||||
</if>
|
||||
<if test="completeStatus != null">
|
||||
complete_status = #{completeStatus},
|
||||
</if>
|
||||
<if test="correctRate != null">
|
||||
correct_rate = #{correctRate},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
|
||||
<update id="deleteById">
|
||||
update practice_info
|
||||
set is_deleted = 1
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<select id="getUnCompleteCount" resultType="java.lang.Integer">
|
||||
select count(1)
|
||||
from practice_info
|
||||
where created_by = #{loginId}
|
||||
and complete_status = 0
|
||||
and is_deleted = 0
|
||||
</select>
|
||||
|
||||
<select id="getUnCompleteList"
|
||||
resultType="com.landaiqing.practice.server.entity.po.PracticePO">
|
||||
select id, set_id as setId, time_use as timeUse, submit_time as submitTime, correct_rate as correctRate
|
||||
from practice_info
|
||||
where created_by = #{loginId}
|
||||
and is_deleted = 0
|
||||
and complete_status = 0
|
||||
order by submit_time desc
|
||||
limit #{limit}, #{offset}
|
||||
</select>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,89 @@
|
||||
<?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.landaiqing.practice.server.dao.PracticeDetailDao">
|
||||
|
||||
<select id="selectCorrectCount" resultType="java.lang.Integer">
|
||||
select count(1)
|
||||
from practice_detail
|
||||
where is_deleted = 0
|
||||
and answer_status = 1
|
||||
and practice_id = #{practiceId,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
||||
<select id="selectByPracticeId"
|
||||
resultType="com.landaiqing.practice.server.entity.po.PracticeDetailPO">
|
||||
select subject_id as subjectId, subject_type as subjectType, answer_status as answerStatus
|
||||
from practice_detail
|
||||
where is_deleted = 0
|
||||
and practice_id = #{practiceId,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
||||
<insert id="insertSingle">
|
||||
INSERT INTO practice_detail(practice_id, subject_id, subject_type, answer_status, answer_content,
|
||||
is_deleted, created_by, created_time)
|
||||
VALUES (#{practiceId},
|
||||
#{subjectId},
|
||||
#{subjectType},
|
||||
#{answerStatus},
|
||||
#{answerContent},
|
||||
#{isDeleted},
|
||||
#{createdBy},
|
||||
#{createdTime})
|
||||
</insert>
|
||||
|
||||
<select id="selectDetail"
|
||||
resultType="com.landaiqing.practice.server.entity.po.PracticeDetailPO">
|
||||
select id,
|
||||
subject_id as subjectId,
|
||||
subject_type as subjectType,
|
||||
answer_status as answerStatus,
|
||||
answer_content as answerContent
|
||||
from practice_detail
|
||||
where is_deleted = 0
|
||||
and practice_id = #{practiceId}
|
||||
and subject_id = #{subjectId}
|
||||
and created_by = #{loginId}
|
||||
</select>
|
||||
|
||||
<update id="update">
|
||||
update practice_detail
|
||||
<set>
|
||||
<if test="answerStatus != null">
|
||||
answer_status = #{answerStatus},
|
||||
</if>
|
||||
<if test="answerContent != null">
|
||||
answer_content = #{answerContent},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
|
||||
<select id="selectAnswer"
|
||||
resultType="com.landaiqing.practice.server.entity.po.PracticeDetailPO">
|
||||
select answer_content as answerContent
|
||||
from practice_detail
|
||||
where is_deleted = 0
|
||||
and practice_id = #{practiceId,jdbcType=BIGINT}
|
||||
and subject_id = #{subjectId,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
||||
<select id="getPracticeCount" resultType="com.landaiqing.practice.server.entity.po.PracticeRankPO">
|
||||
SELECT
|
||||
count(1) AS count,
|
||||
created_by AS createdBy
|
||||
FROM
|
||||
practice_info
|
||||
where is_deleted = 0
|
||||
GROUP BY
|
||||
created_by
|
||||
order by count desc
|
||||
limit 5;
|
||||
</select>
|
||||
|
||||
<update id="deleteByPracticeId">
|
||||
update practice_detail
|
||||
set is_deleted = 1
|
||||
where practice_id = #{practiceId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,76 @@
|
||||
<?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.landaiqing.practice.server.dao.PracticeSetDao">
|
||||
|
||||
<insert id="add">
|
||||
<selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER">
|
||||
SELECT LAST_INSERT_ID()
|
||||
</selectKey>
|
||||
INSERT INTO practice_set(set_name, set_type,primary_category_id, is_deleted, created_by, created_time)
|
||||
values (
|
||||
#{setName,jdbcType=VARCHAR},
|
||||
#{setType,jdbcType=INTEGER},
|
||||
#{primaryCategoryId,jdbcType=BIGINT},
|
||||
#{isDeleted,jdbcType=INTEGER},
|
||||
#{createdBy,jdbcType=VARCHAR},
|
||||
#{createdTime,jdbcType=TIMESTAMP})
|
||||
</insert>
|
||||
|
||||
<select id="selectById" resultType="com.landaiqing.practice.server.entity.po.PracticeSetPO">
|
||||
select set_name as setName,
|
||||
set_type as setType,
|
||||
set_heat as setHeat,
|
||||
set_desc as setDesc,
|
||||
primary_category_id as primaryCategoryId
|
||||
from practice_set
|
||||
where is_deleted = 0
|
||||
and id = #{setId,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
||||
<update id="updateHeat">
|
||||
update practice_set
|
||||
set set_heat = set_heat + 1
|
||||
where id = #{setId,jdbcType=BIGINT}
|
||||
</update>
|
||||
|
||||
<select id="getListCount" resultType="java.lang.Integer">
|
||||
select count(id)
|
||||
from practice_set
|
||||
where is_deleted = 0
|
||||
and set_type = 2
|
||||
<if test="setName != null">
|
||||
and set_name like concat('%',#{setName,jdbcType=VARCHAR},'%')
|
||||
</if>
|
||||
<if test="orderType != null and orderType == 0">
|
||||
order by set_name desc
|
||||
</if>
|
||||
<if test="orderType != null and orderType == 1">
|
||||
order by create_time desc
|
||||
</if>
|
||||
<if test="orderType != null and orderType == 2">
|
||||
order by set_heat desc
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getSetList" resultType="com.landaiqing.practice.server.entity.po.PracticeSetPO">
|
||||
select id,set_name as setName,set_type as setType,set_heat as setHeat,set_desc as setDesc
|
||||
from practice_set
|
||||
where is_deleted = 0
|
||||
and set_type = 2
|
||||
<if test="dto.setName != null">
|
||||
and set_name like concat('%',#{dto.setName,jdbcType=VARCHAR},'%')
|
||||
</if>
|
||||
<if test="dto.orderType != null and dto.orderType == 0">
|
||||
order by set_name desc
|
||||
</if>
|
||||
<if test="dto.orderType != null and dto.orderType == 1">
|
||||
order by create_time desc
|
||||
</if>
|
||||
<if test="dto.orderType != null and dto.orderType == 2">
|
||||
order by set_heat desc
|
||||
</if>
|
||||
limit #{limit}, #{offset}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@@ -0,0 +1,24 @@
|
||||
<?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.landaiqing.practice.server.dao.PracticeSetDetailDao">
|
||||
|
||||
<insert id="add">
|
||||
INSERT INTO practice_set_detail(set_id, subject_id, subject_type, is_deleted, created_by, created_time)
|
||||
values (#{setId,jdbcType=BIGINT},
|
||||
#{subjectId,jdbcType=BIGINT},
|
||||
#{subjectType,jdbcType=INTEGER},
|
||||
#{isDeleted,jdbcType=INTEGER},
|
||||
#{createdBy,jdbcType=VARCHAR},
|
||||
#{createdTime,jdbcType=TIMESTAMP})
|
||||
</insert>
|
||||
|
||||
<select id="selectBySetId" resultType="com.landaiqing.practice.server.entity.po.PracticeSetDetailPO">
|
||||
select subject_id as subjectId, subject_type as subjectType
|
||||
from practice_set_detail
|
||||
where is_deleted = 0
|
||||
and set_id = #{setId,jdbcType=BIGINT}
|
||||
order by subject_type
|
||||
</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.landaiqing.practice.server.dao.SubjectCategoryDao">
|
||||
|
||||
<select id="getPrimaryCategory" resultType="com.landaiqing.practice.server.entity.po.PrimaryCategoryPO">
|
||||
select
|
||||
count(distinct a.subject_id) as subjectCount,
|
||||
b.parent_id as parentId
|
||||
from subject_mapping a,
|
||||
subject_category b,
|
||||
subject_info c
|
||||
where a.category_id = b.id
|
||||
and a.subject_id = c.id
|
||||
and a.is_deleted = 0
|
||||
and b.is_deleted = 0
|
||||
and c.is_deleted = 0
|
||||
and c.subject_type in
|
||||
<foreach collection="subjectTypeList" item="item" open="(" close=")" separator=",">
|
||||
#{item}
|
||||
</foreach>
|
||||
group by b.parent_id
|
||||
</select>
|
||||
|
||||
<select id="selectById" resultType="com.landaiqing.practice.server.entity.po.CategoryPO">
|
||||
select id,
|
||||
category_name as categoryName,
|
||||
category_type as categoryType,
|
||||
parent_id as parentId
|
||||
from subject_category
|
||||
where is_deleted = 0
|
||||
and id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectList" resultType="com.landaiqing.practice.server.entity.po.CategoryPO">
|
||||
select id,
|
||||
category_name as categoryName,
|
||||
category_type as categoryType,
|
||||
parent_id as parentId
|
||||
from subject_category
|
||||
where is_deleted = 0
|
||||
and parent_id = #{parentId}
|
||||
and category_type = #{categoryType}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
@@ -0,0 +1,38 @@
|
||||
<?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.landaiqing.practice.server.dao.SubjectDao">
|
||||
|
||||
<select id="getPracticeSubject"
|
||||
resultType="com.landaiqing.practice.server.entity.po.SubjectPO">
|
||||
select distinct a.subject_id as id,
|
||||
b.subject_type as subjectType
|
||||
from subject_mapping a,
|
||||
subject_info b
|
||||
where a.subject_id = b.id
|
||||
<if test="subjectType!= null">
|
||||
and b.subject_type = #{subjectType, jdbcType= INTEGER}
|
||||
</if>
|
||||
<if test="excludeSubjectIds!= null and excludeSubjectIds.size()>0">
|
||||
and a.subject_id not in
|
||||
<foreach collection="excludeSubjectIds" item="item" open="(" close=")" separator=",">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
and CONCAT(a.category_id,'-',a.label_id) in
|
||||
<foreach collection="assembleIds" item="item" open="(" close=")" separator=",">
|
||||
#{item}
|
||||
</foreach>
|
||||
order by rand() LIMIT #{subjectCount, jdbcType= INTEGER};
|
||||
</select>
|
||||
|
||||
<select id="selectById" resultType="com.landaiqing.practice.server.entity.po.SubjectPO">
|
||||
select id,
|
||||
subject_name as subjectName,
|
||||
subject_type as subjectType
|
||||
from subject_info
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
@@ -0,0 +1,13 @@
|
||||
<?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.landaiqing.practice.server.dao.SubjectJudgeDao">
|
||||
|
||||
<select id="selectBySubjectId"
|
||||
resultType="com.landaiqing.practice.server.entity.po.SubjectJudgePO">
|
||||
select is_correct as isCorrect
|
||||
from subject_judge
|
||||
where is_delete = 0
|
||||
and subject_id = #{subjectId,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,30 @@
|
||||
<?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.landaiqing.practice.server.dao.SubjectLabelDao">
|
||||
|
||||
|
||||
<!--查询单个-->
|
||||
<select id="queryById" resultType="com.landaiqing.practice.server.entity.po.SubjectLabelPO">
|
||||
select id,
|
||||
label_name as labelName,
|
||||
category_id as categoryId,
|
||||
sort_num as sortNum,
|
||||
created_by,
|
||||
created_time,
|
||||
update_by,
|
||||
is_deleted,
|
||||
update_time
|
||||
from subject_label
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="getLabelNameByIds" resultType="java.lang.String">
|
||||
select label_name as labelName from subject_label where id in
|
||||
<foreach collection="labelIds" item="item" open="(" close=")" separator=",">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
@@ -0,0 +1,33 @@
|
||||
<?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.landaiqing.practice.server.dao.SubjectMappingDao">
|
||||
|
||||
<select id="getLabelSubjectCount" resultType="com.landaiqing.practice.server.entity.po.LabelCountPO">
|
||||
select
|
||||
count(distinct a.subject_id) as count,
|
||||
a.label_id as labelId
|
||||
from subject_mapping a,
|
||||
subject_info b
|
||||
where
|
||||
a.subject_id = b.id
|
||||
and a.is_deleted = 0
|
||||
and b.is_deleted = 0
|
||||
and a.category_id = #{categoryId}
|
||||
and b.subject_type in
|
||||
<foreach collection="subjectTypeList" item="item" open="(" close=")" separator=",">
|
||||
#{item}
|
||||
</foreach>
|
||||
group by a.label_id
|
||||
</select>
|
||||
|
||||
<select id="getLabelIdsBySubjectId"
|
||||
resultType="com.landaiqing.practice.server.entity.po.SubjectMappingPO">
|
||||
select distinct label_id as labelId
|
||||
from subject_mapping
|
||||
where is_deleted = 0
|
||||
and subject_id = #{subjectId,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
@@ -0,0 +1,14 @@
|
||||
<?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.landaiqing.practice.server.dao.SubjectMultipleDao">
|
||||
|
||||
<select id="selectBySubjectId"
|
||||
resultType="com.landaiqing.practice.server.entity.po.SubjectMultiplePO">
|
||||
select option_type as optionType, option_content as optionContent, is_correct as isCorrect
|
||||
from subject_multiple
|
||||
where is_deleted = 0
|
||||
and subject_id = #{subjectId,jdbcType=BIGINT}
|
||||
order by option_type
|
||||
</select>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,15 @@
|
||||
<?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.landaiqing.practice.server.dao.SubjectRadioDao">
|
||||
|
||||
<select id="selectBySubjectId"
|
||||
resultType="com.landaiqing.practice.server.entity.po.SubjectRadioPO">
|
||||
select option_type as optionType, option_content as optionContent, is_correct as isCorrect
|
||||
from subject_radio
|
||||
where is_deleted = 0
|
||||
and subject_id = #{subjectId,jdbcType=BIGINT}
|
||||
order by option_type
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
Reference in New Issue
Block a user