Compare commits

...

10 Commits

Author SHA1 Message Date
lyxaa 183f0ec564 更新 2024-03-28 10:20:47 +08:00
lyxaa f34e555bf6 更新 2024-03-28 10:14:46 +08:00
RuoYi 735273d69f Excel注解ColumnType类型新增文本 2024-03-22 16:44:18 +08:00
RuoYi f2a587c2f9 更新compressionPlugin到6.1.2以兼容node18+ 2024-03-18 14:30:11 +08:00
RuoYi 4f7bcef44c 定时任务白名单配置范围缩小 2024-03-11 11:23:38 +08:00
RuoYi 393a9326c8 update copyright 2024 2024-03-11 10:48:30 +08:00
若依 33a52c8166
!360 update ruoyi-modules/ruoyi-job/src/main/resources/mapper/job/SysJobLogMapper.xml.
Merge pull request !360 from 刘继东/N/A
2024-03-04 01:48:41 +00:00
刘继东 b44e0e4de6
update ruoyi-modules/ruoyi-job/src/main/resources/mapper/job/SysJobLogMapper.xml.
任务运行日志列表增加按创建日期倒叙排序

Signed-off-by: 刘继东 <wwwliujidong@163.com>
2024-03-02 03:52:29 +00:00
RuoYi 3fa4901d57 用户密码新增非法字符验证 2024-03-01 21:55:38 +08:00
RuoYi 2dca6f0a12 优化匹配方式 2024-03-01 21:55:28 +08:00
64 changed files with 1651 additions and 89 deletions

View File

@ -42,7 +42,7 @@ public class SysUser extends BaseEntity
private String email; private String email;
/** 手机号码 */ /** 手机号码 */
@Excel(name = "手机号码") @Excel(name = "手机号码", cellType = ColumnType.TEXT)
private String phonenumber; private String phonenumber;
/** 用户性别 */ /** 用户性别 */

View File

@ -51,7 +51,10 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId> <artifactId>ruoyi-common-security</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -1,5 +1,7 @@
package com.ruoyi.auth; package com.ruoyi.auth;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@ -10,6 +12,8 @@ import com.ruoyi.common.security.annotation.EnableRyFeignClients;
* *
* @author ruoyi * @author ruoyi
*/ */
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients @EnableRyFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiAuthApplication public class RuoYiAuthApplication

View File

@ -14,10 +14,10 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 122.51.27.196:8848
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 122.51.27.196:8848
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -24,6 +24,7 @@
<description> <description>
ruoyi-common通用模块 ruoyi-common通用模块
</description> </description>
</project> </project>

View File

@ -23,6 +23,10 @@
<artifactId>spring-cloud-starter-openfeign</artifactId> <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- SpringCloud Loadbalancer --> <!-- SpringCloud Loadbalancer -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
@ -107,12 +111,10 @@
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<!-- Swagger -->
<dependency> <dependency>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId> <artifactId>swagger-annotations</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -166,7 +166,7 @@ public @interface Excel
public enum ColumnType public enum ColumnType
{ {
NUMERIC(0), STRING(1), IMAGE(2); NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
private final int value; private final int value;
ColumnType(int value) ColumnType(int value)

View File

@ -125,7 +125,7 @@ public class Constants
/** /**
* 访 * 访
*/ */
public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" }; public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.job.task" };
/** /**
* *

View File

@ -42,7 +42,7 @@ public class GenConstants
/** 数据库数字类型 */ /** 数据库数字类型 */
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
"bigint", "float", "double", "decimal" }; "bit", "bigint", "float", "double", "decimal" };
/** 页面不需要编辑字段 */ /** 页面不需要编辑字段 */
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };

View File

@ -0,0 +1,32 @@
package com.ruoyi.common.core.domain;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* @ClassName ProductMeradata
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 14:55
*/
@Data
@ApiModel(value = "三范式")
public class ProductMetadata {
@ApiModelProperty(value = "创建时间", example = "2024-03-26 12:00:00")
private Date createTime;
@ApiModelProperty(value = "修改时间", example = "2024-03-26 12:00:00")
private Date updateTime;
@ApiModelProperty(value = "是否删除", example = "0")
private Integer isDelete;
@ApiModelProperty(value = "创建人ID", example = "123456")
private Long createBy;
}

View File

@ -28,6 +28,7 @@ import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataValidation; import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint; import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper; import org.apache.poi.ss.usermodel.DataValidationHelper;
@ -652,6 +653,8 @@ public class ExcelUtil<T>
titleFont.setFontHeightInPoints((short) 16); titleFont.setFontHeightInPoints((short) 16);
titleFont.setBold(true); titleFont.setBold(true);
style.setFont(titleFont); style.setFont(titleFont);
DataFormat dataFormat = wb.createDataFormat();
style.setDataFormat(dataFormat.getFormat("@"));
styles.put("title", style); styles.put("title", style);
style = wb.createCellStyle(); style = wb.createCellStyle();
@ -714,6 +717,9 @@ public class ExcelUtil<T>
headerFont.setBold(true); headerFont.setBold(true);
headerFont.setColor(excel.headerColor().index); headerFont.setColor(excel.headerColor().index);
style.setFont(headerFont); style.setFont(headerFont);
// 设置表格头单元格文本形式
DataFormat dataFormat = wb.createDataFormat();
style.setDataFormat(dataFormat.getFormat("@"));
headerStyles.put(key, style); headerStyles.put(key, style);
} }
} }
@ -731,8 +737,37 @@ public class ExcelUtil<T>
Map<String, CellStyle> styles = new HashMap<String, CellStyle>(); Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
for (Object[] os : fields) for (Object[] os : fields)
{ {
Field field = (Field) os[0];
Excel excel = (Excel) os[1]; Excel excel = (Excel) os[1];
String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor()); if (Collection.class.isAssignableFrom(field.getType()))
{
ParameterizedType pt = (ParameterizedType) field.getGenericType();
Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
for (Field subField : subFields)
{
Excel subExcel = subField.getAnnotation(Excel.class);
annotationDataStyles(styles, subField, subExcel);
}
}
else
{
annotationDataStyles(styles, field, excel);
}
}
return styles;
}
/**
* Excel
*
* @param styles
* @param field
* @param excel
*/
public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
{
String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
if (!styles.containsKey(key)) if (!styles.containsKey(key))
{ {
CellStyle style = wb.createCellStyle(); CellStyle style = wb.createCellStyle();
@ -753,11 +788,14 @@ public class ExcelUtil<T>
dataFont.setFontHeightInPoints((short) 10); dataFont.setFontHeightInPoints((short) 10);
dataFont.setColor(excel.color().index); dataFont.setColor(excel.color().index);
style.setFont(dataFont); style.setFont(dataFont);
if (ColumnType.TEXT == excel.cellType())
{
DataFormat dataFormat = wb.createDataFormat();
style.setDataFormat(dataFormat.getFormat("@"));
}
styles.put(key, style); styles.put(key, style);
} }
} }
return styles;
}
/** /**
* *
@ -773,7 +811,7 @@ public class ExcelUtil<T>
if (isSubList()) if (isSubList())
{ {
// 填充默认样式,防止合并单元格样式失效 // 填充默认样式,防止合并单元格样式失效
sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
if (attr.needMerge()) if (attr.needMerge())
{ {
sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
@ -791,7 +829,7 @@ public class ExcelUtil<T>
*/ */
public void setCellVo(Object value, Excel attr, Cell cell) public void setCellVo(Object value, Excel attr, Cell cell)
{ {
if (ColumnType.STRING == attr.cellType()) if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
{ {
String cellValue = Convert.toStr(value); String cellValue = Convert.toStr(value);
// 对于任何以表达式触发字符 =-+@开头的单元格直接使用tab字符作为前缀防止CSV注入。 // 对于任何以表达式触发字符 =-+@开头的单元格直接使用tab字符作为前缀防止CSV注入。
@ -903,7 +941,7 @@ public class ExcelUtil<T>
CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column);
sheet.addMergedRegion(cellAddress); sheet.addMergedRegion(cellAddress);
} }
cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType())));
// 用于读取对象中的属性 // 用于读取对象中的属性
Object value = getTargetValue(vo, field, attr); Object value = getTargetValue(vo, field, attr);

View File

@ -27,8 +27,13 @@ public class XssValidator implements ConstraintValidator<Xss, String>
public static boolean containsHtml(String value) public static boolean containsHtml(String value)
{ {
StringBuilder sHtml = new StringBuilder();
Pattern pattern = Pattern.compile(HTML_PATTERN); Pattern pattern = Pattern.compile(HTML_PATTERN);
Matcher matcher = pattern.matcher(value); Matcher matcher = pattern.matcher(value);
return matcher.matches(); while (matcher.find())
{
sHtml.append(matcher.group());
}
return pattern.matcher(sHtml).matches();
} }
} }

View File

@ -30,5 +30,11 @@
<version>${swagger.fox.version}</version> <version>${swagger.fox.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -4,6 +4,9 @@ server:
# Spring # Spring
spring: spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
application: application:
# 应用名称 # 应用名称
name: ruoyi-gateway name: ruoyi-gateway
@ -14,10 +17,10 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 122.51.27.196:8848
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 122.51.27.196:8848
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -13,6 +13,7 @@
<module>ruoyi-gen</module> <module>ruoyi-gen</module>
<module>ruoyi-job</module> <module>ruoyi-job</module>
<module>ruoyi-file</module> <module>ruoyi-file</module>
<module>ruoyi-product</module>
</modules> </modules>
<artifactId>ruoyi-modules</artifactId> <artifactId>ruoyi-modules</artifactId>

View File

@ -42,6 +42,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d') and date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
</if> </if>
</where> </where>
order by create_time desc
</select> </select>
<select id="selectJobLogAll" resultMap="SysJobLogResult"> <select id="selectJobLogAll" resultMap="SysJobLogResult">

View File

@ -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/

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-product</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ruoyi-product</name>
<description>ruoyi-product商品管理模块</description>
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>3.6.3</version>
</parent>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- RuoYi Common DataSource -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
</dependency>
<!-- RuoYi Common DataScope -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datascope</artifactId>
</dependency>
<!-- RuoYi Common Swagger -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.ruoyi.product.RuoyiProductApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,160 @@
package com.ruoyi.product;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.exception.DemoModeException;
import com.ruoyi.common.core.exception.InnerAuthException;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.exception.auth.NotPermissionException;
import com.ruoyi.common.core.exception.auth.NotRoleException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import javax.servlet.http.HttpServletRequest;
/**
*
*
* @author ruoyi
*/
@RestControllerAdvice
public class GlobalExceptionHandler
{
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
*
*/
@ExceptionHandler(NotPermissionException.class)
public AjaxResult handleNotPermissionException(NotPermissionException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',权限码校验失败'{}'", requestURI, e.getMessage());
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权");
}
/**
*
*/
@ExceptionHandler(NotRoleException.class)
public AjaxResult handleNotRoleException(NotRoleException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',角色权限校验失败'{}'", requestURI, e.getMessage());
return AjaxResult.error(HttpStatus.FORBIDDEN, "没有访问权限,请联系管理员授权");
}
/**
*
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod());
return AjaxResult.error(e.getMessage());
}
/**
*
*/
@ExceptionHandler(ServiceException.class)
public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
{
log.error(e.getMessage(), e);
Integer code = e.getCode();
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
}
/**
*
*/
@ExceptionHandler(MissingPathVariableException.class)
public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
}
/**
*
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
}
/**
*
*/
@ExceptionHandler(RuntimeException.class)
public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生未知异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
/**
*
*/
@ExceptionHandler(Exception.class)
public AjaxResult handleException(Exception e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求地址'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(e.getMessage());
}
/**
*
*/
@ExceptionHandler(BindException.class)
public AjaxResult handleBindException(BindException e)
{
log.error(e.getMessage(), e);
String message = e.getAllErrors().get(0).getDefaultMessage();
return AjaxResult.error(message);
}
/**
*
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
{
log.error(e.getMessage(), e);
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return AjaxResult.error(message);
}
/**
*
*/
@ExceptionHandler(InnerAuthException.class)
public AjaxResult handleInnerAuthException(InnerAuthException e)
{
return AjaxResult.error(e.getMessage());
}
/**
*
*/
@ExceptionHandler(DemoModeException.class)
public AjaxResult handleDemoModeException(DemoModeException e)
{
return AjaxResult.error("演示模式,不允许操作");
}
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.product;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication
public class RuoyiProductApplication {
public static void main(String[] args) {
SpringApplication.run(RuoyiProductApplication.class, args);
}
}

View File

@ -0,0 +1,35 @@
package com.ruoyi.product.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.product.domain.req.BrandReq;
import com.ruoyi.product.service.BrandService;
import io.swagger.annotations.Api;
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;
/**
* @ClassName BrandController
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 20:55
*/
@RestController
@RequestMapping("/brand")
@Api(tags = "品牌信息")
public class BrandController {
@Autowired
private BrandService brandService;
@PostMapping("/brandInsert")
public R<BrandReq>brandInsert(@RequestBody BrandReq brandReq){
brandService.brandInsert(brandReq);
return R.ok();
}
}

View File

@ -0,0 +1,37 @@
package com.ruoyi.product.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.product.domain.req.ProductClassifyReq;
import com.ruoyi.product.service.ProductClassFyService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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;
/**
* @ClassName ProductClassiFy
* @Description
* @Author YunXiang.Li
* @Date 2024/3/27 20:37
*/
@RestController
@RequestMapping("/productClassFy")
@Api(tags = "商品分类")
public class ProductClassFyController {
@Autowired
private ProductClassFyService productClassFyService;
@PostMapping("/productClassFyInsert")
@ApiOperation("添加商品分类")
public R productClassFyInsert(@RequestBody ProductClassifyReq productClassifyReq){
productClassFyService.productClassFyInsert(productClassifyReq);
return R.ok();
}
}

View File

@ -0,0 +1,44 @@
package com.ruoyi.product.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.product.domain.req.ProductReq;
import com.ruoyi.product.service.ProductService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.math3.stat.descriptive.summary.Product;
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;
/**
* @ClassName ProductController
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 19:07
*/
@RestController
@RequestMapping("/product")
@Api(tags = "商品管理")
public class ProductController {
@Autowired
private ProductService productService;
@PostMapping("/save")
@ApiOperation("商品信息添加")
public R save(@RequestBody ProductReq productReq){
productService.save(productReq);
return R.ok();
}
}

View File

@ -0,0 +1,42 @@
package com.ruoyi.product.domain.favorable;
public enum PreferentialType {
NO_PROMOTION(0,"无优惠"),
USE_PROMOTION_PRICE(1, "使用促销价"),
USE_MEMBER_PRICE(2,"会员价"),
USE_STEP_PRICE(3,"阶梯价格"),
USE_DISCOUNT_PRICE(4,"满减价格");
private Integer code;
private String description;
PreferentialType(Integer code, String description) {
this.code = code;
this.description = description;
}
public Integer getCode() {
return code;
}
public String getDescription() {
return description;
}
public static PreferentialType valueOf(Integer code){
for (PreferentialType type : values()) {
if (type.code == code) {
return type;
}
}
throw new IllegalArgumentException("Invalid PreferentialType code: " + code);
}
}

View File

@ -0,0 +1,46 @@
package com.ruoyi.product.domain.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import lombok.Data;
/**
* @ClassName BrandReq
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 21:01
*/
@Data
@ApiModel(description = "品牌信息实体类")
public class BrandReq {
@ApiModelProperty(value = "品牌id")
private Integer id;
@ApiModelProperty(value = "品牌名称")
private String brandName;
@ApiModelProperty(value = "品牌首字母")
private String brandFirstLetter;
@ApiModelProperty(value = "排序")
private int sort;
@ApiModelProperty(value = "品牌制造商 0-是 1-否")
private int brandManufacturer;
@ApiModelProperty(value = "品牌故事")
private String brandStory;
@ApiModelProperty(value = "品牌logo")
private String brandLogo;
@ApiModelProperty(value = "品牌专区大图")
private String brandSpecialArea;
@ApiModelProperty(value = "是否显示 0-显示 1-不显示")
private int isShow;
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @ClassName FullSubtractionReq
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:14
*/
@Data
@ApiModel(description = "满减价格实体类")
public class FullSubtractionReq {
@ApiModelProperty(value = "ID")
private int id;
@ApiModelProperty(value = "满多少钱")
private double fullPrice;
@ApiModelProperty(value = "立减多少钱")
private double subtractionPrice;
@ApiModelProperty(value = "商品ID")
private int shopId;
}

View File

@ -0,0 +1,25 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.auth.In;
import lombok.Data;
/**
* @ClassName MemberReq
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:23
*/
@Data
@ApiModel(value = "会员类型实体类")
public class MemberReq{
@ApiModelProperty(value = "ID")
private Integer id;
@ApiModelProperty(value = "会员类型名称")
private String memberName;
}

View File

@ -0,0 +1,47 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @ClassName ProductBrandReq
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:26
*/
@Data
@ApiModel(description = "商品品牌实体类")
public class ProductBrandReq{
@ApiModelProperty(value = "ID")
private int id;
@ApiModelProperty(value = "品牌名称")
private String brandName;
@ApiModelProperty(value = "品牌首字母")
private String brandFirstLetter;
@ApiModelProperty(value = "排序")
private int sort;
@ApiModelProperty(value = "品牌制造商 0-是 1-否")
private int brandManufacturer;
@ApiModelProperty(value = "品牌故事")
private String brandStory;
@ApiModelProperty(value = "品牌logo")
private String brandLogo;
@ApiModelProperty(value = "品牌专区大图")
private String brandSpecialArea;
@ApiModelProperty(value = "是否显示 0-显示 1-不显示")
private int isShow;
}

View File

@ -0,0 +1,45 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @ClassName ProductClassifyReq
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:28
*/
@Data
@ApiModel(value = "商品分类表")
public class ProductClassifyReq {
@ApiModelProperty(value = "ID")
private String id;
@ApiModelProperty(value = "分类名称")
private String classifyName;
@ApiModelProperty(value = "分类级别")
private String classifyLevel;
@ApiModelProperty(value = "数量单位")
private String classifyUnit;
@ApiModelProperty(value = "导航栏 0-显示 1-不显示")
private String classifyNavigation;
@ApiModelProperty(value = "是否显示 0-显示 1-不显示")
private String isShow;
@ApiModelProperty(value = "排序")
private String sort;
@ApiModelProperty(value = "父级ID")
private String parentId;
@ApiModelProperty(value = "分类图标")
private String classifyIco;
}

View File

@ -0,0 +1,27 @@
package com.ruoyi.product.domain.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @ClassName ProductGuaranteeLink
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:35
*/
@Data
@ApiModel(description = "商品服务保证关联实体类")
public class ProductGuaranteeLinkReq {
@ApiModelProperty(value = "ID")
private int id;
@ApiModelProperty(value = "商品ID")
private int productId;
@ApiModelProperty(value = "服务保证ID")
private int serviceGuarantee;
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.product.domain.req;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.auth.In;
import lombok.Data;
/**
* @ClassName ProductImg
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:39
*/
@Data
@ApiModel(value = "商品图片表")
public class ProductImg {
@ApiModelProperty(value = "ID")
private Integer id;
@ApiModelProperty(value = "商品ID")
private Integer productId;
@ApiModelProperty(value = "商品图片")
private String imgUrl;
}

View File

@ -0,0 +1,124 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@ApiModel(description = "商品表")
public class ProductReq{
@ApiModelProperty(value = "商品ID")
private Long id;
@ApiModelProperty(value = "商品类型ID")
@NotNull(message = "商品类型不能为空")
private Integer productClassifyId;
@ApiModelProperty(value = "商品名称")
@NotBlank(message = "商品名称不能为空")
private String productName;
@ApiModelProperty(value = "副标题")
@NotBlank(message = "商品副标题不能为空")
private String productSubhead;
@ApiModelProperty(value = "商品品牌ID")
private Integer productBrandId;
@ApiModelProperty(value = "商品介绍")
private String productIntroduce;
@ApiModelProperty(value = "商品货号")
@NotNull(message = "商品货号不能为空")
private Long productNo;
@ApiModelProperty(value = "计量单位")
private String productUnit;
@ApiModelProperty(value = "商品重量")
private Double productWeight;
@ApiModelProperty(value = "排序")
private Integer productSort;
@ApiModelProperty(value = "赠送积分")
private Integer bonusPoints;
@ApiModelProperty(value = "赠送成长值")
private Integer bonusGrowth;
@ApiModelProperty(value = "积分购买限制")
private Integer pointsPurchase;
@ApiModelProperty(value = "预告商品 0-是 1-否")
private Integer isAdvance;
@ApiModelProperty(value = "是否上架 0-是 1-否")
private Integer isPutaway;
@ApiModelProperty(value = "是否新品 0-是 1-否")
private Integer isNew;
@ApiModelProperty(value = "是否推荐 0-是 1-否")
private Integer isRecommend;
@ApiModelProperty(value = "详细页标题")
@NotBlank(message = "详细页标题不能为空")
private String detailTitle;
@ApiModelProperty(value = "详细页描述")
@NotBlank(message = "描述不能为空")
private String detailDescribe;
@ApiModelProperty(value = "商品关键字")
private String detailKey;
@ApiModelProperty(value = "商品备注")
private String detailRemark;
@ApiModelProperty(value = "优惠方式类型,0,1,2,3")
private Integer offersType;
@ApiModelProperty(value = "会员价格,当offersType为xxx时传")
private ShopMemberReq shopMemberReq;
@ApiModelProperty(value = "满减价格,当offersType为xxx时传")
private FullSubtractionReq fullSubtractionReq;
@ApiModelProperty(value = "阶梯价格,当offersType为xxx时传")
private ShopLadderReq shopLadderReq;
@ApiModelProperty(value = "特惠促销,当offersType为xxx时传")
private SpecialOffersReq specialOffersReq;
@ApiModelProperty(value = "优惠ID")
private Integer offersId;
@ApiModelProperty(value = "商品分类ID")
private Integer productTypeId;
@ApiModelProperty(value = "商品详情PC端")
private String pcProductDetail;
@ApiModelProperty(value = "商品详情移动端")
private String mobileProductDetail;
@ApiModelProperty(value = "服务保证")
private List<Integer>serviceGuaranteeList;
@ApiModelProperty(value = "商品相册")
@NotEmpty(message = "商品相册不能为空")
private List<String>productImg;
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @ClassName ShopLadderReq
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:09
*/
@Data
@ApiModel(description = "阶梯价格实体类")
public class ShopLadderReq {
@ApiModelProperty(value = "ID")
private int id;
@ApiModelProperty(value = "阶梯数量")
private int ladderNum;
@ApiModelProperty(value = "阶梯折扣")
private int ladderDiscount;
@ApiModelProperty(value = "商品ID")
private int shopId;
}

View File

@ -0,0 +1,34 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* @ClassName ShopMember
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:12
*/
@Data
@ApiModel(description = "会员价格表")
public class ShopMemberReq {
@ApiModelProperty(value = "ID")
private int id;
@ApiModelProperty(value = "会员类型ID")
private Integer memberTypeId;
@ApiModelProperty(value = "优惠价格")
private BigDecimal offersPrice;
@ApiModelProperty(value = "商品ID")
private Integer shopId;
}

View File

@ -0,0 +1,34 @@
package com.ruoyi.product.domain.req;
import com.ruoyi.common.core.domain.ProductMetadata;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* @ClassName SpecialOffers
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 15:07
*/
@Data
@ApiModel(description = "特惠促销实体类")
public class SpecialOffersReq{
@ApiModelProperty(value = "ID")
private int id;
@ApiModelProperty(value = "开始时间")
private Date startTime;
@ApiModelProperty(value = "结束时间")
private Date endTime;
@ApiModelProperty(value = "优惠价格")
private double offersPrice;
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.product.mapper;
import com.ruoyi.product.domain.req.BrandReq;
import org.apache.ibatis.annotations.Mapper;
/**
* @ClassName BrandMapper
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 21:06
*/
@Mapper
public interface BrandMapper {
void brandInsert(BrandReq brandReq);
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.product.mapper;
import com.ruoyi.product.domain.req.ProductClassifyReq;
import org.apache.ibatis.annotations.Mapper;
/**
* @ClassName ProductClassFyMapper
* @Description
* @Author YunXiang.Li
* @Date 2024/3/27 20:38
*/
@Mapper
public interface ProductClassFyMapper {
void productClassFyInsert(ProductClassifyReq productClassifyReq);
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.product.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* @ClassName ProductMapper
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 19:07
*/
@Mapper
public interface ProductMapper {
Integer selectClassById(@Param("classifyId") Integer classifyId);
String selectByProductName(@Param("productName") String productName);
String selectDetailDescribe(@Param("detailDescribe") String detailDescribe);
}

View File

@ -0,0 +1,17 @@
package com.ruoyi.product.mapper;
import com.ruoyi.product.domain.req.ProductReq;
import org.apache.ibatis.annotations.Mapper;
/**
* @ClassName SaveMapper
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 20:33
*/
@Mapper
public interface SaveMapper {
void save(ProductReq productReq);
void bachProduct(ProductReq productReq1);
}

View File

@ -0,0 +1,13 @@
package com.ruoyi.product.service;
import com.ruoyi.product.domain.req.BrandReq;
/**
* @ClassName BrandService
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 20:56
*/
public interface BrandService {
void brandInsert(BrandReq brandReq);
}

View File

@ -0,0 +1,13 @@
package com.ruoyi.product.service;
import com.ruoyi.product.domain.req.ProductClassifyReq;
/**
* @ClassName ProductClassFyService
* @Description
* @Author YunXiang.Li
* @Date 2024/3/27 20:38
*/
public interface ProductClassFyService {
void productClassFyInsert(ProductClassifyReq productClassifyReq);
}

View File

@ -0,0 +1,13 @@
package com.ruoyi.product.service;
import com.ruoyi.product.domain.req.ProductReq;
/**
* @ClassName ProductService
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 19:07
*/
public interface ProductService {
void save(ProductReq productReq);
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.product.service.impl;
import com.ruoyi.product.domain.req.BrandReq;
import com.ruoyi.product.mapper.BrandMapper;
import com.ruoyi.product.service.BrandService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName BrandServiceImpl
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 20:56
*/
@Service
@Slf4j
public class BrandServiceImpl implements BrandService {
@Autowired
private BrandMapper brandMapper;
@Override
public void brandInsert(BrandReq brandReq) {
brandMapper.brandInsert(brandReq);
}
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.product.service.impl;
import com.ruoyi.product.domain.req.ProductClassifyReq;
import com.ruoyi.product.mapper.ProductClassFyMapper;
import com.ruoyi.product.service.ProductClassFyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @ClassName ProductClassFyServiceImpl
* @Description
* @Author YunXiang.Li
* @Date 2024/3/27 20:38
*/
@Service
public class ProductClassFyServiceImpl implements ProductClassFyService {
@Autowired
private ProductClassFyMapper productClassFyMapper;
@Override
public void productClassFyInsert(ProductClassifyReq productClassifyReq) {
productClassFyMapper.productClassFyInsert(productClassifyReq);
}
}

View File

@ -0,0 +1,114 @@
package com.ruoyi.product.service.impl;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.product.domain.favorable.PreferentialType;
import com.ruoyi.product.domain.req.ProductReq;
import com.ruoyi.product.domain.req.SpecialOffersReq;
import com.ruoyi.product.mapper.ProductMapper;
import com.ruoyi.product.mapper.SaveMapper;
import com.ruoyi.product.service.ProductService;
import lombok.extern.log4j.Log4j2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName ProductServiceImpl
* @Description
* @Author YunXiang.Li
* @Date 2024/3/26 19:08
*/
@Service
@Slf4j
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
@Autowired
private SaveMapper saveMapper;
@Override
@Transactional
public void save(ProductReq productReq) {
//参数校验
ParameterCheck(productReq);
saveMapper.save(productReq);
ArrayList<ProductReq> reqs = new ArrayList<>();
reqs.forEach(productReq1 -> {
productReq1.setProductName(productReq.getProductName());
productReq1.setProductClassifyId(productReq.getProductClassifyId());
productReq1.setProductSubhead(productReq.getProductSubhead());
saveMapper.bachProduct(productReq1);
});
}
private void ParameterCheck(ProductReq productReq) {
//校验类型是否存在
Integer classifyId = productReq.getProductClassifyId();
//去数据库搜索商品类型id是否存在
Integer count=productMapper.selectClassById(classifyId);
if(count==0){
log.info("id不存在:{}",classifyId);
throw new ServiceException("商品类型id不存在");
}
//校验商品名称是否存在
String productName = productReq.getProductName();
//数据库查询商品名称
String name=productMapper.selectByProductName(productName);
if(name==null){
log.info("商品名称不存在:{}",productName);
}
//校验详细页标题
String detailDescribe = productReq.getDetailDescribe();
//查询详细页标题是否存在
String describe=productMapper.selectDetailDescribe(detailDescribe);
if(describe==null){
log.info("详细页标题不存在:{}",detailDescribe);
}
//校验商品副标题
String productSubhead = productReq.getProductSubhead();
if(productSubhead!=null||"".equals(productSubhead)){
log.info("商品副标题:{}",productSubhead+"不能为空");
}
//校验商品货号
Long productNo = productReq.getProductNo();
if(productNo==null){
log.info("商品货号:{}",productNo+"不能为空");
}
//校验商品相册
List<String> productImg = productReq.getProductImg();
//查询相册是否存在
if(productImg==null){
log.info("相册不存在:{}",productImg);
}
if(PreferentialType.NO_PROMOTION.getCode()==productReq.getOffersType()){
SpecialOffersReq specialOffersReq = productReq.getSpecialOffersReq();
}
}
}

View File

@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ _
(_) | |
_ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___
| '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \
| | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | |
|_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_|
__/ | __/ |
|___/ |___/

View File

@ -0,0 +1,28 @@
# Tomcat
server:
port: 9203
# Spring
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
application:
# 应用名称
name: ruoyi-product
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 122.51.27.196:8848
config:
# 配置中心地址
server-addr: 122.51.27.196:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-system" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@ -0,0 +1,17 @@
<?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.ruoyi.product.mapper.BrandMapper">
<insert id="brandInsert">
INSERT INTO `commodity_management`.`t_product_brand`
(`brand_name`, `brand_first_letter`, `sort`, `brand_manufacturer`, `brand_story`,
`brand_logo`,
`brand_special_area`, `is_show`)
VALUES
( #{brandName}, #{brandFirstLetter}, 0, #{brandManufacturer}, #{brandStory},
#{brandLogo}, #{brandSpecialArea}, 0)
</insert>
</mapper>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.product.mapper.ProductClassFyMapper">
<insert id="productClassFyInsert">
INSERT INTO `commodity_management`.`t_product_classify`
( `classify_name`, `classify_level`, `classify_unit`, `classify_navigation`,
`is_show`, `sort`, `parent_id`, `classify_ico`)
VALUES ( #{classifyName}, #{classifyLevel}, #{classifyUnit}, 0, #{isShow}, #{sort}, #{parentId}, #{classifyIco})
</insert>
</mapper>

View File

@ -0,0 +1,20 @@
<?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.ruoyi.product.mapper.ProductMapper">
<select id="selectClassById" resultType="java.lang.Integer">
select product_classify_id from t_product where product_classify_id=#{classifyId}
</select>
<select id="selectByProductName" resultType="java.lang.String">
select product_name from t_product where product_name=#{productName}
</select>
<select id="selectDetailDescribe" resultType="java.lang.String">
select detail_describe from t_product where detail_describe=#{detailDescribe}
</select>
</mapper>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.product.mapper.SaveMapper">
<insert id="save">
INSERT INTO `commodity_management`.`t_product`
(`product_classify_id`, `product_name`, `product_subhead`,
`product_brand_id`, `product_introduce`, `product_no`,
`product_unit`, `product_weight`, `product_sort`,
`bonus_points`, `bonus_growth`, `points_purchase`,
`is_advance`, `is_putaway`, `is_new`, `is_recommend`,
`detail_title`, `detail_describe`, `detail_key`,
`detail_remark`, `offers_type`, `offers_id`, `create_time`,
`update_time`, `is_delete`, `create_by`, `product_type_id`,
`pc_product_detail`, `mobile_product_detail`, `product_img`)
VALUES
( #{productClassifyId}, #{productName}, #{productSubhead},
#{productBrandId}, #{productIntroduce}, #{productNo},
#{productUnit}, #{productWeight}, 0,
0, 0, 0,
#{isAdvance}, #{isPutaway}, #{isNew},
#{isRecommend}, #{detailTitle}, #{detailDescribe},
#{detailKey}, #{detailRemark}, #{offersType},
#{offersId}, now(), now(),
0, 1, #{productTypeId},
#{pcProductDetail}, #{mobileProductDetail}, #{productImg})
</insert>
<insert id="bachProduct" useGeneratedKeys="true" keyProperty="id">
INSERT INTO `commodity_management`.`t_product`
(`product_classify_id`, `product_name`, `product_subhead`,
`product_brand_id`, `product_introduce`, `product_no`,
`product_unit`, `product_weight`, `product_sort`,
`bonus_points`, `bonus_growth`, `points_purchase`,
`is_advance`, `is_putaway`, `is_new`, `is_recommend`,
`detail_title`, `detail_describe`, `detail_key`,
`detail_remark`, `offers_type`, `offers_id`, `create_time`,
`update_time`, `is_delete`, `create_by`, `product_type_id`,
`pc_product_detail`, `mobile_product_detail`, `product_img`)
VALUES
<foreach collection="product" item="product" separator=",">
</foreach>
</insert>
</mapper>

View File

@ -72,12 +72,17 @@
<artifactId>ruoyi-common-log</artifactId> <artifactId>ruoyi-common-log</artifactId>
</dependency> </dependency>
<!-- RuoYi Common Swagger --> <!-- RuoYi Common Swagger -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId> <artifactId>ruoyi-common-swagger</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -14,10 +14,10 @@ spring:
nacos: nacos:
discovery: discovery:
# 服务注册地址 # 服务注册地址
server-addr: 127.0.0.1:8848 server-addr: 122.51.27.196:8848
config: config:
# 配置中心地址 # 配置中心地址
server-addr: 127.0.0.1:8848 server-addr: 122.51.27.196:8848
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置

View File

@ -67,7 +67,7 @@
"babel-eslint": "10.1.0", "babel-eslint": "10.1.0",
"babel-plugin-dynamic-import-node": "2.3.3", "babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "4.1.0", "chalk": "4.1.0",
"compression-webpack-plugin": "5.0.2", "compression-webpack-plugin": "6.1.2",
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "7.15.0", "eslint": "7.15.0",
"eslint-plugin-vue": "7.2.0", "eslint-plugin-vue": "7.2.0",

View File

@ -771,7 +771,7 @@
<li>修复代码生成点击多次表修改数据不变化的问题</li> <li>修复代码生成点击多次表修改数据不变化的问题</li>
<li>修复代码生成导入表结构出现异常页面不提醒问题</li> <li>修复代码生成导入表结构出现异常页面不提醒问题</li>
<li>修复角色权限修改时已有权限未自动勾选异常</li> <li>修复角色权限修改时已有权限未自动勾选异常</li>
<li>创建用户不允许选择系统管理员角色</li> <li>创建用户不允许选择员角色</li>
<li>添加全局异常处理网关异常&业务异常</li> <li>添加全局异常处理网关异常&业务异常</li>
<li>修复终端查询Enter键搜索时是刷新页面而不是查询列表</li> <li>修复终端查询Enter键搜索时是刷新页面而不是查询列表</li>
<li>删除job重复表单参数</li> <li>删除job重复表单参数</li>

View File

@ -56,7 +56,7 @@
</el-form> </el-form>
<!-- 底部 --> <!-- 底部 -->
<div class="el-login-footer"> <div class="el-login-footer">
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span> <span>Copyright © 2018-2024 ruoyi.vip All Rights Reserved.</span>
</div> </div>
</div> </div>
</template> </template>

View File

@ -61,7 +61,7 @@
</el-form> </el-form>
<!-- 底部 --> <!-- 底部 -->
<div class="el-register-footer"> <div class="el-register-footer">
<span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span> <span>Copyright © 2018-2024 ruoyi.vip All Rights Reserved.</span>
</div> </div>
</div> </div>
</template> </template>
@ -95,7 +95,8 @@ export default {
], ],
password: [ password: [
{ required: true, trigger: "blur", message: "请输入您的密码" }, { required: true, trigger: "blur", message: "请输入您的密码" },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' } { min: 5, max: 20, message: "用户密码长度必须介于 5 和 20 之间", trigger: "blur" },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
], ],
confirmPassword: [ confirmPassword: [
{ required: true, trigger: "blur", message: "请再次输入您的密码" }, { required: true, trigger: "blur", message: "请再次输入您的密码" },

View File

@ -433,7 +433,8 @@ export default {
], ],
password: [ password: [
{ required: true, message: "用户密码不能为空", trigger: "blur" }, { required: true, message: "用户密码不能为空", trigger: "blur" },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' } { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
], ],
email: [ email: [
{ {
@ -591,7 +592,12 @@ export default {
cancelButtonText: "取消", cancelButtonText: "取消",
closeOnClickModal: false, closeOnClickModal: false,
inputPattern: /^.{5,20}$/, inputPattern: /^.{5,20}$/,
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间" inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",
inputValidator: (value) => {
if (/<|>|"|'|\||\\/.test(value)) {
return "不能包含非法字符:< > \" ' \\\ |"
}
},
}).then(({ value }) => { }).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => { resetUserPwd(row.userId, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value); this.$modal.msgSuccess("修改成功,新密码是:" + value);

View File

@ -41,7 +41,8 @@ export default {
], ],
newPassword: [ newPassword: [
{ required: true, message: "新密码不能为空", trigger: "blur" }, { required: true, message: "新密码不能为空", trigger: "blur" },
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" } { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" },
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
], ],
confirmPassword: [ confirmPassword: [
{ required: true, message: "确认密码不能为空", trigger: "blur" }, { required: true, message: "确认密码不能为空", trigger: "blur" },

View File

@ -85,7 +85,7 @@
<el-form-item> <el-form-item>
<span slot="label"> <span slot="label">
上级菜单 上级菜单
<el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top"> <el-tooltip content="分配到指定菜单下,例如 " placement="top">
<i class="el-icon-question"></i> <i class="el-icon-question"></i>
</el-tooltip> </el-tooltip>
</span> </span>

View File

@ -62,10 +62,11 @@ module.exports = {
// http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
new CompressionPlugin({ new CompressionPlugin({
cache: false, // 不启用文件缓存 cache: false, // 不启用文件缓存
test: /\.(js|css|html)?$/i, // 压缩文件格式 test: /\.(js|css|html|jpe?g|png|gif|svg)?$/i, // 压缩文件格式
filename: '[path].gz[query]', // 压缩后的文件名 filename: '[path][base].gz[query]', // 压缩后的文件名
algorithm: 'gzip', // 使用gzip压缩 algorithm: 'gzip', // 使用gzip压缩
minRatio: 0.8 // 压缩率小于1才会压缩 minRatio: 0.8, // 压缩比例,小于 80% 的文件不会被压缩
deleteOriginalAssets: false // 压缩后删除原文件
}) })
], ],
}, },

View File

@ -159,7 +159,7 @@ create table sys_menu (
-- 初始化-菜单信息表数据 -- 初始化-菜单信息表数据
-- ---------------------------- -- ----------------------------
-- 一级菜单 -- 一级菜单
insert into sys_menu values('1', '系统管理', '0', '1', 'system', null, '', 1, 0, 'M', '0', '0', '', 'system', 'admin', sysdate(), '', null, '系统管理目录'); insert into sys_menu values('1', '', '0', '1', 'system', null, '', 1, 0, 'M', '0', '0', '', 'system', 'admin', sysdate(), '', null, '目录');
insert into sys_menu values('2', '系统监控', '0', '2', 'monitor', null, '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', sysdate(), '', null, '系统监控目录'); insert into sys_menu values('2', '系统监控', '0', '2', 'monitor', null, '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', sysdate(), '', null, '系统监控目录');
insert into sys_menu values('3', '系统工具', '0', '3', 'tool', null, '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', sysdate(), '', null, '系统工具目录'); insert into sys_menu values('3', '系统工具', '0', '3', 'tool', null, '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', sysdate(), '', null, '系统工具目录');
insert into sys_menu values('4', '若依官网', '0', '4', 'http://ruoyi.vip', null, '', 0, 0, 'M', '0', '0', '', 'guide', 'admin', sysdate(), '', null, '若依官网地址'); insert into sys_menu values('4', '若依官网', '0', '4', 'http://ruoyi.vip', null, '', 0, 0, 'M', '0', '0', '', 'guide', 'admin', sysdate(), '', null, '若依官网地址');