Initial commit
This commit is contained in:
@@ -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>
|
||||
+43
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+204
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -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;
|
||||
}
|
||||
+40
@@ -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;
|
||||
}
|
||||
+40
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -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;
|
||||
}
|
||||
}
|
||||
+35
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -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;
|
||||
}
|
||||
}
|
||||
+48
@@ -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);
|
||||
}
|
||||
+51
@@ -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
|
||||
Reference in New Issue
Block a user