Browse Source

对接拼团数据1

master
wangfukang 2 months ago
parent
commit
c22b60f532
  1. 2
      hiver-admin/src/main/resources/application.yml
  2. 16
      hiver-admin/test-output/test-report.html
  3. 4
      hiver-core/src/main/java/cc/hiver/core/dao/UserDao.java
  4. 4
      hiver-core/src/main/java/cc/hiver/core/dao/WorkerDao.java
  5. 4
      hiver-core/src/main/java/cc/hiver/core/entity/Worker.java
  6. 2
      hiver-core/src/main/java/cc/hiver/core/service/UserService.java
  7. 2
      hiver-core/src/main/java/cc/hiver/core/service/WorkerService.java
  8. 5
      hiver-core/src/main/java/cc/hiver/core/serviceimpl/UserServiceImpl.java
  9. 5
      hiver-core/src/main/java/cc/hiver/core/serviceimpl/WorkerServiceImpl.java
  10. 83
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java
  11. 47
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java
  12. 164
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/controller/CampusAdminController.java
  13. 224
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/controller/CampusController.java
  14. 24
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusAdminActionDTO.java
  15. 12
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusChatMessageDTO.java
  16. 14
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusCommentDTO.java
  17. 15
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusComplaintDTO.java
  18. 25
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusPageQuery.java
  19. 28
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusPostDTO.java
  20. 31
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusAdminLog.java
  21. 35
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusCategory.java
  22. 38
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusChatMessage.java
  23. 50
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusChatSession.java
  24. 53
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusComment.java
  25. 59
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusComplaint.java
  26. 23
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusLike.java
  27. 107
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusPost.java
  28. 33
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusUserLimit.java
  29. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusAdminLogMapper.java
  30. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusCategoryMapper.java
  31. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusChatMessageMapper.java
  32. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusChatSessionMapper.java
  33. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusCommentMapper.java
  34. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusComplaintMapper.java
  35. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusLikeMapper.java
  36. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusPostMapper.java
  37. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusUserLimitMapper.java
  38. 93
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/service/CampusService.java
  39. 1438
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/service/impl/CampusServiceImpl.java
  40. 12
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/vo/CampusPostDetailVO.java
  41. 103
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminDataStatisticsController.java
  42. 121
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java
  43. 21
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/UserAddressController.java
  44. 52
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java
  45. 59
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerRelaPriceController.java
  46. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/WorkerRelaPriceMapper.java
  47. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallDeliveryOrder.java
  48. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/UserAddress.java
  49. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/WorkerRelaPrice.java
  50. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/fishmarket/dto/FishCommentDTO.java
  51. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/fishmarket/dto/FishPublishDTO.java
  52. 51
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/fishmarket/service/impl/FishMarketServiceImpl.java
  53. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/controller/IeController.java
  54. 64
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeAliyunModerationServiceImpl.java
  55. 5
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeSecurityAuditServiceImpl.java
  56. 1
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeAuditResult.java
  57. 12
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java
  58. 14
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java
  59. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerMatchVO.java
  60. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerRealPriceVo.java
  61. 6
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/UserAddressService.java
  62. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/WorkerRelaPriceService.java
  63. 8
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopServiceImpl.java
  64. 41
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java
  65. 8
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/UserAddressServiceImpl.java
  66. 10
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/WorkerRelaPriceServiceImpl.java
  67. 253
      hiver-modules/hiver-mall/src/main/resources/db/campus_circle.sql
  68. 3
      hiver-modules/hiver-mall/src/main/resources/db/user_address_region_id.sql
  69. 3
      hiver-modules/hiver-mall/src/main/resources/db/worker_full_time.sql
  70. 12
      hiver-modules/hiver-mall/src/main/resources/db/worker_rela_price_region_id.sql
  71. 51
      hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml
  72. 32
      hiver-modules/hiver-mall/src/main/resources/mapper/WorkerRelaPriceMapper.xml

2
hiver-admin/src/main/resources/application.yml

@ -13,7 +13,7 @@ ie:
region: cn-beijing
endpoint: green-cip-vpc.cn-beijing.aliyuncs.com
# 控制台规则配置的 serviceCode1
text-service: chat_detection
text-service: comment_detection_pro
image-service: baselineCheck
video-service: videoDetection
# 注意:语音审核 service 是下划线格式(视频是驼峰,阿里云两个产品命名不一致)

16
hiver-admin/test-output/test-report.html

@ -35,7 +35,7 @@
<a href="#"><span class="badge badge-primary">Hiver</span></a>
</li>
<li class="m-r-10">
<a href="#"><span class="badge badge-primary">七月 26, 2026 17:19:19</span></a>
<a href="#"><span class="badge badge-primary">七月 31, 2026 16:45:26</span></a>
</li>
</ul>
</div>
@ -84,7 +84,7 @@
<div class="test-detail">
<span class="meta text-white badge badge-sm"></span>
<p class="name">passTest</p>
<p class="text-sm"><span>17:19:19 下午</span> / <span>0.023 secs</span></p>
<p class="text-sm"><span>16:45:26 下午</span> / <span>0.024 secs</span></p>
</div>
<div class="test-contents d-none">
<div class="detail-head">
@ -92,9 +92,9 @@
<div class="info">
<div class='float-right'><span class='badge badge-default'>#test-id=1</span></div>
<h5 class="test-status text-pass">passTest</h5>
<span class='badge badge-success'>07.26.2026 17:19:19</span>
<span class='badge badge-danger'>07.26.2026 17:19:19</span>
<span class='badge badge-default'>0.023 secs</span>
<span class='badge badge-success'>07.31.2026 16:45:26</span>
<span class='badge badge-danger'>07.31.2026 16:45:26</span>
<span class='badge badge-default'>0.024 secs</span>
</div>
<div class="m-t-10 m-l-5"></div>
</div>
@ -104,7 +104,7 @@
<tbody>
<tr class="event-row">
<td><span class="badge log pass-bg">Pass</span></td>
<td>17:19:19</td>
<td>16:45:26</td>
<td>
Test passed
</td>
@ -128,13 +128,13 @@
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Started</p>
<h3>七月 26, 2026 17:19:19</h3>
<h3>七月 31, 2026 16:45:26</h3>
</div></div>
</div>
<div class="col-md-3">
<div class="card"><div class="card-body">
<p class="m-b-0">Ended</p>
<h3>七月 26, 2026 17:19:19</h3>
<h3>七月 31, 2026 16:45:26</h3>
</div></div>
</div>
<div class="col-md-3">

4
hiver-core/src/main/java/cc/hiver/core/dao/UserDao.java

@ -119,6 +119,10 @@ public interface UserDao extends HiverBaseDao<User, String> {
@Query("update User u set u.mobile=?1 where u.id=?2")
void updateUserPhoneById(String userPhone, String userId);
@Modifying
@Query("update User u set u.nickname=?2, u.avatar=?3 where u.id=?1")
int updateMiniProfile(String userId, String nickname, String avatar);
@Modifying
@Query(value = "update t_user set saved_amount = coalesce(saved_amount, 0) + ?2 where id = ?1", nativeQuery = true)
int increaseSavedAmount(String userId, BigDecimal savedAmount);

4
hiver-core/src/main/java/cc/hiver/core/dao/WorkerDao.java

@ -23,6 +23,10 @@ public interface WorkerDao extends HiverBaseDao<Worker, String> {
@Query("update Worker w set w.isOnLine=?2 where w.workerId=?1")
void changeOnLine(String id, Integer onLine);
@Modifying
@Query("update Worker w set w.isFullTime=?2 where w.workerId=?1")
void changeFullTime(String id, Integer isFullTime);
@Modifying
@Query("update Worker w set w.workerStatus=?2 where w.workerId = ?1")
void delById(String id, Integer workerStatusDisable);

4
hiver-core/src/main/java/cc/hiver/core/entity/Worker.java

@ -199,6 +199,10 @@ public class Worker implements Serializable {
@Column(name = "get_push_order")
private Integer getPushOrder;
@ApiModelProperty(value = "是否全职配送员:0否 1是")
@Column(name = "is_full_time")
private Integer isFullTime = 0;
@ApiModelProperty(value = "评分")
@Column(name = "score")
private BigDecimal score;

2
hiver-core/src/main/java/cc/hiver/core/service/UserService.java

@ -146,6 +146,8 @@ public interface UserService extends HiverBaseService<User, String> {
void updateUserPhoneById(String userPhone, String userId);
int updateMiniProfile(String userId, String nickname, String avatar);
/**
* 判断指定用户是否已完成平台实名认证
*

2
hiver-core/src/main/java/cc/hiver/core/service/WorkerService.java

@ -54,6 +54,8 @@ public interface WorkerService extends HiverBaseService<Worker, String> {
*/
void offLine(String id);
void changeFullTime(String id, Integer isFullTime);
/**
* 删除修改为禁用状态
*

5
hiver-core/src/main/java/cc/hiver/core/serviceimpl/UserServiceImpl.java

@ -369,6 +369,11 @@ public class UserServiceImpl implements UserService {
userDao.updateUserPhoneById(userPhone, userId);
}
@Override
public int updateMiniProfile(String userId, String nickname, String avatar) {
return userDao.updateMiniProfile(userId, nickname, avatar);
}
@Override
public boolean isRealNameVerified(String userId) {
if (CharSequenceUtil.isBlank(userId)) {

5
hiver-core/src/main/java/cc/hiver/core/serviceimpl/WorkerServiceImpl.java

@ -248,6 +248,11 @@ public class WorkerServiceImpl implements WorkerService {
workerDao.changeOnLine(id, CommonConstant.OFF_LINE);
}
@Override
public void changeFullTime(String id, Integer isFullTime) {
workerDao.changeFullTime(id, isFullTime);
}
/**
* 删除修改为禁用状态
*

83
hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java

@ -201,7 +201,7 @@ public class AuthController {
}
Worker worker = workerService.findByUserId(user.getId());
//更新配送员 推送id
if(worker!= null){
if(worker!= null && StringUtils.isNotEmpty(clientId)){
worker.setClientId(clientId);
workerService.update(worker);
String oldRegion = worker.getRegion();
@ -247,8 +247,9 @@ public class AuthController {
@RequestMapping(value = "/smsLogin", method = RequestMethod.POST)
@SystemLog(description = "短信登录", type = LogType.LOGIN)
@ApiOperation("短信登录")
@Transactional(readOnly = true)
@Transactional
public Result smsLogin(@RequestParam String mobile,
@RequestParam(value = "clientId", required = false) String clientId,
@RequestParam(required = false) String type,
@RequestParam(required = false) Boolean saveLogin) {
@ -264,27 +265,73 @@ public class AuthController {
// 返回当前登录人的信息
result.put("user", user);
// 店铺登录的话,根据登录人查询所有关联的店铺(店铺启用,并且在有效期内)
if (UserConstant.USER_TYPE_NORMAL.equals(type)) {
// 获取
final List<ShopUser> shopUsers = shopUserService.selectByUserId(user.getId());
if (!shopUsers.isEmpty()) {
// 获取店主手机号
for (ShopUser shopUser : shopUsers) {
final Shop shop = shopService.findById(shopUser.getShop().getId());
if (shop != null && shop.getShopOwnerId() != null && StringUtils.isNotEmpty(shop.getShopOwnerId())) {
final User shopOwner = userService.findById(shop.getShopOwnerId());
if(shopOwner != null){
shopUser.setShopOwnerName(shopOwner.getNickname());
shopUser.setShopOwnerPhone(shopOwner.getMobile());
List<Shop> shop = shopService.getShopByUserid(user.getId());
if(!shop.isEmpty()){
List<String> shopIds = new ArrayList<>();
for (Shop item : shop) {
shopIds.add(item.getId());
if (StringUtils.isNotEmpty(clientId)) {
item.setClientId(clientId);
shopService.update(item);
shopService.refreshShopCache(item.getId(), item.getRegionId());
}
}
if(!shopIds.isEmpty()){
List<ShopTakeaway> shopTakeaway = shopTakeawayService.selectListByshopId(shopIds);
if(shopTakeaway != null){
shop.forEach(e -> {
for(ShopTakeaway shopTakeawa : shopTakeaway) {
if (e.getId().equals(shopTakeawa.getShopId())) {
e.setShopTakeaway(shopTakeawa);
}
}
});
}
}
result.put("shop", shop);
}
Worker worker = workerService.findByUserId(user.getId());
//更新配送员 推送id
if(worker!= null && StringUtils.isNotEmpty(clientId)){
worker.setClientId(clientId);
workerService.update(worker);
String oldRegion = worker.getRegion();
WorkerRedisVo workerRedisVo = StrUtil.isNotBlank(oldRegion) ? workerRedisCacheUtil.get(oldRegion, worker.getWorkerId()) : null;
if(workerRedisVo != null){
workerRedisVo.setWorker(worker);
if (Objects.equals(oldRegion, worker.getRegion())) {
workerRedisCacheUtil.update(worker.getRegion(), workerRedisVo);
} else {
workerRedisCacheUtil.remove(oldRegion, worker.getWorkerId());
if (StrUtil.isNotBlank(worker.getRegion())) {
workerRedisCacheUtil.put(worker.getRegion(), workerRedisVo);
}
}
result.put("shopList", shopUsers);
} else {
return ResultUtil.error("店铺未开通!");
}
}
if(worker!= null && worker.getGetPushOrder() != null && worker.getGetPushOrder() == 1){
final List<WorkerRelaPrice> workerRelaPriceList = workerRelaPriceService.selectByWorkerId(worker.getWorkerId());
List<WorkerRelaPrice> workerRelaPriceListWaimai = new ArrayList<>();
List<WorkerRelaPrice> workerRelaPriceListKuaidi = new ArrayList<>();
if(workerRelaPriceList != null && workerRelaPriceList.size() > 0){
workerRelaPriceList.forEach(workerRelaPrice -> {
if(workerRelaPrice.getGetPushOrder() == 1){
if(workerRelaPrice.getOrderType() == 0 ){
workerRelaPriceListWaimai.add(workerRelaPrice);
}else{
workerRelaPriceListKuaidi.add(workerRelaPrice);
}
}
});
}
if(workerRelaPriceListWaimai.size() > 0){
result.put("waimaiData", workerRelaPriceListWaimai);
}
if(workerRelaPriceListKuaidi.size() > 0){
result.put("kuaidiData", workerRelaPriceListKuaidi);
}
}
result.put("worker", worker);
return ResultUtil.data(result);
}

47
hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/UserController.java

@ -179,6 +179,53 @@ public class UserController {
return ResultUtil.success("修改成功");
}
@RequestMapping(value = "/profile", method = RequestMethod.POST)
@ApiOperation(value = "小程序修改头像昵称", notes = "头像和昵称来自微信头像昵称填写能力,微信侧已完成安全检测")
public Result<User> updateMiniProfile(@RequestBody Map<String, String> body) {
final User old = securityUtil.getCurrUser();
String nickname = body == null ? "" : StringUtils.trimToEmpty(body.get("nickname"));
String avatar = body == null ? "" : StringUtils.trimToEmpty(body.get("avatar"));
if (StringUtils.isBlank(nickname)) {
return ResultUtil.error("昵称不能为空");
}
if (nickname.length() > 20) {
return ResultUtil.error("昵称长度不能超过20");
}
old.setNickname(nickname);
if (StringUtils.isNotBlank(avatar)) {
old.setAvatar(avatar);
}
userService.update(old);
entityManager.detach(old);
old.setPassword(null);
return new ResultUtil<User>().setData(old);
}
@RequestMapping(value = "/miniProfile", method = RequestMethod.POST)
@ApiOperation(value = "小程序只修改头像昵称", notes = "仅更新user表nickname和avatar两个字段")
public Result<Map<String, String>> updateMiniProfileOnly(@RequestBody Map<String, String> body) {
final User old = securityUtil.getCurrUser();
String nickname = body == null ? "" : StringUtils.trimToEmpty(body.get("nickname"));
String avatar = body == null ? "" : StringUtils.trimToEmpty(body.get("avatar"));
if (StringUtils.isBlank(nickname)) {
return ResultUtil.error("昵称不能为空");
}
if (nickname.length() > 20) {
return ResultUtil.error("昵称长度不能超过20");
}
if (StringUtils.isBlank(avatar)) {
return ResultUtil.error("头像不能为空");
}
userService.updateMiniProfile(old.getId(), nickname, avatar);
Map<String, String> result = new HashMap<>();
result.put("id", old.getId());
result.put("nickname", nickname);
result.put("avatar", avatar);
return new ResultUtil<Map<String, String>>().setData(result);
}
/**
* 线上demo不允许测试账号改密码
*

164
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/controller/CampusAdminController.java

@ -0,0 +1,164 @@
package cc.hiver.mall.campus.controller;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.utils.SecurityUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.core.entity.User;
import cc.hiver.mall.campus.dto.CampusAdminActionDTO;
import cc.hiver.mall.campus.dto.CampusPageQuery;
import cc.hiver.mall.campus.entity.*;
import cc.hiver.mall.campus.service.CampusService;
import cc.hiver.mall.ie.entity.IeContentAuditLog;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@Api(tags = "校园圈后台管理接口")
@RequestMapping("/hiver/app/campus/admin")
public class CampusAdminController {
@Autowired
private CampusService campusService;
@Autowired
private SecurityUtil securityUtil;
@RequestMapping(value = "/categories", method = RequestMethod.GET)
@ApiOperation("后台查询分类与热门标签")
public Result<IPage<CampusCategory>> categories(@RequestParam(required = false) String regionId,
@RequestParam(required = false) String parentCode,
@RequestParam(required = false) String categoryType,
@RequestParam(required = false) String keyword,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
User admin = currentUser();
String currentRegionId = regionId == null || regionId.trim().isEmpty() ? admin.getDepartmentId() : regionId;
CampusPageQuery query = new CampusPageQuery();
query.setRegionId(currentRegionId);
query.setParentCode(parentCode);
query.setCategoryType(categoryType);
query.setKeyword(keyword);
query.setPageNum(pageNum);
query.setPageSize(pageSize);
return new ResultUtil<IPage<CampusCategory>>().setData(campusService.adminPageCategories(query));
}
@RequestMapping(value = "/categories", method = RequestMethod.POST)
@ApiOperation("新增/编辑分类与热门标签")
public Result<CampusCategory> saveCategory(@RequestBody CampusCategory category) {
return new ResultUtil<CampusCategory>().setData(campusService.saveCategory(category, currentUser()));
}
@RequestMapping(value = "/categories/status", method = RequestMethod.POST)
@ApiOperation("上下架分类与热门标签")
public Result<Object> updateCategoryStatus(@RequestBody CampusAdminActionDTO dto) {
campusService.updateCategoryStatus(dto, currentUser());
return ResultUtil.success("处理成功");
}
@RequestMapping(value = "/categories/delete", method = RequestMethod.POST)
@ApiOperation("删除分类与热门标签")
public Result<Object> deleteCategoryPost(@RequestParam String id) {
campusService.deleteCategory(id, currentUser());
return ResultUtil.success("删除成功");
}
@RequestMapping(value = "/posts/page", method = RequestMethod.POST)
@ApiOperation("后台分页查询帖子")
public Result<IPage<CampusPost>> pagePosts(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusPost>>().setData(campusService.pagePosts(query, null));
}
@RequestMapping(value = "/wall/posts/page", method = RequestMethod.POST)
@ApiOperation("后台分页查询校园墙帖子")
public Result<IPage<CampusPost>> wallPosts(@RequestBody(required = false) CampusPageQuery query) {
if (query == null) query = new CampusPageQuery();
query.setPostType("wall");
return new ResultUtil<IPage<CampusPost>>().setData(campusService.pagePosts(query, null));
}
@RequestMapping(value = "/partner/posts/page", method = RequestMethod.POST)
@ApiOperation("后台分页查询搭子帖子")
public Result<IPage<CampusPost>> partnerPosts(@RequestBody(required = false) CampusPageQuery query) {
if (query == null) query = new CampusPageQuery();
query.setPostType("partner");
return new ResultUtil<IPage<CampusPost>>().setData(campusService.pagePosts(query, null));
}
@RequestMapping(value = "/posts/status", method = RequestMethod.POST)
@ApiOperation("审核/下架/恢复/删除帖子")
public Result<Object> updatePostStatus(@RequestBody CampusAdminActionDTO dto) {
campusService.updatePostStatus(dto, currentUser());
return ResultUtil.success("处理成功");
}
@RequestMapping(value = "/posts/{id}/comments/page", method = RequestMethod.GET)
@ApiOperation("后台查询帖子评论")
public Result<IPage<CampusComment>> postComments(@PathVariable String id,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
return new ResultUtil<IPage<CampusComment>>().setData(campusService.adminPageComments(id, pageNum, pageSize));
}
@RequestMapping(value = "/comments/{id}/delete", method = RequestMethod.POST)
@ApiOperation("后台删除评论")
public Result<Object> deleteComment(@PathVariable String id) {
campusService.adminDeleteComment(id, currentUser());
return ResultUtil.success("删除成功");
}
@RequestMapping(value = "/complaints/page", method = RequestMethod.POST)
@ApiOperation("举报分页")
public Result<IPage<CampusComplaint>> complaints(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusComplaint>>().setData(campusService.adminPageComplaints(query));
}
@RequestMapping(value = "/complaints/handle", method = RequestMethod.POST)
@ApiOperation("处理举报")
public Result<Object> handleComplaint(@RequestBody CampusAdminActionDTO dto) {
campusService.handleComplaint(dto, currentUser());
return ResultUtil.success("处理成功");
}
@RequestMapping(value = "/complaints/unblock", method = RequestMethod.POST)
@ApiOperation("解除封禁")
public Result<Object> unblockComplaintUser(@RequestBody CampusAdminActionDTO dto) {
campusService.unblockComplaintUser(dto, currentUser());
return ResultUtil.success("解除封禁成功");
}
@RequestMapping(value = "/users/limits/page", method = RequestMethod.POST)
@ApiOperation("用户风控分页")
public Result<IPage<CampusUserLimit>> userLimits(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusUserLimit>>().setData(campusService.adminPageUserLimits(query));
}
@RequestMapping(value = "/users/limits", method = RequestMethod.POST)
@ApiOperation("保存用户风控")
public Result<CampusUserLimit> saveUserLimit(@RequestBody CampusAdminActionDTO dto) {
return new ResultUtil<CampusUserLimit>().setData(campusService.saveUserLimit(dto, currentUser()));
}
@RequestMapping(value = "/logs/page", method = RequestMethod.POST)
@ApiOperation("后台操作日志分页")
public Result<IPage<CampusAdminLog>> logs(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusAdminLog>>().setData(campusService.adminPageLogs(query));
}
@RequestMapping(value = "/audit-logs/page", method = RequestMethod.GET)
@ApiOperation("校园圈违规内容分页")
public Result<IPage<IeContentAuditLog>> auditLogs(@RequestParam(required = false) String regionId,
@RequestParam(required = false, defaultValue = "1") Integer pageNumber,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
return new ResultUtil<IPage<IeContentAuditLog>>().setData(campusService.adminAuditLogs(regionId, pageNumber, pageSize));
}
private User currentUser() {
User user = securityUtil.getCurrUser();
if (user == null) {
throw new RuntimeException("请先登录");
}
return user;
}
}

224
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/controller/CampusController.java

@ -0,0 +1,224 @@
package cc.hiver.mall.campus.controller;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.utils.SecurityUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.core.entity.User;
import cc.hiver.mall.campus.dto.*;
import cc.hiver.mall.campus.entity.*;
import cc.hiver.mall.campus.service.CampusService;
import cc.hiver.mall.campus.vo.CampusPostDetailVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.List;
import java.util.Map;
@RestController
@Api(tags = "校园圈用户端接口")
@RequestMapping("/hiver/app/campus")
public class CampusController {
@Autowired
private CampusService campusService;
@Autowired
private SecurityUtil securityUtil;
@RequestMapping(value = "/categories", method = RequestMethod.GET)
@ApiOperation("查询校园圈分类和热门标签")
public Result<List<CampusCategory>> categories(@RequestParam(required = false) String regionId,
@RequestParam(required = false) String parentCode,
@RequestParam(required = false) String categoryType) {
return new ResultUtil<List<CampusCategory>>().setData(campusService.listCategories(regionId, parentCode, categoryType));
}
@RequestMapping(value = "/posts/page", method = RequestMethod.POST)
@ApiOperation("分页查询校园圈帖子")
public Result<IPage<CampusPost>> pagePosts(@RequestBody(required = false) CampusPageQuery query) {
if (query == null) query = new CampusPageQuery();
if (query.getStatus() == null) query.setStatus(1);
if (query.getAuditStatus() == null) query.setAuditStatus(1);
return new ResultUtil<IPage<CampusPost>>().setData(campusService.pagePosts(query, currentUserOrNull()));
}
@RequestMapping(value = "/partner/posts/page", method = RequestMethod.POST)
@ApiOperation("分页查询找搭子")
public Result<IPage<CampusPost>> pagePartnerPosts(@RequestBody(required = false) CampusPageQuery query) {
if (query == null) query = new CampusPageQuery();
query.setPostType("partner");
if (query.getStatus() == null) query.setStatus(1);
if (query.getAuditStatus() == null) query.setAuditStatus(1);
return new ResultUtil<IPage<CampusPost>>().setData(campusService.pagePosts(query, currentUserOrNull()));
}
@RequestMapping(value = "/partner/posts/match", method = RequestMethod.POST)
@ApiOperation("按分类和标题模糊匹配找搭子")
public Result<CampusPost> matchPartnerPost(@RequestBody(required = false) CampusPageQuery query) {
if (query == null) query = new CampusPageQuery();
query.setPostType("partner");
query.setStatus(1);
query.setAuditStatus(1);
return new ResultUtil<CampusPost>().setData(campusService.matchPartnerPost(query, currentUserOrNull()));
}
@RequestMapping(value = "/posts/{id}", method = RequestMethod.GET)
@ApiOperation("查询校园圈帖子详情")
public Result<CampusPostDetailVO> detail(@PathVariable String id) {
return new ResultUtil<CampusPostDetailVO>().setData(campusService.postDetail(id, currentUserOrNull()));
}
@RequestMapping(value = "/posts", method = RequestMethod.POST)
@ApiOperation("发布/编辑校园圈内容")
public Result<CampusPost> publish(@RequestBody CampusPostDTO dto) {
return new ResultUtil<CampusPost>().setData(campusService.publishPost(dto, currentUser()));
}
@RequestMapping(value = "/images/audit", method = RequestMethod.POST)
@ApiOperation("校园圈图片审核")
public Result<Map<String, Object>> auditReleaseImage(@RequestBody Map<String, String> body) {
return new ResultUtil<Map<String, Object>>().setData(campusService.auditReleaseImage(body == null ? "" : body.get("url"), currentUser()));
}
@RequestMapping(value = "/like", method = RequestMethod.POST)
@ApiOperation("点赞/表情反应")
public Result<Map<String, Object>> like(@RequestParam String targetType,
@RequestParam String targetId,
@RequestParam(required = false) String reaction) {
return new ResultUtil<Map<String, Object>>().setData(campusService.toggleLike(targetType, targetId, reaction, currentUser()));
}
@RequestMapping(value = "/comments", method = RequestMethod.POST)
@ApiOperation("发表评论/回复")
public Result<CampusComment> addComment(@RequestBody CampusCommentDTO dto) {
return new ResultUtil<CampusComment>().setData(campusService.addComment(dto, currentUser()));
}
@RequestMapping(value = "/comments/page", method = RequestMethod.GET)
@ApiOperation("分页查询评论")
public Result<IPage<CampusComment>> pageComments(@RequestParam String postId,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
return new ResultUtil<IPage<CampusComment>>().setData(campusService.pageComments(postId, pageNum, pageSize, currentUserOrNull()));
}
@RequestMapping(value = "/comments/{id}", method = RequestMethod.DELETE)
@ApiOperation("删除自己的评论")
public Result<Object> deleteComment(@PathVariable String id) {
campusService.deleteComment(id, currentUser());
return ResultUtil.success("删除成功");
}
@RequestMapping(value = "/posts/{postId}/chat", method = RequestMethod.POST)
@ApiOperation("创建校园圈聊天会话")
public Result<CampusChatSession> chat(@PathVariable String postId) {
return new ResultUtil<CampusChatSession>().setData(campusService.createChatSession(postId, currentUser()));
}
@RequestMapping(value = "/chat/sessions/{sessionId}", method = RequestMethod.GET)
@ApiOperation("查询校园圈聊天会话")
public Result<CampusChatSession> chatSession(@PathVariable String sessionId) {
return new ResultUtil<CampusChatSession>().setData(campusService.getChatSession(sessionId, currentUser()));
}
@RequestMapping(value = "/chat/sessions/{sessionId}/messages/page", method = RequestMethod.GET)
@ApiOperation("分页查询校园圈聊天消息")
public Result<IPage<CampusChatMessage>> chatMessages(@PathVariable String sessionId,
@RequestParam(required = false, defaultValue = "1") Integer pageNum,
@RequestParam(required = false, defaultValue = "20") Integer pageSize) {
return new ResultUtil<IPage<CampusChatMessage>>().setData(campusService.pageChatMessages(sessionId, pageNum, pageSize, currentUser()));
}
@RequestMapping(value = "/chat/messages", method = RequestMethod.POST)
@ApiOperation("发送校园圈聊天消息")
public Result<CampusChatMessage> sendChatMessage(@RequestBody CampusChatMessageDTO dto) {
return new ResultUtil<CampusChatMessage>().setData(campusService.sendChatMessage(dto, currentUser()));
}
@RequestMapping(value = "/complaints", method = RequestMethod.POST)
@ApiOperation("提交举报")
public Result<CampusComplaint> complaint(@RequestBody CampusComplaintDTO dto) {
return new ResultUtil<CampusComplaint>().setData(campusService.submitComplaint(dto, currentUser()));
}
@RequestMapping(value = "/my/posts", method = RequestMethod.POST)
@ApiOperation("我的校园圈发布")
public Result<IPage<CampusPost>> myPosts(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusPost>>().setData(campusService.pageMyPosts(query, currentUser()));
}
@RequestMapping(value = "/my/posts/status", method = RequestMethod.POST)
@ApiOperation("上下架/删除自己的校园圈发布")
public Result<Object> updateMyPostStatus(@RequestBody CampusAdminActionDTO dto) {
campusService.updateMyPostStatus(dto, currentUser());
return ResultUtil.success("处理成功");
}
@RequestMapping(value = "/my/sessions", method = RequestMethod.POST)
@ApiOperation("我的校园圈会话")
public Result<IPage<CampusChatSession>> mySessions(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusChatSession>>().setData(campusService.pageMySessions(query, currentUser()));
}
@RequestMapping(value = "/my/sessions/{id}", method = RequestMethod.DELETE)
@ApiOperation("删除我的校园圈会话")
public Result<Object> deleteMySessionMessage(@PathVariable String id) {
campusService.deleteMySessionMessage(id, currentUser());
return ResultUtil.success("删除成功");
}
@RequestMapping(value = "/my/message-comments", method = RequestMethod.POST)
@ApiOperation("我的校园圈留言消息")
public Result<IPage<CampusComment>> myMessageComments(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusComment>>().setData(campusService.pageMyMessageComments(query, currentUser()));
}
@RequestMapping(value = "/my/comments", method = RequestMethod.POST)
@ApiOperation("我的校园圈评论")
public Result<IPage<CampusComment>> myComments(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusComment>>().setData(campusService.pageMyComments(query, currentUser()));
}
@RequestMapping(value = "/my/message-comments/{id}", method = RequestMethod.DELETE)
@ApiOperation("删除我的校园圈留言消息")
public Result<Object> deleteMyCommentMessage(@PathVariable String id) {
campusService.deleteMyCommentMessage(id, currentUser());
return ResultUtil.success("删除成功");
}
@RequestMapping(value = "/my/complaints", method = RequestMethod.POST)
@ApiOperation("我的校园圈举报")
public Result<IPage<CampusComplaint>> myComplaints(@RequestBody(required = false) CampusPageQuery query) {
return new ResultUtil<IPage<CampusComplaint>>().setData(campusService.pageMyComplaints(query, currentUser()));
}
@RequestMapping(value = "/unread/summary", method = RequestMethod.GET)
@ApiOperation("校园圈未读汇总")
public Result<Map<String, Object>> unreadSummary() {
return new ResultUtil<Map<String, Object>>().setData(campusService.unreadSummary(currentUser()));
}
@RequestMapping(value = "/unread/read-all", method = RequestMethod.POST)
@ApiOperation("校园圈一键已读")
public Result<Object> markAllUnreadRead() {
campusService.markAllUnreadRead(currentUser());
return ResultUtil.success("处理成功");
}
private User currentUser() {
User user = securityUtil.getCurrUser();
if (user == null) {
throw new RuntimeException("请先登录");
}
return user;
}
private User currentUserOrNull() {
try {
return securityUtil.getCurrUser();
} catch (Exception e) {
return null;
}
}
}

24
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusAdminActionDTO.java

@ -0,0 +1,24 @@
package cc.hiver.mall.campus.dto;
import lombok.Data;
import java.util.Date;
@Data
public class CampusAdminActionDTO {
private String id;
private String postId;
private String commentId;
private String complaintId;
private String userId;
private Integer status;
private Integer auditStatus;
private String reason;
private String handleResult;
private Boolean blockUser;
private Integer muted;
private Integer publishBanned;
private Integer permanentBanned;
private Date startTime;
private Date endTime;
}

12
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusChatMessageDTO.java

@ -0,0 +1,12 @@
package cc.hiver.mall.campus.dto;
import lombok.Data;
@Data
public class CampusChatMessageDTO {
private String sessionId;
/** 1文本,2图片 */
private Integer messageType;
private String content;
private String clientMsgId;
}

14
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusCommentDTO.java

@ -0,0 +1,14 @@
package cc.hiver.mall.campus.dto;
import lombok.Data;
@Data
public class CampusCommentDTO {
private String postId;
private String userName;
private String userAvatar;
private String parentId;
private String replyToUserId;
private String replyToUserName;
private String content;
}

15
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusComplaintDTO.java

@ -0,0 +1,15 @@
package cc.hiver.mall.campus.dto;
import lombok.Data;
import java.util.List;
@Data
public class CampusComplaintDTO {
private String postId;
private String commentId;
private String sessionId;
private String complaintType;
private String reason;
private List<String> images;
}

25
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusPageQuery.java

@ -0,0 +1,25 @@
package cc.hiver.mall.campus.dto;
import lombok.Data;
@Data
public class CampusPageQuery {
private Integer pageNum = 1;
private Integer pageSize = 10;
private String keyword;
private String regionId;
private String userId;
private String postType;
private String partnerType;
private String parentCode;
private String categoryType;
private String categoryId;
private String tag;
private String statusText;
private Integer auditStatus;
private Integer status;
private String targetType;
private String type;
/** hot/latest/match */
private String sortType;
}

28
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/dto/CampusPostDTO.java

@ -0,0 +1,28 @@
package cc.hiver.mall.campus.dto;
import lombok.Data;
import java.util.List;
@Data
public class CampusPostDTO {
private String id;
private String regionId;
private String regionName;
private String userName;
private String userAvatar;
private String postType;
private String partnerType;
private String categoryId;
private String categoryName;
private String title;
private String content;
private String contentText;
private List<String> images;
private List<String> tags;
private String location;
private String activityTime;
private Integer targetCount;
private String contactWechat;
private String contactPhone;
}

31
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusAdminLog.java

@ -0,0 +1,31 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "校园圈后台操作日志")
@TableName(value = "campus_admin_log", autoResultMap = true)
public class CampusAdminLog extends HiverBaseEntity {
@ApiModelProperty("校区/区域ID")
private String regionId;
@ApiModelProperty("管理员ID")
private String adminId;
@ApiModelProperty("管理员昵称")
private String adminName;
@ApiModelProperty("操作类型")
private String actionType;
@ApiModelProperty("目标类型")
private String targetType;
@ApiModelProperty("目标ID")
private String targetId;
@ApiModelProperty("原因")
private String reason;
@ApiModelProperty("变更前")
private String beforeData;
@ApiModelProperty("变更后")
private String afterData;
}

35
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusCategory.java

@ -0,0 +1,35 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "校园圈分类与热门标签")
@TableName(value = "campus_category", autoResultMap = true)
public class CampusCategory extends HiverBaseEntity {
@ApiModelProperty("校区/区域ID")
private String regionId;
@ApiModelProperty("校区/区域名称")
private String regionName;
@ApiModelProperty("一级频道:wall/game/daily/sport")
private String parentCode;
@ApiModelProperty("分类或标签编码")
private String code;
@ApiModelProperty("分类或标签名称")
private String name;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("图标")
private String icon;
@ApiModelProperty("颜色")
private String color;
@ApiModelProperty("category分类,tag热门标签")
private String categoryType;
@ApiModelProperty("排序")
private Integer sortOrder;
@ApiModelProperty("状态:1启用,2停用")
private Integer status;
}

38
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusChatMessage.java

@ -0,0 +1,38 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "校园圈聊天消息")
@TableName(value = "campus_chat_message", autoResultMap = true)
public class CampusChatMessage extends HiverBaseEntity {
@ApiModelProperty("业务会话ID")
private String sessionId;
@ApiModelProperty("帖子ID")
private String postId;
@ApiModelProperty("发送人ID")
private String senderId;
@ApiModelProperty("接收人ID")
private String receiverId;
@ApiModelProperty("1文本,2图片")
private Integer messageType;
@ApiModelProperty("消息内容")
private String content;
@ApiModelProperty("审核状态:0待审核,1通过,2拒绝")
private Integer auditStatus;
@ApiModelProperty("审核原因")
private String auditReason;
@ApiModelProperty("状态:1正常,2撤回/删除")
private Integer status;
@ApiModelProperty("是否已读:0否,1是")
private Integer readFlag;
@TableField(exist = false)
@ApiModelProperty("小程序端本地消息ID")
private String clientMsgId;
}

50
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusChatSession.java

@ -0,0 +1,50 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "校园圈聊天会话")
@TableName(value = "campus_chat_session", autoResultMap = true)
public class CampusChatSession extends HiverBaseEntity {
@ApiModelProperty("业务会话ID")
private String sessionId;
@ApiModelProperty("帖子ID")
private String postId;
@ApiModelProperty("发布人ID")
private String ownerId;
@ApiModelProperty("联系用户ID")
private String peerUserId;
@ApiModelProperty("最后消息时间")
private Date lastMessageTime;
@ApiModelProperty("最后消息摘要")
private String lastMessage;
@ApiModelProperty("是否结束")
private Integer ended;
@ApiModelProperty("发布人是否删除列表记录")
private Integer ownerDeleted;
@ApiModelProperty("联系用户是否删除列表记录")
private Integer peerDeleted;
@TableField(exist = false)
@ApiModelProperty("帖子标题")
private String displayTitle;
@TableField(exist = false)
@ApiModelProperty("帖子封面")
private String displayCover;
@TableField(exist = false)
@ApiModelProperty("帖子类型")
private String postType;
@TableField(exist = false)
@ApiModelProperty("搭子类型")
private String partnerType;
@TableField(exist = false)
@ApiModelProperty("当前用户未读消息数")
private Integer unreadCount;
}

53
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusComment.java

@ -0,0 +1,53 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "校园圈评论")
@TableName(value = "campus_comment", autoResultMap = true)
public class CampusComment extends HiverBaseEntity {
@ApiModelProperty("帖子ID")
private String postId;
@ApiModelProperty("父评论ID")
private String parentId;
@ApiModelProperty("评论人ID")
private String userId;
@ApiModelProperty("评论人昵称")
private String userName;
@ApiModelProperty("评论人头像")
private String userAvatar;
@ApiModelProperty("回复目标用户ID")
private String replyToUserId;
@ApiModelProperty("回复目标用户昵称")
private String replyToUserName;
@ApiModelProperty("评论内容")
private String content;
@ApiModelProperty("点赞数")
private Integer likeCount;
@ApiModelProperty("审核状态:0待审核,1通过,2拒绝")
private Integer auditStatus;
@ApiModelProperty("审核原因")
private String auditReason;
@ApiModelProperty("状态:1正常,2删除")
private Integer status;
@TableField(exist = false)
@ApiModelProperty("回复列表")
private List<CampusComment> replies;
@TableField(exist = false)
@ApiModelProperty("当前用户未读数")
private Integer unreadCount;
@TableField(exist = false)
@ApiModelProperty("帖子标题")
private String displayTitle;
@TableField(exist = false)
@ApiModelProperty("帖子封面")
private String displayCover;
}

59
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusComplaint.java

@ -0,0 +1,59 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "校园圈投诉举报")
@TableName(value = "campus_complaint", autoResultMap = true)
public class CampusComplaint extends HiverBaseEntity {
@ApiModelProperty("校区/区域ID")
private String regionId;
@ApiModelProperty("举报人ID")
private String reporterId;
@ApiModelProperty("举报人昵称")
private String reporterName;
@ApiModelProperty("帖子ID")
private String postId;
@ApiModelProperty("评论ID")
private String commentId;
@ApiModelProperty("会话ID")
private String sessionId;
@ApiModelProperty("被举报用户ID")
private String targetUserId;
@ApiModelProperty("post/comment/chat")
private String complaintType;
@ApiModelProperty("举报原因")
private String reason;
@ApiModelProperty("举报图片JSON")
private String images;
@ApiModelProperty("0待处理,1通过,2驳回")
private Integer status;
@ApiModelProperty("处理结果")
private String handleResult;
@ApiModelProperty("处理管理员ID")
private String adminId;
@ApiModelProperty("处理管理员名称")
private String adminName;
@ApiModelProperty("处理时间")
private Date handleTime;
@TableField(exist = false)
@ApiModelProperty("举报对象标题")
private String displayTitle;
@TableField(exist = false)
@ApiModelProperty("举报对象封面")
private String displayCover;
@TableField(exist = false)
@ApiModelProperty("评论内容")
private String commentContent;
@TableField(exist = false)
@ApiModelProperty("被举报用户手机号")
private String targetUserMobile;
}

23
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusLike.java

@ -0,0 +1,23 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "校园圈点赞和表情反应")
@TableName(value = "campus_like", autoResultMap = true)
public class CampusLike extends HiverBaseEntity {
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("post/comment/reaction")
private String targetType;
@ApiModelProperty("目标ID")
private String targetId;
@ApiModelProperty("表情反应")
private String reaction;
@ApiModelProperty("1有效,2取消")
private Integer status;
}

107
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusPost.java

@ -0,0 +1,107 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Map;
@Data
@ApiModel(value = "校园圈帖子")
@TableName(value = "campus_post", autoResultMap = true)
public class CampusPost extends HiverBaseEntity {
@ApiModelProperty("校区/区域ID")
private String regionId;
@ApiModelProperty("校区/区域名称")
private String regionName;
@ApiModelProperty("发布人ID")
private String userId;
@ApiModelProperty("发布人昵称")
private String userName;
@ApiModelProperty("发布人头像")
private String userAvatar;
@ApiModelProperty("wall校园墙,partner找搭子")
private String postType;
@ApiModelProperty("game/daily/sport")
private String partnerType;
@ApiModelProperty("二级分类ID")
private String categoryId;
@ApiModelProperty("二级分类名称")
private String categoryName;
@ApiModelProperty("标题")
private String title;
@ApiModelProperty("正文")
private String content;
@ApiModelProperty("纯文本正文")
private String contentText;
@ApiModelProperty("封面图")
private String coverImage;
@ApiModelProperty("图片JSON")
private String images;
@ApiModelProperty("标签JSON")
private String tags;
@ApiModelProperty("地点")
private String location;
@ApiModelProperty("期望时间")
private String activityTime;
@ApiModelProperty("期望人数")
private Integer targetCount;
@ApiModelProperty("已联系/参与人数")
private Integer joinedCount;
@ApiModelProperty("联系方式:chat站内聊天")
private String contactType;
@ApiModelProperty("联系微信")
private String contactWechat;
@ApiModelProperty("联系电话")
private String contactPhone;
@ApiModelProperty("浏览数")
private Integer browseCount;
@ApiModelProperty("点赞数")
private Integer likeCount;
@ApiModelProperty("评论数")
private Integer commentCount;
@ApiModelProperty("会话数")
private Integer chatCount;
@ApiModelProperty("举报数")
private Integer complaintCount;
@ApiModelProperty("热度分")
private Integer hotScore;
@ApiModelProperty("业务状态:1正常,2下架,3删除")
private Integer status;
@ApiModelProperty("审核状态:0待审核,1通过,2拒绝")
private Integer auditStatus;
@ApiModelProperty("审核原因")
private String auditReason;
@ApiModelProperty("下架原因")
private String offShelfReason;
@TableField(exist = false)
@ApiModelProperty("图片列表")
private List<String> imageList;
@TableField(exist = false)
@ApiModelProperty("标签列表")
private List<String> tagList;
@TableField(exist = false)
@ApiModelProperty("当前用户是否点赞")
private Boolean liked;
@TableField(exist = false)
@ApiModelProperty("当前用户是否作者")
private Boolean mine;
@TableField(exist = false)
@ApiModelProperty("最后消息/评论时间")
private Date lastActiveTime;
@TableField(exist = false)
@ApiModelProperty("表情反应数量")
private Map<String, Integer> reactionCounts;
@TableField(exist = false)
@ApiModelProperty("当前用户未读评论数")
private Integer unreadCommentCount;
@TableField(exist = false)
@ApiModelProperty("当前用户未读聊天数")
private Integer unreadChatCount;
}

33
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/entity/CampusUserLimit.java

@ -0,0 +1,33 @@
package cc.hiver.mall.campus.entity;
import cc.hiver.core.base.HiverBaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "校园圈用户风控")
@TableName(value = "campus_user_limit", autoResultMap = true)
public class CampusUserLimit extends HiverBaseEntity {
@ApiModelProperty("校区/区域ID")
private String regionId;
@ApiModelProperty("用户ID")
private String userId;
@ApiModelProperty("用户昵称")
private String userName;
@ApiModelProperty("是否禁言")
private Integer muted;
@ApiModelProperty("是否禁止发布")
private Integer publishBanned;
@ApiModelProperty("是否永久封禁")
private Integer permanentBanned;
@ApiModelProperty("封禁原因")
private String banReason;
@ApiModelProperty("开始时间")
private Date startTime;
@ApiModelProperty("结束时间")
private Date endTime;
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusAdminLogMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusAdminLog;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusAdminLogMapper extends BaseMapper<CampusAdminLog> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusCategoryMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusCategory;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusCategoryMapper extends BaseMapper<CampusCategory> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusChatMessageMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusChatMessage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusChatMessageMapper extends BaseMapper<CampusChatMessage> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusChatSessionMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusChatSession;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusChatSessionMapper extends BaseMapper<CampusChatSession> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusCommentMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusComment;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusCommentMapper extends BaseMapper<CampusComment> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusComplaintMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusComplaint;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusComplaintMapper extends BaseMapper<CampusComplaint> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusLikeMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusLike;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusLikeMapper extends BaseMapper<CampusLike> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusPostMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusPost;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusPostMapper extends BaseMapper<CampusPost> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/mapper/CampusUserLimitMapper.java

@ -0,0 +1,9 @@
package cc.hiver.mall.campus.mapper;
import cc.hiver.mall.campus.entity.CampusUserLimit;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CampusUserLimitMapper extends BaseMapper<CampusUserLimit> {
}

93
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/service/CampusService.java

@ -0,0 +1,93 @@
package cc.hiver.mall.campus.service;
import cc.hiver.core.entity.User;
import cc.hiver.mall.campus.dto.*;
import cc.hiver.mall.campus.entity.*;
import cc.hiver.mall.campus.vo.CampusPostDetailVO;
import cc.hiver.mall.ie.entity.IeContentAuditLog;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.util.List;
import java.util.Map;
public interface CampusService {
List<CampusCategory> listCategories(String regionId, String parentCode, String categoryType);
List<CampusCategory> adminListCategories(String regionId);
IPage<CampusCategory> adminPageCategories(CampusPageQuery query);
CampusCategory saveCategory(CampusCategory category, User admin);
void updateCategoryStatus(CampusAdminActionDTO dto, User admin);
void deleteCategory(String id, User admin);
IPage<CampusPost> pagePosts(CampusPageQuery query, User user);
CampusPost matchPartnerPost(CampusPageQuery query, User user);
IPage<CampusPost> pageMyPosts(CampusPageQuery query, User user);
CampusPostDetailVO postDetail(String id, User user);
CampusPost publishPost(CampusPostDTO dto, User user);
Map<String, Object> auditReleaseImage(String imageUrl, User user);
Map<String, Object> toggleLike(String targetType, String targetId, String reaction, User user);
CampusComment addComment(CampusCommentDTO dto, User user);
IPage<CampusComment> pageComments(String postId, Integer pageNum, Integer pageSize, User user);
IPage<CampusComment> pageMyMessageComments(CampusPageQuery query, User user);
IPage<CampusComment> pageMyComments(CampusPageQuery query, User user);
void deleteMyCommentMessage(String commentId, User user);
CampusChatSession createChatSession(String postId, User user);
CampusChatSession getChatSession(String sessionId, User user);
CampusChatMessage sendChatMessage(CampusChatMessageDTO dto, User user);
IPage<CampusChatMessage> pageChatMessages(String sessionId, Integer pageNum, Integer pageSize, User user);
IPage<CampusChatSession> pageMySessions(CampusPageQuery query, User user);
void deleteMySessionMessage(String sessionId, User user);
CampusComplaint submitComplaint(CampusComplaintDTO dto, User user);
IPage<CampusComplaint> pageMyComplaints(CampusPageQuery query, User user);
Map<String, Object> unreadSummary(User user);
void markAllUnreadRead(User user);
void deleteComment(String id, User user);
void updateMyPostStatus(CampusAdminActionDTO dto, User user);
void updatePostStatus(CampusAdminActionDTO dto, User admin);
IPage<CampusComment> adminPageComments(String postId, Integer pageNum, Integer pageSize);
void adminDeleteComment(String id, User admin);
IPage<CampusComplaint> adminPageComplaints(CampusPageQuery query);
void handleComplaint(CampusAdminActionDTO dto, User admin);
void unblockComplaintUser(CampusAdminActionDTO dto, User admin);
IPage<CampusUserLimit> adminPageUserLimits(CampusPageQuery query);
CampusUserLimit saveUserLimit(CampusAdminActionDTO dto, User admin);
IPage<CampusAdminLog> adminPageLogs(CampusPageQuery query);
IPage<IeContentAuditLog> adminAuditLogs(String regionId, Integer pageNumber, Integer pageSize);
}

1438
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/service/impl/CampusServiceImpl.java

File diff suppressed because it is too large

12
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/campus/vo/CampusPostDetailVO.java

@ -0,0 +1,12 @@
package cc.hiver.mall.campus.vo;
import cc.hiver.mall.campus.entity.CampusPost;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class CampusPostDetailVO extends CampusPost {
private Boolean liked;
private Boolean mine;
}

103
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AdminDataStatisticsController.java

@ -6,8 +6,6 @@ import cc.hiver.mall.billing.entity.BillingUsageRecord;
import cc.hiver.mall.billing.mapper.BillingUsageRecordMapper;
import cc.hiver.mall.dao.mapper.*;
import cc.hiver.mall.entity.*;
import cc.hiver.mall.planet.entity.PlanetPool;
import cc.hiver.mall.planet.mapper.PlanetPoolMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
@ -26,6 +24,7 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
@ -42,9 +41,9 @@ public class AdminDataStatisticsController {
private static final BigDecimal CONTENT_AUDIT_PACKAGE_PRICE = new BigDecimal("0.05");
private static final BigDecimal REAL_NAME_UNIT_PRICE = BigDecimal.ONE;
private static final String REWARD_FREE_ORDER = "免单奖励";
private static final String REWARD_COLLEGE_RANK = "学院排位赛排名奖励";
private static final String REWARD_DELIVERY_RANK = "配送排名奖励";
private static final String REWARD_DRAW_POOL = "白嫖中奖";
@Autowired
private MallOrderMapper mallOrderMapper;
@ -57,9 +56,9 @@ public class AdminDataStatisticsController {
@Autowired
private DealingsRecordMapper dealingsRecordMapper;
@Autowired
private PlanetPoolMapper planetPoolMapper;
@Autowired
private BillingUsageRecordMapper billingUsageRecordMapper;
@Autowired
private MallSettlementRecordMapper mallSettlementRecordMapper;
@Data
public static class DataStatisticsQuery {
@ -85,6 +84,8 @@ public class AdminDataStatisticsController {
private BigDecimal couponDiscountAmount;
private BigDecimal customerAverageAmount;
private BigDecimal actualIncomeAmount;
private Boolean actualIncomeAvailable;
private BigDecimal settledAmount;
private BigDecimal headquartersDeductionAmount;
private BigDecimal deliveryFeeAmount;
private Long smsCount;
@ -120,6 +121,7 @@ public class AdminDataStatisticsController {
List<MallDeliveryOrder> deliveries = mallDeliveryOrderMapper.selectList(new LambdaQueryWrapper<MallDeliveryOrder>()
.eq(StringUtils.isNotBlank(regionId), MallDeliveryOrder::getRegionId, regionId)
.eq(MallDeliveryOrder::getStatus, 3)
.ge(MallDeliveryOrder::getFinishTime, range.start)
.le(MallDeliveryOrder::getFinishTime, range.end)
.isNotNull(MallDeliveryOrder::getFinishTime));
@ -134,12 +136,7 @@ public class AdminDataStatisticsController {
.eq(StringUtils.isNotBlank(regionId), DealingsRecord::getRegionId, regionId)
.ge(DealingsRecord::getDealingsTime, range.start)
.le(DealingsRecord::getDealingsTime, range.end)
.in(DealingsRecord::getDealingsWay, REWARD_FREE_ORDER, REWARD_COLLEGE_RANK, REWARD_DELIVERY_RANK));
List<PlanetPool> pools = planetPoolMapper.selectList(new LambdaQueryWrapper<PlanetPool>()
.eq(StringUtils.isNotBlank(regionId), PlanetPool::getRegionId, regionId)
.ge(PlanetPool::getDrawTime, range.start)
.le(PlanetPool::getDrawTime, range.end));
.in(DealingsRecord::getDealingsWay, REWARD_COLLEGE_RANK, REWARD_DELIVERY_RANK, REWARD_DRAW_POOL));
List<BillingUsageRecord> billingRecords = billingUsageRecordMapper.selectList(new LambdaQueryWrapper<BillingUsageRecord>()
.eq(StringUtils.isNotBlank(regionId), BillingUsageRecord::getRegionId, regionId)
@ -150,13 +147,36 @@ public class AdminDataStatisticsController {
vo.setStartDate(range.startDate.toString());
vo.setEndDate(range.endDate.toString());
Set<String> refundedOrderIds = new HashSet<>();
Set<String> deliveryRefundOrderIds = new HashSet<>();
for (MallRefundRecord refund : refunds) {
if (StringUtils.isBlank(refund.getOrderId())) {
continue;
}
if (refund.getStatus() != null && refund.getStatus() == 1) {
refundedOrderIds.add(refund.getOrderId());
}
if (refund.getRefundTypeStatus() != null && (refund.getRefundTypeStatus() == 2 || refund.getRefundTypeStatus() == 3 || refund.getRefundTypeStatus() == 4)) {
deliveryRefundOrderIds.add(refund.getOrderId());
}
}
BigDecimal goodsAndPackage = BigDecimal.ZERO;
BigDecimal deliveryFee = BigDecimal.ZERO;
BigDecimal grossDeliveryFee = BigDecimal.ZERO;
BigDecimal settlementDeliveryFee = BigDecimal.ZERO;
BigDecimal koiDiscount = BigDecimal.ZERO;
Set<String> shopIds = new HashSet<>();
Set<String> userIds = new HashSet<>();
for (MallOrder order : orders) {
goodsAndPackage = goodsAndPackage.add(amount(order.getGoodsAmount())).add(amount(order.getPackageFee()));
deliveryFee = deliveryFee.add(amount(order.getDeliveryFee()));
BigDecimal orderDeliveryFee = amount(order.getDeliveryFee());
grossDeliveryFee = grossDeliveryFee.add(orderDeliveryFee);
if (!deliveryRefundOrderIds.contains(order.getId())) {
settlementDeliveryFee = settlementDeliveryFee.add(orderDeliveryFee);
}
if (!isRefundedOrder(order, refundedOrderIds)) {
koiDiscount = koiDiscount.add(amount(order.getFreeAmount()));
}
if (StringUtils.isNotBlank(order.getShopId())) {
shopIds.add(order.getShopId());
}
@ -165,25 +185,20 @@ public class AdminDataStatisticsController {
}
}
BigDecimal deliveryFeeAmount = subtractWechatFee(deliveryFee);
BigDecimal customerAverageBase = subtractWechatFee(goodsAndPackage);
BigDecimal grossFlow = subtractWechatFee(goodsAndPackage.add(deliveryFee));
BigDecimal deliveryFeeAmount = subtractWechatFee(settlementDeliveryFee);
BigDecimal grossFlow = subtractWechatFee(goodsAndPackage.add(grossDeliveryFee));
BigDecimal refundAmount = sumRefundAmount(refunds, 1);
BigDecimal afterSaleAmount = sumRefundAmount(refunds, 4);
BigDecimal effectiveFlow = grossFlow.subtract(refundAmount).subtract(afterSaleAmount).subtract(deliveryFeeAmount);
BigDecimal effectiveFlow = subtractWechatFee(goodsAndPackage);
BigDecimal headquartersDeduction = effectiveFlow.multiply(ONE_PERCENT);
BigDecimal koiDiscount = sumDealingsAmount(rewardRecords, REWARD_FREE_ORDER);
BigDecimal collegeRankReward = sumDealingsAmount(rewardRecords, REWARD_COLLEGE_RANK);
BigDecimal deliveryRankReward = sumDealingsAmount(rewardRecords, REWARD_DELIVERY_RANK);
BigDecimal couponDiscount = coupons.stream()
.map(MallUserCoupon::getDiscountAmount)
.map(this::amount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal drawPoolAmount = pools.stream()
.map(PlanetPool::getPoolAmount)
.map(this::amount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal drawPoolAmount = sumDealingsAmount(rewardRecords, REWARD_DRAW_POOL);
long smsCount = billingRecords.stream().filter(item -> "sms".equals(item.getRecordType())).count();
long contentAuditCount = billingRecords.stream().filter(item -> "content_audit".equals(item.getRecordType())).count();
@ -191,15 +206,21 @@ public class AdminDataStatisticsController {
BigDecimal smsCost = BigDecimal.valueOf(smsCount).multiply(SMS_UNIT_PRICE);
BigDecimal contentAuditCost = BigDecimal.valueOf((contentAuditCount + 99) / 100).multiply(CONTENT_AUDIT_PACKAGE_PRICE);
BigDecimal realNameCost = BigDecimal.valueOf(realNameAuthCount).multiply(REAL_NAME_UNIT_PRICE);
BigDecimal actualIncome = effectiveFlow
BigDecimal rewardTotalAmount = collegeRankReward.add(drawPoolAmount).add(deliveryRankReward);
boolean actualIncomeAvailable = isActualIncomeAvailable(range);
BigDecimal settledAmount = actualIncomeAvailable ? sumSettledAmount(regionId, range) : BigDecimal.ZERO;
BigDecimal actualIncome = grossFlow
.subtract(deliveryFeeAmount)
.subtract(headquartersDeduction)
.subtract(koiDiscount)
.subtract(collegeRankReward)
.subtract(drawPoolAmount)
.subtract(deliveryRankReward)
.subtract(refundAmount)
.subtract(afterSaleAmount)
.subtract(couponDiscount)
.subtract(smsCost)
.subtract(contentAuditCost)
.subtract(realNameCost);
.subtract(realNameCost)
.subtract(rewardTotalAmount)
.subtract(settledAmount);
vo.setOrderCount((long) orders.size());
vo.setGrossFlowAmount(money(grossFlow));
@ -210,9 +231,11 @@ public class AdminDataStatisticsController {
vo.setKoiDiscountAmount(money(koiDiscount));
vo.setCouponDiscountAmount(money(couponDiscount));
vo.setOnTimeRate(onTimeRate(deliveries));
vo.setCustomerAverageAmount(orders.isEmpty() ? BigDecimal.ZERO : money(customerAverageBase.divide(BigDecimal.valueOf(orders.size()), 4, RoundingMode.HALF_UP)));
vo.setCustomerAverageAmount(orders.isEmpty() ? BigDecimal.ZERO : money(goodsAndPackage.divide(BigDecimal.valueOf(orders.size()), 4, RoundingMode.HALF_UP)));
vo.setHeadquartersDeductionAmount(money(headquartersDeduction));
vo.setActualIncomeAmount(money(actualIncome));
vo.setActualIncomeAmount(actualIncomeAvailable ? money(actualIncome) : BigDecimal.ZERO);
vo.setActualIncomeAvailable(actualIncomeAvailable);
vo.setSettledAmount(money(settledAmount));
vo.setSmsCount(smsCount);
vo.setContentAuditCount(contentAuditCount);
vo.setRealNameAuthCount(realNameAuthCount);
@ -243,6 +266,28 @@ public class AdminDataStatisticsController {
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
private BigDecimal sumSettledAmount(String regionId, DateRange range) {
List<MallSettlementRecord> settlementRecords = mallSettlementRecordMapper.selectList(new LambdaQueryWrapper<MallSettlementRecord>()
.eq(StringUtils.isNotBlank(regionId), MallSettlementRecord::getRegionId, regionId)
.eq(MallSettlementRecord::getStatus, 1)
.ge(MallSettlementRecord::getCreateTime, range.start)
.le(MallSettlementRecord::getCreateTime, range.end));
return settlementRecords.stream()
.map(MallSettlementRecord::getSettlementAmount)
.map(this::amount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
private boolean isRefundedOrder(MallOrder order, Set<String> refundedOrderIds) {
return (order.getStatus() != null && order.getStatus() == 8)
|| refundedOrderIds.contains(order.getId());
}
private boolean isActualIncomeAvailable(DateRange range) {
long days = ChronoUnit.DAYS.between(range.startDate, range.endDate) + 1;
return days <= 31 && range.endDate.isBefore(LocalDate.now());
}
private BigDecimal onTimeRate(List<MallDeliveryOrder> deliveries) {
if (deliveries == null || deliveries.isEmpty()) {
return BigDecimal.ZERO;

121
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java

@ -45,11 +45,13 @@ import cc.hiver.mall.service.ShopTakeawayService;
import cc.hiver.mall.service.ShopUserService;
import cc.hiver.mall.utils.UpdateUtils;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
@ -57,10 +59,8 @@ import org.springframework.data.domain.PageImpl;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -71,6 +71,9 @@ import java.util.stream.Collectors;
@Api(tags = "店铺管理接口")
@RequestMapping("/hiver/app/shop/")
public class ShopController {
private static final String GROUP_BUY_DEFAULT_PAGE_CACHE_PREFIX = "GROUP_BUY_DEFAULT_SHOP_PAGE:";
private static final long GROUP_BUY_DEFAULT_PAGE_CACHE_SECONDS = 5 * 60L;
@Autowired
private ShopService shopService;
@ -303,16 +306,35 @@ public class ShopController {
@ApiOperation("多条件分页获取公司列表")
public Result<Page<Shop>> getByCondition(Shop shop,
PageVo pageVo) {
long queryStartTime = System.currentTimeMillis();
String regionId = shop.getRegionId();
boolean adminQuery = CharSequenceUtil.isNotBlank(shop.getShopIcon());
String defaultPageCacheKey = buildDefaultGroupBuyPageCacheKey(shop, pageVo, adminQuery);
if (CharSequenceUtil.isNotBlank(defaultPageCacheKey)) {
String cacheJson = redisTemplateHelper.get(defaultPageCacheKey);
if (CharSequenceUtil.isNotBlank(cacheJson)) {
try {
ShopListPageCache cache = JSONUtil.toBean(cacheJson, ShopListPageCache.class);
if (cache != null && cache.getContent() != null) {
Page<Shop> pageResult = new PageImpl<>(cache.getContent(), PageUtil.initPage(pageVo), cache.getTotalElements());
return new ResultUtil<Page<Shop>>().setData(pageResult);
}
} catch (Exception e) {
redisTemplateHelper.delete(defaultPageCacheKey);
log.warn("饭团默认店铺列表缓存解析失败,已回源: key={}", defaultPageCacheKey, e);
}
}
}
if (CharSequenceUtil.isNotBlank(regionId)) {
List<Object> values = redisTemplateHelper.hValues("SHOP_CACHE:" + regionId);
if (values != null && !values.isEmpty()) {
List<Shop> allShops = new ArrayList<>();
for (Object v : values) {
ShopCacheDTO dto = JSONUtil.toBean(v.toString(), ShopCacheDTO.class);
ShopCacheDTO dto = parseShopCacheBase(v.toString());
Shop s = dto.getShop();
s.setProducts(dto.getProducts());
if (s == null) {
continue;
}
s.setShopTakeaway(dto.getShopTakeaway());
if (CharSequenceUtil.isNotBlank(shop.getShopArea())) {
if (!shop.getShopArea().equals(s.getShopArea())) {
@ -458,6 +480,8 @@ public class ShopController {
fillGroupDeliveryTime(pageList, regionId);
Page<Shop> pageResult = new PageImpl<>(pageList, PageUtil.initPage(pageVo), allShops.size());
cacheDefaultGroupBuyPage(defaultPageCacheKey, pageList, allShops.size());
logSlowShopListQuery("redis", queryStartTime, allShops.size(), pageList.size(), regionId);
return new ResultUtil<Page<Shop>>().setData(pageResult);
}
}
@ -483,27 +507,84 @@ public class ShopController {
}
IPage<ProductPageVO> productList = shopService.getShareList(productPageQuery);
Map<String, List<ProductPageVO>> productsByShopId = new HashMap<>();
if(productList.getRecords().size() > 0){
productList.getRecords().forEach(productPageVO -> {
productsByShopId.computeIfAbsent(productPageVO.getShopId(), key -> new ArrayList<>()).add(productPageVO);
});
}
Map<String, ShopTakeaway> takeawayByShopId = new HashMap<>();
for(ShopTakeaway shopTakeawa : shopTakeaways) {
takeawayByShopId.put(shopTakeawa.getShopId(), shopTakeawa);
}
page.getContent().forEach(e -> {
final List<ProductPageVO> products = new ArrayList<>();
if(productList.getRecords().size() > 0){
productList.getRecords().forEach(productPageVO -> {
if (e.getId().equals(productPageVO.getShopId())) {
products.add(productPageVO);
}
});
}
e.setProducts(products);
for(ShopTakeaway shopTakeawa : shopTakeaways) {
if (e.getId().equals(shopTakeawa.getShopId())) {
e.setShopTakeaway(shopTakeawa);
}
}
e.setProducts(productsByShopId.getOrDefault(e.getId(), new ArrayList<>()));
e.setShopTakeaway(takeawayByShopId.get(e.getId()));
});
fillGroupDeliveryTime(page.getContent(), shop.getRegionId());
}
cacheDefaultGroupBuyPage(defaultPageCacheKey, page.getContent(), page.getTotalElements());
logSlowShopListQuery("db", queryStartTime, page.getTotalElements(), page.getContent().size(), shop.getRegionId());
return new ResultUtil<Page<Shop>>().setData(page);
}
private String buildDefaultGroupBuyPageCacheKey(Shop shop, PageVo pageVo, boolean adminQuery) {
if (shop == null || pageVo == null || adminQuery || CharSequenceUtil.isBlank(shop.getRegionId())) {
return null;
}
int pageNumber = pageVo.getPageNumber() > 0 ? pageVo.getPageNumber() : 1;
int pageSize = pageVo.getPageSize() > 0 ? pageVo.getPageSize() : 10;
if (pageNumber != 1 || pageSize != 10) {
return null;
}
if (!Integer.valueOf(1).equals(shop.getMerchantType())) {
return null;
}
if (shop.getIsStudent() != null ||
CharSequenceUtil.isNotBlank(shop.getShopArea()) ||
CharSequenceUtil.isNotBlank(shop.getShopType()) ||
CharSequenceUtil.isNotBlank(shop.getKeyWord()) ||
CharSequenceUtil.isNotBlank(shop.getShopName())) {
return null;
}
if (!"shoprank".equals(pageVo.getSort()) || !"desc".equalsIgnoreCase(pageVo.getOrder())) {
return null;
}
return GROUP_BUY_DEFAULT_PAGE_CACHE_PREFIX + shop.getRegionId() + ":" + pageSize;
}
private ShopCacheDTO parseShopCacheBase(String cacheJson) {
JSONObject jsonObject = JSONUtil.parseObj(cacheJson);
ShopCacheDTO dto = new ShopCacheDTO();
dto.setShop(jsonObject.getBean("shop", Shop.class));
dto.setShopTakeaway(jsonObject.getBean("shopTakeaway", ShopTakeaway.class));
return dto;
}
private void logSlowShopListQuery(String source, long startTime, long totalElements, int pageSize, String regionId) {
long cost = System.currentTimeMillis() - startTime;
if (cost > 300) {
log.warn("app/shop/getByCondition slow source={}, cost={}ms, regionId={}, total={}, pageSize={}",
source, cost, regionId, totalElements, pageSize);
}
}
private void cacheDefaultGroupBuyPage(String cacheKey, List<Shop> content, long totalElements) {
if (CharSequenceUtil.isBlank(cacheKey) || content == null) {
return;
}
ShopListPageCache cache = new ShopListPageCache();
cache.setContent(content);
cache.setTotalElements(totalElements);
redisTemplateHelper.set(cacheKey, JSONUtil.toJsonStr(cache), GROUP_BUY_DEFAULT_PAGE_CACHE_SECONDS, TimeUnit.SECONDS);
}
@Data
private static class ShopListPageCache {
private List<Shop> content;
private long totalElements;
}
private void fillGroupDeliveryTime(List<Shop> shops, String regionId) {
if (shops == null || shops.isEmpty()) {
return;

21
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/UserAddressController.java

@ -36,7 +36,7 @@ public class UserAddressController {
if (result) {
// 如果传过来的就是默认地址,可以调用把其他的设置为非默认
if (userAddress.getIsDefault() != null && userAddress.getIsDefault() == 1) {
userAddressService.setDefaultAddress(userAddress.getId(), userAddress.getUserId());
userAddressService.setDefaultAddress(userAddress.getId(), userAddress.getUserId(), userAddress.getRegionId());
}
return ResultUtil.success("添加成功");
} else {
@ -52,12 +52,18 @@ public class UserAddressController {
}
// 不能修改别人的地址
UserAddress old = userAddressService.getById(userAddress.getId());
if (old == null) {
return ResultUtil.error("地址不存在");
}
if (StringUtils.isBlank(userAddress.getRegionId())) {
userAddress.setRegionId(old.getRegionId());
}
boolean result = userAddressService.updateById(userAddress);
if (result) {
// 如果改成了默认地址,则更新其他为非默认
if (userAddress.getIsDefault() != null && userAddress.getIsDefault() == 1) {
userAddressService.setDefaultAddress(userAddress.getId(), old.getUserId());
userAddressService.setDefaultAddress(userAddress.getId(), old.getUserId(), userAddress.getRegionId());
}
return ResultUtil.success("修改成功");
} else {
@ -81,11 +87,12 @@ public class UserAddressController {
@RequestMapping(value = "/list", method = RequestMethod.GET)
@ApiOperation(value = "获取当前用户的收货地址列表")
public Result list(@RequestParam("userId") String userId) {
public Result list(@RequestParam("userId") String userId,
@RequestParam(value = "regionId", required = false) String regionId) {
if (userId == null || StringUtils.isEmpty(userId)) {
return ResultUtil.error("未获取到当前登录用户信息");
}
List<UserAddressVo> list = userAddressService.getAddressListByUserId(userId);
List<UserAddressVo> list = userAddressService.getAddressListByUserId(userId, regionId);
return new ResultUtil<List<UserAddressVo>>().setData(list);
}
@ -101,11 +108,13 @@ public class UserAddressController {
@RequestMapping(value = "/setDefault", method = RequestMethod.POST)
@ApiOperation(value = "设置默认收货地址")
public Result setDefault(@RequestParam("id") String id,@RequestParam("userId") String userId) {
public Result setDefault(@RequestParam("id") String id,
@RequestParam("userId") String userId,
@RequestParam(value = "regionId", required = false) String regionId) {
if (StringUtils.isBlank(id)) {
return ResultUtil.error("地址ID不能为空");
}
userAddressService.setDefaultAddress(id, userId);
userAddressService.setDefaultAddress(id, userId, regionId);
return ResultUtil.success("设置成功");
}

52
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerController.java

@ -2,6 +2,7 @@ package cc.hiver.mall.controller;
import cc.hiver.core.common.constant.CommonConstant;
import cc.hiver.core.common.constant.WorkerConstant;
import cc.hiver.core.common.redis.RedisTemplateHelper;
import cc.hiver.core.common.utils.BeanUtils;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.utils.SecurityUtil;
@ -26,6 +27,7 @@ import cc.hiver.mall.utils.WaitOrderCacheUtil;
import cc.hiver.mall.utils.WorkerOrderCacheUtil;
import cc.hiver.mall.utils.WorkerRedisCacheUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
@ -41,6 +43,7 @@ import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 配送员管理接口
@ -55,6 +58,9 @@ import java.util.*;
@Transactional
public class WorkerController {
private static final String ONLINE_WORKER_AREA_COUNT_CACHE_PREFIX = "WORKER_AREA_ONLINE_COUNT:";
private static final long ONLINE_WORKER_AREA_COUNT_CACHE_SECONDS = 10L;
@Autowired
private WorkerService workerService;
@ -85,6 +91,9 @@ public class WorkerController {
@Autowired
private SecurityUtil securityUtil;
@Autowired
private RedisTemplateHelper redisTemplateHelper;
@RequestMapping(value = "/getByCondition", method = RequestMethod.POST)
@ApiOperation(value = "多条件分页获取订单列表")
public Result<org.springframework.data.domain.Page<Worker>> getByCondition(@RequestBody WorkerQueryVO worker) {
@ -255,6 +264,29 @@ public class WorkerController {
return ResultUtil.success("操作成功");
}
@RequestMapping(value = "/admin/fullTime/{workerId}", method = RequestMethod.POST)
@ApiOperation(value = "后台设置配送员全职状态")
public Result changeFullTime(@ApiParam("配送员唯一id标识") @PathVariable String workerId,
@RequestParam("isFullTime") Integer isFullTime) {
Worker worker = workerService.get(workerId);
if (worker == null) {
return ResultUtil.error("配送员不存在");
}
if (isFullTime == null || (isFullTime != 0 && isFullTime != 1)) {
return ResultUtil.error("全职状态参数错误");
}
workerService.changeFullTime(workerId, isFullTime);
worker.setIsFullTime(isFullTime);
if (StrUtil.isNotBlank(worker.getRegion())) {
WorkerRedisVo workerRedisVo = workerRedisCacheUtil.get(worker.getRegion(), worker.getWorkerId());
if (workerRedisVo != null) {
workerRedisVo.setWorker(worker);
workerRedisCacheUtil.update(worker.getRegion(), workerRedisVo);
}
}
return ResultUtil.success("操作成功");
}
/**
* 配送员上线
*
@ -281,7 +313,7 @@ public class WorkerController {
workerVO.setWorkerId(worker.getWorkerId());
worker.setIsOnLine(1);
workerVO.setWorker(worker);
List<WorkerRelaPrice> workerRelaPriceList = workerRelaPriceService.selectByWorkerId(worker.getWorkerId());
List<WorkerRelaPrice> workerRelaPriceList = workerRelaPriceService.selectByWorkerIdAndRegionId(worker.getWorkerId(), worker.getRegion());
workerVO.setWorkerRelaPriceList(workerRelaPriceList);
workerRedisCacheUtil.put(worker.getRegion(),workerVO);
return ResultUtil.success("上线成功");
@ -401,6 +433,8 @@ public class WorkerController {
WorkerRelaPrice matchedRule = null;
for (WorkerRelaPrice rp : vo.getWorkerRelaPriceList()) {
// 缓存可能残留旧数据,规则也要限定当前校区
if (StrUtil.isNotBlank(dto.getRegionId()) && !dto.getRegionId().equals(rp.getRegionId())) continue;
// 规则必须接收指派
if (rp.getGetPushOrder() == null || rp.getGetPushOrder() != 1) continue;
// 取货区域匹配
@ -455,6 +489,7 @@ public class WorkerController {
matchVO.setScore(w.getScore());
matchVO.setAvgTime(w.getAvgTime());
matchVO.setRebateAmount(w.getRebateAmount());
matchVO.setIsFullTime(w.getIsFullTime());
matchVO.setHighFloorFee(w.getHighFloorFee());
matchVO.setDeliveryLocation(w.getDeliveryLocation());
matchVO.setOrderBkge(matchedRule.getOrderBkge());
@ -478,6 +513,8 @@ public class WorkerController {
comparator = Comparator.comparing(WorkerMatchVO::getAvgTime,
Comparator.nullsLast(Comparator.naturalOrder()));
}
comparator = Comparator.comparing(WorkerMatchVO::getIsFullTime,
Comparator.nullsLast(Comparator.reverseOrder())).thenComparing(comparator);
// 二级排序:rebateAmount 倒序
comparator = comparator.thenComparing(WorkerMatchVO::getRebateAmount,
Comparator.nullsLast(Comparator.reverseOrder()));
@ -527,6 +564,17 @@ public class WorkerController {
@RequestMapping(value = "/getOnlineWorkerByArea", method = RequestMethod.GET)
@ApiOperation(value = "查询各食堂区域在线配送员数量")
public Result<List<WorkerAreaOnlineCountVO>> getOnlineWorkerByArea(@RequestParam(value = "parentId")String parentId) {
String cacheKey = ONLINE_WORKER_AREA_COUNT_CACHE_PREFIX + parentId;
String cacheJson = redisTemplateHelper.get(cacheKey);
if (StrUtil.isNotBlank(cacheJson)) {
try {
List<WorkerAreaOnlineCountVO> cacheList = JSONUtil.toList(cacheJson, WorkerAreaOnlineCountVO.class);
return new ResultUtil<List<WorkerAreaOnlineCountVO>>().setData(cacheList);
} catch (Exception e) {
redisTemplateHelper.delete(cacheKey);
log.warn("在线配送员区域统计缓存解析失败,已回源: key={}", cacheKey, e);
}
}
//parentId就是regionId
List<WorkerRedisVo> workerRedisVoList = workerRedisCacheUtil.getAll(parentId);
if (workerRedisVoList != null && !workerRedisVoList.isEmpty()) {
@ -564,9 +612,11 @@ public class WorkerController {
countVO.setOnlineWorkerCount(workers != null ? workers.size() : 0);
result.add(countVO);
}
redisTemplateHelper.set(cacheKey, JSONUtil.toJsonStr(result), ONLINE_WORKER_AREA_COUNT_CACHE_SECONDS, TimeUnit.SECONDS);
return new ResultUtil<List<WorkerAreaOnlineCountVO>>().setData(result);
}
List<WorkerAreaOnlineCountVO> list = workerRelaPriceMapper.getOnlineWorkerCountByCanteenArea(parentId);
redisTemplateHelper.set(cacheKey, JSONUtil.toJsonStr(list), ONLINE_WORKER_AREA_COUNT_CACHE_SECONDS, TimeUnit.SECONDS);
return new ResultUtil<List<WorkerAreaOnlineCountVO>>().setData(list);
}

59
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/WorkerRelaPriceController.java

@ -65,17 +65,20 @@ public class WorkerRelaPriceController {
@RequestMapping(value = "/getByWorkerId", method = RequestMethod.GET)
@ApiOperation("根据配送员id获取")
public Result<WorkerRealPriceVo> getByProductId(@RequestParam(value = "workerId") String workerId) {
public Result<WorkerRealPriceVo> getByProductId(@RequestParam(value = "workerId") String workerId,
@RequestParam(value = "regionId", required = false) String regionId) {
WorkerRealPriceVo workerRealPriceVo = new WorkerRealPriceVo();
Worker worker = workerService.findByWorkerId(workerId);
if(worker != null){
regionId = resolveRegionId(regionId, worker);
workerRealPriceVo.setRegionId(regionId);
workerRealPriceVo.setWorkerName(worker.getWorkerName());
workerRealPriceVo.setMobile(worker.getMobile());
workerRealPriceVo.setGetPushOrder(worker.getGetPushOrder());
workerRealPriceVo.setCardPicture(worker.getCardPicture());
workerRealPriceVo.setHighFloorFee(worker.getHighFloorFee());
workerRealPriceVo.setDeliveryLocation(worker.getDeliveryLocation());
final List<WorkerRelaPrice> workerRelaPriceList = workerRelaPriceService.selectByWorkerId(workerId);
final List<WorkerRelaPrice> workerRelaPriceList = selectWorkerRelaPrices(workerId, regionId);
workerRealPriceVo.setWorkerRelaPriceList(workerRelaPriceList);
}
return new ResultUtil<WorkerRealPriceVo>().setData(workerRealPriceVo);
@ -86,18 +89,20 @@ public class WorkerRelaPriceController {
public Result<User> batchAdd(@RequestBody WorkerRealPriceVo workerRealPriceVo) {
User user = userService.findById(workerRealPriceVo.getUserId());
Worker worker = workerService.findByUserId(workerRealPriceVo.getUserId());
String regionId = resolveRegionId(workerRealPriceVo.getRegionId(), worker);
workerRealPriceVo.setRegionId(regionId);
if (CharSequenceUtil.isNotBlank(workerRealPriceVo.getWorkerName())) {
Long auditUserId = Long.valueOf(workerRealPriceVo.getUserId());
IeAuditResult audit = auditService.audit("worker-name", auditUserId, auditUserId,
workerRealPriceVo.getWorkerName(), worker.getRegion());
workerRealPriceVo.getWorkerName(), regionId);
if (Boolean.TRUE.equals(audit.getBlocked())) {
throw new RuntimeException("配送员名称未通过审核,请换一个更合适的名称");
}
workerRealPriceVo.setWorkerName(audit.getFilteredContent());
}
List<WorkerRelaPrice> workerRelaPriceList = workerRelaPriceService.selectByWorkerId(worker.getWorkerId());
List<WorkerRelaPrice> workerRelaPriceList = selectWorkerRelaPrices(worker.getWorkerId(), regionId);
//更新配送员信息
worker.setWorkerName(workerRealPriceVo.getWorkerName());
worker.setCardPicture(workerRealPriceVo.getCardPicture());
@ -119,19 +124,20 @@ public class WorkerRelaPriceController {
});
}
workerRelaPrice.setWorkerId(worker.getWorkerId());
workerRelaPrice.setRegionId(regionId);
});
}
if(workerRealPriceVo != null){
workerRelaPriceService.deleteByWorkerId(worker.getWorkerId());
deleteWorkerRelaPrices(worker.getWorkerId(), regionId);
}
final boolean b = workerRelaPriceService.saveBatch(workerRealPriceVo.getWorkerRelaPriceList());
if (b) {
//更新缓存
WorkerRedisVo workerRedisVo = workerRedisCacheUtil.get(worker.getRegion(), worker.getWorkerId());
WorkerRedisVo workerRedisVo = workerRedisCacheUtil.get(regionId, worker.getWorkerId());
if(workerRedisVo != null){
workerRedisVo.setWorker(worker);
workerRedisVo.setWorkerRelaPriceList(workerRealPriceVo.getWorkerRelaPriceList());
workerRedisCacheUtil.update(worker.getRegion(), workerRedisVo);
workerRedisVo.setWorkerRelaPriceList(selectWorkerRelaPrices(worker.getWorkerId(), regionId));
workerRedisCacheUtil.update(regionId, workerRedisVo);
}
return new ResultUtil<User>().setData(user);
} else {
@ -143,6 +149,7 @@ public class WorkerRelaPriceController {
@ApiOperation("批量更新")
public Result batchUpdate(@RequestBody WorkerRealPriceVo workerRealPriceVo) {
Worker worker = workerService.findByUserId(workerRealPriceVo.getUserId());
String regionId = resolveRegionId(workerRealPriceVo.getRegionId(), worker);
//更新配送员信息 接受指派单
worker.setGetPushOrder(workerRealPriceVo.getGetPushOrder());
workerService.update(worker);
@ -150,23 +157,37 @@ public class WorkerRelaPriceController {
final boolean b = workerRelaPriceService.saveOrUpdateBatch(workerRealPriceVo.getWorkerRelaPriceList());
if (b) {
//更新缓存
WorkerRedisVo workerRedisVo = workerRedisCacheUtil.get(worker.getRegion(), worker.getWorkerId());
WorkerRedisVo workerRedisVo = workerRedisCacheUtil.get(regionId, worker.getWorkerId());
if(workerRedisVo != null){
workerRedisVo.getWorker().setGetPushOrder(workerRealPriceVo.getGetPushOrder());
if(workerRedisVo.getWorkerRelaPriceList() != null){
workerRedisVo.getWorkerRelaPriceList().forEach(workerRelaPrice -> {
workerRealPriceVo.getWorkerRelaPriceList().forEach(workerRelaPrice1 -> {
if(workerRelaPrice.getId() !=null && workerRelaPrice.getId().equals(workerRelaPrice1.getId())){
workerRelaPrice.setGetPushOrder(workerRelaPrice1.getGetPushOrder());
}
});
});
}
workerRedisCacheUtil.update(worker.getRegion(), workerRedisVo);
workerRedisVo.setWorkerRelaPriceList(selectWorkerRelaPrices(worker.getWorkerId(), regionId));
workerRedisCacheUtil.update(regionId, workerRedisVo);
}
return ResultUtil.success("更新成功!");
} else {
return ResultUtil.error("保存失败!");
}
}
private String resolveRegionId(String regionId, Worker worker) {
if (CharSequenceUtil.isNotBlank(regionId)) {
return regionId;
}
return worker == null ? null : worker.getRegion();
}
private List<WorkerRelaPrice> selectWorkerRelaPrices(String workerId, String regionId) {
if (CharSequenceUtil.isNotBlank(regionId)) {
return workerRelaPriceService.selectByWorkerIdAndRegionId(workerId, regionId);
}
return workerRelaPriceService.selectByWorkerId(workerId);
}
private void deleteWorkerRelaPrices(String workerId, String regionId) {
if (CharSequenceUtil.isNotBlank(regionId)) {
workerRelaPriceService.deleteByWorkerIdAndRegionId(workerId, regionId);
return;
}
workerRelaPriceService.deleteByWorkerId(workerId);
}
}

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/WorkerRelaPriceMapper.java

@ -18,8 +18,12 @@ public interface WorkerRelaPriceMapper extends BaseMapper<WorkerRelaPrice> {
List<WorkerRelaPrice> selectByWorkerId(String workerId);
List<WorkerRelaPrice> selectByWorkerIdAndRegionId(@Param("workerId") String workerId, @Param("regionId") String regionId);
void deleteByWorkerId(String workerId);
void deleteByWorkerIdAndRegionId(@Param("workerId") String workerId, @Param("regionId") String regionId);
/**
* 查询匹配条件的配送员列表联查 t_worker_rela_pricet_workermall_delivery_order
* <p>MyBatis-Plus 分页拦截器会根据 page 参数自动追加 COUNT LIMIT/OFFSET</p>

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallDeliveryOrder.java

@ -111,6 +111,10 @@ public class MallDeliveryOrder implements Serializable {
private String transferPickupCode;
@Transient
@TableField(exist = false)
@ApiModelProperty(value = "商家出餐时间")
private Date shopMakeTime;
@Transient
@TableField(exist = false)
@ApiModelProperty(value = "商品信息")
private List<MallOrderGoods> goodsList;
@TableField(exist = false)

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/UserAddress.java

@ -18,6 +18,9 @@ public class UserAddress extends HiverBaseEntity {
@ApiModelProperty(value = "用户ID/会员ID")
private String userId;
@ApiModelProperty(value = "校区/区域ID")
private String regionId;
@ApiModelProperty(value = "收货人姓名")
private String receiverName;

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/WorkerRelaPrice.java

@ -30,6 +30,9 @@ public class WorkerRelaPrice extends HiverBaseEntity {
@ApiModelProperty(value = "配送员id")
private String workerId;
@ApiModelProperty(value = "校区id")
private String regionId;
@ApiModelProperty(value = "取货区域id")
private String getAreaId;

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/fishmarket/dto/FishCommentDTO.java

@ -5,6 +5,8 @@ import lombok.Data;
@Data
public class FishCommentDTO {
private String goodsId;
private String userName;
private String userAvatar;
private String parentId;
private String replyToUserId;
private String replyToUserName;

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/fishmarket/dto/FishPublishDTO.java

@ -13,6 +13,8 @@ public class FishPublishDTO {
private String publishType;
private String regionId;
private String regionName;
private String userName;
private String userAvatar;
private String title;
private String content;
/** 富文本纯文字内容,用于字数限制和文字审核 */

51
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/fishmarket/service/impl/FishMarketServiceImpl.java

@ -5,6 +5,7 @@ import cc.hiver.core.common.sms.SmsUtil;
import cc.hiver.core.entity.User;
import cc.hiver.core.service.UserService;
import cc.hiver.mall.billing.mq.BillingRecordProducer;
import cc.hiver.mall.campus.service.CampusService;
import cc.hiver.mall.fishmarket.dto.*;
import cc.hiver.mall.fishmarket.entity.*;
import cc.hiver.mall.fishmarket.mapper.*;
@ -105,6 +106,8 @@ public class FishMarketServiceImpl implements FishMarketService {
private StringRedisTemplate stringRedisTemplate;
@Autowired(required = false)
private FishMarketSmsReminderProducer smsReminderProducer;
@Autowired(required = false)
private CampusService campusService;
private static final String SMS_PRODUCTTALK_TEMPLATE = SettingConstant.SMS_TYPE.valueOf("SMS_PRODUCTTALK").name();
private static final String FISH_CHAT_UNREAD_KEY_PREFIX = "fishmarket:unread:chat:";
@ -259,8 +262,8 @@ public class FishMarketServiceImpl implements FishMarketService {
throw new RuntimeException("只能编辑自己的商品");
}
goods.setUserId(user.getId());
goods.setUserName(defaultString(user.getMobile(), user.getUsername()));
goods.setUserAvatar(user.getAvatar());
goods.setUserName(resolveDisplayName(dto.getUserName(), user));
goods.setUserAvatar(resolveDisplayAvatar(dto.getUserAvatar(), user));
goods.setRegionId(dto.getRegionId());
goods.setRegionName(dto.getRegionName());
goods.setTitle(cleanText(dto.getTitle(), 60));
@ -310,8 +313,8 @@ public class FishMarketServiceImpl implements FishMarketService {
throw new RuntimeException("只能编辑自己的求购");
}
want.setUserId(user.getId());
want.setUserName(defaultString(user.getNickname(), user.getUsername()));
want.setUserAvatar(user.getAvatar());
want.setUserName(resolveDisplayName(dto.getUserName(), user));
want.setUserAvatar(resolveDisplayAvatar(dto.getUserAvatar(), user));
want.setRegionId(dto.getRegionId());
want.setRegionName(dto.getRegionName());
want.setTitle(cleanText(dto.getTitle(), 60));
@ -481,8 +484,8 @@ public class FishMarketServiceImpl implements FishMarketService {
comment.setReplyToUserId(StringUtils.defaultIfBlank(dto.getReplyToUserId(), parent == null ? null : parent.getUserId()));
comment.setReplyToUserName(StringUtils.defaultIfBlank(dto.getReplyToUserName(), parent == null ? null : parent.getUserName()));
comment.setUserId(user.getId());
comment.setUserName(defaultString(user.getNickname(), user.getUsername()));
comment.setUserAvatar(user.getAvatar());
comment.setUserName(resolveDisplayName(dto.getUserName(), user));
comment.setUserAvatar(resolveDisplayAvatar(dto.getUserAvatar(), user));
comment.setContent(cleanText(dto.getContent(), 500));
comment.setLikeCount(0);
comment.setAuditStatus(1);
@ -866,7 +869,15 @@ public class FishMarketServiceImpl implements FishMarketService {
requireLogin(user);
int chatUnread = sumUnreadHash(chatUnreadKey(user.getId()));
int commentUnread = sumUnreadHash(commentUnreadKey(user.getId()));
return resultMap("chatUnread", chatUnread, "commentUnread", commentUnread, "fishUnread", chatUnread + commentUnread);
Map<String, Object> summary = resultMap("chatUnread", chatUnread, "commentUnread", commentUnread, "fishUnread", chatUnread + commentUnread);
if (campusService != null) {
try {
summary.putAll(campusService.unreadSummary(user));
} catch (Exception e) {
log.warn("校园圈未读汇总扩展失败,不影响校园二手未读", e);
}
}
return summary;
}
@Override
@ -1756,13 +1767,6 @@ public class FishMarketServiceImpl implements FishMarketService {
recordFishAuditBlock(bizType, bizId, userId, content, result);
throw new RuntimeException(FISH_TEXT_AUDIT_REJECT_MESSAGE);
}
if (aliyunModerationService != null) {
IeAliyunModerationResult aliyun = aliyunModerationService.checkText(content, regionId, bizType, bizId, parseLong(userId));
if (aliyun != null && aliyun.isBlock()) {
recordFishAliyunBlock(bizType, bizId, userId, content, aliyun);
throw new RuntimeException(FISH_TEXT_AUDIT_REJECT_MESSAGE);
}
}
}
private void auditStrictText(String bizType, String bizId, String userId, String content, String regionId) {
@ -1772,12 +1776,10 @@ public class FishMarketServiceImpl implements FishMarketService {
recordFishAuditBlock(bizType, bizId, userId, content, result);
throw new RuntimeException(FISH_TEXT_AUDIT_REJECT_MESSAGE);
}
if (aliyunModerationService != null) {
IeAliyunModerationResult aliyun = aliyunModerationService.checkText(content, regionId, bizType, bizId, parseLong(userId));
if (aliyun != null && (aliyun.isBlock() || isMediumOrHigh(aliyun.getRiskLevel()))) {
recordFishAliyunBlock(bizType, bizId, userId, content, aliyun);
throw new RuntimeException(FISH_TEXT_AUDIT_REJECT_MESSAGE);
}
IeAliyunModerationResult aliyun = result == null ? null : result.getAliyunResult();
if (aliyun != null && (aliyun.isBlock() || isMediumOrHigh(aliyun.getRiskLevel()))) {
recordFishAliyunBlock(bizType, bizId, userId, content, aliyun);
throw new RuntimeException(FISH_TEXT_AUDIT_REJECT_MESSAGE);
}
}
@ -2103,6 +2105,15 @@ public class FishMarketServiceImpl implements FishMarketService {
return StringUtils.isNotBlank(value) ? value : StringUtils.defaultString(fallback);
}
private String resolveDisplayName(String cachedName, User user) {
String name = defaultString(cachedName, user == null ? null : defaultString(user.getNickname(), user.getUsername()));
return cleanText(StringUtils.defaultIfBlank(name, "校园同学"), 20);
}
private String resolveDisplayAvatar(String cachedAvatar, User user) {
return StringUtils.defaultIfBlank(cachedAvatar, user == null ? "" : StringUtils.defaultString(user.getAvatar()));
}
private Long parseLong(String value) {
if (StringUtils.isBlank(value)) return null;
try {

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/controller/IeController.java

@ -201,6 +201,13 @@ public class IeController {
return new ResultUtil<IPage<IeRoomMessage>>().setData(chatService.pageMessages(currentUserId(), roomId, pageNumber, pageSize));
}
@RequestMapping(value = "/rooms/{roomId}/read", method = RequestMethod.POST)
@ApiOperation("标记房间消息已读")
public Result<Object> markRoomRead(@PathVariable Long roomId) {
chatService.markRead(currentUserId(), roomId);
return ResultUtil.success("已读");
}
@RequestMapping(value = "/rooms/{roomId}/streak", method = RequestMethod.GET)
@ApiOperation("查询房间陪伴火花")
public Result<Map<String, Object>> roomStreak(@PathVariable Long roomId) {

64
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeAliyunModerationServiceImpl.java

@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Slf4j
@ -36,7 +37,7 @@ public class IeAliyunModerationServiceImpl implements IeAliyunModerationService
@Value("${ie.aliyun.green.region:cn-shanghai}")
private String region;
@Value("${ie.aliyun.green.text-service:chat_detection}")
@Value("${ie.aliyun.green.text-service:comment_detection_pro}")
private String textService;
@Value("${ie.aliyun.green.image-service:baselineCheck}")
@ -72,11 +73,14 @@ public class IeAliyunModerationServiceImpl implements IeAliyunModerationService
}
private IeAliyunModerationResult doCheckText(String content, String regionId, String bizType, String bizId, Long userId) {
if (useTextModerationPlus()) {
return doCheckTextPlus(content, regionId, bizType, bizId, userId);
}
try {
JSONObject parameters = new JSONObject();
parameters.set("content", content);
TextModerationRequest request = new TextModerationRequest();
request.setService(textService);
request.setService(textServiceCode());
request.setServiceParameters(parameters.toString());
TextModerationResponse response = getClient().textModerationWithOptions(request, runtime());
if (response == null || response.getBody() == null) {
@ -107,6 +111,62 @@ public class IeAliyunModerationServiceImpl implements IeAliyunModerationService
}
}
private boolean useTextModerationPlus() {
String service = textServiceCode().toLowerCase();
return service.endsWith("_pro") || service.contains("comment_detection");
}
private String textServiceCode() {
return textService == null ? "" : textService.trim();
}
private IeAliyunModerationResult doCheckTextPlus(String content, String regionId, String bizType, String bizId, Long userId) {
try {
JSONObject parameters = new JSONObject();
parameters.set("content", content);
parameters.set("dataId", UUID.randomUUID().toString());
TextModerationPlusRequest request = new TextModerationPlusRequest();
request.setService(textServiceCode());
request.setServiceParameters(parameters.toString());
TextModerationPlusResponse response = getClient().textModerationPlusWithOptions(request, runtime());
if (response == null || response.getBody() == null) {
return recordContentAudit(regionId, "text", bizType, bizId, userId,
IeAliyunModerationResult.failed("empty text moderation plus response"));
}
TextModerationPlusResponseBody body = response.getBody();
if (body.getCode() == null || body.getCode() != CODE_OK || body.getData() == null) {
return recordContentAudit(regionId, "text", bizType, bizId, userId,
IeAliyunModerationResult.failed("text moderation plus code=" + body.getCode() + ", msg=" + body.getMessage()));
}
TextModerationPlusResponseBody.TextModerationPlusResponseBodyData data = body.getData();
String riskLevel = data.getRiskLevel();
List<TextModerationPlusResponseBody.TextModerationPlusResponseBodyDataResult> resultList = data.getResult();
if (CharSequenceUtil.isBlank(riskLevel) && (resultList == null || resultList.isEmpty())) {
return recordContentAudit(regionId, "text", bizType, bizId, userId,
IeAliyunModerationResult.pass(null, "text plus pass"));
}
StringBuilder labels = new StringBuilder();
if (resultList != null) {
resultList.forEach(item -> {
if (item == null) return;
if (labels.length() > 0) labels.append(";");
labels.append(item.getLabel())
.append(":")
.append(item.getConfidence())
.append(":")
.append(item.getRiskWords());
});
}
return recordContentAudit(regionId, "text", bizType, bizId, userId,
toFinalResult(riskLevel, "text plus riskLevel=" + riskLevel + ", labels=" + labels
+ ", score=" + data.getScore() + ", service=" + textService));
} catch (Exception e) {
log.warn("阿里云增强版文本审核调用失败", e);
return recordContentAudit(regionId, "text", bizType, bizId, userId,
IeAliyunModerationResult.failed("text moderation plus error: " + e.getMessage()));
}
}
@Override
public IeAliyunModerationResult checkImage(String imageUrl, String regionId, String bizType, String bizId, Long userId) {
if (CharSequenceUtil.isBlank(imageUrl)) {

5
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeSecurityAuditServiceImpl.java

@ -42,8 +42,8 @@ public class IeSecurityAuditServiceImpl implements IeSecurityAuditService {
"手机号", "私加", "私聊加", "进群", "刷单", "兼职日结", "网赚", "返利群", "贷款", "套现",
"博彩", "赌博", "下注", "开盘", "卖号", "买号", "盗号", "洗钱", "跑分", "代实名", "出售银行卡",
"收银行卡", "身份证代办", "发定位", "发照片", "要照片", "真实姓名", "宿舍号", "寝室号", "线下见面",
"来我宿舍", "去你宿舍", "约吗", "微信", "法轮功", "草一下", "c一下", "艹一下", "干一下", "逼",
"几把", "鸡吧", "代课"
"来我宿舍", "去你宿舍", "约吗", "微信", "法轮功", "草一下", "c一下", "艹一下", "干一下",
"几把", "鸡吧", "代课", "草拟吗", "双飞", "三飞", "3P", "小bb", "小BB", "小b"
);
private volatile SensitiveWordBs cachedWordBs;
@ -123,6 +123,7 @@ public class IeSecurityAuditServiceImpl implements IeSecurityAuditService {
if (!Boolean.TRUE.equals(result.getBlocked())) {
IeAliyunModerationResult aliResult = aliyunModerationService.checkText(content, regionId, bizType,
bizId == null ? null : String.valueOf(bizId), userId);
result.setAliyunResult(aliResult);
if (aliResult.isBlock()) {
result.setAuditStatus(IeConstants.AUDIT_BLOCK);
result.setRiskLevel(IeConstants.RISK_HIGH);

1
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeAuditResult.java

@ -14,4 +14,5 @@ public class IeAuditResult {
private Boolean blocked;
private List<String> hitWords = new ArrayList<>();
private List<String> hitCategories = new ArrayList<>();
private IeAliyunModerationResult aliyunResult;
}

12
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdminServiceImpl.java

@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@ -90,6 +91,10 @@ public class PlanetAdminServiceImpl implements PlanetAdminService {
return c.getTime();
}
private String genPeriodNo(Date drawTime) {
return new SimpleDateFormat("yyyyMMdd").format(drawTime);
}
private void refreshPoolRewardAmount(String poolId) {
if (StringUtils.isEmpty(poolId)) {
return;
@ -132,6 +137,10 @@ public class PlanetAdminServiceImpl implements PlanetAdminService {
@Override
public PlanetPool savePool(PlanetPool pool) {
if (pool.getDrawTime() == null) {
pool.setDrawTime(nextDrawTime(new Date()));
}
pool.setPeriodNo(genPeriodNo(pool.getDrawTime()));
if (StringUtils.isEmpty(pool.getId())) {
pool.setId(genId());
if (pool.getStatus() == null) {
@ -146,9 +155,6 @@ public class PlanetAdminServiceImpl implements PlanetAdminService {
if (pool.getWinnerCount() == null) {
pool.setWinnerCount(0);
}
if (pool.getDrawTime() == null) {
pool.setDrawTime(nextDrawTime(new Date()));
}
pool.setCreateTime(new Date());
pool.setUpdateTime(new Date());
poolMapper.insert(pool);

14
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java

@ -181,13 +181,14 @@ public class PlanetDrawServiceImpl implements PlanetDrawService {
private PlanetPool createDefaultPool(String regionId) {
final Date now = new Date();
final Date drawTime = nextDrawTime(now);
final PlanetPool pool = new PlanetPool();
pool.setId(UUID.randomUUID().toString().replace("-", ""));
pool.setRegionId(regionId);
pool.setPeriodNo(genPeriodNo());
pool.setPeriodNo(genPeriodNo(drawTime));
pool.setTitle("白嫖星球·本期瓜分");
pool.setPoolAmount(BigDecimal.ZERO);
pool.setDrawTime(nextDrawTime(now));
pool.setDrawTime(drawTime);
pool.setJoinCount(0);
pool.setTicketTotal(0);
pool.setWinnerCount(0);
@ -337,13 +338,14 @@ public class PlanetDrawServiceImpl implements PlanetDrawService {
private void createNextPool(PlanetPool prev) {
final Date now = new Date();
final Date drawTime = nextDrawTime(now);
final PlanetPool pool = new PlanetPool();
pool.setId(UUID.randomUUID().toString().replace("-", ""));
pool.setRegionId(prev.getRegionId());
pool.setPeriodNo(genPeriodNo());
pool.setPeriodNo(genPeriodNo(drawTime));
pool.setTitle(prev.getTitle());
pool.setPoolAmount(prev.getPoolAmount());
pool.setDrawTime(nextDrawTime(now));
pool.setDrawTime(drawTime);
pool.setJoinCount(0);
pool.setTicketTotal(0);
pool.setWinnerCount(0);
@ -564,8 +566,8 @@ public class PlanetDrawServiceImpl implements PlanetDrawService {
return usable.get(usable.size() - 1);
}
private String genPeriodNo() {
return "P" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
private String genPeriodNo(Date drawTime) {
return new SimpleDateFormat("yyyyMMdd").format(drawTime);
}
/**

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerMatchVO.java

@ -40,6 +40,9 @@ public class WorkerMatchVO {
@ApiModelProperty("交易保障金")
private BigDecimal rebateAmount;
@ApiModelProperty("是否全职配送员:0否 1是")
private Integer isFullTime;
@ApiModelProperty("超高层额外费用")
private BigDecimal highFloorFee;

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/WorkerRealPriceVo.java

@ -22,6 +22,9 @@ public class WorkerRealPriceVo implements Serializable {
@ApiModelProperty(value = " 配送规则")
private String userId;
@ApiModelProperty(value = "校区id")
private String regionId;
@ApiModelProperty(value = " 配送规则")
private String workerName;

6
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/UserAddressService.java

@ -14,15 +14,17 @@ public interface UserAddressService extends IService<UserAddress> {
/**
* 查询用户收货地址列表
* @param userId 用户ID
* @param regionId 校区/区域ID
* @return 地址列表
*/
List<UserAddressVo> getAddressListByUserId(String userId);
List<UserAddressVo> getAddressListByUserId(String userId, String regionId);
/**
* 设置默认地址
* @param id 地址ID
* @param userId 用户ID
* @param regionId 校区/区域ID
*/
void setDefaultAddress(String id, String userId);
void setDefaultAddress(String id, String userId, String regionId);
}

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/WorkerRelaPriceService.java

@ -11,5 +11,9 @@ public interface WorkerRelaPriceService extends IService<WorkerRelaPrice> {
List<WorkerRelaPrice> selectByWorkerId(String workerId);
List<WorkerRelaPrice> selectByWorkerIdAndRegionId(String workerId, String regionId);
void deleteByWorkerId(String workerId);
void deleteByWorkerIdAndRegionId(String workerId, String regionId);
}

8
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/ShopServiceImpl.java

@ -68,6 +68,8 @@ import java.util.Map;
@Service
@Transactional
public class ShopServiceImpl implements ShopService {
private static final String GROUP_BUY_DEFAULT_PAGE_CACHE_PREFIX = "GROUP_BUY_DEFAULT_SHOP_PAGE:";
@Autowired
private ShopDao shopDao;
@ -328,6 +330,7 @@ public class ShopServiceImpl implements ShopService {
if (CharSequenceUtil.isBlank(regionId)) {
return;
}
removeGroupBuyDefaultPageCache(regionId);
Shop shop = shopDao.getById(shopId);
if (shop == null) {
removeShopCache(shopId, regionId);
@ -368,6 +371,7 @@ public class ShopServiceImpl implements ShopService {
if (CharSequenceUtil.isBlank(regionId)) {
return;
}
removeGroupBuyDefaultPageCache(regionId);
String redisKey = "SHOP_CACHE:" + regionId;
redisTemplateHelper.hDelete(redisKey, shopId);
@ -376,4 +380,8 @@ public class ShopServiceImpl implements ShopService {
redisTemplateHelper.delete(productsRedisKey);
}
private void removeGroupBuyDefaultPageCache(String regionId) {
redisTemplateHelper.delete(GROUP_BUY_DEFAULT_PAGE_CACHE_PREFIX + regionId + ":10");
}
}

41
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java

@ -689,14 +689,18 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
@Override
public void arriveShop(String deliveryId, String workerId) {
checkWorkerAndStatus(deliveryId, workerId, STATUS_WAIT_PICKUP);
Date arriveTime = new Date();
LambdaUpdateWrapper<MallDeliveryOrder> uw = new LambdaUpdateWrapper<>();
uw.eq(MallDeliveryOrder::getId, deliveryId)
.set(MallDeliveryOrder::getArriveTime, new Date());
.eq(MallDeliveryOrder::getWorkerId, workerId)
.eq(MallDeliveryOrder::getStatus, STATUS_WAIT_PICKUP)
.set(MallDeliveryOrder::getArriveTime, arriveTime);
this.update(uw);
//更新缓存
MallDeliveryOrder delivery = workerOrderCacheUtil.get(workerId, deliveryId);
if(delivery != null){
delivery.setArriveTime(new Date());
delivery.setArriveTime(arriveTime);
workerOrderCacheUtil.update(workerId,delivery);
}
}
@ -1003,6 +1007,16 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
return;
}
java.util.Map<String, Date> shopMakeTimeMap = new java.util.HashMap<>();
List<MallOrder> orders = mallOrderService.listByIds(new java.util.ArrayList<>(allOrderIdsToQuery));
if (orders != null) {
for (MallOrder order : orders) {
if (order != null && StringUtils.isNotBlank(order.getId()) && order.getShopMakeTime() != null) {
shopMakeTimeMap.put(order.getId(), order.getShopMakeTime());
}
}
}
// 3. 一次 IN 查询所有商品明细
List<MallOrderGoods> allGoods = mallOrderGoodsMapper.selectByOrderIds(new java.util.ArrayList<>(allOrderIdsToQuery));
@ -1015,6 +1029,7 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
java.util.Set<String> targetOrderIds = new java.util.HashSet<>();
if (StringUtils.isNotBlank(vo.getOrderId())) {
targetOrderIds.add(vo.getOrderId());
vo.setShopMakeTime(shopMakeTimeMap.get(vo.getOrderId()));
}
if (StringUtils.isNotBlank(vo.getGroupId()) && groupMap.containsKey(vo.getGroupId())) {
MallOrderGroup group = groupMap.get(vo.getGroupId());
@ -1305,11 +1320,14 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
throw new RuntimeException("重新指定配送员失败");
}
if(delivery.getWorkerId() != null){
Worker worker = workerService.findByWorkerId(delivery.getWorkerId());
if(worker.getClientId() != null){
jPushService.sendPushNotification(worker.getClientId(), "您有一笔新的指定配送单,请及时接单", order.getId());
String pushOrderId = order == null ? delivery.getOrderId() : order.getId();
if (isAdminReassignSource(fromWhere)) {
if (StringUtils.isNotBlank(oldWorkerId) && !StringUtils.equals(oldWorkerId, newWorkerId)) {
sendWorkerJPush(oldWorkerId, "您有一笔订单被改派", pushOrderId);
}
sendWorkerJPush(newWorkerId, "您有一个后台指派单,请及时查看", pushOrderId);
} else {
sendWorkerJPush(newWorkerId, "您有一笔新的指定配送单,请及时接单", pushOrderId);
}
delivery.setWorkerId(newWorkerId);
@ -1349,6 +1367,17 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
|| "manager".equalsIgnoreCase(fromWhere);
}
private void sendWorkerJPush(String workerId, String content, String orderId) {
if (StringUtils.isBlank(workerId) || StringUtils.isBlank(content)) {
return;
}
Worker worker = workerService.findByWorkerId(workerId);
if (worker == null || StringUtils.isBlank(worker.getClientId())) {
return;
}
jPushService.sendPushNotification(worker.getClientId(), content, orderId);
}
private void sendReassignedWorkerWechatNotifyAfterCommit(MallDeliveryOrder delivery) {
if (delivery == null || StringUtils.isBlank(delivery.getOrderId()) || StringUtils.isBlank(delivery.getWorkerId())) {
return;

8
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/UserAddressServiceImpl.java

@ -7,6 +7,7 @@ import cc.hiver.mall.service.mybatis.UserAddressService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -22,9 +23,10 @@ import java.util.stream.Collectors;
public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserAddress> implements UserAddressService {
@Override
public List<UserAddressVo> getAddressListByUserId(String userId) {
public List<UserAddressVo> getAddressListByUserId(String userId, String regionId) {
QueryWrapper<UserAddress> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id", userId);
queryWrapper.eq(StringUtils.isNotBlank(regionId), "region_id", regionId);
// 按默认地址排序(1在前面),然后再按创建时间降序
queryWrapper.orderByDesc("is_default");
queryWrapper.orderByDesc("create_time");
@ -44,10 +46,11 @@ public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserA
@Override
@Transactional(rollbackFor = Exception.class)
public void setDefaultAddress(String id, String userId) {
public void setDefaultAddress(String id, String userId, String regionId) {
// 先将该用户的所有地址设置为非默认
UpdateWrapper<UserAddress> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("user_id", userId);
updateWrapper.eq(StringUtils.isNotBlank(regionId), "region_id", regionId);
updateWrapper.set("is_default", 0);
this.update(updateWrapper);
@ -55,6 +58,7 @@ public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserA
UpdateWrapper<UserAddress> defaultWrapper = new UpdateWrapper<>();
defaultWrapper.eq("id", id);
defaultWrapper.eq("user_id", userId); // 增加安全校验,防止修改别人的地址
defaultWrapper.eq(StringUtils.isNotBlank(regionId), "region_id", regionId);
defaultWrapper.set("is_default", 1);
this.update(defaultWrapper);
}

10
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/WorkerRelaPriceServiceImpl.java

@ -28,8 +28,18 @@ public class WorkerRelaPriceServiceImpl extends ServiceImpl<WorkerRelaPriceMappe
return workerRelaPriceMapper.selectByWorkerId(workerId);
}
@Override
public List<WorkerRelaPrice> selectByWorkerIdAndRegionId(String workerId, String regionId) {
return workerRelaPriceMapper.selectByWorkerIdAndRegionId(workerId, regionId);
}
@Override
public void deleteByWorkerId(String workerId) {
workerRelaPriceMapper.deleteByWorkerId(workerId);
}
@Override
public void deleteByWorkerIdAndRegionId(String workerId, String regionId) {
workerRelaPriceMapper.deleteByWorkerIdAndRegionId(workerId, regionId);
}
}

253
hiver-modules/hiver-mall/src/main/resources/db/campus_circle.sql

@ -0,0 +1,253 @@
CREATE TABLE IF NOT EXISTS `campus_category` (
`id` varchar(64) NOT NULL COMMENT '主键',
`region_id` varchar(64) DEFAULT NULL COMMENT '校区/区域ID',
`region_name` varchar(100) DEFAULT NULL COMMENT '校区/区域名称',
`parent_code` varchar(40) NOT NULL COMMENT '一级频道:wall/game/daily/sport',
`code` varchar(80) NOT NULL COMMENT '分类或标签编码',
`name` varchar(80) NOT NULL COMMENT '分类或标签名称',
`description` varchar(300) DEFAULT NULL COMMENT '描述',
`icon` varchar(500) DEFAULT NULL COMMENT '图标',
`color` varchar(30) DEFAULT NULL COMMENT '颜色',
`category_type` varchar(20) DEFAULT 'category' COMMENT 'category分类,tag热门标签',
`sort_order` int DEFAULT 100 COMMENT '排序',
`status` int DEFAULT 1 COMMENT '状态:1启用,2停用',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_campus_category_region_parent_code` (`region_id`,`parent_code`,`code`,`category_type`),
KEY `idx_campus_category_region_parent_status_sort` (`region_id`,`parent_code`,`category_type`,`status`,`sort_order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈分类与热门标签';
CREATE TABLE IF NOT EXISTS `campus_post` (
`id` varchar(64) NOT NULL COMMENT '主键',
`region_id` varchar(64) DEFAULT NULL COMMENT '校区/区域ID',
`region_name` varchar(100) DEFAULT NULL COMMENT '校区/区域名称',
`user_id` varchar(64) NOT NULL COMMENT '发布人ID',
`user_name` varchar(100) DEFAULT NULL COMMENT '发布人昵称',
`user_avatar` varchar(500) DEFAULT NULL COMMENT '发布人头像',
`post_type` varchar(20) NOT NULL COMMENT 'wall校园墙,partner找搭子',
`partner_type` varchar(20) DEFAULT NULL COMMENT 'game/daily/sport',
`category_id` varchar(64) DEFAULT NULL COMMENT '二级分类ID',
`category_name` varchar(100) DEFAULT NULL COMMENT '二级分类名称',
`title` varchar(120) NOT NULL COMMENT '标题',
`content` text COMMENT '正文',
`content_text` varchar(2000) DEFAULT NULL COMMENT '纯文本正文',
`cover_image` varchar(500) DEFAULT NULL COMMENT '封面图',
`images` text COMMENT '图片JSON',
`tags` varchar(1000) DEFAULT NULL COMMENT '标签JSON',
`location` varchar(200) DEFAULT NULL COMMENT '地点',
`activity_time` varchar(100) DEFAULT NULL COMMENT '期望时间',
`target_count` int DEFAULT NULL COMMENT '期望人数',
`joined_count` int DEFAULT 0 COMMENT '已联系/参与人数',
`contact_type` varchar(30) DEFAULT 'chat' COMMENT '联系方式:chat站内聊天',
`contact_wechat` varchar(80) DEFAULT NULL COMMENT '联系微信',
`contact_phone` varchar(20) DEFAULT NULL COMMENT '联系电话',
`browse_count` int DEFAULT 0 COMMENT '浏览数',
`like_count` int DEFAULT 0 COMMENT '点赞数',
`comment_count` int DEFAULT 0 COMMENT '评论数',
`chat_count` int DEFAULT 0 COMMENT '会话数',
`complaint_count` int DEFAULT 0 COMMENT '举报数',
`hot_score` int DEFAULT 0 COMMENT '热度分',
`status` int DEFAULT 1 COMMENT '业务状态:1正常,2下架,3删除',
`audit_status` int DEFAULT 0 COMMENT '审核状态:0待审核,1通过,2拒绝',
`audit_reason` varchar(500) DEFAULT NULL COMMENT '审核原因',
`off_shelf_reason` varchar(500) DEFAULT NULL COMMENT '下架原因',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_campus_post_region_type_status_hot` (`region_id`,`post_type`,`partner_type`,`status`,`audit_status`,`hot_score`,`create_time`),
KEY `idx_campus_post_category_status_time` (`category_id`,`status`,`audit_status`,`create_time`),
KEY `idx_campus_post_match_time` (`region_id`,`post_type`,`partner_type`,`category_id`,`status`,`audit_status`,`create_time`),
KEY `idx_campus_post_user_time` (`user_id`,`create_time`),
KEY `idx_campus_post_region_keyword` (`region_id`,`post_type`,`status`,`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈帖子';
CREATE TABLE IF NOT EXISTS `campus_comment` (
`id` varchar(64) NOT NULL COMMENT '主键',
`post_id` varchar(64) NOT NULL COMMENT '帖子ID',
`parent_id` varchar(64) DEFAULT NULL COMMENT '父评论ID',
`user_id` varchar(64) NOT NULL COMMENT '评论人ID',
`user_name` varchar(100) DEFAULT NULL COMMENT '评论人昵称',
`user_avatar` varchar(500) DEFAULT NULL COMMENT '评论人头像',
`reply_to_user_id` varchar(64) DEFAULT NULL COMMENT '回复目标用户ID',
`reply_to_user_name` varchar(100) DEFAULT NULL COMMENT '回复目标用户昵称',
`content` varchar(1000) NOT NULL COMMENT '评论内容',
`like_count` int DEFAULT 0 COMMENT '点赞数',
`audit_status` int DEFAULT 0 COMMENT '审核状态:0待审核,1通过,2拒绝',
`audit_reason` varchar(500) DEFAULT NULL COMMENT '审核原因',
`status` int DEFAULT 1 COMMENT '状态:1正常,2删除',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_campus_comment_post_status_time` (`post_id`,`status`,`audit_status`,`create_time`),
KEY `idx_campus_comment_parent_status_time` (`parent_id`,`status`,`audit_status`,`create_time`),
KEY `idx_campus_comment_user_time` (`user_id`,`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈评论';
CREATE TABLE IF NOT EXISTS `campus_like` (
`id` varchar(64) NOT NULL COMMENT '主键',
`user_id` varchar(64) NOT NULL COMMENT '用户ID',
`target_type` varchar(20) NOT NULL COMMENT 'post/comment/reaction',
`target_id` varchar(64) NOT NULL COMMENT '目标ID',
`reaction` varchar(20) DEFAULT NULL COMMENT '表情反应',
`status` int DEFAULT 1 COMMENT '1有效,2取消',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_campus_like_user_target` (`user_id`,`target_type`,`target_id`,`reaction`),
KEY `idx_campus_like_target` (`target_type`,`target_id`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈点赞和表情反应';
CREATE TABLE IF NOT EXISTS `campus_chat_session` (
`id` varchar(64) NOT NULL COMMENT '主键',
`session_id` varchar(64) DEFAULT NULL COMMENT '业务会话ID',
`post_id` varchar(64) NOT NULL COMMENT '帖子ID',
`owner_id` varchar(64) NOT NULL COMMENT '发布人ID',
`peer_user_id` varchar(64) NOT NULL COMMENT '联系用户ID',
`last_message_time` datetime DEFAULT NULL COMMENT '最后消息时间',
`last_message` varchar(500) DEFAULT NULL COMMENT '最后消息摘要',
`ended` int DEFAULT 0 COMMENT '是否结束',
`owner_deleted` int DEFAULT 0 COMMENT '发布人是否删除列表记录',
`peer_deleted` int DEFAULT 0 COMMENT '联系用户是否删除列表记录',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_campus_chat_post_peer` (`post_id`,`owner_id`,`peer_user_id`),
KEY `idx_campus_chat_owner_update` (`owner_id`,`last_message_time`),
KEY `idx_campus_chat_peer_update` (`peer_user_id`,`last_message_time`),
KEY `idx_campus_chat_session` (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈聊天会话';
CREATE TABLE IF NOT EXISTS `campus_chat_message` (
`id` varchar(64) NOT NULL COMMENT '主键',
`session_id` varchar(64) NOT NULL COMMENT '业务会话ID',
`post_id` varchar(64) NOT NULL COMMENT '帖子ID',
`sender_id` varchar(64) NOT NULL COMMENT '发送人ID',
`receiver_id` varchar(64) NOT NULL COMMENT '接收人ID',
`message_type` int DEFAULT 1 COMMENT '1文本,2图片',
`content` varchar(1000) NOT NULL COMMENT '消息内容',
`audit_status` int DEFAULT 0 COMMENT '审核状态:0待审核,1通过,2拒绝',
`audit_reason` varchar(500) DEFAULT NULL COMMENT '审核原因',
`status` int DEFAULT 1 COMMENT '状态:1正常,2撤回/删除',
`read_flag` int DEFAULT 0 COMMENT '是否已读',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_campus_chat_message_session_time` (`session_id`,`create_time`),
KEY `idx_campus_chat_message_receiver_read` (`receiver_id`,`read_flag`,`create_time`),
KEY `idx_campus_chat_message_post_time` (`post_id`,`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈聊天消息';
CREATE TABLE IF NOT EXISTS `campus_complaint` (
`id` varchar(64) NOT NULL COMMENT '主键',
`region_id` varchar(64) DEFAULT NULL COMMENT '校区/区域ID',
`reporter_id` varchar(64) NOT NULL COMMENT '举报人ID',
`reporter_name` varchar(100) DEFAULT NULL COMMENT '举报人昵称',
`post_id` varchar(64) DEFAULT NULL COMMENT '帖子ID',
`comment_id` varchar(64) DEFAULT NULL COMMENT '评论ID',
`session_id` varchar(64) DEFAULT NULL COMMENT '会话ID',
`target_user_id` varchar(64) DEFAULT NULL COMMENT '被举报用户ID',
`complaint_type` varchar(30) NOT NULL COMMENT 'post/comment/chat',
`reason` varchar(1000) NOT NULL COMMENT '举报原因',
`images` text COMMENT '举报图片JSON',
`status` int DEFAULT 0 COMMENT '0待处理,1通过,2驳回',
`handle_result` varchar(1000) DEFAULT NULL COMMENT '处理结果',
`admin_id` varchar(64) DEFAULT NULL COMMENT '处理管理员ID',
`admin_name` varchar(100) DEFAULT NULL COMMENT '处理管理员名称',
`handle_time` datetime DEFAULT NULL COMMENT '处理时间',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_campus_complaint_region_status_time` (`region_id`,`status`,`create_time`),
KEY `idx_campus_complaint_post` (`post_id`),
KEY `idx_campus_complaint_target_user` (`target_user_id`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈投诉举报';
CREATE TABLE IF NOT EXISTS `campus_user_limit` (
`id` varchar(64) NOT NULL COMMENT '主键',
`region_id` varchar(64) DEFAULT NULL COMMENT '校区/区域ID',
`user_id` varchar(64) NOT NULL COMMENT '用户ID',
`user_name` varchar(100) DEFAULT NULL COMMENT '用户昵称',
`muted` int DEFAULT 0 COMMENT '是否禁言',
`publish_banned` int DEFAULT 0 COMMENT '是否禁止发布',
`permanent_banned` int DEFAULT 0 COMMENT '是否永久封禁',
`ban_reason` varchar(500) DEFAULT NULL COMMENT '封禁原因',
`start_time` datetime DEFAULT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_campus_user_limit_user` (`user_id`),
KEY `idx_campus_user_limit_region_user` (`region_id`,`user_id`),
KEY `idx_campus_user_limit_status_time` (`muted`,`publish_banned`,`permanent_banned`,`end_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈用户风控';
CREATE TABLE IF NOT EXISTS `campus_admin_log` (
`id` varchar(64) NOT NULL COMMENT '主键',
`region_id` varchar(64) DEFAULT NULL COMMENT '校区/区域ID',
`admin_id` varchar(64) DEFAULT NULL COMMENT '管理员ID',
`admin_name` varchar(100) DEFAULT NULL COMMENT '管理员昵称',
`action_type` varchar(40) NOT NULL COMMENT '操作类型',
`target_type` varchar(40) NOT NULL COMMENT '目标类型',
`target_id` varchar(64) DEFAULT NULL COMMENT '目标ID',
`reason` varchar(500) DEFAULT NULL COMMENT '原因',
`before_data` text COMMENT '变更前',
`after_data` text COMMENT '变更后',
`create_by` varchar(64) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`del_flag` int DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_campus_admin_log_region_time` (`region_id`,`create_time`),
KEY `idx_campus_admin_log_admin_time` (`admin_id`,`create_time`),
KEY `idx_campus_admin_log_target` (`target_type`,`target_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='校园圈后台操作日志';
INSERT INTO `campus_category` (`id`, `region_id`, `parent_code`, `code`, `name`, `description`, `category_type`, `sort_order`, `status`, `del_flag`)
SELECT REPLACE(UUID(), '-', ''), NULL, 'wall', 'campus_life', '校园生活', '日常分享、吐槽和新鲜事', 'category', 10, 1, 0
WHERE NOT EXISTS (SELECT 1 FROM `campus_category` WHERE `region_id` IS NULL AND `parent_code`='wall' AND `code`='campus_life' AND `category_type`='category');
INSERT INTO `campus_category` (`id`, `region_id`, `parent_code`, `code`, `name`, `description`, `category_type`, `sort_order`, `status`, `del_flag`)
SELECT REPLACE(UUID(), '-', ''), NULL, 'game', 'moba', 'MOBA开黑', '王者、LOL手游等组队开黑', 'category', 10, 1, 0
WHERE NOT EXISTS (SELECT 1 FROM `campus_category` WHERE `region_id` IS NULL AND `parent_code`='game' AND `code`='moba' AND `category_type`='category');
INSERT INTO `campus_category` (`id`, `region_id`, `parent_code`, `code`, `name`, `description`, `category_type`, `sort_order`, `status`, `del_flag`)
SELECT REPLACE(UUID(), '-', ''), NULL, 'daily', 'study', '学习搭子', '自习、备考、打卡监督', 'category', 10, 1, 0
WHERE NOT EXISTS (SELECT 1 FROM `campus_category` WHERE `region_id` IS NULL AND `parent_code`='daily' AND `code`='study' AND `category_type`='category');
INSERT INTO `campus_category` (`id`, `region_id`, `parent_code`, `code`, `name`, `description`, `category_type`, `sort_order`, `status`, `del_flag`)
SELECT REPLACE(UUID(), '-', ''), NULL, 'sport', 'ball', '球类运动', '篮球、羽毛球、乒乓球等', 'category', 10, 1, 0
WHERE NOT EXISTS (SELECT 1 FROM `campus_category` WHERE `region_id` IS NULL AND `parent_code`='sport' AND `code`='ball' AND `category_type`='category');
INSERT INTO `campus_category` (`id`, `region_id`, `parent_code`, `code`, `name`, `description`, `category_type`, `sort_order`, `status`, `del_flag`)
SELECT REPLACE(UUID(), '-', ''), NULL, 'game', 'honor_of_kings', '王者荣耀', '热门游戏标签', 'tag', 10, 1, 0
WHERE NOT EXISTS (SELECT 1 FROM `campus_category` WHERE `region_id` IS NULL AND `parent_code`='game' AND `code`='honor_of_kings' AND `category_type`='tag');
INSERT INTO `campus_category` (`id`, `region_id`, `parent_code`, `code`, `name`, `description`, `category_type`, `sort_order`, `status`, `del_flag`)
SELECT REPLACE(UUID(), '-', ''), NULL, 'sport', 'basketball', '篮球', '热门运动标签', 'tag', 10, 1, 0
WHERE NOT EXISTS (SELECT 1 FROM `campus_category` WHERE `region_id` IS NULL AND `parent_code`='sport' AND `code`='basketball' AND `category_type`='tag');

3
hiver-modules/hiver-mall/src/main/resources/db/user_address_region_id.sql

@ -0,0 +1,3 @@
ALTER TABLE `t_user_address`
ADD COLUMN `region_id` varchar(64) DEFAULT NULL COMMENT '校区/区域ID' AFTER `user_id`,
ADD INDEX `idx_user_address_user_region_default_time` (`user_id`, `region_id`, `is_default`, `create_time`);

3
hiver-modules/hiver-mall/src/main/resources/db/worker_full_time.sql

@ -0,0 +1,3 @@
-- 为 t_worker 表添加全职配送员标识
ALTER TABLE `t_worker`
ADD COLUMN `is_full_time` TINYINT NULL DEFAULT 0 COMMENT '是否全职配送员:0否 1是' AFTER `get_push_order`;

12
hiver-modules/hiver-mall/src/main/resources/db/worker_rela_price_region_id.sql

@ -0,0 +1,12 @@
-- 为配送员接单规则添加校区维度
ALTER TABLE `t_worker_rela_price`
ADD COLUMN `region_id` VARCHAR(64) NULL COMMENT '校区id' AFTER `worker_id`;
-- 回填历史规则所属校区
UPDATE `t_worker_rela_price` wrp
INNER JOIN `t_worker` w ON w.`worker_id` = wrp.`worker_id`
SET wrp.`region_id` = w.`region`
WHERE wrp.`region_id` IS NULL OR wrp.`region_id` = '';
CREATE INDEX `idx_worker_rela_price_worker_region`
ON `t_worker_rela_price` (`worker_id`, `region_id`);

51
hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml

@ -104,9 +104,9 @@
</if>
<if test="q.shopDelivery != null">
AND EXISTS (
SELECT 1 FROM mall_order o
WHERE o.id = d.order_id
AND o.shop_delivery = #{q.shopDelivery}
SELECT 1 FROM mall_order mo
WHERE mo.id = d.order_id
AND mo.shop_delivery = #{q.shopDelivery}
)
</if>
<if test="q.transferDelivery != null">
@ -162,6 +162,11 @@
d.transfer_delivery,d.transfer_address_id,d.transfer_address_name,
d.transfer_arrive_time,d.transfer_arrive_image,d.transfer_pickup_code
FROM mall_delivery_order d
LEFT JOIN (
SELECT delivery_order_id, MAX(reassign_time) AS latest_reassign_time
FROM mall_delivery_order_reassign_record
GROUP BY delivery_order_id
) rr ON rr.delivery_order_id = d.id
<where>
AND d.status = 0
<if test="q.regionId != null and q.regionId != ''">
@ -170,6 +175,9 @@
<choose>
<when test="q.deliveryType != null and q.deliveryType == 4">
AND d.worker_id IS NOT NULL AND d.worker_id != ''
<if test="q.workerId != null and q.workerId != ''">
AND d.worker_id = #{q.workerId}
</if>
</when>
<otherwise>
AND (d.worker_id IS NULL OR d.worker_id = '')
@ -198,6 +206,9 @@
</if>
</where>
ORDER BY
(CASE WHEN d.must_finish_time IS NOT NULL AND d.must_finish_time &lt; NOW() THEN 0 ELSE 1 END) ASC,
(CASE WHEN rr.latest_reassign_time IS NULL THEN 1 ELSE 0 END) ASC,
rr.latest_reassign_time DESC,
<if test="q.order != null and q.order == 'deliveryFee'">
d.delivery_fee DESC,
</if>
@ -255,9 +266,9 @@
</if>
<if test="q.shopDelivery != null">
AND EXISTS (
SELECT 1 FROM mall_order o
WHERE o.id = d.order_id
AND o.shop_delivery = #{q.shopDelivery}
SELECT 1 FROM mall_order mo
WHERE mo.id = d.order_id
AND mo.shop_delivery = #{q.shopDelivery}
)
</if>
<if test="q.transferDelivery != null">
@ -287,6 +298,12 @@
d.transfer_delivery,d.transfer_address_id,d.transfer_address_name,
d.transfer_arrive_time,d.transfer_arrive_image,d.transfer_pickup_code
FROM mall_delivery_order d
LEFT JOIN mall_order o ON o.id = d.order_id
LEFT JOIN (
SELECT delivery_order_id, MAX(reassign_time) AS latest_reassign_time
FROM mall_delivery_order_reassign_record
GROUP BY delivery_order_id
) rr ON rr.delivery_order_id = d.id
<where>
d.status not in (-1,4)
<if test="q.regionId != null and q.regionId != ''">
@ -327,9 +344,9 @@
</if>
<if test="q.shopDelivery != null">
AND EXISTS (
SELECT 1 FROM mall_order o
WHERE o.id = d.order_id
AND o.shop_delivery = #{q.shopDelivery}
SELECT 1 FROM mall_order mo
WHERE mo.id = d.order_id
AND mo.shop_delivery = #{q.shopDelivery}
)
</if>
<if test="q.transferDelivery != null">
@ -339,7 +356,12 @@
AND d.transfer_arrive_time IS NULL
</if>
</where>
ORDER BY (CASE WHEN d.must_finish_time IS NULL THEN 1 ELSE 0 END) ASC,
ORDER BY (CASE WHEN o.shop_make_time IS NULL THEN 1 ELSE 0 END) ASC,
o.shop_make_time ASC,
(CASE WHEN d.must_finish_time IS NOT NULL AND d.must_finish_time &lt; NOW() THEN 0 ELSE 1 END) ASC,
(CASE WHEN rr.latest_reassign_time IS NULL THEN 1 ELSE 0 END) ASC,
rr.latest_reassign_time DESC,
(CASE WHEN d.must_finish_time IS NULL THEN 1 ELSE 0 END) ASC,
d.must_finish_time ASC,d.delivery_fee DESC
</select>
@ -393,9 +415,9 @@
</if>
<if test="q.shopDelivery != null">
AND EXISTS (
SELECT 1 FROM mall_order o
WHERE o.id = d.order_id
AND o.shop_delivery = #{q.shopDelivery}
SELECT 1 FROM mall_order mo
WHERE mo.id = d.order_id
AND mo.shop_delivery = #{q.shopDelivery}
)
</if>
<if test="q.transferDelivery != null">
@ -483,6 +505,9 @@
<where>
AND d.worker_id IS NOT NULL AND d.worker_id != ''
AND d.status = 0
<if test="q.workerId != null and q.workerId != ''">
AND d.worker_id = #{q.workerId}
</if>
<if test="q.regionId != null and q.regionId != ''">
AND d.region_id = #{q.regionId}
</if>

32
hiver-modules/hiver-mall/src/main/resources/mapper/WorkerRelaPriceMapper.xml

@ -9,6 +9,7 @@
<result column="update_by" jdbcType="VARCHAR" property="updateBy"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="worker_id" jdbcType="VARCHAR" property="workerId"/>
<result column="region_id" jdbcType="VARCHAR" property="regionId"/>
<result column="get_area_id" jdbcType="VARCHAR" property="getAreaId"/>
<result column="get_area_name" jdbcType="VARCHAR" property="getAreaName"/>
<result column="put_area_id" jdbcType="VARCHAR" property="putAreaId"/>
@ -20,17 +21,17 @@
</resultMap>
<sql id="Base_Column_List">
id, create_by, create_time, del_flag, update_by, update_time, worker_id, get_area_id,
id, create_by, create_time, del_flag, update_by, update_time, worker_id, region_id, get_area_id,
get_area_name, put_area_id, put_area_name, remark, order_type, order_bkge, get_push_order
</sql>
<insert id="insert" parameterType="cc.hiver.mall.entity.ProductGroupBuyPrice">
<insert id="insert" parameterType="cc.hiver.mall.entity.WorkerRelaPrice">
insert into t_worker_rela_price (id, create_by, create_time,
del_flag, update_by, update_time,
worker_id, get_area_id, get_area_name, put_area_id, put_area_name, remark, order_type, order_bkge, get_push_order)
worker_id, region_id, get_area_id, get_area_name, put_area_id, put_area_name, remark, order_type, order_bkge, get_push_order)
values (#{id,jdbcType=VARCHAR}, #{createBy,jdbcType=VARCHAR}, #{createTime,jdbcType=TIMESTAMP},
#{delFlag,jdbcType=INTEGER}, #{updateBy,jdbcType=VARCHAR}, #{updateTime,jdbcType=TIMESTAMP},
#{workerId,jdbcType=VARCHAR}, #{getAreaId,jdbcType=VARCHAR}, #{getAreaName,jdbcType=VARCHAR},
#{workerId,jdbcType=VARCHAR}, #{regionId,jdbcType=VARCHAR}, #{getAreaId,jdbcType=VARCHAR}, #{getAreaName,jdbcType=VARCHAR},
#{putAreaId,jdbcType=VARCHAR}, #{putAreaName,jdbcType=VARCHAR}, #{remark,jdbcType=VARCHAR},
#{orderType,jdbcType=INTEGER}, #{orderBkge,jdbcType=DECIMAL},
#{getPushOrder,jdbcType=INTEGER})
@ -43,12 +44,27 @@
where worker_id = #{workerId,jdbcType=VARCHAR}
</select>
<select id="selectByWorkerIdAndRegionId" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from t_worker_rela_price
where worker_id = #{workerId,jdbcType=VARCHAR}
and region_id = #{regionId,jdbcType=VARCHAR}
</select>
<delete id="deleteByWorkerId" parameterType="java.lang.String">
delete
from t_worker_rela_price
where worker_id = #{workerId,jdbcType=VARCHAR}
</delete>
<delete id="deleteByWorkerIdAndRegionId">
delete
from t_worker_rela_price
where worker_id = #{workerId,jdbcType=VARCHAR}
and region_id = #{regionId,jdbcType=VARCHAR}
</delete>
<!-- =====================================================================
配送员匹配列表:联查 t_worker、t_worker_rela_price、mall_delivery_order
支持:状态过滤、交易保障、相同地址、关键词搜索、动态排序
@ -61,6 +77,7 @@
<result column="score" property="score"/>
<result column="avg_time" property="avgTime"/>
<result column="rebate_amount" property="rebateAmount"/>
<result column="is_full_time" property="isFullTime"/>
<result column="geolocation" property="geolocation"/>
<result column="high_floor_fee" property="highFloorFee"/>
<result column="delivery_location" property="deliveryLocation"/>
@ -80,6 +97,7 @@
w.score,
w.avg_time,
w.rebate_amount,
w.is_full_time,
w.high_floor_fee,
w.delivery_location,
p.order_bkge,
@ -94,6 +112,9 @@
INNER JOIN t_worker_rela_price p
ON p.worker_id = w.worker_id
AND p.get_push_order = 1
<if test="regionId != null and regionId != ''">
AND p.region_id = #{regionId}
</if>
<if test="shopAreaId != null and shopAreaId != ''">
AND p.get_area_id = #{shopAreaId}
</if>
@ -140,8 +161,9 @@
</if>
GROUP BY
w.worker_id, w.worker_name, w.mobile, w.icon,
w.score, w.avg_time, w.rebate_amount, w.high_floor_fee, w.delivery_location, p.order_bkge
w.score, w.avg_time, w.rebate_amount, w.is_full_time, w.high_floor_fee, w.delivery_location, p.order_bkge
ORDER BY
w.is_full_time DESC,
<choose>
<when test="sortField != null and sortField == 'score'">
w.score DESC

Loading…
Cancel
Save