Initial commit

This commit is contained in:
jackyu66git
2026-03-23 11:52:51 +08:00
commit ea8d889fbe
1114 changed files with 92438 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.oneone.cloud</groupId>
<artifactId>oneone-common</artifactId>
<version>${revision}</version>
</parent>
<artifactId>common-biz</artifactId>
<dependencies>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>oneone-upms-api</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-redis</artifactId>
</dependency>
<dependency>
<groupId>com.oneone.cloud</groupId>
<artifactId>common-mybatis-plus</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,43 @@
package com.oneone.common.biz.datapermission.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.oneone.common.mybatis.datapermission.core.aop.DataPermissionAnnotationAdvisor;
import com.oneone.common.mybatis.datapermission.core.db.DataPermissionDatabaseInterceptor;
import com.oneone.common.mybatis.datapermission.core.rule.DataPermissionRule;
import com.oneone.common.mybatis.datapermission.core.rule.DataPermissionRuleFactory;
import com.oneone.common.mybatis.datapermission.core.rule.DataPermissionRuleFactoryImpl;
import com.oneone.common.mybatis.util.MyBatisUtils;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import java.util.List;
/**
* 数据权限的自动配置类
*
*/
@AutoConfiguration
public class DataPermissionAutoConfiguration {
@Bean
public DataPermissionRuleFactory dataPermissionRuleFactory(List<DataPermissionRule> rules) {
return new DataPermissionRuleFactoryImpl(rules);
}
@Bean
public DataPermissionDatabaseInterceptor dataPermissionDatabaseInterceptor(MybatisPlusInterceptor interceptor,
DataPermissionRuleFactory ruleFactory) {
// 创建 DataPermissionDatabaseInterceptor 拦截器
DataPermissionDatabaseInterceptor inner = new DataPermissionDatabaseInterceptor(ruleFactory);
// 添加到 interceptor 中
// 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
MyBatisUtils.addInterceptor(interceptor, inner, 0);
return inner;
}
@Bean
public DataPermissionAnnotationAdvisor dataPermissionAnnotationAdvisor() {
return new DataPermissionAnnotationAdvisor();
}
}
@@ -0,0 +1,40 @@
package com.oneone.common.biz.datapermission.config;
import cn.hutool.extra.spring.SpringUtil;
import com.oneone.common.biz.datapermission.rule.dept.DeptDataPermissionRule;
import com.oneone.common.biz.datapermission.rule.dept.DeptDataPermissionRuleCustomizer;
import com.oneone.upms.api.permission.PermissionApi;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import java.util.List;
/**
* 基于部门的数据权限 AutoConfiguration
*
* @author 芋道源码
*/
@AutoConfiguration
@ConditionalOnBean(value = DeptDataPermissionRuleCustomizer.class)
public class DeptDataPermissionAutoConfiguration {
@Bean
public DeptDataPermissionRule deptDataPermissionRule(PermissionApi permissionApi,
List<DeptDataPermissionRuleCustomizer> customizers) {
// Cloud 专属逻辑:优先使用本地的 PermissionApi 实现类,而不是 Feign 调用
try {
PermissionApi permissionApiImpl = SpringUtil.getBean("permissionApiImpl", PermissionApi.class);
if (permissionApiImpl != null) {
permissionApi = permissionApiImpl;
}
} catch (Exception ignored) {}
// 创建 DeptDataPermissionRule 对象
DeptDataPermissionRule rule = new DeptDataPermissionRule(permissionApi);
// 补全表配置
customizers.forEach(customizer -> customizer.customize(rule));
return rule;
}
}
@@ -0,0 +1,204 @@
package com.oneone.common.biz.datapermission.rule.dept;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.oneone.common.base.LocalUser;
import com.oneone.common.mybatis.datapermission.core.rule.DataPermissionRule;
import com.oneone.common.mybatis.entity.BaseDO;
import com.oneone.common.mybatis.util.MyBatisUtils;
import com.oneone.common.util.JsonUtils;
import com.oneone.common.util.collection.CollectionUtils;
import com.oneone.common.web.util.UserContext;
import com.oneone.upms.api.enums.UserTypeEnum;
import com.oneone.upms.api.permission.PermissionApi;
import com.oneone.upms.api.permission.dto.DeptDataPermissionRespDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* 基于部门的 {@link DataPermissionRule} 数据权限规则实现
*
* 注意,使用 DeptDataPermissionRule 时,需要保证表中有 dept_id 部门编号的字段,可自定义。
*
* 实际业务场景下,会存在一个经典的问题?当用户修改部门时,冗余的 dept_id 是否需要修改?
* 1. 一般情况下,dept_id 不进行修改,则会导致用户看不到之前的数据。【采用该方案】
* 2. 部分情况下,希望该用户还是能看到之前的数据,则有两种方式解决:【需要你改造该 DeptDataPermissionRule 的实现代码】
* 1)编写洗数据的脚本,将 dept_id 修改成新部门的编号;【建议】
* 最终过滤条件是 WHERE dept_id = ?
* 2)洗数据的话,可能涉及的数据量较大,也可以采用 user_id 进行过滤的方式,此时需要获取到 dept_id 对应的所有 user_id 用户编号;
* 最终过滤条件是 WHERE user_id IN (?, ?, ? ...)
* 3)想要保证原 dept_id 和 user_id 都可以看的到,此时使用 dept_id 和 user_id 一起过滤;
* 最终过滤条件是 WHERE dept_id = ? OR user_id IN (?, ?, ? ...)
*
*/
@AllArgsConstructor
@Slf4j
public class DeptDataPermissionRule implements DataPermissionRule {
/**
* LoginUser 的 Context 缓存 Key
*/
protected static final String CONTEXT_KEY = DeptDataPermissionRule.class.getSimpleName();
private static final String DEPT_COLUMN_NAME = "dept_id";
private static final String USER_COLUMN_NAME = "user_id";
static final Expression EXPRESSION_NULL = new NullValue();
private final PermissionApi permissionApi;
/**
* 基于部门的表字段配置
* 一般情况下,每个表的部门编号字段是 dept_id,通过该配置自定义。
*
* key:表名
* value:字段名
*/
private final Map<String, String> deptColumns = new HashMap<>();
/**
* 基于用户的表字段配置
* 一般情况下,每个表的部门编号字段是 dept_id,通过该配置自定义。
*
* key:表名
* value:字段名
*/
private final Map<String, String> userColumns = new HashMap<>();
/**
* 所有表名,是 {@link #deptColumns} 和 {@link #userColumns} 的合集
*/
private final Set<String> TABLE_NAMES = new HashSet<>();
@Override
public Set<String> getTableNames() {
return TABLE_NAMES;
}
@Override
public Expression getExpression(String tableName, Alias tableAlias) {
// 只有有登陆用户的情况下,才进行数据权限的处理
LocalUser localUser = UserContext.getUser();
if (localUser == null) {
return null;
}
// 只有管理员类型的用户,才进行数据权限的处理
if (ObjectUtil.notEqual(localUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
return null;
}
// 获得数据权限
DeptDataPermissionRespDTO deptDataPermission = localUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
// 从上下文中拿不到,则调用逻辑进行获取
if (deptDataPermission == null) {
deptDataPermission = permissionApi.getDeptDataPermission(localUser.getUserId()).getCheckedData();
if (deptDataPermission == null) {
log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJSONString(localUser));
throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
localUser.getUserId(), tableName, tableAlias.getName()));
}
// 添加到上下文中,避免重复计算
localUser.setContext(CONTEXT_KEY, deptDataPermission);
}
// 情况一,如果是 ALL 可查看全部,则无需拼接条件
if (deptDataPermission.getAll()) {
return null;
}
// 情况二,即不能查看部门,又不能查看自己,则说明 100% 无权限
if (CollUtil.isEmpty(deptDataPermission.getDeptIds())
&& Boolean.FALSE.equals(deptDataPermission.getSelf())) {
return new EqualsTo(null, null); // WHERE null = null,可以保证返回的数据为空
}
// 情况三,拼接 Dept 和 User 的条件,最后组合
Expression deptExpression = buildDeptExpression(tableName,tableAlias, deptDataPermission.getDeptIds());
Expression userExpression = buildUserExpression(tableName, tableAlias, deptDataPermission.getSelf(), localUser.getUserId());
if (deptExpression == null && userExpression == null) {
// TODO 芋艿:获得不到条件的时候,暂时不抛出异常,而是不返回数据
log.warn("[getExpression][LoginUser({}) Table({}/{}) DeptDataPermission({}) 构建的条件为空]",
JsonUtils.toJSONString(localUser), tableName, tableAlias, JsonUtils.toJSONString(deptDataPermission));
// throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 构建的条件为空",
// loginUser.getId(), tableName, tableAlias.getName()));
return EXPRESSION_NULL;
}
if (deptExpression == null) {
return userExpression;
}
if (userExpression == null) {
return deptExpression;
}
// 目前,如果有指定部门 + 可查看自己,采用 OR 条件。即,WHERE (dept_id IN ? OR user_id = ?)
return new Parenthesis(new OrExpression(deptExpression, userExpression));
}
private Expression buildDeptExpression(String tableName, Alias tableAlias, Set<Long> deptIds) {
// 如果不存在配置,则无需作为条件
String columnName = deptColumns.get(tableName);
if (StrUtil.isEmpty(columnName)) {
return null;
}
// 如果为空,则无条件
if (CollUtil.isEmpty(deptIds)) {
return null;
}
// 拼接条件
return new InExpression(MyBatisUtils.buildColumn(tableName, tableAlias, columnName),
new ExpressionList(CollectionUtils.convertList(deptIds, LongValue::new)));
}
private Expression buildUserExpression(String tableName, Alias tableAlias, Boolean self, Long userId) {
// 如果不查看自己,则无需作为条件
if (Boolean.FALSE.equals(self)) {
return null;
}
String columnName = userColumns.get(tableName);
if (StrUtil.isEmpty(columnName)) {
return null;
}
// 拼接条件
return new EqualsTo(MyBatisUtils.buildColumn(tableName, tableAlias, columnName), new LongValue(userId));
}
// ==================== 添加配置 ====================
public void addDeptColumn(Class<? extends BaseDO> entityClass) {
addDeptColumn(entityClass, DEPT_COLUMN_NAME);
}
public void addDeptColumn(Class<? extends BaseDO> entityClass, String columnName) {
String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
addDeptColumn(tableName, columnName);
}
public void addDeptColumn(String tableName, String columnName) {
deptColumns.put(tableName, columnName);
TABLE_NAMES.add(tableName);
}
public void addUserColumn(Class<? extends BaseDO> entityClass) {
addUserColumn(entityClass, USER_COLUMN_NAME);
}
public void addUserColumn(Class<? extends BaseDO> entityClass, String columnName) {
String tableName = TableInfoHelper.getTableInfo(entityClass).getTableName();
addUserColumn(tableName, columnName);
}
public void addUserColumn(String tableName, String columnName) {
userColumns.put(tableName, columnName);
TABLE_NAMES.add(tableName);
}
}
@@ -0,0 +1,20 @@
package com.oneone.common.biz.datapermission.rule.dept;
/**
* {@link DeptDataPermissionRule} 的自定义配置接口
*
*
*/
@FunctionalInterface
public interface DeptDataPermissionRuleCustomizer {
/**
* 自定义该权限规则
* 1. 调用 {@link DeptDataPermissionRule#addDeptColumn(Class, String)} 方法,配置基于 dept_id 的过滤规则
* 2. 调用 {@link DeptDataPermissionRule#addUserColumn(Class, String)} 方法,配置基于 user_id 的过滤规则
*
* @param rule 权限规则
*/
void customize(DeptDataPermissionRule rule);
}
@@ -0,0 +1,24 @@
package com.oneone.common.biz.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author mice
* @version 1.0
* @date 2022/2/23 15:58
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "通用奖励" )
public class ActiveReward {
@Schema(description = "奖励类型" )
private Integer type;
@Schema(description = "奖励id" )
private Integer propId;
@Schema(description = "奖励数量" )
private Integer num;
}
@@ -0,0 +1,61 @@
package com.oneone.common.biz.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
/**
* @author mice
* @version 1.0
* @desc 虚拟店铺商品
* @date 2023-04-27 14:41:26
*/
@Data
@Schema(description = "虚拟店铺商品" )
@NoArgsConstructor
@AllArgsConstructor
public class BaseItem {
private static final long serialVersionUID = 1L;
@Schema(description = "" )
private Long id;
/**
* 模型编码
*/
@Schema(description = "模型编码" )
private Integer modelCode;
@Schema(description = "物品类型" )
private Integer itemType;
/**
* 物品id
*/
@Schema(description = "物品id" )
private Integer itemId;
/**
* 商品名称
*/
@Schema(description = "商品名称" )
private String itemName;
/**
* 描述
*/
@Schema(description = "描述" )
private String remark;
@Schema(description = "价格表" )
private Map<String, ItemPrice> priceMap;
@Schema(description = "放置点位" )
private Integer locationCode;
@Schema(description = "放置点位模型编码" )
private Integer locationModelCode;
}
@@ -0,0 +1,40 @@
package com.oneone.common.biz.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author mice
* @version 1.0
* @date 2023-02-10 17:40
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaseUpdateItemParam implements java.io.Serializable {
private final static long serialVersionUID = 1L;
@Schema(description = "用户id" )
protected Long memberId;
@Schema(description = "物品id" )
protected Integer itemId;
@Schema(description = "来源" )
protected String origin;
@Schema(description = "来源序列号" )
protected String originSn;
@Schema(description = "价格" )
private BigDecimal price;
@Schema(description = "币种" )
private String currency;
public BaseUpdateItemParam(Long memberId, Integer itemId, String origin, String originSn) {
this.memberId = memberId;
this.itemId = itemId;
this.origin = origin;
this.originSn = originSn;
}
}
@@ -0,0 +1,29 @@
package com.oneone.common.biz.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author mice
* @version 1.0
* @date 2022/2/23 15:58
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "通用奖励")
public class CommonReward {
@Schema(description = "奖励类型")
private Integer rewardType;
@Schema(description = "奖励id")
private Long rewardId;
@Schema(description = "奖励数量")
private BigDecimal rewardValue;
@Schema(description = "图片url")
private String rewardPicUrl;
}
@@ -0,0 +1,47 @@
package com.oneone.common.biz.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author mice
* @version 1.0
* @date 2023-02-08 15:55
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class ItemPrice implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 币种
*/
@Schema(description = "币种")
@JsonIgnore
private String currency;
/**
* 原始价格
*/
@Schema(description = "原始价格")
private BigDecimal originPrice;
/**
* 价格
*/
@Schema(description = "价格")
private BigDecimal price;
/**
* 折扣
*/
@Schema(description = "折扣")
private BigDecimal discount;
}
@@ -0,0 +1,10 @@
package com.oneone.common.biz.domain;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ItemPriceDTO extends ItemPrice{
private Long relationshipId;
}
@@ -0,0 +1,40 @@
package com.oneone.common.biz.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author shi_chengcai
* @version 1.0
* @desc
* @date 2023/5/8 14:54
*/
@NoArgsConstructor
@AllArgsConstructor
@Data
public class SceneLocationConfig implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 物品类型
*/
@Schema(description = "物品类型")
private Integer itemType;
/**
* 点位code
*/
@Schema(description = "点位code")
private Integer locationCode;
/**
* 点位模型code
*/
@Schema(description = "点位模型code")
private Integer locationModelCode;
}
@@ -0,0 +1,37 @@
package com.oneone.common.biz.enums;
import lombok.Getter;
/**
* APP
*
* @author oneone
* @date 2021/10/4
*/
@Getter
public enum AppNameEnum {
OMS("oms", "订单服务"),
CMS("cms", "藏品服务"),
UMS("ums", "用户服务"),
BOOKSHOP("bookshop", "书店服务");
private final String code;
private final String name;
AppNameEnum(String value, String name) {
this.code = value;
this.name = name;
}
public static AppNameEnum getByCode(String code) {
for (AppNameEnum item : values()) {
if (item.getCode().equals(code)) {
return item;
}
}
return null;
}
}
@@ -0,0 +1,50 @@
package com.oneone.common.biz.enums;
import lombok.Getter;
import lombok.Setter;
/**
* @author oneone
* @date 2021-02-17
*/
@Getter
public enum BusinessTypeEnum {
USER("user", 100),
VS_STORE("vs_store_balance", 110),
MEMBER("member", 200),
ORDER_SN("order_sn", 300),
CONSIGNMENT_ORDER("consignment_order", 310),
WAYBILL_ORDER("waybill_order", 320),
ORDER_TRANSACTION_SN("order_ts_sn", 400),
SYNTHETIC_ORDER_SN("synthetic_order_sn", 500),
COLLECTION_AIRDROP_SN("collection_airdrop_sn", 600),
TRANSFER_SN("transfer_sn", 700),
MALL_SN("mall_sn", 800),
CLUB_MALL_SN("club_mall_sn", 810),
QUIZ("quiz", 820),
BIG_WHEEL("big_wheel", 900),
;
private final String code;
private final Integer value;
BusinessTypeEnum(String code, Integer value) {
this.code = code;
this.value = value;
}
public static BusinessTypeEnum getValue(String code) {
BusinessTypeEnum businessTypeEnum=null;
for (BusinessTypeEnum value : values()) {
if (value.getCode().equals(code)) {
businessTypeEnum =value;
continue;
}
}
return businessTypeEnum;
}
}
@@ -0,0 +1,47 @@
package com.oneone.common.biz.enums;
import com.oneone.common.result.BaseEnum;
import lombok.AllArgsConstructor;
/**
* @author mice
* @version 1.0
* @date 2022-06-21 21:58
*/
@AllArgsConstructor
public enum OriginEnum implements BaseEnum {
SYS_DEFAULT("SYS_DEFAULT", "系统默认"),
ORDER("ORDER", "订单"),
MESSAGE("MESSAGE", "消息"),
ACTIVE_USE("ACTIVE_USE", "分身活动使用"),
ACTIVE_RETURN("ACTIVE_RETURN", "分身活动返还"),
TREASURE("TREASURE", "宝藏"),
REGISTER_REWARD("REGISTER_REWARD", "注册有礼"),
PHOTO_CLOCK("PHOTO_CLOCK", "打卡活动"),
INJECT_METEORITE("INJECT_METEORITE", "星能投放"),
GAME_RECORD_BREAK("GAME_RECORD_BREAK", "打破记录"),
GAME_RACING_ENCOURAGE("GAME_RACING_ENCOURAGE", "AI赛车助威"),
RACING_ENCOURAGE_AWARD("RACING_ENCOURAGE_AWARD", "AI赛车助威奖励"),
RACING_EXPEND("RACING_EXPEND", "赛车消耗"),
AI_CREATE("AI_CREATE", "AI创作"),
NFC("NFC", "NFC"),
;
private final String code;
private final String msg;
@Override
public String getCode() {
return code;
}
@Override
public String getMsg() {
return msg;
}
}
@@ -0,0 +1,35 @@
package com.oneone.common.biz.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum RewardTypeEnum {
UNKNOWN(0, "未知"),
IMAGE(1, ""),
COUPONS(2, "优惠券"),
COLLECTION(3, "藏品"),
GOLD(4, "金币"),
PROP(5, "道具"),
GEM(6, "钻石"),
POINT(7, "点券"),
CLOTHING(8, "皮肤/角色"),
ARTWORK(9, "艺术品"),
BOOK(10, ""),
;
private final Integer code;
private final String text;
public static RewardTypeEnum getByCode(int code) {
for (RewardTypeEnum value : values()) {
if (value.code == code) {
return value;
}
}
return null;
}
}
@@ -0,0 +1,23 @@
package com.oneone.common.biz.logic.config;
import com.oneone.common.biz.logic.itemprice.mapper.ItemPriceMapper;
import com.oneone.common.biz.logic.itemprice.ItemPriceService;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author mice
* @version 1.0
* @date 2023-02-08 16:30
*/
@Configuration
@MapperScan("com.oneone.common.biz.logic.itemprice.mapper")
public class LogicConfiguration {
@Bean
public ItemPriceService itemPriceService(ItemPriceMapper itemPriceMapper){
return new ItemPriceService(itemPriceMapper);
}
}
@@ -0,0 +1,55 @@
package com.oneone.common.biz.logic.itemprice;
import com.oneone.common.biz.domain.ItemPrice;
import com.oneone.common.biz.domain.ItemPriceDTO;
import com.oneone.common.biz.logic.itemprice.mapper.ItemPriceMapper;
import com.oneone.common.util.BeanUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author mice
* @version 1.0
* @date 2023-02-08 16:22
*/
@Component
@RequiredArgsConstructor
public class ItemPriceService {
private final ItemPriceMapper itemPriceMapper;
public List<ItemPrice> getItemPrices(String tableName, Long relationshipId) {
return itemPriceMapper.selectItemPrices(tableName, relationshipId);
}
public ItemPrice getItemPrice(String tableName, Long relationshipId, String currency) {
return itemPriceMapper.selectItemPrice(tableName, relationshipId, currency);
}
public Map<String, ItemPrice> getItemPriceMap(String tableName, Long relationshipId) {
List<ItemPrice> itemPrices = itemPriceMapper.selectItemPrices(tableName, relationshipId);
if (CollectionUtils.isEmpty(itemPrices)) {
return Collections.EMPTY_MAP;
}
return itemPrices.stream().collect(Collectors.toMap(ItemPrice::getCurrency, ItemPrice -> ItemPrice));
}
public Map<Long, Map<String, ItemPrice>> getItemPriceMap(String tableName, List<Long> relationshipIds) {
List<ItemPriceDTO> itemPrices = itemPriceMapper.selectByRelationshipIds(tableName, relationshipIds);
if (CollectionUtils.isEmpty(itemPrices)) {
return Collections.EMPTY_MAP;
}
Map<Long, Map<String, ItemPrice>> resultMap = new HashMap<>();
for (ItemPriceDTO itemPriceDTO : itemPrices) {
Map<String, ItemPrice> itemPriceMap = resultMap.computeIfAbsent(itemPriceDTO.getRelationshipId(), k -> new HashMap<>());
itemPriceMap.put(itemPriceDTO.getCurrency(), BeanUtil.copy(itemPriceDTO, ItemPrice.class));
}
return resultMap;
}
}
@@ -0,0 +1,48 @@
package com.oneone.common.biz.logic.itemprice.mapper;
import com.oneone.common.biz.domain.ItemPrice;
import com.oneone.common.biz.domain.ItemPriceDTO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author mice
* @version 1.0
* @date 2023-02-08 16:15
*/
@Mapper
public interface ItemPriceMapper {
/**
* 通过数据库查询物品价格
* @param tableName
* @param relationshipId
* @return
*/
@Select("select currency,origin_price,price,discount from ${tableName} where relationship_id = #{relationshipId}")
List<ItemPrice> selectItemPrices(@Param("tableName")String tableName, @Param("relationshipId") Long relationshipId);
/**
* 通过数据库查询物品价格
* @param tableName
* @param relationshipId
* @param currency
* @return
*/
@Select("select currency,origin_price,price,discount from ${tableName} where relationship_id = #{relationshipId} and currency = #{currency}")
ItemPrice selectItemPrice(@Param("tableName")String tableName, @Param("relationshipId") Long relationshipId,@Param("currency")String currency);
@Select( "<script> "+
"select relationship_id,currency,origin_price,price,discount from ${tableName} where " +
" relationship_id in" +
"<foreach collection='relationshipIds' item='relationshipId' open='(' separator=',' close=')'>"+
" #{relationshipId} " +
"</foreach> " +
"</script>"
)
List<ItemPriceDTO> selectByRelationshipIds(@Param("tableName") String tableName, @Param("relationshipIds") List<Long> relationshipIds);
}
@@ -0,0 +1,51 @@
package com.oneone.common.biz.utils;
import cn.hutool.core.util.RandomUtil;
import com.oneone.common.biz.enums.BusinessTypeEnum;
import com.oneone.common.constant.RedisConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
@Component
@Slf4j
public class BusinessNoGenerator {
@Autowired
private RedisTemplate redisTemplate;
@Value("${spring.profiles.active}")
private String env;
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
/**
* @param businessType 业务类型枚举
* @param digit 业务序号位数
* @return
*/
public String generate(BusinessTypeEnum businessType, Integer digit) {
String date = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
String key = RedisConstants.BUSINESS_NO_PREFIX + date + ":" + businessType.getCode();
Long increment = redisTemplate.opsForValue().increment(key, RandomUtil.randomInt(1,10));
String no = businessType.getValue() + date + String.format("%0" + digit + "d", increment);
if (!"prod".equals(env)){
return "t"+no;
}else {
return no;
}
}
public String generate(BusinessTypeEnum businessType) {
Integer defaultDigit = 7;
return generate(businessType, defaultDigit);
}
}
@@ -0,0 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.oneone.common.biz.utils.BusinessNoGenerator,\
com.oneone.common.biz.logic.config.LogicConfiguration,\
com.oneone.common.biz.datapermission.config.DataPermissionAutoConfiguration,\
com.oneone.common.biz.datapermission.config.DeptDataPermissionAutoConfiguration