Compare commits
No commits in common. 'main' and 'master' have entirely different histories.
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="17" project-jdk-type="JavaSDK" />
|
||||||
|
</project>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/k-class-roll-call.iml" filepath="$PROJECT_DIR$/.idea/k-class-roll-call.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AutoImportSettings">
|
||||||
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
|
</component>
|
||||||
|
<component name="ChangeListManager">
|
||||||
|
<list default="true" id="b4c20391-644c-4ef8-93ae-166260c047e0" name="更改" comment="" />
|
||||||
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectId" id="2mvSYUAwxILKz9wIrHwcmy17tTE" />
|
||||||
|
<component name="ProjectViewState">
|
||||||
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
|
<option name="showLibraryContents" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PropertiesComponent"><![CDATA[{
|
||||||
|
"keyToString": {
|
||||||
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
|
"WebServerToolWindowFactoryState": "false",
|
||||||
|
"node.js.detected.package.eslint": "true",
|
||||||
|
"node.js.detected.package.tslint": "true",
|
||||||
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
|
"nodejs_package_manager_path": "npm",
|
||||||
|
"vue.rearranger.settings.migration": "true"
|
||||||
|
}
|
||||||
|
}]]></component>
|
||||||
|
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
|
||||||
|
<component name="TaskManager">
|
||||||
|
<task active="true" id="Default" summary="默认任务">
|
||||||
|
<changelist id="b4c20391-644c-4ef8-93ae-166260c047e0" name="更改" comment="" />
|
||||||
|
<created>1727955603618</created>
|
||||||
|
<option name="number" value="Default" />
|
||||||
|
<option name="presentableId" value="Default" />
|
||||||
|
<updated>1727955603618</updated>
|
||||||
|
<workItem from="1727955604708" duration="5000" />
|
||||||
|
<workItem from="1728893452698" duration="322000" />
|
||||||
|
</task>
|
||||||
|
<servers />
|
||||||
|
</component>
|
||||||
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
|
<option name="version" value="3" />
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -0,0 +1,5 @@
|
|||||||
|
部署地址:
|
||||||
|
http://8.210.250.29/
|
||||||
|
测试账号:
|
||||||
|
账号 -- flyingpig
|
||||||
|
密码 -- flyingpig
|
@ -0,0 +1,33 @@
|
|||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.flyingpig.kclassrollcall;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class KClassRollCallApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(KClassRollCallApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.common;
|
||||||
|
|
||||||
|
public class RedisConstant {
|
||||||
|
|
||||||
|
public static final String STUDENT_LIST_KEY = "student:list:";
|
||||||
|
|
||||||
|
public static final String STUDENT_SCORE_KEY = "student:score:";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.common;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Result {
|
||||||
|
private Integer code;//响应码
|
||||||
|
private String msg;//响应信息,描述字符串
|
||||||
|
private Object data;//返回的数据
|
||||||
|
|
||||||
|
//增删改
|
||||||
|
public static Result success() {
|
||||||
|
return new Result(200, "success", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//查询 成功响应
|
||||||
|
public static Result success(Object data) {
|
||||||
|
return new Result(200, "success", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//查询 失败响应
|
||||||
|
public static Result error(Integer code, String msg) {
|
||||||
|
return new Result(code, msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Result error(String msg) {
|
||||||
|
return new Result(500, msg, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.common;
|
||||||
|
|
||||||
|
public class StatusCode {
|
||||||
|
/**
|
||||||
|
* 操作成功
|
||||||
|
*/
|
||||||
|
public static final int OK = 200;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数异常或缺失
|
||||||
|
*/
|
||||||
|
public static final int PARAMETERERROR = 400;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源不存在
|
||||||
|
*/
|
||||||
|
public static final int NOTFOUND = 404;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方法错误
|
||||||
|
*/
|
||||||
|
public static final int METHODERROR = 405;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务端错误
|
||||||
|
*/
|
||||||
|
public static final int SERVERERROR = 500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 未经授权
|
||||||
|
*/
|
||||||
|
public static final int UNAUTHORIZED = 401;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
|
import org.springframework.web.filter.CorsFilter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class CorsConfig {
|
||||||
|
/**
|
||||||
|
* 允许跨域调用的过滤器
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public CorsFilter corsFilter() {
|
||||||
|
CorsConfiguration config = new CorsConfiguration();
|
||||||
|
//允许白名单域名进行跨域调用
|
||||||
|
config.addAllowedOriginPattern("*");
|
||||||
|
//允许跨越发送cookie
|
||||||
|
config.setAllowCredentials(true);
|
||||||
|
//放行全部原始头信息
|
||||||
|
config.addAllowedHeader("*");
|
||||||
|
//允许所有请求方法跨域调用
|
||||||
|
config.addAllowedMethod("*");
|
||||||
|
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||||
|
source.registerCorsConfiguration("/**", config);
|
||||||
|
return new CorsFilter(source);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.config;
|
||||||
|
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Primary;
|
||||||
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class JacksonConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Primary
|
||||||
|
@ConditionalOnMissingBean(ObjectMapper.class)
|
||||||
|
public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
|
||||||
|
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
|
||||||
|
|
||||||
|
// 全局配置序列化返回 JSON 处理
|
||||||
|
SimpleModule simpleModule = new SimpleModule();
|
||||||
|
//JSON Long ==> String
|
||||||
|
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
||||||
|
objectMapper.registerModule(simpleModule);
|
||||||
|
return objectMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.config;
|
||||||
|
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.filter.AuthInterceptor;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class MvcConfig implements WebMvcConfigurer {
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(new AuthInterceptor())
|
||||||
|
.excludePathPatterns("/user/login", "/user/register"); // 排除登录和注册接口
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.config;
|
||||||
|
|
||||||
|
import org.redisson.Redisson;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.redisson.config.Config;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedissonConfig {
|
||||||
|
@Bean
|
||||||
|
public RedissonClient redissonClient(){
|
||||||
|
// 配置
|
||||||
|
Config config = new Config();
|
||||||
|
config.useSingleServer().setAddress("redis://localhost:6379");
|
||||||
|
// 创建RedissonClient对象
|
||||||
|
return Redisson.create(config);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.common.Result;
|
||||||
|
import com.flyingpig.kclassrollcall.dto.req.LoginReq;
|
||||||
|
import com.flyingpig.kclassrollcall.entity.Teacher;
|
||||||
|
import com.flyingpig.kclassrollcall.service.ITeacherService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/user")
|
||||||
|
public class TeacherController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ITeacherService teacherService;
|
||||||
|
|
||||||
|
@PostMapping("/login")
|
||||||
|
public Result login(@RequestBody LoginReq loginReq){
|
||||||
|
return teacherService.login(loginReq);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/register")
|
||||||
|
public Result register(@RequestBody Teacher teacher){
|
||||||
|
return teacherService.register(teacher);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/logout")
|
||||||
|
public Result logout(@RequestBody Teacher teacher){
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.dto.req;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class LoginReq {
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.dto.req;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class StudentExcelModel {
|
||||||
|
private String no; // 学号
|
||||||
|
private String name; // 姓名
|
||||||
|
private String major; // 专业
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.dto.resp;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class LoginResp {
|
||||||
|
private String name;
|
||||||
|
private String token;
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.dto.resp;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class StudentInfoInCache {
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Integer no;
|
||||||
|
|
||||||
|
private String major;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.entity;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("student")
|
||||||
|
@ApiModel(value="Student对象", description="")
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Student implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Integer no;
|
||||||
|
|
||||||
|
private String major;
|
||||||
|
|
||||||
|
private Double score;
|
||||||
|
|
||||||
|
private Long teacherId;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("teacher")
|
||||||
|
@ApiModel(value="Teacher对象", description="")
|
||||||
|
public class Teacher implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.exception;
|
||||||
|
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.common.Result;
|
||||||
|
import com.flyingpig.kclassrollcall.common.StatusCode;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.RedisConnectionFailureException;
|
||||||
|
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||||
|
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
|
||||||
|
|
||||||
|
import java.net.BindException;
|
||||||
|
|
||||||
|
//全局异常处理器
|
||||||
|
@RestControllerAdvice
|
||||||
|
@Slf4j
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数异常/缺少--400
|
||||||
|
*
|
||||||
|
* @param e
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@ExceptionHandler({
|
||||||
|
MissingServletRequestParameterException.class,
|
||||||
|
MethodArgumentTypeMismatchException.class,
|
||||||
|
BindException.class}
|
||||||
|
)
|
||||||
|
public Result missingServletRequestParameterException(Exception e) {
|
||||||
|
return Result.error(StatusCode.PARAMETERERROR, "缺少参数或参数错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方法错误--405
|
||||||
|
* @param e
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
|
||||||
|
public Result httpRequestMethodNotSupportedExceptionHandler(Exception e){
|
||||||
|
log.error("请求方法错误");
|
||||||
|
return Result.error(StatusCode.METHODERROR,"请求方法错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis没连接上--500
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(RedisConnectionFailureException.class)
|
||||||
|
public Result edisConnectionFailureExceptionHandler(RedisConnectionFailureException e) {
|
||||||
|
log.error("redis连接错误啦啦啦啦啦啦");
|
||||||
|
return Result.error(StatusCode.SERVERERROR,"redis连接错误啦啦啦啦啦啦");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 其他异常--500
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public Result exceptionHandler(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Result.error(StatusCode.SERVERERROR,"对不起,操作失败,请联系管理员");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.filter;
|
||||||
|
|
||||||
|
public class UserContext {
|
||||||
|
private static final ThreadLocal<String> tl =new ThreadLocal<>();
|
||||||
|
|
||||||
|
//保存当前登录用户信息到ThreadLocal
|
||||||
|
public static void setUser(String userId){
|
||||||
|
tl.set(userId);
|
||||||
|
}
|
||||||
|
//获取当前登录的用户信息
|
||||||
|
public static String getUser(){
|
||||||
|
return tl.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
//移除当前登录用户信息
|
||||||
|
public static void removeUser(){
|
||||||
|
tl.remove();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.init;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j(topic = "Initialize")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InitializeController {
|
||||||
|
|
||||||
|
private final DataSource dataSource;
|
||||||
|
|
||||||
|
@GetMapping("/initialize/application")
|
||||||
|
public void initializeDispatcherServletAndDataSource() {
|
||||||
|
log.info("开始初始化DispatcherServlet和数据源");
|
||||||
|
try {
|
||||||
|
log.info("初始化DispatcherServlet和数据源成功");
|
||||||
|
dataSource.getConnection().createStatement().execute("SELECT 1");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("初始化DispatcherServlet和数据源失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.init;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public final class InitializeDispatcherServletHandler implements CommandLineRunner {
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
private final ConfigurableEnvironment configurableEnvironment;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
String url = String.format("http://127.0.0.1:%s%s",
|
||||||
|
configurableEnvironment.getProperty("server.port", "8080") + configurableEnvironment.getProperty("server.servlet.context-path", ""),
|
||||||
|
"/initialize/dispatcher-servlet");
|
||||||
|
try {
|
||||||
|
restTemplate.execute(url, HttpMethod.GET, null, null);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.mapper;
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.entity.Student;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface StudentMapper extends BaseMapper<Student> {
|
||||||
|
|
||||||
|
Student rollCall(String teacherId, int randomIndex);
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.mapper;
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.entity.Teacher;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface TeacherMapper extends BaseMapper<Teacher> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.service;
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.common.Result;
|
||||||
|
import com.flyingpig.kclassrollcall.entity.Student;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
public interface IStudentService extends IService<Student> {
|
||||||
|
|
||||||
|
Result rollCall(String mode);
|
||||||
|
|
||||||
|
Result search(String no, String name, Integer pageNo, Integer pageSize);
|
||||||
|
|
||||||
|
Result importExcel(MultipartFile file);
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.service;
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.common.Result;
|
||||||
|
import com.flyingpig.kclassrollcall.dto.req.LoginReq;
|
||||||
|
import com.flyingpig.kclassrollcall.entity.Teacher;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
public interface ITeacherService extends IService<Teacher> {
|
||||||
|
|
||||||
|
Result login(LoginReq loginReq);
|
||||||
|
|
||||||
|
Result register(Teacher teacher);
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.flyingpig.kclassrollcall.common.Result;
|
||||||
|
import com.flyingpig.kclassrollcall.dto.req.LoginReq;
|
||||||
|
import com.flyingpig.kclassrollcall.dto.resp.LoginResp;
|
||||||
|
import com.flyingpig.kclassrollcall.entity.Teacher;
|
||||||
|
import com.flyingpig.kclassrollcall.mapper.TeacherMapper;
|
||||||
|
import com.flyingpig.kclassrollcall.service.ITeacherService;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.flyingpig.kclassrollcall.util.JwtUtil;
|
||||||
|
import org.apache.catalina.User;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务实现类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author flyingpig
|
||||||
|
* @since 2024-09-25
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements ITeacherService {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result login(LoginReq loginReq) {
|
||||||
|
Teacher teacher = this.getOne(new LambdaQueryWrapper<Teacher>()
|
||||||
|
.eq(Teacher::getUsername, loginReq.getUsername()));
|
||||||
|
if (teacher == null || !new BCryptPasswordEncoder().matches(loginReq.getPassword(), teacher.getPassword())) {
|
||||||
|
return Result.error("账号或密码错误");
|
||||||
|
} else {
|
||||||
|
return Result.success(new LoginResp(teacher.getName(), JwtUtil.createJWT(teacher.getId().toString())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result register(Teacher teacher) {
|
||||||
|
try {
|
||||||
|
save(teacher.setPassword(new BCryptPasswordEncoder().encode(teacher.getPassword())));
|
||||||
|
return Result.success("注册成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Result.error("注册失败,可能存在用户名已被注册等问题");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.flyingpig.kclassrollcall.util.cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存加载器
|
||||||
|
* 用于将数据库信息加载到缓存中
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CacheLoader<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载缓存
|
||||||
|
*/
|
||||||
|
T load();
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
server:
|
||||||
|
port: 9090
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://localhost:3306/k-class-roll-call
|
||||||
|
username: root
|
||||||
|
password: '@Aa123456'
|
||||||
|
hikari:
|
||||||
|
minimum-idle: 5 # 最小空闲连接数
|
||||||
|
maximum-pool-size: 10 # 连接池最大连接数
|
||||||
|
connection-timeout: 30000 # 连接超时时间
|
||||||
|
idle-timeout: 600000 # 空闲连接的存活时间
|
||||||
|
max-lifetime: 1800000 # 连接的最长存活时间
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: localhost
|
||||||
|
port: 6379
|
||||||
|
database: 0
|
||||||
|
logging:
|
||||||
|
level:
|
||||||
|
com.baomidou.mybatisplus: DEBUG # MyBatis-Plus 日志级别
|
@ -0,0 +1,8 @@
|
|||||||
|
<?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.flyingpig.kclassrollcall.mapper.StudentMapper">
|
||||||
|
|
||||||
|
<select id="rollCall" resultType="com.flyingpig.kclassrollcall.entity.Student">
|
||||||
|
SELECT * FROM student WHERE teacher_id = #{teacherId} LIMIT 1 OFFSET #{randomIndex};
|
||||||
|
</select>
|
||||||
|
</mapper>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?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.flyingpig.kclassrollcall.mapper.TeacherMapper">
|
||||||
|
|
||||||
|
</mapper>
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
Navicat Premium Data Transfer
|
||||||
|
|
||||||
|
Source Server : k-class-roll-call
|
||||||
|
Source Server Type : MySQL
|
||||||
|
Source Server Version : 80032 (8.0.32)
|
||||||
|
Source Host : localhost:3306
|
||||||
|
Source Schema : k-class-roll-call
|
||||||
|
|
||||||
|
Target Server Type : MySQL
|
||||||
|
Target Server Version : 80032 (8.0.32)
|
||||||
|
File Encoding : 65001
|
||||||
|
|
||||||
|
Date: 28/09/2024 11:06:20
|
||||||
|
*/
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for student
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `student`;
|
||||||
|
CREATE TABLE `student` (
|
||||||
|
`id` bigint NOT NULL,
|
||||||
|
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||||
|
`no` int NULL DEFAULT NULL,
|
||||||
|
`major` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
|
||||||
|
`score` decimal(10, 2) NULL DEFAULT NULL,
|
||||||
|
`teacher_id` bigint NOT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of student
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `student` VALUES (1, '朱嘉翔', 102201604, '计算机科学与技术', 25.50, 1);
|
||||||
|
INSERT INTO `student` VALUES (2, '范国鑫', 102201525, '计算机科学与技术', 34.00, 1);
|
||||||
|
INSERT INTO `student` VALUES (1839635335860477954, '庄学鹏', 102201605, '计算机科学与技术', 9.00, 1);
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Table structure for teacher
|
||||||
|
-- ----------------------------
|
||||||
|
DROP TABLE IF EXISTS `teacher`;
|
||||||
|
CREATE TABLE `teacher` (
|
||||||
|
`id` bigint NOT NULL,
|
||||||
|
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
|
||||||
|
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
|
||||||
|
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
|
||||||
|
PRIMARY KEY (`id`) USING BTREE
|
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Records of teacher
|
||||||
|
-- ----------------------------
|
||||||
|
INSERT INTO `teacher` VALUES (1, '1', '1', '1');
|
||||||
|
INSERT INTO `teacher` VALUES (1839133469267496961, 'flyingpig', 'flyingpig', 'flyingpig');
|
||||||
|
|
||||||
|
SET FOREIGN_KEY_CHECKS = 1;
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.flyingpig.kclassrollcall;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class KClassRollCallApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package com.flyingpig.kclassrollcall;
|
||||||
|
|
||||||
|
import com.flyingpig.kclassrollcall.common.Result;
|
||||||
|
import com.flyingpig.kclassrollcall.dto.req.LoginReq;
|
||||||
|
import com.flyingpig.kclassrollcall.dto.resp.LoginResp;
|
||||||
|
import com.flyingpig.kclassrollcall.entity.Teacher;
|
||||||
|
import com.flyingpig.kclassrollcall.mapper.TeacherMapper;
|
||||||
|
import com.flyingpig.kclassrollcall.service.ITeacherService;
|
||||||
|
import com.flyingpig.kclassrollcall.service.impl.TeacherServiceImpl;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
public class TeacherServiceImplTest {
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private TeacherServiceImpl teacherService; // 替换为你的实际服务类
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private TeacherMapper teacherMapper; // 替换为你的 TeacherMapper 类
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.openMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoginSuccess() {
|
||||||
|
// Arrange
|
||||||
|
LoginReq loginReq = new LoginReq("flyingpig", "flyingpig");
|
||||||
|
Teacher teacher = new Teacher();
|
||||||
|
teacher.setId(1L);
|
||||||
|
teacher.setName("John Doe");
|
||||||
|
teacher.setUsername("flyingpig");
|
||||||
|
teacher.setPassword("flyingpig");
|
||||||
|
|
||||||
|
when(teacherMapper.selectOne(any())).thenReturn(teacher); // 模拟数据库返回教师对象
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result result = teacherService.login(loginReq);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(200, result.getCode()); // 检查返回代码
|
||||||
|
assertEquals("John Doe", ((LoginResp) result.getData()).getName()); // 检查返回的教师名称
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoginFailure() {
|
||||||
|
// Arrange
|
||||||
|
LoginReq loginReq = new LoginReq("username", "wrongpassword");
|
||||||
|
|
||||||
|
when(teacherMapper.selectOne(any())).thenReturn(null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Result result = teacherService.login(loginReq);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertEquals(500, result.getCode()); // 检查返回代码
|
||||||
|
assertEquals("账号或密码错误", result.getMsg()); // 检查返回的错误信息
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 ROBINRUGAN
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
'@vue/cli-plugin-babel/preset'
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "esnext",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "k-calss-rall-call",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.5.1",
|
||||||
|
"core-js": "^3.8.3",
|
||||||
|
"element-ui": "^2.15.14",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
|
"vue": "^2.6.14",
|
||||||
|
"vue-router": "^3.6.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.12.16",
|
||||||
|
"@babel/eslint-parser": "^7.12.16",
|
||||||
|
"@vue/cli-plugin-babel": "~5.0.0",
|
||||||
|
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||||
|
"@vue/cli-service": "~5.0.0",
|
||||||
|
"babel-plugin-component": "^1.1.1",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
|
"eslint-plugin-vue": "^8.0.3",
|
||||||
|
"vue-template-compiler": "^2.6.14"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/essential",
|
||||||
|
"eslint:recommended"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "@babel/eslint-parser"
|
||||||
|
},
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not dead"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
function clickEffect() {
|
||||||
|
let balls = [];
|
||||||
|
let longPressed = false;
|
||||||
|
let longPress;
|
||||||
|
let multiplier = 0;
|
||||||
|
let width, height;
|
||||||
|
let origin;
|
||||||
|
let normal;
|
||||||
|
let ctx;
|
||||||
|
const colours = ["#F73859", "#14FFEC", "#00E0FF", "#FF99FE", "#FAF15D"];
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
document.body.appendChild(canvas);
|
||||||
|
canvas.setAttribute("style", "width: 100%; height: 100%; top: 0; left: 0; z-index: 99999; position: fixed; pointer-events: none;");
|
||||||
|
const pointer = document.createElement("span");
|
||||||
|
pointer.classList.add("pointer");
|
||||||
|
document.body.appendChild(pointer);
|
||||||
|
|
||||||
|
if (canvas.getContext && window.addEventListener) {
|
||||||
|
ctx = canvas.getContext("2d");
|
||||||
|
updateSize();
|
||||||
|
window.addEventListener('resize', updateSize, false);
|
||||||
|
loop();
|
||||||
|
window.addEventListener("mousedown", function(e) {
|
||||||
|
pushBalls(randBetween(10, 20), e.clientX, e.clientY);
|
||||||
|
document.body.classList.add("is-pressed");
|
||||||
|
longPress = setTimeout(function() {
|
||||||
|
document.body.classList.add("is-longpress");
|
||||||
|
longPressed = true;
|
||||||
|
}, 500);
|
||||||
|
}, false);
|
||||||
|
window.addEventListener("mouseup", function(e) {
|
||||||
|
clearInterval(longPress);
|
||||||
|
if (longPressed == true) {
|
||||||
|
document.body.classList.remove("is-longpress");
|
||||||
|
pushBalls(randBetween(50 + Math.ceil(multiplier), 100 + Math.ceil(multiplier)), e.clientX, e.clientY);
|
||||||
|
longPressed = false;
|
||||||
|
}
|
||||||
|
document.body.classList.remove("is-pressed");
|
||||||
|
}, false);
|
||||||
|
window.addEventListener("mousemove", function(e) {
|
||||||
|
let x = e.clientX;
|
||||||
|
let y = e.clientY;
|
||||||
|
pointer.style.top = y + "px";
|
||||||
|
pointer.style.left = x + "px";
|
||||||
|
}, false);
|
||||||
|
} else {
|
||||||
|
console.log("canvas or addEventListener is unsupported!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function updateSize() {
|
||||||
|
canvas.width = window.innerWidth * 2;
|
||||||
|
canvas.height = window.innerHeight * 2;
|
||||||
|
canvas.style.width = window.innerWidth + 'px';
|
||||||
|
canvas.style.height = window.innerHeight + 'px';
|
||||||
|
ctx.scale(2, 2);
|
||||||
|
width = (canvas.width = window.innerWidth);
|
||||||
|
height = (canvas.height = window.innerHeight);
|
||||||
|
origin = {
|
||||||
|
x: width / 2,
|
||||||
|
y: height / 2
|
||||||
|
};
|
||||||
|
normal = {
|
||||||
|
x: width / 2,
|
||||||
|
y: height / 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
class Ball {
|
||||||
|
constructor(x = origin.x, y = origin.y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.angle = Math.PI * 2 * Math.random();
|
||||||
|
if (longPressed == true) {
|
||||||
|
this.multiplier = randBetween(14 + multiplier, 15 + multiplier);
|
||||||
|
} else {
|
||||||
|
this.multiplier = randBetween(6, 12);
|
||||||
|
}
|
||||||
|
this.vx = (this.multiplier + Math.random() * 0.5) * Math.cos(this.angle);
|
||||||
|
this.vy = (this.multiplier + Math.random() * 0.5) * Math.sin(this.angle);
|
||||||
|
this.r = randBetween(8, 12) + 3 * Math.random();
|
||||||
|
this.color = colours[Math.floor(Math.random() * colours.length)];
|
||||||
|
}
|
||||||
|
update() {
|
||||||
|
this.x += this.vx - normal.x;
|
||||||
|
this.y += this.vy - normal.y;
|
||||||
|
normal.x = -2 / window.innerWidth * Math.sin(this.angle);
|
||||||
|
normal.y = -2 / window.innerHeight * Math.cos(this.angle);
|
||||||
|
this.r -= 0.3;
|
||||||
|
this.vx *= 0.9;
|
||||||
|
this.vy *= 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushBalls(count = 1, x = origin.x, y = origin.y) {
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
balls.push(new Ball(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function randBetween(min, max) {
|
||||||
|
return Math.floor(Math.random() * max) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loop() {
|
||||||
|
ctx.fillStyle = "rgba(255, 255, 255, 0)";
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
for (let i = 0; i < balls.length; i++) {
|
||||||
|
let b = balls[i];
|
||||||
|
if (b.r < 0) continue;
|
||||||
|
ctx.fillStyle = b.color;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(b.x, b.y, b.r, 0, Math.PI * 2, false);
|
||||||
|
ctx.fill();
|
||||||
|
b.update();
|
||||||
|
}
|
||||||
|
if (longPressed == true) {
|
||||||
|
multiplier += 0.2;
|
||||||
|
} else if (!longPressed && multiplier >= 0) {
|
||||||
|
multiplier -= 0.4;
|
||||||
|
}
|
||||||
|
removeBall();
|
||||||
|
requestAnimationFrame(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeBall() {
|
||||||
|
for (let i = 0; i < balls.length; i++) {
|
||||||
|
let b = balls[i];
|
||||||
|
if (b.x + b.r < 0 || b.x - b.r > width || b.y + b.r < 0 || b.y - b.r > height || b.r < 0) {
|
||||||
|
balls.splice(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clickEffect();//调用
|
||||||
|
|
After Width: | Height: | Size: 4.5 KiB |
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title>K班点名系统ヾ(≧▽≦*)o</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
|
||||||
|
Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
<script src="1.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
After Width: | Height: | Size: 316 KiB |
@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<div id="app">
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "App",
|
||||||
|
components: {},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
font-family: "微软雅黑";
|
||||||
|
}
|
||||||
|
.el-submenu__title {
|
||||||
|
margin: 0px !important;
|
||||||
|
padding: 0px !important;
|
||||||
|
color: #fff !important;
|
||||||
|
background-color: #a6e0fe !important;
|
||||||
|
font-size: 18px!important;
|
||||||
|
}
|
||||||
|
.el-submenu__title.is-active {
|
||||||
|
padding: 0px !important;
|
||||||
|
background-color: #6fc5f1 !important;
|
||||||
|
}
|
||||||
|
.el-menu-item-group__title {
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
.el-submenu__title i {
|
||||||
|
color: #ffffff!important;
|
||||||
|
}
|
||||||
|
.el-submenu__icon-arrow {
|
||||||
|
font-size: 20px!important;
|
||||||
|
margin-top: -11px!important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
service
|
||||||
|
} from "@/utils/request";
|
||||||
|
|
||||||
|
export function Semester() {
|
||||||
|
return service.request({
|
||||||
|
method: "get",
|
||||||
|
url: `/courseDetails/dataColumn`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Login(data) {
|
||||||
|
return service.request({
|
||||||
|
method: "post",
|
||||||
|
url: `/user/login`,
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function Register(data) {
|
||||||
|
return service.request({
|
||||||
|
method: "post",
|
||||||
|
url: `/user/register`,
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Logout() {
|
||||||
|
return service.request({
|
||||||
|
method: "post",
|
||||||
|
url: `/user/logout`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DeleteStudent(studentId) {
|
||||||
|
return service.request({
|
||||||
|
method: "delete",
|
||||||
|
url: `/student/${studentId}` // 确保 studentId 是字符串
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function ModifyStudentScore(id, score) {
|
||||||
|
return service.request({
|
||||||
|
method: "put",
|
||||||
|
url: `/student/score?id=${id}&&score=${score}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function StudentSearch(data) {
|
||||||
|
const {
|
||||||
|
no,
|
||||||
|
name,
|
||||||
|
pageSize,
|
||||||
|
pageNo
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
// 使用条件运算符来确保查询参数不是 undefined
|
||||||
|
const queryParams = [
|
||||||
|
`no=${no}`,
|
||||||
|
`name=${name}`,
|
||||||
|
`pageSize=${pageSize}`,
|
||||||
|
`pageNo=${pageNo}`
|
||||||
|
].filter(param => param !== undefined).join('&');
|
||||||
|
|
||||||
|
const url = `/student/search?${queryParams}`;
|
||||||
|
|
||||||
|
return service.request({
|
||||||
|
method: "get",
|
||||||
|
url: url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function GetRollBackStudent(mode) {
|
||||||
|
const url = `/student/roll-call?mode=${mode}`;
|
||||||
|
|
||||||
|
return service.request({
|
||||||
|
method: "get",
|
||||||
|
url: url
|
||||||
|
});
|
||||||
|
}
|
After Width: | Height: | Size: 374 KiB |
After Width: | Height: | Size: 156 KiB |
After Width: | Height: | Size: 191 KiB |
After Width: | Height: | Size: 736 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 826 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 596 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 807 B |
After Width: | Height: | Size: 720 B |
After Width: | Height: | Size: 817 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 555 B |
After Width: | Height: | Size: 617 B |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 212 KiB |
@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div id="question">
|
||||||
|
<!-- 添加 "进入提问环节" 文本 -->
|
||||||
|
<div id="question-phase">
|
||||||
|
进入提问环节
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 显示正在回答问题的学生姓名 -->
|
||||||
|
<div id="current-student">
|
||||||
|
现在回答问题的是 {{ currentStudent.name || "某某同学" }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="circle-container">
|
||||||
|
<button v-for="(score, index) in scores" :key="index" class="circle-button" :style="getButtonStyle(index)"
|
||||||
|
@click="selectScore(score)">
|
||||||
|
{{ score }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ModifyStudentScore } from "@/api/api"; // 引入修改分数接口
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
scores: [-1, 0.5, 1, 1.5, 2, 2.5, 3],
|
||||||
|
selectedScore: null,
|
||||||
|
currentStudent: this.$route.params.student, // 从路由参数中获取当前学生信息
|
||||||
|
detailModeType: this.$route.params.detailModeType // 从路由参数中获取当前学生信息
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
selectScore(score) {
|
||||||
|
this.selectedScore = score; // 显示选中的分数
|
||||||
|
if (this.detailModeType != 0 && this.detailModeType != 2) {
|
||||||
|
score = this.detailModeType * score;
|
||||||
|
}
|
||||||
|
// 使用 this.detailModeType 访问 detailModeType
|
||||||
|
ModifyStudentScore(this.currentStudent.id, score).then((res) => {
|
||||||
|
if (res.code == 500) {
|
||||||
|
this.$message.error("修改分数发生错误");
|
||||||
|
} else if (res.code == 200) {
|
||||||
|
this.$message.success(this.currentStudent.name + "分数修改成功, 增加" + score + "分");
|
||||||
|
if (this.$route.path !== "/roll-call") {
|
||||||
|
this.$router.push("/roll-call");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (res.code == 401) {
|
||||||
|
alert("登录过期,请重新登录!");
|
||||||
|
if (this.$route.path !== "/login") {
|
||||||
|
this.$router.push("/login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getButtonStyle(index) {
|
||||||
|
const angle = (index / this.scores.length) * 2 * Math.PI; // 计算每个按钮的角度
|
||||||
|
const radius = 150; // 圆环的半径
|
||||||
|
const x = radius * Math.cos(angle); // 按钮的 x 坐标
|
||||||
|
const y = radius * Math.sin(angle); // 按钮的 y 坐标
|
||||||
|
|
||||||
|
return {
|
||||||
|
position: 'absolute',
|
||||||
|
left: `${150 + x}px`, // 将 x 坐标平移至容器中心
|
||||||
|
top: `${150 + y}px`, // 将 y 坐标平移至容器中心
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#question {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
width: 85.4%;
|
||||||
|
height: 100vh;
|
||||||
|
background-image: url("../assets/login/login-background.png");
|
||||||
|
background-size: cover;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
/* 隐藏溢出内容 */
|
||||||
|
}
|
||||||
|
|
||||||
|
#question-phase {
|
||||||
|
font-size: 28px;
|
||||||
|
color: black;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#current-student {
|
||||||
|
font-size: 24px;
|
||||||
|
color: black;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#circle-container {
|
||||||
|
position: relative;
|
||||||
|
width: 300px;
|
||||||
|
/* 容器宽度,圆环直径 */
|
||||||
|
height: 300px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-button {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #87CEEB;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
font-size: 18px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-button:hover {
|
||||||
|
background-color: #1E90FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#selected-score {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 24px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,175 @@
|
|||||||
|
<template>
|
||||||
|
<div id="sidebar">
|
||||||
|
<div id="info">
|
||||||
|
<img id="logo" src="../assets/home/avatar.png" alt="" />
|
||||||
|
<h1 id="title">KX点名</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-menu :default-active="$route.path" class="menu">
|
||||||
|
<router-link to="/home">
|
||||||
|
<el-menu-item index="/home" >
|
||||||
|
<div class="menu-item">
|
||||||
|
<img src="../assets/home/home-icon.png" alt="" />
|
||||||
|
首页
|
||||||
|
</div>
|
||||||
|
</el-menu-item>
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/student">
|
||||||
|
<el-menu-item index="/student">
|
||||||
|
<div class="menu-item">
|
||||||
|
<img src="../assets/home/search-menu.png" alt="" />
|
||||||
|
学生名单与积分查询
|
||||||
|
</div>
|
||||||
|
</el-menu-item>
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/roll-call">
|
||||||
|
<el-menu-item index="/roll-call">
|
||||||
|
<div class="menu-item">
|
||||||
|
<img src="../assets/home/pass-icon.png" alt="" />
|
||||||
|
点名与提问
|
||||||
|
</div>
|
||||||
|
</el-menu-item>
|
||||||
|
</router-link>
|
||||||
|
</el-menu>
|
||||||
|
<div id="logout" @click="logout">
|
||||||
|
<img src="../assets/home/logout-icon.png" alt="" />
|
||||||
|
<span>退出登录</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Logout } from "@/api/api";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
logout() {
|
||||||
|
Logout().then(
|
||||||
|
(res) => {
|
||||||
|
this.$message.success("退出成功!");
|
||||||
|
localStorage.removeItem("token");
|
||||||
|
localStorage.removeItem("name");
|
||||||
|
if (this.$route.path !== "/login") {
|
||||||
|
this.$router.push("/login");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
this.$message.error(err.msg);
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#sidebar {
|
||||||
|
background-color: #c5d2d8;
|
||||||
|
height: 100vh;
|
||||||
|
width: 260px;
|
||||||
|
box-shadow: 8px 0px 11px 0px rgba(0, 0, 0, 0.16);
|
||||||
|
border-radius: 5px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
#info {
|
||||||
|
height: 95px;
|
||||||
|
width: 260px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
background: #c5d2d8;
|
||||||
|
}
|
||||||
|
#logo {
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
top: 5%;
|
||||||
|
height: 71px;
|
||||||
|
width: 71px;
|
||||||
|
}
|
||||||
|
#title {
|
||||||
|
position: absolute;
|
||||||
|
left: 105px;
|
||||||
|
top: 25%;
|
||||||
|
width: 135px;
|
||||||
|
height: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.menu {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
position: relative;
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 550;
|
||||||
|
}
|
||||||
|
.menu-item {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
padding-left: 40px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.sub-item {
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item img {
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.el-menu {
|
||||||
|
background: transparent !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
.el-menu-item {
|
||||||
|
color: white !important;
|
||||||
|
background-color: #c5d2d8 !important;
|
||||||
|
font-size: 18px !important;
|
||||||
|
}
|
||||||
|
.el-menu-item:hover {
|
||||||
|
outline: 0;
|
||||||
|
background-color: #b8c1c5 !important;
|
||||||
|
}
|
||||||
|
.el-menu-item.is-active {
|
||||||
|
background-color: #c0cbd0 !important;
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logout {
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 550;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
#logout img {
|
||||||
|
height: 35px;
|
||||||
|
width: 35px;
|
||||||
|
margin-right: 15px;
|
||||||
|
margin-left: -30px;
|
||||||
|
}
|
||||||
|
#logout:hover {
|
||||||
|
background: #6fc5f1;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,13 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import VueRouter from 'vue-router'
|
||||||
|
import router from './router'
|
||||||
|
import ElementUI from 'element-ui'
|
||||||
|
import 'element-ui/lib/theme-chalk/index.css';
|
||||||
|
Vue.config.productionTip = false
|
||||||
|
Vue.use(ElementUI)
|
||||||
|
Vue.use(VueRouter)
|
||||||
|
new Vue({
|
||||||
|
render: h => h(App),
|
||||||
|
router,
|
||||||
|
}).$mount('#app')
|
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div id="home">
|
||||||
|
<Sidebar id="sidebar"/>
|
||||||
|
<router-view></router-view>
|
||||||
|
<!-- <HomePart id="home-part"/> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Sidebar from '../components/Sidebar'
|
||||||
|
import HomePart from '../components/HomePart'
|
||||||
|
export default {
|
||||||
|
name: 'Home',
|
||||||
|
components: {
|
||||||
|
Sidebar,
|
||||||
|
HomePart
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
font-family: "微软雅黑";
|
||||||
|
}
|
||||||
|
#home {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
#home-part {
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
#overview {
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
#check-attendance{
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
#check-leave{
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
#empower{
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
#student{
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar {
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,165 @@
|
|||||||
|
<template>
|
||||||
|
<div id="background">
|
||||||
|
<div id="image">
|
||||||
|
<div id="cover">
|
||||||
|
<h1>登录</h1>
|
||||||
|
<input type="text" id="id" v-model="username" placeholder="用户名" /><br />
|
||||||
|
<input type="password" id="pwd" v-model="password" placeholder="密码" @keyup.enter="login" />
|
||||||
|
<button id="loginbtn" @click="login" >登录</button>
|
||||||
|
|
||||||
|
<router-link to="/register">
|
||||||
|
<button id="registerbtn">注册</button>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Login } from "@/api/api";
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
login() {
|
||||||
|
let loginData = {
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
};
|
||||||
|
Login(loginData).then(
|
||||||
|
(res) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
localStorage.setItem("token", res.data.token);
|
||||||
|
localStorage.setItem("name", res.data.name);
|
||||||
|
this.$message.success("登录成功!");
|
||||||
|
this.$router.push("/home");
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg);
|
||||||
|
console.log(res);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
this.$message.error(err.msg);
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#background {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
min-width: 1000px;
|
||||||
|
min-height: 500px;
|
||||||
|
background-image: url("../assets/login/login-background.png");
|
||||||
|
background-size: cover;
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
#image {
|
||||||
|
width: 65.8%;
|
||||||
|
height: 60%;
|
||||||
|
min-width: 1000px;
|
||||||
|
min-height: 500px;
|
||||||
|
background-image: url("../assets/login/login-image.png");
|
||||||
|
background-size: cover;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
@keyframes move {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(0%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cover {
|
||||||
|
width: 50%;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 500px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
background-size: fill;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 20px;
|
||||||
|
animation: move 1s ease-in-out;
|
||||||
|
}
|
||||||
|
#cover h1 {
|
||||||
|
position: absolute;
|
||||||
|
left: 40%;
|
||||||
|
top: 10%;
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 52px;
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: #000000;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#id {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
padding: 5px 10px;
|
||||||
|
top: 32%;
|
||||||
|
left: 11%;
|
||||||
|
width: 75%;
|
||||||
|
height: 10%;
|
||||||
|
font-size: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
#pwd {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
padding: 5px 10px;
|
||||||
|
top: 50%;
|
||||||
|
left: 11%;
|
||||||
|
width: 75%;
|
||||||
|
height: 10%;
|
||||||
|
font-size: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
top: 70%;
|
||||||
|
left: 25%;
|
||||||
|
width: 100px;
|
||||||
|
height: 50px;
|
||||||
|
position: absolute;
|
||||||
|
font-size: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-width: 0px;
|
||||||
|
background-color: #77b6e1;
|
||||||
|
color: white;
|
||||||
|
transition: background-color ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
#registerbtn {
|
||||||
|
left: 52%;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
background-color: #d69898;
|
||||||
|
color: #ffffff;
|
||||||
|
border-color: #000000;
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
border-style: inset;
|
||||||
|
background-color: #d28686;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,194 @@
|
|||||||
|
<template>
|
||||||
|
<div id="background">
|
||||||
|
<div id="image">
|
||||||
|
<div id="cover">
|
||||||
|
<h1>注册</h1>
|
||||||
|
<input type="text" id="id" placeholder="用户名" v-model="username" /><br />
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="pwd"
|
||||||
|
placeholder="密码"
|
||||||
|
v-model="password"
|
||||||
|
/><br />
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="repwd"
|
||||||
|
placeholder="确认密码"
|
||||||
|
v-model="rePassword"
|
||||||
|
/><br />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="name"
|
||||||
|
placeholder="真实姓名"
|
||||||
|
v-model="name"
|
||||||
|
/><br />
|
||||||
|
|
||||||
|
<router-link to="/login">
|
||||||
|
<button id="loginbtn">登录</button>
|
||||||
|
</router-link>
|
||||||
|
<button id="registerbtn" @click="register">注册</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { GetCode, Register } from "@/api/api";
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
id: "",
|
||||||
|
password: "",
|
||||||
|
rePassword: "",
|
||||||
|
name: "",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
register() {
|
||||||
|
if (this.username == "") {
|
||||||
|
this.$message.error("请输入用户名");
|
||||||
|
} else if (this.password == "") {
|
||||||
|
this.$message.error("请输入密码");
|
||||||
|
} else if (this.rePassword == "") {
|
||||||
|
this.$message.error("请确认密码");
|
||||||
|
} else if(this.password != this.rePassword){
|
||||||
|
this.$message.error("两次密码不一致,请重新输入");
|
||||||
|
} else {
|
||||||
|
Register({
|
||||||
|
username: this.username,
|
||||||
|
password: this.password,
|
||||||
|
name: this.name
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
this.$message.success("注册成功");
|
||||||
|
this.$router.push("/login");
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#background {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
min-width: 1000px;
|
||||||
|
min-height: 500px;
|
||||||
|
background-image: url("../assets/login/login-background.png");
|
||||||
|
background-size: cover;
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
#image {
|
||||||
|
width: 65.8%;
|
||||||
|
height: 60%;
|
||||||
|
min-width: 1000px;
|
||||||
|
min-height: 500px;
|
||||||
|
background-image: url("../assets/login/login-image.png");
|
||||||
|
background-size: cover;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 20px;
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
@keyframes move {
|
||||||
|
0% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateX(0%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cover {
|
||||||
|
width: 50%;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 500px;
|
||||||
|
background: rgba(255, 255, 255, 1);
|
||||||
|
background-size: fill;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 20px;
|
||||||
|
animation: move 1s ease-in-out;
|
||||||
|
}
|
||||||
|
#cover h1 {
|
||||||
|
position: absolute;
|
||||||
|
left: 40%;
|
||||||
|
top: 10%;
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 52px;
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: #000000;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
padding: 5px 10px;
|
||||||
|
left: 11%;
|
||||||
|
width: 75%;
|
||||||
|
height: 10%;
|
||||||
|
font-size: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#id {
|
||||||
|
top: 24%;
|
||||||
|
}
|
||||||
|
#pwd {
|
||||||
|
top: 36%;
|
||||||
|
}
|
||||||
|
#repwd {
|
||||||
|
top: 48%;
|
||||||
|
}
|
||||||
|
#name {
|
||||||
|
top: 60%;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
top: 87.5%;
|
||||||
|
left: 25%;
|
||||||
|
width: 100px;
|
||||||
|
height: 50px;
|
||||||
|
position: absolute;
|
||||||
|
font-size: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-width: 0px;
|
||||||
|
background-color: #77b6e1;
|
||||||
|
color: white;
|
||||||
|
transition: background-color ease-in-out 0.3s;
|
||||||
|
}
|
||||||
|
#codeform {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
#registerbtn {
|
||||||
|
left: 52%;
|
||||||
|
}
|
||||||
|
#getcode {
|
||||||
|
width: 30%;
|
||||||
|
top: 72.5%;
|
||||||
|
left: 56%;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
background-color: #d69898;
|
||||||
|
color: #ffffff;
|
||||||
|
border-color: #000000;
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
border-style: inset;
|
||||||
|
background-color: #d28686;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,45 @@
|
|||||||
|
import VueRouter from "vue-router";
|
||||||
|
import Login from "../pages/Login";
|
||||||
|
import Register from "../pages/Register";
|
||||||
|
import Home from "../pages/Home";
|
||||||
|
import HomePart from "../components/HomePart";
|
||||||
|
import Student from "../components/Student";
|
||||||
|
import RollCall from "../components/RollCall";
|
||||||
|
import Question from "../components/Question";
|
||||||
|
export default new VueRouter({
|
||||||
|
mode: 'history',
|
||||||
|
routes: [{
|
||||||
|
path: '/login',
|
||||||
|
component: Login
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/register',
|
||||||
|
component: Register
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
component: Home,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'home',
|
||||||
|
component: HomePart
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'student',
|
||||||
|
component: Student
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'roll-call',
|
||||||
|
component: RollCall
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/question',
|
||||||
|
name: 'question',
|
||||||
|
component: Question, // 这是你的组件
|
||||||
|
}
|
||||||
|
],
|
||||||
|
redirect: '/home'
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
@ -0,0 +1,62 @@
|
|||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
from pathlib import WindowsPath
|
||||||
|
from typing import Optional, List
|
||||||
|
|
||||||
|
|
||||||
|
class DirectionTree:
|
||||||
|
def __init__(self,
|
||||||
|
direction_name: str = 'WorkingDirection',
|
||||||
|
direction_path: str = '.',
|
||||||
|
ignore_list: Optional[List[str]] = None):
|
||||||
|
self.owner: WindowsPath = Path(direction_path)
|
||||||
|
self.tree: str = direction_name + '/\n'
|
||||||
|
self.ignore_list = ignore_list
|
||||||
|
if ignore_list is None:
|
||||||
|
self.ignore_list = []
|
||||||
|
self.direction_ergodic(path_object=self.owner, n=0)
|
||||||
|
|
||||||
|
def tree_add(self, path_object: WindowsPath, n=0, last=False):
|
||||||
|
if n > 0:
|
||||||
|
if last:
|
||||||
|
self.tree += '│' + (' │' * (n - 1)) + ' └────' + path_object.name
|
||||||
|
else:
|
||||||
|
self.tree += '│' + (' │' * (n - 1)) + ' ├────' + path_object.name
|
||||||
|
else:
|
||||||
|
if last:
|
||||||
|
self.tree += '└' + ('──' * 2) + path_object.name
|
||||||
|
else:
|
||||||
|
self.tree += '├' + ('──' * 2) + path_object.name
|
||||||
|
if path_object.is_file():
|
||||||
|
self.tree += '\n'
|
||||||
|
return False
|
||||||
|
elif path_object.is_dir():
|
||||||
|
self.tree += '/\n'
|
||||||
|
return True
|
||||||
|
|
||||||
|
def filter_file(self, file):
|
||||||
|
for item in self.ignore_list:
|
||||||
|
if re.fullmatch(item, file.name):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def direction_ergodic(self, path_object: WindowsPath, n=0):
|
||||||
|
dir_file: list = list(path_object.iterdir())
|
||||||
|
dir_file.sort(key=lambda x: x.name.lower())
|
||||||
|
dir_file = [f for f in filter(self.filter_file, dir_file)]
|
||||||
|
for i, item in enumerate(dir_file):
|
||||||
|
if i + 1 == len(dir_file):
|
||||||
|
if self.tree_add(item, n, last=True):
|
||||||
|
self.direction_ergodic(item, n + 1)
|
||||||
|
else:
|
||||||
|
if self.tree_add(item, n, last=False):
|
||||||
|
self.direction_ergodic(item, n + 1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
i_l = [
|
||||||
|
'\.git', '__pycache__', 'test.+', 'venv', '.+\.whl', '\.idea', '.+\.jpg', '.+\.png',
|
||||||
|
'image', 'css', 'admin', 'db.sqlite3'
|
||||||
|
]
|
||||||
|
tree = DirectionTree(ignore_list=i_l, direction_path='./')
|
||||||
|
print(tree.tree)
|