diff --git a/.gitignore b/.gitignore index df0b6ab..fee6c7c 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,4 @@ out/ ### VS Code ### .vscode/ -application.properties \ No newline at end of file +run/ \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index b624cce..0276e8f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -26,13 +26,23 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-data-redis") implementation("org.springframework.boot:spring-boot-starter-security") - implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-web") { + exclude("org.springframework.boot", "spring-boot-starter-json") + } implementation("org.springframework.boot:spring-boot-starter-websocket") // https://mvnrepository.com/artifact/org.mybatis/mybatis implementation("org.mybatis:mybatis:3.5.13") implementation("com.baomidou:mybatis-plus-boot-starter:3.5.3.1") { exclude("org.mybatis", "mybatis") } + // https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 + implementation("com.alibaba.fastjson2:fastjson2:2.0.38") + // https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension + implementation("com.alibaba.fastjson2:fastjson2-extension:2.0.38") + // https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2-extension-spring6 + implementation("com.alibaba.fastjson2:fastjson2-extension-spring6:2.0.38") + // https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0") compileOnly("org.projectlombok:lombok") developmentOnly("org.springframework.boot:spring-boot-devtools") runtimeOnly("com.mysql:mysql-connector-j") diff --git a/src/main/java/cn/wzpmc/commerce/CommerceSystemBackendApplication.java b/src/main/java/cn/wzpmc/commerce/CommerceSystemBackendApplication.java index 8013cb6..9e8720a 100644 --- a/src/main/java/cn/wzpmc/commerce/CommerceSystemBackendApplication.java +++ b/src/main/java/cn/wzpmc/commerce/CommerceSystemBackendApplication.java @@ -1,11 +1,12 @@ package cn.wzpmc.commerce; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication +@MapperScan("cn.wzpmc.commerce.mappers") public class CommerceSystemBackendApplication { - public static void main(String[] args) { SpringApplication.run(CommerceSystemBackendApplication.class, args); } diff --git a/src/main/java/cn/wzpmc/commerce/config/CorsConfiguration.java b/src/main/java/cn/wzpmc/commerce/config/CorsConfiguration.java new file mode 100644 index 0000000..200d31c --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/config/CorsConfiguration.java @@ -0,0 +1,16 @@ +package cn.wzpmc.commerce.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfiguration implements WebMvcConfigurer { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOriginPatterns("**") + .allowedMethods("GET", "POST", "HEAD", "OPTION", "PUT") + .allowCredentials(true); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/config/FastJsonMvcConfiguration.java b/src/main/java/cn/wzpmc/commerce/config/FastJsonMvcConfiguration.java new file mode 100644 index 0000000..1192f02 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/config/FastJsonMvcConfiguration.java @@ -0,0 +1,32 @@ +package cn.wzpmc.commerce.config; + +import com.alibaba.fastjson2.JSONWriter; +import com.alibaba.fastjson2.support.config.FastJsonConfig; +import com.alibaba.fastjson2.support.spring6.http.converter.FastJsonHttpMessageConverter; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.lang.NonNull; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +@Configuration +public class FastJsonMvcConfiguration implements WebMvcConfigurer { + private static final boolean debug = false; + + @Override + public void configureMessageConverters(@NonNull List> converters) { + FastJsonConfig fastJsonConfig = new FastJsonConfig(); + fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); + fastJsonConfig.setCharset(StandardCharsets.UTF_8); + JSONWriter.Feature[] writerFeatures = {JSONWriter.Feature.MapSortField, JSONWriter.Feature.IgnoreNonFieldGetter, JSONWriter.Feature.PrettyFormat}; + if (!debug) { + writerFeatures = new JSONWriter.Feature[]{JSONWriter.Feature.MapSortField, JSONWriter.Feature.IgnoreNonFieldGetter}; + } + fastJsonConfig.setWriterFeatures(writerFeatures); + FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); + converter.setFastJsonConfig(fastJsonConfig); + converters.add(0, converter); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/config/SecurityConfig.java b/src/main/java/cn/wzpmc/commerce/config/SecurityConfig.java new file mode 100644 index 0000000..3285ec3 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/config/SecurityConfig.java @@ -0,0 +1,79 @@ +package cn.wzpmc.commerce.config; + +import cn.wzpmc.commerce.controllers.AuthController; +import cn.wzpmc.commerce.utils.MessageResponse; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.AccessDeniedHandler; + +import java.io.IOException; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + @SneakyThrows + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity security) { + security.authorizeHttpRequests(registry -> registry.requestMatchers("/api/auth/**", + "/swagger-ui/**", + "/swagger-ui.html", + "/v3/**").permitAll() + .anyRequest().authenticated()); + security.csrf(AbstractHttpConfigurer::disable); + security.cors(AbstractHttpConfigurer::disable); + security.formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer + .loginPage("/api/auth/notLogin") + .loginProcessingUrl("/api/auth/login") + .successHandler(AuthController::loginSuccess) + .failureHandler(AuthController::loginFailed)); + security.logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.logoutUrl("/api/auth/logout") + .logoutSuccessHandler(AuthController::logoutSuccess) + .permitAll()); + security.exceptionHandling(httpSecurityExceptionHandlingConfigurer -> httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(new MyAuthenticationEntryPoint()) + .accessDeniedHandler(new MyAccessDeniedHandler())); + return security.build(); + } + + @Bean + public BCryptPasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + private static class MyAuthenticationEntryPoint implements AuthenticationEntryPoint { + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { + String localizedMessage = authException.getLocalizedMessage(); + response.setStatus(403); + response.setContentType("application/json"); + ServletOutputStream outputStream = response.getOutputStream(); + new MessageResponse(localizedMessage, 403).copyToStream(outputStream); + outputStream.close(); + } + } + + private static class MyAccessDeniedHandler implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { + String localizedMessage = accessDeniedException.getLocalizedMessage(); + response.setStatus(404); + response.setContentType("application/json"); + ServletOutputStream outputStream = response.getOutputStream(); + new MessageResponse(localizedMessage, 403).copyToStream(outputStream); + outputStream.close(); + } + } +} diff --git a/src/main/java/cn/wzpmc/commerce/controllers/AuthController.java b/src/main/java/cn/wzpmc/commerce/controllers/AuthController.java new file mode 100644 index 0000000..11b4ce1 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/controllers/AuthController.java @@ -0,0 +1,81 @@ +package cn.wzpmc.commerce.controllers; + +import cn.wzpmc.commerce.entities.User; +import cn.wzpmc.commerce.entities.vo.AccountVo; +import cn.wzpmc.commerce.services.UserService; +import cn.wzpmc.commerce.utils.DataResponse; +import cn.wzpmc.commerce.utils.MessageResponse; +import io.swagger.v3.oas.annotations.Hidden; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "AuthController", description = "用户权限、登录、注册控制器") +@RestController +@RequestMapping("/api/auth") +public class AuthController { + private final UserService service; + + @Autowired + public AuthController(UserService service) { + this.service = service; + } + + @SneakyThrows + public static void loginSuccess(HttpServletRequest ignoredRequest, HttpServletResponse response, Authentication authentication) { + response.setStatus(200); + response.setContentType("application/json"); + ServletOutputStream outputStream = response.getOutputStream(); + new DataResponse<>((User) authentication.getPrincipal(), "登陆成功!").copyToStream(outputStream); + outputStream.close(); + } + + @SneakyThrows + public static void loginFailed(HttpServletRequest ignoredRequest, HttpServletResponse response, AuthenticationException authenticationException) { + response.setStatus(403); + response.setContentType("application/json"); + ServletOutputStream outputStream = response.getOutputStream(); + new MessageResponse(authenticationException.getLocalizedMessage(), 403).copyToStream(outputStream); + outputStream.close(); + } + + @SneakyThrows + public static void logoutSuccess(HttpServletRequest ignoredRequest, HttpServletResponse response, Authentication ignoredAuthentication) { + response.setStatus(200); + response.setContentType("application/json"); + ServletOutputStream outputStream = response.getOutputStream(); + new MessageResponse("登出成功!").copyToStream(outputStream); + outputStream.close(); + } + + @SneakyThrows + @Hidden + @GetMapping("/notLogin") + public void notLogin(HttpServletResponse response) { + response.setStatus(403); + response.setContentType("application/json"); + ServletOutputStream outputStream = response.getOutputStream(); + new MessageResponse("未登录", 403).copyToStream(outputStream); + outputStream.close(); + } + + @SneakyThrows + @Operation(summary = "注册", description = "注册一个账号") + @ApiResponse(responseCode = "200", description = "返回一个用户对象") + @PostMapping("/register") + public MessageResponse register(@RequestBody AccountVo accountVo) { + User user = service.addUser(accountVo); + if (user != null) { + return new DataResponse<>(user, "注册成功!"); + } + return new MessageResponse("注册失败!用户已存在!", 304); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/controllers/PermissionController.java b/src/main/java/cn/wzpmc/commerce/controllers/PermissionController.java new file mode 100644 index 0000000..654b722 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/controllers/PermissionController.java @@ -0,0 +1,78 @@ +package cn.wzpmc.commerce.controllers; + +import cn.wzpmc.commerce.entities.User; +import cn.wzpmc.commerce.entities.vo.PermissionVo; +import cn.wzpmc.commerce.services.PermissionService; +import cn.wzpmc.commerce.utils.DataResponse; +import cn.wzpmc.commerce.utils.MessageResponse; +import cn.wzpmc.commerce.utils.PageableResponse; +import cn.wzpmc.commerce.utils.ServiceUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@Tag(name = "权限控制器", description = "权限管理器(CRUD)") +@RequestMapping("/authPermissions") +public class PermissionController { + private final PermissionService permissionService; + + @Autowired + public PermissionController(PermissionService permissionService) { + this.permissionService = permissionService; + } + + @Operation(summary = "添加一个权限") + @PostMapping(path = "/addAuthPermissions") + public MessageResponse addAuthPermissions(@RequestBody PermissionVo authPermissionVo, Authentication authentication) { + authPermissionVo.setCreateId(((User) authentication.getPrincipal()).getId()); + if (permissionService.save(authPermissionVo)) { + return new MessageResponse("添加成功!"); + } + return new MessageResponse("添加失败!", 500); + } + + @Operation(summary = "修改权限") + @PostMapping(path = "/changeAuthPermissions") + public MessageResponse changeAuthPermissions(@RequestBody PermissionVo authPermissionVo) { + if (ServiceUtils.update(permissionService, authPermissionVo)) { + return new MessageResponse("修改成功!"); + } + return new MessageResponse("修改失败!", 500); + } + + @Operation(summary = "删除权限") + @GetMapping(path = "/delAuthPermissions") + public MessageResponse delAuthPermissions(@RequestParam("id") int id) { + if (permissionService.removeById(id)) { + return new MessageResponse("删除成功!"); + } + return new MessageResponse("删除失败,未找到!", 500); + } + + @Operation(summary = "分页获取权限") + @GetMapping(path = "/getAuthPermissions") + public PageableResponse getAuthPermissions(@RequestParam("page") int page, @RequestParam("num") int num) { + return PageableResponse.of(permissionService.page(new Page<>(page, num))); + } + + @Operation(summary = "修改一个权限的状态") + @GetMapping(path = "/changeAuthPermissionsStats") + public MessageResponse changeAuthPermissionsStats(@RequestParam("authPermissionId") int id, @RequestParam("status") boolean status) { + if (ServiceUtils.updateStatus(this.permissionService, id, status)) { + return new MessageResponse("修改成功!"); + } + return new MessageResponse("修改失败!", 500); + } + + @Operation(summary = "获取所有权限") + @GetMapping(path = "/getAuthPermissionsId") + public DataResponse> getAuthPermissionsId() { + return new DataResponse<>(permissionService.list()); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/controllers/UserController.java b/src/main/java/cn/wzpmc/commerce/controllers/UserController.java new file mode 100644 index 0000000..ffd26c4 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/controllers/UserController.java @@ -0,0 +1,59 @@ +package cn.wzpmc.commerce.controllers; + +import cn.wzpmc.commerce.entities.User; +import cn.wzpmc.commerce.entities.vo.AccountVo; +import cn.wzpmc.commerce.services.UserService; +import cn.wzpmc.commerce.utils.DataResponse; +import cn.wzpmc.commerce.utils.MessageResponse; +import cn.wzpmc.commerce.utils.PageableResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +@Tag(name = "用户账号控制器", description = "用户的增删改查") +@RestController +@RequestMapping("/account") +public class UserController { + private final UserService userService; + + @Autowired + public UserController(UserService userService) { + this.userService = userService; + } + + @Operation(summary = "更改账户信息", description = "使用传入账号的id对账户信息进行更改(包括用户名、邮箱、真名、权限组)") + @PostMapping("/changeAccount") + public MessageResponse changeAccount(@RequestBody AccountVo accountVo) { + return this.userService.changeAccount(accountVo); + } + + @Operation(summary = "修改密码", parameters = {@Parameter(name = "userId", description = "用户id"), @Parameter(name = "oldPassword", description = "旧密码"), @Parameter(name = "newPassword", description = "新密码")}) + @PostMapping("/changePassword") + public MessageResponse changePassword(@RequestParam("userId") Integer userId, @RequestParam("oldPassword") String oldPassword, @RequestParam("newPassword") String newPassword) { + return this.userService.changePassword(userId, oldPassword, newPassword); + } + + @Operation(summary = "删除用户", parameters = {@Parameter(name = "id", description = "用户id")}) + @GetMapping("/delUser") + public MessageResponse delUser(@RequestParam("id") Integer id, Authentication authentication) { + if (id.equals(((User) authentication.getPrincipal()).getId())) { + return new MessageResponse("不能删除自己!", 403); + } + return this.userService.delUser(id); + } + + @Operation(summary = "获取用户", parameters = {@Parameter(name = "page", description = "页数"), @Parameter(name = "num", description = "每页数量")}) + @GetMapping("/getUser") + public PageableResponse getUser(@RequestParam("page") Long page, @RequestParam("num") Long num, Authentication authentication) { + return this.userService.getUser(page, num, authentication); + } + + @Operation(summary = "获取当前用户信息") + @GetMapping("/getUserInfo") + public DataResponse getUserInfo(Authentication authentication) { + return new DataResponse<>((User) authentication.getPrincipal()); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/Group.java b/src/main/java/cn/wzpmc/commerce/entities/Group.java new file mode 100644 index 0000000..e09dbc6 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/Group.java @@ -0,0 +1,23 @@ +package cn.wzpmc.commerce.entities; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; +import java.util.List; + +@Data +public class Group { + private Integer id; + private String name; + private String description; + private List permissions; + private int createId; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/MerchantUser.java b/src/main/java/cn/wzpmc/commerce/entities/MerchantUser.java new file mode 100644 index 0000000..1e71b71 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/MerchantUser.java @@ -0,0 +1,34 @@ +package cn.wzpmc.commerce.entities; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@Data +public class MerchantUser extends User { + private Integer countDown; + private List orders; + private List commissions; + + public void calcOrderCommission() { + MerchantUserCommission[] array = commissions.toArray(new MerchantUserCommission[]{}); + Arrays.sort(array, Comparator.comparingDouble(MerchantUserCommission::getPriceMin)); + orderFor: + for (Order order : orders) { + double price = order.getPayAmt(); + for (MerchantUserCommission commission : array) { + if (price >= commission.getPriceMin() && price <= commission.getPriceMax()) { + order.setCommission(price * commission.getCommission()); + continue orderFor; + } + } + order.setCommission(0); + } + } +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/MerchantUserCommission.java b/src/main/java/cn/wzpmc/commerce/entities/MerchantUserCommission.java new file mode 100644 index 0000000..6534917 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/MerchantUserCommission.java @@ -0,0 +1,21 @@ +package cn.wzpmc.commerce.entities; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +public class MerchantUserCommission { + private int id; + private double priceMin; + private double priceMax; + private double commission; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/Order.java b/src/main/java/cn/wzpmc/commerce/entities/Order.java new file mode 100644 index 0000000..b6daf2e --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/Order.java @@ -0,0 +1,36 @@ +package cn.wzpmc.commerce.entities; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +public class Order { + private int id; + private String orderNo; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date orderTime; + private String orderStatus; + private String wangNo; + private String weChatNo; + private String alipayNo; + private double payAmt; + private int storeId; + private double commission; + private String alipayName; + private String rpName; + private String rpWeChatName; + private String remark; + private String phoneNumber; + private String cardNo; + private int flag; + private String flagRemark; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date payTime; + private String address; + private String sku; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/Permission.java b/src/main/java/cn/wzpmc/commerce/entities/Permission.java new file mode 100644 index 0000000..26583b6 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/Permission.java @@ -0,0 +1,30 @@ +package cn.wzpmc.commerce.entities; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Date; + +@Data +public class Permission implements GrantedAuthority { + private Integer id; + private String name; + private String code; + private String description; + private int createId; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + + @Override + @JSONField(serialize = false) + public String getAuthority() { + return this.code; + } +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/User.java b/src/main/java/cn/wzpmc/commerce/entities/User.java new file mode 100644 index 0000000..4c5ce02 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/User.java @@ -0,0 +1,51 @@ +package cn.wzpmc.commerce.entities; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.Date; + +@Data +public class User implements UserDetails { + private Integer id; + private String username; + private String email; + private String relName; + private String password; + private Group group; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + + @Override + public Collection getAuthorities() { + return this.group.getPermissions(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/vo/AccountVo.java b/src/main/java/cn/wzpmc/commerce/entities/vo/AccountVo.java new file mode 100644 index 0000000..25a731f --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/vo/AccountVo.java @@ -0,0 +1,37 @@ +package cn.wzpmc.commerce.entities.vo; + +import cn.wzpmc.commerce.utils.ServiceUtils; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@TableName("account") +public class AccountVo { + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + @ServiceUtils.Updatable + private String username; + @ServiceUtils.Updatable + private String email; + @ServiceUtils.Updatable + @TableField("rel_name") + private String relName; + private String password; + @ServiceUtils.Updatable + @TableField("group_id") + private Integer groupId; + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @TableField(value = "update_time", update = "now()") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + @TableLogic + private boolean del; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/vo/BlackListVo.java b/src/main/java/cn/wzpmc/commerce/entities/vo/BlackListVo.java new file mode 100644 index 0000000..0b164e5 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/vo/BlackListVo.java @@ -0,0 +1,33 @@ +package cn.wzpmc.commerce.entities.vo; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@TableName("blacklist") +public class BlackListVo { + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + @TableField("store_id") + private Integer storeId; + @TableField("wang_no") + private String wangNo; + @TableField("wechat_no") + private String weChatNo; + @TableField("create_id") + private Integer createId; + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @TableField(value = "update_time", update = "now()") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + @TableLogic + private boolean del; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/vo/CommissionVo.java b/src/main/java/cn/wzpmc/commerce/entities/vo/CommissionVo.java new file mode 100644 index 0000000..38e3b17 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/vo/CommissionVo.java @@ -0,0 +1,41 @@ +package cn.wzpmc.commerce.entities.vo; + +import cn.wzpmc.commerce.utils.ServiceUtils; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@TableName("commission") +public class CommissionVo { + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + @ServiceUtils.Updatable + @TableField("range_min") + private Double range_min; + @ServiceUtils.Updatable + @TableField("range_max") + private Double range_max; + @ServiceUtils.Updatable + private Double base; + @ServiceUtils.Updatable + private Double extra; + @ServiceUtils.Updatable + @TableField("store_id") + private Integer storeId; + @TableField("create_id") + private Integer createId; + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @TableField(value = "update_time", update = "now()") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + @TableLogic + private boolean del; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/vo/GroupVo.java b/src/main/java/cn/wzpmc/commerce/entities/vo/GroupVo.java new file mode 100644 index 0000000..8811427 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/vo/GroupVo.java @@ -0,0 +1,32 @@ +package cn.wzpmc.commerce.entities.vo; + +import cn.wzpmc.commerce.utils.ServiceUtils; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@TableName("group") +public class GroupVo { + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + @ServiceUtils.Updatable + private String name; + @ServiceUtils.Updatable + private String description; + @TableField("create_id") + private Integer createId; + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @TableField(value = "update_time", update = "now()") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + @TableLogic + private boolean del; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/vo/OrderVo.java b/src/main/java/cn/wzpmc/commerce/entities/vo/OrderVo.java new file mode 100644 index 0000000..2c73ab5 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/vo/OrderVo.java @@ -0,0 +1,51 @@ +package cn.wzpmc.commerce.entities.vo; + +import cn.wzpmc.commerce.enums.OrderStatus; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@TableName("order") +public class OrderVo { + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + private String no; + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date time; + private OrderStatus status; + @TableField("wang_no") + private String wangNo; + @TableField("wechat_no") + private String weChatNo; + @TableField("alipay_no") + private String alipayNo; + @TableField("alipay_name") + private String alipayName; + private String phone; + @TableField("card_no") + private String cardNo; + private Double payment; + @TableField("pay_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date payTime; + @TableField("head_name") + private String headName; + @TableField("head_wechat_name") + private String headWeChatName; + @TableField("store_id") + private Integer storeId; + private String remark; + private Integer flag; + @TableField("flag_remark") + private String flagRemark; + private String address; + private String sku; + @TableLogic + private boolean del; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/vo/PermissionVo.java b/src/main/java/cn/wzpmc/commerce/entities/vo/PermissionVo.java new file mode 100644 index 0000000..8b02f89 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/vo/PermissionVo.java @@ -0,0 +1,36 @@ +package cn.wzpmc.commerce.entities.vo; + +import cn.wzpmc.commerce.utils.ServiceUtils; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@TableName("permissions") +public class PermissionVo { + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + @ServiceUtils.Updatable + private String name; + @ServiceUtils.Updatable + private String code; + @ServiceUtils.Updatable + private String description; + @TableField("group_id") + private Integer groupId; + @TableField("create_id") + private Integer createId; + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @TableField(value = "update_time", update = "now()") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + @TableLogic + private boolean del; +} diff --git a/src/main/java/cn/wzpmc/commerce/entities/vo/StoreVo.java b/src/main/java/cn/wzpmc/commerce/entities/vo/StoreVo.java new file mode 100644 index 0000000..b09aa99 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/entities/vo/StoreVo.java @@ -0,0 +1,36 @@ +package cn.wzpmc.commerce.entities.vo; + +import cn.wzpmc.commerce.utils.ServiceUtils; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +@TableName("store") +public class StoreVo { + @TableId(value = "id", type = IdType.AUTO) + private Integer id; + @ServiceUtils.Updatable + private String name; + @ServiceUtils.Updatable + @TableField("category_id") + private Integer categoryId; + @ServiceUtils.Updatable + @TableField("account_id") + private Integer accountId; + @TableField("create_id") + private Integer createId; + @TableField("create_time") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; + @TableField(value = "update_time", update = "now()") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date updateTime; + @TableLogic + private boolean del; +} diff --git a/src/main/java/cn/wzpmc/commerce/enums/OrderStatus.java b/src/main/java/cn/wzpmc/commerce/enums/OrderStatus.java new file mode 100644 index 0000000..ef5d9ac --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/enums/OrderStatus.java @@ -0,0 +1,6 @@ +package cn.wzpmc.commerce.enums; + +@SuppressWarnings("NonAsciiCharacters") +public enum OrderStatus { + 商家驳回, 已完成, 已确认等待财务审核, 提交, 新建待提交数据, 财务审核已通过, 财务驳回 +} diff --git a/src/main/java/cn/wzpmc/commerce/mappers/AccountMapper.java b/src/main/java/cn/wzpmc/commerce/mappers/AccountMapper.java new file mode 100644 index 0000000..52a5c22 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/mappers/AccountMapper.java @@ -0,0 +1,9 @@ +package cn.wzpmc.commerce.mappers; + +import cn.wzpmc.commerce.entities.vo.AccountVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface AccountMapper extends BaseMapper { +} diff --git a/src/main/java/cn/wzpmc/commerce/mappers/BlackListMapper.java b/src/main/java/cn/wzpmc/commerce/mappers/BlackListMapper.java new file mode 100644 index 0000000..67ecabc --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/mappers/BlackListMapper.java @@ -0,0 +1,9 @@ +package cn.wzpmc.commerce.mappers; + +import cn.wzpmc.commerce.entities.vo.BlackListVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BlackListMapper extends BaseMapper { +} diff --git a/src/main/java/cn/wzpmc/commerce/mappers/CommissionMapper.java b/src/main/java/cn/wzpmc/commerce/mappers/CommissionMapper.java new file mode 100644 index 0000000..4e05333 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/mappers/CommissionMapper.java @@ -0,0 +1,9 @@ +package cn.wzpmc.commerce.mappers; + +import cn.wzpmc.commerce.entities.vo.CommissionVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CommissionMapper extends BaseMapper { +} diff --git a/src/main/java/cn/wzpmc/commerce/mappers/GroupMapper.java b/src/main/java/cn/wzpmc/commerce/mappers/GroupMapper.java new file mode 100644 index 0000000..bc2f07d --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/mappers/GroupMapper.java @@ -0,0 +1,9 @@ +package cn.wzpmc.commerce.mappers; + +import cn.wzpmc.commerce.entities.vo.GroupVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface GroupMapper extends BaseMapper { +} diff --git a/src/main/java/cn/wzpmc/commerce/mappers/OrderMapper.java b/src/main/java/cn/wzpmc/commerce/mappers/OrderMapper.java new file mode 100644 index 0000000..87a6b80 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/mappers/OrderMapper.java @@ -0,0 +1,9 @@ +package cn.wzpmc.commerce.mappers; + +import cn.wzpmc.commerce.entities.vo.OrderVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface OrderMapper extends BaseMapper { +} diff --git a/src/main/java/cn/wzpmc/commerce/mappers/PermissionsMapper.java b/src/main/java/cn/wzpmc/commerce/mappers/PermissionsMapper.java new file mode 100644 index 0000000..e5d7b58 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/mappers/PermissionsMapper.java @@ -0,0 +1,9 @@ +package cn.wzpmc.commerce.mappers; + +import cn.wzpmc.commerce.entities.vo.PermissionVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PermissionsMapper extends BaseMapper { +} diff --git a/src/main/java/cn/wzpmc/commerce/mappers/StoreMapper.java b/src/main/java/cn/wzpmc/commerce/mappers/StoreMapper.java new file mode 100644 index 0000000..953f5dd --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/mappers/StoreMapper.java @@ -0,0 +1,9 @@ +package cn.wzpmc.commerce.mappers; + +import cn.wzpmc.commerce.entities.vo.StoreVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface StoreMapper extends BaseMapper { +} diff --git a/src/main/java/cn/wzpmc/commerce/services/PermissionService.java b/src/main/java/cn/wzpmc/commerce/services/PermissionService.java new file mode 100644 index 0000000..aa56497 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/services/PermissionService.java @@ -0,0 +1,10 @@ +package cn.wzpmc.commerce.services; + +import cn.wzpmc.commerce.entities.vo.PermissionVo; +import cn.wzpmc.commerce.mappers.PermissionsMapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +@Service +public class PermissionService extends ServiceImpl { +} diff --git a/src/main/java/cn/wzpmc/commerce/services/UserService.java b/src/main/java/cn/wzpmc/commerce/services/UserService.java new file mode 100644 index 0000000..8789088 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/services/UserService.java @@ -0,0 +1,153 @@ +package cn.wzpmc.commerce.services; + +import cn.wzpmc.commerce.entities.Group; +import cn.wzpmc.commerce.entities.Permission; +import cn.wzpmc.commerce.entities.User; +import cn.wzpmc.commerce.entities.vo.AccountVo; +import cn.wzpmc.commerce.entities.vo.GroupVo; +import cn.wzpmc.commerce.entities.vo.PermissionVo; +import cn.wzpmc.commerce.mappers.AccountMapper; +import cn.wzpmc.commerce.mappers.GroupMapper; +import cn.wzpmc.commerce.mappers.PermissionsMapper; +import cn.wzpmc.commerce.utils.EntitiesUtils; +import cn.wzpmc.commerce.utils.MessageResponse; +import cn.wzpmc.commerce.utils.PageableResponse; +import cn.wzpmc.commerce.utils.ServiceUtils; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +@Service +public class UserService extends ServiceImpl implements UserDetailsService { + private final AccountMapper accountMapper; + private final PermissionsMapper permissionsMapper; + private final GroupMapper groupMapper; + private final PasswordEncoder encoder; + private final Map userContexts = new HashMap<>(); + + @Autowired + public UserService(AccountMapper accountMapper, PermissionsMapper permissionsMapper, GroupMapper rolesMapper, PasswordEncoder encoder) { + this.accountMapper = accountMapper; + this.permissionsMapper = permissionsMapper; + this.groupMapper = rolesMapper; + this.encoder = encoder; + } + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + SecurityContext context = SecurityContextHolder.getContext(); + User userByName = getUserByName(username); + userContexts.put(userByName.getId(), context); + return userByName; + } + + public User addUser(AccountVo accountVo) { + try { + this.loadUserByUsername(accountVo.getUsername()); + } catch (UsernameNotFoundException e) { + accountVo.setPassword(this.encoder.encode(accountVo.getPassword())); + accountVo.setCreateTime(new Date()); + this.accountMapper.insert(accountVo); + return this.getUserByName(accountVo.getUsername()); + } + return null; + } + + private User getUserByName(String username) throws UsernameNotFoundException { + AccountVo accountVo = this.accountMapper.selectOne(new QueryWrapper() + .eq("username", username) + ); + if (accountVo == null) { + throw new UsernameNotFoundException("用户不存在"); + } + return genUserFromAuthAccount(accountVo); + } + + private User getUserById(int id) throws UsernameNotFoundException { + AccountVo accountVo = this.accountMapper.selectById(id); + if (accountVo == null) { + throw new UsernameNotFoundException("用户不存在"); + } + return genUserFromAuthAccount(accountVo); + } + + private User genUserFromAuthAccount(AccountVo accountVo) { + User user = EntitiesUtils.copyField(accountVo, new User()); + GroupVo groupVo = groupMapper.selectById(accountVo.getGroupId()); + Group group = EntitiesUtils.copyField(groupVo, new Group()); + group.setPermissions(permissionsMapper.selectList( + new QueryWrapper().eq("group_id", groupVo.getId()) + ).stream().map(e -> EntitiesUtils.copyField(e, new Permission())).toList()); + user.setGroup(group); + return user; + } + + public MessageResponse changeAccount(AccountVo authAccountVo) { + String username = authAccountVo.getUsername(); + Integer id = authAccountVo.getId(); + try { + getUserByName(username); + } catch (UsernameNotFoundException e) { + if (!ServiceUtils.update(this, authAccountVo)) { + return new MessageResponse("修改失败!", 403); + } + this.updateUserAuthentication(id); + return new MessageResponse("修改成功"); + } + return new MessageResponse("修改失败,用户名已存在", 403); + } + + public MessageResponse changePassword(Integer userId, String oldPassword, String newPassword) { + oldPassword = this.encoder.encode(oldPassword); + newPassword = this.encoder.encode(newPassword); + if (this.accountMapper.selectOne(new QueryWrapper().eq("id", userId).eq("password", oldPassword)) == null) { + return new MessageResponse("原密码错误", 403); + } + AccountVo accountVo = new AccountVo(); + accountVo.setId(userId); + accountVo.setPassword(newPassword); + this.accountMapper.updateById(accountVo); + return new MessageResponse("修改成功"); + } + + public MessageResponse delUser(Integer id) { + if (this.accountMapper.deleteById(id) == 0) { + return new MessageResponse("未找到用户", 404); + } + return new MessageResponse("修改成功"); + } + + public PageableResponse getUser(Long page, Long num, Authentication authentication) { + User user = (User) authentication.getPrincipal(); + Integer uid = user.getId(); + Integer id = user.getGroup().getId(); + QueryWrapper queryWrapper = new QueryWrapper().gt("role_id", id).or().eq("id", uid); + Page users = this.accountMapper.selectPage(new Page<>(page, num), queryWrapper); + Long l = this.accountMapper.selectCount(queryWrapper); + return new PageableResponse<>(users.getRecords(), l); + } + + public void updateUserAuthentication(int id) { + if (!userContexts.containsKey(id)) { + return; + } + User userById = getUserById(id); + Authentication newAuth = new UsernamePasswordAuthenticationToken(userById, null, userById.getAuthorities()); + SecurityContext securityContext = userContexts.get(id); + securityContext.setAuthentication(newAuth); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/utils/DataResponse.java b/src/main/java/cn/wzpmc/commerce/utils/DataResponse.java new file mode 100644 index 0000000..0dcf2de --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/utils/DataResponse.java @@ -0,0 +1,31 @@ +package cn.wzpmc.commerce.utils; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +public class DataResponse extends MessageResponse { + private T data; + + public DataResponse(T data, int code, String message) { + super(message, code); + this.data = data; + } + + public DataResponse(T data, String message) { + super(message); + this.data = data; + } + + public DataResponse() { + super(); + this.data = null; + } + + public String toString() { + return super.toString(); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/utils/EntitiesUtils.java b/src/main/java/cn/wzpmc/commerce/utils/EntitiesUtils.java new file mode 100644 index 0000000..da298fe --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/utils/EntitiesUtils.java @@ -0,0 +1,103 @@ +package cn.wzpmc.commerce.utils; + +import cn.wzpmc.commerce.entities.User; +import lombok.NoArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class EntitiesUtils { + + @SneakyThrows + public static T copyField(F from, T to, NameParser parser) { + Class fromClass = from.getClass(); + Class toClass = to.getClass(); + Method[] fromMethods = fromClass.getDeclaredMethods(); + Method[] toMethods = toClass.getDeclaredMethods(); + Map getters = new HashMap<>(); + for (Method fromMethod : fromMethods) { + String methodName = fromMethod.getName(); + if ((methodName.startsWith("get") || methodName.startsWith("is")) && fromMethod.getParameters().length == 0) { + getters.put(parser.getterParse(methodName), fromMethod); + } + } + for (Method toMethod : toMethods) { + String methodName = toMethod.getName(); + Parameter[] parameters = toMethod.getParameters(); + if (methodName.startsWith("set") && parameters.length == 1) { + String fieldName = parser.setterParse(methodName); + if (getters.containsKey(fieldName)) { + Method getter = getters.get(fieldName); + Class returnType = getter.getReturnType(); + if (!parameters[0].getType().equals(returnType)) { + continue; + } + Object fieldValue = getter.invoke(from); + toMethod.invoke(to, fieldValue); + } + } + } + return to; + } + + public static T copyField(F from, T to) { + return copyField(from, to, new NameParser()); + } + + @SneakyThrows + public static void addCreateId(T obj) { + Class aClass = obj.getClass(); + int userId = ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getId(); + for (Field declaredField : aClass.getDeclaredFields()) { + declaredField.setAccessible(true); + if (declaredField.getName().equals("create_id")) { + declaredField.set(obj, userId); + return; + } + } + log.warn("在类{}中未找到create_id", aClass); + } + + @NoArgsConstructor + public static class NameParser { + private final HashMap getterParsers = new HashMap<>(); + private final HashMap setterParsers = new HashMap<>(); + + public NameParser addParser(String from, String to) { + this.getterParsers.put(from, to); + this.setterParsers.put(from, to); + return this; + } + + public NameParser addGetter(String from, String to) { + this.getterParsers.put(from, to); + return this; + } + + public NameParser addSetter(String from, String to) { + this.setterParsers.put(from, to); + return this; + } + + private String getterParse(String from) { + if (from.startsWith("get")) { + from = from.replaceFirst("get", ""); + } else { + from = from.replaceFirst("is", ""); + } + return getterParsers.getOrDefault(from, from); + } + + private String setterParse(String from) { + from = from.replaceFirst("set", ""); + return setterParsers.getOrDefault(from, from); + } + } +} diff --git a/src/main/java/cn/wzpmc/commerce/utils/MessageResponse.java b/src/main/java/cn/wzpmc/commerce/utils/MessageResponse.java new file mode 100644 index 0000000..09a131f --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/utils/MessageResponse.java @@ -0,0 +1,42 @@ +package cn.wzpmc.commerce.utils; + +import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.JSONWriter; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.SneakyThrows; + +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Date; + +@Data +@AllArgsConstructor +public class MessageResponse { + private String msg; + private int code; + private long timestamp; + + public MessageResponse() { + this.code = 200; + this.msg = "成功"; + this.timestamp = new Date().getTime(); + } + + public MessageResponse(String msg) { + this(msg, 200); + } + + public MessageResponse(String msg, int code) { + this(msg, code, new Date().getTime()); + } + + public String toString() { + return JSONObject.from(this).toJSONString(JSONWriter.Feature.IgnoreNonFieldGetter); + } + + @SneakyThrows + public void copyToStream(OutputStream stream) { + stream.write(this.toString().getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/src/main/java/cn/wzpmc/commerce/utils/PageableResponse.java b/src/main/java/cn/wzpmc/commerce/utils/PageableResponse.java new file mode 100644 index 0000000..4b1e04c --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/utils/PageableResponse.java @@ -0,0 +1,35 @@ +package cn.wzpmc.commerce.utils; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@EqualsAndHashCode(callSuper = true) +@Data +public class PageableResponse extends DataResponse> { + public PageableResponse(List data, long total) { + this(new PageableData<>(data, total)); + } + + public PageableResponse(PageableData data) { + super(data); + } + + public static PageableResponse of(Page pageResult) { + return new PageableResponse<>(PageableData.of(pageResult)); + } + + @Data + @AllArgsConstructor + public static class PageableData { + private List info; + private long total; + + public static PageableData of(Page pageResult) { + return new PageableData<>(pageResult.getRecords(), pageResult.getTotal()); + } + } +} diff --git a/src/main/java/cn/wzpmc/commerce/utils/ServiceUtils.java b/src/main/java/cn/wzpmc/commerce/utils/ServiceUtils.java new file mode 100644 index 0000000..391ac06 --- /dev/null +++ b/src/main/java/cn/wzpmc/commerce/utils/ServiceUtils.java @@ -0,0 +1,95 @@ +package cn.wzpmc.commerce.utils; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.util.Objects; + +@Slf4j +public class ServiceUtils { + @SneakyThrows + public static boolean update(IService service, T entities) { + Class entityClass = service.getEntityClass(); + Field[] declaredFields = entityClass.getDeclaredFields(); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + Object id = null; + String idName = "id"; + for (Field field : declaredFields) { + field.setAccessible(true); + String fieldName = field.getName(); + TableId tableId = field.getDeclaredAnnotation(TableId.class); + if (Objects.nonNull(tableId) || fieldName.equals("id")) { + id = field.get(entities); + if (Objects.nonNull(tableId)) { + idName = tableId.value(); + } + } + Updatable declaredAnnotation = field.getDeclaredAnnotation(Updatable.class); + if (declaredAnnotation != null) { + TableField tableField = field.getDeclaredAnnotation(TableField.class); + String name; + if (tableField == null) { + name = fieldName; + } else { + name = tableField.value(); + } + Object value = field.get(entities); + updateWrapper.set(Objects.nonNull(value), name, value); + } + } + if (id == null) { + log.warn("类{}未找到id", entityClass); + return false; + } + updateWrapper.eq(idName, id); + return service.update(updateWrapper); + } + + public static boolean updateStatus(IService service, int id, boolean newStatus) { + Class entityClass = service.getEntityClass(); + Field[] declaredFields = entityClass.getDeclaredFields(); + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + boolean has = false; + for (Field field : declaredFields) { + field.setAccessible(true); + String fieldName = field.getName(); + Status declaredAnnotation = field.getDeclaredAnnotation(Status.class); + if (declaredAnnotation != null) { + TableField tableField = field.getDeclaredAnnotation(TableField.class); + String name; + if (tableField == null) { + name = fieldName; + } else { + name = tableField.value(); + } + has = true; + updateWrapper.set(name, newStatus); + } + } + if (!has) { + log.warn("类{}未找到status注解", entityClass); + return false; + } + updateWrapper.eq("id", id); + return service.update(updateWrapper); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) + public @interface Updatable { + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) + public @interface Status { + } +}