|
|
@@ -0,0 +1,693 @@
|
|
|
+package cn.hobbystocks.auc.web;
|
|
|
+
|
|
|
+import cn.hobbystocks.auc.app.AppClient;
|
|
|
+import cn.hobbystocks.auc.cache.CacheMap;
|
|
|
+import cn.hobbystocks.auc.common.constant.Constants;
|
|
|
+import cn.hobbystocks.auc.common.core.controller.BaseController;
|
|
|
+import cn.hobbystocks.auc.common.core.domain.AjaxResult;
|
|
|
+import cn.hobbystocks.auc.common.core.redis.RedisCache;
|
|
|
+import cn.hobbystocks.auc.common.core.text.Convert;
|
|
|
+import cn.hobbystocks.auc.common.exception.AddPriceException;
|
|
|
+import cn.hobbystocks.auc.common.exception.LockException;
|
|
|
+import cn.hobbystocks.auc.common.user.UserInfo;
|
|
|
+import cn.hobbystocks.auc.common.user.UserUtils;
|
|
|
+import cn.hobbystocks.auc.common.utils.CloneUtils;
|
|
|
+import cn.hobbystocks.auc.common.utils.PaginationUtil;
|
|
|
+import cn.hobbystocks.auc.common.utils.SensitiveDataUtils;
|
|
|
+import cn.hobbystocks.auc.domain.*;
|
|
|
+import cn.hobbystocks.auc.event.EventPublisher;
|
|
|
+import cn.hobbystocks.auc.forest.CommonForestClient;
|
|
|
+import cn.hobbystocks.auc.handle.RuleHandlerHolder;
|
|
|
+import cn.hobbystocks.auc.handle.context.Live;
|
|
|
+import cn.hobbystocks.auc.handle.context.LiveContext;
|
|
|
+import cn.hobbystocks.auc.mapper.BidRecordMapper;
|
|
|
+import cn.hobbystocks.auc.service.IBidService;
|
|
|
+import cn.hobbystocks.auc.service.ILotService;
|
|
|
+import cn.hobbystocks.auc.service.IOrderStatusService;
|
|
|
+import cn.hobbystocks.auc.vo.BidVO;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.dtflys.forest.http.ForestResponse;
|
|
|
+import com.github.pagehelper.Page;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import com.google.common.collect.Maps;
|
|
|
+import com.google.common.collect.Sets;
|
|
|
+import io.swagger.annotations.Api;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.util.CollectionUtils;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 出价
|
|
|
+ */
|
|
|
+@RestController
|
|
|
+@RequestMapping({"/bid/bidding"})
|
|
|
+@Slf4j
|
|
|
+@Api(tags = "出价相关接口")
|
|
|
+public class BidingController extends BaseController {
|
|
|
+
|
|
|
+ // region Params
|
|
|
+
|
|
|
+ @Value("${hobbystocks.host.pointUrl}")
|
|
|
+ private String pointUrl;
|
|
|
+ @Autowired
|
|
|
+ private CommonForestClient client;
|
|
|
+ @Autowired
|
|
|
+ private IBidService bidService;
|
|
|
+ @Autowired
|
|
|
+ private ILotService lotService;
|
|
|
+ @Autowired
|
|
|
+ private AppClient appClient;
|
|
|
+ @Autowired
|
|
|
+ private EventPublisher eventPublisher;
|
|
|
+ @Autowired
|
|
|
+ private CacheMap cacheMap;
|
|
|
+ @Autowired
|
|
|
+ private BidRecordMapper bidRecordMapper;
|
|
|
+ @Autowired
|
|
|
+ private RedisCache redisCache;
|
|
|
+ @Autowired
|
|
|
+ private RuleHandlerHolder ruleHandlerHolder;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IOrderStatusService orderStatusService;
|
|
|
+ // endregion
|
|
|
+
|
|
|
+ // region Controllers
|
|
|
+
|
|
|
+ @ApiOperation("同步数据")
|
|
|
+ @PostMapping("/sync")
|
|
|
+ public AjaxResult sync() {
|
|
|
+ eventPublisher.sync();
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("调用积分接口处理积分变动")
|
|
|
+ @PostMapping("/point")
|
|
|
+ public AjaxResult point(@RequestBody Map<String, Object> map) {
|
|
|
+ ForestResponse<CommonForestClient.Response<Map<String, Object>>> response =
|
|
|
+ client.sendPost(pointUrl, Maps.newHashMap(), map);
|
|
|
+ if (Objects.nonNull(response) && Objects.equals(response.getStatusCode(), 200) && Objects.equals(response.getResult().getCode(), 0)) {
|
|
|
+ return AjaxResult.success();
|
|
|
+ }else {
|
|
|
+ throw new RuntimeException();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("积分拍卖增加价格")
|
|
|
+ @PostMapping("/addPrice")
|
|
|
+ public AjaxResult addPrice(@RequestBody BidVO bid) {
|
|
|
+ log.info("add price {}", bid);
|
|
|
+
|
|
|
+ UserInfo userInfo = UserUtils.getUserInfo();
|
|
|
+
|
|
|
+ // 创建bidRecord
|
|
|
+ bid.setCreateBy(userInfo.getSub());
|
|
|
+ bid.setAccount(userInfo.getAccount());
|
|
|
+ String accountId = String.valueOf(userInfo.getId());
|
|
|
+ bid.setAccountId(accountId);
|
|
|
+ bid.setAvatar(userInfo.getAvatar());
|
|
|
+ bid.setBidNo(UUID.randomUUID().toString());
|
|
|
+ Long recordId = createBidRecord(bid);
|
|
|
+ Lot lot = lotService.selectLotById(bid.getLotId());
|
|
|
+ // 判断拍卖状态
|
|
|
+ String error = checkLotStatus(bid);
|
|
|
+ if (StringUtils.hasLength(error)) {
|
|
|
+ return AjaxResult.error(error);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!userInfo.isHasAddress()) {
|
|
|
+ return AjaxResult.error("请先添加地址");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ bidService.addPrice(bid,
|
|
|
+ () -> point(bid) // 这里处理积分相关的
|
|
|
+ );
|
|
|
+ }catch (RuntimeException e) {
|
|
|
+ log.error("addPrice error {}", bid, e);
|
|
|
+ if (e instanceof LockException) {
|
|
|
+ return AjaxResult.error("商品当前积分已变动");
|
|
|
+ }else if (e instanceof AddPriceException) {
|
|
|
+ return AjaxResult.error(e.getMessage());
|
|
|
+ }else {
|
|
|
+ return AjaxResult.error("出价失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @ApiOperation("出价拍卖增加价格")
|
|
|
+ @PostMapping({"/v2/addPrice"})
|
|
|
+ public AjaxResult addPriceV2(@RequestBody BidVO bid) {
|
|
|
+ bid.setAuctionId(2L);
|
|
|
+ log.info("add price {}", bid);
|
|
|
+ // 创建bidRecord
|
|
|
+ UserInfo userInfo = UserUtils.getUserInfo();
|
|
|
+ // 创建bidRecord
|
|
|
+ bid.setCreateBy(userInfo.getSub());
|
|
|
+ bid.setAccount(userInfo.getAccount());
|
|
|
+ String accountId = String.valueOf(userInfo.getId());
|
|
|
+ bid.setAccountId(accountId);
|
|
|
+ bid.setAvatar(userInfo.getAvatar());
|
|
|
+ bid.setBidNo(UUID.randomUUID().toString());
|
|
|
+ Long recordId = createBidRecord(bid);
|
|
|
+
|
|
|
+ if (Objects.equals(2, userInfo.getAccountStatus())) {
|
|
|
+ return AjaxResult.error("暂时无法参与当前竞价");
|
|
|
+ }
|
|
|
+ if (!Objects.equals(1, userInfo.getFaceVerify()) && !bid.getTest()) {
|
|
|
+ return AjaxResult.error("请先进行实名认证");
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!userInfo.isHasAddress()) {
|
|
|
+ return AjaxResult.error("请先添加地址");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断拍卖状态
|
|
|
+ String error = checkLotStatus(bid);
|
|
|
+ if (StringUtils.hasLength(error)) {
|
|
|
+ log.warn("出价失败:{}", error);
|
|
|
+ return AjaxResult.error("出价失败");
|
|
|
+ }
|
|
|
+ Lot lot = cacheMap.viewLot(bid.getAuctionId(), bid.getLotId()).getLot();
|
|
|
+ if (Objects.equals(lot.getMerchantId().intValue(), userInfo.getMerchantId())) {
|
|
|
+ log.warn("出价失败,商家无法参与自己的竞价拍卖");
|
|
|
+ return AjaxResult.error("出价失败,商家无法参与自己的竞价拍卖");
|
|
|
+ }
|
|
|
+ List<Order> orderList = orderStatusService.selectOrderStatusList(Order.builder().flag(1).merchantId(lot.getMerchantId()).userId(userInfo.getId().longValue()).build());
|
|
|
+ /*if (!CollectionUtils.isEmpty(orderList)) {
|
|
|
+ return AjaxResult.error("因您存在超时支付,暂时无法参与当前竞价");
|
|
|
+ }
|
|
|
+ orderList=orderStatusService.selectOrderStatusList(Order.builder().flag(0).merchantId(lot.getMerchantId()).status(100L).userId(userInfo.getId().longValue()).build());
|
|
|
+ if (!CollectionUtils.isEmpty(orderList)) {
|
|
|
+ return AjaxResult.error("支付当前待支付订单才可继续参与竞价");
|
|
|
+ }*/
|
|
|
+ try {
|
|
|
+ bidService.addPrice(bid,() ->{ });
|
|
|
+ }catch (RuntimeException e) {
|
|
|
+ log.error("addPrice error {}", bid, e);
|
|
|
+ return AjaxResult.error("当前价格已变动");
|
|
|
+ }
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 直播间竞拍提速版,使用redis维护出价信息,拍卖结束后统一录入数据库,每秒更新redis数据同步到数据库的表里面
|
|
|
+ * 出价限制由拍卖的接口提供,这里只检查缓存中是否存在,不存在则不能参加:
|
|
|
+ * */
|
|
|
+ @PostMapping({"/v3/addPrice"})
|
|
|
+ public AjaxResult addPriceV4(@RequestBody BidVO bid) {
|
|
|
+ UserInfo userInfo = UserUtils.getSimpleUserInfo();
|
|
|
+ if(userInfo!=null){
|
|
|
+ String nickname = String.valueOf(userInfo.getSub());
|
|
|
+ bid.setCreateBy(nickname);
|
|
|
+ bid.setAccount(nickname);
|
|
|
+ String accountId = String.valueOf(userInfo.getId());
|
|
|
+ bid.setAccountId(accountId);
|
|
|
+ bid.setAvatar(userInfo.getAvatar());
|
|
|
+ bid.setAuctionId(2L);
|
|
|
+ bid.setBidNo(UUID.randomUUID().toString());
|
|
|
+ createBidRecordCache(bid);
|
|
|
+ }
|
|
|
+ else{return AjaxResult.error("出价失败");}
|
|
|
+
|
|
|
+ //从本场拍卖的缓存中拿限制信息,未能通过的用户不能出价参拍
|
|
|
+ Map<String,String> forbbidenUsermap = redisCache.getCacheMap(String.format(Constants.REDIS_MAP_AUC_LOT_BID_USER_TEMPLATE, bid.getLotId()));
|
|
|
+ if(forbbidenUsermap.containsKey(userInfo.getId().toString())){
|
|
|
+ return AjaxResult.error(forbbidenUsermap.get(userInfo.getId().toString()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断拍卖状态
|
|
|
+ String error = checkLotStatus(bid);
|
|
|
+ if (StringUtils.hasLength(error)) {
|
|
|
+ log.warn("出价失败:{}", error);
|
|
|
+ return AjaxResult.error("出价失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ bidService.addPriceV3(bid,() ->{ });
|
|
|
+ }catch (RuntimeException e) {
|
|
|
+ log.error("addPriceV3 error {}", bid, e);
|
|
|
+ return AjaxResult.error("当前价格已变动");
|
|
|
+ }
|
|
|
+ return AjaxResult.success();
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("查询并返回指定拍卖中已结束的拍卖物品列表,并以分页的形式展示")
|
|
|
+ @PostMapping("/view/{auctionId}/finished")
|
|
|
+ public AjaxResult viewFinished(@RequestBody BidVO bidVO, @PathVariable Long auctionId) {
|
|
|
+ log.info("= " + bidVO + "=");
|
|
|
+ bidVO.setOrderBy("real_end_time desc");
|
|
|
+ startPage(bidVO);
|
|
|
+ List<Lot> lots = lotService.selectLotList(Lot.builder()
|
|
|
+ .auctionId(auctionId)
|
|
|
+ .delFlag(Constants.DEL_FLAG_NO_DELETE)
|
|
|
+ .goodsType(bidVO.getGoodsType())
|
|
|
+ .status(Constants.LOT_STATUS_SOLD)
|
|
|
+ .privateDomain(0)
|
|
|
+ .build());
|
|
|
+ Page page = (Page) lots;
|
|
|
+ PaginationUtil.PageResult<Lot> lotlist = new PaginationUtil.PageResult<>(((Page<Lot>) page).getResult(), Integer.parseInt(page.getTotal() + ""), page.getPageNum(), bidVO.getPageSize());
|
|
|
+ lotlist.getItems().forEach(lot->{
|
|
|
+ lot.setDealAccount(SensitiveDataUtils.maskString(lot.getDealAccount(), 4));
|
|
|
+ lot.setUpdateBy(SensitiveDataUtils.maskString(lot.getUpdateBy(), 4));
|
|
|
+ });
|
|
|
+ return AjaxResult.success(lotlist);
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("获取指定拍卖ID的所有拍卖品信息")
|
|
|
+ @PostMapping("/view/{auctionId}/starting")
|
|
|
+ public AjaxResult viewBidding(@RequestBody BidVO bidVO, @PathVariable Long auctionId) {
|
|
|
+ log.info("= " + bidVO + "=");
|
|
|
+ Map<String, Live> map = bidService.view(auctionId);
|
|
|
+ Set<String> statusSet = Sets.newHashSet(Constants.LOT_STATUS_STARTING, Constants.LOT_STATUS_BIDDING, Constants.LOT_STATUS_WAITING);
|
|
|
+ List<Live> list = map.values().stream()
|
|
|
+ .filter(live -> statusSet.contains(live.getLot().getStatus()) && live.getShow())
|
|
|
+ .filter(live -> StringUtils.isEmpty(bidVO.getGoodsType()) || Objects.equals(live.getLot().getGoodsType(), bidVO.getGoodsType()))
|
|
|
+ .map(SensitiveDataUtils::handleViewDataSafe)
|
|
|
+ .sorted(this::sort)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ return AjaxResult.success(PaginationUtil.page(bidVO, list));
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("从 Redis 缓存中获取id对应的 Live 对象,并将其返回")
|
|
|
+ @GetMapping("/viewEx/{id}")
|
|
|
+ public AjaxResult viewEx(@PathVariable Long id) {
|
|
|
+ Live live = redisCache.getCacheMapValue(String.format(Constants.REDIS_AUC_TEMPLATE, 2), id.toString());
|
|
|
+ return AjaxResult.success(JSON.toJSON(live));
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("获取并返回Live 对象,该对象包含了特定拍卖品的详细信息,包括出价记录、交易账户信息等")
|
|
|
+ @GetMapping("/view/{auctionId}/{id}")
|
|
|
+ public AjaxResult view(@PathVariable Long auctionId, @PathVariable Long id) {
|
|
|
+ Live live = bidService.viewLot(auctionId, id);
|
|
|
+ Lot lot = lotService.selectLotById(id);
|
|
|
+ UserInfo userInfo = null;
|
|
|
+ try {
|
|
|
+ userInfo = UserUtils.getUserInfo(Convert.toInt(lot.getDealAccountId()));
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("getUserInfo error", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ log.info("request param auction {} id {}",auctionId,id);
|
|
|
+ // region 获取用户禁止拍卖的检查信息并写入缓存
|
|
|
+ UserInfo curruserInfo = UserUtils.getUserInfo(getUserId());
|
|
|
+ boolean isForbiddenUser = false;
|
|
|
+ String forbiddenReason = "";
|
|
|
+ if (Objects.equals(2, curruserInfo.getAccountStatus())) {
|
|
|
+ isForbiddenUser = true;
|
|
|
+ forbiddenReason = "暂时无法参与当前竞价";
|
|
|
+ }
|
|
|
+ if (!Objects.equals(1, curruserInfo.getFaceVerify())) {
|
|
|
+ isForbiddenUser = true;
|
|
|
+ forbiddenReason = "请先进行实名认证";
|
|
|
+ }
|
|
|
+ if(!curruserInfo.isHasAddress()) {
|
|
|
+ isForbiddenUser = true;
|
|
|
+ forbiddenReason = "请先添加地址";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Objects.equals(lot.getMerchantId().intValue(), curruserInfo.getMerchantId())) {
|
|
|
+ isForbiddenUser = true;
|
|
|
+ forbiddenReason = "出价失败";
|
|
|
+ }
|
|
|
+
|
|
|
+ Long merchantId = lot.getMerchantId();
|
|
|
+ Long userId = Long.valueOf(getUserId());
|
|
|
+ List<Order> orderList = orderStatusService.selectOrderStatusList(Order.builder().flag(1).merchantId(merchantId).userId(userId).build());
|
|
|
+ if (!CollectionUtils.isEmpty(orderList)) {
|
|
|
+ isForbiddenUser = true;
|
|
|
+ forbiddenReason = "因您存在超时支付,暂时无法参与当前竞价";
|
|
|
+ }
|
|
|
+ orderList=orderStatusService.selectOrderStatusList(Order.builder().flag(0).merchantId(lot.getMerchantId()).userId(userId).build());
|
|
|
+ if (!CollectionUtils.isEmpty(orderList)) {
|
|
|
+ isForbiddenUser = true;
|
|
|
+ forbiddenReason = "支付当前待支付订单才可继续参与竞价";
|
|
|
+ }
|
|
|
+ if(isForbiddenUser){
|
|
|
+ redisCache.setCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_BID_USER_TEMPLATE, lot.getId()), curruserInfo.getId().toString(), forbiddenReason);
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ redisCache.delCacheMapValue(String.format(Constants.REDIS_MAP_AUC_LOT_BID_USER_TEMPLATE, lot.getId()), curruserInfo.getId().toString());
|
|
|
+ }
|
|
|
+ // endregion
|
|
|
+
|
|
|
+ }
|
|
|
+ catch (Exception e) {
|
|
|
+ log.error("get curruserInfo error", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ final Lot clone = CloneUtils.clone(lot);
|
|
|
+ List<Bid> bids = bidService.selectBidList(Bid.builder().lotId(lot.getId()).build());
|
|
|
+ List<Bid> bidsDealList = bids.stream()
|
|
|
+ .filter(bid -> bid.getStatus() == 1 && bid.getAccountId().equals(lot.getDealAccountId()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ // 检查 bidsList 是否存在,并且如果存在,找到 anonymous 字段等于 1 的 Bid 对象
|
|
|
+ boolean isDealAccountAnonymous = false;
|
|
|
+ if (!bidsDealList.isEmpty()) {
|
|
|
+ for (Bid bid : bidsDealList) {
|
|
|
+ if (bid.getAnonymous() == 1) {
|
|
|
+ isDealAccountAnonymous = true;
|
|
|
+ break; // 如果只需要找到第一个符合条件的对象,可以在这里停止循环
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Objects.isNull(live)) {
|
|
|
+ LiveContext liveContext = LiveContext.builder().dbLot(lot).bidList(bids).build();
|
|
|
+ ruleHandlerHolder.sync(liveContext);
|
|
|
+ live = liveContext.getLive();
|
|
|
+ if (Objects.equals(auctionId, 2L)) {
|
|
|
+ Long groupId = lot.getGroupId();
|
|
|
+ LotGroup lotGroup = lotService.selectLotGroupById(groupId);
|
|
|
+ if (lotGroup.getFinishNum() >= lotGroup.getNum()) {
|
|
|
+ live.setFinish(1);
|
|
|
+ }else {
|
|
|
+ live.setFinish(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Objects.nonNull(userInfo)){
|
|
|
+ live.getLot().setDealAccountavatar(userInfo.getAvatar());
|
|
|
+ if (clone != null) {
|
|
|
+ clone.setDealAccountavatar(userInfo.getAvatar());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Objects.equals(getUserId().toString(), lot.getDealAccountId())){
|
|
|
+ live.getLot().setOrderId(lot.getOrderId());
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if (clone != null) {
|
|
|
+ clone.setOrderId(null);
|
|
|
+ if(isDealAccountAnonymous){
|
|
|
+ clone.setDealAccountavatar(null);
|
|
|
+ clone.setDealAccount(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ live.setLot(clone);
|
|
|
+ return AjaxResult.success(SensitiveDataUtils.handleViewDataSafe(live));
|
|
|
+ }
|
|
|
+ live.setLot(clone);
|
|
|
+ if (Objects.equals(auctionId, 2L)) {
|
|
|
+ Long groupId = lot.getGroupId();
|
|
|
+ LotGroup lotGroup = lotService.selectLotGroupById(groupId);
|
|
|
+ if (lotGroup.getFinishNum() >= lotGroup.getNum()) {
|
|
|
+ live.setFinish(1);
|
|
|
+ }else {
|
|
|
+ live.setFinish(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Objects.nonNull(userInfo)){
|
|
|
+ live.getLot().setDealAccountavatar(userInfo.getAvatar());
|
|
|
+ }
|
|
|
+ if(Objects.equals(getUserId().toString(), lot.getDealAccountId())){
|
|
|
+ live.getLot().setOrderId(lot.getOrderId());
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ live.getLot().setOrderId(null);
|
|
|
+ if(isDealAccountAnonymous){
|
|
|
+ live.getLot().setDealAccountavatar(null);
|
|
|
+ live.getLot().setDealAccount(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("/bid/bidding/view/ result {}", live);
|
|
|
+ log.info("/bid/bidding/view/ result {}", SensitiveDataUtils.handleViewDataSafe(live));
|
|
|
+ return AjaxResult.success(SensitiveDataUtils.handleViewDataSafe(live));
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 配合v3的竞价使用,查询缓存中的竞价结果
|
|
|
+ * */
|
|
|
+ @GetMapping("/viewv3/{auctionId}/{id}")
|
|
|
+ public AjaxResult viewV4(@PathVariable Long auctionId, @PathVariable Long id) {
|
|
|
+ Live live = bidService.viewLot(auctionId, id);
|
|
|
+ Lot lot = lotService.selectLotById(id);
|
|
|
+ UserInfo userInfo = UserUtils.getUserInfo(Convert.toInt(lot.getDealAccountId()));
|
|
|
+ final Lot clone = CloneUtils.clone(lot);
|
|
|
+ List<Bid> bids = bidService.selectBidList(Bid.builder().lotId(lot.getId()).build());
|
|
|
+ List<Bid> bidsDealList = bids.stream()
|
|
|
+ .filter(bid -> bid.getStatus() == 1 && bid.getAccountId().equals(lot.getDealAccountId()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ // 检查 bidsList 是否存在,并且如果存在,找到 anonymous 字段等于 1 的 Bid 对象
|
|
|
+ boolean isDealAccountAnonymous = false;
|
|
|
+ if (!bidsDealList.isEmpty()) {
|
|
|
+ for (Bid bid : bidsDealList) {
|
|
|
+ if (bid.getAnonymous() == 1) {
|
|
|
+ isDealAccountAnonymous = true;
|
|
|
+ break; // 如果只需要找到第一个符合条件的对象,可以在这里停止循环
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (Objects.isNull(live)) {
|
|
|
+ LiveContext liveContext = LiveContext.builder().dbLot(lot).bidList(bids).build();
|
|
|
+ ruleHandlerHolder.sync(liveContext);
|
|
|
+ live = liveContext.getLive();
|
|
|
+ if (Objects.equals(auctionId, 2L)) {
|
|
|
+ Long groupId = lot.getGroupId();
|
|
|
+ LotGroup lotGroup = lotService.selectLotGroupById(groupId);
|
|
|
+ if (lotGroup.getFinishNum() >= lotGroup.getNum()) {
|
|
|
+ live.setFinish(1);
|
|
|
+ }else {
|
|
|
+ live.setFinish(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Objects.nonNull(userInfo)){
|
|
|
+ live.getLot().setDealAccountavatar(userInfo.getAvatar());
|
|
|
+ if (clone != null) {
|
|
|
+ clone.setDealAccountavatar(userInfo.getAvatar());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Objects.equals(getUserId().toString(), lot.getDealAccountId())){
|
|
|
+ live.getLot().setOrderId(lot.getOrderId());
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if (clone != null) {
|
|
|
+ clone.setOrderId(null);
|
|
|
+ if(isDealAccountAnonymous){
|
|
|
+ clone.setDealAccountavatar(null);
|
|
|
+ clone.setDealAccount(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ live.setLot(clone);
|
|
|
+ log.info("/bid/bidding/view/ result {}", live);
|
|
|
+ log.info("/bid/bidding/view/ result {}", SensitiveDataUtils.handleViewDataSafe(live));
|
|
|
+ return AjaxResult.success(SensitiveDataUtils.handleViewDataSafe(live));
|
|
|
+ }
|
|
|
+ if (Objects.equals(auctionId, 2L)) {
|
|
|
+ Long groupId = lot.getGroupId();
|
|
|
+ LotGroup lotGroup = lotService.selectLotGroupById(groupId);
|
|
|
+ if (lotGroup.getFinishNum() >= lotGroup.getNum()) {
|
|
|
+ live.setFinish(1);
|
|
|
+ }else {
|
|
|
+ live.setFinish(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(Objects.nonNull(userInfo)){
|
|
|
+ live.getLot().setDealAccountavatar(userInfo.getAvatar());
|
|
|
+ }
|
|
|
+ if(Objects.equals(getUserId().toString(), lot.getDealAccountId())){
|
|
|
+ live.getLot().setOrderId(lot.getOrderId());
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ live.getLot().setOrderId(null);
|
|
|
+ if(isDealAccountAnonymous){
|
|
|
+ live.getLot().setDealAccountavatar(null);
|
|
|
+ live.getLot().setDealAccount(null);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ log.info("/bid/bidding/view/ result {}", live);
|
|
|
+ log.info("/bid/bidding/view/ result {}", SensitiveDataUtils.handleViewDataSafe(live));
|
|
|
+ return AjaxResult.success(SensitiveDataUtils.handleViewDataSafe(live));
|
|
|
+ }
|
|
|
+
|
|
|
+ @GetMapping("/viewcache/{auctionId}/{id}")
|
|
|
+ public AjaxResult viewV3cache(@PathVariable Long auctionId, @PathVariable Long id) {
|
|
|
+ List<BidVO> bidList = redisCache.getCacheList(String.format(Constants.REDIS_MAP_AUC_LOT_BID_LIST_PREFIX,id));
|
|
|
+ return AjaxResult.success(bidList);
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("查询拍卖品出价记录等信息")
|
|
|
+ @PostMapping("/list")
|
|
|
+ public AjaxResult listBid(@RequestBody BidVO bidVO) {
|
|
|
+ Lot dbLot = lotService.selectLotById(bidVO.getLotId());
|
|
|
+ if (Constants.LOT_STATUS_SOLD.equals(dbLot.getStatus()) ||
|
|
|
+ Constants.LOT_STATUS_CANCELLED.equals(dbLot.getStatus()) ||
|
|
|
+ Constants.LOT_STATUS_PASS.equals(dbLot.getStatus())) {
|
|
|
+ return findBidPageFromDb(bidVO);
|
|
|
+ }
|
|
|
+ if (bidVO.getPageSize() > 20 || (bidVO.getPageSize() * bidVO.getPageNum()) > 20) {
|
|
|
+ return findBidPageFromDb(bidVO);
|
|
|
+ }else {
|
|
|
+ Integer userId = UserUtils.getSimpleUserInfo().getId();
|
|
|
+ List<Bid> list = bidService.selectCacheBidList(bidVO).stream().map(bid -> {
|
|
|
+ boolean sensitive=false;
|
|
|
+ if (Objects.equals(1, bid.getAnonymous())) {
|
|
|
+ bid.setAvatar("/MC143302022060920611/avatar/1666182630730.jpg");
|
|
|
+ bid.setAccount("匿名用户");
|
|
|
+ sensitive=true;
|
|
|
+ }
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isBlank(bid.getAvatar())){
|
|
|
+ bid.setAvatar("/MC143302022060920611/avatar/1666182630730.jpg");
|
|
|
+ }
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isBlank(bid.getAccount())){
|
|
|
+ bid.setAccount("匿名用户");
|
|
|
+ sensitive=true;
|
|
|
+ }
|
|
|
+ bid.setCurrentAccount(Objects.equals(Integer.parseInt(bid.getAccountId()), userId));
|
|
|
+ if (!sensitive) {
|
|
|
+ return SensitiveDataUtils.handleViewDataSafe(bid);
|
|
|
+ }
|
|
|
+ return bid;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ if (!CollectionUtils.isEmpty(list)) {
|
|
|
+ log.info("CollectionUtils list {}", list);
|
|
|
+ // 使用 Comparator 接口进行排序
|
|
|
+ list.sort((bid1, bid2) -> bid2.getAmount().compareTo(bid1.getAmount()));
|
|
|
+ log.info("CollectionUtils list size after sort {}", list.size());
|
|
|
+ Bid bidLast = list.get(0);
|
|
|
+ Long total = bidLast.getRound();
|
|
|
+ log.info("CollectionUtils bidLast {}", bidLast);
|
|
|
+ List<List<Bid>> partition = Lists.partition(list, bidVO.getPageSize());
|
|
|
+ List<Bid> resultList = Lists.newArrayList();
|
|
|
+ log.info("CollectionUtils partition {}", partition.size());
|
|
|
+ if (partition.size() >= bidVO.getPageNum()) {
|
|
|
+ log.info("CollectionUtils partitionget {}", partition.get(bidVO.getPageNum() - 1));
|
|
|
+ log.info("CollectionUtils partitionget {}", resultList.size());
|
|
|
+ resultList = partition.get(bidVO.getPageNum() - 1);
|
|
|
+ }
|
|
|
+ return AjaxResult.success(new PaginationUtil.PageResult<>(resultList, total.intValue(), bidVO.getPageNum(), bidVO.getPageSize()));
|
|
|
+ }else {
|
|
|
+ log.info("CollectionUtils list is empty");
|
|
|
+ return AjaxResult.success(PaginationUtil.page(bidVO, list));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // endregion
|
|
|
+
|
|
|
+
|
|
|
+ // region Methods
|
|
|
+
|
|
|
+ private void point(BidVO bid) {
|
|
|
+ List<Bid> bids = redisCache.getCacheList(String.format(Constants.REDIS_MAP_AUC_LOT_BID_TEMPLATE, bid.getLotId()));
|
|
|
+ Bid lastBid = null;
|
|
|
+ if (!CollectionUtils.isEmpty(bids)) {
|
|
|
+ lastBid = bids.get(0);
|
|
|
+ }
|
|
|
+ log.info("currBid {} lastBid {}",JSON.toJSONString(bid),JSON.toJSONString(lastBid));
|
|
|
+ if (!appClient.operatePoint(bid, lastBid)) {
|
|
|
+ throw new AddPriceException("积分校验失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String checkLotStatus(BidVO bid) {
|
|
|
+ log.info("checkLotStatus cacheMap {}",cacheMap);
|
|
|
+ log.info("checkLotStatus bid {}",bid);
|
|
|
+ Live live = cacheMap.viewLot(bid.getAuctionId(), bid.getLotId());
|
|
|
+ log.info("checkLotStatus live {}",live);
|
|
|
+
|
|
|
+ if (Objects.isNull(live)) {
|
|
|
+ List<Bid> bids = bidService.selectBidList(Bid.builder().lotId(bid.getLotId()).build());
|
|
|
+ log.info("sync bids {}",bids);
|
|
|
+ Lot lot = lotService.selectLotById(bid.getLotId());
|
|
|
+ log.info("sync lot {}",lot);
|
|
|
+ LiveContext liveContext = LiveContext.builder().dbLot(lot).bidList(bids).build();
|
|
|
+ ruleHandlerHolder.sync(liveContext);
|
|
|
+ log.info("sync liveContext {}",liveContext);
|
|
|
+ live = liveContext.getLive();
|
|
|
+ live.setLot(lot);
|
|
|
+ if (Objects.equals(bid.getAuctionId(), 2L)) {
|
|
|
+ Long groupId = lot.getGroupId();
|
|
|
+ LotGroup lotGroup = lotService.selectLotGroupById(groupId);
|
|
|
+ if (lotGroup.getFinishNum() >= lotGroup.getNum()) {
|
|
|
+ live.setFinish(1);
|
|
|
+ log.info("cacheMap putLive {}","未找到正在进行中的拍卖");
|
|
|
+ return "未找到正在进行中的拍卖";
|
|
|
+ }else {
|
|
|
+ live.setFinish(0);
|
|
|
+ cacheMap.putLive(live);
|
|
|
+ log.info("cacheMap putLive {}",live);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return "未找到正在进行中的拍卖";
|
|
|
+ }
|
|
|
+ if (Constants.LOT_STATUS_WAITING.equals(live.getLot().getStatus())) {
|
|
|
+ return "拍卖还未开始";
|
|
|
+ }
|
|
|
+ if (!Lists.newArrayList(Constants.LOT_STATUS_BIDDING, Constants.LOT_STATUS_STARTING).contains(live.getLot().getStatus())) {
|
|
|
+ return "拍卖已结束";
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Long createBidRecord(Bid bid){
|
|
|
+ BidRecord record = BidRecord.builder()
|
|
|
+ .lotId(bid.getLotId())
|
|
|
+ .bidNo(bid.getBidNo())
|
|
|
+ .userId(Long.parseLong(bid.getAccountId()))
|
|
|
+ .amount(bid.getAmount())
|
|
|
+ .createTime(new Date()).build();
|
|
|
+ bidRecordMapper.insertBidRecord(record);
|
|
|
+ return record.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void createBidRecordCache(Bid bid){
|
|
|
+ List<BidRecord> bidList = new ArrayList<>();
|
|
|
+ BidRecord record = BidRecord.builder()
|
|
|
+ .lotId(bid.getLotId())
|
|
|
+ .bidNo(bid.getBidNo())
|
|
|
+ .userId(Long.parseLong(bid.getAccountId()))
|
|
|
+ .amount(bid.getAmount())
|
|
|
+ .createTime(new Date()).build();
|
|
|
+ bidList.add(record);
|
|
|
+ redisCache.addToCacheList(String.format(Constants.REDIS_MAP_AUC_LOT_BIDRECORD_LIST_PREFIX, bid.getLotId()), bidList);
|
|
|
+ }
|
|
|
+
|
|
|
+ private int sort(Live live1, Live live2) {
|
|
|
+ int sort1 = Objects.nonNull(live1.getLot().getSort()) ? live1.getLot().getSort() : 0;
|
|
|
+ int sort2 = Objects.nonNull(live2.getLot().getSort()) ? live2.getLot().getSort() : 0;
|
|
|
+ return (sort2 - sort1) == 0 ? (int)(live1.getCurrentEndTime() - live2.getCurrentEndTime()) : (sort2 - sort1);
|
|
|
+ }
|
|
|
+
|
|
|
+ private AjaxResult findBidPageFromDb(BidVO bidVO) {
|
|
|
+ bidVO.setDelFlag(Constants.DEL_FLAG_NO_DELETE);
|
|
|
+ startPage(bidVO);
|
|
|
+ List<Bid> data = bidService.selectBidList(bidVO);
|
|
|
+ Integer userId = UserUtils.getSimpleUserInfo().getId();
|
|
|
+ data.forEach(bid -> {
|
|
|
+ boolean sensitive=false;
|
|
|
+ if (Objects.equals(1, bid.getAnonymous())) {
|
|
|
+ bid.setAvatar("/MC143302022060920611/avatar/1666182630730.jpg");
|
|
|
+ bid.setAccount("匿名用户");
|
|
|
+ sensitive=true;
|
|
|
+ }
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isBlank(bid.getAvatar())){
|
|
|
+ bid.setAvatar("/MC143302022060920611/avatar/1666182630730.jpg");
|
|
|
+ }
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isBlank(bid.getAccount())){
|
|
|
+ bid.setAccount("匿名用户");
|
|
|
+ sensitive=true;
|
|
|
+ }
|
|
|
+ bid.setCurrentAccount(Objects.equals(Integer.parseInt(bid.getAccountId()), userId));
|
|
|
+ if (!sensitive) {
|
|
|
+ SensitiveDataUtils.handleViewDataSafe(bid);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ Page page = (Page) data;
|
|
|
+ return AjaxResult.success(new PaginationUtil.PageResult<>(((Page<Bid>) data).getResult(), Integer.parseInt(page.getTotal() + ""), page.getPageNum(), bidVO.getPageSize()));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|