Skip to content

Commit

Permalink
✨ 2.0.1 版本发布准备
Browse files Browse the repository at this point in the history
  • Loading branch information
YunaiV committed Feb 17, 2024
1 parent edd2cef commit f71a3b7
Show file tree
Hide file tree
Showing 27 changed files with 503 additions and 62 deletions.
Binary file added .image/common/erp-feature.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@
* 数据报表
* 商城系统
* 微信公众号
* ERP 系统
* CRM 系统

> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。
>
Expand Down Expand Up @@ -230,6 +232,12 @@
| 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 |
| 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 |

### ERP 系统

![功能图](/.image/common/erp-feature.png)

演示地址:<https://doc.iocoder.cn/erp-preview/>

## 🐨 技术栈

### 微服务
Expand Down
216 changes: 191 additions & 25 deletions sql/mysql/ruoyi-vue-pro.sql

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -288,11 +288,16 @@ public static <T, V extends Comparable<? super V>> V getMinValue(List<T> from, F

public static <T, V extends Comparable<? super V>> V getSumValue(List<T> from, Function<T, V> valueFunc,
BinaryOperator<V> accumulator) {
return getSumValue(from, valueFunc, accumulator, null);
}

public static <T, V extends Comparable<? super V>> V getSumValue(Collection<T> from, Function<T, V> valueFunc,
BinaryOperator<V> accumulator, V defaultValue) {
if (CollUtil.isEmpty(from)) {
return null;
return defaultValue;
}
assert from.size() > 0; // 断言,避免告警
return from.stream().map(valueFunc).reduce(accumulator).get();
assert !from.isEmpty(); // 断言,避免告警
return from.stream().map(valueFunc).filter(Objects::nonNull).reduce(accumulator).orElse(defaultValue);
}

public static <T> void addIfNotNull(Collection<T> coll, T item) {
Expand All @@ -302,8 +307,12 @@ public static <T> void addIfNotNull(Collection<T> coll, T item) {
coll.add(item);
}

public static <T> Collection<T> singleton(T deptId) {
return deptId == null ? Collections.emptyList() : Collections.singleton(deptId);
public static <T> Collection<T> singleton(T obj) {
return obj == null ? Collections.emptyList() : Collections.singleton(obj);
}

public static <T> List<T> newArrayList(List<List<T>> list) {
return list.stream().flatMap(Collection::stream).collect(Collectors.toList());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
*/
public class MoneyUtils {

/**
* 金额的小数位数
*/
private static final int PRICE_SCALE = 2;

/**
* 百分比对应的 BigDecimal 对象
*/
public static final BigDecimal PERCENT_100 = BigDecimal.valueOf(100);

/**
* 计算百分比金额,四舍五入
*
Expand All @@ -35,6 +45,22 @@ public static Integer calculateRatePriceFloor(Integer price, Double rate) {
return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue();
}

/**
* 计算百分比金额
*
* @param price 金额(单位分)
* @param count 数量
* @param percent 折扣(单位分),列如 60.2%,则传入 6020
* @return 商品总价
*/
public static Integer calculator(Integer price, Integer count, Integer percent) {
price = price * count;
if (percent == null) {
return price;
}
return MoneyUtils.calculateRatePriceFloor(price, (double) (percent / 100));
}

/**
* 计算百分比金额
*
Expand Down Expand Up @@ -70,4 +96,36 @@ public static String fenToYuanStr(int fen) {
return new Money(0, fen).toString();
}

/**
* 金额相乘,默认进行四舍五入
*
* 位数:{@link #PRICE_SCALE}
*
* @param price 金额
* @param count 数量
* @return 金额相乘结果
*/
public static BigDecimal priceMultiply(BigDecimal price, BigDecimal count) {
if (price == null || count == null) {
return null;
}
return price.multiply(count).setScale(PRICE_SCALE, RoundingMode.HALF_UP);
}

/**
* 金额相乘(百分比),默认进行四舍五入
*
* 位数:{@link #PRICE_SCALE}
*
* @param price 金额
* @param percent 百分比
* @return 金额相乘结果
*/
public static BigDecimal priceMultiplyPercent(BigDecimal price, BigDecimal percent) {
if (price == null || percent == null) {
return null;
}
return price.multiply(percent).divide(PERCENT_100, PRICE_SCALE, RoundingMode.HALF_UP);
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package cn.iocoder.yudao.framework.common.util.number;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;

import java.math.BigDecimal;

/**
* 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能
*
Expand Down Expand Up @@ -37,4 +40,21 @@ public static double getDistance(double lat1, double lng1, double lat2, double l
return distance;
}

/**
* 提供精确的乘法运算
*
* 和 hutool {@link NumberUtil#mul(BigDecimal...)} 的差别是,如果存在 null,则返回 null
*
* @param values 多个被乘值
* @return 积
*/
public static BigDecimal mul(BigDecimal... values) {
for (BigDecimal value : values) {
if (value == null) {
return null;
}
}
return NumberUtil.mul(values);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.framework.file.core.client;

import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlRespDTO;

/**
* 文件客户端
*
Expand All @@ -18,11 +20,11 @@ public interface FileClient {
* 上传文件
*
* @param content 文件流
* @param path 相对路径
* @param path 相对路径
* @return 完整路径,即 HTTP 访问地址
* @throws Exception 上传文件时,抛出 Exception 异常
*/
String upload(byte[] content, String path, String type) throws Exception;
String upload(byte[] content, String path, String type) throws Exception;

/**
* 删除文件
Expand All @@ -40,4 +42,14 @@ public interface FileClient {
*/
byte[] getContent(String path) throws Exception;

/**
* 获得文件预签名地址
*
* @param path 相对路径
* @return 文件预签名地址
*/
default FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception {
throw new UnsupportedOperationException("不支持的操作");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package cn.iocoder.yudao.framework.file.core.client.s3;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* 文件预签名地址 Response DTO
*
* @author owen
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FilePresignedUrlRespDTO {

/**
* 文件上传 URL(用于上传)
*
* 例如说:
*/
private String uploadUrl;

/**
* 文件 URL(用于读取、下载等)
*/
private String url;

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient;
import io.minio.*;
import io.minio.http.Method;

import java.io.ByteArrayInputStream;
import java.util.concurrent.TimeUnit;

import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_ALIYUN;
import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_TENCENT;
Expand Down Expand Up @@ -117,4 +119,16 @@ public byte[] getContent(String path) throws Exception {
return IoUtil.readBytes(response);
}

@Override
public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception {
String uploadUrl = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(config.getBucket())
.object(path)
.expiry(10, TimeUnit.MINUTES) // 过期时间(秒数)取值范围:1 秒 ~ 7 天
.build()
);
return new FilePresignedUrlRespDTO(uploadUrl, config.getDomain() + "/" + path);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public QueryWrapperX<T> limitN(int n) {
switch (SqlConstants.DB_TYPE) {
case ORACLE:
case ORACLE_12C:
super.eq("ROWNUM", n);
super.le("ROWNUM", n);
break;
case SQL_SERVER:
case SQL_SERVER2005:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public void run(ApplicationArguments args) {
System.out.println("[微信公众号 yudao-module-mp 教程][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
// 商城系统
System.out.println("[商城系统 yudao-module-mall 教程][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
// ERP 系统
System.out.println("[ERP 系统 yudao-module-erp - 已禁用][参考 https://doc.iocoder.cn/erp/build/ 开启]");
// 支付平台
System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]");
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,13 @@ private CommonResult<?> handleTableNotExists(Throwable ex) {
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
}
// 5. 支付平台
// 5. ERP 系统
if (message.contains("erp_")) {
log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]");
}
// 6. 支付平台
if (message.contains("pay_")) {
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public void run(ApplicationArguments args) {
System.out.println("[微信公众号 yudao-module-mp 教程][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
// 商城系统
System.out.println("[商城系统 yudao-module-mall 教程][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
// ERP 系统
System.out.println("[ERP 系统 yudao-module-erp - 已禁用][参考 https://doc.iocoder.cn/erp/build/ 开启]");
// 支付平台
System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]");
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,24 @@
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileUploadReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO;
import cn.iocoder.yudao.module.infra.service.file.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 文件存储")
Expand All @@ -42,14 +39,26 @@ public class FileController {
private FileService fileService;

@PostMapping("/upload")
@Operation(summary = "上传文件")
@Operation(summary = "上传文件", description = "模式一:后端上传文件")
@OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) throws Exception {
MultipartFile file = uploadReqVO.getFile();
String path = uploadReqVO.getPath();
return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
}

@GetMapping("/presigned-url")
@Operation(summary = "获取文件预签名地址", description = "模式二:前端上传文件:用于前端直接上传七牛、阿里云 OSS 等文件存储器")
public CommonResult<FilePresignedUrlRespVO> getFilePresignedUrl(@RequestParam("path") String path) throws Exception {
return success(fileService.getFilePresignedUrl(path));
}

@PostMapping("/create")
@Operation(summary = "创建文件", description = "模式二:前端上传文件:配合 presigned-url 接口,记录上传了上传的文件")
public CommonResult<Long> createFile(@Valid @RequestBody FileCreateReqVO createReqVO) {
return success(fileService.createFile(createReqVO));
}

@DeleteMapping("/delete")
@Operation(summary = "删除文件")
@Parameter(name = "id", description = "编号", required = true)
Expand All @@ -62,7 +71,7 @@ public CommonResult<Boolean> deleteFile(@RequestParam("id") Long id) throws Exce
@GetMapping("/{configId}/get/**")
@PermitAll
@Operation(summary = "下载文件")
@Parameter(name = "configId", description = "配置编号", required = true)
@Parameter(name = "configId", description = "配置编号", required = true)
public void getFileContent(HttpServletRequest request,
HttpServletResponse response,
@PathVariable("configId") Long configId) throws Exception {
Expand Down
Loading

0 comments on commit f71a3b7

Please sign in to comment.