业务场景: 当前有个需求,在一个问题表单中,一般我们的列都是固定的展示哪些列,那么现在用户需要自定义自己的一个列头,不同用户关注的表单字段信息不一样,比如用户A关注问题细节,只想展示几列字段,而用户B关注整体,那么就想展示全部十几列字段。
解决思路:我们前端会设置按钮,展示问题表单全部字段,每个字段左侧有个方框勾选,去给用户勾选自己想展示的列,勾选了十列,就展示十个列数据。
这里不同用户的判断,前提是我们系统中是做好了SSO单点登录,前端发起的每个接口都会先经过过滤器,判断当前用户是否登录,如果登录了,浏览器就会保存用户相关信息在cookies中,后续每次请求,都会带上这个信息,后端拿到信息可以判断当前用户登录,并且返回完整用户信息,这里不展开用户信息接口,只展开对数据表单列头的控制
思路解析:
1.一开始是默认展示整个表单字段列信息,返回给前端,然后在前端配置按钮,进行勾选,保存后,表格字段就会刷新成被勾选的字段列展示,再点击按钮再修改,那么就会再刷新展示对应的字段列
2.从需求上可以看出,我们需要在后台保存每个用户自定义勾选了哪些字段,这里就有两个核心字段,当然表默认都要有个自增id,以及插入数据的创建时间;另外用户还可以多次修改勾选的字段,修改时间字段我们也可以加上; 表中还有一个标识字段data_type, 主要是当前业务有两个问题表单管理,一个是前端问题单 一个是后端问题单,两个前台页面,都有相同需求,所以增加一个字段来标识0,1 ; 判断是哪个页面设置的。
3.所以应该需要设计两个接口:
一个是返回当前用户选择的自定义列信息
一个是更新当前用户选择的自定义列信息
package com.xxx.model;
import java.util.Objects;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class ProdProblemWarnCol implements Serializable {
private static final long serialVersionUID = 1L;
@JsonProperty("checkedCol")
private String checkedCol = null;
@JsonProperty("userCn")
private String userCn = null;
@JsonProperty("DataType")
private String dataType = null;
public ProdProblemWarnCol() {
super();
}
/**
* 配置展示字段
**/
public String getCheckedCol() {
return checkedCol;
}
public void setCheckedCol(String checkedCol) {
this.checkedCol = checkedCol;
}
/**
* 用户
**/
public String getUserCn() {
return userCn;
}
public void setUserCn(String userCn) {
this.userCn = userCn;
}
/**
* 类型,用于区分页面,0:前端问题,1:后端问题
**/
public String getDataType() {
return dataType;
}
public void setDataType(String dataType) {
this.dataType = dataType;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ProdProblemWarnCol prodProblemWarnCol = (ProdProblemWarnCol) o;
return Objects.equals(this.checkedCol,
prodProblemWarnCol.checkedCol)
&& Objects.equals(this.userCn,
prodProblemWarnCol.userCn)
&& Objects.equals(this.dataType,
prodProblemWarnCol.dataType);
}
@Override
public int hashCode() {
return Objects.hash(checkedCol
, userCn
, dataType);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class ProdProblemWarnCol { ");
sb.append(" checkedCol: ").append(checkedCol).append(", ");
sb.append(" userCn: ").append(userCn).append(", ");
sb.append(" dataType: ").append(dataType).append(", ");
sb.append("} ");
return sb.toString();
}
}
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@NoArgsConstructor
@TableName("col_f")
public class MtDistributionColF implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "ID", type = IdType.AUTO)
private Integer id;
/**
* 字段配置,英文逗号分隔
*/
@TableField("CHECKED_COL")
private String checkedCol;
/**
* 用户
*/
@TableField("USER_CN")
private String userCn;
/**
* 类型,用于区分页面,0:前端问题单表,1:后端问题单表
*/
@TableField("DATA_TYPE")
private String dataType;
/**
* 创建时间
*/
@TableField("CREATION_DATE")
private Date creationDate;
/**
* 更新时间
*/
@TableField("LAST_UPDATE_DATE")
private Date lastUpdateDate;
}
@RestController
@RequestMapping(value = "/ProdProblemWarn", produces = {"application/json;charset=UTF-8"})
@Validated
public class ProdProblemWarnController {
@Autowired(required=false)
private ProdProblemWarnService delegate;
@RequestMapping(
value = "/getUserCol",
produces = { "application/json" },
method = RequestMethod.GET)
public ResponseVo getUserCol( @RequestParam(value = "user", required = true) String user)
throws ServiceException {
return delegate.getUserCol(user);
}
@RequestMapping(
value = "/saveUserCol",
produces = { "application/json" },
method = RequestMethod.POST)
public ResponseVo saveUserCol(@RequestBody ProdProblemWarnCol warnCol)
throws ServiceException {
return delegate.saveUserCol(warnCol);
}
}
public interface ProdProblemWarnService {
ResponseVo getUserCol(String user);
ResponseVo saveUserCol(ProdProblemWarnCol warnCol);
}
@Slf4j
public class ProdProblemWarnServiceImpl implements ProdProblemWarnService {
@Resource
private FieldConfigService FieldConfigService;
@Override
public ResponseVo getUserCol(String user) {
//调用字段配置服务接口,把前端传递的user用户信息传递,查询该用户的勾选配置字段
return ResponseUtils.successResponse(FieldConfigService.getUserCol(user, "1"), "获取数据成功");
}
@Override
public ResponseVo saveUserCol(ProdProblemWarnCol warnCol) {
//创建一个实体类接收数据 由于这个saveUserCol接口是最先开发的前端问题的配置字段,
//为了规范 这里后端问题配置字段 另外用ProdProblemWarnCol 实体类接收了,实际上与
//DistributionWarnCol类是一样的属性
DistributionWarnCol param = new DistributionWarnCol();
//将对象拷贝给param 然后传递到 FieldConfigService.saveUserCol入参
MyBeanUtils.shallowCopy(warnCol, param);
param.setDataType("1");
FieldConfigService.saveUserCol(param);
return ResponseUtils.successResponse(null, "保存数据成功");
}
}
public interface FieldConfigService extends IService {
MtDistributionColF getUserCol(String user, String dataType);
void saveUserCol(DistributionWarnCol warnCol);
}
@Slf4j
@Component
public class MatWarnFieldConfigServiceImpl extends ServiceImpl
implements FieldConfigService {
@Override
public MtDistributionColF getUserCol(String user, String dataType) {
//查询 前端传递的用户 对应的一条配置字段记录 一个用户一个datatype页面仅有一条记录
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("USER_CN", user);
wrapper.eq("Data_TYPE", dataType);
return baseMapper.selectOne(wrapper);
}
@Override
public void saveUserCol(DistributionWarnCol warnCol) {
QueryWrapper wrapper = new QueryWrapper<>();
//先查询表中是否存在对应用户,表单页面类型的记录count
wrapper.eq("USER_CN", warnCol.getUserCn());
wrapper.eq("DATA_TYPE", warnCol.getDataType());
Long count = baseMapper.selectCount(wrapper);
//创建对应表实体类对象 将前端传参对象拷贝过去
MtDistributionColF target = new MtDistributionColF();
MyBeanUtils.shallowCopy(warnCol, target);
//如果表中存在有该用户的一条记录 那么就进行更新操作 刷新更新时间字段
if (count > 0) {
LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(MtDistributionColF::getUserCn, warnCol.getUserCn())
.set(MtDistributionColF::getCheckedCol, warnCol.getCheckedCol())
.set(MtDistributionColF::getLastUpdateDate, new Date());
baseMapper.update(null, updateWrapper);
} else {
//如果表中不存在,那么就插入target 转换好的对象 把创建时间也添加系统时间
target.setCreationDate(new Date());
target.setLastUpdateDate(new Date());
baseMapper.insert(target);
}
}
}
没有需要自定义的接口,但是也是需要定义的,规范需要 在实现类中集成的 泛型对象就需要传递mapper接口
@Mapper
public interface MtDistributionColMapper extends BaseMapper {
}