1、system服务国际化相关表免校验租户、token配置;2、system服务枚举相关国际化处理;3、system服务资金管理easyexcel导出表头国际化处理;

This commit is contained in:
gaoqr
2025-11-21 16:08:21 +08:00
parent cafdc15fad
commit ff71a6afbb
55 changed files with 472 additions and 629 deletions
@@ -0,0 +1,14 @@
package com.cf.imes.framework.common.constants;
/**
* 国际化资源包常量
*
* @author Gqr
* @since 2025/11/21 11:33
*/
public final class ResourceBundleConstants {
/**
* 枚举资源包
*/
public static final String MESSAGE_ENUM_PATH = "message_enum";
}
@@ -0,0 +1,40 @@
package com.cf.imes.framework.common.util.i18n.core.util;
import lombok.extern.slf4j.Slf4j;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* 国际化资源包工具类
*
* @author Gqr
* @since 2025/11/21 11:16
*/
@Slf4j
public class ResourceBundleUtils {
/**
* 获取国际化资源值
*
* @param baseName 资源包位置
* @param key i18n key
* @param defaultMessage 没有获取到资源描述返回的缺省值
* @param locale 语种
* @param args 占位符数组
* @return
*/
public static String getMessage(String baseName, String key, String defaultMessage, Locale locale, Object args) {
try {
ResourceBundle messageEnum = ResourceBundle.getBundle(baseName, locale);
if (messageEnum != null) {
String i18nMessage = messageEnum.getString(key);
return MessageFormat.format(i18nMessage, args);
}
} catch (Exception e) {
log.error("[ResourceBundleUtils][getMessage]异常", e);
}
return defaultMessage;
}
}
@@ -1,14 +1,13 @@
package com.cf.imes.framework.common.validation;
import cn.hutool.core.collection.CollUtil;
import com.cf.imes.framework.common.constants.ResourceBundleConstants;
import com.cf.imes.framework.common.core.IntArrayValuable;
import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Collection;
@@ -17,14 +16,10 @@ import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
@Component
public class InEnumCollectionValidator implements ConstraintValidator<InEnum, Collection<Integer>> {
private List<Integer> values;
@Autowired
private MessageSource messageSource;
@Override
public void initialize(InEnum annotation) {
IntArrayValuable[] values = annotation.value().getEnumConstants();
@@ -41,14 +36,15 @@ public class InEnumCollectionValidator implements ConstraintValidator<InEnum, Co
if (CollUtil.containsAll(values, list)) {
return true;
}
String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();
Locale locale = LocaleContextHolder.getLocale();
String message = messageSource.getMessage(defaultConstraintMessageTemplate, new Object[]{CollUtil.join(list, ",")}, locale);
defaultConstraintMessageTemplate = ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ENUM_PATH, defaultConstraintMessageTemplate, defaultConstraintMessageTemplate, locale, CollUtil.join(list, ","));;
// 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
context.buildConstraintViolationWithTemplate(message).addConstraintViolation(); // 重新添加错误提示语句
context.buildConstraintViolationWithTemplate(defaultConstraintMessageTemplate).addConstraintViolation(); // 重新添加错误提示语句
return false;
}
}
@@ -1,13 +1,12 @@
package com.cf.imes.framework.common.validation;
import com.cf.imes.framework.common.constants.ResourceBundleConstants;
import com.cf.imes.framework.common.core.IntArrayValuable;
import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Collections;
@@ -15,14 +14,10 @@ import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
@Component
public class InEnumValidator implements ConstraintValidator<InEnum, Integer> {
private List<Integer> values;
@Autowired
private MessageSource messageSource;
@Override
public void initialize(InEnum annotation) {
IntArrayValuable[] values = annotation.value().getEnumConstants();
@@ -45,12 +40,12 @@ public class InEnumValidator implements ConstraintValidator<InEnum, Integer> {
}
String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();
Locale locale = LocaleContextHolder.getLocale();
String message = messageSource.getMessage(defaultConstraintMessageTemplate, new Object[]{values.toString()}, locale);
defaultConstraintMessageTemplate = ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ENUM_PATH, defaultConstraintMessageTemplate, defaultConstraintMessageTemplate, locale, values.toString());
// 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
context.buildConstraintViolationWithTemplate(message).addConstraintViolation(); // 重新添加错误提示语句
context.buildConstraintViolationWithTemplate(defaultConstraintMessageTemplate).addConstraintViolation(); // 重新添加错误提示语句
return false;
}
}
@@ -28,7 +28,7 @@ public @interface InScope {
*/
Class<? extends IntArrayValuable> value();
String message() default "{desc}不合法";
String message() default "inScope.message";
String desc() default "";
@@ -1,13 +1,17 @@
package com.cf.imes.framework.common.validation;
import cn.hutool.core.collection.CollUtil;
import com.cf.imes.framework.common.constants.ResourceBundleConstants;
import com.cf.imes.framework.common.core.IntArrayValuable;
import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.context.i18n.LocaleContextHolder;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
/**
@@ -40,12 +44,14 @@ public class InScopeValidator implements ConstraintValidator<InScope, List<Integ
if (values.containsAll(integers)) {
return true;
}
String defaultConstraintMessageTemplate = constraintValidatorContext.getDefaultConstraintMessageTemplate();
Locale locale = LocaleContextHolder.getLocale();
String descValue = ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ENUM_PATH, desc, desc, locale, null);
defaultConstraintMessageTemplate = ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ENUM_PATH, defaultConstraintMessageTemplate, defaultConstraintMessageTemplate, locale, descValue);;
// 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
constraintValidatorContext.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
constraintValidatorContext.buildConstraintViolationWithTemplate(constraintValidatorContext.getDefaultConstraintMessageTemplate()
.replace("{desc}", desc)).addConstraintViolation(); // 重新添加错误提示语句
constraintValidatorContext.buildConstraintViolationWithTemplate(defaultConstraintMessageTemplate).addConstraintViolation(); // 重新添加错误提示语句
return false;
}
}
@@ -83,10 +83,11 @@ public class ChenfengOrganAutoConfiguration {
public FilterRegistrationBean<OrganSecurityWebFilter> organSecurityWebFilter(OrganProperties tenantProperties,
WebProperties webProperties,
GlobalExceptionHandler globalExceptionHandler,
OrganFrameworkService organFrameworkService) {
OrganFrameworkService organFrameworkService,
I18nUtils i18nUtils) {
FilterRegistrationBean<OrganSecurityWebFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new OrganSecurityWebFilter(tenantProperties, webProperties,
globalExceptionHandler, organFrameworkService));
globalExceptionHandler, organFrameworkService, i18nUtils));
registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER);
return registrationBean;
}
@@ -53,18 +53,19 @@ public class OrganSecurityWebFilter extends ApiRequestFilter {
private final GlobalExceptionHandler globalExceptionHandler;
private final OrganFrameworkService organFrameworkService;
@Resource
private I18nUtils i18nUtils;
private final I18nUtils i18nUtils;
public OrganSecurityWebFilter(OrganProperties organProperties,
WebProperties webProperties,
GlobalExceptionHandler globalExceptionHandler,
OrganFrameworkService organFrameworkService) {
OrganFrameworkService organFrameworkService,
I18nUtils i18nUtils) {
super(webProperties);
this.organProperties = organProperties;
this.pathMatcher = new AntPathMatcher();
this.globalExceptionHandler = globalExceptionHandler;
this.organFrameworkService = organFrameworkService;
this.i18nUtils = i18nUtils;
}
@Override
@@ -5,8 +5,11 @@ import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.cf.imes.framework.common.constants.ResourceBundleConstants;
import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import com.cf.imes.framework.excel.core.annotations.EnumFormat;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.i18n.LocaleContextHolder;
import java.lang.reflect.Field;
@@ -40,7 +43,7 @@ public class EnumBoolValConvert implements Converter<Boolean> {
for (Object e : enumClass.getEnumConstants()) {
BaseBoolValEnum baseEnum = (BaseBoolValEnum) e;
if (baseEnum.getCode().equals(code)) {
return new WriteCellData<>(baseEnum.getDesc());
return new WriteCellData<>(ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ENUM_PATH, baseEnum.getDesc(), baseEnum.getDesc(), LocaleContextHolder.getLocale(), null));
}
}
}
@@ -5,8 +5,11 @@ import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.cf.imes.framework.common.constants.ResourceBundleConstants;
import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import com.cf.imes.framework.excel.core.annotations.EnumFormat;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.i18n.LocaleContextHolder;
import java.lang.reflect.Field;
@@ -40,7 +43,7 @@ public class EnumConvert implements Converter<Integer> {
for (Object e : enumClass.getEnumConstants()) {
BaseEnum baseEnum = (BaseEnum) e;
if (baseEnum.getCode().equals(code)) {
return new WriteCellData<>(baseEnum.getDesc());
return new WriteCellData<>(ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ENUM_PATH, baseEnum.getDesc(), baseEnum.getDesc(), LocaleContextHolder.getLocale(), null));
}
}
}
@@ -35,6 +35,7 @@ public class ExcelUtils {
EasyExcelFactory.write(response.getOutputStream(), head)
.autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
.registerWriteHandler(new I18nHeadWriteHandler())
.registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
.sheet(sheetName).doWrite(data);
// 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
@@ -0,0 +1,29 @@
package com.cf.imes.framework.excel.core.util;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.cf.imes.framework.common.constants.ResourceBundleConstants;
import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.context.i18n.LocaleContextHolder;
import java.util.List;
/**
* 表头国际化处理器
*
* @author Gqr
* @since 2025/11/21 11:05
*/
public class I18nHeadWriteHandler implements CellWriteHandler {
@Override
public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
if (Boolean.TRUE.equals(isHead)) {
String key = head.getHeadNameList().get(0);
cell.setCellValue(ResourceBundleUtils.getMessage(ResourceBundleConstants.MESSAGE_ENUM_PATH, key, key, LocaleContextHolder.getLocale(), null));
}
}
}
@@ -0,0 +1,24 @@
package com.cf.imes.framework.web.config;
import com.cf.imes.framework.web.core.rpc.LanguageRequestInterceptor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
/**
* WEB RPC 组件的自动配置
*
* @author Gqr
* @since 2025/11/20 13:55
*/
@AutoConfiguration
public class ChenfengWebRpcAutoConfiguration {
/**
* 国际化组件
*
* @return
*/
@Bean
public LanguageRequestInterceptor languageRequestInterceptor() {
return new LanguageRequestInterceptor();
}
}
@@ -0,0 +1,29 @@
package com.cf.imes.framework.web.core.rpc;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpHeaders;
import java.util.Locale;
/**
* 国际化 的 RequestInterceptor 实现类:Feign 请求时,将 {@link LocaleContextHolder} 设置到 header 中,继续透传给被调用的服务
*
* @author 晨丰科技
*/
@Slf4j
public class LanguageRequestInterceptor implements RequestInterceptor {
@Override
@SneakyThrows
public void apply(RequestTemplate requestTemplate) {
Locale locale = LocaleContextHolder.getLocale();
if (locale != null) {
requestTemplate.header(HttpHeaders.ACCEPT_LANGUAGE, locale.toString());
}
}
}
@@ -2,6 +2,7 @@ com.cf.imes.framework.apilog.config.ChenfengApiLogAutoConfiguration
com.cf.imes.framework.jackson.config.ChenfengJacksonAutoConfiguration
com.cf.imes.framework.swagger.config.ChenfengSwaggerAutoConfiguration
com.cf.imes.framework.web.config.ChenfengWebAutoConfiguration
com.cf.imes.framework.web.config.ChenfengWebRpcAutoConfiguration
com.cf.imes.framework.apilog.config.ChenfengApiLogRpcAutoConfiguration
com.cf.imes.framework.async.ChenfengAsyncAutoConfiguration
com.cf.imes.framework.banner.config.ChenfengBannerAutoConfiguration
@@ -1,52 +0,0 @@
package com.cf.imes.module.system.enums.advertisement;
import com.cf.imes.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 延迟消息状态单位态枚举
*
* @author 晨丰科技
*/
@Getter
@AllArgsConstructor
public enum MessageStatusEnum implements IntArrayValuable {
PENDING(0, "待处理"),
PROCESSED(1, "已处理"),
CANCELLED(2, "已取消");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(MessageStatusEnum::getStatus).toArray();
/**
* 状态值
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
public static boolean isPending(String name) {
return Objects.equals(PENDING.name, name);
}
public static boolean isProcessed(String name) {
return Objects.equals(PROCESSED.name, name);
}
public static boolean isCancelled(String name) {
return Objects.equals(CANCELLED.name, name);
}
}
@@ -1,46 +0,0 @@
package com.cf.imes.module.system.enums.products;
import com.cf.imes.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.Objects;
/**
* 产品详情购买方式状态枚举
*
* @author 晨丰科技
*/
@Getter
@AllArgsConstructor
public enum ProductsPurchaseTypeEnum implements IntArrayValuable {
DURATION(0, "时长"),
OUTPUT(1, "产量");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductsPurchaseTypeEnum::getStatus).toArray();
/**
* 状态值
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
public static boolean isDURATION(Integer status) {
return Objects.equals(DURATION.status, status);
}
public static boolean isOUTPUT(Integer status) {
return Objects.equals(OUTPUT.status, status);
}
}
@@ -24,7 +24,7 @@ public class AdvertisementPageReqVO extends PageParam {
private String adName;
@Schema(description = "广告位置")
@InScope(value = AdvertisementPositionEnum.class, desc = "广告位置")
@InScope(value = AdvertisementPositionEnum.class, desc = "inScope.adPosition")
private List<Integer> adPosition;
@Schema(description = "广告状态,0未发布 1已发布 2已结束", example = "0")
@@ -32,7 +32,7 @@ public class AdvertisementSaveReqVO {
@Schema(description = "广告位置,字典键值", example = "[1,2]")
@NotEmpty(message = "{ad.position.notEmpty}")
@InScope(value = AdvertisementPositionEnum.class, desc = "广告位置")
@InScope(value = AdvertisementPositionEnum.class, desc = "inScope.adPosition")
private List<Integer> adPosition;
@@ -29,19 +29,19 @@ public class ProductDelayRespVO {
private Long id;
@Schema(description = "组织名称")
@ExcelProperty("组织名称")
@ExcelProperty("excel.export.head.product.delay.orgName")
private String organName;
@Schema(description = "产品名称")
@ExcelProperty("产品名称")
@ExcelProperty("excel.export.head.product.delay.productName")
private String productName;
@Schema(description = "延期时长")
@ExcelProperty("延期时长")
@ExcelProperty("excel.export.head.product.delay.delayDuration")
private Integer delayDuration;
@Schema(description = "延期时长单位")
@ExcelProperty(value = "延期时长单位", converter = EnumConvert.class)
@ExcelProperty(value = "excel.export.head.product.delay.delayDurationUnit", converter = EnumConvert.class)
@EnumFormat(value = DurationUnitEnum.class)
private Integer delayDurationUnit;
@@ -51,24 +51,24 @@ public class ProductDelayRespVO {
private LocalDate endTime;
@Schema(description = "产品有效时间")
@ExcelProperty("产品有效时间")
@ExcelProperty("excel.export.head.product.delay.delayTime")
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY, timezone = TIME_ZONE_DEFAULT)
private LocalDate delayTime;
@Schema(description = "备注")
@ExcelProperty("备注")
@ExcelProperty("excel.export.head.product.delay.remark")
private String remark;
@Schema(description = "操作时间")
@ExcelProperty("操作时间")
@ExcelProperty("excel.export.head.product.delay.createTime")
private LocalDateTime createTime;
@Schema(description = "操作人")
@ExcelProperty("操作人")
@ExcelProperty("excel.export.head.product.delay.creator")
private String creator;
@Schema(description = "是否支付")
@ExcelProperty(value = "是否支付", converter = EnumBoolValConvert.class)
@ExcelProperty(value = "excel.export.head.product.delay.paid", converter = EnumBoolValConvert.class)
@EnumFormat(value = WhetherEnum.class)
private Boolean paid;
}
@@ -3,71 +3,71 @@ package com.cf.imes.module.system.controller.admin.funds.purchase.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.cf.imes.framework.excel.core.annotations.EnumFormat;
import com.cf.imes.framework.excel.core.convert.EnumConvert;
import com.cf.imes.framework.jackson.core.databind.LocalDateSerializer;
import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
public class ManagePurchaseRecordRespVO {
@Schema(description = "订单号")
@ExcelProperty("excel.export.head.purchase.record.id")
private Long id;
@Schema(description = "组织名称")
@ExcelProperty("组织名称")
@ExcelProperty("excel.export.head.purchase.record.organName")
private String organName;
@Schema(description = "产品名称")
@ExcelProperty("产品名称")
@ExcelProperty("excel.export.head.purchase.record.product.name")
private String productName;
@Schema(description = "购买时长", example = "1")
@ExcelProperty("购买时长")
@ExcelProperty("excel.export.head.purchase.record.purchase.duration")
private Integer purchaseDuration;
@Schema(description = "购买时长单位,0:年、1:月", example = "1")
@ExcelProperty(value = "购买时长单位", converter = EnumConvert.class)
@ExcelProperty(value = "excel.export.head.purchase.record.purchase.duration.unit", converter = EnumConvert.class)
@EnumFormat(value = ProductDurationUnitEnum.class)
private Integer purchaseDurationUnit;
@Schema(description = "赠送时长", example = "1")
@ExcelProperty("赠送时长")
@ExcelProperty("excel.export.head.purchase.record.gift.duration")
private Integer giftDuration;
@Schema(description = "赠送时长单位,0:年、1:月", example = "1")
@ExcelProperty(value = "赠送时长单位", converter = EnumConvert.class)
@ExcelProperty(value = "excel.export.head.purchase.record.gift.duration.unit", converter = EnumConvert.class)
@EnumFormat(value = ProductDurationUnitEnum.class)
private Integer giftDurationUnit;
@Schema(description = "支付方式")
private Integer paymentMethod;
@ExcelProperty("excel.export.head.purchase.record.payment.method")
private String paymentMethod;
@Schema(description = "订单总额")
@ExcelProperty("订单总额")
@ExcelProperty("excel.export.head.purchase.record.total.amount")
private BigDecimal totalAmount;
@Schema(description = "现金余额支出")
@ExcelProperty("现金余额支出")
private BigDecimal accountBalanceSpent;
@Schema(description = "支付宝支出")
@ExcelProperty("支付宝支出")
private BigDecimal alipaySpent;
@Schema(description = "微信支出")
@ExcelProperty("微信支出")
private BigDecimal wechatSpent;
@Schema(description = "赠送金")
@ExcelProperty("赠送金")
private BigDecimal giftMoneySpent;
@Schema(description = "扫码支付")
@ExcelProperty("excel.export.head.purchase.record.external.spent")
private BigDecimal externalSpent;
@Schema(description = "购买时间")
@ExcelProperty("购买时间")
@ExcelProperty("excel.export.head.purchase.record.create.time")
private LocalDateTime createTime;
@Schema(description = "操作人")
@ExcelProperty("操作人")
@ExcelProperty("excel.export.head.purchase.record.creator")
private String creator;
@Schema(description = "产品有效时间")
@ExcelProperty("excel.export.head.purchase.record.end.time")
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate endTime;
}
@@ -20,7 +20,7 @@ public class PurchaseRecordRespVO {
@Schema(description = "订单号")
@ExcelProperty("订单号")
@ExcelProperty("excel.export.head.purchase.record.id")
private Long id;
@Schema(description = "组织ID")
@@ -28,64 +28,53 @@ public class PurchaseRecordRespVO {
private Long organId;
@Schema(description = "组织名称")
@ExcelIgnore
@ExcelProperty("excel.export.head.purchase.record.organName")
private String organName;
@Schema(description = "产品名称")
@ExcelProperty("产品名称")
@ExcelProperty("excel.export.head.purchase.record.product.name")
private String productName;
@Schema(description = "订单号")
@ExcelProperty("订单号")
private String orderNo;
@Schema(description = "购买时长", example = "1")
@ExcelProperty("购买时长")
@ExcelProperty("excel.export.head.purchase.record.purchase.duration")
private Integer purchaseDuration;
@Schema(description = "购买时长单位,0:年、1:月", example = "1")
@ExcelProperty(value = "购买时长单位", converter = EnumConvert.class)
@ExcelProperty(value = "excel.export.head.purchase.record.purchase.duration.unit", converter = EnumConvert.class)
@EnumFormat(value = ProductDurationUnitEnum.class)
private Integer purchaseDurationUnit;
@Schema(description = "赠送时长", example = "1")
@ExcelProperty("赠送时长")
@ExcelProperty("excel.export.head.purchase.record.gift.duration")
private Integer giftDuration;
@Schema(description = "赠送时长单位,0:年、1:月", example = "1")
@ExcelProperty(value = "赠送时长单位", converter = EnumConvert.class)
@ExcelProperty(value = "excel.export.head.purchase.record.gift.duration.unit", converter = EnumConvert.class)
@EnumFormat(value = ProductDurationUnitEnum.class)
private Integer giftDurationUnit;
@Schema(description = "支付方式")
@ExcelProperty("excel.export.head.purchase.record.payment.method")
private String paymentMethod;
@Schema(description = "订单总额")
@ExcelProperty("订单总额")
@ExcelProperty("excel.export.head.purchase.record.total.amount")
private BigDecimal totalAmount;
@Schema(description = "现金余额支出")
@ExcelProperty("现金余额支出")
private BigDecimal accountBalanceSpent;
@Schema(description = "赠送金")
@ExcelProperty("赠送金")
private BigDecimal giftMoneySpent;
@Schema(description = "扫码支付")
@ExcelProperty("扫码支付")
@ExcelProperty("excel.export.head.purchase.record.external.spent")
private BigDecimal externalSpent;
@Schema(description = "购买时间")
@ExcelProperty("购买时间")
@ExcelProperty("excel.export.head.purchase.record.create.time")
private LocalDateTime createTime;
@Schema(description = "操作人")
@ExcelProperty("操作人")
@ExcelProperty("excel.export.head.purchase.record.creator")
private String creator;
@Schema(description = "产品有效时间")
@ExcelProperty("产品有效时间")
@ExcelProperty("excel.export.head.purchase.record.end.time")
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate endTime;
}
@@ -19,34 +19,35 @@ import java.time.LocalDateTime;
public class SalesDetailRespVO {
@Schema(description = "订单号")
@ExcelProperty("订单号")
@ExcelProperty("excel.export.head.sales.detail.id")
private Long id;
@Schema(description = "交易类型,0充值 1软件购买")
@ExcelProperty(value = "交易类型", converter = EnumConvert.class)
@ExcelProperty(value = "excel.export.head.sales.detail.trade.type", converter = EnumConvert.class)
@EnumFormat(value = TradeTypeEnum.class)
private Integer tradeType;
@Schema(description = "产品金额")
@ExcelProperty("产品金额")
@ExcelProperty("excel.export.head.sales.detail.total.amount")
private BigDecimal totalAmount;
@Schema(description = "扫码支付")
@ExcelProperty("扫码支付")
@ExcelProperty("excel.export.head.sales.detail.recharge.spent")
private BigDecimal rechargeSpent;
@Schema(description = "操作人")
@ExcelProperty("操作人")
@ExcelProperty("excel.export.head.sales.detail.creator")
private String creator;
@Schema(description = "组织名称")
@ExcelProperty("组织名称")
@ExcelProperty("excel.export.head.sales.detail.orgName")
private String organName;
@Schema(description = "支付方式")
@ExcelProperty("excel.export.head.sales.detail.payMethod")
private String paymentMethod;
@Schema(description = "交易时间")
@ExcelProperty("交易时间")
@ExcelProperty("excel.export.head.sales.detail.createTime")
private LocalDateTime createTime;
}
@@ -8,6 +8,7 @@ import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.excel.core.util.ExcelUtils;
import com.cf.imes.framework.operatelog.core.annotations.OperateLog;
@@ -71,6 +72,9 @@ public class OrganController {
@Resource
private OrganAmountService organAmountService;
@Resource
private I18nUtils i18nUtils;
@GetMapping("/get-id-by-name")
@PermitAll
@Operation(summary = "使用组织名,获得组织编号", description = "登录界面,根据用户的组织名,获得组织编号")
@@ -136,7 +140,7 @@ public class OrganController {
// 产品有效时间展示为第一项的计算延期时间
p.setEndTime(delayRecordsByPurchaseId.get(0).getDelayTime());
// 延期时长展示为延期记录的时长+单位,用顿号分隔
p.setDelayDuration(delayRecordsByPurchaseId.stream().map(m -> m.getDelayDuration() + DurationUnitEnum.getDesc(m.getDelayDurationUnit())).collect(Collectors.joining("")));
p.setDelayDuration(delayRecordsByPurchaseId.stream().map(m -> m.getDelayDuration() + i18nUtils.getMessage(DurationUnitEnum.getDesc(m.getDelayDurationUnit()))).collect(Collectors.joining("")));
}
});
bean.setOrganPurchaseList(orgPurchaseList);
@@ -213,7 +217,7 @@ public class OrganController {
// 产品有效时间展示为第一项的计算延期时间
p.setEndTime(delayRecordsByPurchaseId.get(0).getDelayTime());
// 延期时长展示为延期记录的时长+单位,用顿号分隔
p.setDelayDuration(delayRecordsByPurchaseId.stream().map(m -> m.getDelayDuration() + DurationUnitEnum.getDesc(m.getDelayDurationUnit())).collect(Collectors.joining("")));
p.setDelayDuration(delayRecordsByPurchaseId.stream().map(m -> m.getDelayDuration() + i18nUtils.getMessage(DurationUnitEnum.getDesc(m.getDelayDurationUnit()))).collect(Collectors.joining("")));
}
});
e.setOrganPurchaseList(purchaseRespVOList);
@@ -1,50 +0,0 @@
package com.cf.imes.module.system.dal.dataobject.funds.advertisement;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.cf.imes.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
/**
* 广告状态修改任务
*
*/
@TableName("system_advertisement_task")
@KeySequence("system_advertisement_task_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdvertisementTaskDO extends BaseDO {
/**
* 主键
*/
@TableId
private Long id;
/**
* 广告id
*/
private Long advertisementId;
/**
* 消息id
*/
private String messageId;
/**
* 广告状态,AdvertisementStatusEnum
*/
private Integer advertisementStatus;
/**
* 消费状态 MessageStatusEnum
*/
private Integer messageStatus;
private Boolean deleted;
}
@@ -25,4 +25,12 @@ public interface DictDataI18nMapper extends BaseMapperX<DictDatai18nDO> {
* @return
*/
List<DictDataDO> getLocaleDictData(@Param("ids") Collection<Long> ids, @Param("locale") String locale);
/**
* 查询指定字典类型的字典数据
*
* @param dictType
* @return
*/
List<DictDataDO> selectListByDictType(@Param("dictType") String dictType, @Param("locale") String locale);
}
@@ -1,45 +0,0 @@
package com.cf.imes.module.system.dal.mysql.funds.advertisement;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.module.system.dal.dataobject.funds.advertisement.AdvertisementTaskDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 广告消费信息表 Mapper
*
* @author 晨丰科技
*/
@Mapper
public interface AdvertisementTaskMapper extends BaseMapperX<AdvertisementTaskDO> {
default int updateToDeletedById(Long adId, Boolean deleted, Integer messageStatus) {
return update(new LambdaUpdateWrapper<AdvertisementTaskDO>()
.set(AdvertisementTaskDO::getDeleted, deleted)
.set(AdvertisementTaskDO::getMessageStatus, messageStatus)
.eq(AdvertisementTaskDO::getAdvertisementId, adId));
}
default List<String> selectIdByAdvertisementId(Long adId) {
return selectList(new LambdaUpdateWrapper<AdvertisementTaskDO>()
.eq(AdvertisementTaskDO::getAdvertisementId, adId))
.stream()
.map(AdvertisementTaskDO::getMessageId)
.toList();
}
default AdvertisementTaskDO selectByMessageId(String messageId) {
return selectOne(new LambdaUpdateWrapper<AdvertisementTaskDO>()
.eq(AdvertisementTaskDO::getMessageId, messageId)
.eq(AdvertisementTaskDO::getDeleted, Boolean.FALSE));
}
default int updateMessageStateByMessageId(String messageId, Boolean deleted, Integer messageStatus) {
return update(new LambdaUpdateWrapper<AdvertisementTaskDO>()
.set(AdvertisementTaskDO::getMessageStatus, messageStatus)
.eq(AdvertisementTaskDO::getMessageId, messageId)
.eq(AdvertisementTaskDO::getDeleted, deleted));
}
}
@@ -13,8 +13,8 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
public enum WhetherEnum implements BaseBoolValEnum {
TRUE(true, ""),
FALSE(false, "");
TRUE(true, "whether.yes"),
FALSE(false, "whether.no");
private final Boolean code;
@@ -17,9 +17,9 @@ import java.util.Objects;
@AllArgsConstructor
public enum DurationUnitEnum implements IntArrayValuable, BaseEnum {
YEAR(0, ""),
MONTH(1, ""),
DAY(2, "");
YEAR(0, "duration.unit.year"),
MONTH(1, "duration.unit.month"),
DAY(2, "duration.unit.day");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(DurationUnitEnum::getCode).toArray();
@@ -37,18 +37,6 @@ public enum DurationUnitEnum implements IntArrayValuable, BaseEnum {
return ARRAYS;
}
public static boolean isYear(String name) {
return Objects.equals(YEAR.code, name);
}
public static boolean isMonth(String name) {
return Objects.equals(MONTH.code, name);
}
public static boolean isDay(String name) {
return Objects.equals(DAY.code, name);
}
public static DurationUnitEnum fromStatus(Integer status) {
return Arrays.stream(values())
.filter(bean -> Objects.equals(bean.code, status))
@@ -18,11 +18,11 @@ public enum PayChannelCodeEnum {
/**
* 支付宝
*/
ALIPAY_PC(0, "支付宝"),
ALIPAY_PC(0, "pay.channel.alipay"),
/**
* 微信
*/
WECHAT_NATIVE(1, "微信");
WECHAT_NATIVE(1, "pay.channel.wechat");
@EnumValue
private final Integer code;
@@ -1,97 +0,0 @@
package com.cf.imes.module.system.enums.pay;
import com.cf.imes.framework.excel.core.convert.BaseEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 产品支付渠道编码
*
* @author Gqr
* @since 2024/7/5 9:25
*/
@Getter
@AllArgsConstructor
public enum PayProductChannelCodeEnum implements BaseEnum {
/**
* 账户余额
*/
BALANCE_ONLY(0, "现金"),
/**
* 赠送金
*/
GIFT_ONLY(1, "赠送金"),
/**
* 支付宝
*/
ALIPAY_PC(2, "支付宝"),
/**
* 微信
*/
WECHAT_NATIVE(3, "微信"),
/**
* 现金+赠送金
*/
BALANCE_AND_GIFT(4, "现金+赠送金"),
/**
* 现金+支付宝
*/
BALANCE_AND_ALIPAY(5, "现金+支付宝"),
/**
* 现金+微信
*/
BALANCE_AND_WECHAT(6, "现金+微信"),
/**
* 赠送金+支付宝
*/
GIFT_AND_ALIPAY(7, "赠送金+支付宝"),
/**
* 赠送金+微信
*/
GIFT_AND_WECHAT(8, "赠送金+微信"),
/**
* 现金+赠送金+支付宝
*/
BALANCE_AND_GIFT_AND_ALIPAY(9, "现金+赠送金+支付宝"),
/**
* 现金+赠送金+微信
*/
BALANCE_AND_GIFT_AND_WECHAT(10, "现金+赠送金+微信"),
/**
* 组织创建首次购买
*/
ORGAN_CREATE(11, "首次订购");
private final Integer code;
private final String desc;
public static PayProductChannelCodeEnum fromType(Integer type) {
for (PayProductChannelCodeEnum value : values()) {
if (value.getCode().equals(type)) {
return value;
}
}
return null;
}
/**
* 产品购买渠道是否包含支付宝支付方式
*
* @param code
* @return
*/
public static boolean isAliPay(Integer code) {
return code.equals(ALIPAY_PC.code) || code.equals(BALANCE_AND_ALIPAY.code) || code.equals(GIFT_AND_ALIPAY.code) || code.equals(BALANCE_AND_GIFT_AND_ALIPAY.code);
}
}
@@ -17,8 +17,8 @@ import java.util.Objects;
@AllArgsConstructor
public enum ProductDurationUnitEnum implements IntArrayValuable, BaseEnum {
YEAR(0, ""),
MONTH(1, "");
YEAR(0, "duration.unit.year"),
MONTH(1, "duration.unit.month");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductDurationUnitEnum::getCode).toArray();
@@ -36,10 +36,6 @@ public enum ProductDurationUnitEnum implements IntArrayValuable, BaseEnum {
return ARRAYS;
}
public static boolean isYear(String name) {
return Objects.equals(YEAR.code, name);
}
public static ProductDurationUnitEnum fromStatus(Integer status) {
return Arrays.stream(values())
.filter(bean -> Objects.equals(bean.code, status))
@@ -17,7 +17,7 @@ public enum TradeTypeEnum implements BaseEnum {
/**
* 产品购买
*/
PRODUCT(1, "产品购买");
PRODUCT(1, "trade.type.product");
private final Integer code;
@@ -32,16 +32,6 @@ public enum TradeTypeEnum implements BaseEnum {
return null;
}
/**
* 是否产品购买
*
* @param code
* @return
*/
public static boolean isProduct(Integer code) {
return PRODUCT.getCode().equals(code);
}
/**
* 获取需要筛选的类型:充值、产品购买
*
@@ -1,71 +0,0 @@
//package com.cf.imes.module.system.mq.consumer.advertisement;
//
//import com.cf.imes.framework.mq.rabbitmq.constant.RabbitMqConstants;
//import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementDO;
//import com.cf.imes.module.system.dal.dataobject.advertisement.AdvertisementTaskDO;
//import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementMapper;
//import com.cf.imes.module.system.dal.mysql.advertisement.AdvertisementTaskMapper;
//import com.cf.imes.module.system.enums.advertisement.AdvertisementStatusEnum;
//import com.cf.imes.module.system.enums.advertisement.MessageStatusEnum;
//import com.cf.imes.module.system.mq.message.advertisement.AdvertisementSendMessage;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.amqp.rabbit.annotation.RabbitListener;
//import org.springframework.stereotype.Component;
//
//import jakarta.annotation.Resource;
//import java.time.LocalDateTime;
//import java.util.Objects;
//
//
///**
// * 针对 {@link AdvertisementSendMessage} 的消费者
// *
// * @author 晨丰科技
// */
//@Component
//@Slf4j
//public class AdvertisementSendConsumer {
//
// @Resource
// private AdvertisementMapper advertisementMapper;
//
// @Resource
// private AdvertisementTaskMapper advertisementTaskMapper;
//
// @RabbitListener(queues = RabbitMqConstants.SYSTEM_ADVERTISEMENT_UPDATE_DELAYED_QUEUE)
// public void onMessage(AdvertisementSendMessage message){
// // 1. 获取广告数据
// AdvertisementDO ad = advertisementMapper.selectById(message.getAdId());
// if (ad == null || ad.getDeleted())
// return;
//
// // 2. 检查消息有效性
// AdvertisementTaskDO messageRecord = advertisementTaskMapper.selectByMessageId(message.getMessageId());
// if (messageRecord == null ||
// Objects.equals(messageRecord.getMessageStatus(), MessageStatusEnum.CANCELLED.getStatus())) {
// return;
// }
//
// // 3. 处理状态变更
// if (AdvertisementStatusEnum.PUBLISHED.getName().equals(message.getAction())) { // 待发布
// if (ad.getStatus() == AdvertisementStatusEnum.UNPUBLISHED.getStatus() &&
// LocalDateTime.now().isAfter(ad.getStartTime())) {
// updateAdStatus(ad, messageRecord.getAdvertisementStatus());
// }
// } else if (AdvertisementStatusEnum.ENDED.getName().equals(message.getAction())) { // 待结束
// if (ad.getStatus() == AdvertisementStatusEnum.PUBLISHED.getStatus() &&
// LocalDateTime.now().isAfter(ad.getEndTime())) {
// updateAdStatus(ad, messageRecord.getAdvertisementStatus());
// }
// }
//
// // 4. 标记消息为已处理
// messageRecord.setMessageStatus(MessageStatusEnum.PROCESSED.getStatus());
// advertisementTaskMapper.updateMessageStateByMessageId(message.getMessageId(),false, MessageStatusEnum.PROCESSED.getStatus());
// }
//
// private void updateAdStatus(AdvertisementDO ad, Integer newStatus) {
// advertisementMapper.updateAdStatus(ad.getId(), newStatus);
// }
//
//}
@@ -5,6 +5,7 @@ import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.productpromotion.vo.ProductPromotionPageReqVO;
@@ -41,6 +42,9 @@ public class ProductPromotionServiceImpl implements ProductPromotionService {
@Resource
private ProductsDetailService productsDetailService;
@Resource
private I18nUtils i18nUtils;
@Override
public Long create(ProductPromotionSaveReqVO createReqVO) {
Long productId = createReqVO.getProductId();
@@ -60,7 +64,7 @@ public class ProductPromotionServiceImpl implements ProductPromotionService {
.eq(ProductPromotionDO::getPurchaseDurationUnit, createReqVO.getPurchaseDurationUnit())
.eq(ProductPromotionDO::getProductId, productId));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, createReqVO.getPurchaseDuration(), DurationUnitEnum.getDesc(createReqVO.getPurchaseDurationUnit()));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, createReqVO.getPurchaseDuration(), i18nUtils.getMessage(DurationUnitEnum.getDesc(createReqVO.getPurchaseDurationUnit())));
ProductPromotionDO promotionDO = BeanUtils.toBean(createReqVO, ProductPromotionDO.class);
promotionDO.setProductId(productsDO.getId());
@@ -92,7 +96,7 @@ public class ProductPromotionServiceImpl implements ProductPromotionService {
.ne(ProductPromotionDO::getId, updateReqVO.getId())
.eq(ProductPromotionDO::getProductId, productId));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, updateReqVO.getPurchaseDuration(), DurationUnitEnum.getDesc(updateReqVO.getPurchaseDurationUnit()));
AssertUtils.empty(productPromotionDO, PRODUCT_PROMOTION_PURCHASEDURATION_IS_EXIST, updateReqVO.getPurchaseDuration(), i18nUtils.getMessage(DurationUnitEnum.getDesc(updateReqVO.getPurchaseDurationUnit())));
ProductPromotionDO promotionDO = BeanUtils.toBean(updateReqVO, ProductPromotionDO.class);
promotionDO.setProductId(productsDO.getId());
@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsPageReqVO;
@@ -40,6 +41,9 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
@Resource
private ProductsMapper productsMapper;
@Resource
private I18nUtils i18nUtils;
@Override
public Long create(ProductDetailsSaveReqVO createReqVO) {
@@ -166,7 +170,7 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
// 时长去重
count = productDetailsMapper.selectCountByDuration(createReqVO.getProductId(), createReqVO.getId(), duration, durationUnit);
if (count > 0) {
throw new ServiceException(PRODUCTS_DETAIL_DURATION_EXIST, duration, ProductDurationUnitEnum.getDesc(durationUnit));
throw new ServiceException(PRODUCTS_DETAIL_DURATION_EXIST, duration, i18nUtils.getMessage(ProductDurationUnitEnum.getDesc(durationUnit)));
}
}
@@ -11,6 +11,7 @@ import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.date.LocalDateTimeUtils;
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO;
@@ -88,6 +89,9 @@ public class PurchaseServiceImpl implements PurchaseService {
@Resource
private ProductPromotionService productPromotionService;
@Resource
private I18nUtils i18nUtils;
@Override
public PurchaseRecordDO getRecord(Long id) {
return purchaseRecordMapper.selectById(id);
@@ -126,7 +130,7 @@ public class PurchaseServiceImpl implements PurchaseService {
List<PurchaseRecordRespVO> respVOS = new ArrayList<>();
for (PurchaseRecordDO purchaseRecordDO : resultList) {
PurchaseRecordRespVO respVO = BeanUtil.copyProperties(purchaseRecordDO, PurchaseRecordRespVO.class, "paymentMethod");
respVO.setPaymentMethod(PayChannelCodeEnum.describe(purchaseRecordDO.getPaymentMethod()));
respVO.setPaymentMethod(i18nUtils.getMessage(PayChannelCodeEnum.describe(purchaseRecordDO.getPaymentMethod())));
respVOS.add(respVO);
}
respVOS.forEach(respVO -> {
@@ -316,7 +320,7 @@ public class PurchaseServiceImpl implements PurchaseService {
// 充值支付=支付宝/微信
respVO.setRechargeSpent(detailDO.getExternalSpent());
// 支付方式
respVO.setPaymentMethod(PayChannelCodeEnum.describe(detailDO.getPaymentMethod()));
respVO.setPaymentMethod(i18nUtils.getMessage(PayChannelCodeEnum.describe(detailDO.getPaymentMethod())));
// 查询组织名称
OrganizationDO organ = organService.getOrganWithDeleted(detailDO.getOrganId());
if (ObjectUtil.isNotNull(organ)) {
@@ -1,5 +1,6 @@
package com.cf.imes.module.system.service.funds.statistics;
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
import com.cf.imes.module.system.controller.admin.statistics.vo.OrgStatusGroupStatisticsReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.statistics.FundsTradeTypeGroupStatisticsDO;
import com.cf.imes.module.system.dal.mysql.incomeandexpense.IncomeExpenseDetailsMapper;
@@ -31,6 +32,9 @@ public class FundsStatisticsServiceImpl implements FundsStatisticsService {
@Resource
private IncomeExpenseDetailsMapper incomeExpenseDetailsMapper;
@Resource
private I18nUtils i18nUtils;
@Override
public Map<String, Object> getFunsTradeTypeGroupStatistics(OrgStatusGroupStatisticsReqVO reqVO) {
Map<String, Object> resultMap = new LinkedHashMap<>();
@@ -58,7 +62,7 @@ public class FundsStatisticsServiceImpl implements FundsStatisticsService {
purchaseCountArr[i] = purchaseAmount;
}
purchaseSeriesItem.put("data", purchaseCountArr);
purchaseSeriesItem.put("name", "销售额");
purchaseSeriesItem.put("name", i18nUtils.getMessage("statistics.series.name.saleAmount"));
series.add(purchaseSeriesItem);
// x轴时间区间字符串
@@ -13,6 +13,7 @@ import com.cf.imes.framework.common.pojo.PageParam;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.collection.CollectionUtils;
import com.cf.imes.framework.common.util.date.DateUtils;
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
import com.cf.imes.framework.common.util.pinyin.PinYinUtils;
@@ -161,6 +162,9 @@ public class OrganServiceImpl implements OrganService {
@Resource
private PurchaseService purchaseService;
@Resource
private I18nUtils i18nUtils;
@Override
public List<Long> getOrganIdList() {
List<OrganizationDO> organizationDOS = organMapper.selectList();
@@ -780,9 +784,9 @@ public class OrganServiceImpl implements OrganService {
deleteCountArr[i] = orderLapseCount;
}
addSeriesItem.put("data", addCountArr);
addSeriesItem.put("name", "新增");
addSeriesItem.put("name", i18nUtils.getMessage("statistics.series.name.add"));
deleteSeriesItem.put("data", deleteCountArr);
deleteSeriesItem.put("name", "注销");
deleteSeriesItem.put("name", i18nUtils.getMessage("statistics.series.name.del"));
series.add(addSeriesItem);
series.add(deleteSeriesItem);
@@ -8,10 +8,11 @@ import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.system.controller.admin.systemconfig.vo.*;
import com.cf.imes.module.system.dal.dataobject.dict.DictDataDO;
import com.cf.imes.module.system.dal.dataobject.systemconfig.SystemConfigDO;
import com.cf.imes.module.system.dal.mysql.dict.DictDataMapper;
import com.cf.imes.module.system.dal.mysql.dict.DictDataI18nMapper;
import com.cf.imes.module.system.dal.mysql.systemconfig.SystemConfigMapper;
import com.cf.imes.module.system.enums.config.SystemConfigTypeEnum;
import com.cf.imes.module.system.service.systemconfig.factory.service.AbstractSystemConfigServiceHandler;
import com.cf.imes.module.system.util.locale.LocaleUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -34,15 +35,12 @@ public class DefaultSystemConfigServiceHandler extends AbstractSystemConfigServi
private SystemConfigMapper systemConfigMapper;
@Resource
private DictDataMapper dictDataMapper;
@Resource
private CustomPlateNoServiceHandler customPlateNoServiceHandler;
private DictDataI18nMapper dictDataI18nMapper;
@Override
public List<SystemConfigDO> selectList(ConfigPageReqVO reqVO) {
List<DictDataDO> dictDataDOS = dictDataMapper.selectListByStatusAndDictType(CommonStatusEnum.ENABLE.getStatus(), "system_config_type_enum");
List<DictDataDO> dictDataDOS = dictDataI18nMapper.selectListByDictType("system_config_type_enum", LocaleUtils.getLocale());
if(CollUtil.isEmpty(dictDataDOS)){
log.error("系统配置项对应的字典被关闭或数据查询有误");
@@ -12,6 +12,7 @@ import com.cf.imes.framework.common.enums.UserTypeEnum;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.collection.CollectionUtils;
import com.cf.imes.framework.common.util.i18n.core.util.I18nUtils;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.monitor.TracerUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
@@ -115,6 +116,9 @@ public class AdminUserServiceImpl implements AdminUserService {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Resource
private I18nUtils i18nUtils;
// 定义密码校验的正则表达式
private static final String LENGTH_PATTERN = ".{8,}";
private static final String UPPER_LETTER_PATTERN = ".*[A-Z].*";
@@ -852,9 +856,9 @@ public class AdminUserServiceImpl implements AdminUserService {
deleteCountArr[i] = deleteCount;
}
addSeriesItem.put("data", addCountArr);
addSeriesItem.put("name", "新增");
addSeriesItem.put("name", i18nUtils.getMessage("statistics.series.name.add"));
deleteSeriesItem.put("data", deleteCountArr);
deleteSeriesItem.put("name", "注销");
deleteSeriesItem.put("name", i18nUtils.getMessage("statistics.series.name.del"));
series.add(addSeriesItem);
series.add(deleteSeriesItem);
@@ -1,31 +0,0 @@
package com.cf.imes.module.system.validation.pay;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 产品支付渠道编码校验注解
* @author Gqr
* @since 2025/4/18 10:21
*/
@Target({
ElementType.FIELD,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {PayProductChannelCodeValidator.class}
)
public @interface PayProductChannelCodeValid {
String message() default "不支持的支付渠道";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -1,27 +0,0 @@
package com.cf.imes.module.system.validation.pay;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.pay.PayProductChannelCodeEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
/**
* 产品支付渠道编码校验器
*
* @author Gqr
* @since 2025/4/18 10:22
*/
public class PayProductChannelCodeValidator implements ConstraintValidator<PayProductChannelCodeValid, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (ObjectUtil.isNull(value)) {
return true;
}
for (PayProductChannelCodeEnum codeEnum : PayProductChannelCodeEnum.values()) {
if (ObjectUtil.equal(codeEnum.getCode(), value)) {
return true;
}
}
return false;
}
}
@@ -1,25 +0,0 @@
package com.cf.imes.module.system.validation.products;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
/**
* 产品详情购买方式校验注解
*/
@Target({
ElementType.FIELD,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {ProductTypeValidator.class}
)
public @interface ProductType {
String message() default "购买方式不合法:0 时长;1 产量";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -1,28 +0,0 @@
package com.cf.imes.module.system.validation.products;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Objects;
/**
* 产品详情购买方式校验器
*/
public class ProductTypeValidator implements ConstraintValidator<ProductType, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (ObjectUtil.isNull(value)) {
return true;
}
for (ProductsPurchaseTypeEnum statusEnum : ProductsPurchaseTypeEnum.values()) {
if (Objects.equals(statusEnum.getStatus(), value)) {
return true;
}
}
return false;
}
}
@@ -207,13 +207,17 @@ chenfeng:
- /admin-api/system/pay/product
- /admin-api/system/recharge-active/available
- /admin-api/system/pay/recharge
- /admin-api/system/dict-data/i18n/version
ignore-tables:
- system_organization
- system_tenant_package
- system_dict_data
- system_dict_data_i18n
- system_dict_data_i18n_version
- system_dict_type
- system_error_code
- system_menu
- system_menu_i18n
- system_sms_channel
- system_sms_template
- system_sms_log
@@ -222,13 +222,17 @@ chenfeng:
- /admin-api/system/pay/product
- /admin-api/system/recharge-active/available
- /admin-api/system/pay/recharge
- /admin-api/system/dict-data/i18n/version
ignore-tables:
- system_organization
- system_tenant_package
- system_dict_data
- system_dict_data_i18n
- system_dict_data_i18n_version
- system_dict_type
- system_error_code
- system_menu
- system_menu_i18n
- system_sms_channel
- system_sms_template
- system_sms_log
@@ -98,7 +98,7 @@ spring:
repositories:
enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度
messages:
basename: message,message_errorcode
basename: message,message_errorcode,message_enum
trans:
config:
appId: 20251110002494620
@@ -20,4 +20,15 @@
</foreach>
</if>
</select>
<select id="selectListByDictType" resultType="com.cf.imes.module.system.dal.dataobject.dict.DictDataDO">
select
coalesce(i.label, d.label) as label,
d.value
from system_dict_data d
left join system_dict_data_i18n i
on d.id = i.dict_data_id and i.locale = #{locale}
where d.deleted = false
and d.dict_type = #{dictType}
</select>
</mapper>
@@ -8,7 +8,7 @@ ad.position.notEmpty=广告位置不能为空
ad.sort.field=广告顺序
ad.startTime.notNull=投放开始时间不能为空
ad.status.invalid=广告状态不合法
inEnum.message=必须在指定范围 {0}
invoice.apply.purchase.list.notEmpty=单词开票选择购买记录不能为空
invoice.apply.purchase.size=单次开票选择购买记录不能超过100条
invoice.confirm.id.notNull=发票申请记录编号不能为空
@@ -83,6 +83,9 @@ sales.detail.page.productPrice.max=产品购买金额不能超过十万
sales.detail.page.productPrice.min=产品购买金额必须大于零
statistics.unit.invalid=统计维度单位不合法
statistics.unit.notNull=统计维度单位不能为空
statistics.series.name.add=新增
statistics.series.name.del=注销
statistics.series.name.saleAmount=销售额
pay.channelCode.invalid=不支持的支付渠道
pay.product.productChannelCode.notNull=产品支付渠道编码不能为空
pay.product.productDetailsId.notNull=产品定价规则编号不能为空
@@ -8,7 +8,7 @@ ad.position.notEmpty=廣告位置不能為空
ad.sort.field=廣告順序
ad.startTime.notNull=投放開始時間不能為空
ad.status.invalid=廣告狀態不合法
inEnum.message=必須在指定範圍 {0}
invoice.apply.purchase.list.notEmpty=單次開票選擇的購買記錄不能為空
invoice.apply.purchase.size=單次開票選擇的購買記錄不能超過 100 條
invoice.confirm.id.notNull=發票申請記錄編號不能為空
@@ -83,6 +83,9 @@ sales.detail.page.productPrice.max=產品購買金額不能超過十萬
sales.detail.page.productPrice.min=產品購買金額必須大於零
statistics.unit.invalid=統計維度單位不合法
statistics.unit.notNull=統計維度單位不能為空
statistics.series.name.add=新增
statistics.series.name.del=註銷
statistics.series.name.saleAmount=銷售額
pay.channelCode.invalid=不支援的支付渠道
pay.product.productChannelCode.notNull=產品支付渠道編碼不能為空
pay.product.productDetailsId.notNull=產品定價規則編號不能為空
@@ -8,7 +8,7 @@ ad.position.notEmpty=Ad position cannot be empty
ad.sort.field=Ad sort order
ad.startTime.notNull=Start time cannot be empty
ad.status.invalid=Invalid ad status
inEnum.message=Must be within the specified range {0}
invoice.apply.purchase.list.notEmpty=Selected purchase records cannot be empty
invoice.apply.purchase.size=You cannot select more than 100 purchase records at once
invoice.confirm.id.notNull=Invoice application ID cannot be empty
@@ -83,6 +83,9 @@ sales.detail.page.productPrice.max=Purchase amount cannot exceed 100,000
sales.detail.page.productPrice.min=Purchase amount must be greater than zero
statistics.unit.invalid=Invalid statistics unit
statistics.unit.notNull=Statistics unit cannot be empty
statistics.series.name.add=Add
statistics.series.name.del=Cancel
statistics.series.name.saleAmount=Sales Volume
pay.channelCode.invalid=Unsupported payment channel
pay.product.productChannelCode.notNull=Product payment channel code cannot be empty
pay.product.productDetailsId.notNull=Product pricing rule ID cannot be empty
@@ -0,0 +1,48 @@
inEnum.message=必须在指定范围 {0}
inScope.message={0}不合法
inScope.adPosition=广告位置
duration.unit.year=
duration.unit.month=
duration.unit.day=
pay.channel.alipay=支付宝
pay.channel.wechat=微信
whether.yes=
whether.no=
trade.type.product=软件购买
excel.export.head.product.delay.orgName=组织名称
excel.export.head.product.delay.productName=产品名称
excel.export.head.product.delay.delayDuration=延期时长
excel.export.head.product.delay.delayDurationUnit=延期时长单位
excel.export.head.product.delay.delayTime=产品有效时间
excel.export.head.product.delay.remark=备注
excel.export.head.product.delay.createTime=操作时间
excel.export.head.product.delay.creator=操作人
excel.export.head.product.delay.paid=是否支付
excel.export.head.sales.detail.id=订单号
excel.export.head.sales.detail.trade.type=交易类型
excel.export.head.sales.detail.total.amount=产品金额
excel.export.head.sales.detail.recharge.spent=扫码支付
excel.export.head.sales.detail.creator=操作人
excel.export.head.sales.detail.orgName=组织名称
excel.export.head.sales.detail.payMethod=支付方式
excel.export.head.sales.detail.createTime=交易时间
excel.export.head.purchase.record.id=订单号
excel.export.head.purchase.record.organName=组织名称
excel.export.head.purchase.record.product.name=产品名称
excel.export.head.purchase.record.purchase.duration=购买时长
excel.export.head.purchase.record.purchase.duration.unit=购买时长单位
excel.export.head.purchase.record.gift.duration=赠送时长
excel.export.head.purchase.record.gift.duration.unit=赠送时长单位
excel.export.head.purchase.record.payment.method=支付方式
excel.export.head.purchase.record.total.amount=订单总额
excel.export.head.purchase.record.external.spent=扫码支付
excel.export.head.purchase.record.create.time=购买时间
excel.export.head.purchase.record.creator=操作人
excel.export.head.purchase.record.end.time=产品有效时间
@@ -0,0 +1,49 @@
inEnum.message=必須在指定範圍 {0}
inScope.message={0}不合法
inScope.adPosition=廣告位置
duration.unit.year=
duration.unit.month=
duration.unit.day=
pay.channel.alipay=支付寶
pay.channel.wechat=微信
whether.yes=
whether.no=
trade.type.product=軟件購買
excel.export.head.product.delay.orgName=組織名稱
excel.export.head.product.delay.productName=產品名稱
excel.export.head.product.delay.delayDuration=延期時長
excel.export.head.product.delay.delayDurationUnit=延期時長單位
excel.export.head.product.delay.delayTime=產品有效時間
excel.export.head.product.delay.remark=備註
excel.export.head.product.delay.createTime=操作時間
excel.export.head.product.delay.creator=操作人
excel.export.head.product.delay.paid=是否支付
excel.export.head.sales.detail.id=訂單號
excel.export.head.sales.detail.trade.type=交易類型
excel.export.head.sales.detail.total.amount=產品金額
excel.export.head.sales.detail.recharge.spent=掃碼支付
excel.export.head.sales.detail.creator=操作人
excel.export.head.sales.detail.orgName=組織名稱
excel.export.head.sales.detail.payMethod=支付方式
excel.export.head.sales.detail.createTime=交易時間
excel.export.head.purchase.record.id=訂單號
excel.export.head.purchase.record.organName=組織名稱
excel.export.head.purchase.record.product.name=產品名稱
excel.export.head.purchase.record.order.no=訂單號
excel.export.head.purchase.record.purchase.duration=購買時長
excel.export.head.purchase.record.purchase.duration.unit=購買時長單位
excel.export.head.purchase.record.gift.duration=贈送時長
excel.export.head.purchase.record.gift.duration.unit=贈送時長單位
excel.export.head.purchase.record.payment.method=支付方式
excel.export.head.purchase.record.total.amount=訂單總額
excel.export.head.purchase.record.external.spent=掃碼支付
excel.export.head.purchase.record.create.time=購買時間
excel.export.head.purchase.record.creator=操作人
excel.export.head.purchase.record.end.time=產品有效時間
@@ -0,0 +1,49 @@
inEnum.message=Must be within the specified range {0}
inScope.message={0} is illegal
inScope.adPosition=Advertising position
duration.unit.year=year
duration.unit.month=month
duration.unit.day=day
pay.channel.alipay=alipay
pay.channel.wechat=wechat
whether.yes=yes
whether.no=no
trade.type.product=Software Purchase
excel.export.head.product.delay.orgName=Organization Name
excel.export.head.product.delay.productName=Product Name
excel.export.head.product.delay.delayDuration=Delay Duration
excel.export.head.product.delay.delayDurationUnit=Delay Duration Unit
excel.export.head.product.delay.delayTime=Product Valid Time
excel.export.head.product.delay.remark=Remarks
excel.export.head.product.delay.createTime=Operation Time
excel.export.head.product.delay.creator=Operator
excel.export.head.product.delay.paid=Payment Status
excel.export.head.sales.detail.id=Order Number
excel.export.head.sales.detail.trade.type=Transaction Type
excel.export.head.sales.detail.total.amount=Product Amount
excel.export.head.sales.detail.recharge.spent=Scan Payment
excel.export.head.sales.detail.creator=Operator
excel.export.head.sales.detail.orgName=Organization Name
excel.export.head.sales.detail.payMethod=Payment Method
excel.export.head.sales.detail.createTime=Transaction Time
excel.export.head.purchase.record.id=Order Number
excel.export.head.purchase.record.organName=Organization Name
excel.export.head.purchase.record.product.name=Product Name
excel.export.head.purchase.record.order.no=Order Number
excel.export.head.purchase.record.purchase.duration=Purchase Duration
excel.export.head.purchase.record.purchase.duration.unit=Purchase Duration Unit
excel.export.head.purchase.record.gift.duration=Gift Duration
excel.export.head.purchase.record.gift.duration.unit=Gift Duration Unit
excel.export.head.purchase.record.payment.method=Payment Method
excel.export.head.purchase.record.total.amount=Total Amount
excel.export.head.purchase.record.external.spent=QR Payment Amount
excel.export.head.purchase.record.create.time=Purchase Time
excel.export.head.purchase.record.creator=Operator
excel.export.head.purchase.record.end.time=Product Valid Until