This commit is contained in:
ran.shang
2025-06-11 09:42:13 +08:00
commit 7e38b8d971
1935 changed files with 132836 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
package com.newyetai.component.action.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 操作记录
* @author sr on 2022-02-18
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ActionField {
String alias() default "";
String dictCode() default "";
}

View File

@@ -0,0 +1,17 @@
package com.newyetai.component.action.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 操作记录对象
* @author sr on 2022-02-18
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ActionModel {
String type();
}

View File

@@ -0,0 +1,9 @@
package com.newyetai.component.action.constant;
/**
* @author sr on 2022-02-18
*/
public interface ActionConstants {
}

View File

@@ -0,0 +1,20 @@
package com.newyetai.component.action.constant;
/**
* 操作类型枚举
* @author sr on 2022-02-21
*/
public enum ActionTypeEnum {
;
ActionTypeEnum(String type) {
this.type = type;
}
private String type;
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,43 @@
package com.newyetai.component.action.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.newyetai.common.AlitaResult;
import com.newyetai.component.action.dto.ActionDTO;
import com.newyetai.component.action.dto.ActionQueryDTO;
import com.newyetai.component.action.service.ActionService;
import com.newyetai.tkmybatis.pojo.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.List;
/**
* @author sr on 2022-02-18
*/
@RestController
@RequestMapping("action")
@Api(tags = "操作记录")
public class ActionController {
@Autowired
private ActionService actionService;
@GetMapping("/page")
@ApiOperation("分页查询")
public AlitaResult<Page<ActionDTO>> page(ActionQueryDTO actionQueryDTO){
actionService.page(actionQueryDTO);
return AlitaResult.success(actionQueryDTO.getPageResult());
}
@GetMapping("/list")
@ApiOperation("分页查询")
public AlitaResult<List<ActionDTO>> list(ActionQueryDTO actionQueryDTO){
return AlitaResult.success(actionService.list(actionQueryDTO));
}
}

View File

@@ -0,0 +1,42 @@
package com.newyetai.component.action.controller;
import com.newyetai.common.AlitaResult;
import com.newyetai.component.action.dto.ActionDetailDTO;
import com.newyetai.component.action.dto.ActionDetailQueryDTO;
import com.newyetai.component.action.service.ActionDetailService;
import com.newyetai.tkmybatis.pojo.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author sr on 2022-02-18
*/
@RestController
@RequestMapping("action_detail")
@Api(tags = "操作记录明细")
public class ActionDetailController {
@Autowired
private ActionDetailService actionDetailService;
@GetMapping("/page")
@ApiOperation("分页查询")
public AlitaResult<Page<ActionDetailDTO>> page(ActionDetailQueryDTO actionDetailQueryDTO){
actionDetailService.page(actionDetailQueryDTO);
return AlitaResult.success(actionDetailQueryDTO.getPageResult());
}
@GetMapping("/list")
@ApiOperation("根据关联业务id查询日志")
public AlitaResult<List<ActionDetailDTO>> list(ActionDetailQueryDTO actionDetailQueryDTO){
return AlitaResult.success(actionDetailService.list(actionDetailQueryDTO));
}
}

View File

@@ -0,0 +1,28 @@
package com.newyetai.component.action.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.newyetai.component.action.dto.ActionDetailDTO;
import com.newyetai.component.action.dto.ActionDetailQueryDTO;
import com.newyetai.component.action.entity.ActionDetail;
import com.newyetai.tkmybatis.mybatis.MyMapper;
/**
* 操作记录明细
*
* @author sr on 2022-02-18
*/
public interface ActionDetailMapper extends MyMapper<ActionDetail> {
/**
* 查询
*
* @param actionDetailQueryDTO
* @return
* @author sr on 2022-02-18
*/
List<ActionDetailDTO> listActionDetailDTO(@Param("param") ActionDetailQueryDTO actionDetailQueryDTO);
}

View File

@@ -0,0 +1,28 @@
package com.newyetai.component.action.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.newyetai.component.action.dto.ActionDTO;
import com.newyetai.component.action.dto.ActionQueryDTO;
import com.newyetai.component.action.entity.Action;
import com.newyetai.tkmybatis.mybatis.MyMapper;
/**
* 操作记录
*
* @author sr on 2022-02-18
*/
public interface ActionMapper extends MyMapper<Action> {
/**
* 查询
*
* @param actionQueryDTO
* @return
* @author sr on 2022-02-18
*/
List<ActionDTO> listActionDTO(@Param("param") ActionQueryDTO actionQueryDTO);
}

View File

@@ -0,0 +1,42 @@
package com.newyetai.component.action.dto;
import java.io.Serializable;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.newyetai.common.dto.BaseOperateDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2022-02-18
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "操作记录创建")
public class ActionCreateDTO extends BaseOperateDTO implements Serializable{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("关联类型")
@NotBlank(message = "关联类型不能为空")
private String unionType;
@ApiModelProperty("关联id")
@NotNull(message = "关联id不能为空")
private Long unionId;
@ApiModelProperty("明细")
@Valid
private List<ActionDetailCreateDTO> detailDtos;
}

View File

@@ -0,0 +1,37 @@
package com.newyetai.component.action.dto;
import com.newyetai.common.dto.BaseDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import java.util.List;
/**
* @author sr on 2022-02-18
*/
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@ApiModel(description = "操作记录")
public class ActionDTO extends BaseDTO {
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("关联类型")
private String unionType;
@ApiModelProperty("关联id")
private Long unionId;
@ApiModelProperty("处理人")
private String createName;
@ApiModelProperty("子节点")
private List<ActionDetailDTO> childNode;
}

View File

@@ -0,0 +1,46 @@
package com.newyetai.component.action.dto;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.newyetai.common.validation.Update;
import com.newyetai.common.dto.BaseOperateDTO;
/**
* @author sr on 2022-02-18
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "操作记录明细创建")
public class ActionDetailCreateDTO extends BaseOperateDTO implements Serializable{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("属性")
@NotBlank(message = "属性不能为空")
private String field;
@ApiModelProperty("属性别名")
private String fieldAlias;
@ApiModelProperty("属性字典编码")
private String fieldDictCode;
@ApiModelProperty("旧值")
private String oldValue;
@ApiModelProperty("新值")
private String newValue;
@ApiModelProperty("差异")
private String diff;
}

View File

@@ -0,0 +1,43 @@
package com.newyetai.component.action.dto;
import com.newyetai.common.dto.BaseDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* @author sr on 2022-02-18
*/
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@ApiModel(description = "操作记录明细")
public class ActionDetailDTO extends BaseDTO {
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("操作记录id")
private Long actionId;
@ApiModelProperty("属性")
private String field;
@ApiModelProperty("属性别名")
private String fieldAlias;
@ApiModelProperty("属性字典编码")
private String fieldDictCode;
@ApiModelProperty("旧值")
private String oldValue;
@ApiModelProperty("新值")
private String newValue;
@ApiModelProperty("差异")
private String diff;
}

View File

@@ -0,0 +1,33 @@
package com.newyetai.component.action.dto;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import com.newyetai.common.dto.PageQueryDTO;
/**
* @author sr on 2022-02-18
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "操作记录明细查询条件")
public class ActionDetailQueryDTO extends PageQueryDTO<ActionDetailDTO> implements Serializable{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("操作记录id")
private Long actionId;
}

View File

@@ -0,0 +1,33 @@
package com.newyetai.component.action.dto;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import com.newyetai.common.dto.PageQueryDTO;
/**
* @author sr on 2022-02-18
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "操作记录查询条件")
public class ActionQueryDTO extends PageQueryDTO<ActionDTO> implements Serializable{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("关联业务id")
private Long unionId;
}

View File

@@ -0,0 +1,32 @@
package com.newyetai.component.action.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* 操作记录
*
* @author sr on 2022-02-18
*/
@TableName("uc_action")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
public class Action extends BaseEntity {
/** **/
private static final long serialVersionUID = 1L;
/** 关联类型 **/
private String unionType;
/** 关联id **/
private Long unionId;
}

View File

@@ -0,0 +1,41 @@
package com.newyetai.component.action.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* 操作记录明细
*
* @author sr on 2022-02-18
*/
@TableName("uc_action_detail")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
public class ActionDetail extends BaseEntity {
/** **/
private static final long serialVersionUID = 1L;
/** 操作记录id **/
private Long actionId;
/** 属性 **/
private String field;
/** 属性别名 **/
private String fieldAlias;
/** 属性字典编码 **/
private String fieldDictCode;
/** 旧值 **/
private String oldValue;
/** 新值 **/
private String newValue;
/** 差异 **/
private String diff;
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newyetai.component.action.dao.ActionDetailMapper">
<select id="listActionDetailDTO" resultType="com.newyetai.component.action.dto.ActionDetailDTO">
select
*
from uc_action_detail
where
deleted = 0
<if test="param.id != null">
and id = #{param.id}
</if>
<if test="param.actionId != null">
and action_id = #{param.actionId}
</if>
order by create_time asc
</select>
</mapper>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newyetai.component.action.dao.ActionMapper">
<select id="listActionDTO" resultType="com.newyetai.component.action.dto.ActionDTO">
select t1.*,t2.nickname as createName
from uc_action t1 left join uc_user t2 on t1.create_by = t2.id and t2.deleted = 0
where
t1.deleted = 0
<if test="param.id != null">
and id = #{param.id}
</if>
<if test="param.unionId != null">
and t1.union_id = #{param.unionId}
</if>
order by t1.create_time asc
</select>
</mapper>

View File

@@ -0,0 +1,37 @@
package com.newyetai.component.action.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.newyetai.component.action.dto.ActionDetailCreateDTO;
import com.newyetai.component.action.dto.ActionDetailDTO;
import com.newyetai.component.action.entity.ActionDetail;
/**
* @author sr on 2022-02-18
*/
@Mapper
public interface ActionDetailMapMapper {
ActionDetailMapMapper INSTANCE =
Mappers.getMapper(ActionDetailMapMapper.class);
/**
* dto to entity
*
* @param actionDetailDto
* @return
* @author sr on 2022-02-18
*/
ActionDetail toEntity(
ActionDetailDTO actionDetailDto);
/**
* @param ActionDetailCreateDTO
* @return
* @author sr on 2022-02-18
*/
ActionDetail toEntity(ActionDetailCreateDTO ActionDetailCreateDTO);
}

View File

@@ -0,0 +1,37 @@
package com.newyetai.component.action.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.newyetai.component.action.dto.ActionCreateDTO;
import com.newyetai.component.action.dto.ActionDTO;
import com.newyetai.component.action.entity.Action;
/**
* @author sr on 2022-02-18
*/
@Mapper
public interface ActionMapMapper {
ActionMapMapper INSTANCE =
Mappers.getMapper(ActionMapMapper.class);
/**
* dto to entity
*
* @param actionDto
* @return
* @author sr on 2022-02-18
*/
Action toEntity(
ActionDTO actionDto);
/**
* @param actionCreateDTO
* @return
* @author sr on 2022-02-18
*/
Action toEntity(ActionCreateDTO actionCreateDTO);
}

View File

@@ -0,0 +1,42 @@
package com.newyetai.component.action.service;
import java.util.List;
import com.newyetai.component.action.dto.ActionDetailDTO;
import com.newyetai.component.action.dto.ActionDetailQueryDTO;
/**
* 操作记录明细
*
* @author sr on 2022-02-18
*/
public interface ActionDetailService {
/**
* 查询
*
* @param actionDetailQueryDTO
* @return
* @author sr on 2022-02-18
*/
List<ActionDetailDTO> list(ActionDetailQueryDTO actionDetailQueryDTO);
/**
* 分页查询
*
* @param actionDetailQueryDTO
* @return
* @author sr on 2022-02-18
*/
void page(ActionDetailQueryDTO actionDetailQueryDTO);
/**
* 单个查询
*
* @param actionDetailQueryDTO
* @return
* @author sr on 2022-02-18
*/
ActionDetailDTO find(ActionDetailQueryDTO actionDetailQueryDTO);
}

View File

@@ -0,0 +1,55 @@
package com.newyetai.component.action.service;
import java.util.List;
import org.springframework.validation.annotation.Validated;
import com.newyetai.component.action.dto.ActionCreateDTO;
import com.newyetai.component.action.dto.ActionDTO;
import com.newyetai.component.action.dto.ActionQueryDTO;
/**
* 操作记录
*
* @author sr on 2022-02-18
*/
public interface ActionService {
/**
* 新增
*
* @param actionOperateDTO
* @return
* @author sr on 2022-02-18
*/
Long create(@Validated ActionCreateDTO actionOperateDTO);
/**
* 查询
*
* @param actionQueryDTO
* @return
* @author sr on 2022-02-18
*/
List<ActionDTO> list(ActionQueryDTO actionQueryDTO);
/**
* 分页查询
*
* @param actionQueryDTO
* @return
* @author sr on 2022-02-18
*/
void page(ActionQueryDTO actionQueryDTO);
/**
* 单个查询
*
* @param actionQueryDTO
* @return
* @author sr on 2022-02-18
*/
ActionDTO find(ActionQueryDTO actionQueryDTO);
}

View File

@@ -0,0 +1,40 @@
package com.newyetai.component.action.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.newyetai.common.util.ListUtil;
import com.newyetai.component.action.dao.ActionDetailMapper;
import com.newyetai.component.action.dto.ActionDetailDTO;
import com.newyetai.component.action.dto.ActionDetailQueryDTO;
import com.newyetai.component.action.service.ActionDetailService;
/**
* @author sr on 2022-02-18
*/
@Service
public class ActionDetailServiceImpl implements ActionDetailService {
@Autowired
private ActionDetailMapper actionDetailMapper;
@Override
public List<ActionDetailDTO> list(ActionDetailQueryDTO actionDetailQueryDTO) {
actionDetailQueryDTO.disablePage();
return actionDetailMapper.listActionDetailDTO(actionDetailQueryDTO);
}
@Override
public void page(ActionDetailQueryDTO actionDetailQueryDTO) {
actionDetailMapper.listActionDetailDTO(actionDetailQueryDTO);
}
@Override
public ActionDetailDTO find(ActionDetailQueryDTO actionDetailQueryDTO) {
List<ActionDetailDTO> actionDetailDTOs = this.list(actionDetailQueryDTO);
return actionDetailDTOs.isEmpty() ? null : ListUtil.first(actionDetailDTOs);
}
}

View File

@@ -0,0 +1,101 @@
package com.newyetai.component.action.service.impl;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.newyetai.common.constant.CommonMqConstants;
import com.newyetai.common.util.ListUtil;
import com.newyetai.common.util.MockUtils;
import com.newyetai.component.action.dao.ActionDetailMapper;
import com.newyetai.component.action.dao.ActionMapper;
import com.newyetai.component.action.dto.ActionCreateDTO;
import com.newyetai.component.action.dto.ActionDTO;
import com.newyetai.component.action.dto.ActionDetailCreateDTO;
import com.newyetai.component.action.dto.ActionDetailQueryDTO;
import com.newyetai.component.action.dto.ActionQueryDTO;
import com.newyetai.component.action.entity.Action;
import com.newyetai.component.action.entity.ActionDetail;
import com.newyetai.component.action.mapstruct.ActionDetailMapMapper;
import com.newyetai.component.action.mapstruct.ActionMapMapper;
import com.newyetai.component.action.service.ActionService;
import com.newyetai.mq.consumer.handler.ITopicMqHandler;
import com.newyetai.mq.dto.TopicMqMessage;
/**
* @author sr on 2022-02-18
*/
@Service
public class ActionServiceImpl implements ActionService , ITopicMqHandler<ActionCreateDTO>{
@Autowired
private ActionMapper actionMapper;
@Autowired
private ActionDetailMapper actionDetailMapper;
@Override
@Transactional
public Long create(ActionCreateDTO actionCreateDTO) {
Action action = ActionMapMapper.INSTANCE.toEntity(actionCreateDTO);
actionMapper.saveEntity(action);
Long actionId = action.getId();
List<ActionDetailCreateDTO> detailCreateDtos = actionCreateDTO.getDetailDtos();
if (CollectionUtils.isEmpty(detailCreateDtos)) {
return actionId;
}
List<ActionDetail> details = detailCreateDtos.stream().map(dto -> {
ActionDetail actionDetail = ActionDetailMapMapper.INSTANCE.toEntity(dto);
actionDetail.setActionId(actionId);
return actionDetail;
}).collect(Collectors.toList());
actionDetailMapper.saveEntites(details);
return actionId;
}
@Override
public List<ActionDTO> list(ActionQueryDTO actionQueryDTO) {
actionQueryDTO.disablePage();
List<ActionDTO> dtoList = actionMapper.listActionDTO(actionQueryDTO);
dtoList.forEach(f ->{
f.setChildNode(actionDetailMapper.listActionDetailDTO(ActionDetailQueryDTO.builder().actionId(f.getId()).build()));
});
return dtoList;
}
@Override
public void page(ActionQueryDTO actionQueryDTO) {
actionMapper.listActionDTO(actionQueryDTO);
}
@Override
public ActionDTO find(ActionQueryDTO actionQueryDTO) {
List<ActionDTO> actionDTOs = this.list(actionQueryDTO);
return actionDTOs.isEmpty() ? null : ListUtil.first(actionDTOs);
}
@Override
public String getRoutingKey() {
return CommonMqConstants.ACTION_LOG;
}
@Override
public void onMessage(TopicMqMessage<ActionCreateDTO> message) {
Long userId = message.getOperateUserId();
if (userId != null) {
MockUtils.mockUser(userId, message.getOperateOrgId());
} else {
MockUtils.mockPlatUser();
}
((ActionService) AopContext.currentProxy()).create(message.getData());
}
}

View File

@@ -0,0 +1,110 @@
package com.newyetai.component.action.util;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
import com.newyetai.common.constant.CommonMqConstants;
import com.newyetai.common.util.StrUtils;
import com.newyetai.component.action.annotation.ActionField;
import com.newyetai.component.action.annotation.ActionModel;
import com.newyetai.component.action.dto.ActionCreateDTO;
import com.newyetai.component.action.dto.ActionDetailCreateDTO;
import com.newyetai.component.dict.util.DictUtils;
import com.newyetai.mq.util.MqSendUtils;
import com.newyetai.mybatisplus.util.MybatisPlusUtils;
import lombok.extern.slf4j.Slf4j;
/**
* @author sr on 2022-02-18
*/
@Slf4j
public class ActionUtils {
public static void diff(Long objId, Object oldObj, Object newObj) {
if (oldObj == null || newObj == null) {
log.info("记录对象不能为空");
return;
}
Class<?> objClass = oldObj.getClass();
if (objClass != newObj.getClass()) {
log.info("记录对象类型需一致");
return;
}
if (objId == null) {
log.info("记录id不能为空");
return;
}
try {
Field[] fields = objClass.getDeclaredFields();
List<ActionDetailCreateDTO> detailCreateDTOs = Lists.newArrayList();
for (Field field : fields) {
ActionField actionLog = field.getAnnotation(ActionField.class);
if (actionLog == null) {
continue;
}
field.setAccessible(true);
String fieldAlias = actionLog.alias();
String fieldName = field.getName();
try {
Object oldValue = MybatisPlusUtils.dealEnumField(field.get(oldObj));
Object newValue = MybatisPlusUtils.dealEnumField(field.get(newObj));
String oldValueStr = oldValue == null ? null : oldValue.toString();
String newValueStr = newValue == null ? null : newValue.toString();
if(StringUtils.isBlank(oldValueStr) && StringUtils.isBlank(newValueStr)){
continue;
}
String dictCode = actionLog.dictCode();
String diff = null;
if (StringUtils.isNotBlank(dictCode)) {
Map<String, String> dictNameMap = DictUtils.getCodeNameMap(dictCode);
diff = formatDiff(fieldAlias, MapUtils.getString(dictNameMap, oldValueStr, oldValueStr),
MapUtils.getString(dictNameMap, newValueStr, newValueStr));
} else {
dictCode = null;
diff = formatDiff(fieldAlias, oldValueStr, newValueStr);
}
ActionDetailCreateDTO detailCreateDTO = ActionDetailCreateDTO.builder()
.field(fieldName)
.fieldAlias(fieldAlias)
.fieldDictCode(dictCode)
.oldValue(oldValueStr)
.newValue(newValueStr)
.diff(diff)
.build();
detailCreateDTOs.add(detailCreateDTO);
} catch (IllegalArgumentException | IllegalAccessException e) {
log.info("获取记录对象属性失败", e);
return;
}
}
ActionModel actionModel = objClass.getAnnotation(ActionModel.class);
String unionType = null;
if (actionModel != null) {
unionType = actionModel.type();
}
unionType =
Optional.ofNullable(unionType)
.orElseGet(() -> StrUtils.toSnake(objClass.getSimpleName()));
ActionCreateDTO actionCreateDTO =
ActionCreateDTO.builder().unionType(unionType).unionId(objId).detailDtos(detailCreateDTOs)
.build();
MqSendUtils.send(CommonMqConstants.ACTION_LOG, actionCreateDTO);
} catch (Exception e) {
log.info("记录操作失败", e);
}
}
private static String formatDiff(String fieldAlias, String oldValueStr, String newValueStr) {
return String.join("", fieldAlias, ",旧值为\"", oldValueStr, "\",新值为\"", newValueStr, "\"");
}
}

View File

@@ -0,0 +1,29 @@
package com.newyetai.component.asyntasknotice.constant;
/**
* 异步任务流程状态
*
* @author sr on 2024-02-06
*/
public enum AsyncTaskFlowStatusEnum {
/** 开启 **/
START(1),
/** 结束 **/
END(2),
;
private Integer status;
AsyncTaskFlowStatusEnum(Integer status) {
this.status = status;
}
public Integer getStatus() {
return status;
}
}

View File

@@ -0,0 +1,30 @@
package com.newyetai.component.asyntasknotice.constant;
/**
* 异步任务通知状态
* @author sr on 2024-02-06
*/
public enum AsyncTaskNoticeStatusEnum {
/** 未读 **/
INIT(1),
/** 已读 **/
READ(2),
;
private Integer status;
AsyncTaskNoticeStatusEnum(Integer status) {
this.status = status;
}
public Integer getStatus() {
return status;
}
}

View File

@@ -0,0 +1,21 @@
package com.newyetai.component.asyntasknotice.constant;
/**
* 异步任务类型
* @author sr on 2024-02-06
*/
public enum AsyncTaskTypeEnum {
COMMON_IMPORT("common_import")
;
private String type;
AsyncTaskTypeEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,49 @@
package com.newyetai.component.asyntasknotice.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.newyetai.common.AlitaResult;
import com.newyetai.common.exception.util.Assert;
import com.newyetai.common.util.UserContextHolder;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO;
import com.newyetai.component.asyntasknotice.service.AsyncTaskNoticeService;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.tkmybatis.pojo.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/**
* @author sr on 2024-02-06
*/
@RestController
@RequestMapping("async_task_notice")
@Api(tags = "异步任务通知")
public class AsyncTaskNoticeController {
@Autowired
private AsyncTaskNoticeService asyncTaskNoticeService;
@GetMapping("/page")
@ApiOperation("分页查询")
public AlitaResult<Page<AsyncTaskNoticeDTO>> page(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO){
asyncTaskNoticeQueryDTO.setCreateBy(UserContextHolder.getExistLoginUserId());
asyncTaskNoticeService.page(asyncTaskNoticeQueryDTO);
return AlitaResult.success(asyncTaskNoticeQueryDTO.getPageResult());
}
@PostMapping("/read")
@ApiOperation("创建")
public AlitaResult<Integer> read(AsyncTaskNoticeReadDTO readDTO){
return AlitaResult.success(asyncTaskNoticeService.read(readDTO));
}
}

View File

@@ -0,0 +1,33 @@
package com.newyetai.component.asyntasknotice.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO;
import com.newyetai.component.asyntasknotice.entity.AsyncTaskNotice;
import com.newyetai.tkmybatis.mybatis.MyMapper;
/**
* 异步任务通知
*
* @author sr on 2024-02-06
*/
public interface AsyncTaskNoticeMapper extends MyMapper<AsyncTaskNotice> {
/**
* 查询
*
* @param asyncTaskNoticeQueryDTO
* @return
* @author sr on 2024-02-06
*/
List<AsyncTaskNoticeDTO> listAsyncTaskNoticeDTO(@Param("param") AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO);
int finish(@Param("param") AsyncTaskNoticeFinishDTO finishDTO);
int read(@Param("param") AsyncTaskNoticeReadDTO readDTO);
}

View File

@@ -0,0 +1,41 @@
package com.newyetai.component.asyntasknotice.dto;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.newyetai.common.dto.BaseOperateDTO;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2024-02-06
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "异步任务通知创建")
public class AsyncTaskNoticeCreateDTO extends BaseOperateDTO{
/** **/
private static final long serialVersionUID = 1L;
/** 关联类型:common_import等**/
@NotBlank(message = "关联类型不能为空")
private String unionType;
/** 关联id**/
@NotNull(message = "关联id不能为空")
private Long unionId;
/** 内容**/
@NotBlank(message = "内容不能为空")
private String content;
/** 业务状态**/
private String bizStatusStr;
/** 业务参数**/
private String bizParamData;
}

View File

@@ -0,0 +1,43 @@
package com.newyetai.component.asyntasknotice.dto;
import com.newyetai.common.dto.BaseDTO;
import com.newyetai.component.action.dto.ActionDetailDTO;
import com.newyetai.component.asyntasknotice.constant.AsyncTaskTypeEnum;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* @author sr on 2024-02-06
*/
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@ApiModel(description = "异步任务通知")
public class AsyncTaskNoticeDTO extends BaseDTO {
/** **/
private static final long serialVersionUID = 1L;
/** @see AsyncTaskTypeEnum 关联类型:common_import等**/
private String unionType;
/** 关联id**/
private Long unionId;
/** 内容**/
private String content;
/** 业务状态**/
private String bizStatusStr;
/** 业务参数**/
private String bizParamData;
/** 流程状态:1开启,2结束**/
private Integer flowStatus;
/** 通知状态:1未读,2已读**/
private Integer noticeStatus;
}

View File

@@ -0,0 +1,36 @@
package com.newyetai.component.asyntasknotice.dto;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.newyetai.common.dto.BaseOperateDTO;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2024-02-06
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "异步任务通知结束")
public class AsyncTaskNoticeFinishDTO extends BaseOperateDTO{
/** **/
private static final long serialVersionUID = 1L;
/** 关联类型:common_import等**/
@NotBlank(message = "关联类型不能为空")
private String unionType;
/** 关联id**/
@NotNull(message = "关联id不能为空")
private Long unionId;
/** 业务状态**/
private String bizStatusStr;
}

View File

@@ -0,0 +1,37 @@
package com.newyetai.component.asyntasknotice.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import com.newyetai.common.dto.PageQueryDTO;
/**
* @author sr on 2024-02-06
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "异步任务通知查询条件")
public class AsyncTaskNoticeQueryDTO extends PageQueryDTO<AsyncTaskNoticeDTO>{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("创建人")
private Long createBy;
/** 关联类型:common_import等**/
private String unionType;
/** 关联id**/
private Long unionId;
}

View File

@@ -0,0 +1,32 @@
package com.newyetai.component.asyntasknotice.dto;
import com.newyetai.common.dto.BaseOperateDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2024-02-06
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "异步任务通知-读取")
public class AsyncTaskNoticeReadDTO extends BaseOperateDTO{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
private Long id;
/** 关联类型:common_import等**/
private String unionType;
/** 关联id**/
private Long unionId;
}

View File

@@ -0,0 +1,43 @@
package com.newyetai.component.asyntasknotice.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* 异步任务通知
*
* @author sr on 2024-02-06
*/
@TableName("async_task_notice")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
public class AsyncTaskNotice extends BaseEntity {
/** **/
private static final long serialVersionUID = 1L;
/** 关联类型:common_import等**/
private String unionType;
/** 关联id**/
private Long unionId;
/** 内容**/
private String content;
/** 业务状态**/
private String bizStatusStr;
/** 业务参数**/
private String bizParamData;
/** 流程状态:1开启,2结束**/
private Integer flowStatus;
/** 通知状态:1未读,2已读**/
private Integer noticeStatus;
}

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newyetai.component.asyntasknotice.dao.AsyncTaskNoticeMapper">
<select id="listAsyncTaskNoticeDTO" resultType="com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO">
select
*
from async_task_notice
where
deleted = 0
<if test="param.id != null">
and id = #{param.id}
</if>
<if test="param.createBy != null">
and create_by = #{param.createBy}
</if>
<if test="param.unionType !=null and param.unionType != ''">
and union_type = #{param.unionType}
</if>
<if test="param.unionId !=null and param.unionId != ''">
and union_id = #{param.unionId}
</if>
</select>
<update id="finish">
update async_task_notice
set flow_status = 2,update_time = now(), update_by = #{param.operateUserId}
<if test="param.bizStatusStr !=null and param.bizStatusStr != ''">
,biz_status_str = #{param.bizStatusStr}
</if>
where
deleted = 0
and union_type = #{param.unionType}
and union_id = #{param.unionId}
and flow_status = 1
</update>
<update id="read">
update async_task_notice
set notice_status = 2,update_time = now(), update_by = #{param.operateUserId}
where
deleted = 0
and create_by = #{param.operateUserId}
and notice_status = 1
<if test="param.id != null">
and id = #{param.id}
</if>
<if test="param.unionType !=null and param.unionType != ''">
and union_type = #{param.unionType}
</if>
<if test="param.unionId !=null and param.unionId != ''">
and union_id = #{param.unionId}
</if>
</update>
</mapper>

View File

@@ -0,0 +1,36 @@
package com.newyetai.component.asyntasknotice.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO;
import com.newyetai.component.asyntasknotice.entity.AsyncTaskNotice;
/**
* @author sr on 2024-02-06
*/
@Mapper
public interface AsyncTaskNoticeMapMapper {
AsyncTaskNoticeMapMapper INSTANCE =
Mappers.getMapper(AsyncTaskNoticeMapMapper.class);
/**
* dto to entity
*
* @param asyncTaskNoticeDto
* @return
* @author sr on 2024-02-06
*/
AsyncTaskNotice toEntity(
AsyncTaskNoticeDTO asyncTaskNoticeDto);
/**
* @return
* @author sr on 2024-02-06
*/
AsyncTaskNotice toEntity(AsyncTaskNoticeCreateDTO createDTO);
}

View File

@@ -0,0 +1,87 @@
package com.newyetai.component.asyntasknotice.service;
import java.util.List;
import javax.validation.Valid;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO;
/**
* 异步任务通知
*
* @author sr on 2024-02-06
*/
public interface AsyncTaskNoticeService {
/**
* 创建
*
* @param createDTO
* @return
* @author sr on 2024-02-06
*/
Long create(@Valid AsyncTaskNoticeCreateDTO createDTO);
/**
* 结束
* @param finishDTO
* @author sr on 2024-02-06
*/
void finish(@Valid AsyncTaskNoticeFinishDTO finishDTO);
/**
* 读取
* @param readDTO
* @return
* @author sr on 2024-02-06
*/
Integer read(AsyncTaskNoticeReadDTO readDTO);
/**
* 删除
*
* @param id
* @author sr on 2024-02-06
*/
void remove(Long id);
/**
* 查询
*
* @param asyncTaskNoticeQueryDTO
* @return
* @author sr on 2024-02-06
*/
List<AsyncTaskNoticeDTO> list(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO);
/**
* 分页查询
*
* @param asyncTaskNoticeQueryDTO
* @return
* @author sr on 2024-02-06
*/
void page(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO);
/**
* 单个查询
*
* @param asyncTaskNoticeQueryDTO
* @return
* @author sr on 2024-02-06
*/
AsyncTaskNoticeDTO find(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO);
}

View File

@@ -0,0 +1,118 @@
package com.newyetai.component.asyntasknotice.service.impl;
import com.newyetai.component.notice.constant.NoticeFirstTypeEnum;
import com.newyetai.component.notice.dto.NoticeMsgDTO;
import com.newyetai.component.notice.service.AsyncNoticeHandler;
import com.newyetai.component.notice.util.NoticeUtils;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.newyetai.common.exception.util.Assert;
import com.newyetai.common.util.ListUtil;
import com.newyetai.common.util.UserContextHolder;
import com.newyetai.component.asyntasknotice.constant.AsyncTaskFlowStatusEnum;
import com.newyetai.component.asyntasknotice.constant.AsyncTaskNoticeStatusEnum;
import com.newyetai.component.asyntasknotice.dao.AsyncTaskNoticeMapper;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeQueryDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeReadDTO;
import com.newyetai.component.asyntasknotice.entity.AsyncTaskNotice;
import com.newyetai.component.asyntasknotice.mapstruct.AsyncTaskNoticeMapMapper;
import com.newyetai.component.asyntasknotice.service.AsyncTaskNoticeService;
import com.newyetai.component.asyntasknotice.util.AsyncTaskNoticeUtils;
import com.newyetai.frame.redis.aop.annotation.AutoUnLock;
import com.newyetai.frame.redis.dto.LockDTO;
import com.newyetai.frame.redis.redisson.RedissonUtils;
import com.newyetai.mq.util.MqSendUtils;
/**
* @author sr on 2024-02-06
*/
@Service
public class AsyncTaskNoticeServiceImpl implements AsyncTaskNoticeService {
private static final String LOCK_NAME = "asynctasknotice";
@Autowired
private AsyncTaskNoticeMapper asyncTaskNoticeMapper;
public static LockDTO getLockDTO(String unionType, Long unionId) {
Assert.notBlank(unionType, "关联类型不能为空");
Assert.notNull(unionId, "关联id不能为空");
return LockDTO.builder().methodName(LOCK_NAME).tryLockWaitTime(0L)
.arg(unionType)
.arg(unionId.toString())
.build();
}
@Override
@AutoUnLock
@Transactional
public Long create(AsyncTaskNoticeCreateDTO createDTO) {
String unionType = createDTO.getUnionType();
Long unionId = createDTO.getUnionId();
AsyncTaskNotice existNotice = AsyncTaskNotice.builder().unionId(unionId).unionId(unionId).build();
boolean exist = asyncTaskNoticeMapper.existsEntity(existNotice);
Assert.isTrue(!exist, "已存在相同关联类型数据");
LockDTO lockDTO = getLockDTO(unionType, unionId);
Assert.isTrue(RedissonUtils.tryLockAutomatically(lockDTO), "关联类型数据正在被操作");
exist = asyncTaskNoticeMapper.existsEntity(existNotice);
Assert.isTrue(!exist, "已存在相同关联类型数据");
AsyncTaskNotice notice = AsyncTaskNoticeMapMapper.INSTANCE.toEntity(createDTO);
notice.setFlowStatus(AsyncTaskFlowStatusEnum.START.getStatus());
notice.setNoticeStatus(AsyncTaskNoticeStatusEnum.INIT.getStatus());
asyncTaskNoticeMapper.saveEntity(notice);
return notice.getId();
}
@Override
@Transactional
public void finish(AsyncTaskNoticeFinishDTO finishDTO) {
AsyncTaskNoticeDTO noticeDTO = find(AsyncTaskNoticeQueryDTO.builder()
.unionType(finishDTO.getUnionType()).unionId(finishDTO.getUnionId()).build());
Assert.notNull(noticeDTO, "未找到对应的异步任务");
Assert.isTrue(AsyncTaskFlowStatusEnum.START.getStatus().equals(noticeDTO.getFlowStatus()), "异步任务已结束");
noticeDTO.setFlowStatus(AsyncTaskFlowStatusEnum.END.getStatus());
noticeDTO.setBizStatusStr(finishDTO.getBizStatusStr());
asyncTaskNoticeMapper.updateEntitySelective(AsyncTaskNoticeMapMapper.INSTANCE.toEntity(noticeDTO));
// 发通知
NoticeUtils.sendAsyncNotice(NoticeMsgDTO.create(noticeDTO.getCreateBy(), NoticeFirstTypeEnum.ASYNC_TASK_NOTICE.getType(), noticeDTO));
}
@Override
@Transactional
public Integer read(AsyncTaskNoticeReadDTO readDTO) {
return asyncTaskNoticeMapper.read(readDTO);
}
@Override
@Transactional
public void remove(Long id) {
asyncTaskNoticeMapper.deleteEntity(AsyncTaskNotice.builder().id(id).build(),
UserContextHolder.getLoginUserId());
}
@Override
public List<AsyncTaskNoticeDTO> list(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO) {
asyncTaskNoticeQueryDTO.disablePage();
return asyncTaskNoticeMapper.listAsyncTaskNoticeDTO(asyncTaskNoticeQueryDTO);
}
@Override
public void page(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO) {
asyncTaskNoticeMapper.listAsyncTaskNoticeDTO(asyncTaskNoticeQueryDTO);
}
@Override
public AsyncTaskNoticeDTO find(AsyncTaskNoticeQueryDTO asyncTaskNoticeQueryDTO) {
List<AsyncTaskNoticeDTO> asyncTaskNoticeDTOs = this.list(asyncTaskNoticeQueryDTO);
return ListUtil.first(asyncTaskNoticeDTOs);
}
}

View File

@@ -0,0 +1,44 @@
package com.newyetai.component.asyntasknotice.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.newyetai.common.constant.CommonConstants;
import com.newyetai.common.util.EnvironmentUtils;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO;
import com.newyetai.component.asyntasknotice.service.AsyncTaskNoticeService;
import lombok.extern.slf4j.Slf4j;
/**
* @author sr on 2024-02-06
*/
@Component
@Slf4j
public class AsyncTaskNoticeUtils {
private static AsyncTaskNoticeService asyncTaskNoticeService;
@Autowired
public void setAsyncTaskNoticeService(AsyncTaskNoticeService asyncTaskNoticeService) {
AsyncTaskNoticeUtils.asyncTaskNoticeService = asyncTaskNoticeService;
}
public static void create(AsyncTaskNoticeCreateDTO createDTO) {
try {
asyncTaskNoticeService.create(createDTO);
} catch (Exception e) {
log.info("异步任务通知创建失败:{}", e.getMessage());
}
}
public static void finish(AsyncTaskNoticeFinishDTO finishDTO) {
try {
asyncTaskNoticeService.finish(finishDTO);
} catch (Exception e) {
log.info("异步任务通知结束失败:{}", e.getMessage());
}
}
}

View File

@@ -0,0 +1,26 @@
package com.newyetai.component.cardbin.dao;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.newyetai.component.cardbin.entity.CardBin;
/**
* @author sr on 2019-09-25
*/
public interface CardBinMapper extends BaseMapper<CardBin> {
/**
* 通过卡bin获取卡bin
* @param cardBin
* @return
*/
CardBin findByCardBin(String cardBin);
/**
* 查询卡bin列表
* @return
*/
List<CardBin> selectAllCardBinList();
}

View File

@@ -0,0 +1,40 @@
package com.newyetai.component.cardbin.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
*
*
* @author sr on 2019-09-25
*/
@TableName("xs_bank_code")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Builder
@Data
public class BankCode extends BaseEntity {
/**
* 联行号
**/
private String bankCode;
/**
* 银行名称
**/
private String bankName;
/**
* 法人行号
**/
private String legalEntityCode;
}

View File

@@ -0,0 +1,60 @@
package com.newyetai.component.cardbin.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 卡bin表
*
* @author sr on 2019-09-25
*/
@TableName("xs_card_bin")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Builder
@Data
public class CardBin extends BaseEntity {
/**
* 机构编号
**/
private String bankOrgCode;
/**
* 联网行编号
**/
private String bankNumber;
/**
* 机构名称
**/
private String bankOrgName;
/**
* 卡长度
**/
private Integer cardLength;
/**
* 卡BIN
**/
private String cardBin;
/**
* 是否银联品牌卡
**/
private Boolean standardCard;
/**
* 卡种
**/
private String cardClassify;
/**
* 总行行号(表里都没值,有点问题)
*/
private String bankNo;
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newyetai.component.cardbin.dao.CardBinMapper">
<select id="findByCardBin" resultType="com.newyetai.component.cardbin.entity.CardBin">
select * from xs_card_bin where length(#{param1}) = card_length and locate(card_bin, #{param1}) = 1 and deleted = 0
</select>
<select id="selectAllCardBinList" resultType="com.newyetai.component.cardbin.entity.CardBin">
SELECT
bank_org_code,
bank_number,
bank_org_name,
card_length,
card_bin,
standard_card,
card_classify
FROM
xs_card_bin
WHERE
deleted = 0
</select>
</mapper>

View File

@@ -0,0 +1,53 @@
package com.newyetai.component.cardbin.service;
import com.newyetai.common.AlitaResult;
import com.newyetai.component.cardbin.entity.CardBin;
import java.util.List;
import java.util.Set;
/**
* @author sr on 2019-09-25
*/
public interface CardBinService {
/**
* 导入卡bin
* @author sr on 2019-09-25
*/
void importCardBin();
/**
* 通过卡bin获取卡bin
* @param cardBin
* @return
*/
CardBin findByCardBin(String cardBin);
/**
*
* @param bankNo
* @return
*/
AlitaResult<String> isBankNo(String bankNo);
/**
* 查询卡bin列表
*
* @return
*/
List<CardBin> findAllCardBinList();
/**
* 校验银行卡
* 如果返回null,代表没有可校验的资源
* 否则,返回校验成功的银行卡号集合
*
* @param bankNos 银行卡号集合
* @return {@link Set}<{@link String}>
*/
Set<String> checkBankNos(Set<String> bankNos);
String getBankNo(String bankNo);
}

View File

@@ -0,0 +1,85 @@
package com.newyetai.component.cardbin.service.impl;
import com.newyetai.common.AlitaResult;
import com.newyetai.component.cardbin.dao.CardBinMapper;
import com.newyetai.component.cardbin.entity.CardBin;
import com.newyetai.component.cardbin.service.CardBinService;
import com.newyetai.frame.redis.util.RedissonValueUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author sr on 2019-09-25
*/
@Service
@Slf4j
public class CardBinServiceImpl implements CardBinService {
@Resource
private CardBinMapper cardBinMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public void importCardBin() {
}
@Override
public CardBin findByCardBin(String cardBin) {
if(StringUtils.isBlank(cardBin)){
return null;
}
return cardBinMapper.findByCardBin(cardBin);
}
@Override
public AlitaResult<String> isBankNo(String bankNo) {
if (StringUtils.isBlank(bankNo)) {
return AlitaResult.error("银行卡号为空");
}
CardBin cardBin = findByCardBin(bankNo);
return cardBin != null ? AlitaResult.success(cardBin.getBankOrgName())
: AlitaResult.error("银行卡号格式错误");
}
@Override
public List<CardBin> findAllCardBinList() {
String key = "alita:cardbin:list";
List<CardBin> cardBinList;
if (RedissonValueUtils.hasKey(key)) {
cardBinList = (List<CardBin>) RedissonValueUtils.get(key);
} else {
cardBinList = cardBinMapper.selectAllCardBinList();
RedissonValueUtils.set(key, cardBinList);
}
return cardBinList;
}
@Override
public Set<String> checkBankNos(Set<String> bankNos) {
List<CardBin> allCardBinList = findAllCardBinList();
if (CollectionUtils.isEmpty(allCardBinList)) {
return null;
}
return bankNos.stream().filter(bankNo -> allCardBinList.parallelStream().anyMatch(cardBin ->
bankNo.startsWith(cardBin.getCardBin()) && bankNo.length() == cardBin.getCardLength()))
.collect(Collectors.toSet());
}
@Override
public String getBankNo(String bankNo) {
if (StringUtils.isBlank(bankNo)) {
return null;
}
CardBin cardBin = findByCardBin(bankNo);
return cardBin == null ? null : cardBin.getBankOrgName();
}
}

View File

@@ -0,0 +1,8 @@
package com.newyetai.component.chat.constant;
/**
* @author sr on 2025-05-29
*/
public interface ChatConstants {
}

View File

@@ -0,0 +1,27 @@
package com.newyetai.component.chat.constant;
public enum ChatMsgStatusEnum {
/** 未读 **/
INIT(1),
/** 已读 **/
READ(2),
;
private Integer status;
ChatMsgStatusEnum(Integer status) {
this.status = status;
}
public Integer getStatus() {
return status;
}
}

View File

@@ -0,0 +1,22 @@
package com.newyetai.component.chat.constant;
import com.google.common.collect.Maps;
import java.util.Map;
public enum ChatMsgTypeEnum {
/** 文字 */
TEXT("text"),
;
private String type;
ChatMsgTypeEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,25 @@
package com.newyetai.component.chat.constant;
import com.google.common.collect.Maps;
import java.util.Map;
public enum ChatStatusEnum {
/** 有效 **/
ACTIVE(1),
/** 关闭 **/
CLOSED(2),
;
private Integer status;
ChatStatusEnum(Integer status) {
this.status = status;
}
public Integer getStatus() {
return status;
}
}

View File

@@ -0,0 +1,19 @@
package com.newyetai.component.chat.constant;
public enum ChatTypeEnum {
/** 岗位 */
POSITION("position"),
;
private String type;
ChatTypeEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,82 @@
package com.newyetai.component.chat.controller;
import com.newyetai.common.util.UserContextHolder;
import com.newyetai.usercenter.user.constant.UserTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.PathVariable;
import com.newyetai.common.validation.Update;
import com.newyetai.common.AlitaResult;
import com.newyetai.tkmybatis.pojo.Page;
import com.newyetai.component.chat.dto.ChatQueryDTO;
import com.newyetai.component.chat.service.ChatService;
import com.newyetai.component.chat.dto.ChatDTO;
import com.newyetai.component.chat.dto.ChatCreateDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/**
* @author sr on 2025-05-29
*/
@RestController
@RequestMapping("chat")
@Api(tags = "聊天会话")
public class ChatController {
@Autowired
private ChatService chatService;
@PostMapping("/create")
@ApiOperation("创建")
public AlitaResult<Long> create(
@Validated @RequestBody ChatCreateDTO chatOperateDTO){
return AlitaResult.success(chatService.create(chatOperateDTO));
}
/* @PutMapping("/modify")
@ApiOperation("修改")
public AlitaResult<Boolean> modify(
@Validated(Update.class) @RequestBody ChatCreateDTO chatOperateDTO){
chatService.modify(chatOperateDTO);
return AlitaResult.success(true);
}*/
@DeleteMapping("/remove/{id}")
@ApiOperation("删除")
public AlitaResult<Boolean> remove(@PathVariable Long id){
chatService.remove(id);
return AlitaResult.success(true);
}
@GetMapping("/page")
@ApiOperation("分页查询")
public AlitaResult<Page<ChatDTO>> page(ChatQueryDTO chatQueryDTO){
chatService.page(chatQueryDTO);
return AlitaResult.success(chatQueryDTO.getPageResult());
}
@GetMapping("/page_curr")
@ApiOperation("分页查询")
public AlitaResult<Page<ChatDTO>> pageCurr(ChatQueryDTO chatQueryDTO){
Long orgId = UserContextHolder.getLoginOrgId();
chatQueryDTO.setOrgId(orgId);
Long userId = UserContextHolder.getLoginUserId();
if (UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType())){
chatQueryDTO.setPersonUserId(userId);
} else {
chatQueryDTO.setOrgUserId(userId);
}
chatService.page(chatQueryDTO);
return AlitaResult.success(chatQueryDTO.getPageResult());
}
}

View File

@@ -0,0 +1,28 @@
package com.newyetai.component.chat.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.newyetai.component.chat.dto.ChatDTO;
import com.newyetai.component.chat.dto.ChatQueryDTO;
import com.newyetai.component.chat.entity.Chat;
import com.newyetai.tkmybatis.mybatis.MyMapper;
/**
* 聊天会话
*
* @author sr on 2025-05-29
*/
public interface ChatMapper extends MyMapper<Chat> {
/**
* 查询
*
* @param chatQueryDTO
* @return
* @author sr on 2025-05-29
*/
List<ChatDTO> listChatDTO(@Param("param") ChatQueryDTO chatQueryDTO);
}

View File

@@ -0,0 +1,28 @@
package com.newyetai.component.chat.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.newyetai.component.chat.dto.ChatMsgDTO;
import com.newyetai.component.chat.dto.ChatMsgQueryDTO;
import com.newyetai.component.chat.entity.ChatMsg;
import com.newyetai.tkmybatis.mybatis.MyMapper;
/**
* 聊天消息
*
* @author sr on 2025-05-29
*/
public interface ChatMsgMapper extends MyMapper<ChatMsg> {
/**
* 查询
*
* @param chatMsgQueryDTO
* @return
* @author sr on 2025-05-29
*/
List<ChatMsgDTO> listChatMsgDTO(@Param("param") ChatMsgQueryDTO chatMsgQueryDTO);
}

View File

@@ -0,0 +1,37 @@
package com.newyetai.component.chat.dto;
import com.newyetai.component.chat.constant.ChatTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import javax.validation.constraints.NotNull;
import com.newyetai.common.validation.Update;
import com.newyetai.common.dto.BaseOperateDTO;
/**
* @author sr on 2025-05-29
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "聊天会话操作")
public class ChatCreateDTO extends BaseOperateDTO {
/** **/
private static final long serialVersionUID = 1L;
@NotNull(message = "机构id不能为空")
private Long orgId;
@NotNull(message = "个人用户id不能为空")
private Long personUserId;
/** @see ChatTypeEnum 类型 */
@Default
private String type = ChatTypeEnum.POSITION.getType();
}

View File

@@ -0,0 +1,44 @@
package com.newyetai.component.chat.dto;
import com.newyetai.common.dto.BaseDTO;
import com.newyetai.component.chat.constant.ChatTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author sr on 2025-05-29
*/
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Builder
@Data
@ApiModel(description = "聊天会话")
public class ChatDTO extends BaseDTO {
/** **/
private static final long serialVersionUID = 1L;
/** 机构id */
private Long orgId;
/** 机构用户id */
private Long orgUserId;
/** 个人用户id */
private Long personUserId;
/** @see ChatTypeEnum 类型 */
private Integer type;
/** 状态:1有效,2关闭 */
private Integer status;
/** 机构名称 */
private String orgName;
/** 个人用户名称*/
private String personUserName;
}

View File

@@ -0,0 +1,45 @@
package com.newyetai.component.chat.dto;
import com.newyetai.component.chat.constant.ChatMsgTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import javax.validation.constraints.NotNull;
import com.newyetai.common.validation.Update;
import com.newyetai.common.dto.BaseOperateDTO;
/**
* @author sr on 2025-05-29
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "聊天消息操作")
public class ChatMsgCreateDTO extends BaseOperateDTO{
/** **/
private static final long serialVersionUID = 1L;
/** 聊天id */
private Long chatId;
/** 机构id */
private Long orgId;
/** 个人用户id */
private Long personUserId;
/** --- 聊天id 或 orgId+personUserId 两者选其一不为空 --- */
/** 消息类型:text等 */
@Default
private String msgType = ChatMsgTypeEnum.TEXT.getType();
/** 内容 */
@NotEmpty(message = "内容不能为空")
private String content;
}

View File

@@ -0,0 +1,42 @@
package com.newyetai.component.chat.dto;
import com.newyetai.common.dto.BaseDTO;
import com.newyetai.component.chat.constant.ChatMsgStatusEnum;
import com.newyetai.component.chat.constant.ChatMsgTypeEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* @author sr on 2025-05-29
*/
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Builder
@Data
@ApiModel(description = "聊天消息")
public class ChatMsgDTO extends BaseDTO {
/** **/
private static final long serialVersionUID = 1L;
/** 聊天id */
private Long chatId;
/** 发送用户id */
private Long senderId;
/** 消息类型:text等 */
@Default
private String msgType = ChatMsgTypeEnum.TEXT.getType();
/** 内容 */
private String content;
/** 消息状态:1未读,2已读 */
@Default
private Integer msgStatus = ChatMsgStatusEnum.INIT.getStatus();
}

View File

@@ -0,0 +1,28 @@
package com.newyetai.component.chat.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import com.newyetai.common.dto.PageQueryDTO;
/**
* @author sr on 2025-05-29
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "聊天消息查询条件")
public class ChatMsgQueryDTO extends PageQueryDTO<ChatMsgDTO>{
/** **/
private static final long serialVersionUID = 1L;
private Long chatId;
}

View File

@@ -0,0 +1,43 @@
package com.newyetai.component.chat.dto;
import com.newyetai.component.chat.constant.ChatTypeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import com.newyetai.common.dto.PageQueryDTO;
/**
* @author sr on 2025-05-29
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "聊天会话查询条件")
public class ChatQueryDTO extends PageQueryDTO<ChatDTO>{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
private Long id;
/** 机构id */
private Long orgId;
/** 机构用户id */
private Long orgUserId;
/** 个人用户id */
private Long personUserId;
/** 状态:1有效,2关闭 */
private Integer status;
/** @see ChatTypeEnum 类型 */
@Default
private String type = ChatTypeEnum.POSITION.getType();
}

View File

@@ -0,0 +1,41 @@
package com.newyetai.component.chat.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.common.entity.BaseEntity;
import com.newyetai.component.chat.constant.ChatTypeEnum;
import lombok.AllArgsConstructor;
import lombok.experimental.SuperBuilder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 聊天会话
*
* @author sr on 2025-05-29
*/
@TableName("xs_chat")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
public class Chat extends BaseEntity {
/** **/
private static final long serialVersionUID = 1L;
/** 机构id */
private Long orgId;
/** 机构用户id */
private Long orgUserId;
/** 个人用户id */
private Long personUserId;
/** @see ChatTypeEnum 类型 */
private String type;
/** 状态:1有效,2关闭 */
private Integer status;
}

View File

@@ -0,0 +1,44 @@
package com.newyetai.component.chat.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.component.chat.constant.ChatMsgStatusEnum;
import com.newyetai.component.chat.constant.ChatMsgTypeEnum;
import com.newyetai.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder.Default;
import lombok.experimental.SuperBuilder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 聊天消息
*
* @author sr on 2025-05-29
*/
@TableName("xs_chat_msg")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
public class ChatMsg extends BaseEntity {
/** **/
private static final long serialVersionUID = 1L;
/** 聊天id */
private Long chatId;
/** 发送用户id */
private Long senderId;
/** 消息类型:text等 */
@Default
private String msgType = ChatMsgTypeEnum.TEXT.getType();
/** 内容 */
private String content;
/** 消息状态:1未读,2已读 */
@Default
private Integer msgStatus = ChatMsgStatusEnum.INIT.getStatus();
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newyetai.component.chat.dao.ChatMapper">
<select id="listChatDTO" resultType="com.newyetai.component.chat.dto.ChatDTO">
select
*,
(select org_name from xs_org o where o.id = org_id) orgName,
(select username from uc_user u where u.id = person_user_id) personUserName
from xs_chat
where
deleted = 0
<if test="param.id != null">
and id = #{param.id}
</if>
<if test="param.orgId != null">
and org_id = #{param.orgId}
</if>
<if test="param.orgUserId != null">
and org_user_id = #{param.orgUserId}
</if>
<if test="param.personUserId != null">
and person_user_id = #{param.personUserId}
</if>
<if test="param.status != null">
and status = #{param.status}
</if>
</select>
</mapper>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newyetai.component.chat.dao.ChatMsgMapper">
<select id="listChatMsgDTO" resultType="com.newyetai.component.chat.dto.ChatMsgDTO">
select
*
from xs_chat_msg
where
deleted = 0
<if test="param.id != null">
and id = #{param.id}
</if>
<if test="param.chatId != null">
and chat_id = #{param.chatId}
</if>
order by id desc
</select>
</mapper>

View File

@@ -0,0 +1,37 @@
package com.newyetai.component.chat.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.newyetai.component.chat.dto.ChatDTO;
import com.newyetai.component.chat.entity.Chat;
import com.newyetai.component.chat.dto.ChatCreateDTO;
/**
* @author sr on 2025-05-29
*/
@Mapper
public interface ChatMapMapper {
ChatMapMapper INSTANCE =
Mappers.getMapper(ChatMapMapper.class);
/**
* dto to entity
*
* @param chatDto
* @return
* @author sr on 2025-05-29
*/
Chat toEntity(
ChatDTO chatDto);
/**
* @param chatOperateDTO
* @return
* @author sr on 2025-05-29
*/
Chat toEntity(ChatCreateDTO chatOperateDTO);
}

View File

@@ -0,0 +1,39 @@
package com.newyetai.component.chat.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.newyetai.component.chat.dto.ChatMsgDTO;
import com.newyetai.component.chat.entity.ChatMsg;
import com.newyetai.component.chat.dto.ChatMsgCreateDTO;
/**
* @author sr on 2025-05-29
*/
@Mapper
public interface ChatMsgMapMapper {
ChatMsgMapMapper INSTANCE =
Mappers.getMapper(ChatMsgMapMapper.class);
/**
* dto to entity
*
* @param chatMsgDto
* @return
* @author sr on 2025-05-29
*/
ChatMsg toEntity(
ChatMsgDTO chatMsgDto);
/**
* @param chatMsgCreateDTO
* @return
* @author sr on 2025-05-29
*/
ChatMsg toEntity(ChatMsgCreateDTO chatMsgCreateDTO);
ChatMsgDTO toDto(ChatMsg chatMsg);
}

View File

@@ -0,0 +1,68 @@
package com.newyetai.component.chat.service;
import java.util.List;
import com.newyetai.component.chat.dto.ChatMsgQueryDTO;
import com.newyetai.component.chat.dto.ChatMsgCreateDTO;
import com.newyetai.component.chat.dto.ChatMsgDTO;
/**
* 聊天消息
*
* @author sr on 2025-05-29
*/
public interface ChatMsgService {
/**
* 新增
*
* @param chatMsgCreateDTO
* @return
* @author sr on 2025-05-29
*/
Long create(ChatMsgCreateDTO chatMsgCreateDTO);
/**
* 修改
*
* @param chatMsgCreateDTO
* @author sr on 2025-05-29
*/
void modify(ChatMsgCreateDTO chatMsgCreateDTO);
/**
* 删除
*
* @param id
* @author sr on 2025-05-29
*/
void remove(Long id);
/**
* 查询
*
* @param chatMsgQueryDTO
* @return
* @author sr on 2025-05-29
*/
List<ChatMsgDTO> list(ChatMsgQueryDTO chatMsgQueryDTO);
/**
* 分页查询
*
* @param chatMsgQueryDTO
* @return
* @author sr on 2025-05-29
*/
void page(ChatMsgQueryDTO chatMsgQueryDTO);
/**
* 单个查询
*
* @param chatMsgQueryDTO
* @return
* @author sr on 2025-05-29
*/
ChatMsgDTO find(ChatMsgQueryDTO chatMsgQueryDTO);
}

View File

@@ -0,0 +1,61 @@
package com.newyetai.component.chat.service;
import java.util.List;
import com.newyetai.component.chat.dto.ChatQueryDTO;
import com.newyetai.component.chat.dto.ChatCreateDTO;
import com.newyetai.component.chat.dto.ChatDTO;
/**
* 聊天会话
*
* @author sr on 2025-05-29
*/
public interface ChatService {
/**
* 新增
*
* @param chatCreateDTO
* @return
* @author sr on 2025-05-29
*/
Long create(ChatCreateDTO chatCreateDTO);
/**
* 删除
*
* @param id
* @author sr on 2025-05-29
*/
void remove(Long id);
/**
* 查询
*
* @param chatQueryDTO
* @return
* @author sr on 2025-05-29
*/
List<ChatDTO> list(ChatQueryDTO chatQueryDTO);
/**
* 分页查询
*
* @param chatQueryDTO
* @return
* @author sr on 2025-05-29
*/
void page(ChatQueryDTO chatQueryDTO);
/**
* 单个查询
*
* @param chatQueryDTO
* @return
* @author sr on 2025-05-29
*/
ChatDTO find(ChatQueryDTO chatQueryDTO);
}

View File

@@ -0,0 +1,108 @@
package com.newyetai.component.chat.service.impl;
import com.newyetai.component.chat.dto.ChatCreateDTO;
import com.newyetai.component.chat.dto.ChatDTO;
import com.newyetai.component.chat.dto.ChatQueryDTO;
import com.newyetai.component.chat.mapstruct.ChatMsgMapMapper;
import com.newyetai.component.chat.service.ChatService;
import com.newyetai.component.notice.constant.NoticeFirstTypeEnum;
import com.newyetai.component.notice.dto.NoticeMsgDTO;
import com.newyetai.component.notice.util.NoticeUtils;
import com.newyetai.usercenter.user.constant.UserTypeEnum;
import com.newyetai.usercenter.websocket.service.impl.WebsocketNoticeSendProvider;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.newyetai.component.chat.dao.ChatMsgMapper;
import com.newyetai.component.chat.service.ChatMsgService;
import com.newyetai.component.chat.dto.ChatMsgQueryDTO;
import com.newyetai.component.chat.dto.ChatMsgDTO;
import com.newyetai.component.chat.dto.ChatMsgCreateDTO;
import com.newyetai.component.chat.entity.ChatMsg;
import com.newyetai.common.util.UserContextHolder;
import com.newyetai.common.util.ListUtil;
/**
* @author sr on 2025-05-29
*/
@Service
public class ChatMsgServiceImpl implements ChatMsgService {
private static final Logger log = LoggerFactory.getLogger(ChatMsgServiceImpl.class);
@Autowired
private ChatMsgMapper chatMsgMapper;
@Autowired
private ChatService chatService;
@Override
@Transactional
public Long create(ChatMsgCreateDTO chatMsgCreateDTO) {
Long chatId = chatMsgCreateDTO.getChatId();
Long senderId = UserContextHolder.getLoginUserId();
Long personUserId = chatMsgCreateDTO.getPersonUserId();
if (UserTypeEnum.PERSON.getType().equals(UserContextHolder.getUserType())){
personUserId = senderId;
}
if (chatId == null) {
chatId = chatService.create(ChatCreateDTO.builder().orgId(chatMsgCreateDTO.getOrgId())
.personUserId(personUserId).build());
}
ChatMsg msg = ChatMsg.builder().chatId(chatId).senderId(senderId).content(chatMsgCreateDTO.getContent()).build();
chatMsgMapper.saveEntity(msg);
// 发通知
this.sendAsyncNotice(chatId, ChatMsgMapMapper.INSTANCE.toDto(msg));
return msg.getId();
}
private void sendAsyncNotice(Long chatId, ChatMsgDTO msgDTO) {
try {
ChatDTO chatDTO = chatService.find(ChatQueryDTO.builder().id(chatId).build());
Long receiverId =
msgDTO.getSenderId().equals(chatDTO.getPersonUserId()) ? chatDTO.getOrgUserId()
: chatDTO.getPersonUserId();
NoticeUtils.sendAsyncNotice(
NoticeMsgDTO.create(receiverId, NoticeFirstTypeEnum.CHAT.getType(), msgDTO));
} catch (Exception e) {
log.info("chat发送异步消息失败", e.getMessage());
}
}
@Override
@Transactional
public void modify(ChatMsgCreateDTO chatMsgCreateDTO) {
// TODO Auto-generated method stub
}
@Override
@Transactional
public void remove(Long id) {
chatMsgMapper.deleteEntity(ChatMsg.builder().id(id).build(),
UserContextHolder.getLoginUserId());
}
@Override
public List<ChatMsgDTO> list(ChatMsgQueryDTO chatMsgQueryDTO) {
chatMsgQueryDTO.disablePage();
return chatMsgMapper.listChatMsgDTO(chatMsgQueryDTO);
}
@Override
public void page(ChatMsgQueryDTO chatMsgQueryDTO) {
chatMsgMapper.listChatMsgDTO(chatMsgQueryDTO);
}
@Override
public ChatMsgDTO find(ChatMsgQueryDTO chatMsgQueryDTO) {
List<ChatMsgDTO> chatMsgDTOs = this.list(chatMsgQueryDTO);
return ListUtil.first(chatMsgDTOs);
}
}

View File

@@ -0,0 +1,99 @@
package com.newyetai.component.chat.service.impl;
import com.newyetai.common.exception.util.Assert;
import com.newyetai.common.util.JsonUtils;
import com.newyetai.common.validation.util.ValidateUtils;
import com.newyetai.component.chat.constant.ChatStatusEnum;
import com.newyetai.component.chat.mapstruct.ChatMapMapper;
import com.newyetai.component.dynamictable.entity.DynamicTable;
import com.newyetai.component.dynamictable.mapstruct.DynamicTableMapMapper;
import com.newyetai.frame.redis.dto.LockDTO;
import com.newyetai.frame.redis.redisson.RedissonUtils;
import com.newyetai.usercenter.user.dao.OrgUserMapper;
import com.newyetai.usercenter.user.dto.OrgUserDTO;
import com.newyetai.usercenter.user.dto.OrgUserQueryDTO;
import java.util.List;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.newyetai.component.chat.dao.ChatMapper;
import com.newyetai.component.chat.service.ChatService;
import com.newyetai.component.chat.dto.ChatQueryDTO;
import com.newyetai.component.chat.dto.ChatDTO;
import com.newyetai.component.chat.dto.ChatCreateDTO;
import com.newyetai.component.chat.entity.Chat;
import com.newyetai.common.util.UserContextHolder;
import com.newyetai.common.util.ListUtil;
/**
* @author sr on 2025-05-29
*/
@Service
public class ChatServiceImpl implements ChatService {
@Autowired
private ChatMapper chatMapper;
@Autowired
private OrgUserMapper orgUserMapper;
public static LockDTO getLockDTO(Long orgId, Long personUserId) {
Assert.notNull(orgId, "机构id不能为空");
Assert.notNull(personUserId, "个人用户id不能为空");
return LockDTO.builder().methodName("chat").tryLockWaitTime(0L)
.arg(orgId.toString())
.arg(personUserId.toString())
.failMsg("该机构-个人聊天正在被操作")
.build();
}
@Override
@Transactional
public Long create(ChatCreateDTO createDTO) {
ValidateUtils.validateBiz(createDTO);
Long orgId = createDTO.getOrgId();
Long personUserId = createDTO.getPersonUserId();
ChatQueryDTO queryDTO = ChatQueryDTO.builder().orgId(orgId).personUserId(personUserId).status(
ChatStatusEnum.ACTIVE.getStatus()).build();
return RedissonUtils.lockAndSave(getLockDTO(orgId, personUserId),
() -> this.find(queryDTO), () -> {
List<OrgUserDTO> orgUserDTOs = orgUserMapper.listOrgUserDTO(
OrgUserQueryDTO.builder().orgId(orgId).administrator(Boolean.TRUE).build());
Assert.isTrue(orgUserDTOs.size() == 1, orgId + ":机构管理员信息异常,请联系管理员");
Chat chat =
ChatMapMapper.INSTANCE.toEntity(createDTO);
chat.setOrgUserId(orgUserDTOs.get(0).getUserId());
chatMapper.saveEntity(chat);
return chat.getId();
});
}
@Override
@Transactional
public void remove(Long id) {
chatMapper.deleteEntity(Chat.builder().id(id).build(),
UserContextHolder.getLoginUserId());
}
@Override
public List<ChatDTO> list(ChatQueryDTO chatQueryDTO) {
chatQueryDTO.disablePage();
return chatMapper.listChatDTO(chatQueryDTO);
}
@Override
public void page(ChatQueryDTO chatQueryDTO) {
chatMapper.listChatDTO(chatQueryDTO);
}
@Override
public ChatDTO find(ChatQueryDTO chatQueryDTO) {
List<ChatDTO> chatDTOs = this.list(chatQueryDTO);
return ListUtil.first(chatDTOs);
}
}

View File

@@ -0,0 +1,8 @@
package com.newyetai.component.chat.util;
/**
* @author sr on 2025-05-29
*/
public class ChatMsgUtils {
}

View File

@@ -0,0 +1,8 @@
package com.newyetai.component.chat.util;
/**
* @author sr on 2025-05-29
*/
public class ChatUtils {
}

View File

@@ -0,0 +1,29 @@
package com.newyetai.component.commonimport.constant;
/**
* 通用导入明细状态
* @author sr on 2024-01-19
*/
public enum ImportDetailStatusEnum {
/** 新建 **/
INIT(1),
/** 校验成功 **/
CHECK_SUCCESS(2),
/** 校验失败 **/
CHECK_FAIL(3),
;
private Integer status;
ImportDetailStatusEnum(Integer status) {
this.status = status;
}
public Integer getStatus() {
return status;
}
}

View File

@@ -0,0 +1,28 @@
package com.newyetai.component.commonimport.constant;
/**
* 指定执行类型
* @author sr on 2024-01-23
*/
public enum ImportExecuteTypeEnum {
/** 普通 **/
NORMAL(1),
/** 指定外部id **/
EXTRA_ID(2),
/** 明细表单 **/
DETAIL_FORM(3),
;
private Integer type;
ImportExecuteTypeEnum(Integer type) {
this.type = type;
}
public Integer getType() {
return type;
}
}

View File

@@ -0,0 +1,58 @@
package com.newyetai.component.commonimport.constant;
import java.util.Map;
import com.google.common.collect.Maps;
/**
* 通用导入状态
* @author sr on 2024-01-19
*/
public enum ImportStatusEnum {
/** 新建 **/
INIT(1, "新建"),
/** 解析失败 **/
ANALY_FAIL(2, "解析失败"),
/** 校验中 **/
CHECKING(3, "校验中"),
/** 校验失败 **/
CHECK_FAIL(4, "校验失败"),
/** 校验完成 **/
CHECKED(5, "校验完成"),
/** 执行导入完成 **/
EXECUTE(6, "已完成"),
;
private static Map<Integer, ImportStatusEnum> importStatusMap ;
static {
ImportStatusEnum[] importStatusEnums = ImportStatusEnum.values();
importStatusMap = Maps.newHashMapWithExpectedSize(importStatusEnums.length);
for(ImportStatusEnum e: importStatusEnums) {
importStatusMap.put(e.getStatus(), e);
}
}
private Integer status;
private String name;
ImportStatusEnum(Integer status, String name) {
this.status = status;
}
public Integer getStatus() {
return status;
}
public String getName() {
return name;
}
public static ImportStatusEnum get(Integer status) {
return importStatusMap.get(status);
}
}

View File

@@ -0,0 +1,50 @@
package com.newyetai.component.commonimport.constant;
import java.util.Map;
import com.google.common.collect.Maps;
/**
* 导入类型
* @author sr on 2024-01-23
*/
public enum ImportTypeEnum {
TALENT("talent", "人才库导入"),
POSITION("position", "岗位导入"),
ADMIN_POSITION("admin_position", "admin岗位导入"),
ORG("org", "机构导入"),
;
private String type;
private String name;
private static Map<String, ImportTypeEnum> importTypeMap ;
static {
ImportTypeEnum[] importTypeEnums = ImportTypeEnum.values();
importTypeMap = Maps.newHashMapWithExpectedSize(importTypeEnums.length);
for(ImportTypeEnum e: importTypeEnums) {
importTypeMap.put(e.getType(), e);
}
}
ImportTypeEnum(String type, String name) {
this.type = type;
this.name = name;
}
public String getType() {
return type;
}
public String getName() {
return name;
}
public static ImportTypeEnum get(String type) {
return importTypeMap.get(type);
}
}

View File

@@ -0,0 +1,109 @@
package com.newyetai.component.commonimport.controller;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.newyetai.common.AlitaResult;
import com.newyetai.common.exception.util.Assert;
import com.newyetai.component.commonimport.dto.ImportDetailPageDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO;
import com.newyetai.component.commonimport.dto.ImportMainDTO;
import com.newyetai.component.commonimport.dto.ImportMainQueryDTO;
import com.newyetai.component.commonimport.service.impl.CommonImportAdapter;
import com.newyetai.config.dto.ConfigDTO;
import com.newyetai.tkmybatis.pojo.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/**
* @author sr on 2024-01-19
*/
@RestController
@RequestMapping("common_import")
@Api(tags = "通用导入")
public class CommonImportController {
@Autowired(required = false)
private CommonImportAdapter commonImportAdapter;
@GetMapping("/template/{type}")
@ApiOperation("模版")
public AlitaResult<ConfigDTO> template(@PathVariable String type){
Assert.notNull(commonImportAdapter, "无通用导入提供者");
return AlitaResult.success(commonImportAdapter.template(type));
}
@GetMapping("/page")
@ApiOperation("分页查询")
public AlitaResult<Page<ImportMainDTO>> page(ImportMainQueryDTO queryDTO){
Assert.notNull(commonImportAdapter, "无通用导入提供者");
commonImportAdapter.page(queryDTO);
return AlitaResult.success(queryDTO.getPageResult());
}
@GetMapping("/find")
@ApiOperation("单个查询")
public AlitaResult<ImportMainDTO> find(ImportMainQueryDTO queryDTO){
Assert.notNull(commonImportAdapter, "无通用导入提供者");
return AlitaResult.success(commonImportAdapter.find(queryDTO));
}
@PostMapping("/create")
@ApiOperation("创建")
public AlitaResult<Long> create(
@Validated @RequestBody ImportMainCreateDTO createDTO){
Assert.notNull(commonImportAdapter, "无通用导入提供者");
return AlitaResult.success(commonImportAdapter.create(createDTO));
}
@PostMapping("/create_async")
@ApiOperation("创建(异步)")
public AlitaResult<Long> createAsync(
@Validated @RequestBody ImportMainCreateDTO createDTO){
Assert.notNull(commonImportAdapter, "无通用导入提供者");
return AlitaResult.success(commonImportAdapter.createAsync(createDTO));
}
@PostMapping("/create_form")
@ApiOperation("创建(明细form)")
public AlitaResult<Long> createForm(
@Validated @RequestBody ImportMainCreateFormDTO createDTO){
Assert.notNull(commonImportAdapter, "无通用导入提供者");
return AlitaResult.success(commonImportAdapter.createForm(createDTO));
}
@PostMapping("/confirm/{type}")
@ApiOperation("执行导入")
public AlitaResult<Long> confirm(@PathVariable String type,
@RequestBody Map<String, Object> executeDto){
Assert.notNull(commonImportAdapter, "无通用导入提供者");
return AlitaResult.success(commonImportAdapter.confirmImport(type, executeDto));
}
@GetMapping("/pageDetail")
@ApiOperation("导入明细分页")
public AlitaResult<Page<T>> pageDetail(@Validated ImportDetailPageDTO importDetailPageDTO) {
Assert.notNull(commonImportAdapter, "无通用导入提供者");
return AlitaResult.success(commonImportAdapter.pageDetail(importDetailPageDTO));
}
@GetMapping("/importDetailExport")
@ApiOperation("导入明细分页")
public void importDetailExport(@Validated ImportDetailPageDTO importDetailPageDTO) {
Assert.notNull(commonImportAdapter, "无通用导入提供者");
commonImportAdapter.importDetailExport(importDetailPageDTO);
}
}

View File

@@ -0,0 +1,31 @@
package com.newyetai.component.commonimport.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.newyetai.component.commonimport.dto.ImportMainDTO;
import com.newyetai.component.commonimport.dto.ImportMainQueryDTO;
import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO;
import com.newyetai.component.commonimport.entity.UcImportMain;
import com.newyetai.tkmybatis.mybatis.MyMapper;
/**
* 通用导入
*
* @author sr on 2024-01-19
*/
public interface ImportMainMapper extends MyMapper<UcImportMain> {
/**
* 查询
*
* @param importMainQueryDTO
* @return
* @author sr on 2024-01-19
*/
List<ImportMainDTO> listImportMainDTO(@Param("param") ImportMainQueryDTO importMainQueryDTO);
int modify(@Param("param") ImportMainUpdateDTO updateDto);
}

View File

@@ -0,0 +1,36 @@
package com.newyetai.component.commonimport.dto;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import lombok.Data;
/**
* @description:
* @author: guixinman
* @create: 2024-01-30 14:04
**/
@Data
public class ImportDetailPageDTO implements Serializable {
@NotNull(message = "参数异常")
private Long mainId;
@NotNull(message = "参数异常")
private String type;
/**
* 第几页
**/
private Integer pageNo = 1;
/**
* 页宽
**/
private Integer pageSize = 20;
/** 导入状态:1新建,2校验成功,3校验失败 **/
private Integer detailStatus;
}

View File

@@ -0,0 +1,43 @@
package com.newyetai.component.commonimport.dto;
import com.newyetai.common.dto.BaseDTO;
import com.newyetai.component.action.dto.ActionDetailDTO;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* @author sr on 2024-01-19
*/
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@ApiModel(description = "通用导入")
public class ImportDetailSuperDTO extends BaseDTO {
/** **/
private static final long serialVersionUID = 1L;
/** 批次id **/
private Long mainId;
/** 导入状态:1新建,2校验成功,3校验失败 **/
private Integer detailStatus;
/** 失败原因 **/
private String failReason;
/** 备注 **/
private String remark;
/** 外部生成明细id **/
private Long extraDetailId;
}

View File

@@ -0,0 +1,40 @@
package com.newyetai.component.commonimport.dto;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2024-01-19
*/
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@ApiModel(description = "通用导入执行")
public class ImportExecuteSuperDTO implements Serializable{
/** **/
private static final long serialVersionUID = 1L;
/** 批次id **/
@NotNull(message = "导入id不能为空")
private Long mainId;
/**(后台设置)执行类型:1.普通,2.指定外部id **/
private Integer executeType;
/**(后台设置)外部生成id(可为空) **/
private Long extraId;
}

View File

@@ -0,0 +1,45 @@
package com.newyetai.component.commonimport.dto;
import javax.validation.constraints.NotBlank;
import com.newyetai.common.dto.BaseOperateDTO;
import com.newyetai.component.commonimport.constant.ImportExecuteTypeEnum;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Builder.Default;
/**
* @author sr on 2024-01-19
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "通用导入操作")
public class ImportMainCreateDTO extends BaseOperateDTO{
/** **/
private static final long serialVersionUID = 1L;
/** 导入类型 **/
@NotBlank(message = "导入类型不能为空")
private String type;
/** 文件CODE **/
@NotBlank(message = "文件code不能为空")
private String fileCode;
/** 文件名称 **/
@NotBlank(message = "文件名称不能为空")
private String fileName;
/** 备注 **/
private String remark;
/** 执行类型:1.普通,2.指定外部id **/
@Default
private Integer executeType = ImportExecuteTypeEnum.NORMAL.getType();
/** 外部生成id **/
private Long extraId;
}

View File

@@ -0,0 +1,39 @@
package com.newyetai.component.commonimport.dto;
import java.util.List;
import java.util.Map;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import com.newyetai.common.dto.BaseOperateDTO;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2024-01-19
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "通用导入操作(form)")
public class ImportMainCreateFormDTO extends BaseOperateDTO{
/** **/
private static final long serialVersionUID = 1L;
/** 导入类型 **/
@NotBlank(message = "导入类型不能为空")
private String type;
/** 备注 **/
private String remark;
@NotNull(message = "明细不能为空")
private List<Map<String, Object>> details;
}

View File

@@ -0,0 +1,59 @@
package com.newyetai.component.commonimport.dto;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.newyetai.common.dto.BaseDTO;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* @author sr on 2024-01-19
*/
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
@ApiModel(description = "通用导入")
public class ImportMainDTO extends BaseDTO {
/** **/
private static final long serialVersionUID = 1L;
/** 批次号 **/
private String importNo;
/** 导入类型 **/
private String type;
/** 导入状态:1新建,2解析失败,3校验中,4校验失败,5校验成功,6执行导入完成 **/
private Integer importStatus;
/** 总数 **/
private Integer totalNum;
/** 成功数 **/
private Integer successNum;
/** 失败原因 **/
private String failMsg;
/** 完成时间时间 **/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date finishTime;
/** 执行类型:1.普通,2.指定外部id,3.明细表单 **/
private Integer executeType;
/** 外部生成id **/
private Long extraId;
/** 文件CODE **/
private String fileCode;
/** 文件名称 **/
private String fileName;
/** 机构ID **/
private Long orgId;
/** 备注 **/
private String remark;
}

View File

@@ -0,0 +1,64 @@
package com.newyetai.component.commonimport.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import io.swagger.annotations.ApiModel;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.newyetai.common.dto.PageQueryDTO;
/**
* @author sr on 2024-01-19
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "通用导入查询条件")
public class ImportMainQueryDTO extends PageQueryDTO<ImportMainDTO>{
/** **/
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
private Long id;
/** 批次号 **/
private String importNo;
/** 导入类型 **/
private String type;
/** 导入状态:1新建,2解析失败,3校验中,4校验失败,5校验成功,6执行导入完成 **/
private Integer importStatus;
/** 文件名称 **/
private String fileNameLike;
/** 外部生成id **/
private Long extraId;
@ApiModelProperty("创建时间起,格式 (yyyy-MM-dd HH:mm:ss)")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTimeStart;
@ApiModelProperty("创建时间止,格式 (yyyy-MM-dd HH:mm:ss)")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTimeEnd;
@ApiModelProperty("完成时间起,格式 (yyyy-MM-dd HH:mm:ss)")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date finishTimeStart;
@ApiModelProperty("完成时间止,格式 (yyyy-MM-dd HH:mm:ss)")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date finishTimeEnd;
private Long orgId;
}

View File

@@ -0,0 +1,48 @@
package com.newyetai.component.commonimport.dto;
import java.util.Date;
import java.util.Set;
import javax.validation.constraints.NotNull;
import com.newyetai.common.dto.BaseOperateDTO;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sr on 2024-01-19
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ApiModel(description = "通用导入修改")
public class ImportMainUpdateDTO extends BaseOperateDTO{
/** **/
private static final long serialVersionUID = 1L;
/** id **/
@NotNull(message = "id不能为空")
private Long id;
/** 原状态 **/
@NotNull(message = "原状态不能为空")
private Set<Integer> oldStatusSet;
/** 新状态 **/
@NotNull(message = "新状态不能为空")
private Integer newStatus;
/** 总数 **/
private Integer totalNum;
/** 成功数 **/
private Integer successNum;
/** 失败原因 **/
private String failMsg;
/** 完成时间时间 **/
private Date finishTime;
/** 外部生成id **/
private Long extraId;
}

View File

@@ -0,0 +1,57 @@
package com.newyetai.component.commonimport.entity;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableName;
import com.newyetai.common.entity.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* 通用导入
*
* @author sr on 2024-01-19
*/
@TableName("uc_import_main")
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
@Data
public class UcImportMain extends BaseEntity {
/** **/
private static final long serialVersionUID = 1L;
/** 批次号 **/
private String importNo;
/** 导入类型 **/
private String type;
/** 导入状态:1新建,2解析失败,3校验中,4校验失败,5校验成功,6执行导入完成 **/
private Integer importStatus;
/** 总数 **/
private Integer totalNum;
/** 成功数 **/
private Integer successNum;
/** 失败原因 **/
private String failMsg;
/** 完成时间时间 **/
private Date finishTime;
/** 执行类型:1.普通,2.指定外部id,3.明细表单 **/
private Integer executeType;
/** 外部生成id **/
private Long extraId;
/** 文件CODE **/
private String fileCode;
/** 文件名称 **/
private String fileName;
/** 机构ID **/
private Long orgId;
/** 备注 **/
private String remark;
}

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.newyetai.component.commonimport.dao.ImportMainMapper">
<select id="listImportMainDTO" resultType="com.newyetai.component.commonimport.dto.ImportMainDTO">
select
*
from uc_import_main
where
deleted = 0
<if test="param.id != null">
and id = #{param.id}
</if>
<if test='param.importNo != null and param.importNo.trim() != ""'>
and import_no = #{param.importNo}
</if>
<if test='param.type != null and param.type.trim() != ""'>
and type = #{param.type}
</if>
<if test="param.importStatus != null">
and import_status = #{param.importStatus}
</if>
<if test="param.extraId != null">
and extra_id = #{param.extraId}
</if>
<if test='param.fileNameLike != null and param.fileNameLike.trim() != ""'>
<bind name="fileNameLike" value="'%' + param.fileNameLike + '%'"/>
and file_name like #{fileNameLike}
</if>
<if test='param.orgId != null'>
AND org_id = #{param.orgId}
</if>
<if test='param.createTimeStart != null'>
and create_time &gt;= #{param.createTimeStart}
</if>
<if test='param.createTimeEnd != null'>
and create_time &lt;= #{param.createTimeEnd}
</if>
<if test='param.finishTimeStart != null'>
and finish_time &gt;= #{param.finishTimeStart}
</if>
<if test='param.finishTimeEnd != null'>
and finish_time &lt;= #{param.finishTimeEnd}
</if>
order by id desc
</select>
<update id="modify">
update uc_import_main
set
<if test="param.newStatus != null">
import_status = #{param.newStatus},
</if>
<if test="param.extraId != null">
extra_id = #{param.extraId},
</if>
<if test="param.totalNum != null">
total_num = #{param.totalNum},
</if>
<if test="param.successNum != null">
success_num = #{param.successNum},
</if>
<if test="param.failMsg != null">
fail_msg = #{param.failMsg},
</if>
<if test="param.finishTime != null">
finish_time = #{param.finishTime},
</if>
update_by = #{param.operateUserId},
update_time = now()
where deleted = 0
and id = #{param.id}
and import_status in
<foreach collection="param.oldStatusSet" item="oldStatus"
open="(" close=")" separator=",">
#{oldStatus}
</foreach>
</update>
</mapper>

View File

@@ -0,0 +1,34 @@
package com.newyetai.component.commonimport.mapstruct;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO;
import com.newyetai.component.commonimport.dto.ImportMainDTO;
import com.newyetai.component.commonimport.entity.UcImportMain;
/**
* @author sr on 2024-01-19
*/
@Mapper
public interface ImportMainMapMapper {
ImportMainMapMapper INSTANCE =
Mappers.getMapper(ImportMainMapMapper.class);
/**
* dto to entity
*
* @param importMainDto
* @return
* @author sr on 2024-01-19
*/
UcImportMain toEntity(
ImportMainDTO importMainDto);
UcImportMain to(ImportMainCreateDTO createDto);
UcImportMain to(ImportMainCreateFormDTO createDto);
}

View File

@@ -0,0 +1,64 @@
package com.newyetai.component.commonimport.service;
import java.util.List;
import com.newyetai.component.commonimport.dto.ImportDetailPageDTO;
import com.newyetai.component.commonimport.dto.ImportDetailSuperDTO;
import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO;
import com.newyetai.tkmybatis.pojo.Page;
public interface ICommonImportProvider<IE extends ImportExecuteSuperDTO, ID extends ImportDetailSuperDTO, IDC extends IImportDetailForm> {
String getType();
/**
* 同步导入
* @param createDto
* @return 导入批次头id
* @author sr on 2024-01-22
*/
Long syncImport(ImportMainCreateDTO createDto);
/**
* 异步导入
* @param createDto
* @return 导入批次头id
* @author sr on 2024-01-22
*/
Long ayncImport(ImportMainCreateDTO createDto);
/**
* 确认导入
* @param executeDto
* @return 外部id
* @author sr on 2024-01-23
*/
Long confirmImport(IE executeDto);
/**
* 同步导入(明细form)
* @param createDto
* @param detailCreateDtos
* @return
* @author sr on 2024-01-26
*/
Long syncImportFrom(ImportMainCreateFormDTO createDto, List<IDC> detailCreateDtos);
/**
* @description: 通用明细查询
* @return:
* @author: guixinman
* @param:
*/
Page<ID> pageDetail(ImportDetailPageDTO importDetailPageDTO);
/**
* @description: 通用明细导出数据
* @return:
* @author: guixinman
* @param:
*/
void importDetailExport(ImportDetailPageDTO importDetailPageDTO);
}

View File

@@ -0,0 +1,9 @@
package com.newyetai.component.commonimport.service;
/**
* 明细form
* @author sr on 2024-01-26
*/
public interface IImportDetailForm {
}

View File

@@ -0,0 +1,11 @@
package com.newyetai.component.commonimport.service;
/**
* @description: 导入详情分页查询
* @author: guixinman
* @create: 2024-01-30 13:27
**/
public interface ImportDetailSuperQueryDTO {
}

View File

@@ -0,0 +1,78 @@
package com.newyetai.component.commonimport.service;
import java.util.List;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO;
import com.newyetai.component.commonimport.dto.ImportMainDTO;
import com.newyetai.component.commonimport.dto.ImportMainQueryDTO;
import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO;
/**
* 通用导入
*
* @author sr on 2024-01-19
*/
public interface ImportMainService {
/**
* 新增
*
* @param importMainOperateDTO
* @return
* @author sr on 2024-01-19
*/
Long create(ImportMainCreateDTO createDto);
/**
* 修改
*
* @param updateDto
* @author sr on 2024-01-19
*/
void modify(ImportMainUpdateDTO updateDto);
/**
* 删除
*
* @param id
* @author sr on 2024-01-19
*/
void remove(Long id);
/**
* 查询
*
* @param importMainQueryDTO
* @return
* @author sr on 2024-01-19
*/
List<ImportMainDTO> list(ImportMainQueryDTO importMainQueryDTO);
/**
* 分页查询
*
* @param importMainQueryDTO
* @return
* @author sr on 2024-01-19
*/
void page(ImportMainQueryDTO importMainQueryDTO);
/**
* 单个查询
*
* @param importMainQueryDTO
* @return
* @author sr on 2024-01-19
*/
ImportMainDTO find(ImportMainQueryDTO importMainQueryDTO);
/**
* 明细表单保存
* @param createDto
* @return
* @author sr on 2024-01-26
*/
Long createForm(ImportMainCreateFormDTO createDto);
}

View File

@@ -0,0 +1,236 @@
package com.newyetai.component.commonimport.service.impl;
import java.util.Date;
import java.util.List;
import com.google.common.collect.Sets;
import com.newyetai.common.constant.CommonConstants;
import com.newyetai.common.exception.BusinessException;
import com.newyetai.common.exception.util.Assert;
import com.newyetai.common.util.EnvironmentUtils;
import com.newyetai.common.util.MockUtils;
import com.newyetai.common.validation.util.ValidateUtils;
import com.newyetai.component.asyntasknotice.constant.AsyncTaskTypeEnum;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeCreateDTO;
import com.newyetai.component.asyntasknotice.dto.AsyncTaskNoticeFinishDTO;
import com.newyetai.component.asyntasknotice.util.AsyncTaskNoticeUtils;
import com.newyetai.component.commonimport.constant.ImportDetailStatusEnum;
import com.newyetai.component.commonimport.constant.ImportExecuteTypeEnum;
import com.newyetai.component.commonimport.constant.ImportStatusEnum;
import com.newyetai.component.commonimport.constant.ImportTypeEnum;
import com.newyetai.component.commonimport.dto.ImportDetailSuperDTO;
import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO;
import com.newyetai.component.commonimport.dto.ImportMainDTO;
import com.newyetai.component.commonimport.dto.ImportMainQueryDTO;
import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO;
import com.newyetai.component.commonimport.service.ICommonImportProvider;
import com.newyetai.component.commonimport.service.IImportDetailForm;
import com.newyetai.component.commonimport.service.ImportMainService;
import com.newyetai.mq.consumer.handler.ITopicMqHandler;
import com.newyetai.mq.dto.TopicMqMessage;
import com.newyetai.mq.util.MqSendUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.transaction.annotation.Transactional;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public abstract class AbstractCommonImportProvider<IE extends ImportExecuteSuperDTO, ID extends ImportDetailSuperDTO, IDC extends IImportDetailForm>
implements ICommonImportProvider<IE, ID, IDC>, ITopicMqHandler<Long> {
private ImportMainService imprImportMainService;
public AbstractCommonImportProvider(ImportMainService imprImportMainService) {
this.imprImportMainService = imprImportMainService;
}
@Override
public Long syncImport(ImportMainCreateDTO createDto) {
// 保存头
Long mainId = imprImportMainService.create(createDto);
// 解析文件+明细
analyAndCheck(mainId);
return mainId;
}
/**
* 校验明细from
*/
protected void preCheckCreateForm(List<IDC> detailCreateDtos) {
ValidateUtils.validateBiz(detailCreateDtos);
}
@Override
public Long syncImportFrom(ImportMainCreateFormDTO createDto, List<IDC> detailCreateDtos) {
preCheckCreateForm(detailCreateDtos);
// 保存头
Long mainId = imprImportMainService.createForm(createDto);
checkAndSave(mainId, detailCreateDtos);
return mainId;
}
/**
* 解析文件,校验明细
*/
@Transactional(rollbackFor = Exception.class)
public void analyAndCheck(Long mainId) {
List<IDC> detailCreateDtos = null;
try {
detailCreateDtos = analy(mainId);
Assert.notEmpty(detailCreateDtos, "文件明细不能为空");
} catch (Exception e) {
analyFail(mainId, e.getMessage());
return;
}
checkAndSave(mainId, detailCreateDtos);
}
/**
* 解析文件
* @param mainId
* @return 文件明细dto
* @author sr on 2024-01-26
*/
public abstract List<IDC> analy(Long mainId);
/**
* 保存明细,校验明细
* @param detailCreateDtos
* @author sr on 2024-01-26
*/
public abstract void checkAndSave(Long mainId, List<IDC> detailCreateDtos);
/**
* 解析失败
*/
protected void analyFail(Long mainId, String failMsg) {
ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId)
.oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus()))
.newStatus(ImportStatusEnum.ANALY_FAIL.getStatus())
.failMsg(failMsg).build();
imprImportMainService.modify(updateDto);
finishAsyncTask(mainId, ImportStatusEnum.ANALY_FAIL.getStatus());
}
/**
* 结束明细校验
* @param mainId
* @param detailDtos 明细结果集
* @author sr on 2024-01-26
*/
protected void finishCheck(Long mainId, List<ID> detailDtos) {
Integer sucNum = 0;
Integer failNum = 0;
for(ID detailDto : detailDtos) {
if (ImportDetailStatusEnum.CHECK_SUCCESS.getStatus().equals(detailDto.getDetailStatus())) {
sucNum ++;
}else if (ImportDetailStatusEnum.CHECK_FAIL.getStatus().equals(detailDto.getDetailStatus())) {
failNum++;
} else {
throw new BusinessException("导入明细未全部校验结束");
}
}
Integer totalNum = sucNum + failNum;
Integer importStatus = ImportStatusEnum.CHECKED.getStatus();
if (sucNum == 0) {
importStatus = ImportStatusEnum.CHECK_FAIL.getStatus();
}
ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId)
.oldStatusSet(Sets.newHashSet(ImportStatusEnum.INIT.getStatus(),
ImportStatusEnum.CHECKING.getStatus()))
.newStatus(importStatus)
.totalNum(totalNum)
.successNum(sucNum).build();
imprImportMainService.modify(updateDto);
finishAsyncTask(mainId, importStatus);
}
@Transactional(rollbackFor = Exception.class)
@Override
public Long confirmImport(IE executeDto) {
Long mainId = executeDto.getMainId();
ImportMainDTO importMainDTO = imprImportMainService.find(ImportMainQueryDTO.builder().id(mainId).build());
Assert.notNull(importMainDTO, "未找到指定导入批次");
Assert.isTrue(ImportStatusEnum.CHECKED.getStatus().equals(importMainDTO.getImportStatus()), "校验完成状态才可确定导入");
Integer executeType = importMainDTO.getExecuteType();
executeDto.setExecuteType(executeType);
if (ImportExecuteTypeEnum.EXTRA_ID.getType().equals(executeType)) {
executeDto.setExtraId(importMainDTO.getExtraId());
} else {
preCheckExecute(executeDto);
}
Long extraId = execute(executeDto);
finishExecute(executeDto.getMainId(), extraId);
return extraId;
}
/**
* 执行dto参数校验
* @author sr on 2024-01-26
*/
protected void preCheckExecute(IE executeDto) {
ValidateUtils.validateBiz(executeDto);
}
/**
* 执行(转正式业务数据)
* @param executeDto
* @return 正式数据头id
* @author sr on 2024-01-26
*/
public abstract Long execute(IE executeDto);
/**
* 完成执行
* @author sr on 2024-01-26
*/
protected void finishExecute(Long mainId, Long extraId) {
ImportMainUpdateDTO updateDto = ImportMainUpdateDTO.builder().id(mainId)
.oldStatusSet(Sets.newHashSet(ImportStatusEnum.CHECKED.getStatus()))
.newStatus(ImportStatusEnum.EXECUTE.getStatus())
.extraId(extraId)
.finishTime(new Date()).build();
imprImportMainService.modify(updateDto);
}
@Override
public Long ayncImport(ImportMainCreateDTO createDto) {
// 保存头
Long mainId = imprImportMainService.create(createDto);
MqSendUtils.send(TopicMqMessage.builder().routingKey(getRoutingKey())
.data(mainId)
.build());
AsyncTaskNoticeUtils.create(AsyncTaskNoticeCreateDTO.builder()
.unionType(AsyncTaskTypeEnum.COMMON_IMPORT.getType())
.unionId(mainId)
.content(String.join(CommonConstants.HYPHEN, ImportTypeEnum.get(getType()).getName(), createDto.getFileName()))
.bizStatusStr(ImportStatusEnum.INIT.getName()).build());
return mainId;
}
@Override
public String getRoutingKey() {
return String.join(CommonConstants.UNDERLINE,
EnvironmentUtils.getApplicationName() + CommonConstants.POINT + "common_import", getType());
}
@Override
public void onMessage(TopicMqMessage<Long> message) {
try {
MockUtils.mockUser(message.getOperateUserId(), message.getOperateOrgId());
AbstractCommonImportProvider abstractCommonImportProvider = (AbstractCommonImportProvider) AopContext.currentProxy();
abstractCommonImportProvider.analyAndCheck(message.getData());
} catch (Exception e) {
log.info("通用导入异步执行失败:", e);
}
}
private static void finishAsyncTask(Long mainId, Integer importStatus) {
AsyncTaskNoticeUtils.finish(AsyncTaskNoticeFinishDTO.builder()
.unionType(AsyncTaskTypeEnum.COMMON_IMPORT.getType()).unionId(mainId)
.bizStatusStr(ImportStatusEnum.get(importStatus).getName()).build());
}
}

View File

@@ -0,0 +1,134 @@
package com.newyetai.component.commonimport.service.impl;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Maps;
import com.newyetai.common.constant.CommonConstants;
import com.newyetai.common.exception.util.Assert;
import com.newyetai.common.util.JsonUtils;
import com.newyetai.component.commonimport.dto.ImportDetailPageDTO;
import com.newyetai.component.commonimport.dto.ImportExecuteSuperDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO;
import com.newyetai.component.commonimport.dto.ImportMainDTO;
import com.newyetai.component.commonimport.dto.ImportMainQueryDTO;
import com.newyetai.component.commonimport.service.ICommonImportProvider;
import com.newyetai.component.commonimport.service.IImportDetailForm;
import com.newyetai.component.commonimport.service.ImportDetailSuperQueryDTO;
import com.newyetai.component.commonimport.service.ImportMainService;
import com.newyetai.config.dto.ConfigDTO;
import com.newyetai.config.service.ConfigService;
import com.newyetai.tkmybatis.pojo.Page;
@Service
@ConditionalOnBean(AbstractCommonImportProvider.class)
public class CommonImportAdapter {
private static Map<String, ICommonImportProvider> providerMap = Maps.newHashMap();
private static Map<String, TypeReference<ImportExecuteSuperDTO>> executeTypeMap = Maps.newHashMap();
private static Map<String, TypeReference<IImportDetailForm>> detailFormTypeMap = Maps.newHashMap();
/**
* 通用导入模版前缀
**/
public static final String TEMPLATE_CODE_PREFIX = "common_import_template_";
public CommonImportAdapter(List<ICommonImportProvider> providers) {
providers.forEach(provider -> {
String type = provider.getType();
providerMap.put(type, provider);
ParameterizedType pt = (ParameterizedType) AopUtils.getTargetClass(provider).getGenericSuperclass();
Type executeDtoType = pt.getActualTypeArguments()[0];
TypeReference<ImportExecuteSuperDTO> executeTypeReference = new TypeReference<ImportExecuteSuperDTO>() {
@Override
public Type getType() {
return executeDtoType;
}
};
Type detailFormType = pt.getActualTypeArguments()[2];
TypeReference<IImportDetailForm> detailFormTypeReference = new TypeReference<IImportDetailForm>() {
@Override
public Type getType() {
return detailFormType;
}
};
executeTypeMap.put(type, executeTypeReference);
detailFormTypeMap.put(type, detailFormTypeReference);
});
}
@Autowired
private ConfigService configService;
@Autowired
private ImportMainService importMainService;
private ICommonImportProvider getProvider(String type) {
ICommonImportProvider provider = providerMap.get(type);
Assert.notNull(provider, "通用导入类型有误:" + type);
return provider;
}
public ConfigDTO template(String type) {
getProvider(type);
String configCode = TEMPLATE_CODE_PREFIX + type;
return configService.queryConfigByCode(CommonConstants.PLATFORM_ORG_ID, configCode);
}
public void page(ImportMainQueryDTO queryDTO) {
importMainService.page(queryDTO);
}
public ImportMainDTO find(ImportMainQueryDTO queryDTO) {
return importMainService.find(queryDTO);
}
public Long create(ImportMainCreateDTO createDto) {
ICommonImportProvider provider = getProvider(createDto.getType());
return provider.syncImport(createDto);
}
public Long createAsync(ImportMainCreateDTO createDto) {
ICommonImportProvider provider = getProvider(createDto.getType());
return provider.ayncImport(createDto);
}
public Long createForm(ImportMainCreateFormDTO createDto) {
String type = createDto.getType();
ICommonImportProvider provider = getProvider(type);
String detailJson = JsonUtils.toJsonString(JsonUtils.buildObjectMapper(), createDto.getDetails());
List<IImportDetailForm> details = JsonUtils.toList(detailJson, (Class<IImportDetailForm>) detailFormTypeMap.get(type).getType());
return provider.syncImportFrom(createDto, details);
}
public Long confirmImport(String type, Map<String, Object> executeDtoMap) {
ICommonImportProvider provider = getProvider(type);
String executeJson = JsonUtils.toJsonString(JsonUtils.buildObjectMapper(), executeDtoMap);
ImportExecuteSuperDTO executeDto = JsonUtils.toObject(executeJson, executeTypeMap.get(type));
return provider.confirmImport(executeDto);
}
public Page<T> pageDetail(ImportDetailPageDTO importDetailPageDTO) {
String type = importDetailPageDTO.getType();
ICommonImportProvider provider = getProvider(type);
return provider.pageDetail(importDetailPageDTO);
}
public void importDetailExport(ImportDetailPageDTO importDetailPageDTO) {
String type = importDetailPageDTO.getType();
ICommonImportProvider provider = getProvider(type);
provider.importDetailExport(importDetailPageDTO);
}
}

View File

@@ -0,0 +1,100 @@
package com.newyetai.component.commonimport.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.newyetai.codegenerator.util.CodeUtils;
import com.newyetai.common.constant.CommonConstants;
import com.newyetai.common.exception.util.Assert;
import com.newyetai.common.util.ListUtil;
import com.newyetai.common.util.UserContextHolder;
import com.newyetai.component.commonimport.constant.ImportExecuteTypeEnum;
import com.newyetai.component.commonimport.constant.ImportStatusEnum;
import com.newyetai.component.commonimport.dao.ImportMainMapper;
import com.newyetai.component.commonimport.dto.ImportMainCreateDTO;
import com.newyetai.component.commonimport.dto.ImportMainCreateFormDTO;
import com.newyetai.component.commonimport.dto.ImportMainDTO;
import com.newyetai.component.commonimport.dto.ImportMainQueryDTO;
import com.newyetai.component.commonimport.dto.ImportMainUpdateDTO;
import com.newyetai.component.commonimport.entity.UcImportMain;
import com.newyetai.component.commonimport.mapstruct.ImportMainMapMapper;
import com.newyetai.component.commonimport.service.ImportMainService;
import com.newyetai.component.constants.CodeTypeEnum;
/**
* @author sr on 2024-01-19
*/
@Service
public class ImportMainServiceImpl implements ImportMainService {
@Autowired
private ImportMainMapper importMainMapper;
@Override
@Transactional
public Long create(ImportMainCreateDTO createDto) {
Long extraId = createDto.getExtraId();
UcImportMain ucImportMain = ImportMainMapMapper.INSTANCE.to(createDto);
init(ucImportMain);
if (extraId != null) {
ucImportMain.setExecuteType(ImportExecuteTypeEnum.EXTRA_ID.getType());
}
importMainMapper.saveEntity(ucImportMain);
return ucImportMain.getId();
}
private void init(UcImportMain ucImportMain) {
ucImportMain.setImportNo(CodeUtils.getCode(CodeTypeEnum.COMMON_IMPORT));
ucImportMain.setImportStatus(ImportStatusEnum.INIT.getStatus());
ucImportMain.setOrgId(UserContextHolder.getExistLoginOrgId());
}
@Override
@Transactional
public Long createForm(ImportMainCreateFormDTO createDto) {
UcImportMain ucImportMain = ImportMainMapMapper.INSTANCE.to(createDto);
ucImportMain.setExecuteType(ImportExecuteTypeEnum.DETAIL_FORM.getType());
ucImportMain.setFileName("快速发放");
init(ucImportMain);
importMainMapper.saveEntity(ucImportMain);
return ucImportMain.getId();
}
@Override
@Transactional
public void modify(ImportMainUpdateDTO updateDto) {
int num = importMainMapper.modify(updateDto);
Assert.isTrue(num > 0, "修改导入批次失败");
}
@Override
@Transactional
public void remove(Long id) {
importMainMapper.deleteEntity(UcImportMain.builder().id(id).build(),
UserContextHolder.getLoginUserId());
}
@Override
public List<ImportMainDTO> list(ImportMainQueryDTO importMainQueryDTO) {
importMainQueryDTO.disablePage();
return importMainMapper.listImportMainDTO(importMainQueryDTO);
}
@Override
public void page(ImportMainQueryDTO importMainQueryDTO) {
if (!CommonConstants.PLATFORM_ORG_ID.equals(UserContextHolder.getExistLoginOrgId())) {
importMainQueryDTO.setOrgId(UserContextHolder.getExistLoginOrgId());
}
importMainMapper.listImportMainDTO(importMainQueryDTO);
}
@Override
public ImportMainDTO find(ImportMainQueryDTO importMainQueryDTO) {
List<ImportMainDTO> importMainDTOs = this.list(importMainQueryDTO);
return ListUtil.first(importMainDTOs);
}
}

View File

@@ -0,0 +1,29 @@
package com.newyetai.component.constants;
import com.newyetai.codegenerator.pojo.CodeParam;
/**
* @author sr on 2020-08-04
*/
public enum CodeTypeEnum {
/**
* FileClass(备用)
**/
FILE_CLASS(CodeParam.builder().type("FC").build()),
/** 通用导入 **/
COMMON_IMPORT(CodeParam.builder().type("CI").build());
private CodeParam codeParam;
CodeTypeEnum(CodeParam codeParam) {
this.codeParam = codeParam;
}
public CodeParam getCodeParam() {
return this.codeParam;
}
}

View File

@@ -0,0 +1,105 @@
package com.newyetai.component.dict.controller;
import com.newyetai.common.AlitaResult;
import com.newyetai.common.util.UserContextHolder;
import com.newyetai.component.dict.dto.DictDTO;
import com.newyetai.component.dict.dto.DictDetailQueryDTO;
import com.newyetai.component.dict.dto.DictQueryDTO;
import com.newyetai.component.dict.dto.DropdownDictDetailDTO;
import com.newyetai.component.dict.service.DictCacheService;
import com.newyetai.component.dict.service.DictDetailService;
import com.newyetai.component.dict.service.DictService;
import com.newyetai.tkmybatis.pojo.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
/**
*
* @author Rey(leijiaping@newyetai.com)
*
*/
@Api(tags = "字典表")
@RestController
@RequestMapping({"/dict"})
public class DictController {
@Autowired
private DictService dictService;
@Autowired
private DictDetailService dictDetailService;
@Autowired
private DictCacheService dictCacheService;
/**
* 新增
*
* @param dict
*/
@ApiOperation("新增字典")
@PostMapping("create")
public AlitaResult<DictDTO> createDict(@RequestBody DictDTO dict) {
dictService.createDict(dict, UserContextHolder.getLoginUserId());
return AlitaResult.success(dict);
}
/**
* 修改
*
* @param dict
*/
@ApiOperation("修改字典")
@PostMapping("modify")
public AlitaResult<DictDTO> modifyDict(@RequestBody DictDTO dict) {
dictService.modifyDict(dict, UserContextHolder.getLoginUserId());
return AlitaResult.success(dict);
}
/**
* 删除
*
* @param dict
*/
@ApiOperation("删除字典")
@PostMapping("remove")
public AlitaResult<DictDTO> removeDict(@RequestBody DictDTO dict) {
dictService.removeDict(dict, UserContextHolder.getLoginUserId());
return AlitaResult.success(dict);
}
/**
* 查询
*
* @param dict
*/
@ApiOperation("后边页面列出字典-带分页")
@GetMapping("page")
public AlitaResult<Page<DictDTO>> page(DictQueryDTO dict) {
dictService.page(dict);
return AlitaResult.success(dict.getPageResult());
}
/**
* 查询
*
* @param dictDetailDTO
*/
@ApiOperation("列出字典")
@GetMapping("lookup")
public AlitaResult<Collection<DropdownDictDetailDTO>> find(DictDetailQueryDTO dictDetailDTO) {
return AlitaResult.success(dictDetailService.getDropdownDictDetails(dictDetailDTO));
}
@ApiOperation("刷新字典-dictCode")
@GetMapping("flush/{dictCode}")
public AlitaResult<Boolean> flushByDictCode(@PathVariable String dictCode){
dictCacheService.removeTreeDictDetailByCode(dictCode);
return AlitaResult.success(Boolean.TRUE);
}
}

View File

@@ -0,0 +1,45 @@
package com.newyetai.component.dict.dao;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.newyetai.component.dict.dto.DictDetailDTO;
import com.newyetai.component.dict.dto.DictDetailQueryDTO;
import com.newyetai.component.dict.dto.DropdownDictDetailDTO;
import com.newyetai.component.dict.entity.DictDetail;
import com.newyetai.tkmybatis.mybatis.MyMapper;
import com.newyetai.tkmybatis.pojo.Page;
/**
* @author Rey(leijiaping@newyetai.com)
*/
public interface DictDetailMapper extends MyMapper<DictDetail> {
/**
* 查询
*
* @param page 不为空分页
* @param dictDetail
* @return
*/
List<DictDetailDTO> list(Page<DictDetailDTO> page, @Param("param") DictDetailQueryDTO dictDetailQueryDTO);
/**
* 查询
*
* @param dictDetailDTO
* @return
*/
List<DropdownDictDetailDTO> getDropdownDictDetails(@Param("param") DictDetailQueryDTO dictDetailQueryDTO);
/**
* 获取字典编码
*
* @param dictDetailQueryDTO
* @return
* @author sr on 2020-07-30
*/
List<String> getDictCode(@Param("param") DictDetailQueryDTO dictDetailQueryDTO);
}

Some files were not shown because too many files have changed in this diff Show More