feat 增加绑定手机

feat 增加修改手机号码
feat 增加收藏文章功能
This commit is contained in:
damonyuan 2024-10-19 22:44:50 +08:00
parent 9a99d79439
commit 26f965ff03
14 changed files with 190 additions and 76 deletions

View File

@ -0,0 +1,43 @@
package com.mdd.common.enums;
/**
* 相册枚举
*/
public enum LoginEnum {
ACCOUNT_PASSWORD(1, "账号/手机号密码登录"),
MOBILE_CAPTCHA(2, "手机验证码登录"),
THIRD_LOGIN(3, "第三方登录");
/**
* 构造方法
*/
private final int code;
private final String msg;
LoginEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
/**
* 获取状态码
*
* @author fzr
* @return Long
*/
public int getCode() {
return this.code;
}
/**
* 获取提示
*
* @author fzr
* @return String
*/
public String getMsg() {
return this.msg;
}
}

View File

@ -3,7 +3,12 @@ package com.mdd.common.plugin.notice;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mdd.common.entity.notice.NoticeRecord; import com.mdd.common.entity.notice.NoticeRecord;
import com.mdd.common.entity.server.Sys; import com.mdd.common.entity.server.Sys;
import com.mdd.common.entity.smsLog.SmsLog;
import com.mdd.common.enums.NoticeEnum;
import com.mdd.common.enums.SmsEnum;
import com.mdd.common.enums.YesNoEnum;
import com.mdd.common.mapper.notice.NoticeRecordMapper; import com.mdd.common.mapper.notice.NoticeRecordMapper;
import com.mdd.common.mapper.smsLog.SmsLogMapper;
import com.mdd.common.util.SpringUtils; import com.mdd.common.util.SpringUtils;
import com.mdd.common.util.StringUtils; import com.mdd.common.util.StringUtils;
@ -14,28 +19,40 @@ import javax.annotation.Resource;
*/ */
public class NoticeCheck { public class NoticeCheck {
public static Boolean verify(Integer scene, Object code) { public static Boolean verify(Integer sceneId, String code, String mobile) {
NoticeRecordMapper noticeRecordMapper = SpringUtils.getBean(NoticeRecordMapper.class);
NoticeRecord noticeRecord = noticeRecordMapper.selectOne(new QueryWrapper<NoticeRecord>() SmsLogMapper smsLogMapper = SpringUtils.getBean(SmsLogMapper.class);
.eq("scene", scene) QueryWrapper queryWrapper = new QueryWrapper();
.eq("status", 1) queryWrapper.eq("mobile", mobile);
.eq("is_read", 0) queryWrapper.eq("send_status", SmsEnum.SEND_SUCCESS.getCode());
.eq("is_captcha", 1) queryWrapper.in("scene_id", NoticeEnum.getSmsScene());
.eq("is_delete", 0) queryWrapper.eq("is_verify", YesNoEnum.NO.getCode());
.eq("code", code.toString().toLowerCase()) if (sceneId.equals(0) == false) {
.last("limit 1")); queryWrapper.eq("scene_id", sceneId);
}
queryWrapper.orderByDesc("send_time");
queryWrapper.last("limit 1");
SmsLog smsLog = smsLogMapper.selectOne(queryWrapper);
if (StringUtils.isNull(noticeRecord)) { if (StringUtils.isNull(smsLog)) {
return false; return false;
} }
boolean result = noticeRecord.getCreateTime() > ((System.currentTimeMillis() / 1000) - (5 * 60)); //5分钟有效 // 没有验证码 最新验证码已校验 已过期(有效期5分钟)
if (smsLog.getIsVerify().equals(1) || smsLog.getSendTime() < System.currentTimeMillis() / 1000 - (5*60)) {
return false;
}
noticeRecord.setRead(1); // 更新校验状态
noticeRecord.setUpdateTime(System.currentTimeMillis() / 1000); smsLog.setCheckNum(smsLog.getCheckNum() + 1);
noticeRecordMapper.updateById(noticeRecord); if (smsLog.getCode().equals(code)) {
return result; smsLog.setIsVerify(YesNoEnum.YES.getCode());
smsLogMapper.updateById(smsLog);
return true;
} else {
smsLogMapper.updateById(smsLog);
return false;
}
} }
} }

View File

@ -58,7 +58,7 @@ public class ArticleController {
return AjaxResult.success(vo); return AjaxResult.success(vo);
} }
@GetMapping("/collectList") @GetMapping("/collect")
@ApiOperation(value="收藏列表") @ApiOperation(value="收藏列表")
public AjaxResult<PageResult<ArticleCollectVo>> collect(@Validated PageValidate pageValidate) { public AjaxResult<PageResult<ArticleCollectVo>> collect(@Validated PageValidate pageValidate) {
Integer userId = LikeFrontThreadLocal.getUserId(); Integer userId = LikeFrontThreadLocal.getUserId();
@ -70,17 +70,17 @@ public class ArticleController {
@PostMapping("/addCollect") @PostMapping("/addCollect")
@ApiOperation(value="收藏加入") @ApiOperation(value="收藏加入")
public AjaxResult<Object> addCollect(@Validated @RequestBody ArticleCollectValidate collectValidate) { public AjaxResult<Object> addCollect(@Validated @RequestBody ArticleCollectValidate collectValidate) {
Integer articleId = collectValidate.getArticleId(); Integer articleId = collectValidate.getId();
Integer userId = LikeFrontThreadLocal.getUserId(); Integer userId = LikeFrontThreadLocal.getUserId();
iArticleService.addCollect(articleId, userId); iArticleService.addCollect(articleId, userId);
return AjaxResult.success(); return AjaxResult.success();
} }
@PostMapping("/collectCancel") @PostMapping("/cancelCollect")
@ApiOperation(value="收藏取消") @ApiOperation(value="收藏取消")
public AjaxResult<Object> cancelCollect(@Validated @RequestBody ArticleCollectValidate collectValidate) { public AjaxResult<Object> cancelCollect(@Validated @RequestBody ArticleCollectValidate collectValidate) {
Integer articleId = collectValidate.getArticleId(); Integer articleId = collectValidate.getId();
Integer userId = LikeFrontThreadLocal.getUserId(); Integer userId = LikeFrontThreadLocal.getUserId();
iArticleService.cancelCollect(articleId, userId); iArticleService.cancelCollect(articleId, userId);

View File

@ -44,25 +44,22 @@ public class LoginController {
@PostMapping("/account") @PostMapping("/account")
@ApiOperation(value="账号登录") @ApiOperation(value="账号登录")
public AjaxResult<LoginTokenVo> account(@Validated @RequestBody LoginPwdValidate loginPwdValidate) { public AjaxResult<LoginTokenVo> account(@Validated @RequestBody LoginPwdValidate loginPwdValidate) {
Integer terminal = LikeFrontThreadLocal.getTerminal(); loginPwdValidate.setTerminal(LikeFrontThreadLocal.getTerminal());
String account = loginPwdValidate.getAccount(); LoginTokenVo vo = iLoginService.accountLogin(loginPwdValidate);
String password = loginPwdValidate.getPassword();
LoginTokenVo vo = iLoginService.accountLogin(account, password, terminal);
return AjaxResult.success(vo); return AjaxResult.success(vo);
} }
@NotLogin // @NotLogin
@PostMapping("/mobileLogin") // @PostMapping("/mobileLogin")
@ApiOperation(value="手机登录") // @ApiOperation(value="手机登录")
public AjaxResult<LoginTokenVo> mobileLogin(@Validated @RequestBody LoginPhoneValidate loginPhoneValidate) { // public AjaxResult<LoginTokenVo> mobileLogin(@Validated @RequestBody LoginPhoneValidate loginPhoneValidate) {
Integer terminal = LikeFrontThreadLocal.getTerminal(); // Integer terminal = LikeFrontThreadLocal.getTerminal();
String mobile = loginPhoneValidate.getMobile(); // String mobile = loginPhoneValidate.getMobile();
String code = loginPhoneValidate.getCode(); // String code = loginPhoneValidate.getCode();
//
LoginTokenVo vo = iLoginService.mobileLogin(mobile, code, terminal); // LoginTokenVo vo = iLoginService.mobileLogin(mobile, code, terminal);
return AjaxResult.success(vo); // return AjaxResult.success(vo);
} // }
@NotLogin @NotLogin
@PostMapping("/mnpLogin") @PostMapping("/mnpLogin")

View File

@ -2,6 +2,7 @@ package com.mdd.front.controller;
import com.mdd.common.aop.NotLogin; import com.mdd.common.aop.NotLogin;
import com.mdd.common.core.AjaxResult; import com.mdd.common.core.AjaxResult;
import com.mdd.common.exception.OperateException;
import com.mdd.front.LikeFrontThreadLocal; import com.mdd.front.LikeFrontThreadLocal;
import com.mdd.front.service.IUserService; import com.mdd.front.service.IUserService;
import com.mdd.front.validate.users.*; import com.mdd.front.validate.users.*;
@ -50,11 +51,14 @@ public class UserController {
return AjaxResult.success(); return AjaxResult.success();
} }
@PostMapping("/changePwd") @PostMapping("/changePassword")
@ApiOperation(value="修改密码") @ApiOperation(value="修改密码")
public AjaxResult<Object> changePwd(@Validated @RequestBody UserChangePwdValidate passwordValidate) { public AjaxResult<Object> changePassword(@Validated @RequestBody UserChangePwdValidate passwordValidate) {
Integer userId = LikeFrontThreadLocal.getUserId(); Integer userId = LikeFrontThreadLocal.getUserId();
if (passwordValidate.getPassword().equals(passwordValidate.getPasswordConfirm()) == false) {
throw new OperateException("两次输入的密码不一致");
}
iUserService.changePwd(passwordValidate.getPassword(), passwordValidate.getOldPassword(), userId); iUserService.changePwd(passwordValidate.getPassword(), passwordValidate.getOldPassword(), userId);
return AjaxResult.success(); return AjaxResult.success();
} }

View File

@ -1,5 +1,6 @@
package com.mdd.front.service; package com.mdd.front.service;
import com.mdd.front.validate.login.LoginPwdValidate;
import com.mdd.front.vo.login.LoginTokenVo; import com.mdd.front.vo.login.LoginTokenVo;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
@ -28,7 +29,7 @@ public interface ILoginService {
* @param terminal 终端 * @param terminal 终端
* @return LoginTokenVo * @return LoginTokenVo
*/ */
LoginTokenVo accountLogin(String account, String password, Integer terminal); LoginTokenVo accountLogin(LoginPwdValidate loginPwdValidate);
/** /**
* 手机登录 * 手机登录
@ -39,7 +40,7 @@ public interface ILoginService {
* @param terminal 终端 * @param terminal 终端
* @return LoginTokenVo * @return LoginTokenVo
*/ */
LoginTokenVo mobileLogin(String mobile, String code, Integer terminal); LoginTokenVo mobileLogin(String mobile, String code, Integer terminal, Integer sceneId);
/** /**
* 微信登录 * 微信登录

View File

@ -201,24 +201,26 @@ public class ArticleServiceImpl implements IArticleService {
Integer pageNo = pageValidate.getPage_no(); Integer pageNo = pageValidate.getPage_no();
Integer pageSize = pageValidate.getPage_size(); Integer pageSize = pageValidate.getPage_size();
MPJQueryWrapper<ArticleCollect> mpjQueryWrapper = new MPJQueryWrapper<>(); MPJQueryWrapper<Article> mpjQueryWrapper = new MPJQueryWrapper<>();
mpjQueryWrapper.select("t.id,t.article_id,a.title,a.image,a.intro,a.visit,a.create_time") mpjQueryWrapper.setAlias("a").select("c.id,c.article_id,a.title,a.image,a.desc,a.is_show,a.click_virtual, a.click_actual,a.create_time, c.create_time as collect_time")
.eq("t.user_id", userId) .eq("c.user_id", userId)
.isNull("t.delete_time") .isNull("c.delete_time")
.isNull("a.delete_time") .isNull("a.delete_time")
.orderByDesc("t.id") .eq("c.status", YesNoEnum.YES.getCode())
.innerJoin("?_article a ON a.id=t.article_id".replace("?_", GlobalConfig.tablePrefix)); .eq("a.is_show", YesNoEnum.YES.getCode())
.orderByDesc("c.id")
.innerJoin("?_article_collect c ON c.article_id=a.id".replace("?_", GlobalConfig.tablePrefix));
IPage<ArticleCollectVo> iPage = articleCollectMapper.selectJoinPage( IPage<ArticleCollectVo> iPage = articleMapper.selectJoinPage(
new Page<>(pageNo, pageSize), new Page<>(pageNo, pageSize),
ArticleCollectVo.class, ArticleCollectVo.class,
mpjQueryWrapper); mpjQueryWrapper);
for (ArticleCollectVo vo : iPage.getRecords()) { for (ArticleCollectVo vo : iPage.getRecords()) {
vo.setImage(UrlUtils.toAbsoluteUrl(vo.getImage())); vo.setImage(UrlUtils.toAbsoluteUrl(vo.getImage()));
vo.setCreateTime(TimeUtils.timestampToDate(vo.getCreateTime())); vo.setCreateTime(TimeUtils.timestampToDate(Long.valueOf(vo.getCreateTime().toString())));
vo.setCollectTime(TimeUtils.timestampToDate(Long.valueOf(vo.getCollectTime().toString())));
} }
return PageResult.iPageHandle(iPage); return PageResult.iPageHandle(iPage);
} }
@ -240,7 +242,7 @@ public class ArticleServiceImpl implements IArticleService {
if (StringUtils.isNotNull(articleCollect)) { if (StringUtils.isNotNull(articleCollect)) {
articleCollect.setUpdateTime(System.currentTimeMillis() / 1000); articleCollect.setUpdateTime(System.currentTimeMillis() / 1000);
articleCollect.setStatus(YesNoEnum.NO.getCode()); articleCollect.setStatus(YesNoEnum.YES.getCode());
articleCollectMapper.updateById(articleCollect); articleCollectMapper.updateById(articleCollect);
} else { } else {
ArticleCollect model = new ArticleCollect(); ArticleCollect model = new ArticleCollect();

View File

@ -3,10 +3,12 @@ package com.mdd.front.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert; import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.mdd.common.entity.user.User; import com.mdd.common.entity.user.User;
import com.mdd.common.entity.user.UserAuth; import com.mdd.common.entity.user.UserAuth;
import com.mdd.common.enums.LoginEnum;
import com.mdd.common.enums.NoticeEnum; import com.mdd.common.enums.NoticeEnum;
import com.mdd.common.exception.OperateException; import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.user.UserAuthMapper; import com.mdd.common.mapper.user.UserAuthMapper;
@ -17,6 +19,7 @@ import com.mdd.common.util.*;
import com.mdd.front.cache.ScanLoginCache; import com.mdd.front.cache.ScanLoginCache;
import com.mdd.front.cache.TokenLoginCache; import com.mdd.front.cache.TokenLoginCache;
import com.mdd.front.service.ILoginService; import com.mdd.front.service.ILoginService;
import com.mdd.front.validate.login.LoginPwdValidate;
import com.mdd.front.vo.login.LoginTokenVo; import com.mdd.front.vo.login.LoginTokenVo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
@ -91,18 +94,36 @@ public class LoginServiceImpl implements ILoginService {
* @return LoginTokenVo * @return LoginTokenVo
*/ */
@Override @Override
public LoginTokenVo accountLogin(String account, String password, Integer terminal) { public LoginTokenVo accountLogin(LoginPwdValidate loginPwdValidate) {
User user = userMapper.selectOne(new QueryWrapper<User>() JSONArray config = JSONArray.parseArray(ConfigUtils.get("login", "login_way", "[]"));
.eq("account", account) if (config.contains(loginPwdValidate.getScene().toString()) == false) {
.isNull("delete_time") throw new OperateException("不支持的登录方式");
.last("limit 1")); }
Assert.notNull(user, "账号不存在!"); String account = loginPwdValidate.getAccount();
String pwd = ToolUtils.makePassword(password); String password = loginPwdValidate.getPassword();
Assert.isFalse(!pwd.equals(user.getPassword()), "账号或密码错误!"); Integer terminal = loginPwdValidate.getTerminal();
Assert.isFalse(!user.getIsDisable().equals(0), "账号已被禁用!"); String code = loginPwdValidate.getCode();
Integer sceneId = loginPwdValidate.getScene();
// 账号密码登录
if (loginPwdValidate.getScene().equals(LoginEnum.ACCOUNT_PASSWORD.getCode())) {
User user = userMapper.selectOne(new QueryWrapper<User>()
.nested(wq->wq
.like("account", account).or()
.like("mobile", account).or()
)
.isNull("delete_time")
.last("limit 1"));
return this.__loginToken(user.getId(), user.getMobile(), user.getIsNewUser(), terminal); Assert.notNull(user, "账号不存在!");
String pwd = ToolUtils.makePassword(password);
Assert.isFalse(!pwd.equals(user.getPassword()), "账号或密码错误!");
Assert.isFalse(!user.getIsDisable().equals(0), "账号已被禁用!");
return this.__loginToken(user.getId(), user.getMobile(), user.getIsNewUser(), terminal);
} else {
return mobileLogin(account, code, terminal, sceneId);
}
} }
/** /**
@ -114,18 +135,18 @@ public class LoginServiceImpl implements ILoginService {
* @return LoginTokenVo * @return LoginTokenVo
*/ */
@Override @Override
public LoginTokenVo mobileLogin(String mobile, String code, Integer terminal) { public LoginTokenVo mobileLogin(String mobile, String code, Integer terminal, Integer sceneId) {
// 校验验证码 // 校验验证码
int sceneCode = NoticeEnum.LOGIN_CAPTCHA.getCode(); int sceneCode = NoticeEnum.LOGIN_CAPTCHA.getCode();
if (!NoticeCheck.verify(sceneCode, code)) { if (!NoticeCheck.verify(sceneCode, code, mobile)) {
throw new OperateException("验证码错误!"); throw new OperateException("验证码错误!");
} }
// 查询手机号 // 查询手机号
User user = userMapper.selectOne(new QueryWrapper<User>() User user = userMapper.selectOne(new QueryWrapper<User>()
.select("id,username,mobile,is_disable,is_new") .select("id,account,mobile,is_disable,is_new_user")
.eq("mobile", mobile) .eq("mobile", mobile)
.eq("is_delete", 0) .isNull("delete_time")
.last("limit 1")); .last("limit 1"));
Assert.notNull(user, "账号不存在!"); Assert.notNull(user, "账号不存在!");
@ -328,7 +349,7 @@ public class LoginServiceImpl implements ILoginService {
User user = null; User user = null;
if (StringUtils.isNotNull(userAuth)) { if (StringUtils.isNotNull(userAuth)) {
user = userMapper.selectOne(new QueryWrapper<User>() user = userMapper.selectOne(new QueryWrapper<User>()
.eq("is_delete", 0) .isNull("delete_time")
.eq("id", userAuth.getUserId()) .eq("id", userAuth.getUserId())
.last("limit 1")); .last("limit 1"));
} }

View File

@ -192,7 +192,7 @@ public class UserServiceImpl implements IUserService {
@Override @Override
public void changePwd(String password, String oldPassword, Integer userId) { public void changePwd(String password, String oldPassword, Integer userId) {
User user = userMapper.selectOne(new QueryWrapper<User>() User user = userMapper.selectOne(new QueryWrapper<User>()
.select("id,password,salt") .select("id,password")
.eq("id", userId) .eq("id", userId)
.isNull("delete_time") .isNull("delete_time")
.last("limit 1")); .last("limit 1"));
@ -228,7 +228,7 @@ public class UserServiceImpl implements IUserService {
public void forgotPwd(String password, String mobile, String code) { public void forgotPwd(String password, String mobile, String code) {
// 校验验证码 // 校验验证码
int sceneCode = NoticeEnum.FIND_LOGIN_PASSWORD_CAPTCHA.getCode(); int sceneCode = NoticeEnum.FIND_LOGIN_PASSWORD_CAPTCHA.getCode();
if (!NoticeCheck.verify(sceneCode, code)) { if (!NoticeCheck.verify(sceneCode, code, mobile)) {
throw new OperateException("验证码错误!"); throw new OperateException("验证码错误!");
} }
@ -266,7 +266,7 @@ public class UserServiceImpl implements IUserService {
// 校验验证码 // 校验验证码
int sceneCode = type.equals("bind") ? NoticeEnum.BIND_MOBILE_CAPTCHA.getCode() : NoticeEnum.CHANGE_MOBILE_CAPTCHA.getCode() ; int sceneCode = type.equals("bind") ? NoticeEnum.BIND_MOBILE_CAPTCHA.getCode() : NoticeEnum.CHANGE_MOBILE_CAPTCHA.getCode() ;
if (!NoticeCheck.verify(sceneCode, code)) { if (!NoticeCheck.verify(sceneCode, code, mobile)) {
throw new OperateException("验证码错误!"); throw new OperateException("验证码错误!");
} }

View File

@ -17,6 +17,6 @@ public class ArticleCollectValidate implements Serializable {
@NotNull(message = "articleId参数缺失") @NotNull(message = "articleId参数缺失")
@IDMust(message = "articleId参数必须大于0") @IDMust(message = "articleId参数必须大于0")
@ApiModelProperty(value = "文章ID", required = true) @ApiModelProperty(value = "文章ID", required = true)
private Integer articleId; private Integer id;
} }

View File

@ -16,9 +16,16 @@ public class LoginPwdValidate {
@ApiModelProperty(value = "登录账号", required = true) @ApiModelProperty(value = "登录账号", required = true)
private String account; private String account;
@NotNull(message = "password参数缺失") @ApiModelProperty(value = "登录密码")
@NotEmpty(message = "密码不能为空")
@ApiModelProperty(value = "登录密码", required = true)
private String password; private String password;
@ApiModelProperty(value = "验证码登录")
private String code;
@ApiModelProperty(value = "终端")
private Integer scene;
@ApiModelProperty(value = "终端")
private Integer terminal;
} }

View File

@ -19,6 +19,11 @@ public class UserChangePwdValidate implements Serializable {
@ApiModelProperty(value = "新密码", required = true) @ApiModelProperty(value = "新密码", required = true)
private String password; private String password;
@NotNull(message = "请确认密码")
@Pattern(message = "确认密码密码必须是6-20字母+数字组合!", regexp="^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$")
@ApiModelProperty(value = "确认密码", required = true)
private String passwordConfirm;
@NotNull(message = "oldPassword参数缺失") @NotNull(message = "oldPassword参数缺失")
@NotNull(message = "旧密码不能为空") @NotNull(message = "旧密码不能为空")
@ApiModelProperty(value = "旧密码", required = true) @ApiModelProperty(value = "旧密码", required = true)

View File

@ -1,5 +1,6 @@
package com.mdd.front.vo.article; package com.mdd.front.vo.article;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
@ -25,12 +26,28 @@ public class ArticleCollectVo implements Serializable {
private String image; private String image;
@ApiModelProperty(value = "文章简介") @ApiModelProperty(value = "文章简介")
private String intro; private String desc;
@ApiModelProperty(value = "浏览数量") @ApiModelProperty(value = "是否显示:1-是.0-否")
private Integer visit; private Integer isShow;
@ApiModelProperty(value = "虚拟浏览量")
private Integer clickVirtual;
@ApiModelProperty(value = "实际浏览量")
private Integer clickActual;
@ApiModelProperty(value = "创建时间") @ApiModelProperty(value = "创建时间")
private String createTime; private Object createTime;
@ApiModelProperty(value = "收集时间")
private Object collectTime;
// @ApiModelProperty(value = "创建时间")
// @JsonProperty("create_time")
// private String createTimeStr;
//
// @ApiModelProperty(value = "收集时间")
// @JsonProperty("collect_time")
// private String collectTimeStr;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB